aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/pci/bt8xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci/bt8xx')
-rw-r--r--drivers/media/pci/bt8xx/Makefile1
-rw-r--r--drivers/media/pci/bt8xx/bt878.c4
-rw-r--r--drivers/media/pci/bt8xx/bttv-cards.c228
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c1243
-rw-r--r--drivers/media/pci/bt8xx/bttv-gpio.c2
-rw-r--r--drivers/media/pci/bt8xx/bttv-i2c.c13
-rw-r--r--drivers/media/pci/bt8xx/bttv-input.c31
-rw-r--r--drivers/media/pci/bt8xx/bttv.h9
-rw-r--r--drivers/media/pci/bt8xx/bttvp.h41
-rw-r--r--drivers/media/pci/bt8xx/dst.c20
-rw-r--r--drivers/media/pci/bt8xx/dst_ca.c4
11 files changed, 783 insertions, 813 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/bt878.c b/drivers/media/pci/bt8xx/bt878.c
index 66eb0baab0e..d0c281f41a0 100644
--- a/drivers/media/pci/bt8xx/bt878.c
+++ b/drivers/media/pci/bt8xx/bt878.c
@@ -488,8 +488,7 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
btwrite(0, BT848_INT_MASK);
result = request_irq(bt->irq, bt878_irq,
- IRQF_SHARED | IRQF_DISABLED, "bt878",
- (void *) bt);
+ IRQF_SHARED, "bt878", (void *) bt);
if (result == -EINVAL) {
printk(KERN_ERR "bt878(%d): Bad irq number or handler\n",
bt878_num);
@@ -563,7 +562,6 @@ static void bt878_remove(struct pci_dev *pci_dev)
bt->shutdown = 1;
bt878_mem_free(bt);
- pci_set_drvdata(pci_dev, NULL);
pci_disable_device(pci_dev);
return;
}
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
index c4c59175e52..d8ec583c154 100644
--- a/drivers/media/pci/bt8xx/bttv-cards.c
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -52,6 +52,7 @@ static void osprey_eeprom(struct bttv *btv, const u8 ee[256]);
static void modtec_eeprom(struct bttv *btv);
static void init_PXC200(struct bttv *btv);
static void init_RTV24(struct bttv *btv);
+static void init_PCI8604PW(struct bttv *btv);
static void rv605_muxsel(struct bttv *btv, unsigned int input);
static void eagle_muxsel(struct bttv *btv, unsigned int input);
@@ -131,7 +132,7 @@ MODULE_PARM_DESC(vsfx,"set VSFX pci config bit "
"[yet another chipset flaw workaround]");
MODULE_PARM_DESC(latency,"pci latency timer");
MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
-MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)");
+MODULE_PARM_DESC(pll, "specify installed crystal (0=none, 28=28 MHz, 35=35 MHz, 14=14 MHz)");
MODULE_PARM_DESC(tuner,"specify installed tuner type");
MODULE_PARM_DESC(autoload, "obsolete option, please do not use anymore");
MODULE_PARM_DESC(audiodev, "specify audio device:\n"
@@ -2426,7 +2427,7 @@ struct tvcard bttv_tvcards[] = {
},
/* ---- card 0x87---------------------------------- */
[BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = {
- /* Michael Krufky <mkrufky@m1k.net> */
+ /* Michael Krufky <mkrufky@linuxtv.org> */
.name = "DViCO FusionHDTV 5 Lite",
.tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
.tuner_addr = ADDR_UNSET,
@@ -2705,7 +2706,7 @@ struct tvcard bttv_tvcards[] = {
.has_radio = 1,
.has_remote = 1,
},
- [BTTV_BOARD_VD012] = {
+ [BTTV_BOARD_VD012] = {
/* D.Heer@Phytec.de */
.name = "PHYTEC VD-012 (bt878)",
.video_inputs = 4,
@@ -2718,7 +2719,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
},
- [BTTV_BOARD_VD012_X1] = {
+ [BTTV_BOARD_VD012_X1] = {
/* D.Heer@Phytec.de */
.name = "PHYTEC VD-012-X1 (bt878)",
.video_inputs = 4,
@@ -2731,7 +2732,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
},
- [BTTV_BOARD_VD012_X2] = {
+ [BTTV_BOARD_VD012_X2] = {
/* D.Heer@Phytec.de */
.name = "PHYTEC VD-012-X2 (bt878)",
.video_inputs = 4,
@@ -2744,7 +2745,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
},
- [BTTV_BOARD_GEOVISION_GV800S] = {
+ [BTTV_BOARD_GEOVISION_GV800S] = {
/* Bruno Christo <bchristo@inf.ufsm.br>
*
* GeoVision GV-800(S) has 4 Conexant Fusion 878A:
@@ -2771,7 +2772,7 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.muxsel_hook = gv800s_muxsel,
},
- [BTTV_BOARD_GEOVISION_GV800S_SL] = {
+ [BTTV_BOARD_GEOVISION_GV800S_SL] = {
/* Bruno Christo <bchristo@inf.ufsm.br>
*
* GeoVision GV-800(S) has 4 Conexant Fusion 878A:
@@ -2808,6 +2809,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
},
+ /* ---- card 0xa0---------------------------------- */
[BTTV_BOARD_TVT_TD3116] = {
.name = "Tongwei Video Technology TD-3116",
.video_inputs = 16,
@@ -2825,7 +2827,67 @@ struct tvcard bttv_tvcards[] = {
.muxsel = MUXSEL(2, 3, 1, 0),
.tuner_type = TUNER_ABSENT,
},
-
+ [BTTV_BOARD_ADLINK_MPG24] = {
+ /* Adlink MPG24 */
+ .name = "Adlink MPG24",
+ .video_inputs = 1,
+ /* .audio_inputs= 1, */
+ .svhs = NO_SVHS,
+ .muxsel = MUXSEL(2, 2, 2, 2),
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .pll = PLL_28,
+ },
+ [BTTV_BOARD_BT848_CAP_14] = {
+ .name = "Bt848 Capture 14MHz",
+ .video_inputs = 4,
+ .svhs = 2,
+ .muxsel = MUXSEL(2, 3, 1, 0),
+ .pll = PLL_14,
+ .tuner_type = TUNER_ABSENT,
+ },
+ [BTTV_BOARD_CYBERVISION_CV06] = {
+ .name = "CyberVision CV06 (SV)",
+ .video_inputs = 4,
+ /* .audio_inputs= 0, */
+ .svhs = NO_SVHS,
+ .muxsel = MUXSEL(2, 3, 1, 0),
+ .pll = PLL_28,
+ .tuner_type = TUNER_ABSENT,
+ .tuner_addr = ADDR_UNSET,
+ },
+ [BTTV_BOARD_KWORLD_VSTREAM_XPERT] = {
+ /* Pojar George <geoubuntu@gmail.com> */
+ .name = "Kworld V-Stream Xpert TV PVR878",
+ .video_inputs = 3,
+ /* .audio_inputs= 1, */
+ .svhs = 2,
+ .gpiomask = 0x001c0007,
+ .muxsel = MUXSEL(2, 3, 1, 1),
+ .gpiomux = { 0, 1, 2, 2 },
+ .gpiomute = 3,
+ .pll = PLL_28,
+ .tuner_type = TUNER_TENA_9533_DI,
+ .tuner_addr = ADDR_UNSET,
+ .has_remote = 1,
+ .has_radio = 1,
+ },
+ /* ---- card 0xa6---------------------------------- */
+ [BTTV_BOARD_PCI_8604PW] = {
+ /* PCI-8604PW with special unlock sequence */
+ .name = "PCI-8604PW",
+ .video_inputs = 2,
+ /* .audio_inputs= 0, */
+ .svhs = NO_SVHS,
+ /* The second input is available on CN4, if populated.
+ * The other 5x2 header (CN2?) connects to the same inputs
+ * as the on-board BNCs */
+ .muxsel = MUXSEL(2, 3),
+ .tuner_type = TUNER_ABSENT,
+ .no_msp34xx = 1,
+ .no_tda7432 = 1,
+ .pll = PLL_35,
+ },
};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3260,6 +3322,9 @@ void bttv_init_card1(struct bttv *btv)
case BTTV_BOARD_ADLINK_RTV24:
init_RTV24( btv );
break;
+ case BTTV_BOARD_PCI_8604PW:
+ init_PCI8604PW(btv);
+ break;
}
if (!bttv_tvcards[btv->c.type].has_dvb)
@@ -3390,6 +3455,10 @@ void bttv_init_card2(struct bttv *btv)
btv->pll.pll_ifreq=35468950;
btv->pll.pll_crystal=BT848_IFORM_XT1;
}
+ if (PLL_14 == bttv_tvcards[btv->c.type].pll) {
+ btv->pll.pll_ifreq = 14318181;
+ btv->pll.pll_crystal = BT848_IFORM_XT0;
+ }
/* insmod options can override */
switch (pll[btv->c.nr]) {
case 0: /* none */
@@ -3409,6 +3478,12 @@ void bttv_init_card2(struct bttv *btv)
btv->pll.pll_ofreq = 0;
btv->pll.pll_crystal = BT848_IFORM_XT1;
break;
+ case 3: /* 14 MHz */
+ case 14:
+ btv->pll.pll_ifreq = 14318181;
+ btv->pll.pll_ofreq = 0;
+ btv->pll.pll_crystal = BT848_IFORM_XT0;
+ break;
}
}
btv->pll.pll_current = -1;
@@ -3547,6 +3622,16 @@ void bttv_init_card2(struct bttv *btv)
if (btv->sd_msp34xx)
return;
+ /* Now see if we can find one of the tvaudio devices. */
+ btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+ &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+ if (btv->sd_tvaudio) {
+ /* There may be two tvaudio chips on the card, so try to
+ find another. */
+ v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+ &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+ }
+
/* it might also be a tda7432. */
if (!bttv_tvcards[btv->c.type].no_tda7432) {
static const unsigned short addrs[] = {
@@ -3554,14 +3639,11 @@ void bttv_init_card2(struct bttv *btv)
I2C_CLIENT_END
};
- if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
- &btv->c.i2c_adap, "tda7432", 0, addrs))
+ btv->sd_tda7432 = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+ &btv->c.i2c_adap, "tda7432", 0, addrs);
+ if (btv->sd_tda7432)
return;
}
-
- /* Now see if we can find one of the tvaudio devices. */
- btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
- &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
if (btv->sd_tvaudio)
return;
@@ -3940,7 +4022,7 @@ static void avermedia_eeprom(struct bttv *btv)
u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits)
{
- if (btv->audio == TVAUDIO_INPUT_TUNER) {
+ if (btv->audio_input == TVAUDIO_INPUT_TUNER) {
if (bttv_tvnorms[btv->tvnorm].v4l2_id & V4L2_STD_MN)
gpiobits |= 0x10000;
else
@@ -4123,6 +4205,96 @@ init_RTV24 (struct bttv *btv)
/* ----------------------------------------------------------------------- */
+/*
+ * The PCI-8604PW contains a CPLD, probably an ispMACH 4A, that filters
+ * the PCI REQ signals comming from the four BT878 chips. After power
+ * up, the CPLD does not forward requests to the bus, which prevents
+ * the BT878 from fetching RISC instructions from memory. While the
+ * CPLD is connected to most of the GPIOs of PCI device 0xD, only
+ * five appear to play a role in unlocking the REQ signal. The following
+ * sequence has been determined by trial and error without access to the
+ * original driver.
+ *
+ * Eight GPIOs of device 0xC are provided on connector CN4 (4 in, 4 out).
+ * Devices 0xE and 0xF do not appear to have anything connected to their
+ * GPIOs.
+ *
+ * The correct GPIO_OUT_EN value might have some more bits set. It should
+ * be possible to derive it from a boundary scan of the CPLD. Its JTAG
+ * pins are routed to test points.
+ *
+ */
+/* ----------------------------------------------------------------------- */
+static void
+init_PCI8604PW(struct bttv *btv)
+{
+ int state;
+
+ if ((PCI_SLOT(btv->c.pci->devfn) & ~3) != 0xC) {
+ pr_warn("This is not a PCI-8604PW\n");
+ return;
+ }
+
+ if (PCI_SLOT(btv->c.pci->devfn) != 0xD)
+ return;
+
+ btwrite(0x080002, BT848_GPIO_OUT_EN);
+
+ state = (btread(BT848_GPIO_DATA) >> 21) & 7;
+
+ for (;;) {
+ switch (state) {
+ case 1:
+ case 5:
+ case 6:
+ case 4:
+ pr_debug("PCI-8604PW in state %i, toggling pin\n",
+ state);
+ btwrite(0x080000, BT848_GPIO_DATA);
+ msleep(1);
+ btwrite(0x000000, BT848_GPIO_DATA);
+ msleep(1);
+ break;
+ case 7:
+ pr_info("PCI-8604PW unlocked\n");
+ return;
+ case 0:
+ /* FIXME: If we are in state 7 and toggle GPIO[19] one
+ more time, the CPLD goes into state 0, where PCI bus
+ mastering is inhibited again. We have not managed to
+ get out of that state. */
+
+ pr_err("PCI-8604PW locked until reset\n");
+ return;
+ default:
+ pr_err("PCI-8604PW in unknown state %i\n", state);
+ return;
+ }
+
+ state = (state << 4) | ((btread(BT848_GPIO_DATA) >> 21) & 7);
+
+ switch (state) {
+ case 0x15:
+ case 0x56:
+ case 0x64:
+ case 0x47:
+ /* The transition from state 7 to state 0 is, as explained
+ above, valid but undesired and with this code impossible
+ as we exit as soon as we are in state 7.
+ case 0x70: */
+ break;
+ default:
+ pr_err("PCI-8604PW invalid transition %i -> %i\n",
+ state >> 4, state & 7);
+ return;
+ }
+ state &= 7;
+ }
+}
+
+
+
+/* ----------------------------------------------------------------------- */
/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */
/*
* Copyright (c) 1999 Csaba Halasz <qgehali@uni-miskolc.hu>
@@ -4394,9 +4566,7 @@ static void tibetCS16_init(struct bttv *btv)
* is {3, 0, 2, 1}, i.e. the first controller to be detected is logical
* unit 3, the second (which is the master) is logical unit 0, etc.
* We need to maintain the status of the analog switch (which of the 16
- * cameras is connected to which of the 4 controllers). Rather than
- * add to the bttv structure for this, we use the data reserved for
- * the mbox (unused for this card type).
+ * cameras is connected to which of the 4 controllers) in sw_status array.
*/
/*
@@ -4431,7 +4601,6 @@ static void kodicom4400r_write(struct bttv *btv,
*/
static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
{
- char *sw_status;
int xaddr, yaddr;
struct bttv *mctlr;
static unsigned char map[4] = {3, 0, 2, 1};
@@ -4442,14 +4611,13 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
}
yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */
yaddr = map[yaddr];
- sw_status = (char *)(&mctlr->mbox_we);
xaddr = input & 0xf;
/* Check if the controller/camera pair has changed, else ignore */
- if (sw_status[yaddr] != xaddr)
+ if (mctlr->sw_status[yaddr] != xaddr)
{
/* "open" the old switch, "close" the new one, save the new */
- kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0);
- sw_status[yaddr] = xaddr;
+ kodicom4400r_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0);
+ mctlr->sw_status[yaddr] = xaddr;
kodicom4400r_write(mctlr, xaddr, yaddr, 1);
}
}
@@ -4462,7 +4630,6 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
*/
static void kodicom4400r_init(struct bttv *btv)
{
- char *sw_status = (char *)(&btv->mbox_we);
int ix;
gpio_inout(0x0003ff, 0x0003ff);
@@ -4470,7 +4637,7 @@ static void kodicom4400r_init(struct bttv *btv)
gpio_write(0);
/* Preset camera 0 to the 4 controllers */
for (ix = 0; ix < 4; ix++) {
- sw_status[ix] = ix;
+ btv->sw_status[ix] = ix;
kodicom4400r_write(btv, ix, ix, 1);
}
/*
@@ -4747,7 +4914,6 @@ static void gv800s_write(struct bttv *btv,
static void gv800s_muxsel(struct bttv *btv, unsigned int input)
{
struct bttv *mctlr;
- char *sw_status;
int xaddr, yaddr;
static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 },
{ 0x1, 0x5, 0xb, 0x7 },
@@ -4760,14 +4926,13 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input)
return;
}
yaddr = (btv->c.nr - mctlr->c.nr) & 3;
- sw_status = (char *)(&mctlr->mbox_we);
xaddr = map[yaddr][input] & 0xf;
/* Check if the controller/camera pair has changed, ignore otherwise */
- if (sw_status[yaddr] != xaddr) {
+ if (mctlr->sw_status[yaddr] != xaddr) {
/* disable the old switch, enable the new one and save status */
- gv800s_write(mctlr, sw_status[yaddr], yaddr, 0);
- sw_status[yaddr] = xaddr;
+ gv800s_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0);
+ mctlr->sw_status[yaddr] = xaddr;
gv800s_write(mctlr, xaddr, yaddr, 1);
}
}
@@ -4775,7 +4940,6 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input)
/* GeoVision GV-800(S) "master" chip init */
static void gv800s_init(struct bttv *btv)
{
- char *sw_status = (char *)(&btv->mbox_we);
int ix;
gpio_inout(0xf107f, 0xf107f);
@@ -4784,7 +4948,7 @@ static void gv800s_init(struct bttv *btv)
/* Preset camera 0 to the 4 controllers */
for (ix = 0; ix < 4; ix++) {
- sw_status[ix] = ix;
+ btv->sw_status[ix] = ix;
gv800s_write(btv, ix, ix, 1);
}
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 45e5d0661b6..da780f42b12 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -49,6 +49,7 @@
#include "bttvp.h"
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
#include <media/tvaudio.h>
#include <media/msp3400.h>
@@ -93,7 +94,7 @@ static unsigned int combfilter;
static unsigned int lumafilter;
static unsigned int automute = 1;
static unsigned int chroma_agc;
-static unsigned int adc_crush = 1;
+static unsigned int agc_crush = 1;
static unsigned int whitecrush_upper = 0xCF;
static unsigned int whitecrush_lower = 0x7F;
static unsigned int vcr_hack;
@@ -125,7 +126,7 @@ module_param(combfilter, int, 0444);
module_param(lumafilter, int, 0444);
module_param(automute, int, 0444);
module_param(chroma_agc, int, 0444);
-module_param(adc_crush, int, 0444);
+module_param(agc_crush, int, 0444);
module_param(whitecrush_upper, int, 0444);
module_param(whitecrush_lower, int, 0444);
module_param(vcr_hack, int, 0444);
@@ -138,27 +139,27 @@ module_param_array(video_nr, int, NULL, 0444);
module_param_array(radio_nr, int, NULL, 0444);
module_param_array(vbi_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
-MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
-MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
-MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
-MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
-MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
+MODULE_PARM_DESC(radio, "The TV card supports radio, default is 0 (no)");
+MODULE_PARM_DESC(bigendian, "byte order of the framebuffer, default is native endian");
+MODULE_PARM_DESC(bttv_verbose, "verbose startup messages, default is 1 (yes)");
+MODULE_PARM_DESC(bttv_gpio, "log gpio changes, default is 0 (no)");
+MODULE_PARM_DESC(bttv_debug, "debug messages, default is 0 (no)");
+MODULE_PARM_DESC(irq_debug, "irq handler debug messages, default is 0 (no)");
MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
-MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
-MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
-MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
+MODULE_PARM_DESC(gbuffers, "number of capture buffers. range 2-32, default 8");
+MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 0x208000");
+MODULE_PARM_DESC(reset_crop, "reset cropping parameters at open(), default "
"is 1 (yes) for compatibility with older applications");
-MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
-MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
-MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
-MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
-MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
-MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
-MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
-MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
-MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
-MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
+MODULE_PARM_DESC(automute, "mute audio on bad/missing video signal, default is 1 (yes)");
+MODULE_PARM_DESC(chroma_agc, "enables the AGC of chroma signal, default is 0 (no)");
+MODULE_PARM_DESC(agc_crush, "enables the luminance AGC crush, default is 1 (yes)");
+MODULE_PARM_DESC(whitecrush_upper, "sets the white crush upper value, default is 207");
+MODULE_PARM_DESC(whitecrush_lower, "sets the white crush lower value, default is 127");
+MODULE_PARM_DESC(vcr_hack, "enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
+MODULE_PARM_DESC(irq_iswitch, "switch inputs in irq handler");
+MODULE_PARM_DESC(uv_ratio, "ratio between u and v gains, default is 50");
+MODULE_PARM_DESC(full_luma_range, "use the full luma range, default is 0 (no)");
+MODULE_PARM_DESC(coring, "set the luma coring level, default is 0 (no)");
MODULE_PARM_DESC(video_nr, "video device numbers");
MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
MODULE_PARM_DESC(radio_nr, "radio device numbers");
@@ -168,6 +169,17 @@ MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
MODULE_LICENSE("GPL");
MODULE_VERSION(BTTV_VERSION);
+#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_USER_BTTV_BASE + 0)
+#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_USER_BTTV_BASE + 1)
+#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_USER_BTTV_BASE + 2)
+#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_USER_BTTV_BASE + 3)
+#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_USER_BTTV_BASE + 4)
+#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_USER_BTTV_BASE + 5)
+#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_USER_BTTV_BASE + 6)
+#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_USER_BTTV_BASE + 7)
+#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_USER_BTTV_BASE + 8)
+#define V4L2_CID_PRIVATE_CORING (V4L2_CID_USER_BTTV_BASE + 9)
+
/* ----------------------------------------------------------------------- */
/* sysfs */
@@ -250,17 +262,19 @@ static u8 SRAM_Table[][60] =
vdelay start of active video in 2 * field lines relative to
trailing edge of /VRESET pulse (VDELAY register).
sheight height of active video in 2 * field lines.
+ extraheight Added to sheight for cropcap.bounds.height only
videostart0 ITU-R frame line number of the line corresponding
to vdelay in the first field. */
#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \
- vdelay, sheight, videostart0) \
+ vdelay, sheight, extraheight, videostart0) \
.cropcap.bounds.left = minhdelayx1, \
/* * 2 because vertically we count field lines times two, */ \
/* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \
.cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
/* 4 is a safety margin at the end of the line. */ \
.cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \
- .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY, \
+ .cropcap.bounds.height = (sheight) + (extraheight) + (vdelay) - \
+ MIN_VDELAY, \
.cropcap.defrect.left = hdelayx1, \
.cropcap.defrect.top = (videostart0) * 2, \
.cropcap.defrect.width = swidth, \
@@ -301,9 +315,10 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
/* totalwidth */ 1135,
/* sqwidth */ 944,
/* vdelay */ 0x20,
- /* bt878 (and bt848?) can capture another
- line below active video. */
- /* sheight */ (576 + 2) + 0x20 - 2,
+ /* sheight */ 576,
+ /* bt878 (and bt848?) can capture another
+ line below active video. */
+ /* extraheight */ 2,
/* videostart0 */ 23)
},{
.v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
@@ -330,6 +345,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
/* sqwidth */ 780,
/* vdelay */ 0x1a,
/* sheight */ 480,
+ /* extraheight */ 0,
/* videostart0 */ 23)
},{
.v4l2_id = V4L2_STD_SECAM,
@@ -355,6 +371,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
/* sqwidth */ 944,
/* vdelay */ 0x20,
/* sheight */ 576,
+ /* extraheight */ 0,
/* videostart0 */ 23)
},{
.v4l2_id = V4L2_STD_PAL_Nc,
@@ -380,6 +397,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
/* sqwidth */ 780,
/* vdelay */ 0x1a,
/* sheight */ 576,
+ /* extraheight */ 0,
/* videostart0 */ 23)
},{
.v4l2_id = V4L2_STD_PAL_M,
@@ -405,6 +423,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
/* sqwidth */ 780,
/* vdelay */ 0x1a,
/* sheight */ 480,
+ /* extraheight */ 0,
/* videostart0 */ 23)
},{
.v4l2_id = V4L2_STD_PAL_N,
@@ -430,6 +449,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
/* sqwidth */ 944,
/* vdelay */ 0x20,
/* sheight */ 576,
+ /* extraheight */ 0,
/* videostart0 */ 23)
},{
.v4l2_id = V4L2_STD_NTSC_M_JP,
@@ -455,6 +475,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
/* sqwidth */ 780,
/* vdelay */ 0x16,
/* sheight */ 480,
+ /* extraheight */ 0,
/* videostart0 */ 23)
},{
/* that one hopefully works with the strange timing
@@ -484,6 +505,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
/* sqwidth */ 944,
/* vdelay */ 0x1a,
/* sheight */ 480,
+ /* extraheight */ 0,
/* videostart0 */ 23)
}
};
@@ -622,198 +644,6 @@ static const struct bttv_format formats[] = {
static const unsigned int FORMATS = ARRAY_SIZE(formats);
/* ----------------------------------------------------------------------- */
-
-#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4)
-#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5)
-#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6)
-#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8)
-#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9)
-#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10)
-#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11)
-
-static const struct v4l2_queryctrl no_ctl = {
- .name = "42",
- .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-static const struct v4l2_queryctrl bttv_ctls[] = {
- /* --- video --- */
- {
- .id = V4L2_CID_BRIGHTNESS,
- .name = "Brightness",
- .minimum = 0,
- .maximum = 65535,
- .step = 256,
- .default_value = 32768,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_CONTRAST,
- .name = "Contrast",
- .minimum = 0,
- .maximum = 65535,
- .step = 128,
- .default_value = 27648,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_SATURATION,
- .name = "Saturation",
- .minimum = 0,
- .maximum = 65535,
- .step = 128,
- .default_value = 32768,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_COLOR_KILLER,
- .name = "Color killer",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- }, {
- .id = V4L2_CID_HUE,
- .name = "Hue",
- .minimum = 0,
- .maximum = 65535,
- .step = 256,
- .default_value = 32768,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },
- /* --- audio --- */
- {
- .id = V4L2_CID_AUDIO_MUTE,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_AUDIO_VOLUME,
- .name = "Volume",
- .minimum = 0,
- .maximum = 65535,
- .step = 65535/100,
- .default_value = 65535,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_AUDIO_BALANCE,
- .name = "Balance",
- .minimum = 0,
- .maximum = 65535,
- .step = 65535/100,
- .default_value = 32768,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_AUDIO_BASS,
- .name = "Bass",
- .minimum = 0,
- .maximum = 65535,
- .step = 65535/100,
- .default_value = 32768,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_AUDIO_TREBLE,
- .name = "Treble",
- .minimum = 0,
- .maximum = 65535,
- .step = 65535/100,
- .default_value = 32768,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },
- /* --- private --- */
- {
- .id = V4L2_CID_PRIVATE_CHROMA_AGC,
- .name = "chroma agc",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_PRIVATE_COMBFILTER,
- .name = "combfilter",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_PRIVATE_AUTOMUTE,
- .name = "automute",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_PRIVATE_LUMAFILTER,
- .name = "luma decimation filter",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_PRIVATE_AGC_CRUSH,
- .name = "agc crush",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_PRIVATE_VCR_HACK,
- .name = "vcr hack",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
- .name = "whitecrush upper",
- .minimum = 0,
- .maximum = 255,
- .step = 1,
- .default_value = 0xCF,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
- .name = "whitecrush lower",
- .minimum = 0,
- .maximum = 255,
- .step = 1,
- .default_value = 0x7F,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_PRIVATE_UV_RATIO,
- .name = "uv ratio",
- .minimum = 0,
- .maximum = 100,
- .step = 1,
- .default_value = 50,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
- .name = "full luma range",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_PRIVATE_CORING,
- .name = "coring",
- .minimum = 0,
- .maximum = 3,
- .step = 1,
- .default_value = 0,
- .type = V4L2_CTRL_TYPE_INTEGER,
- }
-
-
-
-};
-
-static const struct v4l2_queryctrl *ctrl_by_id(int id)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
- if (bttv_ctls[i].id == id)
- return bttv_ctls+i;
-
- return NULL;
-}
-
-/* ----------------------------------------------------------------------- */
/* resource management */
/*
@@ -1168,23 +998,20 @@ static char *audio_modes[] = {
"audio: intern", "audio: mute"
};
-static int
-audio_mux(struct bttv *btv, int input, int mute)
+static void
+audio_mux_gpio(struct bttv *btv, int input, int mute)
{
- int gpio_val, signal;
- struct v4l2_control ctrl;
+ int gpio_val, signal, mute_gpio;
gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
bttv_tvcards[btv->c.type].gpiomask);
signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
- btv->mute = mute;
- btv->audio = input;
-
/* automute */
- mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
+ mute_gpio = mute || (btv->opt_automute && (!signal || !btv->users)
+ && !btv->has_radio_tuner);
- if (mute)
+ if (mute_gpio)
gpio_val = bttv_tvcards[btv->c.type].gpiomute;
else
gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
@@ -1200,13 +1027,39 @@ audio_mux(struct bttv *btv, int input, int mute)
}
if (bttv_gpio)
- bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
- if (in_interrupt())
- return 0;
+ bttv_gpio_tracking(btv, audio_modes[mute_gpio ? 4 : input]);
+}
+
+static int
+audio_mute(struct bttv *btv, int mute)
+{
+ struct v4l2_ctrl *ctrl;
+
+ audio_mux_gpio(btv, btv->audio_input, mute);
+
+ if (btv->sd_msp34xx) {
+ ctrl = v4l2_ctrl_find(btv->sd_msp34xx->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+ if (ctrl)
+ v4l2_ctrl_s_ctrl(ctrl, mute);
+ }
+ if (btv->sd_tvaudio) {
+ ctrl = v4l2_ctrl_find(btv->sd_tvaudio->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+ if (ctrl)
+ v4l2_ctrl_s_ctrl(ctrl, mute);
+ }
+ if (btv->sd_tda7432) {
+ ctrl = v4l2_ctrl_find(btv->sd_tda7432->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+ if (ctrl)
+ v4l2_ctrl_s_ctrl(ctrl, mute);
+ }
+ return 0;
+}
+
+static int
+audio_input(struct bttv *btv, int input)
+{
+ audio_mux_gpio(btv, input, btv->mute);
- ctrl.id = V4L2_CID_AUDIO_MUTE;
- ctrl.value = btv->mute;
- bttv_call_all(btv, core, s_ctrl, &ctrl);
if (btv->sd_msp34xx) {
u32 in;
@@ -1255,23 +1108,11 @@ audio_mux(struct bttv *btv, int input, int mute)
}
if (btv->sd_tvaudio) {
v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
- input, 0, 0);
+ input, 0, 0);
}
return 0;
}
-static inline int
-audio_mute(struct bttv *btv, int mute)
-{
- return audio_mux(btv, btv->audio, mute);
-}
-
-static inline int
-audio_input(struct bttv *btv, int input)
-{
- return audio_mux(btv, input, btv->mute);
-}
-
static void
bttv_crop_calc_limits(struct bttv_crop *c)
{
@@ -1285,9 +1126,9 @@ bttv_crop_calc_limits(struct bttv_crop *c)
c->min_scaled_height = 32;
} else {
c->min_scaled_width =
- (max(48, c->rect.width >> 4) + 3) & ~3;
+ (max_t(unsigned int, 48, c->rect.width >> 4) + 3) & ~3;
c->min_scaled_height =
- max(32, c->rect.height >> 4);
+ max_t(unsigned int, 32, c->rect.height >> 4);
}
c->max_scaled_width = c->rect.width & ~3;
@@ -1341,7 +1182,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
break;
}
id = tvnorm->v4l2_id;
- bttv_call_all(btv, core, s_std, id);
+ bttv_call_all(btv, video, s_std, id);
return 0;
}
@@ -1365,8 +1206,9 @@ set_input(struct bttv *btv, unsigned int input, unsigned int norm)
} else {
video_mux(btv,input);
}
- audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
- TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
+ btv->audio_input = (btv->tuner_type != TUNER_ABSENT && input == 0) ?
+ TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN;
+ audio_input(btv, btv->audio_input);
set_tvnorm(btv, norm);
}
@@ -1394,8 +1236,6 @@ static void init_irqreg(struct bttv *btv)
static void init_bt848(struct bttv *btv)
{
- int val;
-
if (bttv_tvcards[btv->c.type].no_video) {
/* very basic init only */
init_irqreg(btv);
@@ -1415,30 +1255,10 @@ static void init_bt848(struct bttv *btv)
BT848_GPIO_DMA_CTL_GPINTI,
BT848_GPIO_DMA_CTL);
- val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
- btwrite(val, BT848_E_SCLOOP);
- btwrite(val, BT848_O_SCLOOP);
-
btwrite(0x20, BT848_E_VSCALE_HI);
btwrite(0x20, BT848_O_VSCALE_HI);
- btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
- BT848_ADC);
-
- btwrite(whitecrush_upper, BT848_WC_UP);
- btwrite(whitecrush_lower, BT848_WC_DOWN);
-
- if (btv->opt_lumafilter) {
- btwrite(0, BT848_E_CONTROL);
- btwrite(0, BT848_O_CONTROL);
- } else {
- btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
- btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
- }
- bt848_bright(btv, btv->bright);
- bt848_hue(btv, btv->hue);
- bt848_contrast(btv, btv->contrast);
- bt848_sat(btv, btv->saturation);
+ v4l2_ctrl_handler_setup(&btv->ctrl_handler);
/* interrupt */
init_irqreg(btv);
@@ -1460,103 +1280,26 @@ static void bttv_reinit_bt848(struct bttv *btv)
set_input(btv, btv->input, btv->tvnorm);
}
-static int bttv_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *c)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
-
- switch (c->id) {
- case V4L2_CID_BRIGHTNESS:
- c->value = btv->bright;
- break;
- case V4L2_CID_HUE:
- c->value = btv->hue;
- break;
- case V4L2_CID_CONTRAST:
- c->value = btv->contrast;
- break;
- case V4L2_CID_SATURATION:
- c->value = btv->saturation;
- break;
- case V4L2_CID_COLOR_KILLER:
- c->value = btv->opt_color_killer;
- break;
-
- case V4L2_CID_AUDIO_MUTE:
- case V4L2_CID_AUDIO_VOLUME:
- case V4L2_CID_AUDIO_BALANCE:
- case V4L2_CID_AUDIO_BASS:
- case V4L2_CID_AUDIO_TREBLE:
- bttv_call_all(btv, core, g_ctrl, c);
- break;
-
- case V4L2_CID_PRIVATE_CHROMA_AGC:
- c->value = btv->opt_chroma_agc;
- break;
- case V4L2_CID_PRIVATE_COMBFILTER:
- c->value = btv->opt_combfilter;
- break;
- case V4L2_CID_PRIVATE_LUMAFILTER:
- c->value = btv->opt_lumafilter;
- break;
- case V4L2_CID_PRIVATE_AUTOMUTE:
- c->value = btv->opt_automute;
- break;
- case V4L2_CID_PRIVATE_AGC_CRUSH:
- c->value = btv->opt_adc_crush;
- break;
- case V4L2_CID_PRIVATE_VCR_HACK:
- c->value = btv->opt_vcr_hack;
- break;
- case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
- c->value = btv->opt_whitecrush_upper;
- break;
- case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
- c->value = btv->opt_whitecrush_lower;
- break;
- case V4L2_CID_PRIVATE_UV_RATIO:
- c->value = btv->opt_uv_ratio;
- break;
- case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
- c->value = btv->opt_full_luma_range;
- break;
- case V4L2_CID_PRIVATE_CORING:
- c->value = btv->opt_coring;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int bttv_s_ctrl(struct file *file, void *f,
- struct v4l2_control *c)
+static int bttv_s_ctrl(struct v4l2_ctrl *c)
{
- int err;
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
-
- err = v4l2_prio_check(&btv->prio, fh->prio);
- if (0 != err)
- return err;
+ struct bttv *btv = container_of(c->handler, struct bttv, ctrl_handler);
+ int val;
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
- bt848_bright(btv, c->value);
+ bt848_bright(btv, c->val);
break;
case V4L2_CID_HUE:
- bt848_hue(btv, c->value);
+ bt848_hue(btv, c->val);
break;
case V4L2_CID_CONTRAST:
- bt848_contrast(btv, c->value);
+ bt848_contrast(btv, c->val);
break;
case V4L2_CID_SATURATION:
- bt848_sat(btv, c->value);
+ bt848_sat(btv, c->val);
break;
case V4L2_CID_COLOR_KILLER:
- btv->opt_color_killer = c->value;
- if (btv->opt_color_killer) {
+ if (c->val) {
btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
} else {
@@ -1565,36 +1308,23 @@ static int bttv_s_ctrl(struct file *file, void *f,
}
break;
case V4L2_CID_AUDIO_MUTE:
- audio_mute(btv, c->value);
- /* fall through */
- case V4L2_CID_AUDIO_VOLUME:
- if (btv->volume_gpio)
- btv->volume_gpio(btv, c->value);
-
- bttv_call_all(btv, core, s_ctrl, c);
+ audio_mute(btv, c->val);
+ btv->mute = c->val;
break;
- case V4L2_CID_AUDIO_BALANCE:
- case V4L2_CID_AUDIO_BASS:
- case V4L2_CID_AUDIO_TREBLE:
- bttv_call_all(btv, core, s_ctrl, c);
+ case V4L2_CID_AUDIO_VOLUME:
+ btv->volume_gpio(btv, c->val);
break;
- case V4L2_CID_PRIVATE_CHROMA_AGC:
- btv->opt_chroma_agc = c->value;
- if (btv->opt_chroma_agc) {
- btor(BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
- btor(BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
- } else {
- btand(~BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
- btand(~BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
- }
+ case V4L2_CID_CHROMA_AGC:
+ val = c->val ? BT848_SCLOOP_CAGC : 0;
+ btwrite(val, BT848_E_SCLOOP);
+ btwrite(val, BT848_O_SCLOOP);
break;
case V4L2_CID_PRIVATE_COMBFILTER:
- btv->opt_combfilter = c->value;
+ btv->opt_combfilter = c->val;
break;
case V4L2_CID_PRIVATE_LUMAFILTER:
- btv->opt_lumafilter = c->value;
- if (btv->opt_lumafilter) {
+ if (c->val) {
btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
} else {
@@ -1603,36 +1333,31 @@ static int bttv_s_ctrl(struct file *file, void *f,
}
break;
case V4L2_CID_PRIVATE_AUTOMUTE:
- btv->opt_automute = c->value;
+ btv->opt_automute = c->val;
break;
case V4L2_CID_PRIVATE_AGC_CRUSH:
- btv->opt_adc_crush = c->value;
btwrite(BT848_ADC_RESERVED |
- (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+ (c->val ? BT848_ADC_CRUSH : 0),
BT848_ADC);
break;
case V4L2_CID_PRIVATE_VCR_HACK:
- btv->opt_vcr_hack = c->value;
+ btv->opt_vcr_hack = c->val;
break;
case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
- btv->opt_whitecrush_upper = c->value;
- btwrite(c->value, BT848_WC_UP);
+ btwrite(c->val, BT848_WC_UP);
break;
case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
- btv->opt_whitecrush_lower = c->value;
- btwrite(c->value, BT848_WC_DOWN);
+ btwrite(c->val, BT848_WC_DOWN);
break;
case V4L2_CID_PRIVATE_UV_RATIO:
- btv->opt_uv_ratio = c->value;
+ btv->opt_uv_ratio = c->val;
bt848_sat(btv, btv->saturation);
break;
case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
- btv->opt_full_luma_range = c->value;
- btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+ btaor((c->val << 7), ~BT848_OFORM_RANGE, BT848_OFORM);
break;
case V4L2_CID_PRIVATE_CORING:
- btv->opt_coring = c->value;
- btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+ btaor((c->val << 5), ~BT848_OFORM_CORE32, BT848_OFORM);
break;
default:
return -EINVAL;
@@ -1642,6 +1367,121 @@ static int bttv_s_ctrl(struct file *file, void *f,
/* ----------------------------------------------------------------------- */
+static const struct v4l2_ctrl_ops bttv_ctrl_ops = {
+ .s_ctrl = bttv_s_ctrl,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_combfilter = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_COMBFILTER,
+ .name = "Comb Filter",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_automute = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_AUTOMUTE,
+ .name = "Auto Mute",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_lumafilter = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_LUMAFILTER,
+ .name = "Luma Decimation Filter",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_agc_crush = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_AGC_CRUSH,
+ .name = "AGC Crush",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_vcr_hack = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_VCR_HACK,
+ .name = "VCR Hack",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_whitecrush_lower = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
+ .name = "Whitecrush Lower",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = 255,
+ .step = 1,
+ .def = 0x7f,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_whitecrush_upper = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
+ .name = "Whitecrush Upper",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = 255,
+ .step = 1,
+ .def = 0xcf,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_uv_ratio = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_UV_RATIO,
+ .name = "UV Ratio",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = 100,
+ .step = 1,
+ .def = 50,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_full_luma = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
+ .name = "Full Luma Range",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_coring = {
+ .ops = &bttv_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_CORING,
+ .name = "Coring",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = 3,
+ .step = 1,
+};
+
+
+/* ----------------------------------------------------------------------- */
+
void bttv_gpio_tracking(struct bttv *btv, char *comment)
{
unsigned int outbits, data;
@@ -1871,25 +1711,33 @@ static struct videobuf_queue_ops bttv_video_qops = {
.buf_release = buffer_release,
};
-static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static void radio_enable(struct bttv *btv)
+{
+ /* Switch to the radio tuner */
+ if (!btv->has_radio_tuner) {
+ btv->has_radio_tuner = 1;
+ bttv_call_all(btv, tuner, s_radio);
+ btv->audio_input = TVAUDIO_INPUT_RADIO;
+ audio_input(btv, btv->audio_input);
+ }
+}
+
+static int bttv_s_std(struct file *file, void *priv, v4l2_std_id id)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
unsigned int i;
- int err;
-
- err = v4l2_prio_check(&btv->prio, fh->prio);
- if (err)
- goto err;
+ int err = 0;
for (i = 0; i < BTTV_TVNORMS; i++)
- if (*id & bttv_tvnorms[i].v4l2_id)
+ if (id & bttv_tvnorms[i].v4l2_id)
break;
if (i == BTTV_TVNORMS) {
err = -EINVAL;
goto err;
}
+ btv->std = id;
set_tvnorm(btv, i);
err:
@@ -1897,15 +1745,24 @@ err:
return err;
}
+static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct bttv_fh *fh = priv;
+ struct bttv *btv = fh->btv;
+
+ *id = btv->std;
+ return 0;
+}
+
static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
- *id = V4L2_STD_625_50;
+ *id &= V4L2_STD_625_50;
else
- *id = V4L2_STD_525_60;
+ *id &= V4L2_STD_525_60;
return 0;
}
@@ -1922,7 +1779,7 @@ static int bttv_enum_input(struct file *file, void *priv,
}
i->type = V4L2_INPUT_TYPE_CAMERA;
- i->audioset = 1;
+ i->audioset = 0;
if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
sprintf(i->name, "Television");
@@ -1964,49 +1821,29 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
- int err;
-
- err = v4l2_prio_check(&btv->prio, fh->prio);
- if (unlikely(err))
- goto err;
-
- if (i > bttv_tvcards[btv->c.type].video_inputs) {
- err = -EINVAL;
- goto err;
- }
+ if (i >= bttv_tvcards[btv->c.type].video_inputs)
+ return -EINVAL;
set_input(btv, i, btv->tvnorm);
-
-err:
return 0;
}
static int bttv_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
+ const struct v4l2_tuner *t)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
- int err;
- if (unlikely(0 != t->index))
+ if (t->index)
return -EINVAL;
- if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
- err = -EINVAL;
- goto err;
- }
-
- err = v4l2_prio_check(&btv->prio, fh->prio);
- if (unlikely(err))
- goto err;
-
bttv_call_all(btv, tuner, s_tuner, t);
- if (btv->audio_mode_gpio)
- btv->audio_mode_gpio(btv, t, 1);
-
-err:
+ if (btv->audio_mode_gpio) {
+ struct v4l2_tuner copy = *t;
+ btv->audio_mode_gpio(btv, &copy, 1);
+ }
return 0;
}
@@ -2016,45 +1853,55 @@ static int bttv_g_frequency(struct file *file, void *priv,
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
- f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
- f->frequency = btv->freq;
+ if (f->tuner)
+ return -EINVAL;
+
+ if (f->type == V4L2_TUNER_RADIO)
+ radio_enable(btv);
+ f->frequency = f->type == V4L2_TUNER_RADIO ?
+ btv->radio_freq : btv->tv_freq;
return 0;
}
+static void bttv_set_frequency(struct bttv *btv, const struct v4l2_frequency *f)
+{
+ struct v4l2_frequency new_freq = *f;
+
+ bttv_call_all(btv, tuner, s_frequency, f);
+ /* s_frequency may clamp the frequency, so get the actual
+ frequency before assigning radio/tv_freq. */
+ bttv_call_all(btv, tuner, g_frequency, &new_freq);
+ if (new_freq.type == V4L2_TUNER_RADIO) {
+ radio_enable(btv);
+ btv->radio_freq = new_freq.frequency;
+ if (btv->has_matchbox)
+ tea5757_set_freq(btv, btv->radio_freq);
+ } else {
+ btv->tv_freq = new_freq.frequency;
+ }
+}
+
static int bttv_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
+ const struct v4l2_frequency *f)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
- int err;
- if (unlikely(f->tuner != 0))
+ if (f->tuner)
return -EINVAL;
- err = v4l2_prio_check(&btv->prio, fh->prio);
- if (unlikely(err))
- goto err;
-
- if (unlikely(f->type != (btv->radio_user
- ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
- err = -EINVAL;
- goto err;
- }
- btv->freq = f->frequency;
- bttv_call_all(btv, tuner, s_frequency, f);
- if (btv->has_matchbox && btv->radio_user)
- tea5757_set_freq(btv, btv->freq);
-err:
-
+ bttv_set_frequency(btv, f);
return 0;
}
static int bttv_log_status(struct file *file, void *f)
{
+ struct video_device *vdev = video_devdata(file);
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
+ v4l2_ctrl_handler_log_status(vdev->ctrl_handler, btv->c.v4l2_dev.name);
bttv_call_all(btv, core, log_status);
return 0;
}
@@ -2066,12 +1913,6 @@ static int bttv_g_register(struct file *file, void *f,
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (!v4l2_chip_match_host(&reg->match))
- return -EINVAL;
-
/* bt848 has a 12-bit register space */
reg->reg &= 0xfff;
reg->val = btread(reg->reg);
@@ -2081,20 +1922,13 @@ static int bttv_g_register(struct file *file, void *f,
}
static int bttv_s_register(struct file *file, void *f,
- struct v4l2_dbg_register *reg)
+ const struct v4l2_dbg_register *reg)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (!v4l2_chip_match_host(&reg->match))
- return -EINVAL;
-
/* bt848 has a 12-bit register space */
- reg->reg &= 0xfff;
- btwrite(reg->val, reg->reg);
+ btwrite(reg->val, reg->reg & 0xfff);
return 0;
}
@@ -2190,7 +2024,7 @@ limit_scaled_size_lock (struct bttv_fh * fh,
/* We cannot scale up. When the scaled image is larger
than crop.rect we adjust the crop.rect as required
by the V4L2 spec, hence cropcap.bounds are our limit. */
- max_width = min(b->width, (__s32) MAX_HACTIVE);
+ max_width = min_t(unsigned int, b->width, MAX_HACTIVE);
max_height = b->height;
/* We cannot capture the same line as video and VBI data.
@@ -2263,22 +2097,33 @@ limit_scaled_size_lock (struct bttv_fh * fh,
may also adjust the current cropping parameters to get closer
to the desired window size. */
static int
-verify_window_lock (struct bttv_fh * fh,
- struct v4l2_window * win,
- int adjust_size,
- int adjust_crop)
+verify_window_lock(struct bttv_fh *fh, struct v4l2_window *win,
+ int adjust_size, int adjust_crop)
{
enum v4l2_field field;
unsigned int width_mask;
int rc;
- if (win->w.width < 48 || win->w.height < 32)
- return -EINVAL;
+ if (win->w.width < 48)
+ win->w.width = 48;
+ if (win->w.height < 32)
+ win->w.height = 32;
if (win->clipcount > 2048)
- return -EINVAL;
+ win->clipcount = 2048;
+ win->chromakey = 0;
+ win->global_alpha = 0;
field = win->field;
+ switch (field) {
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ case V4L2_FIELD_INTERLACED:
+ break;
+ default:
+ field = V4L2_FIELD_ANY;
+ break;
+ }
if (V4L2_FIELD_ANY == field) {
__s32 height2;
@@ -2287,18 +2132,11 @@ verify_window_lock (struct bttv_fh * fh,
? V4L2_FIELD_INTERLACED
: V4L2_FIELD_TOP;
}
- switch (field) {
- case V4L2_FIELD_TOP:
- case V4L2_FIELD_BOTTOM:
- case V4L2_FIELD_INTERLACED:
- break;
- default:
- return -EINVAL;
- }
+ win->field = field;
- /* 4-byte alignment. */
if (NULL == fh->ovfmt)
return -EINVAL;
+ /* 4-byte alignment. */
width_mask = ~0;
switch (fh->ovfmt->depth) {
case 8:
@@ -2323,8 +2161,6 @@ verify_window_lock (struct bttv_fh * fh,
adjust_size, adjust_crop);
if (0 != rc)
return rc;
-
- win->field = field;
return 0;
}
@@ -2481,6 +2317,7 @@ static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
fh->width, fh->height);
f->fmt.pix.field = fh->cap.field;
f->fmt.pix.pixelformat = fh->fmt->fourcc;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
}
@@ -2504,6 +2341,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
struct bttv *btv = fh->btv;
enum v4l2_field field;
__s32 width, height;
+ __s32 height2;
int rc;
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
@@ -2512,30 +2350,25 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
field = f->fmt.pix.field;
- if (V4L2_FIELD_ANY == field) {
- __s32 height2;
-
- height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
- field = (f->fmt.pix.height > height2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_BOTTOM;
- }
-
- if (V4L2_FIELD_SEQ_BT == field)
- field = V4L2_FIELD_SEQ_TB;
-
switch (field) {
case V4L2_FIELD_TOP:
case V4L2_FIELD_BOTTOM:
case V4L2_FIELD_ALTERNATE:
case V4L2_FIELD_INTERLACED:
break;
+ case V4L2_FIELD_SEQ_BT:
case V4L2_FIELD_SEQ_TB:
- if (fmt->flags & FORMAT_FLAGS_PLANAR)
- return -EINVAL;
+ if (!(fmt->flags & FORMAT_FLAGS_PLANAR)) {
+ field = V4L2_FIELD_SEQ_TB;
+ break;
+ }
+ /* fall through */
+ default: /* FIELD_ANY case */
+ height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+ field = (f->fmt.pix.height > height2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_BOTTOM;
break;
- default:
- return -EINVAL;
}
width = f->fmt.pix.width;
@@ -2552,6 +2385,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
/* update data for the application */
f->fmt.pix.field = field;
pix_format_set_size(&f->fmt.pix, fmt, width, height);
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
}
@@ -2561,9 +2395,10 @@ static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
{
struct bttv_fh *fh = priv;
- return verify_window_lock(fh, &f->fmt.win,
+ verify_window_lock(fh, &f->fmt.win,
/* adjust_size */ 1,
/* adjust_crop */ 0);
+ return 0;
}
static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
@@ -2630,6 +2465,7 @@ static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
static int bttv_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
+ struct video_device *vdev = video_devdata(file);
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
@@ -2642,11 +2478,15 @@ static int bttv_querycap(struct file *file, void *priv,
"PCI:%s", pci_name(btv->c.pci));
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING;
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_DEVICE_CAPS;
if (no_overlay <= 0)
cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+ if (btv->vbi_dev)
+ cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
+ if (btv->radio_dev)
+ cap->capabilities |= V4L2_CAP_RADIO;
/*
* No need to lock here: those vars are initialized during board
@@ -2656,6 +2496,25 @@ static int bttv_querycap(struct file *file, void *priv,
cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
if (btv->tuner_type != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER;
+ if (vdev->vfl_type == VFL_TYPE_GRABBER)
+ cap->device_caps = cap->capabilities &
+ (V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_VIDEO_OVERLAY |
+ V4L2_CAP_TUNER);
+ else if (vdev->vfl_type == VFL_TYPE_VBI)
+ cap->device_caps = cap->capabilities &
+ (V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_TUNER);
+ else {
+ cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
+ if (btv->has_saa6588)
+ cap->device_caps |= V4L2_CAP_READWRITE |
+ V4L2_CAP_RDS_CAPTURE;
+ }
return 0;
}
@@ -2718,6 +2577,7 @@ static int bttv_g_fbuf(struct file *file, void *f,
*fb = btv->fbuf;
fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+ fb->flags = V4L2_FBUF_FLAG_PRIMARY;
if (fh->ovfmt)
fb->fmt.pixelformat = fh->ovfmt->fourcc;
return 0;
@@ -2891,36 +2751,15 @@ static int bttv_streamoff(struct file *file, void *priv,
return 0;
}
-static int bttv_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
- const struct v4l2_queryctrl *ctrl;
-
- if ((c->id < V4L2_CID_BASE ||
- c->id >= V4L2_CID_LASTP1) &&
- (c->id < V4L2_CID_PRIVATE_BASE ||
- c->id >= V4L2_CID_PRIVATE_LASTP1))
- return -EINVAL;
-
- if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
- *c = no_ctl;
- else {
- ctrl = ctrl_by_id(c->id);
-
- *c = (NULL != ctrl) ? *ctrl : no_ctl;
- }
-
- return 0;
-}
-
static int bttv_g_parm(struct file *file, void *f,
struct v4l2_streamparm *parm)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ parm->parm.capture.readbuffers = gbuffers;
v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
&parm->parm.capture.timeperframe);
@@ -2933,15 +2772,13 @@ static int bttv_g_tuner(struct file *file, void *priv,
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
- if (btv->tuner_type == TUNER_ABSENT)
- return -EINVAL;
if (0 != t->index)
return -EINVAL;
t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ t->capability = V4L2_TUNER_CAP_NORM;
bttv_call_all(btv, tuner, g_tuner, t);
strcpy(t->name, "Television");
- t->capability = V4L2_TUNER_CAP_NORM;
t->type = V4L2_TUNER_ANALOG_TV;
if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
t->signal = 0xffff;
@@ -2952,28 +2789,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
return 0;
}
-static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
-
- *p = v4l2_prio_max(&btv->prio);
-
- return 0;
-}
-
-static int bttv_s_priority(struct file *file, void *f,
- enum v4l2_priority prio)
-{
- struct bttv_fh *fh = f;
- struct bttv *btv = fh->btv;
- int rc;
-
- rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
-
- return rc;
-}
-
static int bttv_cropcap(struct file *file, void *priv,
struct v4l2_cropcap *cap)
{
@@ -3026,11 +2841,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
/* Make sure tvnorm, vbi_end and the current cropping
parameters remain consistent until we're done. Note
read() may change vbi_end in check_alloc_btres_lock(). */
- retval = v4l2_prio_check(&btv->prio, fh->prio);
- if (0 != retval) {
- return retval;
- }
-
retval = -EBUSY;
if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
@@ -3088,23 +2898,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
return 0;
}
-static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
- if (unlikely(a->index))
- return -EINVAL;
-
- strcpy(a->name, "audio");
- return 0;
-}
-
-static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
-{
- if (unlikely(a->index))
- return -EINVAL;
-
- return 0;
-}
-
static ssize_t bttv_read(struct file *file, char __user *data,
size_t count, loff_t *ppos)
{
@@ -3144,34 +2937,43 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
struct bttv_fh *fh = file->private_data;
struct bttv_buffer *buf;
enum v4l2_field field;
- unsigned int rc = POLLERR;
+ unsigned int rc = 0;
+ unsigned long req_events = poll_requested_events(wait);
+
+ if (v4l2_event_pending(&fh->fh))
+ rc = POLLPRI;
+ else if (req_events & POLLPRI)
+ poll_wait(file, &fh->fh.wait, wait);
+
+ if (!(req_events & (POLLIN | POLLRDNORM)))
+ return rc;
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
- return POLLERR;
- return videobuf_poll_stream(file, &fh->vbi, wait);
+ return rc | POLLERR;
+ return rc | videobuf_poll_stream(file, &fh->vbi, wait);
}
if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
/* streaming capture */
if (list_empty(&fh->cap.stream))
- goto err;
+ return rc | POLLERR;
buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
} else {
/* read() capture */
if (NULL == fh->cap.read_buf) {
/* need to capture a new frame */
if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
- goto err;
+ return rc | POLLERR;
fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
if (NULL == fh->cap.read_buf)
- goto err;
+ return rc | POLLERR;
fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
field = videobuf_next_field(&fh->cap);
if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
kfree (fh->cap.read_buf);
fh->cap.read_buf = NULL;
- goto err;
+ return rc | POLLERR;
}
fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
fh->cap.read_off = 0;
@@ -3182,10 +2984,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
poll_wait(file, &buf->vb.done, wait);
if (buf->vb.state == VIDEOBUF_DONE ||
buf->vb.state == VIDEOBUF_ERROR)
- rc = POLLIN|POLLRDNORM;
- else
- rc = 0;
-err:
+ rc = rc | POLLIN|POLLRDNORM;
return rc;
}
@@ -3214,15 +3013,15 @@ static int bttv_open(struct file *file)
fh = kmalloc(sizeof(*fh), GFP_KERNEL);
if (unlikely(!fh))
return -ENOMEM;
+ btv->users++;
file->private_data = fh;
*fh = btv->init;
+ v4l2_fh_init(&fh->fh, vdev);
fh->type = type;
fh->ov.setup_ok = 0;
- v4l2_prio_open(&btv->prio, &fh->prio);
-
videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
&btv->c.pci->dev, &btv->s_lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
@@ -3237,8 +3036,7 @@ static int bttv_open(struct file *file)
fh, &btv->lock);
set_tvnorm(btv,btv->tvnorm);
set_input(btv, btv->input, btv->tvnorm);
-
- btv->users++;
+ audio_mute(btv, btv->mute);
/* The V4L2 spec requires one global set of cropping parameters
which only change on request. These are stored in btv->crop[1].
@@ -3257,6 +3055,7 @@ static int bttv_open(struct file *file)
bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
bttv_field_count(btv);
+ v4l2_fh_add(&fh->fh);
return 0;
}
@@ -3292,16 +3091,17 @@ static int bttv_release(struct file *file)
videobuf_mmap_free(&fh->cap);
videobuf_mmap_free(&fh->vbi);
- v4l2_prio_close(&btv->prio, fh->prio);
file->private_data = NULL;
- kfree(fh);
btv->users--;
bttv_field_count(btv);
if (!btv->users)
- audio_mute(btv, 1);
+ audio_mute(btv, btv->mute);
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
+ kfree(fh);
return 0;
}
@@ -3340,20 +3140,16 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
.vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
.vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
.vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
- .vidioc_g_audio = bttv_g_audio,
- .vidioc_s_audio = bttv_s_audio,
.vidioc_cropcap = bttv_cropcap,
.vidioc_reqbufs = bttv_reqbufs,
.vidioc_querybuf = bttv_querybuf,
.vidioc_qbuf = bttv_qbuf,
.vidioc_dqbuf = bttv_dqbuf,
.vidioc_s_std = bttv_s_std,
+ .vidioc_g_std = bttv_g_std,
.vidioc_enum_input = bttv_enum_input,
.vidioc_g_input = bttv_g_input,
.vidioc_s_input = bttv_s_input,
- .vidioc_queryctrl = bttv_queryctrl,
- .vidioc_g_ctrl = bttv_g_ctrl,
- .vidioc_s_ctrl = bttv_s_ctrl,
.vidioc_streamon = bttv_streamon,
.vidioc_streamoff = bttv_streamoff,
.vidioc_g_tuner = bttv_g_tuner,
@@ -3363,13 +3159,13 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
.vidioc_g_fbuf = bttv_g_fbuf,
.vidioc_s_fbuf = bttv_s_fbuf,
.vidioc_overlay = bttv_overlay,
- .vidioc_g_priority = bttv_g_priority,
- .vidioc_s_priority = bttv_s_priority,
.vidioc_g_parm = bttv_g_parm,
.vidioc_g_frequency = bttv_g_frequency,
.vidioc_s_frequency = bttv_s_frequency,
.vidioc_log_status = bttv_log_status,
.vidioc_querystd = bttv_querystd,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.vidioc_g_register = bttv_g_register,
.vidioc_s_register = bttv_s_register,
@@ -3380,7 +3176,6 @@ static struct video_device bttv_video_template = {
.fops = &bttv_fops,
.ioctl_ops = &bttv_ioctl_ops,
.tvnorms = BTTV_NORMS,
- .current_norm = V4L2_STD_PAL,
};
/* ----------------------------------------------------------------------- */
@@ -3402,13 +3197,12 @@ static int radio_open(struct file *file)
return -ENOMEM;
file->private_data = fh;
*fh = btv->init;
-
- v4l2_prio_open(&btv->prio, &fh->prio);
+ v4l2_fh_init(&fh->fh, vdev);
btv->radio_user++;
+ audio_mute(btv, btv->mute);
- bttv_call_all(btv, tuner, s_radio);
- audio_input(btv,TVAUDIO_INPUT_RADIO);
+ v4l2_fh_add(&fh->fh);
return 0;
}
@@ -3419,28 +3213,17 @@ static int radio_release(struct file *file)
struct bttv *btv = fh->btv;
struct saa6588_command cmd;
- v4l2_prio_close(&btv->prio, fh->prio);
file->private_data = NULL;
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
kfree(fh);
btv->radio_user--;
bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
- return 0;
-}
-
-static int radio_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct bttv_fh *fh = priv;
- struct bttv *btv = fh->btv;
-
- strcpy(cap->driver, "bttv");
- strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
- sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
- cap->capabilities = V4L2_CAP_TUNER;
-
+ if (btv->radio_user == 0)
+ btv->has_radio_tuner = 0;
return 0;
}
@@ -3449,12 +3232,11 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
- if (btv->tuner_type == TUNER_ABSENT)
- return -EINVAL;
if (0 != t->index)
return -EINVAL;
strcpy(t->name, "Radio");
t->type = V4L2_TUNER_RADIO;
+ radio_enable(btv);
bttv_call_all(btv, tuner, g_tuner, t);
@@ -3464,31 +3246,8 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
return 0;
}
-static int radio_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- if (i->index != 0)
- return -EINVAL;
-
- strcpy(i->name, "Radio");
- i->type = V4L2_INPUT_TYPE_TUNER;
-
- return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- if (unlikely(a->index))
- return -EINVAL;
-
- strcpy(a->name, "Radio");
-
- return 0;
-}
-
static int radio_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
+ const struct v4l2_tuner *t)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
@@ -3496,66 +3255,24 @@ static int radio_s_tuner(struct file *file, void *priv,
if (0 != t->index)
return -EINVAL;
+ radio_enable(btv);
bttv_call_all(btv, tuner, s_tuner, t);
return 0;
}
-static int radio_s_audio(struct file *file, void *priv,
- const struct v4l2_audio *a)
-{
- if (unlikely(a->index))
- return -EINVAL;
-
- return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
- if (unlikely(i))
- return -EINVAL;
-
- return 0;
-}
-
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
-{
- return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- const struct v4l2_queryctrl *ctrl;
-
- if (c->id < V4L2_CID_BASE ||
- c->id >= V4L2_CID_LASTP1)
- return -EINVAL;
-
- if (c->id == V4L2_CID_AUDIO_MUTE) {
- ctrl = ctrl_by_id(c->id);
- *c = *ctrl;
- } else
- *c = no_ctl;
-
- return 0;
-}
-
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
static ssize_t radio_read(struct file *file, char __user *data,
size_t count, loff_t *ppos)
{
struct bttv_fh *fh = file->private_data;
struct bttv *btv = fh->btv;
struct saa6588_command cmd;
- cmd.block_count = count/3;
+
+ cmd.block_count = count / 3;
+ cmd.nonblocking = file->f_flags & O_NONBLOCK;
cmd.buffer = data;
cmd.instance = file;
cmd.result = -ENODEV;
+ radio_enable(btv);
bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
@@ -3566,10 +3283,18 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
{
struct bttv_fh *fh = file->private_data;
struct bttv *btv = fh->btv;
+ unsigned long req_events = poll_requested_events(wait);
struct saa6588_command cmd;
+ unsigned int res = 0;
+
+ if (v4l2_event_pending(&fh->fh))
+ res = POLLPRI;
+ else if (req_events & POLLPRI)
+ poll_wait(file, &fh->fh.wait, wait);
+ radio_enable(btv);
cmd.instance = file;
cmd.event_list = wait;
- cmd.result = -ENODEV;
+ cmd.result = res;
bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
return cmd.result;
@@ -3586,20 +3311,14 @@ static const struct v4l2_file_operations radio_fops =
};
static const struct v4l2_ioctl_ops radio_ioctl_ops = {
- .vidioc_querycap = radio_querycap,
+ .vidioc_querycap = bttv_querycap,
+ .vidioc_log_status = bttv_log_status,
.vidioc_g_tuner = radio_g_tuner,
- .vidioc_enum_input = radio_enum_input,
- .vidioc_g_audio = radio_g_audio,
.vidioc_s_tuner = radio_s_tuner,
- .vidioc_s_audio = radio_s_audio,
- .vidioc_s_input = radio_s_input,
- .vidioc_s_std = radio_s_std,
- .vidioc_queryctrl = radio_queryctrl,
- .vidioc_g_input = radio_g_input,
- .vidioc_g_ctrl = bttv_g_ctrl,
- .vidioc_s_ctrl = bttv_s_ctrl,
.vidioc_g_frequency = bttv_g_frequency,
.vidioc_s_frequency = bttv_s_frequency,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
static struct video_device radio_template = {
@@ -3835,7 +3554,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 +3597,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 +3668,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);
@@ -4102,7 +3821,8 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
bttv_irq_switch_video(btv);
if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
- audio_mute(btv, btv->mute); /* trigger automute */
+ /* trigger automute */
+ audio_mux_gpio(btv, btv->audio_input, btv->mute);
if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
pr_info("%d: %s%s @ %08x,",
@@ -4151,7 +3871,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
/* ----------------------------------------------------------------------- */
-/* initialitation */
+/* initialization */
static struct video_device *vdev_init(struct bttv *btv,
const struct video_device *template,
@@ -4166,10 +3886,17 @@ static struct video_device *vdev_init(struct bttv *btv,
vfd->v4l2_dev = &btv->c.v4l2_dev;
vfd->release = video_device_release;
vfd->debug = bttv_debug;
+ set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, btv);
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
type_name, bttv_tvcards[btv->c.type].name);
+ if (btv->tuner_type == TUNER_ABSENT) {
+ v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
+ v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
+ v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
+ v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
+ }
return vfd;
}
@@ -4237,6 +3964,7 @@ static int bttv_register_video(struct bttv *btv)
btv->radio_dev = vdev_init(btv, &radio_template, "radio");
if (NULL == btv->radio_dev)
goto err;
+ btv->radio_dev->ctrl_handler = &btv->radio_ctrl_handler;
if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
radio_nr[btv->c.nr]) < 0)
goto err;
@@ -4267,9 +3995,15 @@ static void pci_set_command(struct pci_dev *dev)
static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
{
+ struct v4l2_frequency init_freq = {
+ .tuner = 0,
+ .type = V4L2_TUNER_ANALOG_TV,
+ .frequency = 980,
+ };
int result;
unsigned char lat;
struct bttv *btv;
+ struct v4l2_ctrl_handler *hdl;
if (bttv_num == BTTV_MAX)
return -ENOMEM;
@@ -4291,7 +4025,6 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
INIT_LIST_HEAD(&btv->c.subs);
INIT_LIST_HEAD(&btv->capture);
INIT_LIST_HEAD(&btv->vcapture);
- v4l2_prio_init(&btv->prio);
init_timer(&btv->timeout);
btv->timeout.function = bttv_irq_timeout;
@@ -4329,6 +4062,10 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
goto fail0;
}
+ hdl = &btv->ctrl_handler;
+ v4l2_ctrl_handler_init(hdl, 20);
+ btv->c.v4l2_dev.ctrl_handler = hdl;
+ v4l2_ctrl_handler_init(&btv->radio_ctrl_handler, 6);
btv->revision = dev->revision;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
@@ -4351,7 +4088,7 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
/* disable irqs, register irq handler */
btwrite(0, BT848_INT_MASK);
result = request_irq(btv->c.pci->irq, bttv_irq,
- IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
+ IRQF_SHARED, btv->c.v4l2_dev.name, (void *)btv);
if (result < 0) {
pr_err("%d: can't get IRQ %d\n",
bttv_num, btv->c.pci->irq);
@@ -4365,16 +4102,19 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
/* init options from insmod args */
btv->opt_combfilter = combfilter;
- btv->opt_lumafilter = lumafilter;
+ bttv_ctrl_combfilter.def = combfilter;
+ bttv_ctrl_lumafilter.def = lumafilter;
btv->opt_automute = automute;
- btv->opt_chroma_agc = chroma_agc;
- btv->opt_adc_crush = adc_crush;
+ bttv_ctrl_automute.def = automute;
+ bttv_ctrl_agc_crush.def = agc_crush;
btv->opt_vcr_hack = vcr_hack;
- btv->opt_whitecrush_upper = whitecrush_upper;
- btv->opt_whitecrush_lower = whitecrush_lower;
+ bttv_ctrl_vcr_hack.def = vcr_hack;
+ bttv_ctrl_whitecrush_upper.def = whitecrush_upper;
+ bttv_ctrl_whitecrush_lower.def = whitecrush_lower;
btv->opt_uv_ratio = uv_ratio;
- btv->opt_full_luma_range = full_luma_range;
- btv->opt_coring = coring;
+ bttv_ctrl_uv_ratio.def = uv_ratio;
+ bttv_ctrl_full_luma.def = full_luma_range;
+ bttv_ctrl_coring.def = coring;
/* fill struct bttv with some useful defaults */
btv->init.btv = btv;
@@ -4383,8 +4123,39 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
btv->init.width = 320;
btv->init.height = 240;
+ btv->init.ov.w.width = 320;
+ btv->init.ov.w.height = 240;
+ btv->init.ov.field = V4L2_FIELD_INTERLACED;
btv->input = 0;
+ v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 0xff00, 0x100, 32768);
+ v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 0xff80, 0x80, 0x6c00);
+ v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+ V4L2_CID_SATURATION, 0, 0xff80, 0x80, 32768);
+ v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+ V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+ V4L2_CID_HUE, 0, 0xff00, 0x100, 32768);
+ v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+ V4L2_CID_CHROMA_AGC, 0, 1, 1, !!chroma_agc);
+ v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+ if (btv->volume_gpio)
+ v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+ V4L2_CID_AUDIO_VOLUME, 0, 0xff00, 0x100, 0xff00);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_combfilter, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_automute, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_lumafilter, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_agc_crush, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_vcr_hack, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_lower, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_upper, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_uv_ratio, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_full_luma, NULL);
+ v4l2_ctrl_new_custom(hdl, &bttv_ctrl_coring, NULL);
+
/* initialize hardware */
if (bttv_gpio)
bttv_gpio_tracking(btv,"pre-init");
@@ -4407,21 +4178,35 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
/* some card-specific stuff (needs working i2c) */
bttv_init_card2(btv);
bttv_init_tuner(btv);
+ if (btv->tuner_type != TUNER_ABSENT) {
+ bttv_set_frequency(btv, &init_freq);
+ btv->radio_freq = 90500 * 16; /* 90.5Mhz default */
+ }
+ btv->std = V4L2_STD_PAL;
init_irqreg(btv);
+ if (!bttv_tvcards[btv->c.type].no_video)
+ v4l2_ctrl_handler_setup(hdl);
+ if (hdl->error) {
+ result = hdl->error;
+ goto fail2;
+ }
+ /* mute device */
+ audio_mute(btv, 1);
/* register video4linux + input */
if (!bttv_tvcards[btv->c.type].no_video) {
- bttv_register_video(btv);
- bt848_bright(btv,32768);
- bt848_contrast(btv, 27648);
- bt848_hue(btv,32768);
- bt848_sat(btv,32768);
- audio_mute(btv, 1);
+ v4l2_ctrl_add_handler(&btv->radio_ctrl_handler, hdl,
+ v4l2_ctrl_radio_filter);
+ if (btv->radio_ctrl_handler.error) {
+ result = btv->radio_ctrl_handler.error;
+ goto fail2;
+ }
set_input(btv, 0, btv->tvnorm);
bttv_crop_reset(&btv->crop[0], btv->tvnorm);
btv->crop[1] = btv->crop[0]; /* current = default */
disclaim_vbi_lines(btv);
disclaim_video_lines(btv);
+ bttv_register_video(btv);
}
/* add subdevices and autoload dvb-bt8xx if needed */
@@ -4443,6 +4228,8 @@ fail2:
free_irq(btv->c.pci->irq,btv);
fail1:
+ v4l2_ctrl_handler_free(&btv->ctrl_handler);
+ v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
v4l2_device_unregister(&btv->c.v4l2_dev);
fail0:
@@ -4484,9 +4271,11 @@ static void bttv_remove(struct pci_dev *pci_dev)
bttv_unregister_video(btv);
/* free allocated memory */
+ v4l2_ctrl_handler_free(&btv->ctrl_handler);
+ v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
btcx_riscmem_free(btv->c.pci,&btv->main);
- /* free ressources */
+ /* free resources */
free_irq(btv->c.pci->irq,btv);
iounmap(btv->bt848_mmio);
release_mem_region(pci_resource_start(btv->c.pci,0),
diff --git a/drivers/media/pci/bt8xx/bttv-gpio.c b/drivers/media/pci/bt8xx/bttv-gpio.c
index 922e8233fd0..3f364b7062b 100644
--- a/drivers/media/pci/bt8xx/bttv-gpio.c
+++ b/drivers/media/pci/bt8xx/bttv-gpio.c
@@ -98,7 +98,7 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
err = device_register(&sub->dev);
if (0 != err) {
- kfree(sub);
+ put_device(&sub->dev);
return err;
}
pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
diff --git a/drivers/media/pci/bt8xx/bttv-i2c.c b/drivers/media/pci/bt8xx/bttv-i2c.c
index 5039b8826e0..d43911deb61 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;
@@ -395,3 +394,11 @@ int init_bttv_i2c(struct bttv *btv)
return btv->i2c_rc;
}
+
+int fini_bttv_i2c(struct bttv *btv)
+{
+ if (btv->i2c_rc == 0)
+ i2c_del_adapter(&btv->c.i2c_adap);
+
+ return 0;
+}
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
index 04207a79905..5930bce1665 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -375,6 +375,7 @@ void init_bttv_i2c_ir(struct bttv *btv)
I2C_CLIENT_END
};
struct i2c_board_info info;
+ struct i2c_client *i2c_dev;
if (0 != btv->i2c_rc)
return;
@@ -390,7 +391,12 @@ void init_bttv_i2c_ir(struct bttv *btv)
btv->init_data.ir_codes = RC_MAP_PV951;
info.addr = 0x4b;
break;
- default:
+ }
+
+ if (btv->init_data.name) {
+ info.platform_data = &btv->init_data;
+ i2c_dev = i2c_new_device(&btv->c.i2c_adap, &info);
+ } else {
/*
* The external IR receiver is at i2c address 0x34 (0x35 for
* reads). Future Hauppauge cards will have an internal
@@ -399,24 +405,14 @@ void init_bttv_i2c_ir(struct bttv *btv)
* internal.
* That's why we probe 0x1a (~0x34) first. CB
*/
-
- i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL);
- return;
+ i2c_dev = i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL);
}
+ if (NULL == i2c_dev)
+ return;
- if (btv->init_data.name)
- info.platform_data = &btv->init_data;
- i2c_new_device(&btv->c.i2c_adap, &info);
-
- return;
-}
-
-int fini_bttv_i2c(struct bttv *btv)
-{
- if (0 != btv->i2c_rc)
- return 0;
-
- return i2c_del_adapter(&btv->c.i2c_adap);
+#if defined(CONFIG_MODULES) && defined(MODULE)
+ request_module("ir-kbd-i2c");
+#endif
}
int bttv_input_init(struct bttv *btv)
@@ -487,6 +483,7 @@ int bttv_input_init(struct bttv *btv)
case BTTV_BOARD_ASKEY_CPH03X:
case BTTV_BOARD_CONCEPTRONIC_CTVFMI2:
case BTTV_BOARD_CONTVFMI:
+ case BTTV_BOARD_KWORLD_VSTREAM_XPERT:
ir_codes = RC_MAP_PIXELVIEW;
ir->mask_keycode = 0x001F00;
ir->mask_keyup = 0x006000;
diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h
index 79a11240a59..f0812624466 100644
--- a/drivers/media/pci/bt8xx/bttv.h
+++ b/drivers/media/pci/bt8xx/bttv.h
@@ -185,6 +185,11 @@
#define BTTV_BOARD_PV183 0x9f
#define BTTV_BOARD_TVT_TD3116 0xa0
#define BTTV_BOARD_APOSONIC_WDVR 0xa1
+#define BTTV_BOARD_ADLINK_MPG24 0xa2
+#define BTTV_BOARD_BT848_CAP_14 0xa3
+#define BTTV_BOARD_CYBERVISION_CV06 0xa4
+#define BTTV_BOARD_KWORLD_VSTREAM_XPERT 0xa5
+#define BTTV_BOARD_PCI_8604PW 0xa6
/* more card-specific defines */
#define PT2254_L_CHANNEL 0x10
@@ -232,6 +237,7 @@ struct tvcard {
#define PLL_NONE 0
#define PLL_28 1
#define PLL_35 2
+#define PLL_14 3
/* i2c audio flags */
unsigned int no_msp34xx:1;
@@ -359,6 +365,9 @@ void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits);
#define bttv_call_all(btv, o, f, args...) \
v4l2_device_call_all(&btv->c.v4l2_dev, 0, o, f, ##args)
+#define bttv_call_all_err(btv, o, f, args...) \
+ v4l2_device_call_until_err(&btv->c.v4l2_dev, 0, o, f, ##args)
+
extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
unsigned char b2, int both);
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 9ec0adba236..6eefb595d0f 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -33,9 +33,11 @@
#include <linux/input.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
+#include <linux/device.h>
#include <asm/io.h>
#include <media/v4l2-common.h>
-#include <linux/device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
#include <media/videobuf-dma-sg.h>
#include <media/tveeprom.h>
#include <media/rc-core.h>
@@ -214,11 +216,11 @@ struct bttv_crop {
};
struct bttv_fh {
+ /* This must be the first field in this struct */
+ struct v4l2_fh fh;
+
struct bttv *btv;
int resources;
-#ifdef VIDIOC_G_PRIORITY
- enum v4l2_priority prio;
-#endif
enum v4l2_buf_type type;
/* video capture */
@@ -298,6 +300,10 @@ extern int no_overlay;
/* bttv-input.c */
extern void init_bttv_i2c_ir(struct bttv *btv);
+
+/* ---------------------------------------------------------- */
+/* bttv-i2c.c */
+extern int init_bttv_i2c(struct bttv *btv);
extern int fini_bttv_i2c(struct bttv *btv);
/* ---------------------------------------------------------- */
@@ -308,7 +314,6 @@ extern unsigned int bttv_verbose;
extern unsigned int bttv_debug;
extern unsigned int bttv_gpio;
extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
-extern int init_bttv_i2c(struct bttv *btv);
#define dprintk(fmt, ...) \
do { \
@@ -393,12 +398,17 @@ struct bttv {
wait_queue_head_t i2c_queue;
struct v4l2_subdev *sd_msp34xx;
struct v4l2_subdev *sd_tvaudio;
+ struct v4l2_subdev *sd_tda7432;
/* video4linux (1) */
struct video_device *video_dev;
struct video_device *radio_dev;
struct video_device *vbi_dev;
+ /* controls */
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl_handler radio_ctrl_handler;
+
/* infrared remote */
int has_remote;
struct bttv_ir *remote;
@@ -410,38 +420,30 @@ struct bttv {
spinlock_t s_lock;
struct mutex lock;
int resources;
-#ifdef VIDIOC_G_PRIORITY
- struct v4l2_prio_state prio;
-#endif
/* video state */
unsigned int input;
- unsigned int audio;
+ unsigned int audio_input;
unsigned int mute;
- unsigned long freq;
+ unsigned long tv_freq;
unsigned int tvnorm;
+ v4l2_std_id std;
int hue, contrast, bright, saturation;
struct v4l2_framebuffer fbuf;
unsigned int field_count;
/* various options */
int opt_combfilter;
- int opt_lumafilter;
int opt_automute;
- int opt_chroma_agc;
- int opt_color_killer;
- int opt_adc_crush;
int opt_vcr_hack;
- int opt_whitecrush_upper;
- int opt_whitecrush_lower;
int opt_uv_ratio;
- int opt_full_luma_range;
- int opt_coring;
/* radio data/state */
int has_radio;
+ int has_radio_tuner;
int radio_user;
int radio_uses_msp_demodulator;
+ unsigned long radio_freq;
/* miro/pinnacle + Aimslab VHX
philips matchbox (tea5757 radio tuner) support */
@@ -457,6 +459,9 @@ struct bttv {
int mbox_iow;
int mbox_csel;
+ /* switch status for multi-controller cards */
+ char sw_status[4];
+
/* risc memory management data
- must acquire s_lock before changing these
- only the irq handler is supported to touch top + bottom + vcurr */
diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c
index 430b3eb1181..f2261dfe5d1 100644
--- a/drivers/media/pci/bt8xx/dst.c
+++ b/drivers/media/pci/bt8xx/dst.c
@@ -1544,7 +1544,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
}
-static int dst_init(struct dvb_frontend *fe)
+static int bt8xx_dst_init(struct dvb_frontend *fe)
{
struct dst_state *state = fe->demodulator_priv;
@@ -1707,7 +1707,7 @@ static int dst_get_frontend(struct dvb_frontend *fe)
return 0;
}
-static void dst_release(struct dvb_frontend *fe)
+static void bt8xx_dst_release(struct dvb_frontend *fe)
{
struct dst_state *state = fe->demodulator_priv;
if (state->dst_ca) {
@@ -1776,8 +1776,8 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
FE_CAN_GUARD_INTERVAL_AUTO
},
- .release = dst_release,
- .init = dst_init,
+ .release = bt8xx_dst_release,
+ .init = bt8xx_dst_init,
.tune = dst_tune_frontend,
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
@@ -1801,8 +1801,8 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
},
- .release = dst_release,
- .init = dst_init,
+ .release = bt8xx_dst_release,
+ .init = bt8xx_dst_init,
.tune = dst_tune_frontend,
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
@@ -1834,8 +1834,8 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
FE_CAN_QAM_256
},
- .release = dst_release,
- .init = dst_init,
+ .release = bt8xx_dst_release,
+ .init = bt8xx_dst_init,
.tune = dst_tune_frontend,
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
@@ -1857,8 +1857,8 @@ static struct dvb_frontend_ops dst_atsc_ops = {
.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
},
- .release = dst_release,
- .init = dst_init,
+ .release = bt8xx_dst_release,
+ .init = bt8xx_dst_init,
.tune = dst_tune_frontend,
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
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;
}