From 8f1a4a70005cbcdec3d3d28838ea85f94701fb38 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:50 -0300 Subject: V4L/DVB (7087): tuner-simple: whitespace / comments / codingstyle cleanups Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 138 +++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index c1db576696c6..770d6281c154 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -13,15 +13,15 @@ #include "tuner-i2c.h" #include "tuner-simple.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); #define PREFIX "tuner-simple" -static int offset = 0; +static int offset; module_param(offset, int, 0664); -MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); +MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner"); /* ---------------------------------------------------------------------- */ @@ -36,8 +36,8 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); */ #define TEMIC_SET_PAL_I 0x05 #define TEMIC_SET_PAL_DK 0x09 -#define TEMIC_SET_PAL_L 0x0a // SECAM ? -#define TEMIC_SET_PAL_L2 0x0b // change IF ! +#define TEMIC_SET_PAL_L 0x0a /* SECAM ? */ +#define TEMIC_SET_PAL_L2 0x0b /* change IF ! */ #define TEMIC_SET_PAL_BG 0x0c /* tv tuner system standard selection for Philips FQ1216ME @@ -107,7 +107,7 @@ static int tuner_read_status(struct dvb_frontend *fe) struct tuner_simple_priv *priv = fe->tuner_priv; unsigned char byte; - if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1)) + if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1)) return 0; return byte; @@ -121,13 +121,13 @@ static inline int tuner_signal(const int status) static inline int tuner_stereo(const int type, const int status) { switch (type) { - case TUNER_PHILIPS_FM1216ME_MK3: - case TUNER_PHILIPS_FM1236_MK3: - case TUNER_PHILIPS_FM1256_IH3: - case TUNER_LG_NTSC_TAPE: - return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); - default: - return status & TUNER_STEREO; + case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FM1256_IH3: + case TUNER_LG_NTSC_TAPE: + return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); + default: + return status & TUNER_STEREO; } } @@ -219,9 +219,9 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, continue; break; } - /* use default tuner_t_params if desired_type not available */ + /* use default tuner params if desired_type not available */ if (desired_type != tun->params[j].type) { - tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n", + tuner_dbg("IFPCoff = %d: params undefined for tuner %d\n", IFPCoff, priv->type); j = 0; } @@ -234,7 +234,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, } if (i == t_params->count) { tuner_dbg("TV frequency out of range (%d > %d)", - params->frequency, t_params->ranges[i - 1].limit); + params->frequency, t_params->ranges[i - 1].limit); params->frequency = t_params->ranges[--i].limit; } config = t_params->ranges[i].config; @@ -242,24 +242,25 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, /* i == 0 -> VHF_LO * i == 1 -> VHF_HI * i == 2 -> UHF */ - tuner_dbg("tv: param %d, range %d\n",j,i); + tuner_dbg("tv: param %d, range %d\n", j, i); - div=params->frequency + IFPCoff + offset; + div = params->frequency + IFPCoff + offset; - tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", - params->frequency / 16, params->frequency % 16 * 100 / 16, - IFPCoff / 16, IFPCoff % 16 * 100 / 16, - offset / 16, offset % 16 * 100 / 16, - div); + tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " + "Offset=%d.%02d MHz, div=%0d\n", + params->frequency / 16, params->frequency % 16 * 100 / 16, + IFPCoff / 16, IFPCoff % 16 * 100 / 16, + offset / 16, offset % 16 * 100 / 16, div); /* tv norm specific stuff for multi-norm tuners */ switch (priv->type) { - case TUNER_PHILIPS_SECAM: // FI1216MF + case TUNER_PHILIPS_SECAM: /* FI1216MF */ /* 0x01 -> ??? no change ??? */ /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ cb &= ~0x03; - if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM + if (params->std & V4L2_STD_SECAM_L) + /* also valid for V4L2_STD_SECAM */ cb |= PHILIPS_MF_SET_STD_L; else if (params->std & V4L2_STD_SECAM_LC) cb |= PHILIPS_MF_SET_STD_LC; @@ -333,10 +334,14 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, /* set to the correct mode (analog or digital) */ tuneraddr = priv->i2c_props.addr; priv->i2c_props.addr = 0x0a; - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); priv->i2c_props.addr = tuneraddr; /* FIXME: input */ break; @@ -357,8 +362,10 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, if (t_params->has_tda9887) { struct v4l2_priv_tun_config tda9887_cfg; int config = 0; - int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && - !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); + int is_secam_l = (params->std & (V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC)) && + !(params->std & ~(V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC)); tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &config; @@ -368,8 +375,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, config |= TDA9887_PORT1_ACTIVE; if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) config |= TDA9887_PORT2_ACTIVE; - } - else { + } else { if (t_params->port1_active) config |= TDA9887_PORT1_ACTIVE; if (t_params->port2_active) @@ -384,8 +390,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, config |= TDA9887_TOP(t_params->default_top_secam_mid); else if (t_params->default_top_secam_high) config |= TDA9887_TOP(t_params->default_top_secam_high); - } - else { + } else { if (i == 0 && t_params->default_top_low) config |= TDA9887_TOP(t_params->default_top_low); else if (i == 1 && t_params->default_top_mid) @@ -399,10 +404,11 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, &tda9887_cfg); } tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); + buffer[0], buffer[1], buffer[2], buffer[3]); - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); switch (priv->type) { case TUNER_LG_TDVS_H06XF: @@ -411,23 +417,28 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, buffer[0] &= ~0x20; buffer[0] |= 0x18; buffer[1] = 0x20; - tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]); + tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); break; case TUNER_MICROTUNE_4042FI5: { - // FIXME - this may also work for other tuners + /* FIXME - this may also work for other tuners */ unsigned long timeout = jiffies + msecs_to_jiffies(1); u8 status_byte = 0; /* Wait until the PLL locks */ for (;;) { - if (time_after(jiffies,timeout)) + if (time_after(jiffies, timeout)) return 0; - if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) { - tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc); + rc = tuner_i2c_xfer_recv(&priv->i2c_props, + &status_byte, 1); + if (1 != rc) { + tuner_warn("i2c i/o read error: rc == %d " + "(should be 1)\n", rc); break; } if (status_byte & TUNER_PLL_LOCKED) @@ -442,10 +453,12 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, buffer[2] = config; buffer[3] = cb; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); + buffer[0], buffer[1], buffer[2], buffer[3]); - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 4)\n", rc); break; } } @@ -483,7 +496,8 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, freq += (unsigned int)(41.3*16000); break; default: - tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if); + tuner_warn("Unsupported radio_if value %d\n", + t_params->radio_if); return 0; } @@ -491,7 +505,8 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, switch (priv->type) { case TUNER_TENA_9533_DI: case TUNER_YMEC_TVF_5533MF: - tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n"); + tuner_dbg("This tuner doesn't have FM. " + "Most cards have a TEA5767 for FM\n"); return 0; case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: @@ -534,7 +549,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, } tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); + buffer[0], buffer[1], buffer[2], buffer[3]); priv->last_div = div; if (t_params->has_tda9887) { @@ -544,9 +559,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &config; - if (t_params->port1_active && !t_params->port1_fm_high_sensitivity) + if (t_params->port1_active && + !t_params->port1_fm_high_sensitivity) config |= TDA9887_PORT1_ACTIVE; - if (t_params->port2_active && !t_params->port2_fm_high_sensitivity) + if (t_params->port2_active && + !t_params->port2_fm_high_sensitivity) config |= TDA9887_PORT2_ACTIVE; if (t_params->intercarrier_mode) config |= TDA9887_INTERCARRIER; @@ -557,10 +574,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, if (t_params->radio_if == 2) config |= TDA9887_RIF_41_3; i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG, - &tda9887_cfg); + &tda9887_cfg); } - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); return 0; } @@ -627,16 +645,16 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, priv->type = cfg->type; priv->tun = cfg->tun; - memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); + memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, + sizeof(struct dvb_tuner_ops)); tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name); - strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name)); + strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, + sizeof(fe->ops.tuner_ops.info.name)); return fe; } - - EXPORT_SYMBOL_GPL(simple_tuner_attach); MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver"); -- cgit v1.2.3 From 1c45713dc67a5bdb65ac4e9e7213738eceec8932 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 2 Apr 2008 14:25:51 -0300 Subject: V4L/DVB (7105): ivtv-yuv.c: make 3 functions static This patch makes the following needlessly global functions static: - ivtv_yuv_next_free() - ivtv_yuv_setup_frame() - ivtv_yuv_udma_frame() Signed-off-by: Adrian Bunk Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-yuv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 85183480a225..8fdd67cef74c 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -914,7 +914,7 @@ static void ivtv_yuv_init(struct ivtv *itv) } /* Get next available yuv buffer on PVR350 */ -void ivtv_yuv_next_free(struct ivtv *itv) +static void ivtv_yuv_next_free(struct ivtv *itv) { int draw, display; struct yuv_playback_info *yi = &itv->yuv_info; @@ -937,7 +937,7 @@ void ivtv_yuv_next_free(struct ivtv *itv) } /* Set up frame according to ivtv_dma_frame parameters */ -void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) +static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) { struct yuv_playback_info *yi = &itv->yuv_info; u8 frame = yi->draw_frame; @@ -1042,7 +1042,7 @@ void ivtv_yuv_frame_complete(struct ivtv *itv) (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS); } -int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) +static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) { DEFINE_WAIT(wait); int rc = 0; -- cgit v1.2.3 From 1cd1c78fc4cbeb08de5bbc9478f6be8e17c051c8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 2 Apr 2008 14:25:51 -0300 Subject: V4L/DVB (7107): frontends/xc5000.c: make a struct static struct XC5000_Standard[] can become static. Signed-off-by: Adrian Bunk Reviewed-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/xc5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/xc5000.c b/drivers/media/dvb/frontends/xc5000.c index f642ca200b59..a5094b7f21fd 100644 --- a/drivers/media/dvb/frontends/xc5000.c +++ b/drivers/media/dvb/frontends/xc5000.c @@ -151,7 +151,7 @@ typedef struct { #define FM_Radio_INPUT2 21 #define FM_Radio_INPUT1 22 -XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { +static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, {"M/N-NTSC/PAL-A2", 0x0600, 0x8020}, {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020}, -- cgit v1.2.3 From 9b65e96640dd0a07ad0ba31487ce19a0e6949c5a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 2 Apr 2008 14:25:51 -0300 Subject: V4L/DVB (7114): tuner-xc2028.c: make a function static dump_firm_type_and_int_freq() can become static. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-xc2028.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 50cf876f020f..8f4fdf70f7eb 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -145,7 +145,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) } #define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) -void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) +static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) { if (type & BASE) printk("BASE "); -- cgit v1.2.3 From b34a8a36e3d9d5f1b7516cb10c9fc0ba83a68031 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 2 Apr 2008 14:25:53 -0300 Subject: V4L/DVB (7094): static memory - Static memory is always initialized with 0. - Replaced in some cases C99 comments for /* */ Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-functions.c | 2 +- drivers/media/dvb/b2c2/flexcop-pci.c | 2 +- drivers/media/dvb/dvb-core/dvb_net.c | 2 +- drivers/media/dvb/frontends/cx22702.c | 2 +- drivers/media/dvb/frontends/dvb-pll.c | 2 +- drivers/media/dvb/frontends/lgdt330x.c | 2 +- drivers/media/dvb/frontends/nxt6000.c | 2 +- drivers/media/dvb/frontends/s5h1409.c | 2 +- drivers/media/dvb/frontends/s5h1420.c | 2 +- drivers/media/dvb/frontends/sp8870.c | 12 ++++++------ drivers/media/dvb/frontends/tda10086.c | 2 +- drivers/media/dvb/frontends/tda826x.c | 2 +- drivers/media/dvb/frontends/tda827x.c | 2 +- drivers/media/dvb/frontends/ves1x93.c | 2 +- drivers/media/dvb/frontends/zl10353.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 2 +- drivers/media/radio/miropcm20-rds.c | 2 +- drivers/media/radio/radio-cadet.c | 10 +++++----- drivers/media/radio/radio-typhoon.c | 2 +- drivers/media/video/adv7170.c | 2 +- drivers/media/video/adv7175.c | 2 +- drivers/media/video/arv.c | 4 ++-- drivers/media/video/bt819.c | 2 +- drivers/media/video/bt856.c | 2 +- drivers/media/video/bt8xx/bttv-vbi.c | 2 +- drivers/media/video/bw-qcam.c | 4 ++-- drivers/media/video/c-qcam.c | 4 ++-- drivers/media/video/cafe_ccic.c | 4 ++-- drivers/media/video/cpia2/cpia2_core.c | 4 ++-- drivers/media/video/cpia2/cpia2_usb.c | 2 +- drivers/media/video/cx23885/cx23885-i2c.c | 2 +- drivers/media/video/cx88/cx88-blackbird.c | 2 +- drivers/media/video/cx88/cx88-core.c | 6 +++--- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/cx88/cx88-i2c.c | 4 ++-- drivers/media/video/cx88/cx88-input.c | 2 +- drivers/media/video/cx88/cx88-mpeg.c | 2 +- drivers/media/video/cx88/cx88-tvaudio.c | 6 +++--- drivers/media/video/cx88/cx88-vbi.c | 2 +- drivers/media/video/cx88/cx88-video.c | 4 ++-- drivers/media/video/dpc7146.c | 4 ++-- drivers/media/video/em28xx/em28xx-core.c | 6 +++--- drivers/media/video/em28xx/em28xx-i2c.c | 4 ++-- drivers/media/video/em28xx/em28xx-video.c | 2 +- drivers/media/video/et61x251/et61x251_core.c | 2 +- drivers/media/video/hexium_gemini.c | 4 ++-- drivers/media/video/hexium_orion.c | 4 ++-- drivers/media/video/ir-kbd-i2c.c | 2 +- drivers/media/video/ivtv/ivtv-driver.c | 6 +++--- drivers/media/video/meye.c | 2 +- drivers/media/video/mt20xx.c | 4 ++-- drivers/media/video/mxb.c | 4 ++-- drivers/media/video/pms.c | 4 ++-- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 +++--- drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 2 +- drivers/media/video/pwc/pwc-if.c | 8 ++++---- drivers/media/video/saa6588.c | 8 ++++---- drivers/media/video/saa7110.c | 2 +- drivers/media/video/saa7111.c | 2 +- drivers/media/video/saa7114.c | 2 +- drivers/media/video/saa7115.c | 2 +- drivers/media/video/saa711x.c | 2 +- drivers/media/video/saa7134/saa7134-alsa.c | 2 +- drivers/media/video/saa7134/saa7134-core.c | 10 +++++----- drivers/media/video/saa7134/saa7134-dvb.c | 6 +++--- drivers/media/video/saa7134/saa7134-empress.c | 2 +- drivers/media/video/saa7134/saa7134-i2c.c | 4 ++-- drivers/media/video/saa7134/saa7134-input.c | 6 +++--- drivers/media/video/saa7134/saa7134-ts.c | 2 +- drivers/media/video/saa7134/saa7134-tvaudio.c | 6 +++--- drivers/media/video/saa7134/saa7134-vbi.c | 2 +- drivers/media/video/saa7134/saa7134-video.c | 2 +- drivers/media/video/saa7185.c | 2 +- drivers/media/video/se401.c | 2 +- drivers/media/video/sn9c102/sn9c102_core.c | 2 +- drivers/media/video/stradis.c | 4 ++-- drivers/media/video/stv680.c | 9 ++++++--- drivers/media/video/tda9840.c | 2 +- drivers/media/video/tea5761.c | 2 +- drivers/media/video/tea5767.c | 2 +- drivers/media/video/tea6415c.c | 2 +- drivers/media/video/tea6420.c | 2 +- drivers/media/video/tuner-core.c | 6 +++--- drivers/media/video/tvaudio.c | 8 ++++---- drivers/media/video/tvp5150.c | 2 +- drivers/media/video/usbvideo/ibmcam.c | 2 +- drivers/media/video/usbvideo/konicawc.c | 2 +- drivers/media/video/usbvideo/quickcam_messenger.c | 2 +- drivers/media/video/usbvideo/ultracam.c | 4 ++-- drivers/media/video/usbvideo/usbvideo.c | 2 +- drivers/media/video/usbvision/usbvision-core.c | 14 ++++++++------ drivers/media/video/usbvision/usbvision-i2c.c | 2 +- drivers/media/video/usbvision/usbvision-video.c | 4 ++-- drivers/media/video/v4l1-compat.c | 2 +- drivers/media/video/videobuf-dma-sg.c | 2 +- drivers/media/video/videobuf-dvb.c | 2 +- drivers/media/video/videobuf-vmalloc.c | 2 +- drivers/media/video/videocodec.c | 4 ++-- drivers/media/video/vino.c | 10 +++++----- drivers/media/video/vpx3220.c | 2 +- drivers/media/video/w9966.c | 4 ++-- drivers/media/video/w9968cf.c | 2 +- drivers/media/video/zc0301/zc0301_core.c | 2 +- drivers/media/video/zoran_card.c | 6 +++--- drivers/media/video/zoran_device.c | 5 +++-- drivers/media/video/zoran_driver.c | 2 +- drivers/media/video/zr36016.c | 5 ++--- drivers/media/video/zr36050.c | 5 ++--- drivers/media/video/zr36060.c | 6 +++--- drivers/media/video/zr364xx.c | 4 ++-- 111 files changed, 196 insertions(+), 192 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index bb2a027b9483..266505207925 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -34,7 +34,7 @@ static int repeat = 1; module_param(repeat, int, 0444); MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); -static int debug = 0; /* debug level (0,1,2) */ +static int debug; /* debug level (0,1,2) */ module_param(debug, int, 0644); #define dprintk(level, fmt, arg...) if (debug >= level) \ diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 01af4d237eb1..5b30dfc7846b 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -32,7 +32,7 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus #define deb_irq(args...) dprintk(0x08,args) #define deb_chk(args...) dprintk(0x10,args) -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 4c8b62e2c035..efaa297ac34d 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -354,7 +354,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) #ifdef ULE_DEBUG /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ static unsigned char ule_hist[100*TS_SZ]; - static unsigned char *ule_where = ule_hist, ule_dump = 0; + static unsigned char *ule_where = ule_hist, ule_dump; #endif /* For all TS cells in current buffer. diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index 1dc164d5488c..406c4cfa82bb 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -48,7 +48,7 @@ struct cx22702_state { u8 prevUCBlocks; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk /* Register values to initialise the demod */ diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 8c8d7342d0b3..decf798994e9 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -44,7 +44,7 @@ struct dvb_pll_priv { static unsigned int dvb_pll_devcount; -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index bdc9fa88b86a..dc897a3903fc 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -49,7 +49,7 @@ /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */ /* #define USE_EQMSE */ -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c index d313d7dcf386..0eef22dbf8a0 100644 --- a/drivers/media/dvb/frontends/nxt6000.c +++ b/drivers/media/dvb/frontends/nxt6000.c @@ -38,7 +38,7 @@ struct nxt6000_state { struct dvb_frontend frontend; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data) diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 819433485d3b..c5232e8ffc56 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -48,7 +48,7 @@ struct s5h1409_state { u32 qam_state; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk /* Register values to initialise the demod, this will set VSB by default */ diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 2c2c344c4c64..7c64af91e5ac 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -53,7 +53,7 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings); -static int debug = 0; +static int debug; #define dprintk if (debug) printk static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data) diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c index da876f7bfe32..f5b3bfc00436 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb/frontends/sp8870.c @@ -449,15 +449,15 @@ static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks return 0; } -// number of trials to recover from lockup +/* number of trials to recover from lockup */ #define MAXTRIALS 5 -// maximum checks for data valid signal +/* maximum checks for data valid signal */ #define MAXCHECKS 100 -// only for debugging: counter for detected lockups -static int lockups = 0; -// only for debugging: counter for channel switches -static int switches = 0; +/* only for debugging: counter for detected lockups */ +static int lockups; +/* only for debugging: counter for channel switches */ +static int switches; static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 0d2b69a99ad4..143af96439b9 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -43,7 +43,7 @@ struct tda10086_state { bool has_lock; }; -static int debug = 0; +static int debug; #define dprintk(args...) \ do { \ if (debug) printk(KERN_DEBUG "tda10086: " args); \ diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index bd3ebc284835..9a91eb0333d9 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -26,7 +26,7 @@ #include "tda826x.h" -static int debug = 0; +static int debug; #define dprintk(args...) \ do { \ if (debug) printk(KERN_DEBUG "tda826x: " args); \ diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index 229b11987a58..3190c8d0c17c 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -25,7 +25,7 @@ #include "tda827x.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c index 23fd0303c91b..c041c81f9686 100644 --- a/drivers/media/dvb/frontends/ves1x93.c +++ b/drivers/media/dvb/frontends/ves1x93.c @@ -48,7 +48,7 @@ struct ves1x93_state { u8 demod_type; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk #define DEMOD_VES1893 0 diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 276e3b631dc2..3d508ff4b292 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -46,7 +46,7 @@ static int debug; if (debug) printk(KERN_DEBUG "zl10353: " args); \ } while (0) -static int debug_regs = 0; +static int debug_regs; static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val) { diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 509349211d4f..0f476f75e03d 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -86,7 +86,7 @@ static int rc5_device = -1; module_param(rc5_device, int, 0644); MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); -static int ir_debug = 0; +static int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 7902ae1d9a18..ab39f9694e74 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -542,7 +542,7 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data, int len); #endif -static int numpkt = 0, numts, numstuff, numsec, numinvalid; +static int numpkt, numts, numstuff, numsec, numinvalid; static unsigned long lastj; static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c index aed11477378b..06dfed9ef4c7 100644 --- a/drivers/media/radio/miropcm20-rds.c +++ b/drivers/media/radio/miropcm20-rds.c @@ -19,7 +19,7 @@ #include "miropcm20-rds-core.h" static char * text_buffer; -static int rds_users = 0; +static int rds_users; static int rds_f_open(struct inode *in, struct file *fi) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 57b9e3adc8f0..265c4ea95502 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io=-1; /* default to isapnp activation */ static int radio_nr = -1; -static int users=0; -static int curtuner=0; -static int tunestat=0; -static int sigstrength=0; +static int users; +static int curtuner; +static int tunestat; +static int sigstrength; static wait_queue_head_t read_queue; static struct timer_list readtimer; -static __u8 rdsin=0,rdsout=0,rdsstat=0; +static __u8 rdsin, rdsout, rdsstat; static unsigned char rdsbuf[RDS_BUFFER]; static spinlock_t cadet_io_lock; diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 1366326474e5..02e3a2f05eee 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -404,7 +404,7 @@ MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); module_param(radio_nr, int, 0); #ifdef MODULE -static unsigned long mutefreq = 0; +static unsigned long mutefreq; module_param(mutefreq, ulong, 0); MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); #endif diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index fea2e723e34b..f794f2dbfb32 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(x) (x)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 10d4d89623f1..8ee07a68f702 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index c94a4d0f2804..e4d891b29f63 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -125,8 +125,8 @@ static unsigned char yuv[MAX_AR_FRAME_BYTES]; /* default frequency */ #define DEFAULT_FREQ 50 /* 50 or 75 (MHz) is available as BCLK */ static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */ -static int vga = 0; /* default mode(0:QVGA mode, other:VGA mode) */ -static int vga_interlace = 0; /* 0 is normal mode for, else interlace mode */ +static int vga; /* default mode(0:QVGA mode, other:VGA mode) */ +static int vga_interlace; /* 0 is normal mode for, else interlace mode */ module_param(freq, int, 0); module_param(vga, int, 0); module_param(vga_interlace, int, 0); diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index e663cc045c41..8bfd5c75cb3a 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -57,7 +57,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 7dee2e3235ad..98ee2d8feb34 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index 75fa82c7c735..bfdbc469e30f 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c @@ -54,7 +54,7 @@ #define VBI_DEFLINES 16 static unsigned int vbibufs = 4; -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbibufs, int, 0444); module_param(vbi_debug, int, 0644); diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 032265383df2..40a8e92a01b9 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -523,7 +523,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) int ret=1; unsigned int hi, lo; unsigned int hi2, lo2; - static int state = 0; + static int state; if (buffer == NULL) { @@ -912,7 +912,7 @@ static struct video_device qcam_template= #define MAX_CAMS 4 static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams = 0; +static unsigned int num_cams; static int init_bwqcam(struct parport *port) { diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index cf1546b5a7f1..d4d5adfb0351 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -69,7 +69,7 @@ struct qcam_device { static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; static int probe = 2; -static int force_rgb = 0; +static int force_rgb; static int video_nr = -1; static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) @@ -741,7 +741,7 @@ static struct qcam_device *qcam_init(struct parport *port) } static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams = 0; +static unsigned int num_cams; static int init_cqcam(struct parport *port) { diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 7ae499c9c54c..5195b1f3378a 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("Video"); */ #define MAX_DMA_BUFS 3 -static int alloc_bufs_at_read = 0; +static int alloc_bufs_at_read; module_param(alloc_bufs_at_read, bool, 0444); MODULE_PARM_DESC(alloc_bufs_at_read, "Non-zero value causes DMA buffers to be allocated when the " @@ -99,7 +99,7 @@ MODULE_PARM_DESC(max_buffers, "will be allowed to allocate. These buffers are big and live " "in vmalloc space."); -static int flip = 0; +static int flip; module_param(flip, bool, 0444); MODULE_PARM_DESC(flip, "If set, the sensor will be instructed to flip the image " diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index a76bd786cf13..a439a56c3cc9 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -34,7 +34,7 @@ #include #include -//#define _CPIA2_DEBUG_ +/* #define _CPIA2_DEBUG_ */ #include "cpia2patch.h" @@ -48,7 +48,7 @@ static const char *block_name[] = { }; #endif -static unsigned int debugs_on = 0;//DEBUG_REG; +static unsigned int debugs_on; /* default 0 - DEBUG_REG */ /****************************************************************************** diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c index d8e929863a88..a4574740350d 100644 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ b/drivers/media/video/cpia2/cpia2_usb.c @@ -84,7 +84,7 @@ static struct usb_driver cpia2_driver = { *****************************************************************************/ static void process_frame(struct camera_data *cam) { - static int frame_count = 0; + static int frame_count; unsigned char *inbuff = cam->workbuff->data; diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 92fe0bd37c84..748c79a46549 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -33,7 +33,7 @@ static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index a99e9d5950aa..c37269074524 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -45,7 +45,7 @@ static unsigned int mpegbufs = 32; module_param(mpegbufs,int,0644); MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 01e2ac98970b..12440b91e4b3 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -47,15 +47,15 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int nicam = 0; +static unsigned int nicam; module_param(nicam,int,0644); MODULE_PARM_DESC(nicam,"tv audio is nicam"); -static unsigned int nocomb = 0; +static unsigned int nocomb; module_param(nocomb,int,0644); MODULE_PARM_DESC(nocomb,"disable comb filter"); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index f7b41eb1bb5a..7586fe31f643 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -51,7 +51,7 @@ MODULE_AUTHOR("Chris Pascoe "); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 566b26af523e..c6b44732a082 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -35,11 +35,11 @@ #include "cx88.h" #include -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index bb0911b4d2f6..d2e42c77b5a8 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -57,7 +57,7 @@ struct cx88_IR { u32 mask_keyup; }; -static int ir_debug = 0; +static int ir_debug; module_param(ir_debug, int, 0644); /* debug level [IR] */ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index e357f415db06..a02cabbab778 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -39,7 +39,7 @@ MODULE_AUTHOR("Chris Pascoe "); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 76e5c78d8ae4..c574f450498f 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -53,15 +53,15 @@ #include "cx88.h" -static unsigned int audio_debug = 0; +static unsigned int audio_debug; module_param(audio_debug, int, 0644); MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]"); -static unsigned int always_analog = 0; +static unsigned int always_analog; module_param(always_analog,int,0644); MODULE_PARM_DESC(always_analog,"force analog audio out"); -static unsigned int radio_deemphasis = 0; +static unsigned int radio_deemphasis; module_param(radio_deemphasis,int,0644); MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, " "0=None, 1=50us (elsewhere), 2=75us (USA)"); diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index d96ecfcf393a..0943060682bc 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -11,7 +11,7 @@ static unsigned int vbibufs = 4; module_param(vbibufs,int,0644); MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbi_debug,int,0644); MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 227179620d13..8b293a3357b2 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -63,11 +63,11 @@ MODULE_PARM_DESC(video_nr,"video device numbers"); MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); MODULE_PARM_DESC(radio_nr,"radio device numbers"); -static unsigned int video_debug = 0; +static unsigned int video_debug; module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); -static unsigned int irq_debug = 0; +static unsigned int irq_debug; module_param(irq_debug,int,0644); MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c index 9ceb6b2f3949..88d6df71d051 100644 --- a/drivers/media/video/dpc7146.c +++ b/drivers/media/video/dpc7146.c @@ -54,11 +54,11 @@ #define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); -static int dpc_num = 0; +static int dpc_num; #define DPC_INPUTS 2 static struct v4l2_input dpc_inputs[DPC_INPUTS] = { diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index c1caaa855b99..dbea89c115b1 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -31,7 +31,7 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); @@ -40,7 +40,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int reg_debug = 0; +static unsigned int reg_debug; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); @@ -49,7 +49,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int isoc_debug = 0; +static unsigned int isoc_debug; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index cacd04d46e99..c3d98d81c335 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -33,11 +33,11 @@ /* ----------------------------------------------------------- */ -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 4abe6701a770..c8264f40aa0d 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -74,7 +74,7 @@ MODULE_PARM_DESC(video_nr, "video device numbers"); MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); -static unsigned int video_debug = 0; +static unsigned int video_debug; module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 06b6a3ae06c4..32ebb71097b5 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2538,7 +2538,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct et61x251_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0; diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index c7fed3405655..352f84d440fb 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -25,12 +25,12 @@ #include -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); /* global variables */ -static int hexium_num = 0; +static int hexium_num; #define HEXIUM_GEMINI 4 #define HEXIUM_GEMINI_DUAL 5 diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 137c4736da04..8d3c1482e7ea 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -25,12 +25,12 @@ #include -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); /* global variables */ -static int hexium_num = 0; +static int hexium_num; #define HEXIUM_HV_PCI6_ORION 1 #define HEXIUM_ORION_1SVHS_3BNC 2 diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 9851987b95fb..5084db22bbd3 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -51,7 +51,7 @@ static int debug; module_param(debug, int, 0644); /* debug level (0,1,2) */ -static int hauppauge = 0; +static int hauppauge; module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */ MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 948ca35e7ee8..b533188c9439 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -126,11 +126,11 @@ static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS; static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS; static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS; -static int ivtv_yuv_mode = 0; -static int ivtv_yuv_threshold=-1; +static int ivtv_yuv_mode; +static int ivtv_yuv_threshold = -1; static int ivtv_pci_latency = 1; -int ivtv_debug = 0; +int ivtv_debug; static int newi2c = -1; diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 3d51fa0a52b6..a079e7222cc9 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -789,7 +789,7 @@ static irqreturn_t meye_irq(int irq, void *dev_id) { u32 v; int reqnr; - static int sequence = 0; + static int sequence; v = mchip_read(MCHIP_MM_INTA); diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 74fd6a01d4c4..1fa89dbdff24 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -10,7 +10,7 @@ #include "tuner-i2c.h" #include "mt20xx.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); @@ -24,7 +24,7 @@ module_param(optimize_vco, int, 0644); static unsigned int tv_antenna = 1; module_param(tv_antenna, int, 0644); -static unsigned int radio_antenna = 0; +static unsigned int radio_antenna; module_param(radio_antenna, int, 0644); /* ---------------------------------------------------------------------- */ diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index cb5a510f9251..f68e91fbe7fb 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -38,7 +38,7 @@ #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) /* global variable */ -static int mxb_num = 0; +static int mxb_num; /* initial frequence the tuner will be tuned to. in verden (lower saxony, germany) 4148 is a @@ -47,7 +47,7 @@ static int freq = 4148; module_param(freq, int, 0644); MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup"); -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 6820c2aabd30..4a6c5723f7cc 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -57,11 +57,11 @@ struct i2c_info u8 hits; }; -static int i2c_count = 0; +static int i2c_count; static struct i2c_info i2cinfo[64]; static int decoder = PHILIPS2; -static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ +static int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ /* * I/O ports and Shared Memory diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index d6955fa39598..b74951a97d16 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -44,13 +44,13 @@ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; static DEFINE_MUTEX(pvr2_unit_mtx); -static int ctlchg = 0; +static int ctlchg; static int initusbreset = 1; -static int procreload = 0; +static int procreload; static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; -static int init_pause_msec = 0; +static int init_pause_msec; module_param(ctlchg, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value"); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 62867fa3517a..793c89a8d672 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -35,7 +35,7 @@ */ -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index e0a453a6543d..b6240a1a606f 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -130,8 +130,8 @@ static int default_fbufs = 3; /* Default number of frame buffers */ #ifdef CONFIG_USB_PWC_DEBUG int pwc_trace = PWC_DEBUG_LEVEL; #endif -static int power_save = 0; -static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ +static int power_save; +static int led_on = 100, led_off; /* defaults to LED that is on while in use */ static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */ static struct { int type; @@ -786,8 +786,8 @@ static void pwc_isoc_handler(struct urb *urb) } /* ..status == 0 */ else { /* This is normally not interesting to the user, unless - * you are really debugging something */ - static int iso_error = 0; + * you are really debugging something, default = 0 */ + static int iso_error; iso_error++; if (iso_error < 20) PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst); diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 72e344a12c79..716ee7f64df3 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -44,10 +44,10 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; /* insmod options */ -static unsigned int debug = 0; -static unsigned int xtal = 0; -static unsigned int rbds = 0; -static unsigned int plvl = 0; +static unsigned int debug; +static unsigned int xtal; +static unsigned int rbds; +static unsigned int plvl; static unsigned int bufblocks = 100; module_param(debug, int, 0644); diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 1df2602cd184..4aa82b310708 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); #include #include -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index a0772c53bb1f..96c3d4357722 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -55,7 +55,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index bf91a4faa706..e79075533beb 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(x) (x)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 41e5e518a47e..aaec17f9d4eb 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -57,7 +57,7 @@ MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, " "Hans Verkuil, Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); -static int debug = 0; +static int debug; module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 80bf91187856..cedb988574bd 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); #include -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)"); diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 047add8f3010..505bc0a478af 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -31,7 +31,7 @@ #include "saa7134.h" #include "saa7134-reg.h" -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 58ab163fdbd7..ef1fd5a93b1b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -42,23 +42,23 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -static unsigned int irq_debug = 0; +static unsigned int irq_debug; module_param(irq_debug, int, 0644); MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug, int, 0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int gpio_tracking = 0; +static unsigned int gpio_tracking; module_param(gpio_tracking, int, 0644); MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); -static unsigned int alsa = 0; +static unsigned int alsa; module_param(alsa, int, 0644); MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); -static unsigned int oss = 0; +static unsigned int oss; module_param(oss, int, 0644); MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]"); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index ea2be9eceeb8..9d61d74fabd4 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -47,16 +47,16 @@ MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int antenna_pwr = 0; +static unsigned int antenna_pwr; module_param(antenna_pwr, int, 0444); MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); -static int use_frontend = 0; +static int use_frontend; module_param(use_frontend, int, 0644); MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)"); -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off)."); diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 3d2ec30de227..40d4a66b77f5 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -40,7 +40,7 @@ static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; module_param_array(empress_nr, int, NULL, 0444); MODULE_PARM_DESC(empress_nr,"ts device number"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index d3322c3018f2..ba71dd0040be 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -33,11 +33,11 @@ /* ----------------------------------------------------------- */ -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index b4188819782f..65f8e594d6fb 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -27,15 +27,15 @@ #include "saa7134-reg.h" #include "saa7134.h" -static unsigned int disable_ir = 0; +static unsigned int disable_ir; module_param(disable_ir, int, 0444); MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); -static unsigned int ir_debug = 0; +static unsigned int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); -static int pinnacle_remote = 0; +static int pinnacle_remote; module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index f1b8fcaeb43a..eae72fd60cec 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -32,7 +32,7 @@ /* ------------------------------------------------------------------ */ -static unsigned int ts_debug = 0; +static unsigned int ts_debug; module_param(ts_debug, int, 0644); MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]"); diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 4e9810469ae3..b90c55c0536e 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -35,18 +35,18 @@ /* ------------------------------------------------------------------ */ -static unsigned int audio_debug = 0; +static unsigned int audio_debug; module_param(audio_debug, int, 0644); MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]"); -static unsigned int audio_ddep = 0; +static unsigned int audio_ddep; module_param(audio_ddep, int, 0644); MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite"); static int audio_clock_override = UNSET; module_param(audio_clock_override, int, 0644); -static int audio_clock_tweak = 0; +static int audio_clock_tweak; module_param(audio_clock_tweak, int, 0644); MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])"); diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c index f0d5ed9c2b06..cb0304298a96 100644 --- a/drivers/media/video/saa7134/saa7134-vbi.c +++ b/drivers/media/video/saa7134/saa7134-vbi.c @@ -31,7 +31,7 @@ /* ------------------------------------------------------------------ */ -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbi_debug, int, 0644); MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 39c41ad97d0e..5385026a85ef 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -40,7 +40,7 @@ unsigned int video_debug; static unsigned int gbuffers = 8; -static unsigned int noninterlaced = 0; +static unsigned int noninterlaced; /* 0 */ static unsigned int gbufsize = 720*576*4; static unsigned int gbufsize_max = 720*576*4; static char secam[] = "--"; diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 41f70440fd3b..02fda4eecea3 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index d5d7d6cf734a..312a01a1f095 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -35,7 +35,7 @@ static const char version[] = "0.24"; #include #include "se401.h" -static int flickerless=0; +static int flickerless; static int video_nr = -1; static struct usb_device_id device_table [] = { diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index c40ba3adab21..e5ef0190ebdc 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -3239,7 +3239,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct sn9c102_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0, r; diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 3fb85af5d1f2..3118dd322b24 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -58,7 +58,7 @@ static struct saa7146 saa7146s[SAA7146_MAX]; -static int saa_num = 0; /* number of SAA7146s in use */ +static int saa_num; /* number of SAA7146s in use */ static int video_nr = -1; module_param(video_nr, int, 0); @@ -248,7 +248,7 @@ static void I2CBusScan(struct saa7146 *saa) attach_inform(saa, i); } -static int debiwait_maxwait = 0; +static int debiwait_maxwait; static int wait_for_debi_done(struct saa7146 *saa) { diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index afc32aa56fde..1542797c048f 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -72,10 +72,13 @@ #include "stv680.h" static int video_nr = -1; -static int swapRGB = 0; /* default for auto sleect */ -static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */ -static unsigned int debug = 0; +static int swapRGB; /* 0 = default for auto select */ + +/* 0 = default to allow auto select; -1 = swap never, +1 = swap always */ +static int swapRGB_on; + +static unsigned int debug; #define PDEBUG(level, fmt, args...) \ do { \ diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index bdca5d278978..269761ce84a5 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -31,7 +31,7 @@ #include "tda9840.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c index 5326eeceaacd..35612665d933 100644 --- a/drivers/media/video/tea5761.c +++ b/drivers/media/video/tea5761.c @@ -14,7 +14,7 @@ #include "tuner-i2c.h" #include "tea5761.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index e1b48d87e7b7..ba66c6d3e2b9 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -16,7 +16,7 @@ #include "tuner-i2c.h" #include "tea5767.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index df2fad9f391e..f22620e1872e 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -33,7 +33,7 @@ #include "tea6415c.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index 4ff6c63f7237..dc0f0405f4c9 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -33,7 +33,7 @@ #include "tea6420.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 78a09a2a4857..770dbcbecb63 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -68,9 +68,9 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; /* insmod options used at init time => read/only */ -static unsigned int addr = 0; -static unsigned int no_autodetect = 0; -static unsigned int show_i2c = 0; +static unsigned int addr; +static unsigned int no_autodetect; +static unsigned int show_i2c; /* insmod options used at runtime => read/write */ static int tuner_debug; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 01ebcec040c4..f29a2cd0f2f2 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -38,7 +38,7 @@ /* ---------------------------------------------------------------------- */ /* insmod args */ -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips"); @@ -1235,11 +1235,11 @@ static int tda9850 = 1; static int tda9855 = 1; static int tda9873 = 1; static int tda9874a = 1; -static int tea6300 = 0; /* address clash with msp34xx */ -static int tea6320 = 0; /* address clash with msp34xx */ +static int tea6300; /* default 0 - address clash with msp34xx */ +static int tea6320; /* default 0 - address clash with msp34xx */ static int tea6420 = 1; static int pic16c54 = 1; -static int ta8874z = 0; /* address clash with tda9840 */ +static int ta8874z; /* default 0 - address clash with tda9840 */ module_param(tda8425, int, 0444); module_param(tda9840, int, 0444); diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index b6e24e714a23..6a3af1005f03 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -27,7 +27,7 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index 14db95e10cfe..84ee6b1d9fd2 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -121,7 +121,7 @@ static int init_model2_yb = -1; /* 01.01.08 - Added for RCA video in support -LO */ /* Settings for camera model 3 */ -static int init_model3_input = 0; +static int init_model3_input; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 719b17ce83f8..97479609f97d 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -61,7 +61,7 @@ static int debug; } #else #define DEBUG(n, arg...) -static const int debug = 0; +static const int debug; #endif diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index a2acba0bcc47..e0ee6d8f2565 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -50,7 +50,7 @@ static int debug; } #else #define DEBUG(n, arg...) -static const int debug = 0; +static const int debug; #endif #define DRIVER_VERSION "v0.01" diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c index 95453c108d40..9544e644bf0d 100644 --- a/drivers/media/video/usbvideo/ultracam.c +++ b/drivers/media/video/usbvideo/ultracam.c @@ -28,9 +28,9 @@ typedef struct { static struct usbvideo *cams = NULL; -static int debug = 0; +static int debug; -static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ +static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ static const int min_canvasWidth = 8; static const int min_canvasHeight = 4; diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index 5d363be7bc73..f1ccf59545d4 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -522,7 +522,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) struct usbvideo_frame *frame; int num_cell = 0; int scan_length = 0; - static int num_pass = 0; + static int num_pass; if (uvd == NULL) { err("%s: uvd == NULL", __FUNCTION__); diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 56775ab8b75d..47f64a031cad 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -53,19 +53,21 @@ #include "usbvision.h" -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int force_testpattern = 0; +static unsigned int force_testpattern; module_param(force_testpattern,int,0644); MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); -static int adjustCompression = 1; // Set the compression to be adaptive +static int adjustCompression = 1; /* Set the compression to be adaptive */ module_param(adjustCompression, int, 0444); MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); -static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. +/* To help people with Black and White output with using s-video input. + * Some cables and input device are wired differently. */ +static int SwitchSVideoInput; module_param(SwitchSVideoInput, int, 0444); MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); @@ -418,7 +420,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, unsigned char *f; int num_cell = 0; int scan_length = 0; - static int num_pass = 0; + static int num_pass; if (usbvision == NULL) { printk(KERN_ERR "%s: usbvision == NULL\n", proc); @@ -1430,7 +1432,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, } #if ENABLE_HEXDUMP if (totlen > 0) { - static int foo = 0; + static int foo; if (foo < 1) { printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index aabc42cae9c7..a7ed6f21f119 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -40,7 +40,7 @@ #define DBG_I2C 1<<0 -static int i2c_debug = 0; +static int i2c_debug; module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index df52f8a60215..2c2e10639564 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -115,7 +115,7 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) /* sequential number of usbvision device */ -static int usbvision_nr = 0; +static int usbvision_nr; static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, @@ -135,7 +135,7 @@ static void usbvision_release(struct usb_usbvision *usbvision); /* Set the default format for ISOC endpoint */ static int isocMode = ISOC_MODE_COMPRESS; /* Set the default Debug Mode of the device driver */ -static int video_debug = 0; +static int video_debug; /* Set the default device to power on at startup */ static int PowerOnAtOpen = 1; /* Sequential Number of Video Device */ diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 50e1ff9f2be5..118a0611b6ed 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -39,7 +39,7 @@ #include #endif -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); MODULE_AUTHOR("Bill Dirks"); diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 53fed4b74ce9..7008afabe92c 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -39,7 +39,7 @@ #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers"); diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index b73aba65d21d..4ba8b7db7fda 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -30,7 +30,7 @@ MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 5266ecc91dab..3de3c8920175 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -33,7 +33,7 @@ #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers"); diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c index 87951ec8254f..b30b6b2a9a85 100644 --- a/drivers/media/video/videocodec.c +++ b/drivers/media/video/videocodec.c @@ -44,7 +44,7 @@ #include "videocodec.h" -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); @@ -325,7 +325,7 @@ videocodec_unregister (const struct videocodec *codec) /* ============ */ static char *videocodec_buf = NULL; -static int videocodec_bufsize = 0; +static int videocodec_bufsize; static int videocodec_build_table (void) diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 5bb75294b5aa..d545c98dd5e7 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -333,7 +333,7 @@ struct vino_settings { * * Use non-zero value to enable conversion. */ -static int vino_pixel_conversion = 0; +static int vino_pixel_conversion; module_param_named(pixelconv, vino_pixel_conversion, int, 0); @@ -4370,8 +4370,8 @@ static int vino_ioctl(struct inode *inode, struct file *file, /* Initialization and cleanup */ -// __initdata -static int vino_init_stage = 0; +/* __initdata */ +static int vino_init_stage; static const struct file_operations vino_fops = { .owner = THIS_MODULE, @@ -4385,8 +4385,8 @@ static const struct file_operations vino_fops = { static struct video_device v4l_device_template = { .name = "NOT SET", - //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | - // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY + /*.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | */ + /* VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY */ .fops = &vino_fops, .minor = -1, }; diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index a9133858e913..35293029da02 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -40,7 +40,7 @@ #define I2C_VPX3220 0x86 #define VPX3220_DEBUG KERN_DEBUG "vpx3220: " -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 08aaae07c7e0..cc8c8246c30e 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -61,7 +61,7 @@ #include #include -//#define DEBUG // Undef me for production +/*#define DEBUG*/ /* Undef me for production */ #ifdef DEBUG #define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a) @@ -134,7 +134,7 @@ MODULE_PARM_DESC(pardev, "pardev: where to search for\n\ \tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\ \tcam 1 to parport3 and search every parport for cam 2 etc..."); -static int parmode = 0; +static int parmode; module_param(parmode, int, 0); MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp"); diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 2ae1430f5f7d..cce23d24e6fc 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -3481,7 +3481,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) enum w9968cf_model_id mod_id; struct list_head* ptr; u8 sc = 0; /* number of simultaneous cameras */ - static unsigned short dev_nr = 0; /* we are handling device number n */ + static unsigned short dev_nr; /* 0 - we are handling device number n */ if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 2c5665c82442..af357cbcb9bb 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -1939,7 +1939,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct zc0301_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0; diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index 690281bb59ee..006d48847e24 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -83,7 +83,7 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder"); or set in in a VIDIOCSFBUF ioctl */ -static unsigned long vidmem = 0; /* Video memory base address */ +static unsigned long vidmem; /* default = 0 - Video memory base address */ module_param(vidmem, ulong, 0444); MODULE_PARM_DESC(vidmem, "Default video memory base address"); @@ -91,7 +91,7 @@ MODULE_PARM_DESC(vidmem, "Default video memory base address"); Default input and video norm at startup of the driver. */ -static unsigned int default_input = 0; /* 0=Composite, 1=S-Video */ +static unsigned int default_input; /* default 0 = Composite, 1 = S-Video */ module_param(default_input, uint, 0444); MODULE_PARM_DESC(default_input, "Default input (0=Composite, 1=S-Video, 2=Internal)"); @@ -101,7 +101,7 @@ module_param(default_mux, int, 0644); MODULE_PARM_DESC(default_mux, "Default 6 Eyes mux setting (Input selection)"); -static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ +static int default_norm; /* default 0 = PAL, 1 = NTSC 2 = SECAM */ module_param(default_norm, int, 0444); MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index f97c20692057..10686c68a65b 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -60,7 +60,8 @@ extern const struct zoran_format zoran_formats[]; -static int lml33dpath = 0; /* 1 will use digital path in capture +static int lml33dpath; /* default = 0 + * 1 will use digital path in capture * mode instead of analog. It can be * used for picture adjustments using * tool like xawtv while watching image @@ -987,7 +988,7 @@ void zr36057_enable_jpg (struct zoran *zr, enum zoran_codec_mode mode) { - static int zero = 0; + static int zero; static int one = 1; struct vfe_settings cap; int field_size = diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index fea4946ee713..5cca61cb8ba8 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -205,7 +205,7 @@ extern int jpg_nbufs; extern int jpg_bufsize; extern int pass_through; -static int lock_norm = 0; /* 1=Don't change TV standard (norm) */ +static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ module_param(lock_norm, int, 0644); MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c index dd084555da8f..00d132bcd1e4 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zr36016.c @@ -55,11 +55,10 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36016_codecs = 0; +static int zr36016_codecs; /* debugging is available via module parameter */ - -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index faae4ec3ea0b..cf8b271a1c8f 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c @@ -52,11 +52,10 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36050_codecs = 0; +static int zr36050_codecs; /* debugging is available via module parameter */ - -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index 7849b65969d0..8e74054d5ef1 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -52,14 +52,14 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36060_codecs = 0; +static int zr36060_codecs; -static int low_bitrate = 0; +static int low_bitrate; module_param(low_bitrate, bool, 0); MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate"); /* debugging is available via module parameter */ -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 04949c823654..a0e49dc66301 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -62,8 +62,8 @@ /* Module parameters */ -static int debug = 0; -static int mode = 0; +static int debug; +static int mode; /* Module parameters interface */ -- cgit v1.2.3 From 6e34f22d9fe481c28048bb866468e50fbf854a93 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:54 -0300 Subject: V4L/DVB (7123): tuner-simple: create separate t_params and ranges lookup functions Move some reuseable code out of simple_set_tv_freq into separate functions. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 109 +++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 770d6281c154..4854fc4a7d39 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -173,6 +173,82 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength) /* ---------------------------------------------------------------------- */ +static inline char *tuner_param_name(enum param_type type) +{ + char *name; + + switch (type) { + case TUNER_PARAM_TYPE_RADIO: + name = "radio"; + break; + case TUNER_PARAM_TYPE_PAL: + name = "pal"; + break; + case TUNER_PARAM_TYPE_SECAM: + name = "secam"; + break; + case TUNER_PARAM_TYPE_NTSC: + name = "ntsc"; + break; + default: + name = "unknown"; + break; + } + return name; +} + +static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe, + enum param_type desired_type) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + struct tunertype *tun = priv->tun; + int i; + + for (i = 0; i < tun->count; i++) + if (desired_type == tun->params[i].type) + break; + + /* use default tuner params if desired_type not available */ + if (i == tun->count) { + tuner_dbg("desired params (%s) undefined for tuner %d\n", + tuner_param_name(desired_type), priv->type); + i = 0; + } + + tuner_dbg("using tuner params #%d (%s)\n", i, + tuner_param_name(tun->params[i].type)); + + return &tun->params[i]; +} + +static int simple_config_lookup(struct dvb_frontend *fe, + struct tuner_params *t_params, + int *frequency, u8 *config, u8 *cb) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int i; + + for (i = 0; i < t_params->count; i++) { + if (*frequency > t_params->ranges[i].limit) + continue; + break; + } + if (i == t_params->count) { + tuner_dbg("frequency out of range (%d > %d)\n", + *frequency, t_params->ranges[i - 1].limit); + *frequency = t_params->ranges[--i].limit; + } + *config = t_params->ranges[i].config; + *cb = t_params->ranges[i].cb; + + tuner_dbg("freq = %d, range = %d, config = 0x%02x, cb = 0x%02x\n", + *frequency, i, *config, *cb); + + return i; +} + +/* ---------------------------------------------------------------------- */ + static int simple_set_tv_freq(struct dvb_frontend *fe, struct analog_parameters *params) { @@ -181,7 +257,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, u16 div; struct tunertype *tun; u8 buffer[4]; - int rc, IFPCoff, i, j; + int rc, IFPCoff, i; enum param_type desired_type; struct tuner_params *t_params; @@ -214,35 +290,10 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, desired_type = TUNER_PARAM_TYPE_PAL; } - for (j = 0; j < tun->count-1; j++) { - if (desired_type != tun->params[j].type) - continue; - break; - } - /* use default tuner params if desired_type not available */ - if (desired_type != tun->params[j].type) { - tuner_dbg("IFPCoff = %d: params undefined for tuner %d\n", - IFPCoff, priv->type); - j = 0; - } - t_params = &tun->params[j]; + t_params = simple_tuner_params(fe, desired_type); - for (i = 0; i < t_params->count; i++) { - if (params->frequency > t_params->ranges[i].limit) - continue; - break; - } - if (i == t_params->count) { - tuner_dbg("TV frequency out of range (%d > %d)", - params->frequency, t_params->ranges[i - 1].limit); - params->frequency = t_params->ranges[--i].limit; - } - config = t_params->ranges[i].config; - cb = t_params->ranges[i].cb; - /* i == 0 -> VHF_LO - * i == 1 -> VHF_HI - * i == 2 -> UHF */ - tuner_dbg("tv: param %d, range %d\n", j, i); + i = simple_config_lookup(fe, t_params, ¶ms->frequency, + &config, &cb); div = params->frequency + IFPCoff + offset; -- cgit v1.2.3 From e83a813784ecb948fa658e9d720f4ece528984d1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:54 -0300 Subject: V4L/DVB (7124): tuner-simple: display frequency in MHz fix debug in simple_config_lookup to display frequency in MHz Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 4854fc4a7d39..85556d44c8ab 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -241,8 +241,10 @@ static int simple_config_lookup(struct dvb_frontend *fe, *config = t_params->ranges[i].config; *cb = t_params->ranges[i].cb; - tuner_dbg("freq = %d, range = %d, config = 0x%02x, cb = 0x%02x\n", - *frequency, i, *config, *cb); + tuner_dbg("freq = %d.%02d (%d), range = %d, " + "config = 0x%02x, cb = 0x%02x\n", + *frequency / 16, *frequency % 16 * 100 / 16, *frequency, + i, *config, *cb); return i; } -- cgit v1.2.3 From 008930de0b39e2c312e5570af69a8e1548c214d2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:55 -0300 Subject: V4L/DVB (7125): tuner: build tuner-types independently of tuner-core tuner-types is needed for tuner-simple, and does not need to be bound to tuner-core. Any caller of tuner-simple, including tuner-core, needs to pass a structure from tuner-types into tuner-simple at attach-time. Export the two needed symbols from tuner-types for now, so that card-level drivers can attach tuner-simple for hybrid dvb_frontend devices. We will remove this dependency altogether as tuner refactoring phase 3 progresses. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 5 +++++ drivers/media/video/Makefile | 3 ++- drivers/media/video/tuner-types.c | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 11950698a2e7..408838418d04 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -71,9 +71,13 @@ source "drivers/media/dvb/Kconfig" source "drivers/media/common/Kconfig" +config VIDEO_TUNER_TYPES + tristate + config VIDEO_TUNER tristate depends on I2C + select VIDEO_TUNER_TYPES select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE @@ -136,6 +140,7 @@ config TUNER_TEA5767 config TUNER_SIMPLE tristate "Simple tuner support" depends on I2C + select VIDEO_TUNER_TYPES select TUNER_TDA9887 default m if VIDEO_TUNER_CUSTOMIZE help diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 3f209b32eeac..6f1ef09df1d6 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -4,7 +4,7 @@ zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o -tuner-objs := tuner-core.o tuner-types.o +tuner-objs := tuner-core.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o @@ -84,6 +84,7 @@ obj-$(CONFIG_VIDEO_DPC) += dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEO_TUNER) += tuner.o +obj-$(CONFIG_VIDEO_TUNER_TYPES) += tuner-types.o obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 883047f9c28c..87f28b5a2cfa 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1480,5 +1480,19 @@ struct tunertype tuners[] = { /* see xc5000.c for details */ }, }; +EXPORT_SYMBOL(tuners); unsigned const int tuner_count = ARRAY_SIZE(tuners); +EXPORT_SYMBOL(tuner_count); + +MODULE_DESCRIPTION("Simple tuner device type database"); +MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); +MODULE_LICENSE("GPL"); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ -- cgit v1.2.3 From 5446156fc44450d70732a6b551593af94c206e85 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:55 -0300 Subject: V4L/DVB (7126): tuner: move tuner type ID check to simple_tuner_attach Move tuner type ID check from tuner-core::set_type to simple_tuner_attach. Since tuner-core forwards all attach requests to tuner-simple as the default case, unless a specific attach function is specified in set_type, this change is an appropriate cleanup. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 5 ----- drivers/media/video/tuner-simple.c | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 770dbcbecb63..4d791766ce11 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -352,11 +352,6 @@ static void set_type(struct i2c_client *c, unsigned int type, return; } - if (type >= tuner_count) { - tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count); - return; - } - t->type = type; t->config = new_config; if (tuner_callback != NULL) { diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 85556d44c8ab..d3362703e258 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -688,6 +688,12 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, { struct tuner_simple_priv *priv = NULL; + if (type >= tuner_count) { + printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n", + __FUNCTION__, type, tuner_count-1); + return NULL; + } + priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL); if (priv == NULL) return NULL; -- cgit v1.2.3 From b39eb0d254f807b5ea19ec3929852ea01a9f8bcb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:55 -0300 Subject: V4L/DVB (7127): tuner: remove dependency of tuner-core on tuner-types This patch fully removes the dependency of tuner-core on tuner-types. There is no longer any need to pass struct tunertype in attach-time config structure - instead pass the tuner type ID. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 11 +++-------- drivers/media/video/tuner-simple.c | 10 +++++----- drivers/media/video/tuner-simple.h | 11 ++--------- 3 files changed, 10 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 4d791766ce11..d6b64e9178eb 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -313,18 +313,13 @@ static void tuner_i2c_address_check(struct tuner *t) tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", - t->i2c->adapter->name, t->i2c->addr, t->type, - tuners[t->type].name); + t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name); tuner_warn("====================== WARNING! ======================\n"); } -static void attach_simple_tuner(struct tuner *t) +static inline void attach_simple_tuner(struct tuner *t) { - struct simple_tuner_config cfg = { - .type = t->type, - .tun = &tuners[t->type] - }; - simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); + simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, t->type); } static void attach_tda829x(struct tuner *t) diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index d3362703e258..de0b291459f7 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -684,7 +684,7 @@ static struct dvb_tuner_ops simple_tuner_ops = { struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg) + unsigned int type) { struct tuner_simple_priv *priv = NULL; @@ -701,15 +701,15 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; - priv->type = cfg->type; - priv->tun = cfg->tun; + priv->type = type; + priv->tun = &tuners[type]; memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); - tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name); + tuner_info("type set to %d (%s)\n", priv->type, priv->tun->name); - strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, + strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name, sizeof(fe->ops.tuner_ops.info.name)); return fe; diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h index 9089939a8c02..bf425f325f87 100644 --- a/drivers/media/video/tuner-simple.h +++ b/drivers/media/video/tuner-simple.h @@ -20,23 +20,16 @@ #include #include "dvb_frontend.h" -struct simple_tuner_config -{ - /* chip type */ - unsigned int type; - struct tunertype *tun; -}; - #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE)) extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg); + unsigned int type); #else static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg) + unsigned int type) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return NULL; -- cgit v1.2.3 From ab1160cf431f33bac6c87758e831b9b1d2caec4a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:56 -0300 Subject: V4L/DVB (7128): tuner: properly handle failed calls to simple_tuner_attach If simple_tuner_attach fails, set t->type to TUNER_ABSENT, set t->mode_mask to T_UNINITIALIZED, and exit the set_type function. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index d6b64e9178eb..335a971298a3 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -317,11 +317,6 @@ static void tuner_i2c_address_check(struct tuner *t) tuner_warn("====================== WARNING! ======================\n"); } -static inline void attach_simple_tuner(struct tuner *t) -{ - simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, t->type); -} - static void attach_tda829x(struct tuner *t) { struct tda829x_config cfg = { @@ -399,7 +394,12 @@ static void set_type(struct i2c_client *c, unsigned int type, buffer[2] = 0x86; buffer[3] = 0x54; i2c_master_send(c, buffer, 4); - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, + t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; case TUNER_PHILIPS_TD1316: buffer[0] = 0x0b; @@ -407,7 +407,12 @@ static void set_type(struct i2c_client *c, unsigned int type, buffer[2] = 0x86; buffer[3] = 0xa4; i2c_master_send(c,buffer,4); - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, + t->i2c->addr, t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; case TUNER_XC2028: { @@ -445,7 +450,12 @@ static void set_type(struct i2c_client *c, unsigned int type, } break; default: - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, + t->i2c->addr, t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; } -- cgit v1.2.3 From dee6327ca2932f71db910e4af3ca6f140386f378 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:56 -0300 Subject: V4L/DVB (7129): tuner-simple: move device-specific code into three separate functions Move the switch..case blocks with device-specific code from functions simple_set_tv_freq and simple_set_radio_freq ...into three new functions: simple_std_setup, simple_post_tune and simple_radio_bandswitch Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 331 +++++++++++++++++++++---------------- 1 file changed, 184 insertions(+), 147 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index de0b291459f7..10addf2ba5ce 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -251,59 +251,13 @@ static int simple_config_lookup(struct dvb_frontend *fe, /* ---------------------------------------------------------------------- */ -static int simple_set_tv_freq(struct dvb_frontend *fe, - struct analog_parameters *params) +static int simple_std_setup(struct dvb_frontend *fe, + struct analog_parameters *params, + u8 *buffer, u8 *config, u8 *cb) { struct tuner_simple_priv *priv = fe->tuner_priv; - u8 config, cb, tuneraddr; - u16 div; - struct tunertype *tun; - u8 buffer[4]; - int rc, IFPCoff, i; - enum param_type desired_type; - struct tuner_params *t_params; - - tun = priv->tun; - - /* IFPCoff = Video Intermediate Frequency - Vif: - 940 =16*58.75 NTSC/J (Japan) - 732 =16*45.75 M/N STD - 704 =16*44 ATSC (at DVB code) - 632 =16*39.50 I U.K. - 622.4=16*38.90 B/G D/K I, L STD - 592 =16*37.00 D China - 590 =16.36.875 B Australia - 543.2=16*33.95 L' STD - 171.2=16*10.70 FM Radio (at set_radio_freq) - */ - - if (params->std == V4L2_STD_NTSC_M_JP) { - IFPCoff = 940; - desired_type = TUNER_PARAM_TYPE_NTSC; - } else if ((params->std & V4L2_STD_MN) && - !(params->std & ~V4L2_STD_MN)) { - IFPCoff = 732; - desired_type = TUNER_PARAM_TYPE_NTSC; - } else if (params->std == V4L2_STD_SECAM_LC) { - IFPCoff = 543; - desired_type = TUNER_PARAM_TYPE_SECAM; - } else { - IFPCoff = 623; - desired_type = TUNER_PARAM_TYPE_PAL; - } - - t_params = simple_tuner_params(fe, desired_type); - - i = simple_config_lookup(fe, t_params, ¶ms->frequency, - &config, &cb); - - div = params->frequency + IFPCoff + offset; - - tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " - "Offset=%d.%02d MHz, div=%0d\n", - params->frequency / 16, params->frequency % 16 * 100 / 16, - IFPCoff / 16, IFPCoff % 16 * 100 / 16, - offset / 16, offset % 16 * 100 / 16, div); + u8 tuneraddr; + int rc; /* tv norm specific stuff for multi-norm tuners */ switch (priv->type) { @@ -311,45 +265,45 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, /* 0x01 -> ??? no change ??? */ /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ - cb &= ~0x03; + *cb &= ~0x03; if (params->std & V4L2_STD_SECAM_L) /* also valid for V4L2_STD_SECAM */ - cb |= PHILIPS_MF_SET_STD_L; + *cb |= PHILIPS_MF_SET_STD_L; else if (params->std & V4L2_STD_SECAM_LC) - cb |= PHILIPS_MF_SET_STD_LC; + *cb |= PHILIPS_MF_SET_STD_LC; else /* V4L2_STD_B|V4L2_STD_GH */ - cb |= PHILIPS_MF_SET_STD_BG; + *cb |= PHILIPS_MF_SET_STD_BG; break; case TUNER_TEMIC_4046FM5: - cb &= ~0x0f; + *cb &= ~0x0f; if (params->std & V4L2_STD_PAL_BG) { - cb |= TEMIC_SET_PAL_BG; + *cb |= TEMIC_SET_PAL_BG; } else if (params->std & V4L2_STD_PAL_I) { - cb |= TEMIC_SET_PAL_I; + *cb |= TEMIC_SET_PAL_I; } else if (params->std & V4L2_STD_PAL_DK) { - cb |= TEMIC_SET_PAL_DK; + *cb |= TEMIC_SET_PAL_DK; } else if (params->std & V4L2_STD_SECAM_L) { - cb |= TEMIC_SET_PAL_L; + *cb |= TEMIC_SET_PAL_L; } break; case TUNER_PHILIPS_FQ1216ME: - cb &= ~0x0f; + *cb &= ~0x0f; if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { - cb |= PHILIPS_SET_PAL_BGDK; + *cb |= PHILIPS_SET_PAL_BGDK; } else if (params->std & V4L2_STD_PAL_I) { - cb |= PHILIPS_SET_PAL_I; + *cb |= PHILIPS_SET_PAL_I; } else if (params->std & V4L2_STD_SECAM_L) { - cb |= PHILIPS_SET_PAL_L; + *cb |= PHILIPS_SET_PAL_L; } break; @@ -359,15 +313,15 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, /* 0x01 -> ATSC antenna input 2 */ /* 0x02 -> NTSC antenna input 1 */ /* 0x03 -> NTSC antenna input 2 */ - cb &= ~0x03; + *cb &= ~0x03; if (!(params->std & V4L2_STD_ATSC)) - cb |= 2; + *cb |= 2; /* FIXME: input */ break; case TUNER_MICROTUNE_4042FI5: /* Set the charge pump for fast tuning */ - config |= TUNER_CHARGE_PUMP; + *config |= TUNER_CHARGE_PUMP; break; case TUNER_PHILIPS_TUV1236D: @@ -379,9 +333,9 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, buffer[1] = 0x00; buffer[2] = 0x17; buffer[3] = 0x00; - cb &= ~0x40; + *cb &= ~0x40; if (params->std & V4L2_STD_ATSC) { - cb |= 0x40; + *cb |= 0x40; buffer[1] = 0x04; } /* set to the correct mode (analog or digital) */ @@ -400,6 +354,165 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, break; } + return 0; +} + +static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, + u16 div, u8 config, u8 cb) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int rc; + + switch (priv->type) { + case TUNER_LG_TDVS_H06XF: + /* Set the Auxiliary Byte. */ + buffer[0] = buffer[2]; + buffer[0] &= ~0x20; + buffer[0] |= 0x18; + buffer[1] = 0x20; + tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); + + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); + break; + case TUNER_MICROTUNE_4042FI5: + { + /* FIXME - this may also work for other tuners */ + unsigned long timeout = jiffies + msecs_to_jiffies(1); + u8 status_byte = 0; + + /* Wait until the PLL locks */ + for (;;) { + if (time_after(jiffies, timeout)) + return 0; + rc = tuner_i2c_xfer_recv(&priv->i2c_props, + &status_byte, 1); + if (1 != rc) { + tuner_warn("i2c i/o read error: rc == %d " + "(should be 1)\n", rc); + break; + } + if (status_byte & TUNER_PLL_LOCKED) + break; + udelay(10); + } + + /* Set the charge pump for optimized phase noise figure */ + config &= ~TUNER_CHARGE_PUMP; + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; + buffer[2] = config; + buffer[3] = cb; + tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", + buffer[0], buffer[1], buffer[2], buffer[3]); + + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 4)\n", rc); + break; + } + } + + return 0; +} + +static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + switch (priv->type) { + case TUNER_TENA_9533_DI: + case TUNER_YMEC_TVF_5533MF: + tuner_dbg("This tuner doesn't have FM. " + "Most cards have a TEA5767 for FM\n"); + return 0; + case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FMD1216ME_MK3: + case TUNER_LG_NTSC_TAPE: + case TUNER_PHILIPS_FM1256_IH3: + buffer[3] = 0x19; + break; + case TUNER_TNF_5335MF: + buffer[3] = 0x11; + break; + case TUNER_LG_PAL_FM: + buffer[3] = 0xa5; + break; + case TUNER_THOMSON_DTT761X: + buffer[3] = 0x39; + break; + case TUNER_MICROTUNE_4049FM5: + default: + buffer[3] = 0xa4; + break; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int simple_set_tv_freq(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u8 config, cb; + u16 div; + struct tunertype *tun; + u8 buffer[4]; + int rc, IFPCoff, i; + enum param_type desired_type; + struct tuner_params *t_params; + + tun = priv->tun; + + /* IFPCoff = Video Intermediate Frequency - Vif: + 940 =16*58.75 NTSC/J (Japan) + 732 =16*45.75 M/N STD + 704 =16*44 ATSC (at DVB code) + 632 =16*39.50 I U.K. + 622.4=16*38.90 B/G D/K I, L STD + 592 =16*37.00 D China + 590 =16.36.875 B Australia + 543.2=16*33.95 L' STD + 171.2=16*10.70 FM Radio (at set_radio_freq) + */ + + if (params->std == V4L2_STD_NTSC_M_JP) { + IFPCoff = 940; + desired_type = TUNER_PARAM_TYPE_NTSC; + } else if ((params->std & V4L2_STD_MN) && + !(params->std & ~V4L2_STD_MN)) { + IFPCoff = 732; + desired_type = TUNER_PARAM_TYPE_NTSC; + } else if (params->std == V4L2_STD_SECAM_LC) { + IFPCoff = 543; + desired_type = TUNER_PARAM_TYPE_SECAM; + } else { + IFPCoff = 623; + desired_type = TUNER_PARAM_TYPE_PAL; + } + + t_params = simple_tuner_params(fe, desired_type); + + i = simple_config_lookup(fe, t_params, ¶ms->frequency, + &config, &cb); + + div = params->frequency + IFPCoff + offset; + + tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " + "Offset=%d.%02d MHz, div=%0d\n", + params->frequency / 16, params->frequency % 16 * 100 / 16, + IFPCoff / 16, IFPCoff % 16 * 100 / 16, + offset / 16, offset % 16 * 100 / 16, div); + + /* tv norm specific stuff for multi-norm tuners */ + simple_std_setup(fe, params, &buffer[1], &config, &cb); + if (t_params->cb_first_if_lower_freq && div < priv->last_div) { buffer[0] = config; buffer[1] = cb; @@ -463,58 +576,8 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, if (4 != rc) tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); - switch (priv->type) { - case TUNER_LG_TDVS_H06XF: - /* Set the Auxiliary Byte. */ - buffer[0] = buffer[2]; - buffer[0] &= ~0x20; - buffer[0] |= 0x18; - buffer[1] = 0x20; - tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); - - rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); - if (2 != rc) - tuner_warn("i2c i/o error: rc == %d " - "(should be 2)\n", rc); - break; - case TUNER_MICROTUNE_4042FI5: - { - /* FIXME - this may also work for other tuners */ - unsigned long timeout = jiffies + msecs_to_jiffies(1); - u8 status_byte = 0; - - /* Wait until the PLL locks */ - for (;;) { - if (time_after(jiffies, timeout)) - return 0; - rc = tuner_i2c_xfer_recv(&priv->i2c_props, - &status_byte, 1); - if (1 != rc) { - tuner_warn("i2c i/o read error: rc == %d " - "(should be 1)\n", rc); - break; - } - if (status_byte & TUNER_PLL_LOCKED) - break; - udelay(10); - } - - /* Set the charge pump for optimized phase noise figure */ - config &= ~TUNER_CHARGE_PUMP; - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; - buffer[2] = config; - buffer[3] = cb; - tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0], buffer[1], buffer[2], buffer[3]); + simple_post_tune(fe, &buffer[0], div, config, cb); - rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); - if (4 != rc) - tuner_warn("i2c i/o error: rc == %d " - "(should be 4)\n", rc); - break; - } - } return 0; } @@ -555,33 +618,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, } /* Bandswitch byte */ - switch (priv->type) { - case TUNER_TENA_9533_DI: - case TUNER_YMEC_TVF_5533MF: - tuner_dbg("This tuner doesn't have FM. " - "Most cards have a TEA5767 for FM\n"); - return 0; - case TUNER_PHILIPS_FM1216ME_MK3: - case TUNER_PHILIPS_FM1236_MK3: - case TUNER_PHILIPS_FMD1216ME_MK3: - case TUNER_LG_NTSC_TAPE: - case TUNER_PHILIPS_FM1256_IH3: - buffer[3] = 0x19; - break; - case TUNER_TNF_5335MF: - buffer[3] = 0x11; - break; - case TUNER_LG_PAL_FM: - buffer[3] = 0xa5; - break; - case TUNER_THOMSON_DTT761X: - buffer[3] = 0x39; - break; - case TUNER_MICROTUNE_4049FM5: - default: - buffer[3] = 0xa4; - break; - } + simple_radio_bandswitch(fe, &buffer[0]); buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ -- cgit v1.2.3 From 2e4a8d0c94264ae402ce1a3a3b39292b756d2d40 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:56 -0300 Subject: V4L/DVB (7130): tuner: remove emacs c-basic-offset override block I'd prefer to leave this here, but official CodingStyle doesn't care what I think :-/ Remove the emacs format override block to comply with Kernel CodingStyle. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 87f28b5a2cfa..9276ad33d03b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1488,11 +1488,3 @@ EXPORT_SYMBOL(tuner_count); MODULE_DESCRIPTION("Simple tuner device type database"); MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); MODULE_LICENSE("GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ -- cgit v1.2.3 From 6b23b9560a9625d4ece2c3a98e11b231529e7463 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:58 -0300 Subject: V4L/DVB (7134): tuner: create a macro for sharing state between hybrid tuner instances Create a macro implementing a standard method to share state amongst multiple instances of a hybrid tuner object. Also, prepare tuner_foo printk macros for the removal of PREFIX Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-i2c.h | 112 ++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index de52e8ffd347..8ec5b41d459f 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -26,6 +26,10 @@ struct tuner_i2c_props { u8 addr; struct i2c_adapter *adap; + + /* used for tuner instance management */ + int count; + char *name; }; static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len) @@ -59,29 +63,105 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, return (ret == 2) ? ilen : ret; } -#define tuner_warn(fmt, arg...) do { \ - printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr, ##arg); \ +/* Callers must declare as a global for the module: + * + * static LIST_HEAD(hybrid_tuner_instance_list); + * + * hybrid_tuner_instance_list should be the third argument + * passed into hybrid_tuner_request_state(). + * + * state structure must contain the following: + * + * struct list_head hybrid_tuner_instance_list; + * struct tuner_i2c_props i2c_props; + * + * hybrid_tuner_instance_list (both within state structure and globally) + * is only required if the driver is using hybrid_tuner_request_state + * and hybrid_tuner_release_state to manage state sharing between + * multiple instances of hybrid tuners. + */ + +#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \ + printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \ + i2c_adapter_id(i2cprops.adap), \ + i2cprops.addr, ##arg); \ } while (0) -#define tuner_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ +/* TO DO: convert all callers of these macros to pass in + * struct tuner_i2c_props, then remove the macro wrappers */ + +#define __tuner_warn(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \ } while (0) -#define tuner_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ +#define __tuner_info(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \ } while (0) -#define tuner_dbg(fmt, arg...) do { \ +#define __tuner_err(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \ + } while (0) + +#define __tuner_dbg(i2cprops, fmt, arg...) do { \ if ((debug)) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ + tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \ } while (0) +#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg) +#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg) +#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg) +#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg) + +/****************************************************************************/ + +/* The return value of hybrid_tuner_request_state indicates the number of + * instances using this tuner object. + * + * 0 - no instances, indicates an error - kzalloc must have failed + * + * 1 - one instance, indicates that the tuner object was created successfully + * + * 2 (or more) instances, indicates that an existing tuner object was found + */ + +#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\ +({ \ + int __ret = 0; \ + list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \ + if ((i2c_adapter_id(state->i2c_props.adap) == \ + i2c_adapter_id(i2cadap)) && \ + (state->i2c_props.addr == i2caddr)) { \ + __tuner_info(state->i2c_props, \ + "attaching existing instance\n"); \ + state->i2c_props.count++; \ + __ret = state->i2c_props.count; \ + break; \ + } \ + } \ + if (0 == __ret) { \ + state = kzalloc(sizeof(type), GFP_KERNEL); \ + if (NULL == state) \ + goto __fail; \ + state->i2c_props.addr = i2caddr; \ + state->i2c_props.adap = i2cadap; \ + state->i2c_props.name = devname; \ + __tuner_info(state->i2c_props, \ + "creating new instance\n"); \ + list_add_tail(&state->hybrid_tuner_instance_list, &list);\ + state->i2c_props.count++; \ + __ret = state->i2c_props.count; \ + } \ +__fail: \ + __ret; \ +}) + +#define hybrid_tuner_release_state(state) do { \ + state->i2c_props.count--; \ + if (!state->i2c_props.count) { \ + __tuner_info(state->i2c_props, "destroying instance\n");\ + list_del(&state->hybrid_tuner_instance_list); \ + kfree(state); \ + } \ +} while (0) + #endif /* __TUNER_I2C_H__ */ -- cgit v1.2.3 From 3213f69377fb27000cf27bc94fbbe95bff28d8b3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:58 -0300 Subject: V4L/DVB (7135): remove PREFIX from users of tuner_foo printk macros Store a pointer to the device name in the name field of struct tuner_i2c_props, so that we can remove the printk macros defined in tuner-i2c.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt20xx.c | 3 +-- drivers/media/video/tda8290.c | 3 +-- drivers/media/video/tda9887.c | 3 +-- drivers/media/video/tea5761.c | 5 ++--- drivers/media/video/tea5767.c | 32 ++++++++++++++++---------------- drivers/media/video/tuner-simple.c | 4 ++-- drivers/media/video/tuner-xc2028.c | 8 ++++---- 7 files changed, 27 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 1fa89dbdff24..fbcb28233737 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -14,8 +14,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "mt20xx" - /* ---------------------------------------------------------------------- */ static unsigned int optimize_vco = 1; @@ -611,6 +609,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "mt20xx"; //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 55bc89a6f069..6f2449ab46a0 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -32,8 +32,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tda8290" - /* ---------------------------------------------------------------------- */ struct tda8290_priv { @@ -674,6 +672,7 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tda829x"; if (cfg) { priv->cfg.config = cfg->lna_cfg; priv->cfg.tuner_callback = cfg->tuner_callback; diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 106c93b8203f..75d08404d238 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -25,8 +25,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tda9887" - struct tda9887_priv { struct tuner_i2c_props i2c_props; @@ -673,6 +671,7 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tda9887"; priv->mode = T_STANDBY; tuner_info("tda988[5/6/7] found\n"); diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c index 35612665d933..bd5ad549c1df 100644 --- a/drivers/media/video/tea5761.c +++ b/drivers/media/video/tea5761.c @@ -18,8 +18,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5761" - struct tea5761_priv { struct tuner_i2c_props i2c_props; @@ -131,7 +129,7 @@ static void tea5761_status_dump(unsigned char *buffer) frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */ - printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n", + printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n", frq / 1000, frq % 1000, div); } @@ -302,6 +300,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tea5761"; memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops, sizeof(struct dvb_tuner_ops)); diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index ba66c6d3e2b9..833f2768958d 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -20,8 +20,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5767" - /*****************************************************************************/ struct tea5767_priv { @@ -137,14 +135,14 @@ static void tea5767_status_dump(struct tea5767_priv *priv, unsigned int div, frq; if (TEA5767_READY_FLAG_MASK & buffer[0]) - printk(PREFIX "Ready Flag ON\n"); + tuner_info("Ready Flag ON\n"); else - printk(PREFIX "Ready Flag OFF\n"); + tuner_info("Ready Flag OFF\n"); if (TEA5767_BAND_LIMIT_MASK & buffer[0]) - printk(PREFIX "Tuner at band limit\n"); + tuner_info("Tuner at band limit\n"); else - printk(PREFIX "Tuner not at band limit\n"); + tuner_info("Tuner not at band limit\n"); div = ((buffer[0] & 0x3f) << 8) | buffer[1]; @@ -166,23 +164,23 @@ static void tea5767_status_dump(struct tea5767_priv *priv, buffer[0] = (div >> 8) & 0x3f; buffer[1] = div & 0xff; - printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n", - frq / 1000, frq % 1000, div); + tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n", + frq / 1000, frq % 1000, div); if (TEA5767_STEREO_MASK & buffer[2]) - printk(PREFIX "Stereo\n"); + tuner_info("Stereo\n"); else - printk(PREFIX "Mono\n"); + tuner_info("Mono\n"); - printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK); + tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK); - printk(PREFIX "ADC Level = %d\n", - (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4); + tuner_info("ADC Level = %d\n", + (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4); - printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK)); + tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK)); - printk(PREFIX "Reserved = 0x%02x\n", - (buffer[4] & TEA5767_RESERVED_MASK)); + tuner_info("Reserved = 0x%02x\n", + (buffer[4] & TEA5767_RESERVED_MASK)); } /* Freq should be specifyed at 62.5 Hz */ @@ -456,6 +454,8 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tea5767"; + priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768; priv->ctrl.port1 = 1; priv->ctrl.port2 = 1; diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 10addf2ba5ce..dc2467159ece 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -17,8 +17,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tuner-simple" - static int offset; module_param(offset, int, 0664); MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner"); @@ -738,6 +736,8 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tuner-simple"; + priv->type = type; priv->tun = &tuners[type]; diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 8f4fdf70f7eb..42dc2c6ccbbf 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -23,8 +23,6 @@ #include "dvb_frontend.h" -#define PREFIX "xc2028" - static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); @@ -1153,13 +1151,13 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, void *video_dev; if (debug) - printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n"); + printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n"); if (NULL == cfg || NULL == cfg->video_dev) return NULL; if (!fe) { - printk(KERN_ERR PREFIX ": No frontend!\n"); + printk(KERN_ERR "xc2028: No frontend!\n"); return NULL; } @@ -1183,6 +1181,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, priv->i2c_props.addr = cfg->i2c_addr; priv->i2c_props.adap = cfg->i2c_adap; + priv->i2c_props.name = "xc2028"; + priv->video_dev = video_dev; priv->tuner_callback = cfg->callback; priv->ctrl.max_len = 13; -- cgit v1.2.3 From 62ccb84fe46325e53128f13013410f8b06c5d1bf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:59 -0300 Subject: V4L/DVB (7136): tda18271: use hybrid_tuner_request_state to manage tuner instances Convert tda18271 to use the new hybrid_tuner_request_state and hybrid_tuner_release_state macros to manage state sharing between hybrid tuner instances. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-common.c | 19 ++++---- drivers/media/dvb/frontends/tda18271-fe.c | 66 ++++++++++----------------- drivers/media/dvb/frontends/tda18271-priv.h | 7 ++- 3 files changed, 37 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c index bca570990613..39496463ccf3 100644 --- a/drivers/media/dvb/frontends/tda18271-common.c +++ b/drivers/media/dvb/frontends/tda18271-common.c @@ -125,16 +125,16 @@ int tda18271_read_regs(struct dvb_frontend *fe) unsigned char buf = 0x00; int ret; struct i2c_msg msg[] = { - { .addr = priv->i2c_addr, .flags = 0, + { .addr = priv->i2c_props.addr, .flags = 0, .buf = &buf, .len = 1 }, - { .addr = priv->i2c_addr, .flags = I2C_M_RD, + { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, .buf = regs, .len = 16 } }; tda18271_i2c_gate_ctrl(fe, 1); /* read all registers */ - ret = i2c_transfer(priv->i2c_adap, msg, 2); + ret = i2c_transfer(priv->i2c_props.adap, msg, 2); tda18271_i2c_gate_ctrl(fe, 0); @@ -155,16 +155,16 @@ int tda18271_read_extended(struct dvb_frontend *fe) unsigned char buf = 0x00; int ret, i; struct i2c_msg msg[] = { - { .addr = priv->i2c_addr, .flags = 0, + { .addr = priv->i2c_props.addr, .flags = 0, .buf = &buf, .len = 1 }, - { .addr = priv->i2c_addr, .flags = I2C_M_RD, + { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, .buf = regdump, .len = TDA18271_NUM_REGS } }; tda18271_i2c_gate_ctrl(fe, 1); /* read all registers */ - ret = i2c_transfer(priv->i2c_adap, msg, 2); + ret = i2c_transfer(priv->i2c_props.adap, msg, 2); tda18271_i2c_gate_ctrl(fe, 0); @@ -192,7 +192,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; unsigned char buf[TDA18271_NUM_REGS + 1]; - struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = len + 1 }; int i, ret; @@ -205,7 +205,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) tda18271_i2c_gate_ctrl(fe, 1); /* write registers */ - ret = i2c_transfer(priv->i2c_adap, &msg, 1); + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); tda18271_i2c_gate_ctrl(fe, 0); @@ -223,7 +223,8 @@ int tda18271_init_regs(struct dvb_frontend *fe) unsigned char *regs = priv->tda18271_regs; tda_dbg("initializing registers for device @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), priv->i2c_addr); + i2c_adapter_id(priv->i2c_props.adap), + priv->i2c_props.addr); /* initialize registers */ switch (priv->id) { diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index dfe72aaec380..7f7fab7cd5af 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -31,8 +31,8 @@ static int tda18271_cal_on_startup; module_param_named(cal, tda18271_cal_on_startup, int, 0644); MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup"); -static LIST_HEAD(tda18271_list); static DEFINE_MUTEX(tda18271_list_mutex); +static LIST_HEAD(hybrid_tuner_instance_list); /*---------------------------------------------------------------------*/ @@ -986,16 +986,9 @@ static int tda18271_release(struct dvb_frontend *fe) mutex_lock(&tda18271_list_mutex); - priv->count--; + if (priv) + hybrid_tuner_release_state(priv); - if (!priv->count) { - tda_dbg("destroying instance @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), - priv->i2c_addr); - list_del(&priv->tda18271_list); - - kfree(priv); - } mutex_unlock(&tda18271_list_mutex); fe->tuner_priv = NULL; @@ -1109,7 +1102,8 @@ static int tda18271_get_id(struct dvb_frontend *fe) } tda_info("%s detected @ %d-%04x%s\n", name, - i2c_adapter_id(priv->i2c_adap), priv->i2c_addr, + i2c_adapter_id(priv->i2c_props.adap), + priv->i2c_props.addr, (0 == ret) ? "" : ", device not supported."); return ret; @@ -1136,46 +1130,25 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, struct tda18271_config *cfg) { struct tda18271_priv *priv = NULL; - int state_found = 0; + int instance; mutex_lock(&tda18271_list_mutex); - list_for_each_entry(priv, &tda18271_list, tda18271_list) { - if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) && - (priv->i2c_addr == addr)) { - tda_dbg("attaching existing tuner @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), - priv->i2c_addr); - priv->count++; - fe->tuner_priv = priv; - state_found = 1; - /* allow dvb driver to override i2c gate setting */ - if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) - priv->gate = cfg->gate; - break; - } - } - if (state_found == 0) { - tda_dbg("creating new tuner instance @ %d-%04x\n", - i2c_adapter_id(i2c), addr); - - priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); - if (priv == NULL) { - mutex_unlock(&tda18271_list_mutex); - return NULL; - } - - priv->i2c_addr = addr; - priv->i2c_adap = i2c; + instance = hybrid_tuner_request_state(struct tda18271_priv, priv, + hybrid_tuner_instance_list, + i2c, addr, "tda18271"); + switch (instance) { + case 0: + goto fail; + break; + case 1: + /* new tuner instance */ priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; priv->cal_initialized = false; mutex_init(&priv->lock); - priv->count++; fe->tuner_priv = priv; - list_add_tail(&priv->tda18271_list, &tda18271_list); - if (tda18271_get_id(fe) < 0) goto fail; @@ -1189,6 +1162,15 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, tda18271_rf_cal_init(fe); mutex_unlock(&priv->lock); + break; + default: + /* existing tuner instance */ + fe->tuner_priv = priv; + + /* allow dvb driver to override i2c gate setting */ + if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) + priv->gate = cfg->gate; + break; } /* override default std map with values in config struct */ diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index 7b939a5325fb..840b1803d171 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -24,6 +24,7 @@ #include #include #include +#include "tuner-i2c.h" #include "tda18271.h" #define R_ID 0x00 /* ID byte */ @@ -98,17 +99,15 @@ enum tda18271_ver { }; struct tda18271_priv { - u8 i2c_addr; - struct i2c_adapter *i2c_adap; unsigned char tda18271_regs[TDA18271_NUM_REGS]; - struct list_head tda18271_list; + struct list_head hybrid_tuner_instance_list; + struct tuner_i2c_props i2c_props; enum tda18271_mode mode; enum tda18271_i2c_gate gate; enum tda18271_ver id; - unsigned int count; unsigned int tm_rfcal; unsigned int cal_initialized:1; -- cgit v1.2.3 From dec3163121b0561dd389e791a282c2f638afd655 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:25:59 -0300 Subject: V4L/DVB (7137): tuner: return number of instances remaining after hybrid_tuner_release_state Assign the number of instances remaining as the return value of hybrid_tuner_release_state, in case there is any extra cleanup that the tuner driver needs to do after an instance has been destroyed. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-i2c.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index 8ec5b41d459f..c53c327a487c 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -155,13 +155,17 @@ __fail: \ __ret; \ }) -#define hybrid_tuner_release_state(state) do { \ +#define hybrid_tuner_release_state(state) \ +({ \ + int __ret; \ state->i2c_props.count--; \ + __ret = state->i2c_props.count; \ if (!state->i2c_props.count) { \ __tuner_info(state->i2c_props, "destroying instance\n");\ list_del(&state->hybrid_tuner_instance_list); \ kfree(state); \ } \ -} while (0) + __ret; \ +}) #endif /* __TUNER_I2C_H__ */ -- cgit v1.2.3 From 7521f23dbc78419cb79f196035b5727e2094c9b0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 2 Apr 2008 14:26:00 -0300 Subject: V4L/DVB: constify function pointer tables Signed-off-by: Jan Engelhardt Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvbdev.c | 2 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 18738faecbbc..ce5122e220f6 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -97,7 +97,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) } -static struct file_operations dvb_device_fops = +static const struct file_operations dvb_device_fops = { .owner = THIS_MODULE, .open = dvb_device_open, diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index ab39f9694e74..1b3b6c1589f7 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1005,7 +1005,7 @@ static int stc_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations stc_fops = { +static const struct file_operations stc_fops = { .owner = THIS_MODULE, .read = stc_read, .open = stc_open, -- cgit v1.2.3 From 73a83a4075a575a07ab6f22a9dad16518c555563 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:01 -0300 Subject: V4L/DVB (7170): soc_camera V4L2 driver for directly-connected SoC-based cameras This driver provides an interface between platform-specific camera busses and camera devices. It should be used if the camera is connected not over a "proper" bus like PCI or USB, but over a special bus, like, for example, the Quick Capture interface on PXA270 SoCs. Later it should also be used for i.MX31 SoCs from Freescale. It can handle multiple cameras and / or multiple busses, which can be used, e.g., in stereo-vision applications. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 9 + drivers/media/video/Makefile | 2 + drivers/media/video/soc_camera.c | 973 +++++++++++++++++++++++++++++++++++++++ include/media/soc_camera.h | 147 ++++++ 4 files changed, 1131 insertions(+) create mode 100644 drivers/media/video/soc_camera.c create mode 100644 include/media/soc_camera.h (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 1832966f53f3..5d3fbd969b6b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -836,4 +836,13 @@ config USB_STKWEBCAM endif # V4L_USB_DRIVERS +config SOC_CAMERA + tristate "SoC camera support" + depends on VIDEO_V4L2 + select VIDEOBUF_DMA_SG + help + SoC Camera is a common API to several cameras, not connecting + over a bus like PCI or USB. For example some i2c camera connected + directly to the data bus of an SoC. + endif # VIDEO_CAPTURE_DRIVERS diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 6f1ef09df1d6..cf5e990a47bf 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -136,5 +136,7 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ +obj-$(CONFIG_SOC_CAMERA) += soc_camera.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c new file mode 100644 index 000000000000..904e9dfc1a89 --- /dev/null +++ b/drivers/media/video/soc_camera.c @@ -0,0 +1,973 @@ +/* + * camera image capture (abstract) bus driver + * + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This driver provides an interface between platform-specific camera + * busses and camera devices. It should be used if the camera is + * connected not over a "proper" bus like PCI or USB, but over a + * special bus, like, for example, the Quick Capture interface on PXA270 + * SoCs. Later it should also be used for i.MX31 SoCs from Freescale. + * It can handle multiple cameras and / or multiple busses, which can + * be used, e.g., in stereo-vision applications. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static LIST_HEAD(hosts); +static LIST_HEAD(devices); +static DEFINE_MUTEX(list_lock); +static DEFINE_MUTEX(video_lock); + +const static struct soc_camera_data_format* +format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < icd->ops->num_formats; i++) + if (icd->ops->formats[i].fourcc == fourcc) + return icd->ops->formats + i; + return NULL; +} + +static int soc_camera_try_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + enum v4l2_field field; + const struct soc_camera_data_format *fmt; + int ret; + + WARN_ON(priv != file->private_data); + + fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!fmt) { + dev_dbg(&icd->dev, "invalid format 0x%08x\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc); + + field = f->fmt.pix.field; + + if (field == V4L2_FIELD_ANY) { + field = V4L2_FIELD_NONE; + } else if (V4L2_FIELD_NONE != field) { + dev_err(&icd->dev, "Field type invalid.\n"); + return -EINVAL; + } + + /* limit to host capabilities */ + ret = ici->try_fmt_cap(ici, f); + + /* limit to sensor capabilities */ + if (!ret) + ret = icd->ops->try_fmt_cap(icd, f); + + /* calculate missing fields */ + f->fmt.pix.field = field; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return ret; +} + +static int soc_camera_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index != 0) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_UNKNOWN; + strcpy(inp->name, "Camera"); + + return 0; +} + +static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i) +{ + *i = 0; + + return 0; +} + +static int soc_camera_s_input(struct file *file, void *priv, unsigned int i) +{ + if (i > 0) + return -EINVAL; + + return 0; +} + +static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) +{ + return 0; +} + +static int soc_camera_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + int ret; + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s: %d\n", __FUNCTION__, p->memory); + + ret = videobuf_reqbufs(&icf->vb_vidq, p); + if (ret < 0) + return ret; + + return ici->reqbufs(icf, p); + + return ret; +} + +static int soc_camera_querybuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_querybuf(&icf->vb_vidq, p); +} + +static int soc_camera_qbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_qbuf(&icf->vb_vidq, p); +} + +static int soc_camera_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); +} + +static int soc_camera_open(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct soc_camera_device *icd = container_of(vdev->dev, + struct soc_camera_device, dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct soc_camera_file *icf; + int ret; + + icf = vmalloc(sizeof(*icf)); + if (!icf) + return -ENOMEM; + + icf->icd = icd; + + if (!try_module_get(icd->ops->owner)) { + dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); + ret = -EINVAL; + goto emgd; + } + + if (!try_module_get(ici->owner)) { + dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); + ret = -EINVAL; + goto emgi; + } + + file->private_data = icf; + dev_dbg(&icd->dev, "camera device open\n"); + + /* We must pass NULL as dev pointer, then all pci_* dma operations + * transform to normal dma_* ones. Do we need an irqlock? */ + videobuf_queue_pci_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + ici->msize, icd); + + return 0; + +emgi: + module_put(icd->ops->owner); +emgd: + vfree(icf); + return ret; +} + +static int soc_camera_close(struct inode *inode, struct file *file) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct video_device *vdev = icd->vdev; + + module_put(icd->ops->owner); + module_put(ici->owner); + vfree(file->private_data); + + dev_dbg(vdev->dev, "camera device close\n"); + + return 0; +} + +static int soc_camera_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct video_device *vdev = icd->vdev; + int err = -EINVAL; + + dev_err(vdev->dev, "camera device read not implemented\n"); + + return err; +} + +static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int err; + + dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma); + + err = videobuf_mmap_mapper(&icf->vb_vidq, vma); + + dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, + err); + + return err; +} + +static unsigned int soc_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + if (list_empty(&icf->vb_vidq.stream)) { + dev_err(&icd->dev, "Trying to poll with no queued buffers!\n"); + return POLLERR; + } + + return ici->poll(file, pt); +} + + +static struct file_operations soc_camera_fops = { + .owner = THIS_MODULE, + .open = soc_camera_open, + .release = soc_camera_close, + .ioctl = video_ioctl2, + .read = soc_camera_read, + .mmap = soc_camera_mmap, + .poll = soc_camera_poll, + .llseek = no_llseek, +}; + + +static int soc_camera_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + struct v4l2_rect rect; + const static struct soc_camera_data_format *data_fmt; + + WARN_ON(priv != file->private_data); + + data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!data_fmt) + return -EINVAL; + + /* cached_datawidth may be further adjusted by the ici */ + icd->cached_datawidth = data_fmt->depth; + + ret = soc_camera_try_fmt_cap(file, icf, f); + if (ret < 0) + return ret; + + rect.left = icd->x_current; + rect.top = icd->y_current; + rect.width = f->fmt.pix.width; + rect.height = f->fmt.pix.height; + ret = ici->set_capture_format(icd, f->fmt.pix.pixelformat, &rect); + + if (!ret) { + icd->current_fmt = data_fmt; + icd->width = rect.width; + icd->height = rect.height; + icf->vb_vidq.field = f->fmt.pix.field; + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) + dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", + f->type); + + dev_dbg(&icd->dev, "set width: %d height: %d\n", + icd->width, icd->height); + } + + return ret; +} + +static int soc_camera_enum_fmt_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + const struct soc_camera_data_format *format; + + WARN_ON(priv != file->private_data); + + if (f->index >= icd->ops->num_formats) + return -EINVAL; + + format = &icd->ops->formats[f->index]; + + strlcpy(f->description, format->name, sizeof(f->description)); + f->pixelformat = format->fourcc; + return 0; +} + +static int soc_camera_g_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + f->fmt.pix.width = icd->width; + f->fmt.pix.height = icd->height; + f->fmt.pix.field = icf->vb_vidq.field; + f->fmt.pix.pixelformat = icd->current_fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * icd->current_fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", + icd->current_fmt->fourcc); + return 0; +} + +static int soc_camera_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + WARN_ON(priv != file->private_data); + + strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver)); + return ici->querycap(ici, cap); +} + +static int soc_camera_streamon(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + icd->ops->start_capture(icd); + + /* This calls buf_queue from host driver's videobuf_queue_ops */ + return videobuf_streamon(&icf->vb_vidq); +} + +static int soc_camera_streamoff(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* This calls buf_release from host driver's videobuf_queue_ops for all + * remaining buffers. When the last buffer is freed, stop capture */ + videobuf_streamoff(&icf->vb_vidq); + + icd->ops->stop_capture(icd); + + return 0; +} + +static int soc_camera_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int i; + + WARN_ON(priv != file->private_data); + + if (!qc->id) + return -EINVAL; + + for (i = 0; i < icd->ops->num_controls; i++) + if (qc->id == icd->ops->controls[i].id) { + memcpy(qc, &(icd->ops->controls[i]), + sizeof(*qc)); + return 0; + } + + return -EINVAL; +} + +static int soc_camera_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + switch (ctrl->id) { + case V4L2_CID_GAIN: + if (icd->gain == (unsigned short)~0) + return -EINVAL; + ctrl->value = icd->gain; + return 0; + case V4L2_CID_EXPOSURE: + if (icd->exposure == (unsigned short)~0) + return -EINVAL; + ctrl->value = icd->exposure; + return 0; + } + + if (icd->ops->get_control) + return icd->ops->get_control(icd, ctrl); + return -EINVAL; +} + +static int soc_camera_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + if (icd->ops->set_control) + return icd->ops->set_control(icd, ctrl); + return -EINVAL; +} + +static int soc_camera_cropcap(struct file *file, void *fh, + struct v4l2_cropcap *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->bounds.left = icd->x_min; + a->bounds.top = icd->y_min; + a->bounds.width = icd->width_max; + a->bounds.height = icd->height_max; + a->defrect.left = icd->x_min; + a->defrect.top = icd->y_min; + a->defrect.width = 640; + a->defrect.height = 480; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int soc_camera_g_crop(struct file *file, void *fh, + struct v4l2_crop *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->c.left = icd->x_current; + a->c.top = icd->y_current; + a->c.width = icd->width; + a->c.height = icd->height; + + return 0; +} + +static int soc_camera_s_crop(struct file *file, void *fh, + struct v4l2_crop *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + ret = ici->set_capture_format(icd, 0, &a->c); + if (!ret) { + icd->width = a->c.width; + icd->height = a->c.height; + icd->x_current = a->c.left; + icd->y_current = a->c.top; + } + + return ret; +} + +static int soc_camera_g_chip_ident(struct file *file, void *fh, + struct v4l2_chip_ident *id) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->get_chip_id) + return -EINVAL; + + return icd->ops->get_chip_id(icd, id); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int soc_camera_g_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->get_register) + return -EINVAL; + + return icd->ops->get_register(icd, reg); +} + +static int soc_camera_s_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->set_register) + return -EINVAL; + + return icd->ops->set_register(icd, reg); +} +#endif + +static int device_register_link(struct soc_camera_device *icd) +{ + int ret = device_register(&icd->dev); + + if (ret < 0) { + /* Prevent calling device_unregister() */ + icd->dev.parent = NULL; + dev_err(&icd->dev, "Cannot register device: %d\n", ret); + /* Even if probe() was unsuccessful for all registered drivers, + * device_register() returns 0, and we add the link, just to + * document this camera's control device */ + } else if (icd->control) + /* Have to sysfs_remove_link() before device_unregister()? */ + if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj, + "control")) + dev_warn(&icd->dev, + "Failed creating the control symlink\n"); + return ret; +} + +/* So far this function cannot fail */ +static void scan_add_host(struct soc_camera_host *ici) +{ + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_for_each_entry(icd, &devices, list) { + if (icd->iface == ici->nr) { + icd->dev.parent = &ici->dev; + device_register_link(icd); + } + } + + mutex_unlock(&list_lock); +} + +/* return: 0 if no match found or a match found and + * device_register() successful, error code otherwise */ +static int scan_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici; + int ret = 0; + + mutex_lock(&list_lock); + + list_add_tail(&icd->list, &devices); + + /* Watch out for class_for_each_device / class_find_device API by + * Dave Young */ + list_for_each_entry(ici, &hosts, list) { + if (icd->iface == ici->nr) { + ret = 1; + icd->dev.parent = &ici->dev; + break; + } + } + + mutex_unlock(&list_lock); + + if (ret) + ret = device_register_link(icd); + + return ret; +} + +static int soc_camera_probe(struct device *dev) +{ + struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + + if (!icd->probe) + return -ENODEV; + + ret = ici->add(icd); + if (ret < 0) + return ret; + + ret = icd->probe(icd); + if (ret < 0) + ici->remove(icd); + else { + const struct v4l2_queryctrl *qctrl; + + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); + icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = qctrl ? qctrl->default_value : + (unsigned short)~0; + } + + return ret; +} + +/* This is called on device_unregister, which only means we have to disconnect + * from the host, but not remove ourselves from the device list */ +static int soc_camera_remove(struct device *dev) +{ + struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + if (icd->remove) + icd->remove(icd); + + ici->remove(icd); + + return 0; +} + +static struct bus_type soc_camera_bus_type = { + .name = "soc-camera", + .probe = soc_camera_probe, + .remove = soc_camera_remove, +}; + +static struct device_driver ic_drv = { + .name = "camera", + .bus = &soc_camera_bus_type, + .owner = THIS_MODULE, +}; + +/* + * Image capture host - this is a host device, not a bus device, so, + * no bus reference, no probing. + */ +static struct class soc_camera_host_class = { + .owner = THIS_MODULE, + .name = "camera_host", +}; + +static void dummy_release(struct device *dev) +{ +} + +int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) +{ + int ret; + struct soc_camera_host *ix; + + if (!ici->vbq_ops || !ici->add || !ici->remove || !owner) + return -EINVAL; + + /* Number might be equal to the platform device ID */ + sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); + ici->dev.class = &soc_camera_host_class; + + mutex_lock(&list_lock); + list_for_each_entry(ix, &hosts, list) { + if (ix->nr == ici->nr) { + mutex_unlock(&list_lock); + return -EBUSY; + } + } + + list_add_tail(&ici->list, &hosts); + mutex_unlock(&list_lock); + + ici->owner = owner; + ici->dev.release = dummy_release; + + ret = device_register(&ici->dev); + + if (ret) + goto edevr; + + scan_add_host(ici); + + return 0; + +edevr: + mutex_lock(&list_lock); + list_del(&ici->list); + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(soc_camera_host_register); + +/* Unregister all clients! */ +void soc_camera_host_unregister(struct soc_camera_host *ici) +{ + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_del(&ici->list); + + list_for_each_entry(icd, &devices, list) { + if (icd->dev.parent == &ici->dev) { + device_unregister(&icd->dev); + /* Not before device_unregister(), .remove + * needs parent to call ici->remove() */ + icd->dev.parent = NULL; + memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); + } + } + + mutex_unlock(&list_lock); + + device_unregister(&ici->dev); +} +EXPORT_SYMBOL(soc_camera_host_unregister); + +/* Image capture device */ +int soc_camera_device_register(struct soc_camera_device *icd) +{ + struct soc_camera_device *ix; + int num = -1, i; + + if (!icd) + return -EINVAL; + + for (i = 0; i < 256 && num < 0; i++) { + num = i; + list_for_each_entry(ix, &devices, list) { + if (ix->iface == icd->iface && ix->devnum == i) { + num = -1; + break; + } + } + } + + if (num < 0) + /* ok, we have 256 cameras on this host... + * man, stay reasonable... */ + return -ENOMEM; + + icd->devnum = num; + icd->dev.bus = &soc_camera_bus_type; + snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id), + "%u-%u", icd->iface, icd->devnum); + + icd->dev.release = dummy_release; + + if (icd->ops->get_datawidth) + icd->cached_datawidth = icd->ops->get_datawidth(icd); + + return scan_add_device(icd); +} +EXPORT_SYMBOL(soc_camera_device_register); + +void soc_camera_device_unregister(struct soc_camera_device *icd) +{ + mutex_lock(&list_lock); + list_del(&icd->list); + + /* The bus->remove will be eventually called */ + if (icd->dev.parent) + device_unregister(&icd->dev); + mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(soc_camera_device_unregister); + +int soc_camera_video_start(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int err = -ENOMEM; + struct video_device *vdev; + + if (!icd->dev.parent) + return -ENODEV; + + vdev = video_device_alloc(); + if (!vdev) + goto evidallocd; + dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); + + strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); + /* Maybe better &ici->dev */ + vdev->dev = &icd->dev; + vdev->type = VID_TYPE_CAPTURE; + vdev->current_norm = V4L2_STD_UNKNOWN; + vdev->fops = &soc_camera_fops; + vdev->release = video_device_release; + vdev->minor = -1; + vdev->tvnorms = V4L2_STD_UNKNOWN, + vdev->vidioc_querycap = soc_camera_querycap; + vdev->vidioc_g_fmt_cap = soc_camera_g_fmt_cap; + vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap; + vdev->vidioc_s_fmt_cap = soc_camera_s_fmt_cap; + vdev->vidioc_enum_input = soc_camera_enum_input; + vdev->vidioc_g_input = soc_camera_g_input; + vdev->vidioc_s_input = soc_camera_s_input; + vdev->vidioc_s_std = soc_camera_s_std; + vdev->vidioc_reqbufs = soc_camera_reqbufs; + vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap; + vdev->vidioc_querybuf = soc_camera_querybuf; + vdev->vidioc_qbuf = soc_camera_qbuf; + vdev->vidioc_dqbuf = soc_camera_dqbuf; + vdev->vidioc_streamon = soc_camera_streamon; + vdev->vidioc_streamoff = soc_camera_streamoff; + vdev->vidioc_queryctrl = soc_camera_queryctrl; + vdev->vidioc_g_ctrl = soc_camera_g_ctrl; + vdev->vidioc_s_ctrl = soc_camera_s_ctrl; + vdev->vidioc_cropcap = soc_camera_cropcap; + vdev->vidioc_g_crop = soc_camera_g_crop; + vdev->vidioc_s_crop = soc_camera_s_crop; + vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident; +#ifdef CONFIG_VIDEO_ADV_DEBUG + vdev->vidioc_g_register = soc_camera_g_register; + vdev->vidioc_s_register = soc_camera_s_register; +#endif + + icd->current_fmt = &icd->ops->formats[0]; + + err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); + if (err < 0) { + dev_err(vdev->dev, "video_register_device failed\n"); + goto evidregd; + } + icd->vdev = vdev; + + return 0; + +evidregd: + video_device_release(vdev); +evidallocd: + return err; +} +EXPORT_SYMBOL(soc_camera_video_start); + +void soc_camera_video_stop(struct soc_camera_device *icd) +{ + struct video_device *vdev = icd->vdev; + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (!icd->dev.parent || !vdev) + return; + + mutex_lock(&video_lock); + video_unregister_device(vdev); + icd->vdev = NULL; + mutex_unlock(&video_lock); +} +EXPORT_SYMBOL(soc_camera_video_stop); + +static int __init soc_camera_init(void) +{ + int ret = bus_register(&soc_camera_bus_type); + if (ret) + return ret; + ret = driver_register(&ic_drv); + if (ret) + goto edrvr; + ret = class_register(&soc_camera_host_class); + if (ret) + goto eclr; + + return 0; + +eclr: + driver_unregister(&ic_drv); +edrvr: + bus_unregister(&soc_camera_bus_type); + return ret; +} + +static void __exit soc_camera_exit(void) +{ + class_unregister(&soc_camera_host_class); + driver_unregister(&ic_drv); + bus_unregister(&soc_camera_bus_type); +} + +module_init(soc_camera_init); +module_exit(soc_camera_exit); + +MODULE_DESCRIPTION("Image capture bus driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h new file mode 100644 index 000000000000..69aba7188e44 --- /dev/null +++ b/include/media/soc_camera.h @@ -0,0 +1,147 @@ +/* + * camera image capture (abstract) bus driver header + * + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef SOC_CAMERA_H +#define SOC_CAMERA_H + +#include +#include + +struct soc_camera_device { + struct list_head list; + struct device dev; + struct device *control; + unsigned short width; /* Current window */ + unsigned short height; /* sizes */ + unsigned short x_min; /* Camera capabilities */ + unsigned short y_min; + unsigned short x_current; /* Current window location */ + unsigned short y_current; + unsigned short width_min; + unsigned short width_max; + unsigned short height_min; + unsigned short height_max; + unsigned short y_skip_top; /* Lines to skip at the top */ + unsigned short gain; + unsigned short exposure; + unsigned char iface; /* Host number */ + unsigned char devnum; /* Device number per host */ + unsigned char cached_datawidth; /* See comment in .c */ + struct soc_camera_ops *ops; + struct video_device *vdev; + const struct soc_camera_data_format *current_fmt; + int (*probe)(struct soc_camera_device *icd); + void (*remove)(struct soc_camera_device *icd); + struct module *owner; +}; + +struct soc_camera_file { + struct soc_camera_device *icd; + struct videobuf_queue vb_vidq; +}; + +struct soc_camera_host { + struct list_head list; + struct device dev; + unsigned char nr; /* Host number */ + size_t msize; + struct videobuf_queue_ops *vbq_ops; + struct module *owner; + void *priv; + char *drv_name; + int (*add)(struct soc_camera_device *); + void (*remove)(struct soc_camera_device *); + int (*set_capture_format)(struct soc_camera_device *, __u32, + struct v4l2_rect *); + int (*try_fmt_cap)(struct soc_camera_host *, struct v4l2_format *); + int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); + int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); + unsigned int (*poll)(struct file *, poll_table *); +}; + +struct soc_camera_link { + /* Camera bus id, used to match a camera and a bus */ + int bus_id; + /* GPIO number to switch between 8 and 10 bit modes */ + unsigned int gpio; +}; + +static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) +{ + return container_of(dev, struct soc_camera_device, dev); +} + +static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) +{ + return container_of(dev, struct soc_camera_host, dev); +} + +extern int soc_camera_host_register(struct soc_camera_host *ici, + struct module *owner); +extern void soc_camera_host_unregister(struct soc_camera_host *ici); +extern int soc_camera_device_register(struct soc_camera_device *icd); +extern void soc_camera_device_unregister(struct soc_camera_device *icd); + +extern int soc_camera_video_start(struct soc_camera_device *icd); +extern void soc_camera_video_stop(struct soc_camera_device *icd); + +struct soc_camera_data_format { + char *name; + unsigned int depth; + __u32 fourcc; + enum v4l2_colorspace colorspace; +}; + +struct soc_camera_ops { + struct module *owner; + int (*init)(struct soc_camera_device *); + int (*release)(struct soc_camera_device *); + int (*start_capture)(struct soc_camera_device *); + int (*stop_capture)(struct soc_camera_device *); + int (*set_capture_format)(struct soc_camera_device *, __u32, + struct v4l2_rect *, unsigned int); + int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); + int (*get_chip_id)(struct soc_camera_device *, + struct v4l2_chip_ident *); +#ifdef CONFIG_VIDEO_ADV_DEBUG + int (*get_register)(struct soc_camera_device *, struct v4l2_register *); + int (*set_register)(struct soc_camera_device *, struct v4l2_register *); +#endif + const struct soc_camera_data_format *formats; + int num_formats; + int (*get_control)(struct soc_camera_device *, struct v4l2_control *); + int (*set_control)(struct soc_camera_device *, struct v4l2_control *); + const struct v4l2_queryctrl *controls; + int num_controls; + unsigned int(*get_datawidth)(struct soc_camera_device *icd); +}; + +static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( + struct soc_camera_ops *ops, int id) +{ + int i; + + for (i = 0; i < ops->num_controls; i++) + if (ops->controls[i].id == id) + return &ops->controls[i]; + + return NULL; +} + +#define IS_MASTER (1<<0) +#define IS_HSYNC_ACTIVE_HIGH (1<<1) +#define IS_VSYNC_ACTIVE_HIGH (1<<2) +#define IS_DATAWIDTH_8 (1<<3) +#define IS_DATAWIDTH_9 (1<<4) +#define IS_DATAWIDTH_10 (1<<5) +#define IS_PCLK_SAMPLE_RISING (1<<6) + +#endif -- cgit v1.2.3 From 5f1e5244ee6b9f139a262d5e7a930a41488afbbe Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:01 -0300 Subject: V4L/DVB (7172): V4L2 soc_camera driver for PXA27x processors This patch adds a driver for the Quick Capture Interface on the PXA270. It is based on the original driver from Intel, but has been re-worked multiple times since then, now for the first time it supports the V4L2 API. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- arch/arm/mach-pxa/devices.c | 32 ++ drivers/media/video/Kconfig | 7 + drivers/media/video/Makefile | 1 + drivers/media/video/pxa_camera.c | 937 ++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-pxa/camera.h | 48 ++ include/asm-arm/arch-pxa/pxa-regs.h | 166 +++++-- 6 files changed, 1155 insertions(+), 36 deletions(-) create mode 100644 drivers/media/video/pxa_camera.c create mode 100644 include/asm-arm/arch-pxa/camera.h (limited to 'drivers') diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index bfccb80ac8ef..3838aabdf338 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "devices.h" @@ -540,6 +541,37 @@ struct platform_device pxa27x_device_ssp3 = { .resource = pxa27x_resource_ssp3, .num_resources = ARRAY_SIZE(pxa27x_resource_ssp3), }; + +static struct resource pxa27x_resource_camera[] = { + [0] = { + .start = 0x50000000, + .end = 0x50000fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_CAMERA, + .end = IRQ_CAMERA, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32); + +static struct platform_device pxa27x_device_camera = { + .name = "pxa27x-camera", + .id = 0, /* This is used to put cameras on this interface */ + .dev = { + .dma_mask = &pxa27x_dma_mask_camera, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(pxa27x_resource_camera), + .resource = pxa27x_resource_camera, +}; + +void __init pxa_set_camera_info(struct pxacamera_platform_data *info) +{ + pxa_register_device(&pxa27x_device_camera, info); +} #endif /* CONFIG_PXA27x || CONFIG_PXA3xx */ #ifdef CONFIG_PXA3xx diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 5d3fbd969b6b..fb4bf089c68f 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -845,4 +845,11 @@ config SOC_CAMERA over a bus like PCI or USB. For example some i2c camera connected directly to the data bus of an SoC. +config VIDEO_PXA27x + tristate "PXA27x Quick Capture Interface driver" + depends on VIDEO_DEV && PXA27x + select SOC_CAMERA + ---help--- + This is a v4l2 driver for the PXA27x Quick Capture Interface + endif # VIDEO_CAPTURE_DRIVERS diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index cf5e990a47bf..874ed967f416 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -136,6 +136,7 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ +obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c new file mode 100644 index 000000000000..11aecad769cc --- /dev/null +++ b/drivers/media/video/pxa_camera.c @@ -0,0 +1,937 @@ +/* + * V4L2 Driver for PXA camera host + * + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) +#define PXA_CAM_DRV_NAME "pxa27x-camera" + +#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \ + CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \ + CICR0_EOFM | CICR0_FOM) + +static DEFINE_MUTEX(camera_lock); + +/* + * Structures + */ + +/* buffer for one video frame */ +struct pxa_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + const struct soc_camera_data_format *fmt; + + /* our descriptor list needed for the PXA DMA engine */ + dma_addr_t sg_dma; + struct pxa_dma_desc *sg_cpu; + size_t sg_size; + int inwork; +}; + +struct pxa_framebuffer_queue { + dma_addr_t sg_last_dma; + struct pxa_dma_desc *sg_last_cpu; +}; + +struct pxa_camera_dev { + struct device *dev; + /* PXA27x is only supposed to handle one camera on its Quick Capture + * interface. If anyone ever builds hardware to enable more than + * one camera, they will have to modify this driver too */ + struct soc_camera_device *icd; + struct clk *clk; + + unsigned int irq; + void __iomem *base; + unsigned int dma_chan_y; + + enum v4l2_buf_type type; + + struct pxacamera_platform_data *pdata; + struct resource *res; + unsigned long platform_flags; + unsigned long platform_mclk_10khz; + + struct list_head capture; + + spinlock_t lock; + + int dma_running; + + struct pxa_buffer *active; +}; + +static const char *pxa_cam_driver_description = "PXA_Camera"; + +static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ + +/* + * Videobuf operations + */ +static int +pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct soc_camera_device *icd = vq->priv_data; + + dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + + *size = icd->width * icd->height * ((icd->current_fmt->depth + 7) >> 3); + + if (0 == *count) + *count = 32; + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + + return 0; +} + +static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + + BUG_ON(in_interrupt()); + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + &buf->vb, buf->vb.baddr, buf->vb.bsize); + + /* This waits until this buffer is out of danger, i.e., until it is no + * longer in STATE_QUEUED or STATE_ACTIVE */ + videobuf_waiton(&buf->vb, 0, 0); + videobuf_dma_unmap(vq, dma); + videobuf_dma_free(dma); + + if (buf->sg_cpu) + dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu, + buf->sg_dma); + buf->sg_cpu = NULL; + + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int +pxa_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); + int i, ret; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + /* Added list head initialization on alloc */ + WARN_ON(!list_empty(&vb->queue)); + +#ifdef DEBUG + /* This can be useful if you want to see if we actually fill + * the buffer with something */ + memset((void *)vb->baddr, 0xaa, vb->bsize); +#endif + + BUG_ON(NULL == icd->current_fmt); + + /* I think, in buf_prepare you only have to protect global data, + * the actual buffer is yours */ + buf->inwork = 1; + + if (buf->fmt != icd->current_fmt || + vb->width != icd->width || + vb->height != icd->height || + vb->field != field) { + buf->fmt = icd->current_fmt; + vb->width = icd->width; + vb->height = icd->height; + vb->field = field; + vb->state = VIDEOBUF_NEEDS_INIT; + } + + vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); + if (0 != vb->baddr && vb->bsize < vb->size) { + ret = -EINVAL; + goto out; + } + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + unsigned int size = vb->size; + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + + ret = videobuf_iolock(vq, vb, NULL); + if (ret) + goto fail; + + if (buf->sg_cpu) + dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu, + buf->sg_dma); + + buf->sg_size = (dma->sglen + 1) * sizeof(struct pxa_dma_desc); + buf->sg_cpu = dma_alloc_coherent(pcdev->dev, buf->sg_size, + &buf->sg_dma, GFP_KERNEL); + if (!buf->sg_cpu) { + ret = -ENOMEM; + goto fail; + } + + dev_dbg(&icd->dev, "nents=%d size: %d sg=0x%p\n", + dma->sglen, size, dma->sglist); + for (i = 0; i < dma->sglen; i++) { + struct scatterlist *sg = dma->sglist; + unsigned int dma_len = sg_dma_len(&sg[i]), xfer_len; + + /* CIBR0 */ + buf->sg_cpu[i].dsadr = pcdev->res->start + 0x28; + buf->sg_cpu[i].dtadr = sg_dma_address(&sg[i]); + /* PXA270 Developer's Manual 27.4.4.1: + * round up to 8 bytes */ + xfer_len = (min(dma_len, size) + 7) & ~7; + if (xfer_len & 7) + dev_err(&icd->dev, "Unaligned buffer: " + "dma_len %u, size %u\n", dma_len, size); + buf->sg_cpu[i].dcmd = DCMD_FLOWSRC | DCMD_BURST8 | + DCMD_INCTRGADDR | xfer_len; + size -= dma_len; + buf->sg_cpu[i].ddadr = buf->sg_dma + (i + 1) * + sizeof(struct pxa_dma_desc); + } + buf->sg_cpu[dma->sglen - 1].ddadr = DDADR_STOP; + buf->sg_cpu[dma->sglen - 1].dcmd |= DCMD_ENDIRQEN; + + vb->state = VIDEOBUF_PREPARED; + } + + buf->inwork = 0; + + return 0; + +fail: + free_buffer(vq, buf); +out: + buf->inwork = 0; + return ret; +} + +static void +pxa_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); + struct pxa_buffer *active = pcdev->active; + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + int nents = dma->sglen; + unsigned long flags; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + spin_lock_irqsave(&pcdev->lock, flags); + + list_add_tail(&vb->queue, &pcdev->capture); + + vb->state = VIDEOBUF_ACTIVE; + + if (!pcdev->active) { + CIFR |= CIFR_RESET_F; + DDADR(pcdev->dma_chan_y) = buf->sg_dma; + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + pcdev->active = buf; + CICR0 |= CICR0_ENB; + } else { + struct videobuf_dmabuf *active_dma = + videobuf_to_dma(&active->vb); + /* Stop DMA engine */ + DCSR(pcdev->dma_chan_y) = 0; + + /* Add the descriptors we just initialized to the currently + * running chain + */ + active->sg_cpu[active_dma->sglen - 1].ddadr = buf->sg_dma; + + /* Setup a dummy descriptor with the DMA engines current + * state + */ + /* CIBR0 */ + buf->sg_cpu[nents].dsadr = pcdev->res->start + 0x28; + buf->sg_cpu[nents].dtadr = DTADR(pcdev->dma_chan_y); + buf->sg_cpu[nents].dcmd = DCMD(pcdev->dma_chan_y); + + if (DDADR(pcdev->dma_chan_y) == DDADR_STOP) { + /* The DMA engine is on the last descriptor, set the + * next descriptors address to the descriptors + * we just initialized + */ + buf->sg_cpu[nents].ddadr = buf->sg_dma; + } else { + buf->sg_cpu[nents].ddadr = DDADR(pcdev->dma_chan_y); + } + + /* The next descriptor is the dummy descriptor */ + DDADR(pcdev->dma_chan_y) = buf->sg_dma + nents * + sizeof(struct pxa_dma_desc); + +#ifdef DEBUG + if (CISR & CISR_IFO_0) { + dev_warn(pcdev->dev, "FIFO overrun\n"); + DDADR(pcdev->dma_chan_y) = pcdev->active->sg_dma; + + CICR0 &= ~CICR0_ENB; + CIFR |= CIFR_RESET_F; + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + CICR0 |= CICR0_ENB; + } else +#endif + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + } + + spin_unlock_irqrestore(&pcdev->lock, flags); + +} + +static void pxa_videobuf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); +#ifdef DEBUG + struct soc_camera_device *icd = vq->priv_data; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + switch (vb->state) { + case VIDEOBUF_ACTIVE: + dev_dbg(&icd->dev, "%s (active)\n", __FUNCTION__); + break; + case VIDEOBUF_QUEUED: + dev_dbg(&icd->dev, "%s (queued)\n", __FUNCTION__); + break; + case VIDEOBUF_PREPARED: + dev_dbg(&icd->dev, "%s (prepared)\n", __FUNCTION__); + break; + default: + dev_dbg(&icd->dev, "%s (unknown)\n", __FUNCTION__); + break; + } +#endif + + free_buffer(vq, buf); +} + +static void pxa_camera_dma_irq_y(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + struct pxa_buffer *buf; + unsigned long flags; + unsigned int status; + struct videobuf_buffer *vb; + + spin_lock_irqsave(&pcdev->lock, flags); + + status = DCSR(pcdev->dma_chan_y); + if (status & DCSR_BUSERR) { + dev_err(pcdev->dev, "%s: Bus Error\n", __FUNCTION__); + DCSR(pcdev->dma_chan_y) |= DCSR_BUSERR; + goto out; + } + + if (!(status & DCSR_ENDINTR)) { + dev_err(pcdev->dev, "%s: unknown dma interrupt source. " + "status: 0x%08x\n", __FUNCTION__, status); + goto out; + } + + DCSR(pcdev->dma_chan_y) |= DCSR_ENDINTR; + + if (!pcdev->active) { + dev_err(pcdev->dev, "%s: no active buf\n", __FUNCTION__); + goto out; + } + + vb = &pcdev->active->vb; + buf = container_of(vb, struct pxa_buffer, vb); + WARN_ON(buf->inwork || list_empty(&vb->queue)); + dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + /* _init is used to debug races, see comment in pxa_is_reqbufs() */ + list_del_init(&vb->queue); + vb->state = VIDEOBUF_DONE; + do_gettimeofday(&vb->ts); + vb->field_count++; + wake_up(&vb->done); + + if (list_empty(&pcdev->capture)) { + pcdev->active = NULL; + DCSR(pcdev->dma_chan_y) = 0; + CICR0 &= ~CICR0_ENB; + goto out; + } + + pcdev->active = list_entry(pcdev->capture.next, struct pxa_buffer, + vb.queue); + +out: + spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static struct videobuf_queue_ops pxa_video_ops = { + .buf_setup = pxa_videobuf_setup, + .buf_prepare = pxa_videobuf_prepare, + .buf_queue = pxa_videobuf_queue, + .buf_release = pxa_videobuf_release, +}; + +static int mclk_get_divisor(struct pxa_camera_dev *pcdev) +{ + unsigned int mclk_10khz = pcdev->platform_mclk_10khz; + unsigned long div; + unsigned long lcdclk; + + lcdclk = clk_get_rate(pcdev->clk) / 10000; + + /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here + * they get a nice Oops */ + div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1; + + dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, " + "divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div); + + return div; +} + +static void pxa_is_activate(struct pxa_camera_dev *pcdev) +{ + struct pxacamera_platform_data *pdata = pcdev->pdata; + u32 cicr4 = 0; + + dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n", + pcdev, pdata); + + if (pdata && pdata->init) { + dev_dbg(pcdev->dev, "%s: Init gpios\n", __FUNCTION__); + pdata->init(pcdev->dev); + } + + if (pdata && pdata->power) { + dev_dbg(pcdev->dev, "%s: Power on camera\n", __FUNCTION__); + pdata->power(pcdev->dev, 1); + } + + if (pdata && pdata->reset) { + dev_dbg(pcdev->dev, "%s: Releasing camera reset\n", + __FUNCTION__); + pdata->reset(pcdev->dev, 1); + } + + CICR0 = 0x3FF; /* disable all interrupts */ + + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + cicr4 |= CICR4_PCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) + cicr4 |= CICR4_MCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_PCP) + cicr4 |= CICR4_PCP; + if (pcdev->platform_flags & PXA_CAMERA_HSP) + cicr4 |= CICR4_HSP; + if (pcdev->platform_flags & PXA_CAMERA_VSP) + cicr4 |= CICR4_VSP; + + CICR4 = mclk_get_divisor(pcdev) | cicr4; + + clk_enable(pcdev->clk); +} + +static void pxa_is_deactivate(struct pxa_camera_dev *pcdev) +{ + struct pxacamera_platform_data *board = pcdev->pdata; + + clk_disable(pcdev->clk); + + if (board && board->reset) { + dev_dbg(pcdev->dev, "%s: Asserting camera reset\n", + __FUNCTION__); + board->reset(pcdev->dev, 0); + } + + if (board && board->power) { + dev_dbg(pcdev->dev, "%s: Power off camera\n", __FUNCTION__); + board->power(pcdev->dev, 0); + } +} + +static irqreturn_t pxa_camera_irq(int irq, void *data) +{ + struct pxa_camera_dev *pcdev = data; + unsigned int status = CISR; + + dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status); + + CISR = status; + + return IRQ_HANDLED; +} + +/* The following two functions absolutely depend on the fact, that + * there can be only one camera on PXA quick capture interface */ +static int pxa_is_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + int ret; + + mutex_lock(&camera_lock); + + if (pcdev->icd) { + ret = -EBUSY; + goto ebusy; + } + + dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", + icd->devnum); + + pxa_is_activate(pcdev); + ret = icd->ops->init(icd); + + if (!ret) + pcdev->icd = icd; + +ebusy: + mutex_unlock(&camera_lock); + + return ret; +} + +static void pxa_is_remove_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + + BUG_ON(icd != pcdev->icd); + + dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n", + icd->devnum); + + /* disable capture, disable interrupts */ + CICR0 = 0x3ff; + /* Stop DMA engine */ + DCSR(pcdev->dma_chan_y) = 0; + + icd->ops->release(icd); + + pxa_is_deactivate(pcdev); + + pcdev->icd = NULL; +} + +static int pxa_is_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned int datawidth = 0, dw, bpp; + u32 cicr0, cicr4 = 0; + int ret; + + /* If requested data width is supported by the platform, use it */ + switch (icd->cached_datawidth) { + case 10: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) + datawidth = IS_DATAWIDTH_10; + break; + case 9: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) + datawidth = IS_DATAWIDTH_9; + break; + case 8: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) + datawidth = IS_DATAWIDTH_8; + } + if (!datawidth) + return -EINVAL; + + ret = icd->ops->set_capture_format(icd, pixfmt, rect, + datawidth | + (pcdev->platform_flags & PXA_CAMERA_MASTER ? + IS_MASTER : 0) | + (pcdev->platform_flags & PXA_CAMERA_HSP ? + 0 : IS_HSYNC_ACTIVE_HIGH) | + (pcdev->platform_flags & PXA_CAMERA_VSP ? + 0 : IS_VSYNC_ACTIVE_HIGH) | + (pcdev->platform_flags & PXA_CAMERA_PCP ? + 0 : IS_PCLK_SAMPLE_RISING)); + if (ret < 0) + return ret; + + /* Datawidth is now guaranteed to be equal to one of the three values. + * We fix bit-per-pixel equal to data-width... */ + switch (datawidth) { + case IS_DATAWIDTH_10: + icd->cached_datawidth = 10; + dw = 4; + bpp = 0x40; + break; + case IS_DATAWIDTH_9: + icd->cached_datawidth = 9; + dw = 3; + bpp = 0x20; + break; + default: + /* Actually it can only be 8 now, + * default is just to silence compiler warnings */ + case IS_DATAWIDTH_8: + icd->cached_datawidth = 8; + dw = 2; + bpp = 0; + } + + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + cicr4 |= CICR4_PCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) + cicr4 |= CICR4_MCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_PCP) + cicr4 |= CICR4_PCP; + if (pcdev->platform_flags & PXA_CAMERA_HSP) + cicr4 |= CICR4_HSP; + if (pcdev->platform_flags & PXA_CAMERA_VSP) + cicr4 |= CICR4_VSP; + + cicr0 = CICR0; + if (cicr0 & CICR0_ENB) + CICR0 = cicr0 & ~CICR0_ENB; + CICR1 = CICR1_PPL_VAL(rect->width - 1) | bpp | dw; + CICR2 = 0; + CICR3 = CICR3_LPF_VAL(rect->height - 1) | + CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); + CICR4 = mclk_get_divisor(pcdev) | cicr4; + + /* CIF interrupts are not used, only DMA */ + CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ? + 0 : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) | + CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB); + + return 0; +} + +static int pxa_is_try_fmt_cap(struct soc_camera_host *ici, + struct v4l2_format *f) +{ + /* limit to pxa hardware capabilities */ + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.height > 2048) + f->fmt.pix.height = 2048; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 2048) + f->fmt.pix.width = 2048; + f->fmt.pix.width &= ~0x01; + + return 0; +} + +static int pxa_is_reqbufs(struct soc_camera_file *icf, + struct v4l2_requestbuffers *p) +{ + int i; + + /* This is for locking debugging only. I removed spinlocks and now I + * check whether .prepare is ever called on a linked buffer, or whether + * a dma IRQ can occur for an in-work or unlinked buffer. Until now + * it hadn't triggered */ + for (i = 0; i < p->count; i++) { + struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i], + struct pxa_buffer, vb); + buf->inwork = 0; + INIT_LIST_HEAD(&buf->vb.queue); + } + + return 0; +} + +static unsigned int pxa_is_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + struct pxa_buffer *buf; + + buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer, + vb.stream); + + poll_wait(file, &buf->vb.done, pt); + + if (buf->vb.state == VIDEOBUF_DONE || + buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + + return 0; +} + +static int pxa_is_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the firendly caller:-> */ + strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); + cap->version = PXA_CAM_VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + + return 0; +} + +/* Should beallocated dynamically too, but we have only one. */ +static struct soc_camera_host pxa_soc_camera_host = { + .drv_name = PXA_CAM_DRV_NAME, + .vbq_ops = &pxa_video_ops, + .add = pxa_is_add_device, + .remove = pxa_is_remove_device, + .msize = sizeof(struct pxa_buffer), + .set_capture_format = pxa_is_set_capture_format, + .try_fmt_cap = pxa_is_try_fmt_cap, + .reqbufs = pxa_is_reqbufs, + .poll = pxa_is_poll, + .querycap = pxa_is_querycap, +}; + +static int pxa_camera_probe(struct platform_device *pdev) +{ + struct pxa_camera_dev *pcdev; + struct resource *res; + void __iomem *base; + unsigned int irq; + int err = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!res || !irq) { + err = -ENODEV; + goto exit; + } + + pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); + if (!pcdev) { + dev_err(&pdev->dev, "%s: Could not allocate pcdev\n", + __FUNCTION__); + err = -ENOMEM; + goto exit; + } + + pcdev->clk = clk_get(&pdev->dev, "CAMCLK"); + if (IS_ERR(pcdev->clk)) { + err = PTR_ERR(pcdev->clk); + goto exit_kfree; + } + + dev_set_drvdata(&pdev->dev, pcdev); + pcdev->res = res; + + pcdev->pdata = pdev->dev.platform_data; + pcdev->platform_flags = pcdev->pdata->flags; + if (!pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | + PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10)) { + /* Platform hasn't set available data widths. This is bad. + * Warn and use a default. */ + dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " + "data widths, using default 10 bit\n"); + pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; + } + pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz; + if (!pcdev->platform_mclk_10khz) { + dev_warn(&pdev->dev, + "mclk_10khz == 0! Please, fix your platform data. " + "Using default 20MHz\n"); + pcdev->platform_mclk_10khz = 2000; + } + + INIT_LIST_HEAD(&pcdev->capture); + spin_lock_init(&pcdev->lock); + + /* + * Request the regions. + */ + if (!request_mem_region(res->start, res->end - res->start + 1, + PXA_CAM_DRV_NAME)) { + err = -EBUSY; + goto exit_clk; + } + + base = ioremap(res->start, res->end - res->start + 1); + if (!base) { + err = -ENOMEM; + goto exit_release; + } + pcdev->irq = irq; + pcdev->base = base; + pcdev->dev = &pdev->dev; + + /* request dma */ + pcdev->dma_chan_y = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, + pxa_camera_dma_irq_y, pcdev); + if (pcdev->dma_chan_y < 0) { + dev_err(pcdev->dev, "Can't request DMA for Y\n"); + err = -ENOMEM; + goto exit_iounmap; + } + dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan_y); + + DRCMR68 = pcdev->dma_chan_y | DRCMR_MAPVLD; + + /* request irq */ + err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME, + pcdev); + if (err) { + dev_err(pcdev->dev, "Camera interrupt register failed \n"); + goto exit_free_dma; + } + + pxa_soc_camera_host.priv = pcdev; + pxa_soc_camera_host.dev.parent = &pdev->dev; + pxa_soc_camera_host.nr = pdev->id; + err = soc_camera_host_register(&pxa_soc_camera_host, THIS_MODULE); + if (err) + goto exit_free_irq; + + return 0; + +exit_free_irq: + free_irq(pcdev->irq, pcdev); +exit_free_dma: + pxa_free_dma(pcdev->dma_chan_y); +exit_iounmap: + iounmap(base); +exit_release: + release_mem_region(res->start, res->end - res->start + 1); +exit_clk: + clk_put(pcdev->clk); +exit_kfree: + kfree(pcdev); +exit: + return err; +} + +static int __devexit pxa_camera_remove(struct platform_device *pdev) +{ + struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + struct resource *res; + + clk_put(pcdev->clk); + + pxa_free_dma(pcdev->dma_chan_y); + free_irq(pcdev->irq, pcdev); + + soc_camera_host_unregister(&pxa_soc_camera_host); + + iounmap(pcdev->base); + + res = pcdev->res; + release_mem_region(res->start, res->end - res->start + 1); + + kfree(pcdev); + + dev_info(&pdev->dev, "%s: PXA Camera driver unloaded\n", __FUNCTION__); + + return 0; +} + +/* + * Suspend the Camera Module. + */ +static int pxa_camera_suspend(struct platform_device *pdev, pm_message_t level) +{ + struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + + dev_info(&pdev->dev, "camera suspend\n"); + disable_irq(pcdev->irq); + return 0; +} + +/* + * Resume the Camera Module. + */ +static int pxa_camera_resume(struct platform_device *pdev) +{ + struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + + dev_info(&pdev->dev, "camera resume\n"); + enable_irq(pcdev->irq); + +/* if (pcdev) { */ /* FIXME: dev in use? */ +/* DRCMR68 = pcdev->dma_chan_y | DRCMR_MAPVLD; */ +/* DRCMR69 = pcdev->dma_chan_cb | DRCMR_MAPVLD; */ +/* DRCMR70 = pcdev->dma_chan_cr | DRCMR_MAPVLD; */ +/* } */ + + return 0; +} + + +static struct platform_driver pxa_camera_driver = { + .driver = { + .name = PXA_CAM_DRV_NAME, + }, + .probe = pxa_camera_probe, + .remove = __exit_p(pxa_camera_remove), + .suspend = pxa_camera_suspend, + .resume = pxa_camera_resume, +}; + + +static int __devinit pxa_camera_init(void) +{ + return platform_driver_register(&pxa_camera_driver); +} + +static void __exit pxa_camera_exit(void) +{ + return platform_driver_unregister(&pxa_camera_driver); +} + +module_init(pxa_camera_init); +module_exit(pxa_camera_exit); + +MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); diff --git a/include/asm-arm/arch-pxa/camera.h b/include/asm-arm/arch-pxa/camera.h new file mode 100644 index 000000000000..39516ced8b1f --- /dev/null +++ b/include/asm-arm/arch-pxa/camera.h @@ -0,0 +1,48 @@ +/* + camera.h - PXA camera driver header file + + Copyright (C) 2003, Intel Corporation + Copyright (C) 2008, Guennadi Liakhovetski + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ASM_ARCH_CAMERA_H_ +#define __ASM_ARCH_CAMERA_H_ + +#define PXA_CAMERA_MASTER 1 +#define PXA_CAMERA_DATAWIDTH_4 2 +#define PXA_CAMERA_DATAWIDTH_5 4 +#define PXA_CAMERA_DATAWIDTH_8 8 +#define PXA_CAMERA_DATAWIDTH_9 0x10 +#define PXA_CAMERA_DATAWIDTH_10 0x20 +#define PXA_CAMERA_PCLK_EN 0x40 +#define PXA_CAMERA_MCLK_EN 0x80 +#define PXA_CAMERA_PCP 0x100 +#define PXA_CAMERA_HSP 0x200 +#define PXA_CAMERA_VSP 0x400 + +struct pxacamera_platform_data { + int (*init)(struct device *); + int (*power)(struct device *, int); + int (*reset)(struct device *, int); + + unsigned long flags; + unsigned long mclk_10khz; +}; + +extern void pxa_set_camera_info(struct pxacamera_platform_data *); + +#endif /* __ASM_ARCH_CAMERA_H_ */ diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 2357a73340d4..e9ef1073bc29 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -46,13 +46,13 @@ #define PCMCIA1AttrSp PCMCIAAttrSp /* PCMCIA 1 Attribute Space [byte] */ #define PCMCIA1MemSp PCMCIAMemSp /* PCMCIA 1 Memory Space [byte] */ -#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \ - (0x20000000 + (Nb)*PCMCIASp) +#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \ + (0x20000000 + (Nb)*PCMCIASp) #define _PCMCIAIO(Nb) _PCMCIA (Nb) /* PCMCIA I/O [0..1] */ -#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \ - (_PCMCIA (Nb) + 2*PCMCIAPrtSp) -#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \ - (_PCMCIA (Nb) + 3*PCMCIAPrtSp) +#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \ + (_PCMCIA (Nb) + 2*PCMCIAPrtSp) +#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \ + (_PCMCIA (Nb) + 3*PCMCIAPrtSp) #define _PCMCIA0 _PCMCIA (0) /* PCMCIA 0 */ #define _PCMCIA0IO _PCMCIAIO (0) /* PCMCIA 0 I/O */ @@ -1248,19 +1248,26 @@ #define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */ #define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */ #define GPIO12_32KHz 12 /* 32 kHz out */ +#define GPIO12_CIF_DD7 12 /* Capture Interface D7 (PXA27x) */ #define GPIO13_MBGNT 13 /* memory controller grant */ #define GPIO14_MBREQ 14 /* alternate bus master request */ #define GPIO15_nCS_1 15 /* chip select 1 */ #define GPIO16_PWM0 16 /* PWM0 output */ #define GPIO17_PWM1 17 /* PWM1 output */ +#define GPIO17_CIF_DD6 17 /* Capture Interface D6 (PXA27x) */ #define GPIO18_RDY 18 /* Ext. Bus Ready */ #define GPIO19_DREQ1 19 /* External DMA Request */ #define GPIO20_DREQ0 20 /* External DMA Request */ #define GPIO23_SCLK 23 /* SSP clock */ +#define GPIO23_CIF_MCLK 23 /* Capture Interface MCLK (PXA27x) */ #define GPIO24_SFRM 24 /* SSP Frame */ +#define GPIO24_CIF_FV 24 /* Capture Interface FV (PXA27x) */ #define GPIO25_STXD 25 /* SSP transmit */ +#define GPIO25_CIF_LV 25 /* Capture Interface LV (PXA27x) */ #define GPIO26_SRXD 26 /* SSP receive */ +#define GPIO26_CIF_PCLK 26 /* Capture Interface PCLK (PXA27x) */ #define GPIO27_SEXTCLK 27 /* SSP ext_clk */ +#define GPIO27_CIF_DD0 27 /* Capture Interface D0 (PXA27x) */ #define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */ #define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */ #define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */ @@ -1281,28 +1288,40 @@ #define GPIO41_FFRTS 41 /* FFUART request to send */ #define GPIO42_BTRXD 42 /* BTUART receive data */ #define GPIO42_HWRXD 42 /* HWUART receive data */ +#define GPIO42_CIF_MCLK 42 /* Capture interface MCLK (PXA27x) */ #define GPIO43_BTTXD 43 /* BTUART transmit data */ #define GPIO43_HWTXD 43 /* HWUART transmit data */ +#define GPIO43_CIF_FV 43 /* Capture interface FV (PXA27x) */ #define GPIO44_BTCTS 44 /* BTUART clear to send */ #define GPIO44_HWCTS 44 /* HWUART clear to send */ +#define GPIO44_CIF_LV 44 /* Capture interface LV (PXA27x) */ #define GPIO45_BTRTS 45 /* BTUART request to send */ #define GPIO45_HWRTS 45 /* HWUART request to send */ #define GPIO45_AC97_SYSCLK 45 /* AC97 System Clock */ +#define GPIO45_CIF_PCLK 45 /* Capture interface PCLK (PXA27x) */ #define GPIO46_ICPRXD 46 /* ICP receive data */ #define GPIO46_STRXD 46 /* STD_UART receive data */ #define GPIO47_ICPTXD 47 /* ICP transmit data */ #define GPIO47_STTXD 47 /* STD_UART transmit data */ +#define GPIO47_CIF_DD0 47 /* Capture interface D0 (PXA27x) */ #define GPIO48_nPOE 48 /* Output Enable for Card Space */ +#define GPIO48_CIF_DD5 48 /* Capture interface D5 (PXA27x) */ #define GPIO49_nPWE 49 /* Write Enable for Card Space */ #define GPIO50_nPIOR 50 /* I/O Read for Card Space */ +#define GPIO50_CIF_DD3 50 /* Capture interface D3 (PXA27x) */ #define GPIO51_nPIOW 51 /* I/O Write for Card Space */ +#define GPIO51_CIF_DD2 51 /* Capture interface D2 (PXA27x) */ #define GPIO52_nPCE_1 52 /* Card Enable for Card Space */ +#define GPIO52_CIF_DD4 52 /* Capture interface D4 (PXA27x) */ #define GPIO53_nPCE_2 53 /* Card Enable for Card Space */ #define GPIO53_MMCCLK 53 /* MMC Clock */ +#define GPIO53_CIF_MCLK 53 /* Capture interface MCLK (PXA27x) */ #define GPIO54_MMCCLK 54 /* MMC Clock */ #define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */ #define GPIO54_nPCE_2 54 /* Card Enable for Card Space (PXA27x) */ +#define GPIO54_CIF_PCLK 54 /* Capture interface PCLK (PXA27x) */ #define GPIO55_nPREG 55 /* Card Address bit 26 */ +#define GPIO55_CIF_DD1 55 /* Capture interface D1 (PXA27x) */ #define GPIO56_nPWAIT 56 /* Wait signal for Card Space */ #define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */ #define GPIO58_LDD_0 58 /* LCD data pin 0 */ @@ -1337,11 +1356,28 @@ #define GPIO79_nCS_3 79 /* chip select 3 */ #define GPIO80_nCS_4 80 /* chip select 4 */ #define GPIO81_NSCLK 81 /* NSSP clock */ +#define GPIO81_CIF_DD0 81 /* Capture Interface D0 (PXA27x) */ #define GPIO82_NSFRM 82 /* NSSP Frame */ +#define GPIO82_CIF_DD5 82 /* Capture Interface D5 (PXA27x) */ #define GPIO83_NSTXD 83 /* NSSP transmit */ +#define GPIO83_CIF_DD4 83 /* Capture Interface D4 (PXA27x) */ #define GPIO84_NSRXD 84 /* NSSP receive */ +#define GPIO84_CIF_FV 84 /* Capture Interface FV (PXA27x) */ #define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */ +#define GPIO85_CIF_LV 85 /* Capture Interface LV (PXA27x) */ +#define GPIO90_CIF_DD4 90 /* Capture Interface DD4 (PXA27x) */ +#define GPIO91_CIF_DD5 91 /* Capture Interface DD5 (PXA27x) */ #define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */ +#define GPIO93_CIF_DD6 93 /* Capture interface D6 (PXA27x) */ +#define GPIO94_CIF_DD5 94 /* Capture interface D5 (PXA27x) */ +#define GPIO95_CIF_DD4 95 /* Capture interface D4 (PXA27x) */ +#define GPIO98_CIF_DD0 98 /* Capture interface D0 (PXA27x) */ +#define GPIO103_CIF_DD3 103 /* Capture interface D3 (PXA27x) */ +#define GPIO104_CIF_DD2 104 /* Capture interface D2 (PXA27x) */ +#define GPIO105_CIF_DD1 105 /* Capture interface D1 (PXA27x) */ +#define GPIO106_CIF_DD9 106 /* Capture interface D9 (PXA27x) */ +#define GPIO107_CIF_DD8 107 /* Capture interface D8 (PXA27x) */ +#define GPIO108_CIF_DD7 108 /* Capture interface D7 (PXA27x) */ #define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */ #define GPIO109_MMCDAT1 109 /* MMC DAT1 (PXA27x) */ #define GPIO110_MMCDAT2 110 /* MMC DAT2 (PXA27x) */ @@ -1351,6 +1387,9 @@ #define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */ #define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */ #define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */ +#define GPIO114_CIF_DD1 114 /* Capture interface D1 (PXA27x) */ +#define GPIO115_CIF_DD3 115 /* Capture interface D3 (PXA27x) */ +#define GPIO116_CIF_DD2 116 /* Capture interface D2 (PXA27x) */ /* GPIO alternate function mode & direction */ @@ -1376,19 +1415,26 @@ #define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT) #define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT) #define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT) +#define GPIO12_CIF_DD7_MD (12 | GPIO_ALT_FN_2_IN) #define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT) #define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN) #define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT) #define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT) #define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT) +#define GPIO17_CIF_DD6_MD (17 | GPIO_ALT_FN_2_IN) #define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN) #define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN) #define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN) +#define GPIO23_CIF_MCLK_MD (23 | GPIO_ALT_FN_1_OUT) #define GPIO23_SCLK_MD (23 | GPIO_ALT_FN_2_OUT) +#define GPIO24_CIF_FV_MD (24 | GPIO_ALT_FN_1_OUT) #define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT) +#define GPIO25_CIF_LV_MD (25 | GPIO_ALT_FN_1_OUT) #define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT) #define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN) +#define GPIO26_CIF_PCLK_MD (26 | GPIO_ALT_FN_2_IN) #define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN) +#define GPIO27_CIF_DD0_MD (27 | GPIO_ALT_FN_3_IN) #define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN) #define GPIO28_BITCLK_IN_I2S_MD (28 | GPIO_ALT_FN_2_IN) #define GPIO28_BITCLK_OUT_I2S_MD (28 | GPIO_ALT_FN_1_OUT) @@ -1413,34 +1459,46 @@ #define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT) #define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT) #define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN) +#define GPIO42_CIF_MCLK_MD (42 | GPIO_ALT_FN_3_OUT) #define GPIO42_HWRXD_MD (42 | GPIO_ALT_FN_3_IN) #define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT) +#define GPIO43_CIF_FV_MD (43 | GPIO_ALT_FN_3_OUT) #define GPIO43_HWTXD_MD (43 | GPIO_ALT_FN_3_OUT) #define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN) #define GPIO44_HWCTS_MD (44 | GPIO_ALT_FN_3_IN) +#define GPIO44_CIF_LV_MD (44 | GPIO_ALT_FN_3_OUT) #define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT) #define GPIO45_HWRTS_MD (45 | GPIO_ALT_FN_3_OUT) #define GPIO45_SYSCLK_AC97_MD (45 | GPIO_ALT_FN_1_OUT) +#define GPIO45_CIF_PCLK_MD (45 | GPIO_ALT_FN_3_IN) #define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN) #define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN) #define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT) #define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT) +#define GPIO47_CIF_DD0_MD (47 | GPIO_ALT_FN_1_IN) #define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT) +#define GPIO48_CIF_DD5_MD (48 | GPIO_ALT_FN_1_IN) #define GPIO48_HWTXD_MD (48 | GPIO_ALT_FN_1_OUT) #define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT) #define GPIO49_HWRXD_MD (49 | GPIO_ALT_FN_1_IN) #define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT) #define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT) +#define GPIO50_CIF_DD3_MD (50 | GPIO_ALT_FN_1_IN) #define GPIO50_HWCTS_MD (50 | GPIO_ALT_FN_1_IN) #define GPIO51_HWRTS_MD (51 | GPIO_ALT_FN_1_OUT) #define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT) +#define GPIO51_CIF_DD2_MD (51 | GPIO_ALT_FN_1_IN) #define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT) +#define GPIO52_CIF_DD4_MD (52 | GPIO_ALT_FN_1_IN) #define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT) #define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT) +#define GPIO53_CIF_MCLK_MD (53 | GPIO_ALT_FN_2_OUT) #define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT) #define GPIO54_nPCE_2_MD (54 | GPIO_ALT_FN_2_OUT) #define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT) +#define GPIO54_CIF_PCLK_MD (54 | GPIO_ALT_FN_3_IN) #define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT) +#define GPIO55_CIF_DD1_MD (55 | GPIO_ALT_FN_1_IN) #define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN) #define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN) #define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT) @@ -1477,16 +1535,33 @@ #define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT) #define GPIO81_NSSP_CLK_OUT (81 | GPIO_ALT_FN_1_OUT) #define GPIO81_NSSP_CLK_IN (81 | GPIO_ALT_FN_1_IN) +#define GPIO81_CIF_DD0_MD (81 | GPIO_ALT_FN_2_IN) #define GPIO82_NSSP_FRM_OUT (82 | GPIO_ALT_FN_1_OUT) #define GPIO82_NSSP_FRM_IN (82 | GPIO_ALT_FN_1_IN) +#define GPIO82_CIF_DD5_MD (82 | GPIO_ALT_FN_3_IN) #define GPIO83_NSSP_TX (83 | GPIO_ALT_FN_1_OUT) #define GPIO83_NSSP_RX (83 | GPIO_ALT_FN_2_IN) +#define GPIO83_CIF_DD4_MD (83 | GPIO_ALT_FN_3_IN) #define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT) #define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN) +#define GPIO84_CIF_FV_MD (84 | GPIO_ALT_FN_3_OUT) #define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT) +#define GPIO85_CIF_LV_MD (85 | GPIO_ALT_FN_3_OUT) +#define GPIO90_CIF_DD4_MD (90 | GPIO_ALT_FN_3_IN) +#define GPIO91_CIF_DD5_MD (91 | GPIO_ALT_FN_3_IN) #define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT) +#define GPIO93_CIF_DD6_MD (93 | GPIO_ALT_FN_2_IN) +#define GPIO94_CIF_DD5_MD (94 | GPIO_ALT_FN_2_IN) +#define GPIO95_CIF_DD4_MD (95 | GPIO_ALT_FN_2_IN) +#define GPIO98_CIF_DD0_MD (98 | GPIO_ALT_FN_2_IN) #define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT) +#define GPIO103_CIF_DD3_MD (103 | GPIO_ALT_FN_1_IN) #define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT) +#define GPIO104_CIF_DD2_MD (104 | GPIO_ALT_FN_1_IN) +#define GPIO105_CIF_DD1_MD (105 | GPIO_ALT_FN_1_IN) +#define GPIO106_CIF_DD9_MD (106 | GPIO_ALT_FN_1_IN) +#define GPIO107_CIF_DD8_MD (107 | GPIO_ALT_FN_1_IN) +#define GPIO108_CIF_DD7_MD (108 | GPIO_ALT_FN_1_IN) #define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT) @@ -1715,7 +1790,7 @@ #define LCCR0_Color (LCCR0_CMS*0) /* Color display */ #define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */ #define LCCR0_SDS (1 << 2) /* Single/Dual Panel Display */ - /* Select */ + /* Select */ #define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */ #define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */ @@ -1727,11 +1802,11 @@ #define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */ #define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */ #define LCCR0_DPD (1 << 9) /* Double Pixel Data (monochrome */ - /* display mode) */ + /* display mode) */ #define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome */ - /* display */ + /* display */ #define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome */ - /* display */ + /* display */ #define LCCR0_DIS (1 << 10) /* LCD Disable */ #define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */ #define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */ @@ -1746,47 +1821,47 @@ #define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */ #define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \ - (((Pixel) - 1) << FShft (LCCR1_PPL)) + (((Pixel) - 1) << FShft (LCCR1_PPL)) #define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */ #define LCCR1_HorSnchWdth(Tpix) /* Horizontal Synchronization */ \ - /* pulse Width [1..64 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_HSW)) + /* pulse Width [1..64 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_HSW)) #define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait */ - /* count - 1 [Tpix] */ + /* count - 1 [Tpix] */ #define LCCR1_EndLnDel(Tpix) /* End-of-Line Delay */ \ - /* [1..256 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_ELW)) + /* [1..256 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_ELW)) #define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */ - /* Wait count - 1 [Tpix] */ + /* Wait count - 1 [Tpix] */ #define LCCR1_BegLnDel(Tpix) /* Beginning-of-Line Delay */ \ - /* [1..256 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_BLW)) + /* [1..256 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_BLW)) #define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */ #define LCCR2_DisHght(Line) /* Display Height [1..1024 lines] */ \ - (((Line) - 1) << FShft (LCCR2_LPP)) + (((Line) - 1) << FShft (LCCR2_LPP)) #define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse */ - /* Width - 1 [Tln] (L_FCLK) */ + /* Width - 1 [Tln] (L_FCLK) */ #define LCCR2_VrtSnchWdth(Tln) /* Vertical Synchronization pulse */ \ - /* Width [1..64 Tln] */ \ - (((Tln) - 1) << FShft (LCCR2_VSW)) + /* Width [1..64 Tln] */ \ + (((Tln) - 1) << FShft (LCCR2_VSW)) #define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */ - /* count [Tln] */ + /* count [Tln] */ #define LCCR2_EndFrmDel(Tln) /* End-of-Frame Delay */ \ - /* [0..255 Tln] */ \ - ((Tln) << FShft (LCCR2_EFW)) + /* [0..255 Tln] */ \ + ((Tln) << FShft (LCCR2_EFW)) #define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */ - /* Wait count [Tln] */ + /* Wait count [Tln] */ #define LCCR2_BegFrmDel(Tln) /* Beginning-of-Frame Delay */ \ - /* [0..255 Tln] */ \ - ((Tln) << FShft (LCCR2_BFW)) + /* [0..255 Tln] */ \ + ((Tln) << FShft (LCCR2_BFW)) #if 0 #define LCCR3_PCD (0xff) /* Pixel clock divisor */ @@ -1803,7 +1878,7 @@ #define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */ #define LCCR3_OEP (1 << 23) /* Output Enable Polarity (L_BIAS, */ - /* active display mode) */ + /* active display mode) */ #define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */ #define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */ @@ -1816,25 +1891,25 @@ #define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */ #define LCCR3_PixClkDiv(Div) /* Pixel Clock Divisor */ \ - (((Div) << FShft (LCCR3_PCD))) + (((Div) << FShft (LCCR3_PCD))) #define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */ #define LCCR3_Bpp(Bpp) /* Bit Per Pixel */ \ - (((Bpp) << FShft (LCCR3_BPP))) + (((Bpp) << FShft (LCCR3_BPP))) #define LCCR3_ACB Fld (8, 8) /* AC Bias */ #define LCCR3_Acb(Acb) /* BAC Bias */ \ - (((Acb) << FShft (LCCR3_ACB))) + (((Acb) << FShft (LCCR3_ACB))) #define LCCR3_HorSnchH (LCCR3_HSP*0) /* Horizontal Synchronization */ - /* pulse active High */ + /* pulse active High */ #define LCCR3_HorSnchL (LCCR3_HSP*1) /* Horizontal Synchronization */ #define LCCR3_VrtSnchH (LCCR3_VSP*0) /* Vertical Synchronization pulse */ - /* active High */ + /* active High */ #define LCCR3_VrtSnchL (LCCR3_VSP*1) /* Vertical Synchronization pulse */ - /* active Low */ + /* active Low */ #define LCSR_LDD (1 << 0) /* LCD Disable Done */ #define LCSR_SOF (1 << 1) /* Start of frame */ @@ -1941,6 +2016,11 @@ #define CICR0_ENB (1 << 28) /* Camera interface enable */ #define CICR0_DIS (1 << 27) /* Camera interface disable */ #define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ +#define CICR0_SIM_MP (0 << 24) +#define CICR0_SIM_SP (1 << 24) +#define CICR0_SIM_MS (2 << 24) +#define CICR0_SIM_EP (3 << 24) +#define CICR0_SIM_ES (4 << 24) #define CICR0_TOM (1 << 9) /* Time-out mask */ #define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ #define CICR0_FEM (1 << 7) /* FIFO-empty mask */ @@ -1991,6 +2071,20 @@ #define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ #define CICR4_DIV (0xff << 0) /* Clock divisor mask */ +#define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */ +#define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */ + +#define CICR2_BLW_VAL(x) (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */ +#define CICR2_ELW_VAL(x) (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */ +#define CICR2_HSW_VAL(x) (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */ +#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */ +#define CICR2_FSW_VAL(x) (((x) << 0) & CICR2_FSW) /* Frame stabilization wait count */ + +#define CICR3_BFW_VAL(x) (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count */ +#define CICR3_EFW_VAL(x) (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */ +#define CICR3_VSW_VAL(x) (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */ +#define CICR3_LPF_VAL(x) (((x) << 0) & CICR3_LPF) /* Lines per frame */ + #define CISR_FTO (1 << 15) /* FIFO time-out */ #define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ #define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ -- cgit v1.2.3 From f696edca119729826b819d108be57ac0c300225c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:03 -0300 Subject: V4L/DVB (7173): Add support for the MT9M001 camera This driver supports Micron MT9M001 monochrome and colour cameras. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 15 + drivers/media/video/Makefile | 1 + drivers/media/video/mt9m001.c | 694 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 710 insertions(+) create mode 100644 drivers/media/video/mt9m001.c (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index fb4bf089c68f..393bbf92b100 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -845,6 +845,21 @@ config SOC_CAMERA over a bus like PCI or USB. For example some i2c camera connected directly to the data bus of an SoC. +config SOC_CAMERA_MT9M001 + tristate "mt9m001 support" + depends on SOC_CAMERA && GENERIC_GPIO + select GPIO_PCA953X if MT9M001_PCA9536_SWITCH + help + This driver supports MT9M001 cameras from Micron, monochrome + and colour models. + +config MT9M001_PCA9536_SWITCH + bool "pca9536 datawidth switch for mt9m001" + depends on SOC_CAMERA_MT9M001 + help + Select this if your MT9M001 camera uses a PCA9536 I2C GPIO + extender to switch between 8 and 10 bit datawidth modes + config VIDEO_PXA27x tristate "PXA27x Quick Capture Interface driver" depends on VIDEO_DEV && PXA27x diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 874ed967f416..9321f68e52a7 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -138,6 +138,7 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885/ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o +obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c new file mode 100644 index 000000000000..3c5867c378d3 --- /dev/null +++ b/drivers/media/video/mt9m001.c @@ -0,0 +1,694 @@ +/* + * Driver for MT9M001 CMOS Image Sensor from Micron + * + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* mt9m001 i2c address 0x5d + * The platform has to define i2c_board_info + * and call i2c_register_board_info() */ + +/* mt9m001 selected register addresses */ +#define MT9M001_CHIP_VERSION 0x00 +#define MT9M001_ROW_START 0x01 +#define MT9M001_COLUMN_START 0x02 +#define MT9M001_WINDOW_HEIGHT 0x03 +#define MT9M001_WINDOW_WIDTH 0x04 +#define MT9M001_HORIZONTAL_BLANKING 0x05 +#define MT9M001_VERTICAL_BLANKING 0x06 +#define MT9M001_OUTPUT_CONTROL 0x07 +#define MT9M001_SHUTTER_WIDTH 0x09 +#define MT9M001_FRAME_RESTART 0x0b +#define MT9M001_SHUTTER_DELAY 0x0c +#define MT9M001_RESET 0x0d +#define MT9M001_READ_OPTIONS1 0x1e +#define MT9M001_READ_OPTIONS2 0x20 +#define MT9M001_GLOBAL_GAIN 0x35 +#define MT9M001_CHIP_ENABLE 0xF1 + +static const struct soc_camera_data_format mt9m001_colour_formats[] = { + { + .name = "RGB Bayer (sRGB)", + .depth = 16, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + } +}; + +static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { + { + .name = "Monochrome 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_Y16, + }, { + .name = "Monochrome 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_GREY, + }, +}; + +struct mt9m001 { + struct i2c_client *client; + struct soc_camera_device icd; + int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + int switch_gpio; + unsigned char autoexposure; + unsigned char datawidth; +}; + +static int reg_read(struct soc_camera_device *icd, const u8 reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = mt9m001->client; + s32 data = i2c_smbus_read_word_data(client, reg); + return data < 0 ? data : swab16(data); +} + +static int reg_write(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data)); +} + +static int reg_set(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret | data); +} + +static int reg_clear(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret & ~data); +} + +static int mt9m001_init(struct soc_camera_device *icd) +{ + int ret; + + /* Disable chip, synchronous option update */ + dev_dbg(icd->vdev->dev, "%s\n", __FUNCTION__); + + ret = reg_write(icd, MT9M001_RESET, 1); + if (ret >= 0) + ret = reg_write(icd, MT9M001_RESET, 0); + if (ret >= 0) + ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + + return ret >= 0 ? 0 : -EIO; +} + +static int mt9m001_release(struct soc_camera_device *icd) +{ + /* Disable the chip */ + reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + return 0; +} + +static int mt9m001_start_capture(struct soc_camera_device *icd) +{ + /* Switch to master "normal" mode */ + if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0) + return -EIO; + return 0; +} + +static int mt9m001_stop_capture(struct soc_camera_device *icd) +{ + /* Stop sensor readout */ + if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0) + return -EIO; + return 0; +} + +static int bus_switch_request(struct mt9m001 *mt9m001, + struct soc_camera_link *icl) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + int ret; + unsigned int gpio = icl->gpio; + + if (gpio != NO_GPIO) { + /* We have a data bus switch. */ + ret = gpio_request(gpio, "mt9m001"); + if (ret < 0) { + dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n", + gpio); + return ret; + } + + ret = gpio_direction_output(gpio, 0); + if (ret < 0) { + dev_err(&mt9m001->client->dev, + "Cannot set GPIO %u to output\n", gpio); + gpio_free(gpio); + return ret; + } + } + + mt9m001->switch_gpio = gpio; +#else + mt9m001->switch_gpio = NO_GPIO; +#endif + return 0; +} + +static void bus_switch_release(struct mt9m001 *mt9m001) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + if (mt9m001->switch_gpio != NO_GPIO) + gpio_free(mt9m001->switch_gpio); +#endif +} + +static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + if (mt9m001->switch_gpio == NO_GPIO) + return -ENODEV; + + gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit); + return 0; +#else + return -ENODEV; +#endif +} + +static int mt9m001_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | + IS_DATAWIDTH_8); + int ret; + const u16 hblank = 9, vblank = 25; + + /* MT9M001 has all capture_format parameters fixed */ + if (!(flags & IS_MASTER) || + !(flags & IS_PCLK_SAMPLE_RISING) || + !(flags & IS_HSYNC_ACTIVE_HIGH) || + !(flags & IS_VSYNC_ACTIVE_HIGH)) + return -EINVAL; + + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; + + if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || + (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || + (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { + /* data width switch requested */ + if (mt9m001->switch_gpio == NO_GPIO) + return -EINVAL; + + /* Well, we actually only can do 10 or 8 bits... */ + if (width_flag == IS_DATAWIDTH_9) + return -EINVAL; + ret = bus_switch_act(mt9m001, + width_flag == IS_DATAWIDTH_8); + if (ret < 0) + return ret; + + mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; + } + + /* Blanking and start values - default... */ + ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); + if (ret >= 0) + ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); + + /* The caller provides a supported format, as verified per + * call to icd->try_fmt_cap() */ + if (ret >= 0) + ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); + if (ret >= 0) + ret = reg_write(icd, MT9M001_ROW_START, rect->top); + if (ret >= 0) + ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); + if (ret >= 0) + ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, + rect->height + icd->y_skip_top - 1); + if (ret >= 0 && mt9m001->autoexposure) { + ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + vblank); + if (ret >= 0) { + const struct v4l2_queryctrl *qctrl = + soc_camera_find_qctrl(icd->ops, + V4L2_CID_EXPOSURE); + icd->exposure = (524 + (rect->height + icd->y_skip_top + + vblank - 1) * + (qctrl->maximum - qctrl->minimum)) / + 1048 + qctrl->minimum; + } + } + + return ret < 0 ? ret : 0; +} + +static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + if (f->fmt.pix.height < 32 + icd->y_skip_top) + f->fmt.pix.height = 32 + icd->y_skip_top; + if (f->fmt.pix.height > 1024 + icd->y_skip_top) + f->fmt.pix.height = 1024 + icd->y_skip_top; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 1280) + f->fmt.pix.width = 1280; + f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */ + + return 0; +} + +static int mt9m001_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match_chip != mt9m001->client->addr) + return -ENODEV; + + id->ident = mt9m001->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9m001_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9m001->client->addr) + return -ENODEV; + + reg->val = reg_read(icd, reg->reg); + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int mt9m001_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9m001->client->addr) + return -ENODEV; + + if (reg_write(icd, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + return mt9m001->datawidth; +} + +const struct v4l2_queryctrl mt9m001_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 64, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 1, + .maximum = 255, + .step = 1, + .default_value = 255, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + } +}; + +static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); +static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); + +static struct soc_camera_ops mt9m001_ops = { + .owner = THIS_MODULE, + .init = mt9m001_init, + .release = mt9m001_release, + .start_capture = mt9m001_start_capture, + .stop_capture = mt9m001_stop_capture, + .set_capture_format = mt9m001_set_capture_format, + .try_fmt_cap = mt9m001_try_fmt_cap, + .formats = NULL, /* Filled in later depending on the */ + .num_formats = 0, /* camera type and data widths */ + .get_datawidth = mt9m001_get_datawidth, + .controls = mt9m001_controls, + .num_controls = ARRAY_SIZE(mt9m001_controls), + .get_control = mt9m001_get_control, + .set_control = mt9m001_set_control, + .get_chip_id = mt9m001_get_chip_id, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = mt9m001_get_register, + .set_register = mt9m001_set_register, +#endif +}; + +static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + data = reg_read(icd, MT9M001_READ_OPTIONS2); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x8000); + break; + case V4L2_CID_EXPOSURE_AUTO: + ctrl->value = mt9m001->autoexposure; + break; + } + return 0; +} + +static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + const struct v4l2_queryctrl *qctrl; + int data; + + qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id); + + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (ctrl->value) + data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000); + else + data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000); + if (data < 0) + return -EIO; + break; + case V4L2_CID_GAIN: + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + /* See Datasheet Table 7, Gain settings. */ + if (ctrl->value <= qctrl->default_value) { + /* Pack it into 0..1 step 0.125, register values 0..8 */ + unsigned long range = qctrl->default_value - qctrl->minimum; + data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; + + dev_dbg(&icd->dev, "Setting gain %d\n", data); + data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + if (data < 0) + return -EIO; + } else { + /* Pack it into 1.125..15 variable step, register values 9..67 */ + /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ + unsigned long range = qctrl->maximum - qctrl->default_value - 1; + unsigned long gain = ((ctrl->value - qctrl->default_value - 1) * + 111 + range / 2) / range + 9; + + if (gain <= 32) + data = gain; + else if (gain <= 64) + data = ((gain - 32) * 16 + 16) / 32 + 80; + else + data = ((gain - 64) * 7 + 28) / 56 + 96; + + dev_dbg(&icd->dev, "Setting gain from %d to %d\n", + reg_read(icd, MT9M001_GLOBAL_GAIN), data); + data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + if (data < 0) + return -EIO; + } + + /* Success */ + icd->gain = ctrl->value; + break; + case V4L2_CID_EXPOSURE: + /* mt9m001 has maximum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 + + range / 2) / range + 1; + + dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n", + reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter); + if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0) + return -EIO; + icd->exposure = ctrl->value; + mt9m001->autoexposure = 0; + } + break; + case V4L2_CID_EXPOSURE_AUTO: + if (ctrl->value) { + const u16 vblank = 25; + if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height + + icd->y_skip_top + vblank) < 0) + return -EIO; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) * + (qctrl->maximum - qctrl->minimum)) / + 1048 + qctrl->minimum; + mt9m001->autoexposure = 1; + } else + mt9m001->autoexposure = 0; + break; + } + return 0; +} + +/* Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one */ +static int mt9m001_video_probe(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + s32 data; + int ret; + + /* We must have a parent by now. And it cannot be a wrong one. + * So this entire test is completely redundant. */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* Enable the chip */ + data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1); + dev_dbg(&icd->dev, "write: %d\n", data); + + /* Read out the chip version register */ + data = reg_read(icd, MT9M001_CHIP_VERSION); + + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ + switch (data) { + case 0x8411: + case 0x8421: + mt9m001->model = V4L2_IDENT_MT9M001C12ST; + mt9m001_ops.formats = mt9m001_colour_formats; + mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_colour_formats); + break; + case 0x8431: + mt9m001->model = V4L2_IDENT_MT9M001C12STM; + mt9m001_ops.formats = mt9m001_monochrome_formats; + if (mt9m001->client->dev.platform_data) + mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); + else + mt9m001_ops.num_formats = 1; + break; + default: + ret = -ENODEV; + dev_err(&icd->dev, + "No MT9M001 chip detected, register read %x\n", data); + goto ei2c; + } + + dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, + data == 0x8431 ? "C12STM" : "C12ST"); + + /* Now that we know the model, we can start video */ + ret = soc_camera_video_start(icd); + if (ret) + goto eisis; + + return 0; + +eisis: +ei2c: + return ret; +} + +static void mt9m001_video_remove(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, + mt9m001->icd.dev.parent, mt9m001->icd.vdev); + soc_camera_video_stop(&mt9m001->icd); +} + +static int mt9m001_probe(struct i2c_client *client) +{ + struct mt9m001 *mt9m001; + struct soc_camera_device *icd; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl = client->dev.platform_data; + int ret; + + if (!icl) { + dev_err(&client->dev, "MT9M001 driver needs platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL); + if (!mt9m001) + return -ENOMEM; + + mt9m001->client = client; + i2c_set_clientdata(client, mt9m001); + + /* Second stage probe - when a capture adapter is there */ + icd = &mt9m001->icd; + icd->probe = mt9m001_video_probe; + icd->remove = mt9m001_video_remove; + icd->ops = &mt9m001_ops; + icd->control = &client->dev; + icd->x_min = 20; + icd->y_min = 12; + icd->x_current = 20; + icd->y_current = 12; + icd->width_min = 48; + icd->width_max = 1280; + icd->height_min = 32; + icd->height_max = 1024; + icd->y_skip_top = 1; + icd->iface = icl->bus_id; + /* Default datawidth - this is the only width this camera (normally) + * supports. It is only with extra logic that it can support + * other widths. Therefore it seems to be a sensible default. */ + mt9m001->datawidth = 10; + /* Simulated autoexposure. If enabled, we calculate shutter width + * ourselves in the driver based on vertical blanking and frame width */ + mt9m001->autoexposure = 1; + + ret = bus_switch_request(mt9m001, icl); + if (ret) + goto eswinit; + + ret = soc_camera_device_register(icd); + if (ret) + goto eisdr; + + return 0; + +eisdr: + bus_switch_release(mt9m001); +eswinit: + kfree(mt9m001); + return ret; +} + +static int mt9m001_remove(struct i2c_client *client) +{ + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + + soc_camera_device_unregister(&mt9m001->icd); + bus_switch_release(mt9m001); + kfree(mt9m001); + + return 0; +} + +static struct i2c_driver mt9m001_i2c_driver = { + .driver = { + .name = "mt9m001", + }, + .probe = mt9m001_probe, + .remove = mt9m001_remove, +}; + +static int __init mt9m001_mod_init(void) +{ + return i2c_add_driver(&mt9m001_i2c_driver); +} + +static void __exit mt9m001_mod_exit(void) +{ + i2c_del_driver(&mt9m001_i2c_driver); +} + +module_init(mt9m001_mod_init); +module_exit(mt9m001_mod_exit); + +MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 5e56094eb87c7f9a59d42ac5ebb8d31150ceb9d2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:03 -0300 Subject: V4L/DVB (7174): Add support for the MT9V022 camera This driver supports Micron MT9V022 colour camera. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 14 + drivers/media/video/Makefile | 1 + drivers/media/video/mt9v022.c | 804 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 819 insertions(+) create mode 100644 drivers/media/video/mt9v022.c (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 393bbf92b100..21f250b8cbb0 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -860,6 +860,20 @@ config MT9M001_PCA9536_SWITCH Select this if your MT9M001 camera uses a PCA9536 I2C GPIO extender to switch between 8 and 10 bit datawidth modes +config SOC_CAMERA_MT9V022 + tristate "mt9v022 support" + depends on SOC_CAMERA && GENERIC_GPIO + select GPIO_PCA953X if MT9V022_PCA9536_SWITCH + help + This driver supports MT9V022 cameras from Micron + +config MT9V022_PCA9536_SWITCH + bool "pca9536 datawidth switch for mt9v022" + depends on SOC_CAMERA_MT9V022 + help + Select this if your MT9V022 camera uses a PCA9536 I2C GPIO + extender to switch between 8 and 10 bit datawidth modes + config VIDEO_PXA27x tristate "PXA27x Quick Capture Interface driver" depends on VIDEO_DEV && PXA27x diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 9321f68e52a7..77cfaff76420 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -139,6 +139,7 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885/ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o +obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c new file mode 100644 index 000000000000..9b406e41902a --- /dev/null +++ b/drivers/media/video/mt9v022.c @@ -0,0 +1,804 @@ +/* + * Driver for MT9V022 CMOS Image Sensor from Micron + * + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c + * The platform has to define i2c_board_info + * and call i2c_register_board_info() */ + +static char *sensor_type; +module_param(sensor_type, charp, S_IRUGO); +MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"\n"); + +/* mt9v022 selected register addresses */ +#define MT9V022_CHIP_VERSION 0x00 +#define MT9V022_COLUMN_START 0x01 +#define MT9V022_ROW_START 0x02 +#define MT9V022_WINDOW_HEIGHT 0x03 +#define MT9V022_WINDOW_WIDTH 0x04 +#define MT9V022_HORIZONTAL_BLANKING 0x05 +#define MT9V022_VERTICAL_BLANKING 0x06 +#define MT9V022_CHIP_CONTROL 0x07 +#define MT9V022_SHUTTER_WIDTH1 0x08 +#define MT9V022_SHUTTER_WIDTH2 0x09 +#define MT9V022_SHUTTER_WIDTH_CTRL 0x0a +#define MT9V022_TOTAL_SHUTTER_WIDTH 0x0b +#define MT9V022_RESET 0x0c +#define MT9V022_READ_MODE 0x0d +#define MT9V022_MONITOR_MODE 0x0e +#define MT9V022_PIXEL_OPERATION_MODE 0x0f +#define MT9V022_LED_OUT_CONTROL 0x1b +#define MT9V022_ADC_MODE_CONTROL 0x1c +#define MT9V022_ANALOG_GAIN 0x34 +#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 +#define MT9V022_PIXCLK_FV_LV 0x74 +#define MT9V022_DIGITAL_TEST_PATTERN 0x7f +#define MT9V022_AEC_AGC_ENABLE 0xAF +#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH 0xBD + +/* Progressive scan, master, defaults */ +#define MT9V022_CHIP_CONTROL_DEFAULT 0x188 + +static const struct soc_camera_data_format mt9v022_formats[] = { + { + .name = "RGB Bayer (sRGB)", + .depth = 8, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "RGB Bayer (sRGB)", + .depth = 10, + .fourcc = V4L2_PIX_FMT_SBGGR16, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "Monochrome 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_Y16, + }, { + .name = "Monochrome 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_GREY, + }, +}; + +struct mt9v022 { + struct i2c_client *client; + struct soc_camera_device icd; + int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + int switch_gpio; + u16 chip_control; + unsigned char datawidth; +}; + +static int reg_read(struct soc_camera_device *icd, const u8 reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = mt9v022->client; + s32 data = i2c_smbus_read_word_data(client, reg); + return data < 0 ? data : swab16(data); +} + +static int reg_write(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data)); +} + +static int reg_set(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret | data); +} + +static int reg_clear(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret & ~data); +} + +static int mt9v022_init(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + int ret; + + /* Almost the default mode: master, parallel, simultaneous, and an + * undocumented bit 0x200, which is present in table 7, but not in 8, + * plus snapshot mode to disable scan for now */ + mt9v022->chip_control |= 0x10; + ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + if (ret >= 0) + reg_write(icd, MT9V022_READ_MODE, 0x300); + + /* All defaults */ + if (ret >= 0) + /* AEC, AGC on */ + ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); + if (ret >= 0) + ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); + if (ret >= 0) + /* default - auto */ + ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); + if (ret >= 0) + ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); + + return ret >= 0 ? 0 : -EIO; +} + +static int mt9v022_release(struct soc_camera_device *icd) +{ + /* Nothing? */ + return 0; +} + +static int mt9v022_start_capture(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + /* Switch to master "normal" mode */ + mt9v022->chip_control &= ~0x10; + if (reg_write(icd, MT9V022_CHIP_CONTROL, + mt9v022->chip_control) < 0) + return -EIO; + return 0; +} + +static int mt9v022_stop_capture(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + /* Switch to snapshot mode */ + mt9v022->chip_control |= 0x10; + if (reg_write(icd, MT9V022_CHIP_CONTROL, + mt9v022->chip_control) < 0) + return -EIO; + return 0; +} + +static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + int ret; + unsigned int gpio = icl->gpio; + + if (gpio != NO_GPIO) { + /* We have a data bus switch. */ + ret = gpio_request(gpio, "mt9v022"); + if (ret < 0) { + dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio); + return ret; + } + + ret = gpio_direction_output(gpio, 0); + if (ret < 0) { + dev_err(&mt9v022->client->dev, + "Cannot set GPIO %u to output\n", gpio); + gpio_free(gpio); + return ret; + } + } + + mt9v022->switch_gpio = gpio; +#else + mt9v022->switch_gpio = NO_GPIO; +#endif + return 0; +} + +static void bus_switch_release(struct mt9v022 *mt9v022) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + if (mt9v022->switch_gpio != NO_GPIO) + gpio_free(mt9v022->switch_gpio); +#endif +} + +static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + if (mt9v022->switch_gpio == NO_GPIO) + return -ENODEV; + + gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit); + return 0; +#else + return -ENODEV; +#endif +} + +static int mt9v022_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | + IS_DATAWIDTH_8); + u16 pixclk = 0; + int ret; + + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; + + /* The caller provides a supported format, as verified per call to + * icd->try_fmt_cap(), datawidth is from our supported format list */ + switch (pixfmt) { + case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_Y16: + if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) + return -EINVAL; + break; + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SBGGR16: + if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) + return -EINVAL; + break; + case 0: + /* No format change, only geometry */ + break; + default: + return -EINVAL; + } + + /* Like in example app. Contradicts the datasheet though */ + ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (ret >= 0) { + if (ret & 1) /* Autoexposure */ + ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + 43); + else + ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + 43); + } + /* Setup frame format: defaults apart from width and height */ + if (ret >= 0) + ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); + if (ret >= 0) + ret = reg_write(icd, MT9V022_ROW_START, rect->top); + if (ret >= 0) + /* Default 94, Phytec driver says: + * "width + horizontal blank >= 660" */ + ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, + rect->width > 660 - 43 ? 43 : + 660 - rect->width); + if (ret >= 0) + ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); + if (ret >= 0) + ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); + if (ret >= 0) + ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, + rect->height + icd->y_skip_top); + + if (ret < 0) + return ret; + + dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); + + if ((mt9v022->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || + (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || + (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { + /* data width switch requested */ + if (mt9v022->switch_gpio == NO_GPIO) + return -EINVAL; + + /* Well, we actually only can do 10 or 8 bits... */ + if (width_flag == IS_DATAWIDTH_9) + return -EINVAL; + + ret = bus_switch_act(mt9v022, + width_flag == IS_DATAWIDTH_8); + if (ret < 0) + return ret; + + mt9v022->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; + } + + if (flags & IS_PCLK_SAMPLE_RISING) + pixclk |= 0x10; + + if (!(flags & IS_HSYNC_ACTIVE_HIGH)) + pixclk |= 0x1; + + if (!(flags & IS_VSYNC_ACTIVE_HIGH)) + pixclk |= 0x2; + + ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); + if (ret < 0) + return ret; + + if (!(flags & IS_MASTER)) + mt9v022->chip_control &= ~0x8; + + ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + if (ret < 0) + return ret; + + dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", + pixclk, mt9v022->chip_control); + + return 0; +} + +static int mt9v022_try_fmt_cap(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + if (f->fmt.pix.height < 32 + icd->y_skip_top) + f->fmt.pix.height = 32 + icd->y_skip_top; + if (f->fmt.pix.height > 480 + icd->y_skip_top) + f->fmt.pix.height = 480 + icd->y_skip_top; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 752) + f->fmt.pix.width = 752; + f->fmt.pix.width &= ~0x03; /* ? */ + + return 0; +} + +static int mt9v022_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match_chip != mt9v022->client->addr) + return -ENODEV; + + id->ident = mt9v022->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9v022_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9v022->client->addr) + return -ENODEV; + + reg->val = reg_read(icd, reg->reg); + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int mt9v022_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9v022->client->addr) + return -ENODEV; + + if (reg_write(icd, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static unsigned int mt9v022_get_datawidth(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + return mt9v022->datawidth; +} + +const struct v4l2_queryctrl mt9v022_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Analog Gain", + .minimum = 64, + .maximum = 127, + .step = 1, + .default_value = 64, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 1, + .maximum = 255, + .step = 1, + .default_value = 255, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Gain", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + } +}; + +static int mt9v022_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl); +static int mt9v022_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl); + +static struct soc_camera_ops mt9v022_ops = { + .owner = THIS_MODULE, + .init = mt9v022_init, + .release = mt9v022_release, + .start_capture = mt9v022_start_capture, + .stop_capture = mt9v022_stop_capture, + .set_capture_format = mt9v022_set_capture_format, + .try_fmt_cap = mt9v022_try_fmt_cap, + .formats = mt9v022_formats, + .num_formats = ARRAY_SIZE(mt9v022_formats), + .get_datawidth = mt9v022_get_datawidth, + .controls = mt9v022_controls, + .num_controls = ARRAY_SIZE(mt9v022_controls), + .get_control = mt9v022_get_control, + .set_control = mt9v022_set_control, + .get_chip_id = mt9v022_get_chip_id, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = mt9v022_get_register, + .set_register = mt9v022_set_register, +#endif +}; + +static int mt9v022_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + data = reg_read(icd, MT9V022_READ_MODE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x10); + break; + case V4L2_CID_HFLIP: + data = reg_read(icd, MT9V022_READ_MODE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x20); + break; + case V4L2_CID_EXPOSURE_AUTO: + data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x1); + break; + case V4L2_CID_AUTOGAIN: + data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x2); + break; + } + return 0; +} + +static int mt9v022_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + int data; + const struct v4l2_queryctrl *qctrl; + + qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); + + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (ctrl->value) + data = reg_set(icd, MT9V022_READ_MODE, 0x10); + else + data = reg_clear(icd, MT9V022_READ_MODE, 0x10); + if (data < 0) + return -EIO; + break; + case V4L2_CID_HFLIP: + if (ctrl->value) + data = reg_set(icd, MT9V022_READ_MODE, 0x20); + else + data = reg_clear(icd, MT9V022_READ_MODE, 0x20); + if (data < 0) + return -EIO; + break; + case V4L2_CID_GAIN: + /* mt9v022 has minimum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + /* Datasheet says 16 to 64. autogain only works properly + * after setting gain to maximum 14. Larger values + * produce "white fly" noise effect. On the whole, + * manually setting analog gain does no good. */ + unsigned long gain = ((ctrl->value - qctrl->minimum) * + 10 + range / 2) / range + 4; + if (gain >= 32) + gain &= ~1; + /* The user wants to set gain manually, hope, she + * knows, what she's doing... Switch AGC off. */ + + if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) + return -EIO; + + dev_info(&icd->dev, "Setting gain from %d to %lu\n", + reg_read(icd, MT9V022_ANALOG_GAIN), gain); + if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0) + return -EIO; + icd->gain = ctrl->value; + } + break; + case V4L2_CID_EXPOSURE: + /* mt9v022 has maximum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + unsigned long shutter = ((ctrl->value - qctrl->minimum) * + 479 + range / 2) / range + 1; + /* The user wants to set shutter width manually, hope, + * she knows, what she's doing... Switch AEC off. */ + + if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) + return -EIO; + + dev_dbg(&icd->dev, "Shutter width from %d to %lu\n", + reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH), + shutter); + if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + shutter) < 0) + return -EIO; + icd->exposure = ctrl->value; + } + break; + case V4L2_CID_AUTOGAIN: + if (ctrl->value) + data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + else + data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + if (data < 0) + return -EIO; + break; + case V4L2_CID_EXPOSURE_AUTO: + if (ctrl->value) + data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + else + data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + if (data < 0) + return -EIO; + break; + } + return 0; +} + +/* Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one */ +static int mt9v022_video_probe(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + s32 data; + int ret; + + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* Read out the chip version register */ + data = reg_read(icd, MT9V022_CHIP_VERSION); + + /* must be 0x1311 or 0x1313 */ + if (data != 0x1311 && data != 0x1313) { + ret = -ENODEV; + dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n", + data); + goto ei2c; + } + + /* Soft reset */ + ret = reg_write(icd, MT9V022_RESET, 1); + if (ret < 0) + goto ei2c; + /* 15 clock cycles */ + udelay(200); + if (reg_read(icd, MT9V022_RESET)) { + dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); + goto ei2c; + } + + /* Set monochrome or colour sensor type */ + if (sensor_type && (!strcmp("colour", sensor_type) || + !strcmp("color", sensor_type))) { + ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); + mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; + } else { + ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); + mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; + } + + if (ret >= 0) + ret = soc_camera_video_start(icd); + if (ret < 0) + goto eisis; + + dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", + data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? + "monochrome" : "colour"); + + return 0; + +eisis: +ei2c: + return ret; +} + +static void mt9v022_video_remove(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, + mt9v022->icd.dev.parent, mt9v022->icd.vdev); + soc_camera_video_stop(&mt9v022->icd); +} + +static int mt9v022_probe(struct i2c_client *client) +{ + struct mt9v022 *mt9v022; + struct soc_camera_device *icd; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl = client->dev.platform_data; + int ret; + + if (!icl) { + dev_err(&client->dev, "MT9V022 driver needs platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL); + if (!mt9v022) + return -ENOMEM; + + mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; + mt9v022->client = client; + i2c_set_clientdata(client, mt9v022); + + icd = &mt9v022->icd; + icd->probe = mt9v022_video_probe; + icd->remove = mt9v022_video_remove; + icd->ops = &mt9v022_ops; + icd->control = &client->dev; + icd->x_min = 1; + icd->y_min = 4; + icd->x_current = 1; + icd->y_current = 4; + icd->width_min = 48; + icd->width_max = 752; + icd->height_min = 32; + icd->height_max = 480; + icd->y_skip_top = 1; + icd->iface = icl->bus_id; + /* Default datawidth - this is the only width this camera (normally) + * supports. It is only with extra logic that it can support + * other widths. Therefore it seems to be a sensible default. */ + mt9v022->datawidth = 10; + + ret = bus_switch_request(mt9v022, icl); + if (ret) + goto eswinit; + + ret = soc_camera_device_register(icd); + if (ret) + goto eisdr; + + return 0; + +eisdr: + bus_switch_release(mt9v022); +eswinit: + kfree(mt9v022); + return ret; +} + +static int mt9v022_remove(struct i2c_client *client) +{ + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + + soc_camera_device_unregister(&mt9v022->icd); + bus_switch_release(mt9v022); + kfree(mt9v022); + + return 0; +} + +static struct i2c_driver mt9v022_i2c_driver = { + .driver = { + .name = "mt9v022", + }, + .probe = mt9v022_probe, + .remove = mt9v022_remove, +}; + +static int __init mt9v022_mod_init(void) +{ + return i2c_add_driver(&mt9v022_i2c_driver); +} + +static void __exit mt9v022_mod_exit(void) +{ + i2c_del_driver(&mt9v022_i2c_driver); +} + +module_init(mt9v022_mod_init); +module_exit(mt9v022_mod_exit); + +MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 76056a11155fafc4dc387139405a0a0e64257863 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:26:04 -0300 Subject: V4L/DVB (7184): make hybrid_tuner_request_state tolerant of devices without i2c adapters Some dvb demodulators access the tuner directly without using i2c. In these cases, i2c_adap may be NULL. This patch fixes hybrid_tuner_request_state to allow for NULL i2c_adapters. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-i2c.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index c53c327a487c..60ba794809fe 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -83,7 +83,8 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, #define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \ printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \ - i2c_adapter_id(i2cprops.adap), \ + i2cprops.adap ? \ + i2c_adapter_id(i2cprops.adap) : -1, \ i2cprops.addr, ##arg); \ } while (0) @@ -128,9 +129,10 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, ({ \ int __ret = 0; \ list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \ - if ((i2c_adapter_id(state->i2c_props.adap) == \ - i2c_adapter_id(i2cadap)) && \ - (state->i2c_props.addr == i2caddr)) { \ + if ((state->i2c_props.addr == i2caddr) && \ + ((state->i2c_props.adap ? \ + i2c_adapter_id(state->i2c_props.adap) : -1) == \ + (i2cadap ? i2c_adapter_id(i2cadap) : -1))) { \ __tuner_info(state->i2c_props, \ "attaching existing instance\n"); \ state->i2c_props.count++; \ -- cgit v1.2.3 From 6063572de2ac5a3db548c30983a8952c6eb7f689 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:04 -0300 Subject: V4L/DVB (7196): Lift videobuf-dma-sg's PCI dependency, until it is fixed videobuf-dma-sg.c should be converted to the generic DMA API to make it also useful for non-PCI configurations. Even now it can be used thanks to compatibility macros in include/asm-generic/pci-dma-compat.h. This has been verified to work on PXA270 CPU with the pxa_camera.c soc-camera driver. For this the following temporary work-around is needed. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 408838418d04..a86504587447 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -160,7 +160,7 @@ config VIDEOBUF_GEN tristate config VIDEOBUF_DMA_SG - depends on PCI + depends on PCI || ARCH_PXA select VIDEOBUF_GEN tristate -- cgit v1.2.3 From e01640aa445d8c131c1f87327f2d1b2957e2d748 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 14:26:05 -0300 Subject: V4L/DVB (7204): remove V4L2_CID_SHARPNESS from meye.h and report private control as DISABLED - Continue to support the V4L2_CID_PRIVATE_BASE + 1 control in the ABI - Report the same control as V4L2_CID_SHARPNESS - Report the private control disabled via QUERYCTRL Signed-off-by: Brandon Philips Acked-by: Stelian Pop Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/meye.c | 10 +++++++++- include/linux/meye.h | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index a079e7222cc9..caa9a7ac6184 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1239,6 +1239,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, 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"); @@ -1246,7 +1247,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->maximum = 63; c->step = 1; c->default_value = 32; - c->flags = 0; + + /* 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; @@ -1312,6 +1318,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.agc = c->value; 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; @@ -1356,6 +1363,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, 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: diff --git a/include/linux/meye.h b/include/linux/meye.h index 39fd9c8ddd4b..12010ace1f04 100644 --- a/include/linux/meye.h +++ b/include/linux/meye.h @@ -58,7 +58,7 @@ struct meye_params { /* V4L2 private controls */ #define V4L2_CID_AGC V4L2_CID_PRIVATE_BASE -#define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_MEYE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 1) #define V4L2_CID_PICTURE (V4L2_CID_PRIVATE_BASE + 2) #define V4L2_CID_JPEGQUAL (V4L2_CID_PRIVATE_BASE + 3) #define V4L2_CID_FRAMERATE (V4L2_CID_PRIVATE_BASE + 4) -- cgit v1.2.3 From 15f62f1bfb5cd9103ca694a6bff95f67d84b7c4c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:26:05 -0300 Subject: V4L/DVB (7211): tda18271: remove duplicated channel configuration code from tda18271c1_tune remove duplicated channel configuration code from tda18271c1_tune, instead call function tda18271_channel_configuration Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 48 +------------------------------ 1 file changed, 1 insertion(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 7f7fab7cd5af..26042a977e4e 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -752,54 +752,8 @@ static int tda18271c1_tune(struct dvb_frontend *fe, if (0 == tda18271_calc_rf_cal(fe, &freq)) tda18271_write_regs(fe, R_EB14, 1); - /* Channel Configuration */ - - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_EB22] = 0x2c; - break; - case TDA18271_DIGITAL: - regs[R_EB22] = 0x37; - break; - } - tda18271_write_regs(fe, R_EB22, 1); - - regs[R_EP1] |= 0x40; /* set dis power level on */ - - /* set standard */ - regs[R_EP3] &= ~0x1f; /* clear std bits */ - - /* see table 22 */ - regs[R_EP3] |= std; - - regs[R_EP4] &= ~0x03; /* set cal mode to normal */ - - regs[R_EP4] &= ~0x1c; /* clear if level bits */ - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_MPD] &= ~0x80; /* IF notch = 0 */ - break; - case TDA18271_DIGITAL: - regs[R_EP4] |= 0x04; - regs[R_MPD] |= 0x80; - break; - } - - if (radio) - regs[R_EP4] |= 0x80; - else - regs[R_EP4] &= ~0x80; - - /* image rejection validity */ - tda18271_calc_ir_measure(fe, &freq); - - /* calculate MAIN PLL */ - N = freq + ifc; - - tda18271_calc_main_pll(fe, N); + tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); - tda18271_write_regs(fe, R_TM, 15); - msleep(5); mutex_unlock(&priv->lock); return 0; -- cgit v1.2.3 From 04bfbbfed67861b8f65e7834fdde4a43a35a7dcb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:26:05 -0300 Subject: V4L/DVB (7212): tda18271: move rf calibration code from tda18271c1_tune into a new function move rf calibration code from tda18271c1_tune into a new function, tda18271c1_rf_tracking_filter_calibration Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 26042a977e4e..250899a90aa2 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -652,21 +652,13 @@ static int tda18271c2_tune(struct dvb_frontend *fe, /* ------------------------------------------------------------------ */ -static int tda18271c1_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) +static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, + u32 freq, u32 bw) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; u32 N = 0; - tda18271_init(fe); - - mutex_lock(&priv->lock); - - tda_dbg("freq = %d, ifc = %d\n", freq, ifc); - - /* RF tracking filter calibration */ - /* calculate bp filter */ tda18271_calc_bp_filter(fe, &freq); tda18271_write_regs(fe, R_EP1, 1); @@ -737,7 +729,7 @@ static int tda18271c1_tune(struct dvb_frontend *fe, regs[R_EB7] = 0x40; tda18271_write_regs(fe, R_EB7, 1); - msleep(10); + msleep(10); /* pll locking */ regs[R_EB20] = 0xec; tda18271_write_regs(fe, R_EB20, 1); @@ -752,6 +744,22 @@ static int tda18271c1_tune(struct dvb_frontend *fe, if (0 == tda18271_calc_rf_cal(fe, &freq)) tda18271_write_regs(fe, R_EB14, 1); + return 0; +} + +static int tda18271c1_tune(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std, int radio) +{ + struct tda18271_priv *priv = fe->tuner_priv; + + tda18271_init(fe); + + mutex_lock(&priv->lock); + + tda_dbg("freq = %d, ifc = %d\n", freq, ifc); + + tda18271c1_rf_tracking_filter_calibration(fe, freq, bw); + tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); mutex_unlock(&priv->lock); -- cgit v1.2.3 From 75636c3a006738bdd977f83044a1e28091b2cdc9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:26:06 -0300 Subject: V4L/DVB (7213): tda18271: consolidate tune functions combine tda18271c1_tune and tda18271c2_tune into a single function Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 60 +++++++++---------------------- 1 file changed, 16 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 250899a90aa2..2f05c4cdb8b7 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -195,8 +195,8 @@ static int tda18271_read_thermometer(struct dvb_frontend *fe) return tm; } -static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe, - u32 freq) +static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, + u32 freq) { struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; @@ -630,26 +630,6 @@ static int tda18271_init(struct dvb_frontend *fe) return 0; } -static int tda18271c2_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) -{ - struct tda18271_priv *priv = fe->tuner_priv; - - tda_dbg("freq = %d, ifc = %d\n", freq, ifc); - - tda18271_init(fe); - - mutex_lock(&priv->lock); - - tda18271_rf_tracking_filters_correction(fe, freq); - - tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); - - mutex_unlock(&priv->lock); - - return 0; -} - /* ------------------------------------------------------------------ */ static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, @@ -747,41 +727,33 @@ static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, return 0; } -static int tda18271c1_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) +/* ------------------------------------------------------------------ */ + +static int tda18271_tune(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std, int radio) { struct tda18271_priv *priv = fe->tuner_priv; + tda_dbg("freq = %d, ifc = %d, bw = %d, std = 0x%02x\n", + freq, ifc, bw, std); + tda18271_init(fe); mutex_lock(&priv->lock); - tda_dbg("freq = %d, ifc = %d\n", freq, ifc); - - tda18271c1_rf_tracking_filter_calibration(fe, freq, bw); - - tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); - - mutex_unlock(&priv->lock); - - return 0; -} - -static inline int tda18271_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) -{ - struct tda18271_priv *priv = fe->tuner_priv; - int ret = -EINVAL; - switch (priv->id) { case TDA18271HDC1: - ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio); + tda18271c1_rf_tracking_filter_calibration(fe, freq, bw); break; case TDA18271HDC2: - ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio); + tda18271c2_rf_tracking_filters_correction(fe, freq); break; } - return ret; + tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); + + mutex_unlock(&priv->lock); + + return 0; } /* ------------------------------------------------------------------ */ -- cgit v1.2.3 From bfee6808ee9f6bb2d636576e0181df6d7bc2b3c3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:26:06 -0300 Subject: V4L/DVB (7214): tda18271: move init functions to directly above tda18271_tune Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 78 +++++++++++++++---------------- 1 file changed, 38 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 2f05c4cdb8b7..b5d69a8108d9 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -36,22 +36,6 @@ static LIST_HEAD(hybrid_tuner_instance_list); /*---------------------------------------------------------------------*/ -static int tda18271_ir_cal_init(struct dvb_frontend *fe) -{ - struct tda18271_priv *priv = fe->tuner_priv; - unsigned char *regs = priv->tda18271_regs; - - tda18271_read_regs(fe); - - /* test IR_CAL_OK to see if we need init */ - if ((regs[R_EP1] & 0x08) == 0) - tda18271_init_regs(fe); - - return 0; -} - -/* ------------------------------------------------------------------ */ - static int tda18271_channel_configuration(struct dvb_frontend *fe, u32 ifc, u32 freq, u32 bw, u8 std, int radio) @@ -195,6 +179,8 @@ static int tda18271_read_thermometer(struct dvb_frontend *fe) return tm; } +/* ------------------------------------------------------------------ */ + static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, u32 freq) { @@ -587,7 +573,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) /* ------------------------------------------------------------------ */ -static int tda18271_rf_cal_init(struct dvb_frontend *fe) +static int tda18271c2_rf_cal_init(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; @@ -610,28 +596,6 @@ static int tda18271_rf_cal_init(struct dvb_frontend *fe) return 0; } -static int tda18271_init(struct dvb_frontend *fe) -{ - struct tda18271_priv *priv = fe->tuner_priv; - - mutex_lock(&priv->lock); - - /* power up */ - tda18271_set_standby_mode(fe, 0, 0, 0); - - /* initialization */ - tda18271_ir_cal_init(fe); - - if (priv->id == TDA18271HDC2) - tda18271_rf_cal_init(fe); - - mutex_unlock(&priv->lock); - - return 0; -} - -/* ------------------------------------------------------------------ */ - static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, u32 freq, u32 bw) { @@ -729,6 +693,40 @@ static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, /* ------------------------------------------------------------------ */ +static int tda18271_ir_cal_init(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + + tda18271_read_regs(fe); + + /* test IR_CAL_OK to see if we need init */ + if ((regs[R_EP1] & 0x08) == 0) + tda18271_init_regs(fe); + + return 0; +} + +static int tda18271_init(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + + mutex_lock(&priv->lock); + + /* power up */ + tda18271_set_standby_mode(fe, 0, 0, 0); + + /* initialization */ + tda18271_ir_cal_init(fe); + + if (priv->id == TDA18271HDC2) + tda18271c2_rf_cal_init(fe); + + mutex_unlock(&priv->lock); + + return 0; +} + static int tda18271_tune(struct dvb_frontend *fe, u32 ifc, u32 freq, u32 bw, u8 std, int radio) { @@ -1093,7 +1091,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, tda18271_init_regs(fe); if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2)) - tda18271_rf_cal_init(fe); + tda18271c2_rf_cal_init(fe); mutex_unlock(&priv->lock); break; -- cgit v1.2.3 From 117014ed461bf3a4eacbcaee02bc32158026ed34 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:06 -0300 Subject: V4L/DVB (7217): Replace NO_GPIO with gpio_is_valid() Upon suggestion by David Brownell use a gpio_is_valid() predicate instead of an explicit NO_GPIO macro. The respective patch to include/asm-generic/gpio.h has been accepted upstream. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 10 +++++----- drivers/media/video/mt9v022.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 3c5867c378d3..b65ff7745b8d 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -154,7 +154,7 @@ static int bus_switch_request(struct mt9m001 *mt9m001, int ret; unsigned int gpio = icl->gpio; - if (gpio != NO_GPIO) { + if (gpio_is_valid(gpio)) { /* We have a data bus switch. */ ret = gpio_request(gpio, "mt9m001"); if (ret < 0) { @@ -174,7 +174,7 @@ static int bus_switch_request(struct mt9m001 *mt9m001, mt9m001->switch_gpio = gpio; #else - mt9m001->switch_gpio = NO_GPIO; + mt9m001->switch_gpio = -EINVAL; #endif return 0; } @@ -182,7 +182,7 @@ static int bus_switch_request(struct mt9m001 *mt9m001, static void bus_switch_release(struct mt9m001 *mt9m001) { #ifdef CONFIG_MT9M001_PCA9536_SWITCH - if (mt9m001->switch_gpio != NO_GPIO) + if (gpio_is_valid(mt9m001->switch_gpio)) gpio_free(mt9m001->switch_gpio); #endif } @@ -190,7 +190,7 @@ static void bus_switch_release(struct mt9m001 *mt9m001) static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) { #ifdef CONFIG_MT9M001_PCA9536_SWITCH - if (mt9m001->switch_gpio == NO_GPIO) + if (!gpio_is_valid(mt9m001->switch_gpio)) return -ENODEV; gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit); @@ -224,7 +224,7 @@ static int mt9m001_set_capture_format(struct soc_camera_device *icd, (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { /* data width switch requested */ - if (mt9m001->switch_gpio == NO_GPIO) + if (!gpio_is_valid(mt9m001->switch_gpio)) return -EINVAL; /* Well, we actually only can do 10 or 8 bits... */ diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 9b406e41902a..5fbeaa305f35 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -187,7 +187,7 @@ static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *i int ret; unsigned int gpio = icl->gpio; - if (gpio != NO_GPIO) { + if (gpio_is_valid(gpio)) { /* We have a data bus switch. */ ret = gpio_request(gpio, "mt9v022"); if (ret < 0) { @@ -206,7 +206,7 @@ static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *i mt9v022->switch_gpio = gpio; #else - mt9v022->switch_gpio = NO_GPIO; + mt9v022->switch_gpio = -EINVAL; #endif return 0; } @@ -214,7 +214,7 @@ static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *i static void bus_switch_release(struct mt9v022 *mt9v022) { #ifdef CONFIG_MT9V022_PCA9536_SWITCH - if (mt9v022->switch_gpio != NO_GPIO) + if (gpio_is_valid(mt9v022->switch_gpio)) gpio_free(mt9v022->switch_gpio); #endif } @@ -222,7 +222,7 @@ static void bus_switch_release(struct mt9v022 *mt9v022) static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit) { #ifdef CONFIG_MT9V022_PCA9536_SWITCH - if (mt9v022->switch_gpio == NO_GPIO) + if (!gpio_is_valid(mt9v022->switch_gpio)) return -ENODEV; gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit); @@ -303,7 +303,7 @@ static int mt9v022_set_capture_format(struct soc_camera_device *icd, (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { /* data width switch requested */ - if (mt9v022->switch_gpio == NO_GPIO) + if (!gpio_is_valid(mt9v022->switch_gpio)) return -EINVAL; /* Well, we actually only can do 10 or 8 bits... */ -- cgit v1.2.3 From 39f59351eeb415bc618810dcf94eb274192d6d9d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:07 -0300 Subject: V4L/DVB (7218): Fix breakage in mt9m001 and mt9v022 driver if "CONFIG_GENERIC_GPIO is not set" Both camera drivers can function without GPIO support, in which case they will only support the 10 bit data width mode. But the two respective switch have to depend on CONFIG_GENERIC_GPIO. Additionally remove redundant gpio_is_valid tests - they are repeated in bus_switch_request() functions. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 8 ++++---- drivers/media/video/mt9m001.c | 6 ++---- drivers/media/video/mt9v022.c | 6 ++---- 3 files changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 21f250b8cbb0..de6a6208e344 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -847,7 +847,7 @@ config SOC_CAMERA config SOC_CAMERA_MT9M001 tristate "mt9m001 support" - depends on SOC_CAMERA && GENERIC_GPIO + depends on SOC_CAMERA select GPIO_PCA953X if MT9M001_PCA9536_SWITCH help This driver supports MT9M001 cameras from Micron, monochrome @@ -855,21 +855,21 @@ config SOC_CAMERA_MT9M001 config MT9M001_PCA9536_SWITCH bool "pca9536 datawidth switch for mt9m001" - depends on SOC_CAMERA_MT9M001 + depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO help Select this if your MT9M001 camera uses a PCA9536 I2C GPIO extender to switch between 8 and 10 bit datawidth modes config SOC_CAMERA_MT9V022 tristate "mt9v022 support" - depends on SOC_CAMERA && GENERIC_GPIO + depends on SOC_CAMERA select GPIO_PCA953X if MT9V022_PCA9536_SWITCH help This driver supports MT9V022 cameras from Micron config MT9V022_PCA9536_SWITCH bool "pca9536 datawidth switch for mt9v022" - depends on SOC_CAMERA_MT9V022 + depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO help Select this if your MT9V022 camera uses a PCA9536 I2C GPIO extender to switch between 8 and 10 bit datawidth modes diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index b65ff7745b8d..e3afc82050af 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -17,7 +17,9 @@ #include #include +#ifdef CONFIG_MT9M001_PCA9536_SWITCH #include +#endif /* mt9m001 i2c address 0x5d * The platform has to define i2c_board_info @@ -223,10 +225,6 @@ static int mt9m001_set_capture_format(struct soc_camera_device *icd, if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { - /* data width switch requested */ - if (!gpio_is_valid(mt9m001->switch_gpio)) - return -EINVAL; - /* Well, we actually only can do 10 or 8 bits... */ if (width_flag == IS_DATAWIDTH_9) return -EINVAL; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 5fbeaa305f35..468333946d57 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -18,7 +18,9 @@ #include #include +#ifdef CONFIG_MT9M001_PCA9536_SWITCH #include +#endif /* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c * The platform has to define i2c_board_info @@ -302,10 +304,6 @@ static int mt9v022_set_capture_format(struct soc_camera_device *icd, if ((mt9v022->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { - /* data width switch requested */ - if (!gpio_is_valid(mt9v022->switch_gpio)) - return -EINVAL; - /* Well, we actually only can do 10 or 8 bits... */ if (width_flag == IS_DATAWIDTH_9) return -EINVAL; -- cgit v1.2.3 From fcd6dfc36e0931cf8ec95a97f75418f3c9acb263 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Wed, 2 Apr 2008 14:26:07 -0300 Subject: V4L/DVB (7220): drivers/media/video/sn9c102/sn9c102_core.c Fix Unlikely(x) == y Fix Unlikely(x) == y Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Reviewed-by: Luca Risolia Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sn9c102/sn9c102_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index e5ef0190ebdc..94f393eebd51 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -528,7 +528,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) /* Search for the SOF marker (fixed part) in the header */ for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) { - if (unlikely(i+j) == len) + if (unlikely(i+j == len)) return NULL; if (*(m+i+j) == marker[cam->sof.bytesread]) { cam->sof.header[cam->sof.bytesread] = *(m+i+j); -- cgit v1.2.3 From b448600fe6f900f8e7d6464dfea114fbc9b1f82a Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:26:08 -0300 Subject: V4L/DVB (7223): Add support for the ISL6405 dual LNB supply chip The chip can control 2 LNBs independently. The driver distinguishes them by evaluating the MSB of the override_set parameter of the isl6405_attach function. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 +++++++ drivers/media/dvb/frontends/Makefile | 1 + 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 9ad86ce4a4e5..0209644f222a 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -379,6 +379,13 @@ config DVB_LNBP21 help An SEC control chip. +config DVB_ISL6405 + tristate "ISL6405 SEC controller" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + An SEC control chip. + config DVB_ISL6421 tristate "ISL6421 SEC controller" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 16bd107ebd32..23304b3774b5 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_LNBP21) += lnbp21.o +obj-$(CONFIG_DVB_ISL6405) += isl6405.o obj-$(CONFIG_DVB_ISL6421) += isl6421.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o -- cgit v1.2.3 From d1f549ea35a041721634211ab39e2372b290af8e Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:26:08 -0300 Subject: V4L/DVB (7224): Initial DVB-S support for MD8800 /CTX948 Support is not complete yet and untested. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/isl6405.c | 164 ++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/isl6405.h | 74 ++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 18 +++- 3 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 drivers/media/dvb/frontends/isl6405.c create mode 100644 drivers/media/dvb/frontends/isl6405.h (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb/frontends/isl6405.c new file mode 100644 index 000000000000..33d33f4d8867 --- /dev/null +++ b/drivers/media/dvb/frontends/isl6405.c @@ -0,0 +1,164 @@ +/* + * isl6405.c - driver for dual lnb supply and control ic ISL6405 + * + * Copyright (C) 2008 Hartmut Hackmann + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "isl6405.h" + +struct isl6405 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + u8 i2c_addr; +}; + +static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv; + struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0, + .buf = &isl6405->config, + .len = sizeof(isl6405->config) }; + + if (isl6405->override_or & 0x80) { + isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2); + switch (voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + isl6405->config |= ISL6405_EN2; + break; + case SEC_VOLTAGE_18: + isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2); + break; + default: + return -EINVAL; + } + } else { + isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1); + switch (voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + isl6405->config |= ISL6405_EN1; + break; + case SEC_VOLTAGE_18: + isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1); + break; + default: + return -EINVAL; + }; + } + isl6405->config |= isl6405->override_or; + isl6405->config &= isl6405->override_and; + + return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv; + struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0, + .buf = &isl6405->config, + .len = sizeof(isl6405->config) }; + + if (isl6405->override_or & 0x80) { + if (arg) + isl6405->config |= ISL6405_LLC2; + else + isl6405->config &= ~ISL6405_LLC2; + } else { + if (arg) + isl6405->config |= ISL6405_LLC1; + else + isl6405->config &= ~ISL6405_LLC1; + } + isl6405->config |= isl6405->override_or; + isl6405->config &= isl6405->override_and; + + return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void isl6405_release(struct dvb_frontend *fe) +{ + /* power off */ + isl6405_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free */ + kfree(fe->sec_priv); + fe->sec_priv = NULL; +} + +struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, + u8 i2c_addr, u8 override_set, u8 override_clear) +{ + struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL); + if (!isl6405) + return NULL; + + /* default configuration */ + if (override_set & 0x80) + isl6405->config = ISL6405_ISEL2; + else + isl6405->config = ISL6405_ISEL1; + isl6405->i2c = i2c; + isl6405->i2c_addr = i2c_addr; + fe->sec_priv = isl6405; + + /* bits which should be forced to '1' */ + isl6405->override_or = override_set; + + /* bits which should be forced to '0' */ + isl6405->override_and = ~override_clear; + + /* detect if it is present or not */ + if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(isl6405); + fe->sec_priv = NULL; + return NULL; + } + + /* install release callback */ + fe->ops.release_sec = isl6405_release; + + /* override frontend ops */ + fe->ops.set_voltage = isl6405_set_voltage; + fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage; + + return fe; +} +EXPORT_SYMBOL(isl6405_attach); + +MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405"); +MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h new file mode 100644 index 000000000000..9d4001a2237e --- /dev/null +++ b/drivers/media/dvb/frontends/isl6405.h @@ -0,0 +1,74 @@ +/* + * isl6405.h - driver for dual lnb supply and control ic ISL6405 + * + * Copyright (C) 2008 Hartmut Hackmann + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef _ISL6405_H +#define _ISL6405_H + +#include + +/* system register bits */ + +/* this bit selects register (control) 1 or 2 + note that the bit maps are different */ + +#define ISL6405_SR 0x80 + +/* SR = 0 */ +#define ISL6405_OLF1 0x01 +#define ISL6405_EN1 0x02 +#define ISL6405_VSEL1 0x04 +#define ISL6405_LLC1 0x08 +#define ISL6405_ENT1 0x10 +#define ISL6405_ISEL1 0x20 +#define ISL6405_DCL 0x40 + +/* SR = 1 */ +#define ISL6405_OLF2 0x01 +#define ISL6405_OTF 0x02 +#define ISL6405_EN2 0x04 +#define ISL6405_VSEL2 0x08 +#define ISL6405_LLC2 0x10 +#define ISL6405_ENT2 0x20 +#define ISL6405_ISEL2 0x40 + +#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE)) +/* override_set and override_clear control which system register bits (above) + * to always set & clear + */ +extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, + u8 i2c_addr, u8 override_set, u8 override_clear); +#else +static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 i2c_addr, + u8 override_set, u8 override_clear) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif /* CONFIG_DVB_ISL6405 */ + +#endif diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 9d61d74fabd4..72fd9fed8a34 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -43,6 +43,7 @@ #include "tda826x.h" #include "tda827x.h" #include "isl6421.h" +#include "isl6405.h" MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -990,7 +991,22 @@ static int dvb_init(struct saa7134_dev *dev) configure_tda827x_fe(dev, &tevion_dvbt220rf_config); break; case SAA7134_BOARD_MEDION_MD8800_QUADRO: - configure_tda827x_fe(dev, &md8800_dvbt_config); + if (!use_frontend) { /* terrestrial */ + configure_tda827x_fe(dev, &md8800_dvbt_config); + } else { /* satellite */ + dev->dvb.frontend = dvb_attach(tda10086_attach, + &flydvbs, &dev->i2c_adap); + if (dev->dvb.frontend) { + if (dvb_attach(tda826x_attach, dev->dvb.frontend, + 0x60, &dev->i2c_adap, 0) == NULL) + wprintk("%s: Medion Quadro, no tda826x " + "found !\n", __FUNCTION__); + if (dvb_attach(isl6405_attach, dev->dvb.frontend, + &dev->i2c_adap, 0x08, 0, 0) == NULL) + wprintk("%s: Medion Quadro, no ISL6405 " + "found !\n", __FUNCTION__); + } + } break; case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, -- cgit v1.2.3 From c1fd49226d7e05dfb126b0a88760273d1e0f7f95 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:26:08 -0300 Subject: V4L/DVB (7226): saa7134: add support for the NXP Snake DVB-S reference design Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 26 ++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 13 +++++++++++++ drivers/media/video/saa7134/saa7134.h | 3 ++- 4 files changed, 42 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 0424901ebc78..3ec78d4cfea3 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -131,3 +131,4 @@ 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193] 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 132 -> Genius TVGO AM11MCE +133 -> NXP Snake DVB-S reference design diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 6f5744286e8c..16cd319dc4e6 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3992,6 +3992,24 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x6000, }, }, + [SAA7134_BOARD_PHILIPS_SNAKE] = { + .name = "NXP Snake DVB-S reference design", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5283,6 +5301,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PHILIPS_EUROPA: + if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) { + /* Reconfigure board as Snake reference design */ + dev->board = SAA7134_BOARD_PHILIPS_SNAKE; + dev->tuner_type = saa7134_boards[dev->board].tuner_type; + printk(KERN_INFO "%s: Reconfigured board as %s\n", + dev->name, saa7134_boards[dev->board].name); + break; + } case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: /* The Philips EUROPA based hybrid boards have the tuner connected through diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 72fd9fed8a34..5d20ec06e48d 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -44,6 +44,7 @@ #include "tda827x.h" #include "isl6421.h" #include "isl6405.h" +#include "lnbp21.h" MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -1080,6 +1081,18 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config); break; + case SAA7134_BOARD_PHILIPS_SNAKE: + dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + &dev->i2c_adap); + if (dev->dvb.frontend) { + if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, + &dev->i2c_adap, 0) == NULL) + wprintk("%s: No tda826x found!\n", __FUNCTION__); + if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + &dev->i2c_adap, 0, 0) == NULL) + wprintk("%s: No lnbp21 found!\n", __FUNCTION__); + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f940d0254798..4dc66f4b0e4a 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -253,7 +253,8 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_607_9FM 129 #define SAA7134_BOARD_BEHOLD_M6 130 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 -#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 +#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 +#define SAA7134_BOARD_PHILIPS_SNAKE 133 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 16769f2774d07cb79b6c3241f0bb229f0a299f9b Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:26:09 -0300 Subject: V4L/DVB (7227): saa7134: fixed DVB-S support for Medion/Creatix CTX948 The I2C bus interface of the LNB supply sits behind the i2c gate of the tda10086, so wrappers were necessary for the set_voltage functions. For the time being, the board will show up as MD8800 Many thanks to Hermann Pitton for his help Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 45 ++++++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134.h | 4 ++- 2 files changed, 47 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 5d20ec06e48d..180d3193c971 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -846,6 +846,36 @@ static struct tda10086_config flydvbs = { .diseqc_tone = 0, }; +/* ------------------------------------------------------------------ + * special case: lnb supply is connected to the gated i2c + */ + +static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + int res = -EIO; + struct saa7134_dev *dev = fe->dvb->priv; + if (fe->ops.i2c_gate_ctrl) { + fe->ops.i2c_gate_ctrl(fe, 1); + if (dev->original_set_voltage) + res = dev->original_set_voltage(fe, voltage); + fe->ops.i2c_gate_ctrl(fe, 0); + } + return res; +}; + +static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg) +{ + int res = -EIO; + struct saa7134_dev *dev = fe->dvb->priv; + if (fe->ops.i2c_gate_ctrl) { + fe->ops.i2c_gate_ctrl(fe, 1); + if (dev->original_set_high_voltage) + res = dev->original_set_high_voltage(fe, arg); + fe->ops.i2c_gate_ctrl(fe, 0); + } + return res; +}; + /* ================================================================== * nxt200x based ATSC cards, helper functions */ @@ -998,14 +1028,27 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); if (dev->dvb.frontend) { + struct dvb_frontend *fe; if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) wprintk("%s: Medion Quadro, no tda826x " "found !\n", __FUNCTION__); - if (dvb_attach(isl6405_attach, dev->dvb.frontend, + /* Note 10.2. Hac + * up to here. configuration for ctx948 and and one branch + * of md8800 should be identical + */ + /* we need to open the i2c gate (we know it exists) */ + fe = dev->dvb.frontend; + fe->ops.i2c_gate_ctrl(fe, 1); + if (dvb_attach(isl6405_attach, fe, &dev->i2c_adap, 0x08, 0, 0) == NULL) wprintk("%s: Medion Quadro, no ISL6405 " "found !\n", __FUNCTION__); + fe->ops.i2c_gate_ctrl(fe, 0); + dev->original_set_voltage = fe->ops.set_voltage; + fe->ops.set_voltage = md8800_set_voltage; + dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage; + fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage; } } break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4dc66f4b0e4a..2b7661f58a70 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -557,7 +557,9 @@ struct saa7134_dev { #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) /* SAA7134_MPEG_DVB only */ struct videobuf_dvb dvb; - int (*original_demod_sleep)(struct dvb_frontend* fe); + int (*original_demod_sleep)(struct dvb_frontend *fe); + int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); + int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg); #endif }; -- cgit v1.2.3 From b679f305de808c4d380fe9cf0b560b7d8c426856 Mon Sep 17 00:00:00 2001 From: Hermann Pitton Date: Wed, 2 Apr 2008 14:26:09 -0300 Subject: V4L/DVB (7229): saa7134: add support for the Creatix CTX953_V.1.4.3 Hybrid Signed-off-by: Hermann Pitton Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 31 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 3 +++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 36 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 3ec78d4cfea3..bae05ff515df 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -132,3 +132,4 @@ 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 132 -> Genius TVGO AM11MCE 133 -> NXP Snake DVB-S reference design +134 -> Medion/Creatix CTX953 Hybrid [16be:0010] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 16cd319dc4e6..a827af4546d0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4010,6 +4010,30 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, } }, }, + [SAA7134_BOARD_CREATIX_CTX953] = { + .name = "Medion/Creatix CTX953 Hybrid", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 0, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4960,6 +4984,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/ .subdevice = 0x0022, .driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x16be, + .subdevice = 0x0010, /* Medion version CTX953_V.1.4.3 */ + .driver_data = SAA7134_BOARD_CREATIX_CTX953, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -5359,6 +5389,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_MEDION_MD8800_QUADRO: case SAA7134_BOARD_AVERMEDIA_SUPER_007: case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: + case SAA7134_BOARD_CREATIX_CTX953: /* this is a hybrid board, initialize to analog mode * and configure firmware eeprom address */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 180d3193c971..683a67561a6e 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1136,6 +1136,9 @@ static int dvb_init(struct saa7134_dev *dev) wprintk("%s: No lnbp21 found!\n", __FUNCTION__); } break; + case SAA7134_BOARD_CREATIX_CTX953: + configure_tda827x_fe(dev, &md8800_dvbt_config); + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 2b7661f58a70..e483209b6854 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -255,6 +255,7 @@ struct saa7134_format { #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 #define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 #define SAA7134_BOARD_PHILIPS_SNAKE 133 +#define SAA7134_BOARD_CREATIX_CTX953 134 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 3be64bfc553c82f18bfd61dd718387532300eb71 Mon Sep 17 00:00:00 2001 From: Russell Kliese Date: Wed, 2 Apr 2008 14:26:09 -0300 Subject: V4L/DVB (7230): saa7134: add support for the MSI TV@nywhere A/D v1.1 card Signed-off-by: Russell Kliese Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 36 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 3 +++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 41 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index bae05ff515df..765a06b1f0f6 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -133,3 +133,4 @@ 132 -> Genius TVGO AM11MCE 133 -> NXP Snake DVB-S reference design 134 -> Medion/Creatix CTX953 Hybrid [16be:0010] +135 -> MSI TV@nywhere A/D v1.1 [1462:8625] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index a827af4546d0..f9c85b7cba1a 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4034,6 +4034,36 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, } }, }, + [SAA7134_BOARD_MSI_TVANYWHERE_AD11] = { + .name = "MSI TV@nywhere A/D v1.1", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 2, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x0200000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4990,6 +5020,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x16be, .subdevice = 0x0010, /* Medion version CTX953_V.1.4.3 */ .driver_data = SAA7134_BOARD_CREATIX_CTX953, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1462, /* MSI */ + .subdevice = 0x8625, /* TV@nywhere A/D v1.1 */ + .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 683a67561a6e..b55df4877aff 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1139,6 +1139,9 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_CREATIX_CTX953: configure_tda827x_fe(dev, &md8800_dvbt_config); break; + case SAA7134_BOARD_MSI_TVANYWHERE_AD11: + configure_tda827x_fe(dev, &philips_tiger_s_config); + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index e483209b6854..d7e0781fe8a1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -256,6 +256,7 @@ struct saa7134_format { #define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 #define SAA7134_BOARD_PHILIPS_SNAKE 133 #define SAA7134_BOARD_CREATIX_CTX953 134 +#define SAA7134_BOARD_MSI_TVANYWHERE_AD11 135 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 7691aede741eba49ad0dc11dc5996f545210de90 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:10 -0300 Subject: V4L/DVB (7235): tuner-simple: fix a buffer overflow simple_set_tv() creates a buffer with 4 elements, and calls simple_std_setup(), passing &buffer[1]. This makes the 5th element of buffer to be initialized to 0, overriding some area outside the buffer. Also, simple_std_setup() receives a buffer as parameter, but the buffer is just overriden after the call, so, it doesn't make much sense to pass it as a parameter. This patch removes buffer[] from the function call, creating, instead, a local var to be used internally. Thanks to Axel Rometsch for pointing the issue. Reviewed-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index dc2467159ece..ee5ef860700a 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -251,7 +251,7 @@ static int simple_config_lookup(struct dvb_frontend *fe, static int simple_std_setup(struct dvb_frontend *fe, struct analog_parameters *params, - u8 *buffer, u8 *config, u8 *cb) + u8 *config, u8 *cb) { struct tuner_simple_priv *priv = fe->tuner_priv; u8 tuneraddr; @@ -323,14 +323,12 @@ static int simple_std_setup(struct dvb_frontend *fe, break; case TUNER_PHILIPS_TUV1236D: + { /* 0x40 -> ATSC antenna input 1 */ /* 0x48 -> ATSC antenna input 2 */ /* 0x00 -> NTSC antenna input 1 */ /* 0x08 -> NTSC antenna input 2 */ - buffer[0] = 0x14; - buffer[1] = 0x00; - buffer[2] = 0x17; - buffer[3] = 0x00; + u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00}; *cb &= ~0x40; if (params->std & V4L2_STD_ATSC) { *cb |= 0x40; @@ -351,6 +349,7 @@ static int simple_std_setup(struct dvb_frontend *fe, /* FIXME: input */ break; } + } return 0; } @@ -509,7 +508,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, offset / 16, offset % 16 * 100 / 16, div); /* tv norm specific stuff for multi-norm tuners */ - simple_std_setup(fe, params, &buffer[1], &config, &cb); + simple_std_setup(fe, params, &config, &cb); if (t_params->cb_first_if_lower_freq && div < priv->last_div) { buffer[0] = config; -- cgit v1.2.3 From 15f7a58e93dc8596f332b2e698b0b87652f085ff Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:10 -0300 Subject: V4L/DVB (7237): Convert videobuf-dma-sg to generic DMA API videobuf-dma-sg does not need to depend on PCI. Switch it to using generic DMA API, convert all affected drivers, relax Kconfig restriction, improve compile-time type checking, fix some Coding Style violations while at it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 2 +- drivers/media/common/saa7146_vbi.c | 4 +- drivers/media/common/saa7146_video.c | 4 +- drivers/media/video/bt8xx/bttv-driver.c | 16 ++-- drivers/media/video/cx23885/cx23885-dvb.c | 2 +- drivers/media/video/cx23885/cx23885-video.c | 4 +- drivers/media/video/cx88/cx88-alsa.c | 8 +- drivers/media/video/cx88/cx88-blackbird.c | 4 +- drivers/media/video/cx88/cx88-dvb.c | 4 +- drivers/media/video/cx88/cx88-video.c | 8 +- drivers/media/video/saa7134/saa7134-alsa.c | 10 +-- drivers/media/video/saa7134/saa7134-dvb.c | 4 +- drivers/media/video/saa7134/saa7134-empress.c | 4 +- drivers/media/video/saa7134/saa7134-video.c | 8 +- drivers/media/video/soc_camera.c | 2 +- drivers/media/video/videobuf-dma-sg.c | 117 +++++++++++++------------- drivers/media/video/videobuf-vmalloc.c | 2 +- include/media/videobuf-dma-sg.h | 14 +-- 18 files changed, 109 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index a86504587447..b9b38d9ff650 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -160,7 +160,7 @@ config VIDEOBUF_GEN tristate config VIDEOBUF_DMA_SG - depends on PCI || ARCH_PXA + depends on HAS_DMA select VIDEOBUF_GEN tristate diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index bfbd5a841ebf..74e2b56ecb5b 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) fh->vbi_fmt.start[1] = 312; fh->vbi_fmt.count[1] = 16; - videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, // FIXME: does this really work? sizeof(struct saa7146_buf), diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 66fdbd0e6a6d..3cbc6ebbe649 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file) sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; - videobuf_queue_pci_init(&fh->video_q, &video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->video_q, &video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct saa7146_buf), diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index fcf8f2d208a8..af2c0c994186 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -2372,7 +2372,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); @@ -2760,7 +2760,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) mutex_lock(&fh->cap.vb_lock); if (on) { fh->ov.tvnorm = btv->tvnorm; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); } else { @@ -2834,7 +2834,7 @@ static int bttv_s_fbuf(struct file *file, void *f, if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv, fh, new); @@ -3184,7 +3184,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) /* need to capture a new frame */ if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) goto err; - fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize); + fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize); if (NULL == fh->cap.read_buf) goto err; fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; @@ -3251,14 +3251,14 @@ static int bttv_open(struct inode *inode, struct file *file) fh->ov.setup_ok = 0; v4l2_prio_open(&btv->prio,&fh->prio); - videobuf_queue_pci_init(&fh->cap, &bttv_video_qops, - btv->c.pci, &btv->s_lock, + videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, + &btv->c.pci->dev, &btv->s_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct bttv_buffer), fh); - videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops, - btv->c.pci, &btv->s_lock, + videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops, + &btv->c.pci->dev, &btv->s_lock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct bttv_buffer), diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index ed465c007cea..6c21779852fb 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -349,7 +349,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port) /* dvb stuff */ printk("%s: cx23885 based dvb card\n", dev->name); - videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock, + videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx23885_buffer), port); err = dvb_register(port); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index d3c4d2c5cbe0..45bf2146a193 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -765,8 +765,8 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx23885_buffer), diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 316b106c3511..2f5a4a4ba407 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -283,7 +283,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) BUG_ON(!chip->dma_size); dprintk(2,"Freeing buffer\n"); - videobuf_pci_dma_unmap(chip->pci, chip->dma_risc); + videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); videobuf_dma_free(chip->dma_risc); btcx_riscmem_free(chip->pci,&chip->buf->risc); kfree(chip->buf); @@ -385,7 +385,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, BUG_ON(!chip->dma_size); BUG_ON(chip->num_periods & (chip->num_periods-1)); - buf = videobuf_pci_alloc(sizeof(*buf)); + buf = videobuf_sg_alloc(sizeof(*buf)); if (NULL == buf) return -ENOMEM; @@ -396,14 +396,14 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, buf->vb.height = chip->num_periods; buf->vb.size = chip->dma_size; - dma=videobuf_to_dma(&buf->vb); + dma = videobuf_to_dma(&buf->vb); videobuf_dma_init(dma); ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); if (ret < 0) goto error; - ret = videobuf_pci_dma_map(chip->pci,dma); + ret = videobuf_sg_dma_map(&chip->pci->dev, dma); if (ret < 0) goto error; diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index c37269074524..d582395805df 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1087,8 +1087,8 @@ static int mpeg_open(struct inode *inode, struct file *file) file->private_data = fh; fh->dev = dev; - videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 7586fe31f643..fa21666966e6 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -744,8 +744,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); - videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 8b293a3357b2..c30356bb35e9 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -776,14 +776,14 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), fh); - videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct cx88_buffer), diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 505bc0a478af..048081be91fe 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -503,7 +503,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, /* release the old buffer */ if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } @@ -519,12 +519,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, return err; } - if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) { + if (0 != (err = videobuf_sg_dma_map(&dev->pci->dev, &dev->dmasound.dma))) { dsp_buffer_free(dev); return err; } if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -533,7 +533,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, dev->dmasound.dma.sglen, 0))) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -569,7 +569,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream) if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index b55df4877aff..eabc67d03b2c 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -899,8 +899,8 @@ static int dvb_init(struct saa7134_dev *dev) dev->ts.nr_bufs = 32; dev->ts.nr_packets = 32*4; dev->dvb.name = dev->name; - videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, sizeof(struct saa7134_buf), diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 40d4a66b77f5..e002be568c21 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -427,8 +427,8 @@ static int empress_init(struct saa7134_dev *dev) printk(KERN_INFO "%s: registered device video%d [mpeg]\n", dev->name,dev->empress_dev->minor & 0x1f); - videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, sizeof(struct saa7134_buf), diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 5385026a85ef..ecc5243da57e 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1350,14 +1350,14 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 576; v4l2_prio_open(&dev->prio,&fh->prio); - videobuf_queue_pci_init(&fh->cap, &video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->cap, &video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct saa7134_buf), fh); - videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct saa7134_buf), diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 904e9dfc1a89..c947525c3f2f 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -210,7 +210,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* We must pass NULL as dev pointer, then all pci_* dma operations * transform to normal dma_* ones. Do we need an irqlock? */ - videobuf_queue_pci_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, + videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, ici->msize, icd); diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 7008afabe92c..6141a13bfc97 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -1,5 +1,5 @@ /* - * helper functions for PCI DMA video4linux capture buffers + * helper functions for SG DMA video4linux capture buffers * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ static int debug; module_param(debug, int, 0644); -MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers"); +MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers"); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); @@ -119,10 +119,10 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf) { - struct videbuf_pci_sg_memory *mem=buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = buf->priv; + BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); return &mem->dma; } @@ -141,9 +141,14 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, dma->direction = direction; switch (dma->direction) { - case PCI_DMA_FROMDEVICE: rw = READ; break; - case PCI_DMA_TODEVICE: rw = WRITE; break; - default: BUG(); + case DMA_FROM_DEVICE: + rw = READ; + break; + case DMA_TO_DEVICE: + rw = WRITE; + break; + default: + BUG(); } first = (data & PAGE_MASK) >> PAGE_SHIFT; @@ -216,10 +221,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, return 0; } -int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) +int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) { - void *dev=q->dev; - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); @@ -245,7 +248,7 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) return -ENOMEM; } if (!dma->bus_addr) { - dma->sglen = pci_map_sg(dev,dma->sglist, + dma->sglen = dma_map_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); if (0 == dma->sglen) { printk(KERN_WARNING @@ -259,14 +262,12 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) return 0; } -int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma) +int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma) { - void *dev=q->dev; - - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + MAGIC_CHECK(dma->magic, MAGIC_DMABUF); BUG_ON(!dma->sglen); - pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction); + dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction); return 0; } @@ -274,11 +275,11 @@ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { void *dev=q->dev; - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + MAGIC_CHECK(dma->magic, MAGIC_DMABUF); if (!dma->sglen) return 0; - pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction); + dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); kfree(dma->sglist); dma->sglist = NULL; @@ -306,28 +307,28 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) if (dma->bus_addr) { dma->bus_addr = 0; } - dma->direction = PCI_DMA_NONE; + dma->direction = DMA_NONE; return 0; } /* --------------------------------------------------------------------- */ -int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) +int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma) { struct videobuf_queue q; - q.dev=pci; + q.dev = dev; - return (videobuf_dma_map(&q,dma)); + return videobuf_dma_map(&q, dma); } -int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) +int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) { struct videobuf_queue q; - q.dev=pci; + q.dev = dev; - return (videobuf_dma_unmap(&q,dma)); + return videobuf_dma_unmap(&q, dma); } /* --------------------------------------------------------------------- */ @@ -347,7 +348,7 @@ videobuf_vm_close(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; struct videobuf_queue *q = map->q; - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; int i; dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, @@ -409,18 +410,18 @@ static struct vm_operations_struct videobuf_vm_ops = }; /* --------------------------------------------------------------------- - * PCI handlers for the generic methods + * SG handlers for the generic methods */ /* Allocated area consists on 3 parts: struct video_buffer struct _buffer (cx88_buffer, saa7134_buf, ...) - struct videobuf_pci_sg_memory + struct videobuf_dma_sg_memory */ static void *__videobuf_alloc(size_t size) { - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; struct videobuf_buffer *vb; vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); @@ -443,10 +444,10 @@ static int __videobuf_iolock (struct videobuf_queue* q, { int err,pages; dma_addr_t bus; - struct videbuf_pci_sg_memory *mem=vb->priv; + struct videobuf_dma_sg_memory *mem = vb->priv; BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); switch (vb->memory) { case V4L2_MEMORY_MMAP: @@ -455,14 +456,14 @@ static int __videobuf_iolock (struct videobuf_queue* q, /* no userspace addr -- kernel bounce buffer */ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; err = videobuf_dma_init_kernel( &mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, pages ); if (0 != err) return err; } else if (vb->memory == V4L2_MEMORY_USERPTR) { /* dma directly to userspace */ err = videobuf_dma_init_user( &mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, vb->baddr,vb->bsize ); if (0 != err) return err; @@ -473,7 +474,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, locking inversion, so don't take it here */ err = videobuf_dma_init_user_locked(&mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, vb->baddr, vb->bsize); if (0 != err) return err; @@ -490,7 +491,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, */ bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff; pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; - err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE, + err = videobuf_dma_init_overlay(&mem->dma, DMA_FROM_DEVICE, bus, pages); if (0 != err) return err; @@ -498,7 +499,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, default: BUG(); } - err = videobuf_dma_map(q,&mem->dma); + err = videobuf_dma_map(q, &mem->dma); if (0 != err) return err; @@ -508,8 +509,8 @@ static int __videobuf_iolock (struct videobuf_queue* q, static int __videobuf_sync(struct videobuf_queue *q, struct videobuf_buffer *buf) { - struct videbuf_pci_sg_memory *mem=buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); return videobuf_dma_sync(q,&mem->dma); @@ -532,7 +533,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; struct videobuf_mapping *map; unsigned int first,last,size,i; int retval; @@ -552,7 +553,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, if (NULL == q->bufs[first]) continue; mem=q->bufs[first]->priv; - BUG_ON (!mem); + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) @@ -615,8 +616,8 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q, char __user *data, size_t count, int nonblocking ) { - struct videbuf_pci_sg_memory *mem=q->read_buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = q->read_buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); /* copy to userspace */ @@ -634,8 +635,8 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q, int vbihack, int nonblocking ) { unsigned int *fc; - struct videbuf_pci_sg_memory *mem=q->read_buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = q->read_buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); if (vbihack) { @@ -658,7 +659,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q, return count; } -static struct videobuf_qtype_ops pci_ops = { +static struct videobuf_qtype_ops sg_ops = { .magic = MAGIC_QTYPE_OPS, .alloc = __videobuf_alloc, @@ -670,21 +671,21 @@ static struct videobuf_qtype_ops pci_ops = { .copy_stream = __videobuf_copy_stream, }; -void *videobuf_pci_alloc (size_t size) +void *videobuf_sg_alloc(size_t size) { struct videobuf_queue q; /* Required to make generic handler to call __videobuf_alloc */ - q.int_ops=&pci_ops; + q.int_ops = &sg_ops; - q.msize=size; + q.msize = size; - return videobuf_alloc (&q); + return videobuf_alloc(&q); } -void videobuf_queue_pci_init(struct videobuf_queue* q, +void videobuf_queue_sg_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -692,7 +693,7 @@ void videobuf_queue_pci_init(struct videobuf_queue* q, void *priv) { videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, - priv, &pci_ops); + priv, &sg_ops); } /* --------------------------------------------------------------------- */ @@ -709,11 +710,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_sync); EXPORT_SYMBOL_GPL(videobuf_dma_unmap); EXPORT_SYMBOL_GPL(videobuf_dma_free); -EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); -EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); -EXPORT_SYMBOL_GPL(videobuf_pci_alloc); +EXPORT_SYMBOL_GPL(videobuf_sg_dma_map); +EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap); +EXPORT_SYMBOL_GPL(videobuf_sg_alloc); -EXPORT_SYMBOL_GPL(videobuf_queue_pci_init); +EXPORT_SYMBOL_GPL(videobuf_queue_sg_init); /* * Local variables: diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 3de3c8920175..4a2508dfa0e3 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -102,7 +102,7 @@ static struct vm_operations_struct videobuf_vm_ops = /* Allocated area consists on 3 parts: struct video_buffer struct _buffer (cx88_buffer, saa7134_buf, ...) - struct videobuf_pci_sg_memory + struct videobuf_dma_sg_memory */ static void *__videobuf_alloc(size_t size) diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index 38105031db23..b6ab08045de6 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -1,5 +1,5 @@ /* - * helper functions for PCI DMA video4linux capture buffers + * helper functions for SG DMA video4linux capture buffers * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented @@ -81,7 +81,7 @@ struct videobuf_dmabuf { int direction; }; -struct videbuf_pci_sg_memory +struct videobuf_dma_sg_memory { u32 magic; @@ -103,11 +103,11 @@ int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf); -void *videobuf_pci_alloc (size_t size); +void *videobuf_sg_alloc(size_t size); -void videobuf_queue_pci_init(struct videobuf_queue* q, +void videobuf_queue_sg_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -117,6 +117,6 @@ void videobuf_queue_pci_init(struct videobuf_queue* q, /*FIXME: these variants are used only on *-alsa code, where videobuf is * used without queue */ -int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma); -int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma); +int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma); +int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma); -- cgit v1.2.3 From 9ac8daf7f00e1cc6aa5c38a82b1b67744d0e8c84 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 2 Apr 2008 14:26:10 -0300 Subject: V4L/DVB (7238): make stk_camera_{suspend,resume}() static This patch makes the needlessly global stk_camera_{suspend,resume}() static. Signed-off-by: Adrian Bunk Acked-by: Jaime Velasco Juan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/stk-webcam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index ceba45ad0294..d2bf54194b63 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -1465,7 +1465,7 @@ static void stk_camera_disconnect(struct usb_interface *interface) } #ifdef CONFIG_PM -int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) +static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) { struct stk_camera *dev = usb_get_intfdata(intf); if (is_streaming(dev)) { @@ -1476,7 +1476,7 @@ int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) return 0; } -int stk_camera_resume(struct usb_interface *intf) +static int stk_camera_resume(struct usb_interface *intf) { struct stk_camera *dev = usb_get_intfdata(intf); if (!is_initialised(dev)) -- cgit v1.2.3 From 7fb4933e57cd6ec1b370e271d1abfcac7a158b2f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:26:11 -0300 Subject: V4L/DVB (7240): tveeprom: remove obsolete i2c driver code The i2c driver code was once added for the out-of-tree ivtv driver, but the ivtv driver hasn't used that for a long time so this code can now be removed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tveeprom.c | 103 ----------------------------------------- 1 file changed, 103 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index dc0da44a5af6..3cf8a8e801e5 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -745,109 +745,6 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len) } EXPORT_SYMBOL(tveeprom_read); -/* ----------------------------------------------------------------------- */ -/* needed for ivtv.sf.net at the moment. Should go away in the long */ -/* run, just call the exported tveeprom_* directly, there is no point in */ -/* using the indirect way via i2c_driver->command() */ - -static unsigned short normal_i2c[] = { - 0xa0 >> 1, - I2C_CLIENT_END, -}; - -I2C_CLIENT_INSMOD; - -static struct i2c_driver i2c_driver_tveeprom; - -static int -tveeprom_command(struct i2c_client *client, - unsigned int cmd, - void *arg) -{ - struct tveeprom eeprom; - u32 *eeprom_props = arg; - u8 *buf; - - switch (cmd) { - case 0: - buf = kzalloc(256, GFP_KERNEL); - tveeprom_read(client, buf, 256); - tveeprom_hauppauge_analog(client, &eeprom, buf); - kfree(buf); - eeprom_props[0] = eeprom.tuner_type; - eeprom_props[1] = eeprom.tuner_formats; - eeprom_props[2] = eeprom.model; - eeprom_props[3] = eeprom.revision; - eeprom_props[4] = eeprom.has_radio; - break; - default: - return -EINVAL; - } - return 0; -} - -static int -tveeprom_detect_client(struct i2c_adapter *adapter, - int address, - int kind) -{ - struct i2c_client *client; - - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (NULL == client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_tveeprom; - snprintf(client->name, sizeof(client->name), "tveeprom"); - i2c_attach_client(client); - - return 0; -} - -static int -tveeprom_attach_adapter(struct i2c_adapter *adapter) -{ - if (adapter->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adapter, &addr_data, tveeprom_detect_client); - return 0; -} - -static int -tveeprom_detach_client(struct i2c_client *client) -{ - int err; - - err = i2c_detach_client(client); - if (err < 0) - return err; - kfree(client); - return 0; -} - -static struct i2c_driver i2c_driver_tveeprom = { - .driver = { - .name = "tveeprom", - }, - .id = I2C_DRIVERID_TVEEPROM, - .attach_adapter = tveeprom_attach_adapter, - .detach_client = tveeprom_detach_client, - .command = tveeprom_command, -}; - -static int __init tveeprom_init(void) -{ - return i2c_add_driver(&i2c_driver_tveeprom); -} - -static void __exit tveeprom_exit(void) -{ - i2c_del_driver(&i2c_driver_tveeprom); -} - -module_init(tveeprom_init); -module_exit(tveeprom_exit); - /* * Local variables: * c-basic-offset: 8 -- cgit v1.2.3 From cc34e5cd3bd31b42c936fadb55f442c39334a1e7 Mon Sep 17 00:00:00 2001 From: Tyler Trafford Date: Wed, 2 Apr 2008 14:26:11 -0300 Subject: V4L/DVB (7241): cx25840: code cleanup - Use min() - Eliminate extraneous variables Signed-off-by: Tyler Trafford Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-firmware.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 1ddf724a2c74..620d295947ab 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -79,11 +79,9 @@ static int check_fw_load(struct i2c_client *client, int size) return 0; } -static int fw_write(struct i2c_client *client, u8 * data, int size) +static int fw_write(struct i2c_client *client, u8 *data, int size) { - int sent; - - if ((sent = i2c_master_send(client, data, size)) < size) { + if (i2c_master_send(client, data, size) < size) { v4l_err(client, "firmware load i2c failure\n"); return -ENOSYS; } @@ -96,7 +94,7 @@ int cx25840_loadfw(struct i2c_client *client) struct cx25840_state *state = i2c_get_clientdata(client); const struct firmware *fw = NULL; u8 buffer[4], *ptr; - int size, send, retval; + int size, retval; if (state->is_cx23885) firmware = FWFILE_CX23885; @@ -124,8 +122,7 @@ int cx25840_loadfw(struct i2c_client *client) while (size > 0) { ptr[0] = 0x08; ptr[1] = 0x02; - send = size > (FWSEND - 2) ? FWSEND : size + 2; - retval = fw_write(client, ptr, send); + retval = fw_write(client, ptr, min(FWSEND, size + 2)); if (retval < 0) { release_firmware(fw); -- cgit v1.2.3 From 7f2b3beb65b289e410fcb780d61441227c6c25b5 Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Wed, 2 Apr 2008 14:26:11 -0300 Subject: V4L/DVB (7243): ivtv: yuv framebuffer tracking The existing yuv code limits output to the display area occupied by the framebuffer. This patch allows the yuv output to be 'detached' via V4L2_FBUF_FLAG_OVERLAY. By default, the yuv output window will be restricted to the framebuffer dimensions and the output position is relative to the top left corner of the framebuffer. This matches the behaviour of previous versions. If V4L2_FBUF_FLAG_OVERLAY is cleared, the yuv output will no longer be linked to the framebuffer. The maximum dimensions are either 720x576 or 720x480 depending on the current broadcast standard, with the output position relative to the top left corner of the display. The framebuffer itself can be resized, moved and panned without affecting the yuv output. Signed-off-by: Ian Armstrong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 1 + drivers/media/video/ivtv/ivtv-driver.h | 2 ++ drivers/media/video/ivtv/ivtv-ioctl.c | 25 +++++++++++++++++-------- drivers/media/video/ivtv/ivtv-yuv.c | 32 ++++++++++++++++++-------------- 4 files changed, 38 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index b533188c9439..d0bb5b18797a 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -711,6 +711,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->yuv_info.lace_mode = ivtv_yuv_mode; itv->yuv_info.lace_threshold = ivtv_yuv_threshold; itv->yuv_info.max_frames_buffered = 3; + itv->yuv_info.track_osd = 1; return 0; } diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 536140f0c19e..ba06e813c58c 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -456,6 +456,8 @@ struct yuv_playback_info int v_filter_2; int h_filter; + u8 track_osd; /* Should yuv output track the OSD size & position */ + u32 osd_x_offset; u32 osd_y_offset; diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index edef2a579617..f562cbbadc16 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -712,6 +712,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg) int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg) { struct ivtv_open_id *id = NULL; + struct yuv_playback_info *yi = &itv->yuv_info; u32 data[CX2341X_MBOX_MAX_DATA]; int streamtype = 0; @@ -837,8 +838,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { - cropcap->bounds.width = itv->yuv_info.osd_full_w; - cropcap->bounds.height = itv->yuv_info.osd_full_h; + if (yi->track_osd) { + cropcap->bounds.width = yi->osd_full_w; + cropcap->bounds.height = yi->osd_full_h; + } else { + cropcap->bounds.width = 720; + cropcap->bounds.height = + itv->is_out_50hz ? 576 : 480; + } cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; } else { @@ -856,7 +863,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { - itv->yuv_info.main_rect = crop->c; + yi->main_rect = crop->c; return 0; } else { if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, @@ -878,7 +885,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) - crop->c = itv->yuv_info.main_rect; + crop->c = yi->main_rect; else crop->c = itv->main_rect; return 0; @@ -1070,11 +1077,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void itv->main_rect.height = itv->params.height; ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, 720, itv->main_rect.height, 0, 0); - itv->yuv_info.main_rect = itv->main_rect; + yi->main_rect = itv->main_rect; if (!itv->osd_info) { - itv->yuv_info.osd_full_w = 720; - itv->yuv_info.osd_full_h = - itv->is_out_50hz ? 576 : 480; + yi->osd_full_w = 720; + yi->osd_full_h = itv->is_out_50hz ? 576 : 480; } } break; @@ -1272,6 +1278,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void else fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; } + if (yi->track_osd) + fb->flags |= V4L2_FBUF_FLAG_OVERLAY; break; } @@ -1285,6 +1293,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0; itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; ivtv_set_osd_alpha(itv); + yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0; break; } diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 8fdd67cef74c..393d917cd672 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -718,9 +718,11 @@ static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f) f->src_w -= (osd_scale * osd_crop) >> 16; } - /* The OSD can be moved. Track to it */ - f->dst_x += itv->yuv_info.osd_x_offset; - f->dst_y += itv->yuv_info.osd_y_offset; + if (itv->yuv_info.track_osd) { + /* The OSD can be moved. Track to it */ + f->dst_x += itv->yuv_info.osd_x_offset; + f->dst_y += itv->yuv_info.osd_y_offset; + } /* Width & height for both src & dst must be even. Same for coordinates. */ @@ -792,11 +794,19 @@ void ivtv_yuv_work_handler(struct ivtv *itv) IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame); f = yi->new_frame_info[frame]; - /* Update the osd pan info */ - f.pan_x = yi->osd_x_pan; - f.pan_y = yi->osd_y_pan; - f.vis_w = yi->osd_vis_w; - f.vis_h = yi->osd_vis_h; + if (yi->track_osd) { + /* Snapshot the osd pan info */ + f.pan_x = yi->osd_x_pan; + f.pan_y = yi->osd_y_pan; + f.vis_w = yi->osd_vis_w; + f.vis_h = yi->osd_vis_h; + } else { + /* Not tracking the osd, so assume full screen */ + f.pan_x = 0; + f.pan_y = 0; + f.vis_w = 720; + f.vis_h = yi->decode_height; + } /* Calculate the display window coordinates. Exit if nothing left */ if (!(yuv_update = ivtv_yuv_window_setup(itv, &f))) @@ -965,12 +975,6 @@ static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) /* Are we going to offset the Y plane */ nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0; - /* Snapshot the osd pan info */ - nf->pan_x = yi->osd_x_pan; - nf->pan_y = yi->osd_y_pan; - nf->vis_w = yi->osd_vis_w; - nf->vis_h = yi->osd_vis_h; - nf->update = 0; nf->interlaced_y = 0; nf->interlaced_uv = 0; -- cgit v1.2.3 From 2f0b816b2735a5527dae958930fb327ad3a748a5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:26:13 -0300 Subject: V4L/DVB (7244): ivtv: CROP is not supported for video capture CROPCAP suggests that video capture supports cropping, but this is not the case. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-ioctl.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index f562cbbadc16..1beb296a1763 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -828,8 +828,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void case VIDIOC_CROPCAP: { struct v4l2_cropcap *cropcap = arg; - if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; cropcap->bounds.top = cropcap->bounds.left = 0; cropcap->bounds.width = 720; @@ -874,9 +873,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void } return -EINVAL; } - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - return itv->video_dec_func(itv, VIDIOC_S_CROP, arg); + return -EINVAL; } case VIDIOC_G_CROP: { @@ -890,9 +887,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void crop->c = itv->main_rect; return 0; } - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - return itv->video_dec_func(itv, VIDIOC_G_CROP, arg); + return -EINVAL; } case VIDIOC_ENUM_FMT: { -- cgit v1.2.3 From 5db38e23c96c043ca95c644af41bb3f218227eee Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:26:13 -0300 Subject: V4L/DVB (7245): ivtv: start timer for each DMA transfer The DMA timeout timer was started once for each set of DMA transfers, but it should be started for each single DMA transfer. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-irq.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 65604dde9726..a329c4689dbf 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -384,6 +384,8 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s) ivtv_stream_sync_for_device(s); write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR); write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); + itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); + add_timer(&itv->dma_timer); } static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s) @@ -398,6 +400,8 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s) ivtv_stream_sync_for_device(s); write_reg(s->sg_handle, IVTV_REG_DECDMAADDR); write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); + itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); + add_timer(&itv->dma_timer); } /* start the encoder DMA */ @@ -459,8 +463,6 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) ivtv_dma_enc_start_xfer(s); set_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = s->type; - itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); - add_timer(&itv->dma_timer); } } @@ -481,8 +483,6 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s) ivtv_dma_dec_start_xfer(s); set_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = s->type; - itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); - add_timer(&itv->dma_timer); } static void ivtv_irq_dma_read(struct ivtv *itv) @@ -492,10 +492,11 @@ static void ivtv_irq_dma_read(struct ivtv *itv) int hw_stream_type = 0; IVTV_DEBUG_HI_IRQ("DEC DMA READ\n"); - if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) { - del_timer(&itv->dma_timer); + + del_timer(&itv->dma_timer); + + if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) return; - } if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { s = &itv->streams[itv->cur_dma_stream]; @@ -543,7 +544,6 @@ static void ivtv_irq_dma_read(struct ivtv *itv) } wake_up(&s->waitq); } - del_timer(&itv->dma_timer); clear_bit(IVTV_F_I_UDMA, &itv->i_flags); clear_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = -1; @@ -557,10 +557,12 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); - if (itv->cur_dma_stream < 0) { - del_timer(&itv->dma_timer); + + del_timer(&itv->dma_timer); + + if (itv->cur_dma_stream < 0) return; - } + s = &itv->streams[itv->cur_dma_stream]; ivtv_stream_sync_for_cpu(s); @@ -585,7 +587,6 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) ivtv_dma_enc_start_xfer(s); return; } - del_timer(&itv->dma_timer); clear_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = -1; dma_post(s); -- cgit v1.2.3 From 8c795e8467395248ff7b7cccf1ef30565e1b4f1a Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 2 Apr 2008 14:26:13 -0300 Subject: V4L/DVB (7247): V4L: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l1-compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 118a0611b6ed..ffd3f106dd4f 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -126,7 +126,7 @@ set_v4l_control(struct inode *inode, /* ----------------------------------------------------------------- */ -const static unsigned int palette2pixelformat[] = { +static const unsigned int palette2pixelformat[] = { [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY, [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555, [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565, -- cgit v1.2.3 From 02ba43d9080572bbd8b1f621f55bf1f6eaf4c636 Mon Sep 17 00:00:00 2001 From: maximilian attems Date: Wed, 2 Apr 2008 14:26:14 -0300 Subject: V4L/DVB (7248): dabfirmware.h add missing license Received written ack from the dabusb author that the firmware is BSD licensed. As bonus clarify copyright holder. Signed-off-by: maximilian attems Acked-by: Deti Fliegl Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/dabfirmware.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/dabfirmware.h b/drivers/media/video/dabfirmware.h index d14d803566a3..cbd92635993d 100644 --- a/drivers/media/video/dabfirmware.h +++ b/drivers/media/video/dabfirmware.h @@ -1,5 +1,12 @@ /* * dabdata.h - dab usb firmware and bitstream data + * + * Copyright (C) 1999 BayCom GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that redistributions of source + * code retain the above copyright notice and this comment without + * modification. */ static INTEL_HEX_RECORD firmware[] = { -- cgit v1.2.3 From 09e97c7d8501a5030b2b18a71c9089d8e074aee6 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:14 -0300 Subject: V4L/DVB (7249): Fix advertised pixel formats in mt9m001 and mt9v022 Only advertise pixel formats, that we actually can support in the present configuration. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 17 ++++++++++++++--- drivers/media/video/mt9v022.c | 35 ++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index e3afc82050af..4ad834326fa8 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -44,15 +44,23 @@ #define MT9M001_CHIP_ENABLE 0xF1 static const struct soc_camera_data_format mt9m001_colour_formats[] = { + /* Order important: first natively supported, + * second supported with a GPIO extender */ { - .name = "RGB Bayer (sRGB)", - .depth = 16, + .name = "Bayer (sRGB) 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_SBGGR16, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "Bayer (sRGB) 8 bit", + .depth = 8, .fourcc = V4L2_PIX_FMT_SBGGR8, .colorspace = V4L2_COLORSPACE_SRGB, } }; static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { + /* Order important - see above */ { .name = "Monochrome 10 bit", .depth = 10, @@ -547,7 +555,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) case 0x8421: mt9m001->model = V4L2_IDENT_MT9M001C12ST; mt9m001_ops.formats = mt9m001_colour_formats; - mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_colour_formats); + if (mt9m001->client->dev.platform_data) + mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_colour_formats); + else + mt9m001_ops.num_formats = 1; break; case 0x8431: mt9m001->model = V4L2_IDENT_MT9M001C12STM; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 468333946d57..d677344d233d 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -59,18 +59,25 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"\n"); /* Progressive scan, master, defaults */ #define MT9V022_CHIP_CONTROL_DEFAULT 0x188 -static const struct soc_camera_data_format mt9v022_formats[] = { +static const struct soc_camera_data_format mt9v022_colour_formats[] = { + /* Order important: first natively supported, + * second supported with a GPIO extender */ { - .name = "RGB Bayer (sRGB)", - .depth = 8, - .fourcc = V4L2_PIX_FMT_SBGGR8, - .colorspace = V4L2_COLORSPACE_SRGB, - }, { - .name = "RGB Bayer (sRGB)", + .name = "Bayer (sRGB) 10 bit", .depth = 10, .fourcc = V4L2_PIX_FMT_SBGGR16, .colorspace = V4L2_COLORSPACE_SRGB, }, { + .name = "Bayer (sRGB) 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + } +}; + +static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { + /* Order important - see above */ + { .name = "Monochrome 10 bit", .depth = 10, .fourcc = V4L2_PIX_FMT_Y16, @@ -486,8 +493,8 @@ static struct soc_camera_ops mt9v022_ops = { .stop_capture = mt9v022_stop_capture, .set_capture_format = mt9v022_set_capture_format, .try_fmt_cap = mt9v022_try_fmt_cap, - .formats = mt9v022_formats, - .num_formats = ARRAY_SIZE(mt9v022_formats), + .formats = NULL, /* Filled in later depending on the */ + .num_formats = 0, /* sensor type and data widths */ .get_datawidth = mt9v022_get_datawidth, .controls = mt9v022_controls, .num_controls = ARRAY_SIZE(mt9v022_controls), @@ -671,9 +678,19 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) !strcmp("color", sensor_type))) { ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; + mt9v022_ops.formats = mt9v022_colour_formats; + if (mt9v022->client->dev.platform_data) + mt9v022_ops.num_formats = ARRAY_SIZE(mt9v022_colour_formats); + else + mt9v022_ops.num_formats = 1; } else { ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; + mt9v022_ops.formats = mt9v022_monochrome_formats; + if (mt9v022->client->dev.platform_data) + mt9v022_ops.num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); + else + mt9v022_ops.num_formats = 1; } if (ret >= 0) -- cgit v1.2.3 From 2f4a87873f13924871d7bb82e27d02d0e16fbe02 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:14 -0300 Subject: V4L/DVB (7250): Clean up pxa-camera driver, remove non-functional and never tested pm-support This patch addresses most issues pointed out by Russell and Erik, moves recently introduced into pxa-regs.h camera-specific defines into pxa_camera.c, removes dummy power-management functions, improves function-naming, etc. Signed-off-by: Guennadi Liakhovetski Acked-by: Russell King Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 150 +++++++++++++++--------------------- include/asm-arm/arch-pxa/pxa-regs.h | 19 ----- 2 files changed, 64 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 11aecad769cc..a34a193249f6 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -10,10 +10,9 @@ * (at your option) any later version. */ -#include - #include #include +#include #include #include #include @@ -42,6 +41,26 @@ #define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) #define PXA_CAM_DRV_NAME "pxa27x-camera" +#define CICR0_SIM_MP (0 << 24) +#define CICR0_SIM_SP (1 << 24) +#define CICR0_SIM_MS (2 << 24) +#define CICR0_SIM_EP (3 << 24) +#define CICR0_SIM_ES (4 << 24) + +#define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */ +#define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */ + +#define CICR2_BLW_VAL(x) (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */ +#define CICR2_ELW_VAL(x) (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */ +#define CICR2_HSW_VAL(x) (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */ +#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */ +#define CICR2_FSW_VAL(x) (((x) << 0) & CICR2_FSW) /* Frame stabilization wait count */ + +#define CICR3_BFW_VAL(x) (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count */ +#define CICR3_EFW_VAL(x) (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */ +#define CICR3_VSW_VAL(x) (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */ +#define CICR3_LPF_VAL(x) (((x) << 0) & CICR3_LPF) /* Lines per frame */ + #define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \ CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \ CICR0_EOFM | CICR0_FOM) @@ -83,8 +102,6 @@ struct pxa_camera_dev { void __iomem *base; unsigned int dma_chan_y; - enum v4l2_buf_type type; - struct pxacamera_platform_data *pdata; struct resource *res; unsigned long platform_flags; @@ -94,8 +111,6 @@ struct pxa_camera_dev { spinlock_t lock; - int dma_running; - struct pxa_buffer *active; }; @@ -106,9 +121,8 @@ static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ /* * Videobuf operations */ -static int -pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) +static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) { struct soc_camera_device *icd = vq->priv_data; @@ -151,9 +165,8 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) buf->vb.state = VIDEOBUF_NEEDS_INIT; } -static int -pxa_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) +static int pxa_videobuf_prepare(struct videobuf_queue *vq, + struct videobuf_buffer *vb, enum v4l2_field field) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = @@ -255,15 +268,15 @@ out: return ret; } -static void -pxa_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +static void pxa_videobuf_queue(struct videobuf_queue *vq, + struct videobuf_buffer *vb) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); - struct pxa_buffer *active = pcdev->active; + struct pxa_buffer *active; struct videobuf_dmabuf *dma = videobuf_to_dma(vb); int nents = dma->sglen; unsigned long flags; @@ -275,8 +288,9 @@ pxa_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) list_add_tail(&vb->queue, &pcdev->capture); vb->state = VIDEOBUF_ACTIVE; + active = pcdev->active; - if (!pcdev->active) { + if (!active) { CIFR |= CIFR_RESET_F; DDADR(pcdev->dma_chan_y) = buf->sg_dma; DCSR(pcdev->dma_chan_y) = DCSR_RUN; @@ -373,22 +387,21 @@ static void pxa_camera_dma_irq_y(int channel, void *data) spin_lock_irqsave(&pcdev->lock, flags); status = DCSR(pcdev->dma_chan_y); + DCSR(pcdev->dma_chan_y) = status; + if (status & DCSR_BUSERR) { - dev_err(pcdev->dev, "%s: Bus Error\n", __FUNCTION__); - DCSR(pcdev->dma_chan_y) |= DCSR_BUSERR; + dev_err(pcdev->dev, "DMA Bus Error IRQ!\n"); goto out; } if (!(status & DCSR_ENDINTR)) { - dev_err(pcdev->dev, "%s: unknown dma interrupt source. " - "status: 0x%08x\n", __FUNCTION__, status); + dev_err(pcdev->dev, "Unknown DMA IRQ source, " + "status: 0x%08x\n", status); goto out; } - DCSR(pcdev->dma_chan_y) |= DCSR_ENDINTR; - if (!pcdev->active) { - dev_err(pcdev->dev, "%s: no active buf\n", __FUNCTION__); + dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n"); goto out; } @@ -398,7 +411,7 @@ static void pxa_camera_dma_irq_y(int channel, void *data) dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, vb, vb->baddr, vb->bsize); - /* _init is used to debug races, see comment in pxa_is_reqbufs() */ + /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ list_del_init(&vb->queue); vb->state = VIDEOBUF_DONE; do_gettimeofday(&vb->ts); @@ -419,7 +432,7 @@ out: spin_unlock_irqrestore(&pcdev->lock, flags); } -static struct videobuf_queue_ops pxa_video_ops = { +static struct videobuf_queue_ops pxa_videobuf_ops = { .buf_setup = pxa_videobuf_setup, .buf_prepare = pxa_videobuf_prepare, .buf_queue = pxa_videobuf_queue, @@ -444,7 +457,7 @@ static int mclk_get_divisor(struct pxa_camera_dev *pcdev) return div; } -static void pxa_is_activate(struct pxa_camera_dev *pcdev) +static void pxa_camera_activate(struct pxa_camera_dev *pcdev) { struct pxacamera_platform_data *pdata = pcdev->pdata; u32 cicr4 = 0; @@ -486,7 +499,7 @@ static void pxa_is_activate(struct pxa_camera_dev *pcdev) clk_enable(pcdev->clk); } -static void pxa_is_deactivate(struct pxa_camera_dev *pcdev) +static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) { struct pxacamera_platform_data *board = pcdev->pdata; @@ -518,7 +531,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) /* The following two functions absolutely depend on the fact, that * there can be only one camera on PXA quick capture interface */ -static int pxa_is_add_device(struct soc_camera_device *icd) +static int pxa_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; @@ -534,7 +547,7 @@ static int pxa_is_add_device(struct soc_camera_device *icd) dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", icd->devnum); - pxa_is_activate(pcdev); + pxa_camera_activate(pcdev); ret = icd->ops->init(icd); if (!ret) @@ -546,7 +559,7 @@ ebusy: return ret; } -static void pxa_is_remove_device(struct soc_camera_device *icd) +static void pxa_camera_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; @@ -563,13 +576,13 @@ static void pxa_is_remove_device(struct soc_camera_device *icd) icd->ops->release(icd); - pxa_is_deactivate(pcdev); + pxa_camera_deactivate(pcdev); pcdev->icd = NULL; } -static int pxa_is_set_capture_format(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int pxa_camera_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); @@ -652,14 +665,14 @@ static int pxa_is_set_capture_format(struct soc_camera_device *icd, /* CIF interrupts are not used, only DMA */ CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ? - 0 : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) | + CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) | CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB); return 0; } -static int pxa_is_try_fmt_cap(struct soc_camera_host *ici, - struct v4l2_format *f) +static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, + struct v4l2_format *f) { /* limit to pxa hardware capabilities */ if (f->fmt.pix.height < 32) @@ -675,8 +688,8 @@ static int pxa_is_try_fmt_cap(struct soc_camera_host *ici, return 0; } -static int pxa_is_reqbufs(struct soc_camera_file *icf, - struct v4l2_requestbuffers *p) +static int pxa_camera_reqbufs(struct soc_camera_file *icf, + struct v4l2_requestbuffers *p) { int i; @@ -694,7 +707,7 @@ static int pxa_is_reqbufs(struct soc_camera_file *icf, return 0; } -static unsigned int pxa_is_poll(struct file *file, poll_table *pt) +static unsigned int pxa_camera_poll(struct file *file, poll_table *pt) { struct soc_camera_file *icf = file->private_data; struct pxa_buffer *buf; @@ -711,8 +724,8 @@ static unsigned int pxa_is_poll(struct file *file, poll_table *pt) return 0; } -static int pxa_is_querycap(struct soc_camera_host *ici, - struct v4l2_capability *cap) +static int pxa_camera_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) { /* cap->name is set by the firendly caller:-> */ strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); @@ -725,15 +738,15 @@ static int pxa_is_querycap(struct soc_camera_host *ici, /* Should beallocated dynamically too, but we have only one. */ static struct soc_camera_host pxa_soc_camera_host = { .drv_name = PXA_CAM_DRV_NAME, - .vbq_ops = &pxa_video_ops, - .add = pxa_is_add_device, - .remove = pxa_is_remove_device, + .vbq_ops = &pxa_videobuf_ops, + .add = pxa_camera_add_device, + .remove = pxa_camera_remove_device, .msize = sizeof(struct pxa_buffer), - .set_capture_format = pxa_is_set_capture_format, - .try_fmt_cap = pxa_is_try_fmt_cap, - .reqbufs = pxa_is_reqbufs, - .poll = pxa_is_poll, - .querycap = pxa_is_querycap, + .set_capture_format = pxa_camera_set_capture_format, + .try_fmt_cap = pxa_camera_try_fmt_cap, + .reqbufs = pxa_camera_reqbufs, + .poll = pxa_camera_poll, + .querycap = pxa_camera_querycap, }; static int pxa_camera_probe(struct platform_device *pdev) @@ -753,8 +766,7 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); if (!pcdev) { - dev_err(&pdev->dev, "%s: Could not allocate pcdev\n", - __FUNCTION__); + dev_err(&pdev->dev, "Could not allocate pcdev\n"); err = -ENOMEM; goto exit; } @@ -871,51 +883,17 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev) kfree(pcdev); - dev_info(&pdev->dev, "%s: PXA Camera driver unloaded\n", __FUNCTION__); - - return 0; -} - -/* - * Suspend the Camera Module. - */ -static int pxa_camera_suspend(struct platform_device *pdev, pm_message_t level) -{ - struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + dev_info(&pdev->dev, "PXA Camera driver unloaded\n"); - dev_info(&pdev->dev, "camera suspend\n"); - disable_irq(pcdev->irq); return 0; } -/* - * Resume the Camera Module. - */ -static int pxa_camera_resume(struct platform_device *pdev) -{ - struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); - - dev_info(&pdev->dev, "camera resume\n"); - enable_irq(pcdev->irq); - -/* if (pcdev) { */ /* FIXME: dev in use? */ -/* DRCMR68 = pcdev->dma_chan_y | DRCMR_MAPVLD; */ -/* DRCMR69 = pcdev->dma_chan_cb | DRCMR_MAPVLD; */ -/* DRCMR70 = pcdev->dma_chan_cr | DRCMR_MAPVLD; */ -/* } */ - - return 0; -} - - static struct platform_driver pxa_camera_driver = { .driver = { .name = PXA_CAM_DRV_NAME, }, .probe = pxa_camera_probe, .remove = __exit_p(pxa_camera_remove), - .suspend = pxa_camera_suspend, - .resume = pxa_camera_resume, }; diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index e9ef1073bc29..87bfd7fce103 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -2016,11 +2016,6 @@ #define CICR0_ENB (1 << 28) /* Camera interface enable */ #define CICR0_DIS (1 << 27) /* Camera interface disable */ #define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ -#define CICR0_SIM_MP (0 << 24) -#define CICR0_SIM_SP (1 << 24) -#define CICR0_SIM_MS (2 << 24) -#define CICR0_SIM_EP (3 << 24) -#define CICR0_SIM_ES (4 << 24) #define CICR0_TOM (1 << 9) /* Time-out mask */ #define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ #define CICR0_FEM (1 << 7) /* FIFO-empty mask */ @@ -2071,20 +2066,6 @@ #define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ #define CICR4_DIV (0xff << 0) /* Clock divisor mask */ -#define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */ -#define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */ - -#define CICR2_BLW_VAL(x) (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */ -#define CICR2_ELW_VAL(x) (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */ -#define CICR2_HSW_VAL(x) (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */ -#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */ -#define CICR2_FSW_VAL(x) (((x) << 0) & CICR2_FSW) /* Frame stabilization wait count */ - -#define CICR3_BFW_VAL(x) (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count */ -#define CICR3_EFW_VAL(x) (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */ -#define CICR3_VSW_VAL(x) (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */ -#define CICR3_LPF_VAL(x) (((x) << 0) & CICR3_LPF) /* Lines per frame */ - #define CISR_FTO (1 << 15) /* FIFO time-out */ #define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ #define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ -- cgit v1.2.3 From d4d734a4d85702ce2390a5d44ac9ef8d1ff706ce Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Wed, 2 Apr 2008 14:26:15 -0300 Subject: V4L/DVB (7252): cx88: Add support for the Dvico PCI Nano ATSC is known to work. SVideo / Composite should work (I have no cable to test). Analog tuner support does not work. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 27 +++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 69 +++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 98 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index bc5593bd9704..79c166a7f230 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -57,3 +57,4 @@ 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602] 57 -> ADS Tech Instant Video PCI [1421:0390] 58 -> Pinnacle PCTV HD 800i [11bd:0051] + 59 -> DVICO HDTV5 PCI Nano [18ac:d530] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 8c9a8adf52de..23b58bc9cf2b 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1401,6 +1401,29 @@ static const struct cx88_board cx88_boards[] = { }}, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = { + .name = "DVICO HDTV5 PCI Nano", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x000027df, /* Unconfirmed */ + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000027df, /* Unconfirmed */ + .audioroute = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000027df, /* Unconfirmed */ + .audioroute = 1, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -1714,6 +1737,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x11bd, .subdevice = 0x0051, .card = CX88_BOARD_PINNACLE_PCTV_HD_800i, + }, { + .subvendor = 0x18ac, + .subdevice = 0xd530, + .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO, }, }; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index fa21666966e6..735376060df2 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -45,6 +45,8 @@ #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" +#include "tuner-xc2028.h" +#include "tuner-xc2028-types.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -357,6 +359,40 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, return 0; } +static int cx88_xc3028_callback(void *ptr, int command, int arg) +{ + struct cx88_core *core = ptr; + + switch (command) { + case XC2028_TUNER_RESET: + /* Send the tuner in then out of reset */ + dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg); + + switch (core->boardnr) { + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + /* GPIO-4 xc3028 tuner */ + + cx_set(MO_GP0_IO, 0x00001000); + cx_clear(MO_GP0_IO, 0x00000010); + msleep(100); + cx_set(MO_GP0_IO, 0x00000010); + msleep(100); + break; + } + + break; + case XC2028_RESET_CLK: + dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg); + break; + default: + dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__, + command, arg); + return -EINVAL; + } + + return 0; +} + static struct cx24123_config geniatech_dvbs_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, @@ -383,6 +419,15 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = { .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, }; +static struct s5h1409_config dvico_hdtv5_pci_nano_config = { + .demod_address = 0x32 >> 1, + .output_mode = S5H1409_SERIAL_OUTPUT, + .gpio = S5H1409_GPIO_OFF, + .inversion = S5H1409_INVERSION_OFF, + .status_mode = S5H1409_DEMODLOCKING, + .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, +}; + static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .i2c_address = 0x64, .if_khz = 5380, @@ -658,6 +703,30 @@ static int dvb_register(struct cx8802_dev *dev) &pinnacle_pctv_hd_800i_tuner_config); } break; + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + dev->dvb.frontend = dvb_attach(s5h1409_attach, + &dvico_hdtv5_pci_nano_config, + &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->core->i2c_adap, + .i2c_addr = 0x61, + .video_dev = dev->core, + .callback = cx88_xc3028_callback, + }; + static struct xc2028_ctrl ctl = { + .fname = "xc3028-v27.fw", + .max_len = 64, + .scode_table = OREN538, + }; + + fe = dvb_attach(xc2028_attach, + dev->dvb.frontend, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctl); + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 37e6d2e4002f..8121bd07a88a 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -211,6 +211,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_HAUPPAUGE_HVR1300 56 #define CX88_BOARD_ADSTECH_PTV_390 57 #define CX88_BOARD_PINNACLE_PCTV_HD_800i 58 +#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 063787a61565f472941d427b80d5027b259435a2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:26:15 -0300 Subject: V4L/DVB (7254): cx88: fix FusionHDTV 5 PCI nano name and enable IR support load ir-kbd-i2c for IR remote control support on DViCO FusionHDTV 5 PCI nano Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 2 +- drivers/media/video/cx88/cx88-cards.c | 3 ++- drivers/media/video/cx88/cx88-video.c | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 79c166a7f230..7d48e3dbd074 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -57,4 +57,4 @@ 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602] 57 -> ADS Tech Instant Video PCI [1421:0390] 58 -> Pinnacle PCTV HD 800i [11bd:0051] - 59 -> DVICO HDTV5 PCI Nano [18ac:d530] + 59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 23b58bc9cf2b..a1756c6c6dca 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1402,7 +1402,8 @@ static const struct cx88_board cx88_boards[] = { .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = { - .name = "DVICO HDTV5 PCI Nano", + .name = "DViCO FusionHDTV 5 PCI nano", + /* xc3008 tuner, digital only for now */ .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index c30356bb35e9..191577d166aa 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1832,8 +1832,10 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - request_module("ir-kbd-i2c"); request_module("rtc-isl1208"); + /* break intentionally omitted */ + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + request_module("ir-kbd-i2c"); } /* register v4l devices */ -- cgit v1.2.3 From f73541224ac8aa7f94cd4fb46d9f5be615552294 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:16 -0300 Subject: V4L/DVB (7256): cx88: Add support for tuner-xc3028 Callback gpio's based on Markus Rechberger, Christopher Pascoe and Steven Toth patches. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 91 +++++++++++++++++++++++++++++------ drivers/media/video/cx88/cx88-mpeg.c | 2 + 2 files changed, 79 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index a1756c6c6dca..3e07fbe4c843 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -27,6 +27,7 @@ #include "cx88.h" #include "tea5767.h" +#include "tuner-xc2028.h" static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; @@ -1908,26 +1909,63 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) } } +static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + switch (command) { + case XC2028_TUNER_RESET: + { + switch (INPUT(core->input).type) { + case CX88_RADIO: + printk(KERN_INFO "setting GPIO to radio!\n"); + cx_write(MO_GP0_IO, 0x4ff); + mdelay(250); + cx_write(MO_GP2_IO, 0xff); + mdelay(250); + cx_write(MO_GP1_IO, 0x101010); + mdelay(250); + cx_write(MO_GP1_IO, 0x101000); + mdelay(250); + cx_write(MO_GP1_IO, 0x101010); + mdelay(250); + return 0; + case CX88_VMUX_DVB: /* Digital TV*/ + default: /* Analog TV */ + printk(KERN_INFO "setting GPIO to TV!\n"); + cx_write(MO_GP1_IO, 0x101010); + mdelay(250); + cx_write(MO_GP1_IO, 0x101000); + mdelay(250); + cx_write(MO_GP1_IO, 0x101010); + mdelay(250); + return 0; + } + } + } + return -EINVAL; +} + /* ----------------------------------------------------------------------- */ /* Tuner callback function. Currently only needed for the Pinnacle * * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both * * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */ -int cx88_tuner_callback(void *priv, int command, int arg) +static int cx88_xc5000_tuner_callback(void *priv, int command, int arg) { struct i2c_algo_bit_data *i2c_algo = priv; struct cx88_core *core = i2c_algo->data; - switch(core->boardnr) { + switch (core->boardnr) { case CX88_BOARD_PINNACLE_PCTV_HD_800i: - if(command == 0) { /* This is the reset command from xc5000 */ + if (command == 0) { /* This is the reset command from xc5000 */ /* Reset XC5000 tuner via SYS_RSTO_pin */ cx_write(MO_SRST_IO, 0); msleep(10); cx_write(MO_SRST_IO, 1); return 0; - } - else { + } else { printk(KERN_ERR "xc5000: unknown tuner callback command.\n"); return -EINVAL; @@ -1936,6 +1974,20 @@ int cx88_tuner_callback(void *priv, int command, int arg) } return 0; /* Should never be here */ } + +int cx88_tuner_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + switch (core->board.tuner_type) { + case TUNER_XC2028: + return cx88_xc2028_tuner_callback(priv, command, arg); + case TUNER_XC5000: + return cx88_xc5000_tuner_callback(priv, command, arg); + } + return -EINVAL; +} EXPORT_SYMBOL(cx88_tuner_callback); /* ----------------------------------------------------------------------- */ @@ -2090,6 +2142,26 @@ static void cx88_card_setup(struct cx88_core *core) cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); } } + + if (core->board.tuner_type == TUNER_XC2028) { + struct v4l2_priv_tun_config xc2028_cfg; + struct xc2028_ctrl ctl; + + memset(&xc2028_cfg, 0, sizeof(ctl)); + memset(&ctl, 0, sizeof(ctl)); + + ctl.fname = XC2028_DEFAULT_FIRMWARE; + ctl.max_len = 64; + /* FIXME: Those should be device-dependent */ + ctl.demod = XC3028_FE_OREN538; + ctl.mts = 1; + + xc2028_cfg.tuner = TUNER_XC2028; + xc2028_cfg.priv = &ctl; + + cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); + } + } /* ------------------------------------------------------------------ */ @@ -2235,12 +2307,3 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) return core; } - -/* ------------------------------------------------------------------ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index a02cabbab778..6467ca336142 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -613,6 +613,8 @@ static int cx8802_request_acquire(struct cx8802_driver *drv) core->active_type_id != drv->type_id) return -EBUSY; + core->input = CX88_VMUX_DVB; + if (drv->advise_acquire) { mutex_lock(&drv->core->lock); -- cgit v1.2.3 From dd7fc3f633533e92926097238648fd91481dd54a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:17 -0300 Subject: V4L/DVB (7257): cx88: Add xc2028/3028 boards This patch ports a patch from Markus Rechberger to work with tuner-xc2028. It adds entries for several cx88 boards with xc2038/3028 tuners. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 4 + drivers/media/video/cx88/cx88-cards.c | 188 +++++++++++++++++++++++++++++++- drivers/media/video/cx88/cx88-dvb.c | 44 +++++++- drivers/media/video/cx88/cx88.h | 4 + 4 files changed, 238 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 7d48e3dbd074..c92795b6e697 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -58,3 +58,7 @@ 57 -> ADS Tech Instant Video PCI [1421:0390] 58 -> Pinnacle PCTV HD 800i [11bd:0051] 59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530] + 60 -> Pinnacle Hybrid PCTV [12ab:1788] + 61 -> Winfast TV2000 XP Global [107d:6f18] + 62 -> PowerColor Real Angel 330 [14f1:ea3d] + 63 -> Geniatech X8000-MT DVBT [14f1:8852] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 3e07fbe4c843..d07286fa21f5 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1426,6 +1426,124 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_PINNACLE_HYBRID_PCTV] = { + .name = "Pinnacle Hybrid PCTV", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + }, + [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { + .name = "Winfast TV2000 XP Global", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio1 = 0x0000, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio1 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + }, + [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { + .name = "PowerColor Real Angel 330", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio1 = 0x0000, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio1 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000ff, + .gpio1 = 0x0f37d, + .gpio2 = 0x00019, + .gpio3 = 0x00000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000ff, + .gpio1 = 0x0f35d, + .gpio2 = 0x00019, + .gpio3 = 0x00000, + }, + }, + [CX88_BOARD_GENIATECH_X8000_MT] = { + /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */ + .name = "Geniatech X8000-MT DVBT", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e341, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e361, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e361, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e341, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, + .mpeg = CX88_MPEG_DVB, + } }; /* ------------------------------------------------------------------ */ @@ -1743,7 +1861,23 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x18ac, .subdevice = 0xd530, .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO, - }, + }, { + .subvendor = 0x12ab, + .subdevice = 0x1788, + .card = CX88_BOARD_PINNACLE_HYBRID_PCTV, + }, { + .subvendor = 0x14f1, + .subdevice = 0xea3d, + .card = CX88_BOARD_POWERCOLOR_REAL_ANGEL, + }, { + .subvendor = 0x107d, + .subdevice = 0x6f18, + .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, + }, { + .subvendor = 0x14f1, + .subdevice = 0x8852, + .card = CX88_BOARD_GENIATECH_X8000_MT, + } }; /* ----------------------------------------------------------------------- */ @@ -1875,6 +2009,50 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) CX88_RADIO : 0; } +/* ----------------------------------------------------------------------- */ +/* some Geniatech specific stuff */ + +static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mode) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + switch (command) { + case XC2028_TUNER_RESET: + switch (INPUT(core->input).type) { + case CX88_RADIO: + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + cx_write(MO_GP1_IO, 0x101000); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + return 0; + case CX88_VMUX_DVB: + cx_write(MO_GP1_IO, 0x030302); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + cx_write(MO_GP1_IO, 0x101000); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + return 0; + default: + cx_write(MO_GP1_IO, 0x030301); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + cx_write(MO_GP1_IO, 0x101000); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + return 0; + } + } + return -EINVAL; +} + /* ----------------------------------------------------------------------- */ /* some DViCO specific stuff */ @@ -1914,6 +2092,14 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) struct i2c_algo_bit_data *i2c_algo = priv; struct cx88_core *core = i2c_algo->data; + /* Board-specific callbacks */ + switch (core->boardnr) { + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + case CX88_BOARD_GENIATECH_X8000_MT: + return cx88_xc3028_geniatech_tuner_callback(priv, command, arg); + } + switch (command) { case XC2028_TUNER_RESET: { diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 735376060df2..c786d951a04b 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -434,8 +434,16 @@ static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .tuner_callback = cx88_tuner_callback, }; +static struct zl10353_config cx88_geniatech_x8000_mt = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, +}; + + static int dvb_register(struct cx8802_dev *dev) { + int attach_xc3028 = 0; + /* init struct videobuf_dvb */ dev->dvb.name = dev->core->name; dev->ts_gen_cntrl = 0x0c; @@ -727,16 +735,50 @@ static int dvb_register(struct cx8802_dev *dev) fe->ops.tuner_ops.set_config(fe, &ctl); } break; + case CX88_BOARD_PINNACLE_HYBRID_PCTV: + dev->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_geniatech_x8000_mt, + &dev->core->i2c_adap); + attach_xc3028 = 1; + break; + case CX88_BOARD_GENIATECH_X8000_MT: + dev->ts_gen_cntrl = 0x00; + + dev->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_geniatech_x8000_mt, + &dev->core->i2c_adap); + attach_xc3028 = 1; + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); break; } if (NULL == dev->dvb.frontend) { - printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name); + printk(KERN_ERR + "%s/2: frontend initialization failed\n", + dev->core->name); return -1; } + if (attach_xc3028) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->core->i2c_adap, + .i2c_addr = 0x61, + .video_dev = dev->core, + }; + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc3028 attach failed\n", + dev->core->name); + dvb_frontend_detach(dev->dvb.frontend); + dvb_unregister_frontend(dev->dvb.frontend); + dev->dvb.frontend = NULL; + return -1; + } + } + /* Ensure all frontends negotiate bus access */ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 8121bd07a88a..5145bf2f5557 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -212,6 +212,10 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_ADSTECH_PTV_390 57 #define CX88_BOARD_PINNACLE_PCTV_HD_800i 58 #define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59 +#define CX88_BOARD_PINNACLE_HYBRID_PCTV 60 +#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61 +#define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62 +#define CX88_BOARD_GENIATECH_X8000_MT 63 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From c3b56c988729b3a2bd053d1ae98d63f76afffdf6 Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Wed, 2 Apr 2008 14:26:21 -0300 Subject: V4L/DVB (7258): Support DVB-T tuning on the DViCO FusionHDTV DVB-T Pro Add support for tuning DVB-T channels on DViCO's FusionHDTV DVB-T Pro board. The IR remote and analog tuner are not supported at this time. Some changes made by Mauro Chehab to allow merging it with some other xc3028 patches. Signed-off-by: Chris Pascoe Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 65 ++++++++++++++++++++++++++++++--- drivers/media/video/cx88/cx88-dvb.c | 23 ++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 85 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index c92795b6e697..423da1543815 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -62,3 +62,4 @@ 61 -> Winfast TV2000 XP Global [107d:6f18] 62 -> PowerColor Real Angel 330 [14f1:ea3d] 63 -> Geniatech X8000-MT DVBT [14f1:8852] + 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index d07286fa21f5..1dc70f27f7f9 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1543,7 +1543,24 @@ static const struct cx88_board cx88_boards[] = { .gpio3 = 0x00000000, }, .mpeg = CX88_MPEG_DVB, - } + }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { + .name = "DViCO FusionHDTV DVB-T PRO", + .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = { { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000067df, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000067df, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -1748,7 +1765,11 @@ static const struct cx88_subid cx88_subids[] = { .subdevice = 0xdb11, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, /* Re-branded DViCO: UltraView DVB-T Plus */ - },{ + }, { + .subvendor = 0x18ac, + .subdevice = 0xdb30, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO, + }, { .subvendor = 0x17de, .subdevice = 0x0840, .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, @@ -2009,6 +2030,28 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) CX88_RADIO : 0; } +/* ------------------------------------------------------------------- */ +/* some Divco specific stuff */ +static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg) +{ + struct cx88_core *core = ptr; + + switch (command) { + case XC2028_TUNER_RESET: + cx_set(MO_GP0_IO, 0x0200); + cx_clear(MO_GP0_IO, 0x02); + mdelay(100); + cx_set(MO_GP0_IO, 0x02); + mdelay(100); + break; + default: + return -EINVAL; + } + + return 0; +} + + /* ----------------------------------------------------------------------- */ /* some Geniatech specific stuff */ @@ -2098,6 +2141,8 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: return cx88_xc3028_geniatech_tuner_callback(priv, command, arg); + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + return cx88_dvico_xc2028_callback(priv, command, arg); } switch (command) { @@ -2267,6 +2312,7 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: /* GPIO0:0 is hooked to mt352 reset pin */ cx_set(MO_GP0_IO, 0x00000101); cx_clear(MO_GP0_IO, 0x00000001); @@ -2338,9 +2384,18 @@ static void cx88_card_setup(struct cx88_core *core) ctl.fname = XC2028_DEFAULT_FIRMWARE; ctl.max_len = 64; - /* FIXME: Those should be device-dependent */ - ctl.demod = XC3028_FE_OREN538; - ctl.mts = 1; + + switch (core->boardnr) { + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + ctl.scode_table = XC3028_FE_ZARLINK456; + break; + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + ctl.demod = XC3028_FE_OREN538; + break; + default: + ctl.demod = XC3028_FE_OREN538; + ctl.mts = 1; + } xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index c786d951a04b..591037d8d14f 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -237,6 +237,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = { .no_tuner = 1, }; +static struct zl10353_config dvico_fusionhdtv_xc3028 = { + .demod_address = 0x0f, + .if2 = 45600, + .no_tuner = 1, +}; + +static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = { + .demod_address = 0x0f, + .if2 = 4560, + .no_tuner = 1, + .demod_init = dvico_fusionhdtv_demod_init, +}; + static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { .demod_address = 0x0f, }; @@ -567,6 +580,16 @@ static int dvb_register(struct cx8802_dev *dev) DVB_PLL_THOMSON_FE6600); } break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + dev->dvb.frontend = dvb_attach(zl10353_attach, + &dvico_fusionhdtv_xc3028, + &dev->core->i2c_adap); + if (dev->dvb.frontend == NULL) + dev->dvb.frontend = dvb_attach(mt352_attach, + &dvico_fusionhdtv_mt352_xc3028, + &dev->core->i2c_adap); + attach_xc3028 = 1; + break; case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &dev->core->i2c_adap); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 5145bf2f5557..9df3f198a4df 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -216,6 +216,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61 #define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62 #define CX88_BOARD_GENIATECH_X8000_MT 63 +#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From a55472e47f05aaf918a987fb22982a5feb39733f Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Wed, 2 Apr 2008 14:26:22 -0300 Subject: V4L/DVB (7259): FusionHDTV DVB-T Pro tuning problem fixes It seems that on this board, the demodulator provides the pullup on the I2C bus, which means that calling i2c_gate_ctrl crashes the bus. Turn this off and the xc3028 can talk OK. Also fix some GPIO related settings that became more clear through working on this. Some changes made by Mauro Chehab to allow merging it with some other xc3028 patches. Signed-off-by: Chris Pascoe Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 16 ++++++++++------ drivers/media/video/cx88/cx88-dvb.c | 8 ++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 1dc70f27f7f9..1fe6b9da9815 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2038,11 +2038,9 @@ static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg) switch (command) { case XC2028_TUNER_RESET: - cx_set(MO_GP0_IO, 0x0200); - cx_clear(MO_GP0_IO, 0x02); - mdelay(100); - cx_set(MO_GP0_IO, 0x02); - mdelay(100); + cx_write(MO_GP0_IO, 0x101000); + mdelay(5); + cx_set(MO_GP0_IO, 0x101010); break; default: return -EINVAL; @@ -2302,6 +2300,13 @@ static void cx88_card_setup(struct cx88_core *core) cx_write(MO_GP0_IO, 0x000007f8); cx_write(MO_GP1_IO, 0x00000001); break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + /* GPIO0:0 is hooked to demod reset */ + /* GPIO0:4 is hooked to xc3028 reset */ + cx_write(MO_GP0_IO, 0x00111100); + msleep(1); + cx_write(MO_GP0_IO, 0x00111111); + break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* GPIO0:6 is hooked to FX2 reset pin */ cx_set(MO_GP0_IO, 0x00004040); @@ -2312,7 +2317,6 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: /* GPIO0:0 is hooked to mt352 reset pin */ cx_set(MO_GP0_IO, 0x00000101); cx_clear(MO_GP0_IO, 0x00000001); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 591037d8d14f..ae2a0f5f0806 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -588,6 +588,14 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_mt352_xc3028, &dev->core->i2c_adap); + /* + * On this board, the demod provides the I2C bus pullup. + * We must not permit gate_ctrl to be performed, or + * the xc3028 cannot communicate on the bus. + */ + if (dev->dvb.frontend) + dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; + attach_xc3028 = 1; break; case CX88_BOARD_PCHDTV_HD3000: -- cgit v1.2.3 From bdfdae6cb5337b5da3ab1d49ac9bebe393c049ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:22 -0300 Subject: V4L/DVB (7260): tuner-xc3028: Don't check return code for clock reset Only tm6000 needs to be aware when a frequency is being changed. This seems to improve channel change detection. Other bridges don't need this. So, better to discard any errors if this fails, and proceed changing the channels. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-xc2028.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 42dc2c6ccbbf..a9caae1af49d 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -904,9 +904,11 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, if (rc < 0) goto ret; - rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); - if (rc < 0) - goto ret; + /* Return code shouldn't be checked. + The reset CLK is needed only with tm6000. + Driver should work fine even if this fails. + */ + priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); msleep(10); -- cgit v1.2.3 From bdd9d92cca29bb88076ee1402744b27ad6870a2f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:23 -0300 Subject: V4L/DVB (7261): Use the same callback argument as xc3028 and xc5000 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda827x.c | 6 ++---- drivers/media/video/saa7134/saa7134-core.c | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index 3190c8d0c17c..967ac8b28efd 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -578,8 +578,7 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, else arg = 0; if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv->i2c_adap->algo_data, - 1, arg); + priv->cfg->tuner_callback(priv, 1, arg); buf[1] = high ? 0 : 1; if (*priv->cfg->config == 2) buf[1] = high ? 1 : 0; @@ -587,8 +586,7 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, break; case 3: /* switch with GPIO of saa713x */ if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv->i2c_adap->algo_data, - 0, high); + priv->cfg->tuner_callback(priv, 0, high); break; } } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index ef1fd5a93b1b..4817a0e046a8 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -145,7 +145,8 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value) int saa7134_tuner_callback(void *ptr, int command, int arg) { u8 sync_control; - struct saa7134_dev *dev = ptr; + struct i2c_algo_bit_data *i2c_algo = priv; + struct saa7134_dev *dev = i2c_algo->data; switch (dev->tuner_type) { case TUNER_PHILIPS_TDA8290: -- cgit v1.2.3 From 42da2c21fbe24f5052440a5f2ce2edcf7a3ed347 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:23 -0300 Subject: V4L/DVB (7262): Add support for xc3028-based boards This patch adds support for the following saa7134 xc3028 based boards: 132 -> AVerMedia Cardbus TV/Radio (E506R) [1461:f436] 133 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936] 134 -> Avermedia M115 [1461:a836] 135 -> Compro VideoMate T750 [185b:c900] This is based on a original patch thanks to Markus Rechberger that added xc3028 gpio init code for the above boards. This patch moves saa7134_tuner_callback to saa7134-cards, originally used only by tda8290 DVB-S boards. The callback was made more generic to support other tuners. Currently, it supports both tda8290 and xc2028/xc3028 tuners. Added also the basis for xc5000 tuner callback. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 4 + drivers/media/video/saa7134/saa7134-cards.c | 230 ++++++++++++++++++++++++++-- drivers/media/video/saa7134/saa7134-core.c | 34 ---- drivers/media/video/saa7134/saa7134-dvb.c | 32 ++++ drivers/media/video/saa7134/saa7134.h | 7 +- 5 files changed, 259 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 765a06b1f0f6..c1f9f138d1bb 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -134,3 +134,7 @@ 133 -> NXP Snake DVB-S reference design 134 -> Medion/Creatix CTX953 Hybrid [16be:0010] 135 -> MSI TV@nywhere A/D v1.1 [1462:8625] +136 -> AVerMedia Cardbus TV/Radio (E506R) [1461:f436] +137 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936] +138 -> Avermedia M115 [1461:a836] +139 -> Compro VideoMate T750 [185b:c900] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index f9c85b7cba1a..6fde042ee317 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -22,9 +22,12 @@ #include #include +#include +#include #include "saa7134-reg.h" #include "saa7134.h" +#include "tuner-xc2028.h" #include #include @@ -4064,6 +4067,97 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = { + .name = "AVerMedia Cardbus TV/Radio (E506R)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + /* + TODO: + .mpeg = SAA7134_MPEG_DVB, + */ + + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + }, + }, + [SAA7134_BOARD_AVERMEDIA_A16D] = { + .name = "AVerMedia Hybrid TV/Radio (A16D)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE1, + }, + }, + [SAA7134_BOARD_AVERMEDIA_M115] = { + .name = "Avermedia M115", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + }, + [SAA7134_BOARD_VIDEOMATE_T750] = { + /* John Newbigin */ + .name = "Compro VideoMate T750", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_XC2028, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = TV, + } + } }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5027,6 +5121,30 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x8625, /* TV@nywhere A/D v1.1 */ .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf436, + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_506, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf936, + .driver_data = SAA7134_BOARD_AVERMEDIA_A16D, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa836, + .driver_data = SAA7134_BOARD_AVERMEDIA_M115, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x185b, + .subdevice = 0xc900, + .driver_data = SAA7134_BOARD_VIDEOMATE_T750, + }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -5082,6 +5200,67 @@ static void board_flyvideo(struct saa7134_dev *dev) dev->name, dev->name, dev->name); } +static int saa7134_xc2028_callback(struct saa7134_dev *dev, + int command, int arg) +{ + switch (command) { + case XC2028_TUNER_RESET: + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); + saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02); + saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81); + saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7); + saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03); + saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2, + 0x0001e000, 0x0001e000); + return 0; + } + return -EINVAL; +} + + +static int saa7134_tda8290_callback(struct saa7134_dev *dev, + int command, int arg) +{ + u8 sync_control; + + switch (command) { + case 0: /* switch LNA gain through GPIO 22*/ + saa7134_set_gpio(dev, 22, arg) ; + break; + case 1: /* vsync output at GPIO22. 50 / 60Hz */ + saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80); + saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03); + if (arg == 1) + sync_control = 11; + else + sync_control = 17; + saa_writeb(SAA7134_VGATE_START, sync_control); + saa_writeb(SAA7134_VGATE_STOP, sync_control + 1); + saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00); + break; + default: + return -EINVAL; + } + + return 0; +} + +int saa7134_tuner_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct saa7134_dev *dev = i2c_algo->data; + + switch (dev->tuner_type) { + case TUNER_PHILIPS_TDA8290: + return saa7134_tda8290_callback(dev, command, arg); + case TUNER_XC2028: + return saa7134_xc2028_callback(dev, command, arg); + } + return -EINVAL; +} +EXPORT_SYMBOL(saa7134_tuner_callback); + /* ----------------------------------------------------------- */ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) @@ -5151,6 +5330,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: + case SAA7134_BOARD_VIDEOMATE_T750: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: @@ -5217,6 +5397,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000); break; case SAA7134_BOARD_AVERMEDIA_CARDBUS: + case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + case SAA7134_BOARD_AVERMEDIA_M115: case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0xffffffff); @@ -5284,11 +5466,16 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->tuner_type = saa7134_boards[dev->board].tuner_type; if (TUNER_ABSENT != dev->tuner_type) { - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; - tun_setup.type = dev->tuner_type; - tun_setup.addr = ADDR_UNSET; + tun_setup.mode_mask = T_RADIO | + T_ANALOG_TV | + T_DIGITAL_TV; + tun_setup.type = dev->tuner_type; + tun_setup.addr = ADDR_UNSET; + tun_setup.tuner_callback = saa7134_tuner_callback; - saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup); + saa7134_i2c_call_clients(dev, + TUNER_SET_TYPE_ADDR, + &tun_setup); } break; case SAA7134_BOARD_MD7134: @@ -5359,11 +5546,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) &tda9887_cfg); } - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_RADIO | + T_ANALOG_TV | + T_DIGITAL_TV; tun_setup.type = dev->tuner_type; tun_setup.addr = ADDR_UNSET; - saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); + saa7134_i2c_call_clients(dev, + TUNER_SET_TYPE_ADDR, &tun_setup); } break; case SAA7134_BOARD_PHILIPS_EUROPA: @@ -5496,12 +5686,26 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; } + + if (dev->tuner_type == TUNER_XC2028) { + struct v4l2_priv_tun_config xc2028_cfg; + struct xc2028_ctrl ctl; + + memset(&xc2028_cfg, 0, sizeof(ctl)); + memset(&ctl, 0, sizeof(ctl)); + + ctl.fname = XC2028_DEFAULT_FIRMWARE; + ctl.max_len = 64; + + /* FIXME: This should be device-dependent */ + ctl.demod = XC3028_FE_OREN538; + ctl.mts = 1; + + xc2028_cfg.tuner = TUNER_XC2028; + xc2028_cfg.priv = &ctl; + + saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); + } + return 0; } - -/* ----------------------------------------------------------- */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 4817a0e046a8..ed96ce775a9b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -142,40 +142,6 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value) } } -int saa7134_tuner_callback(void *ptr, int command, int arg) -{ - u8 sync_control; - struct i2c_algo_bit_data *i2c_algo = priv; - struct saa7134_dev *dev = i2c_algo->data; - - switch (dev->tuner_type) { - case TUNER_PHILIPS_TDA8290: - switch (command) { - case 0: /* switch LNA gain through GPIO 22*/ - saa7134_set_gpio(dev, 22, arg) ; - break; - case 1: /* vsync output at GPIO22. 50 / 60Hz */ - dprintk("setting GPIO22 to vsync %d\n", arg); - saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80); - saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03); - if (arg == 1) - sync_control = 11; - else - sync_control = 17; - saa_writeb(SAA7134_VGATE_START, sync_control); - saa_writeb(SAA7134_VGATE_STOP, sync_control + 1); - saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00); - break; - default: - return -EINVAL; - } - break; - default: - return -ENODEV; - } - return 0; -} - /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index eabc67d03b2c..97d9178dca2b 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -38,6 +38,7 @@ #include "mt352_priv.h" /* FIXME */ #include "tda1004x.h" #include "nxt200x.h" +#include "tuner-xc2028.h" #include "tda10086.h" #include "tda826x.h" @@ -190,6 +191,11 @@ static struct mt352_config avermedia_777 = { .demod_init = mt352_aver777_init, }; +static struct mt352_config avermedia_e506r_mt352_dev = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, +}; + /* ================================================================== * tda1004x based DVB-T cards, helper functions */ @@ -895,6 +901,8 @@ static struct nxt200x_config kworldatsc110 = { static int dvb_init(struct saa7134_dev *dev) { int ret; + int attach_xc3028 = 0; + /* init struct videobuf_dvb */ dev->ts.nr_bufs = 32; dev->ts.nr_packets = 32*4; @@ -1142,11 +1150,35 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_MSI_TVANYWHERE_AD11: configure_tda827x_fe(dev, &philips_tiger_s_config); break; + case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + dev->dvb.frontend = dvb_attach(mt352_attach, + &avermedia_e506r_mt352_dev, + &dev->i2c_adap); + attach_xc3028 = 1; + break; default: wprintk("Huh? unknown DVB card?\n"); break; } + if (attach_xc3028) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->i2c_adap, + .i2c_addr = 0x61, + .video_dev = dev, + }; + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc3028 attach failed\n", + dev->name); + dvb_frontend_detach(dev->dvb.frontend); + dvb_unregister_frontend(dev->dvb.frontend); + dev->dvb.frontend = NULL; + return -1; + } + } + if (NULL == dev->dvb.frontend) { printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); return -1; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index d7e0781fe8a1..ba88a1093d14 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -257,6 +257,11 @@ struct saa7134_format { #define SAA7134_BOARD_PHILIPS_SNAKE 133 #define SAA7134_BOARD_CREATIX_CTX953 134 #define SAA7134_BOARD_MSI_TVANYWHERE_AD11 135 +#define SAA7134_BOARD_AVERMEDIA_CARDBUS_506 136 +#define SAA7134_BOARD_AVERMEDIA_A16D 137 +#define SAA7134_BOARD_AVERMEDIA_M115 138 +#define SAA7134_BOARD_VIDEOMATE_T750 139 + #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -599,7 +604,6 @@ extern int saa7134_no_overlay; void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value); -int saa7134_tuner_callback(void *ptr, int command, int arg); #define SAA7134_PGTABLE_SIZE 4096 @@ -636,6 +640,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[]; extern int saa7134_board_init1(struct saa7134_dev *dev); extern int saa7134_board_init2(struct saa7134_dev *dev); +int saa7134_tuner_callback(void *priv, int command, int arg); /* ----------------------------------------------------------- */ -- cgit v1.2.3 From 6525182fcbacdb31d7c6d636bf0d3a716a3d9423 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:23 -0300 Subject: V4L/DVB (7263): Some cleanups at cx88 callback methods Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 57 ++++++++++++----------------------- 1 file changed, 19 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 1fe6b9da9815..fc870882ffe2 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2062,34 +2062,22 @@ static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mod case XC2028_TUNER_RESET: switch (INPUT(core->input).type) { case CX88_RADIO: - cx_write(MO_GP1_IO, 0x101010); - mdelay(50); - cx_write(MO_GP1_IO, 0x101000); - mdelay(50); - cx_write(MO_GP1_IO, 0x101010); - mdelay(50); - return 0; + break; case CX88_VMUX_DVB: cx_write(MO_GP1_IO, 0x030302); mdelay(50); - cx_write(MO_GP1_IO, 0x101010); - mdelay(50); - cx_write(MO_GP1_IO, 0x101000); - mdelay(50); - cx_write(MO_GP1_IO, 0x101010); - mdelay(50); - return 0; + break; default: cx_write(MO_GP1_IO, 0x030301); mdelay(50); - cx_write(MO_GP1_IO, 0x101010); - mdelay(50); - cx_write(MO_GP1_IO, 0x101000); - mdelay(50); - cx_write(MO_GP1_IO, 0x101010); - mdelay(50); - return 0; - } + } + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + cx_write(MO_GP1_IO, 0x101000); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + return 0; } return -EINVAL; } @@ -2145,7 +2133,6 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) switch (command) { case XC2028_TUNER_RESET: - { switch (INPUT(core->input).type) { case CX88_RADIO: printk(KERN_INFO "setting GPIO to radio!\n"); @@ -2153,25 +2140,19 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) mdelay(250); cx_write(MO_GP2_IO, 0xff); mdelay(250); - cx_write(MO_GP1_IO, 0x101010); - mdelay(250); - cx_write(MO_GP1_IO, 0x101000); - mdelay(250); - cx_write(MO_GP1_IO, 0x101010); - mdelay(250); - return 0; + break; case CX88_VMUX_DVB: /* Digital TV*/ default: /* Analog TV */ printk(KERN_INFO "setting GPIO to TV!\n"); - cx_write(MO_GP1_IO, 0x101010); - mdelay(250); - cx_write(MO_GP1_IO, 0x101000); - mdelay(250); - cx_write(MO_GP1_IO, 0x101010); - mdelay(250); - return 0; + break; } - } + cx_write(MO_GP1_IO, 0x101010); + mdelay(250); + cx_write(MO_GP1_IO, 0x101000); + mdelay(250); + cx_write(MO_GP1_IO, 0x101010); + mdelay(250); + return 0; } return -EINVAL; } -- cgit v1.2.3 From 7cf2a91cffea723546a5f5a239abc0e3a011cb36 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:24 -0300 Subject: V4L/DVB (7264): cx88-cards: always use a level on printk messages Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 71 ++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index fc870882ffe2..2429cfe31554 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -45,6 +45,16 @@ static unsigned int latency = UNSET; module_param(latency,int,0444); MODULE_PARM_DESC(latency,"pci latency timer"); +#define info_printk(core, fmt, arg...) \ + printk(KERN_INFO "%s: " fmt, core->name , ## arg) + +#define warn_printk(core, fmt, arg...) \ + printk(KERN_WARNING "%s: " fmt, core->name , ## arg) + +#define err_printk(core, fmt, arg...) \ + printk(KERN_ERR "%s: " fmt, core->name , ## arg) + + /* ------------------------------------------------------------------ */ /* board config info */ @@ -1915,17 +1925,16 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) if (eeprom_data[4] != 0x7d || eeprom_data[5] != 0x10 || eeprom_data[7] != 0x66) { - printk(KERN_WARNING "%s: Leadtek eeprom invalid.\n", - core->name); + warn_printk(core, "Leadtek eeprom invalid.\n"); return; } core->board.tuner_type = (eeprom_data[6] == 0x13) ? TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3; - printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: " - "tuner=%d, eeprom[0]=0x%02x\n", - core->name, core->board.tuner_type, eeprom_data[0]); + info_printk(core, "Leadtek Winfast 2000XP Expert config: " + "tuner=%d, eeprom[0]=0x%02x\n", + core->board.tuner_type, eeprom_data[0]); } static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) @@ -1969,13 +1978,12 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) /* known */ break; default: - printk("%s: warning: unknown hauppauge model #%d\n", - core->name, tv.model); + warn_printk(core, "warning: unknown hauppauge model #%d\n", + tv.model); break; } - printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", - core->name, tv.model); + info_printk(core, "hauppauge eeprom: model=%d\n", tv.model); } /* ----------------------------------------------------------------------- */ @@ -2021,8 +2029,7 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner)) ? gdi_tuner[eeprom_data[0x0d]].name : NULL; - printk(KERN_INFO "%s: GDI: tuner=%s\n", core->name, - name ? name : "unknown"); + info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown"); if (NULL == name) return; core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id; @@ -2110,7 +2117,8 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) msg.len = (i != 12 ? 5 : 2); err = i2c_transfer(&core->i2c_adap, &msg, 1); if (err != 1) { - printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err); + warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d " + "failed (err = %d)!\n", i, err); return; } } @@ -2135,7 +2143,7 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) case XC2028_TUNER_RESET: switch (INPUT(core->input).type) { case CX88_RADIO: - printk(KERN_INFO "setting GPIO to radio!\n"); + info_printk(core, "setting GPIO to radio!\n"); cx_write(MO_GP0_IO, 0x4ff); mdelay(250); cx_write(MO_GP2_IO, 0xff); @@ -2143,7 +2151,7 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) break; case CX88_VMUX_DVB: /* Digital TV*/ default: /* Analog TV */ - printk(KERN_INFO "setting GPIO to TV!\n"); + info_printk(core, "setting GPIO to TV!\n"); break; } cx_write(MO_GP1_IO, 0x101010); @@ -2176,8 +2184,8 @@ static int cx88_xc5000_tuner_callback(void *priv, int command, int arg) cx_write(MO_SRST_IO, 1); return 0; } else { - printk(KERN_ERR - "xc5000: unknown tuner callback command.\n"); + err_printk(core, "xc5000: unknown tuner " + "callback command.\n"); return -EINVAL; } break; @@ -2192,10 +2200,14 @@ int cx88_tuner_callback(void *priv, int command, int arg) switch (core->board.tuner_type) { case TUNER_XC2028: + info_printk(core, "Calling XC2028/3028 callback\n"); return cx88_xc2028_tuner_callback(priv, command, arg); case TUNER_XC5000: + info_printk(core, "Calling XC5000 callback\n"); return cx88_xc5000_tuner_callback(priv, command, arg); } + err_printk(core, "Error: Calling callback for tuner %d\n", + core->board.tuner_type); return -EINVAL; } EXPORT_SYMBOL(cx88_tuner_callback); @@ -2208,23 +2220,25 @@ static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) if (0 == pci->subsystem_vendor && 0 == pci->subsystem_device) { - printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n" + printk(KERN_ERR + "%s: Your board has no valid PCI Subsystem ID and thus can't\n" "%s: be autodetected. Please pass card= insmod option to\n" "%s: workaround that. Redirect complaints to the vendor of\n" "%s: the TV card. Best regards,\n" "%s: -- tux\n", core->name,core->name,core->name,core->name,core->name); } else { - printk("%s: Your board isn't known (yet) to the driver. You can\n" + printk(KERN_ERR + "%s: Your board isn't known (yet) to the driver. You can\n" "%s: try to pick one of the existing card configs via\n" "%s: card= insmod option. Updating to the latest\n" "%s: version might help as well.\n", core->name,core->name,core->name,core->name); } - printk("%s: Here is a list of valid choices for the card= insmod option:\n", - core->name); + err_printk(core, "Here is a list of valid choices for the card= " + "insmod option:\n"); for (i = 0; i < ARRAY_SIZE(cx88_boards); i++) - printk("%s: card=%d -> %s\n", + printk(KERN_ERR "%s: card=%d -> %s\n", core->name, i, cx88_boards[i].name); } @@ -2335,10 +2349,8 @@ static void cx88_card_setup(struct cx88_core *core) for (i = 0; i < ARRAY_SIZE(buffer); i++) if (2 != i2c_master_send(&core->i2c_client, buffer[i],2)) - printk(KERN_WARNING - "%s: Unable to enable " - "tuner(%i).\n", - core->name, i); + warn_printk(core, "Unable to enable " + "tuner(%i).\n", i); } break; case CX88_BOARD_MSI_TVANYWHERE_MASTER: @@ -2504,9 +2516,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board)); - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", - core->name,pci->subsystem_vendor, - pci->subsystem_device, core->board.name, + info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + pci->subsystem_vendor, pci->subsystem_device, core->board.name, core->boardnr, card[core->nr] == core->boardnr ? "insmod option" : "autodetected"); @@ -2515,8 +2526,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) if (radio[core->nr] != UNSET) core->board.radio_type = radio[core->nr]; - printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n", - core->name, core->board.tuner_type, core->board.radio_type); + info_printk(core, "TV tuner type %d, Radio tuner type %d\n", + core->board.tuner_type, core->board.radio_type); /* init hardware */ cx88_reset(core); -- cgit v1.2.3 From a58a5f3ac7434a5ae2de633bbfde4341cdf5928c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:24 -0300 Subject: V4L/DVB (7265): cx88: prints an info when xc2028 is set or is attached Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 3 ++- drivers/media/video/cx88/cx88-dvb.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 2429cfe31554..350c402920e7 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2397,9 +2397,10 @@ static void cx88_card_setup(struct cx88_core *core) xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; + info_printk(core, "Asking xc2028/3028 to load firmware %s\n", + ctl.fname); cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); } - } /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index ae2a0f5f0806..ef83dab72410 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -808,6 +808,8 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend = NULL; return -1; } + printk(KERN_INFO "%s/2: xc3028 attached\n", + dev->core->name); } /* Ensure all frontends negotiate bus access */ -- cgit v1.2.3 From 1e20e7474f1078e93942974c7483d4b46019bf7c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:24 -0300 Subject: V4L/DVB (7266): cx88-dvb: convert attach_xc3028 into a function Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 58 ++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index ef83dab72410..59180cab0a85 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -452,11 +452,33 @@ static struct zl10353_config cx88_geniatech_x8000_mt = { .no_tuner = 1, }; +static int attach_xc3028(u8 addr, struct cx8802_dev *dev) +{ + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->core->i2c_adap, + .i2c_addr = addr, + .video_dev = dev->core, + }; + + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc3028 attach failed\n", + dev->core->name); + dvb_frontend_detach(dev->dvb.frontend); + dvb_unregister_frontend(dev->dvb.frontend); + dev->dvb.frontend = NULL; + return -EINVAL; + } + + printk(KERN_INFO "%s/2: xc3028 attached\n", + dev->core->name); + + return 0; +} static int dvb_register(struct cx8802_dev *dev) { - int attach_xc3028 = 0; - /* init struct videobuf_dvb */ dev->dvb.name = dev->core->name; dev->ts_gen_cntrl = 0x0c; @@ -595,8 +617,8 @@ static int dvb_register(struct cx8802_dev *dev) */ if (dev->dvb.frontend) dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; - - attach_xc3028 = 1; + if (attach_xc3028(0x61, dev) < 0) + return -EINVAL; break; case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, @@ -770,7 +792,8 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, &dev->core->i2c_adap); - attach_xc3028 = 1; + if (attach_xc3028(0x61, dev) < 0) + return -EINVAL; break; case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; @@ -778,7 +801,8 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, &dev->core->i2c_adap); - attach_xc3028 = 1; + if (attach_xc3028(0x61, dev) < 0) + return -EINVAL; break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", @@ -789,27 +813,7 @@ static int dvb_register(struct cx8802_dev *dev) printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name); - return -1; - } - - if (attach_xc3028) { - struct dvb_frontend *fe; - struct xc2028_config cfg = { - .i2c_adap = &dev->core->i2c_adap, - .i2c_addr = 0x61, - .video_dev = dev->core, - }; - fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); - if (!fe) { - printk(KERN_ERR "%s/2: xc3028 attach failed\n", - dev->core->name); - dvb_frontend_detach(dev->dvb.frontend); - dvb_unregister_frontend(dev->dvb.frontend); - dev->dvb.frontend = NULL; - return -1; - } - printk(KERN_INFO "%s/2: xc3028 attached\n", - dev->core->name); + return -EINVAL; } /* Ensure all frontends negotiate bus access */ -- cgit v1.2.3 From dc2a2e20adf4d30ac322654b3773810a4669086f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:25 -0300 Subject: V4L/DVB (7269): cx88: Powercolor Angel works only with firmware version 2.5 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 350c402920e7..dbfaabb3e2e2 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2383,6 +2383,10 @@ static void cx88_card_setup(struct cx88_core *core) ctl.max_len = 64; switch (core->boardnr) { + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + /* Doesn't work with firmware version 2.7 */ + ctl.fname = "xc3028-v25.fw"; + break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: ctl.scode_table = XC3028_FE_ZARLINK456; break; -- cgit v1.2.3 From c28f77cb69c998b088444fb998b4d3675a4a9c6c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:25 -0300 Subject: V4L/DVB (7270): cx88-dvb: Renames pci_nano callback This callback is specific to pci_nano, since supports only dvb. Renames it to avoid future mistakes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 59180cab0a85..cf6b9b05f496 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -372,7 +372,7 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, return 0; } -static int cx88_xc3028_callback(void *ptr, int command, int arg) +static int cx88_pci_nano_callback(void *ptr, int command, int arg) { struct cx88_core *core = ptr; @@ -774,7 +774,7 @@ static int dvb_register(struct cx8802_dev *dev) .i2c_adap = &dev->core->i2c_adap, .i2c_addr = 0x61, .video_dev = dev->core, - .callback = cx88_xc3028_callback, + .callback = cx88_pci_nano_callback, }; static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", -- cgit v1.2.3 From 7534fb48a2ffc1d4860cd75ba02a167cf0dd168a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:26:25 -0300 Subject: V4L/DVB (7271): cx88-cards: Fix powerangel gpio1 With this gpio, audio works properly. Thanks to Daniel Fraga for helping on fixing the code for Powerangel Real board. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index dbfaabb3e2e2..bf58f350e269 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1494,7 +1494,7 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ - .gpio1 = 0x0000, + .gpio1 = 0xf35d, .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ }, { .type = CX88_VMUX_COMPOSITE1, -- cgit v1.2.3 From 1f512ae40b5c51607fabf4886fad42cdc9a17655 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 2 Apr 2008 14:26:26 -0300 Subject: V4L/DVB (7272): V4L: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser CC: Luca Risolia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sn9c102/sn9c102_sensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 2d7d786b8430..2dc7c6869484 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -126,7 +126,7 @@ extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2], Register adresses must be < 256. */ #define sn9c102_write_const_regs(sn9c102_device, data...) \ - ({ const static u8 _valreg[][2] = {data}; \ + ({ static const u8 _valreg[][2] = {data}; \ sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); }) /*****************************************************************************/ -- cgit v1.2.3 From e7cd60c5fc7c3a6f8326c8e54505244d8c886d46 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Apr 2008 14:26:26 -0300 Subject: V4L/DVB (7273): suppress compound statement warning in dvb-bt8xx.c Prevailing kernel style seems to prefer always using braces for do {} while (). Add braces to dprintk to suppress the sparse warnings: drivers/media/dvb/bt8xx/dvb-bt8xx.c:73:2: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:93:2: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:529:2: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:614:4: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:629:4: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:639:4: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:883:2: warning: do-while statement is not a compound statement drivers/media/dvb/bt8xx/dvb-bt8xx.c:917:2: warning: do-while statement is not a compound statement Signed-off-by: Harvey Harrison Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index dedd30a8356b..209356be5828 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -41,9 +41,9 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk( args... ) \ - do \ + do { \ if (debug) printk(KERN_DEBUG args); \ - while (0) + } while (0) #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ -- cgit v1.2.3 From 110cd6b55b202af49d8f5bbc5738d55ac5886bc8 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Apr 2008 14:26:26 -0300 Subject: V4L/DVB (7274): dabusb: fix shadowed variable warning in dabusb.c drivers/media/video/dabusb.c:208:6: warning: symbol 'buffers' shadows an earlier one drivers/media/video/dabusb.c:63:12: originally declared here Signed-off-by: Harvey Harrison Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/dabusb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index a5731f90be0f..8d1f8ee2a533 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -205,7 +205,7 @@ static void dabusb_iso_complete (struct urb *purb) /*-------------------------------------------------------------------*/ static int dabusb_alloc_buffers (pdabusb_t s) { - int buffers = 0; + int transfer_len = 0; pbuff_t b; unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); @@ -216,7 +216,7 @@ static int dabusb_alloc_buffers (pdabusb_t s) dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d", pipesize, packets, transfer_buffer_length); - while (buffers < (s->total_buffer_size << 10)) { + while (transfer_len < (s->total_buffer_size << 10)) { b = kzalloc(sizeof (buff_t), GFP_KERNEL); if (!b) { err("kzalloc(sizeof(buff_t))==NULL"); @@ -251,10 +251,10 @@ static int dabusb_alloc_buffers (pdabusb_t s) b->purb->iso_frame_desc[i].length = pipesize; } - buffers += transfer_buffer_length; + transfer_len += transfer_buffer_length; list_add_tail (&b->buff_list, &s->free_buff_list); } - s->got_mem = buffers; + s->got_mem = transfer_len; return 0; -- cgit v1.2.3 From 1d1be38686e24bf5a46f495599f955ac9b816e8c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:26:26 -0300 Subject: V4L/DVB (7276): soc-camera: deactivate cameras when not used Only attach cameras to the host interface for probing, then detach until open. This allows platforms with several cameras on an interface, physically supporting only one camera, to handle multiple cameras and activate them selectively after initial probing. The first attach during probe is needed to activate the host interface to be able to physically communicate with cameras. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 52 ++++++++++++++++++++++++++++++---------- include/media/soc_camera.h | 2 ++ 2 files changed, 41 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index c947525c3f2f..322f837bcfea 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -179,11 +179,9 @@ static int soc_camera_dqbuf(struct file *file, void *priv, static int soc_camera_open(struct inode *inode, struct file *file) { - struct video_device *vdev = video_devdata(file); - struct soc_camera_device *icd = container_of(vdev->dev, - struct soc_camera_device, dev); - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct video_device *vdev; + struct soc_camera_device *icd; + struct soc_camera_host *ici; struct soc_camera_file *icf; int ret; @@ -191,7 +189,12 @@ static int soc_camera_open(struct inode *inode, struct file *file) if (!icf) return -ENOMEM; - icf->icd = icd; + /* Protect against icd->remove() until we module_get() both drivers. */ + mutex_lock(&video_lock); + + vdev = video_devdata(file); + icd = container_of(vdev->dev, struct soc_camera_device, dev); + ici = to_soc_camera_host(icd->dev.parent); if (!try_module_get(icd->ops->owner)) { dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); @@ -205,6 +208,22 @@ static int soc_camera_open(struct inode *inode, struct file *file) goto emgi; } + icd->use_count++; + + icf->icd = icd; + + /* Now we really have to activate the camera */ + if (icd->use_count == 1) { + ret = ici->add(icd); + if (ret < 0) { + dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); + icd->use_count--; + goto eiciadd; + } + } + + mutex_unlock(&video_lock); + file->private_data = icf; dev_dbg(&icd->dev, "camera device open\n"); @@ -216,9 +235,13 @@ static int soc_camera_open(struct inode *inode, struct file *file) return 0; + /* All errors are entered with the video_lock held */ +eiciadd: + module_put(ici->owner); emgi: module_put(icd->ops->owner); emgd: + mutex_unlock(&video_lock); vfree(icf); return ret; } @@ -230,8 +253,14 @@ static int soc_camera_close(struct inode *inode, struct file *file) struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct video_device *vdev = icd->vdev; + mutex_lock(&video_lock); + icd->use_count--; + if (!icd->use_count) + ici->remove(icd); module_put(icd->ops->owner); module_put(ici->owner); + mutex_unlock(&video_lock); + vfree(file->private_data); dev_dbg(vdev->dev, "camera device close\n"); @@ -673,14 +702,14 @@ static int soc_camera_probe(struct device *dev) if (!icd->probe) return -ENODEV; + /* We only call ->add() here to activate and probe the camera. + * We shall ->remove() and deactivate it immediately afterwards. */ ret = ici->add(icd); if (ret < 0) return ret; ret = icd->probe(icd); - if (ret < 0) - ici->remove(icd); - else { + if (ret >= 0) { const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); @@ -689,6 +718,7 @@ static int soc_camera_probe(struct device *dev) icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; } + ici->remove(icd); return ret; } @@ -698,14 +728,10 @@ static int soc_camera_probe(struct device *dev) static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); if (icd->remove) icd->remove(icd); - ici->remove(icd); - return 0; } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 69aba7188e44..c886b1e64872 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -41,6 +41,8 @@ struct soc_camera_device { int (*probe)(struct soc_camera_device *icd); void (*remove)(struct soc_camera_device *icd); struct module *owner; + /* soc_camera.c private count. Only accessed with video_lock held */ + int use_count; }; struct soc_camera_file { -- cgit v1.2.3 From 3582f8523563e0debe1da320aed329b1c2085a29 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 14:27:39 -0300 Subject: V4L/DVB (7281): v4l: Deadlock in videobuf-core for DQBUF waiting on QBUF Avoid a deadlock where DQBUF is holding the vb_lock while waiting on a QBUF which also needs the vb_lock. Reported by Hans Verkuil . Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index eab79ffdf56a..5ea635fac236 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -605,7 +605,9 @@ int videobuf_dqbuf(struct videobuf_queue *q, goto done; } buf = list_entry(q->stream.next, struct videobuf_buffer, stream); + mutex_unlock(&q->vb_lock); retval = videobuf_waiton(buf, nonblocking, 1); + mutex_lock(&q->vb_lock); if (retval < 0) { dprintk(1, "dqbuf: waiton returned %d\n", retval); goto done; -- cgit v1.2.3 From a46f9922d657ace8548b40a90d24aef16b951631 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 2 Apr 2008 14:27:39 -0300 Subject: V4L/DVB (7283): videobuf-dma-sg: Remove unused variable Removed warning message: - videobuf-dma-sg.c: In function 'videobuf_dma_unmap': - videobuf-dma-sg.c:281: warning: unused variable 'dev' Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-sg.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 6141a13bfc97..717783fa8b3e 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -273,8 +273,6 @@ int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma) int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { - void *dev=q->dev; - MAGIC_CHECK(dma->magic, MAGIC_DMABUF); if (!dma->sglen) return 0; -- cgit v1.2.3 From 222bd9e30c373165dd61774f1216d3be800c75c2 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Wed, 2 Apr 2008 14:27:39 -0300 Subject: V4L/DVB (7286): limit stack usage of ir-kbd-i2c.c ir_probe allocated struct i2c_client on stack; it's pretty big structure, so allocate it with kzalloc make checkstack output without this patch: x059d ir_probe [ir-kbd-i2c]: 1000 Signed-off-by: Marcin Slusarz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ir-kbd-i2c.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 5084db22bbd3..d17f0d4e6544 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -510,9 +510,9 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 }; static const int probe_cx23885[] = { 0x6b, -1 }; const int *probe = NULL; - struct i2c_client c; + struct i2c_client *c; unsigned char buf; - int i,rc; + int i, rc; switch (adap->id) { case I2C_HW_B_BT848: @@ -537,19 +537,23 @@ static int ir_probe(struct i2c_adapter *adap) if (NULL == probe) return 0; - memset(&c,0,sizeof(c)); - c.adapter = adap; + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return -ENOMEM; + + c->adapter = adap; for (i = 0; -1 != probe[i]; i++) { - c.addr = probe[i]; - rc = i2c_master_recv(&c,&buf,0); + c->addr = probe[i]; + rc = i2c_master_recv(c, &buf, 0); dprintk(1,"probe 0x%02x @ %s: %s\n", probe[i], adap->name, (0 == rc) ? "yes" : "no"); if (0 == rc) { - ir_attach(adap,probe[i],0,0); + ir_attach(adap, probe[i], 0, 0); break; } } + kfree(c); return 0; } -- cgit v1.2.3 From 4ad62a2bb79c55df33baca524b63d57ff4a8a40e Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Wed, 2 Apr 2008 14:27:39 -0300 Subject: V4L/DVB (7287): cx88: add analog support for DVICO FusionHDTV7 Gold Signed-off-by: Steven Toth Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 40 +++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 42 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 423da1543815..b5f2134f1664 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -63,3 +63,4 @@ 62 -> PowerColor Real Angel 330 [14f1:ea3d] 63 -> Geniatech X8000-MT DVBT [14f1:8852] 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] + 65 -> DVICO FusionHDTV7 Gold [18ac:d610] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index bf58f350e269..8e29e48a86f3 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1571,6 +1571,26 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = { + .name = "DVICO FusionHDTV7 Gold", + .tuner_type = TUNER_XC5000, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x37df, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x37df, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x37df, + }}, + }, }; /* ------------------------------------------------------------------ */ @@ -1908,6 +1928,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x14f1, .subdevice = 0x8852, .card = CX88_BOARD_GENIATECH_X8000_MT, + },{ + .subvendor = 0x18ac, + .subdevice = 0xd610, + .card = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD, } }; @@ -2189,6 +2213,18 @@ static int cx88_xc5000_tuner_callback(void *priv, int command, int arg) return -EINVAL; } break; + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + if (command == 0) { /* This is the reset command from xc5000 */ + cx_clear(MO_GP0_IO, 0x00000010); + msleep(10); + cx_set(MO_GP0_IO, 0x00000010); + return 0; + } else { + printk(KERN_ERR + "xc5000: unknown tuner callback command.\n"); + return -EINVAL; + } + break; } return 0; /* Should never be here */ } @@ -2255,6 +2291,10 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ udelay(1000); break; + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + /* Enable the xc5000 tuner */ + cx_set(MO_GP0_IO, 0x00001010); + break; } } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 9df3f198a4df..85a95a0a94d9 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -217,6 +217,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62 #define CX88_BOARD_GENIATECH_X8000_MT 63 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 +#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From b7f3fd561734d8321efaf80faa4c822a0226656c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:40 -0300 Subject: V4L/DVB (7288): cx88: fix GPIO for FusionHDTV 7 Gold input selection Fix GPIO for FusionHDTV 7 Gold tv / s-video / composite input selection. Fix card textual name to match other FusionHDTV device names. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 2 +- drivers/media/video/cx88/cx88-cards.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index b5f2134f1664..da7f70dfad2a 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -63,4 +63,4 @@ 62 -> PowerColor Real Angel 330 [14f1:ea3d] 63 -> Geniatech X8000-MT DVBT [14f1:8852] 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] - 65 -> DVICO FusionHDTV7 Gold [18ac:d610] + 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 8e29e48a86f3..7a2b0f26921a 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1572,7 +1572,7 @@ static const struct cx88_board cx88_boards[] = { .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = { - .name = "DVICO FusionHDTV7 Gold", + .name = "DViCO FusionHDTV 7 Gold", .tuner_type = TUNER_XC5000, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, @@ -1580,15 +1580,15 @@ static const struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x37df, + .gpio0 = 0x10df, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x37df, + .gpio0 = 0x16d9, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0x37df, + .gpio0 = 0x16d9, }}, }, }; -- cgit v1.2.3 From bf8fd8212c2ea6b49d6ed277e13d14ecebba0e38 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:40 -0300 Subject: V4L/DVB (7289): cx88: enable IR receiver and real time clock on FusionHDTV7 Gold Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 191577d166aa..327c0a87c081 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1832,6 +1832,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: request_module("rtc-isl1208"); /* break intentionally omitted */ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: -- cgit v1.2.3 From 8d6160d7f0ddf4397f4297e49c590d87be13bd36 Mon Sep 17 00:00:00 2001 From: Peter Hartley Date: Wed, 2 Apr 2008 14:27:40 -0300 Subject: V4L/DVB (7293): DMX_OUT_TSDEMUX_TAP: record two streams from same mux, resend Currently (in linux-2.6.24, but linux-dvb hg looks similar), the dmx_output_t in the dmx_pes_filter_params decides two things: whether output is sent to demux0 or dvr0 (in dmxdev.c:dvb_dmxdev_ts_callback), *and* whether to depacketise TS (in dmxdev.c:dvb_dmxdev_filter_start). As it stands, those two things can't be set independently: output destined for demux0 is depacketised, output for dvr0 isn't. This is what you want for capturing multiple audio streams from the same multiplex simultaneously: open demux0 several times and send depacketised output there. And capturing a single video stream is fine not what you want: you want multi-open (so demux0, not dvr0), but you want the TS nature preserved (because that's what you want on output, as you're going to re-multiplex it with the audio). At least one existing solution -- GStreamer -- sends all its streams simultaneously via dvr0 and demuxes again in userland, but it seems a bit of a shame to pick out all the PIDs in kernel, stick them back together in kernel, and send them to userland only to get unpicked again, when the alternative is such a small API addition. The attached patch adds a new value for dmx_output_t: DMX_OUT_TSDEMUX_TAP, which sends TS to the demux0 device. With this patch and a dvb-usb-dib0700 (and UK Freeview from Sandy Heath), I can successfully capture an audio/video PID pair into a TS file that mplayer can play back. Signed-off-by: Peter Hartley Acked-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 5 +++-- include/linux/dvb/dmx.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index f94bc31e3b33..e7f7aef862a8 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -374,7 +374,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, return 0; } - if (dmxdevfilter->params.pes.output == DMX_OUT_TAP) + if (dmxdevfilter->params.pes.output == DMX_OUT_TAP + || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) buffer = &dmxdevfilter->buffer; else buffer = &dmxdevfilter->dev->dvr_buffer; @@ -618,7 +619,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) else ts_type = 0; - if (otype == DMX_OUT_TS_TAP) + if (otype == DMX_OUT_TS_TAP || otype == DMX_OUT_TSDEMUX_TAP) ts_type |= TS_PACKET; if (otype == DMX_OUT_TAP) diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h index c6a2353c4e68..402fb7a8d922 100644 --- a/include/linux/dvb/dmx.h +++ b/include/linux/dvb/dmx.h @@ -39,9 +39,10 @@ typedef enum DMX_OUT_DECODER, /* Streaming directly to decoder. */ DMX_OUT_TAP, /* Output going to a memory buffer */ /* (to be retrieved via the read command).*/ - DMX_OUT_TS_TAP /* Output multiplexed into a new TS */ + DMX_OUT_TS_TAP, /* Output multiplexed into a new TS */ /* (to be retrieved by reading from the */ /* logical DVR device). */ + DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */ } dmx_output_t; -- cgit v1.2.3 From 47ce8bae722e90591554cc38d9076e2386137b56 Mon Sep 17 00:00:00 2001 From: Wojciech Migda Date: Wed, 2 Apr 2008 14:27:41 -0300 Subject: V4L/DVB (7294): : tuner and radio addresses are missing for the PixelView PlayTV card The PixelView PlayTV card definition structure was missing initialization of the tuner_addr and radio_addr fields. As a result it was impossible to have the tuner initialized using parameters specified while loading the bttv.ko module. This regression became visible after the v4l rearrangements introduced somewhere around 2.6.15 kernel version. The root cause for the tuner initialization failure is located in the attach_inform function in the bttv-i2c.c file. There at the very beginning the addr variable holding the tuner device address is initialized with the value taken from the bttv_tvcards array. For the PixelView PlayTV card the tuner address field (and the radio address as well) was uninitialized, and thus equal 0. Later in that function execution of the TUNER_SET_TYPE_ADDR tuner command is guarded with check for the tuner address either equal ADDR_UNSET, or client->addr. Since both are non-zero (the latter in case of the card owned by me at the runtime is equal 0x61) the TUNER_SET_TYPE_ADDR command is not executed, and consequently in the tuner_attach function in the tuner-core.c file call to i2c_attach_client does not result in assigning the tuner type variable with the requested value. Providing initialization of the tuner_addr and radio_addr with ADDR_UNSET values as it is already done for other tv cards defined in bttv-cards.c ensures that the tuner initialization is done correctly, just as it used to be in the 2.6.14 kernel. Signed-off-by: Wojciech Migda Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 7374c02dd183..b963bde97412 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -576,6 +576,8 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_WINVIEW_601] = { .name = "Leadtek WinView 601", -- cgit v1.2.3 From 487a88761d3d60b522c55fea47513729383056ad Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:41 -0300 Subject: V4L/DVB (7295): pvrusb2: add device attributes for fm radio and digital tuner Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 5 +++++ drivers/media/video/pvrusb2/pvrusb2-devattr.h | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 4df6d6d936fc..6532e28d0457 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -56,6 +56,7 @@ static const struct pvr2_device_desc pvr2_device_29xxx = { .fx2_firmware.lst = pvr2_fw1_names_29xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx), .flag_has_hauppauge_rom = !0, + .flag_has_fmradio = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, }; @@ -85,6 +86,7 @@ static const struct pvr2_device_desc pvr2_device_24xxx = { .flag_has_wm8775 = !0, .flag_has_hauppauge_rom = !0, .flag_has_hauppauge_custom_ir = !0, + .flag_has_fmradio = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, }; @@ -126,6 +128,7 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { .client_modules.lst = pvr2_client_onair_creator, .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator), .default_tuner_type = TUNER_LG_TDVS_H06XF, + .flag_has_digitaltuner = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, }; #endif @@ -148,6 +151,7 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .client_modules.lst = pvr2_client_onair_usb2, .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2), .default_tuner_type = TUNER_PHILIPS_ATSC, + .flag_has_digitaltuner = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, }; #endif @@ -175,6 +179,7 @@ static const struct pvr2_device_desc pvr2_device_75xxx = { .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), .flag_has_cx25840 = !0, .flag_has_hauppauge_rom = !0, + .flag_has_digitaltuner = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .default_std_mask = V4L2_STD_NTSC_M, }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 64b467f0637f..d89a44071cc1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -102,6 +102,13 @@ struct pvr2_device_desc { implement the virtual receiver in terms of appropriate FX2 commands. */ char flag_has_hauppauge_custom_ir; + + /* Device has FM radio capability. */ + char flag_has_fmradio; + + /* Device has a digital tuner; if this is set then we enable extra + functionality to switch between analog and digital modes. */ + char flag_has_digitaltuner; }; extern struct usb_device_id pvr2_device_table[]; -- cgit v1.2.3 From 4667b1d6fd8fb578429a6d56a54bfdc3b45c303a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:41 -0300 Subject: V4L/DVB (7296): pvrusb2: Define device attributes for all input modes Different devices support different input types. Up until now we've really been assuming that everyone has an analog tuner, an FM radio, composite, and s-video inputs. But as we add other devices, these assumptions are no longer true. The way to deal with this is to define the available inputs as additional device attributes, so that the driver can adjust its internal behavior accordingly. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 18 ++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-devattr.h | 12 ++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 6532e28d0457..e9bf2f4c54fc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -56,7 +56,10 @@ static const struct pvr2_device_desc pvr2_device_29xxx = { .fx2_firmware.lst = pvr2_fw1_names_29xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx), .flag_has_hauppauge_rom = !0, + .flag_has_analogtuner = !0, .flag_has_fmradio = !0, + .flag_has_composite = !0, + .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, }; @@ -86,7 +89,10 @@ static const struct pvr2_device_desc pvr2_device_24xxx = { .flag_has_wm8775 = !0, .flag_has_hauppauge_rom = !0, .flag_has_hauppauge_custom_ir = !0, + .flag_has_analogtuner = !0, .flag_has_fmradio = !0, + .flag_has_composite = !0, + .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, }; @@ -107,6 +113,9 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = { .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2), .flag_has_cx25840 = !0, .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .flag_has_analogtuner = !0, + .flag_has_composite = !0, + .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW, }; @@ -129,6 +138,9 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator), .default_tuner_type = TUNER_LG_TDVS_H06XF, .flag_has_digitaltuner = !0, + .flag_has_analogtuner = !0, + .flag_has_composite = !0, + .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, }; #endif @@ -152,6 +164,9 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2), .default_tuner_type = TUNER_PHILIPS_ATSC, .flag_has_digitaltuner = !0, + .flag_has_analogtuner = !0, + .flag_has_composite = !0, + .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, }; #endif @@ -180,6 +195,9 @@ static const struct pvr2_device_desc pvr2_device_75xxx = { .flag_has_cx25840 = !0, .flag_has_hauppauge_rom = !0, .flag_has_digitaltuner = !0, + .flag_has_analogtuner = !0, + .flag_has_composite = !0, + .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .default_std_mask = V4L2_STD_NTSC_M, }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index d89a44071cc1..b564121803bb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -103,12 +103,12 @@ struct pvr2_device_desc { commands. */ char flag_has_hauppauge_custom_ir; - /* Device has FM radio capability. */ - char flag_has_fmradio; - - /* Device has a digital tuner; if this is set then we enable extra - functionality to switch between analog and digital modes. */ - char flag_has_digitaltuner; + /* These bits define which kinds of sources the device can handle. */ + char flag_has_fmradio; /* Has FM radio receiver */ + char flag_has_analogtuner; /* Has analog tuner */ + char flag_has_digitaltuner; /* Has digital tuner */ + char flag_has_composite; /* Has composite input */ + char flag_has_svideo; /* Has s-video input */ }; extern struct usb_device_id pvr2_device_table[]; -- cgit v1.2.3 From 161ed03ca971ddc4a23a320eaeff1390d7b563ab Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:41 -0300 Subject: V4L/DVB (7297): pvrusb2: Dynamically control range of input selections This follows from defining the available inputs as device attributes. This change causes the driver to adjust its list of inputs based on those attributes. Now, for example, the FM radio will appear as a choice only if the hardware supports an FM radio. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 26 +++++++++++++++++++++++++- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 7 ++++--- 2 files changed, 29 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b74951a97d16..ba4324cc00ce 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -183,6 +183,7 @@ static const char *control_values_srate[] = { static const char *control_values_input[] = { [PVR2_CVAL_INPUT_TV] = "television", /*xawtv needs this name*/ + [PVR2_CVAL_INPUT_DTV] = "dtv", [PVR2_CVAL_INPUT_RADIO] = "radio", [PVR2_CVAL_INPUT_SVIDEO] = "s-video", [PVR2_CVAL_INPUT_COMPOSITE] = "composite", @@ -368,6 +369,27 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp) return 0; } +static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + const struct pvr2_device_desc *dsc = hdw->hdw_desc; + + switch (v) { + case PVR2_CVAL_INPUT_TV: + return dsc->flag_has_analogtuner != 0; + case PVR2_CVAL_INPUT_DTV: + return dsc->flag_has_digitaltuner != 0; + case PVR2_CVAL_INPUT_SVIDEO: + return dsc->flag_has_svideo != 0; + case PVR2_CVAL_INPUT_COMPOSITE: + return dsc->flag_has_composite != 0; + case PVR2_CVAL_INPUT_RADIO: + return dsc->flag_has_fmradio != 0; + default: + return 0; + } +} + static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) { struct pvr2_hdw *hdw = cptr->hdw; @@ -383,7 +405,8 @@ static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { hdw->freqSelector = 0; hdw->freqDirty = !0; - } else if (hdw->input_val == PVR2_CVAL_INPUT_TV) { + } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) || + (hdw->input_val == PVR2_CVAL_INPUT_DTV)) { hdw->freqSelector = 1; hdw->freqDirty = !0; } @@ -804,6 +827,7 @@ static const struct pvr2_ctl_info control_defs[] = { .name = "input", .internal_id = PVR2_CID_INPUT, .default_value = PVR2_CVAL_INPUT_TV, + .check_value = ctrl_check_input, DEFREF(input), DEFENUM(control_values_input), },{ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 3ad7a13d6c39..d33b313966ef 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -40,9 +40,10 @@ /* Legal values for the INPUT state variable */ #define PVR2_CVAL_INPUT_TV 0 -#define PVR2_CVAL_INPUT_SVIDEO 1 -#define PVR2_CVAL_INPUT_COMPOSITE 2 -#define PVR2_CVAL_INPUT_RADIO 3 +#define PVR2_CVAL_INPUT_DTV 1 +#define PVR2_CVAL_INPUT_SVIDEO 2 +#define PVR2_CVAL_INPUT_COMPOSITE 3 +#define PVR2_CVAL_INPUT_RADIO 4 enum pvr2_config { pvr2_config_empty, /* No configuration */ -- cgit v1.2.3 From ae71ae3f01c78c540f8c56116cba55710ef6db85 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:42 -0300 Subject: V4L/DVB (7298): pvrusb2: Account for dtv choice (a bit) in v4l2 implementation The v4l2 implementation in pvru2b2 must produce a sane answer when asked, when the input choice is set to dtv. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 8f0587ebd4bd..5e2292726e94 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -267,6 +267,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ret = 0; switch (vi->index) { case PVR2_CVAL_INPUT_TV: + case PVR2_CVAL_INPUT_DTV: case PVR2_CVAL_INPUT_RADIO: tmp.type = V4L2_INPUT_TYPE_TUNER; break; -- cgit v1.2.3 From e741ba44178561ac83fe4010b7e59a645c7c7e40 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:42 -0300 Subject: V4L/DVB (7299): pvrusb2: Improve logic which handles input choice availability Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 3 ++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 35 +++++++++++----------- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 4 +++ 3 files changed, 24 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index d7a216b41b72..aa374c7e08fd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -323,6 +323,9 @@ struct pvr2_hdw { int v4l_minor_number_vbi; int v4l_minor_number_radio; + /* Bit mask of PVR2_CVAL_INPUT choices which are valid */ + unsigned int input_avail_mask; + /* Location of eeprom or a negative number if none */ int eeprom_addr; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index ba4324cc00ce..8cc0b9d05ab4 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -371,23 +371,7 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp) static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) { - struct pvr2_hdw *hdw = cptr->hdw; - const struct pvr2_device_desc *dsc = hdw->hdw_desc; - - switch (v) { - case PVR2_CVAL_INPUT_TV: - return dsc->flag_has_analogtuner != 0; - case PVR2_CVAL_INPUT_DTV: - return dsc->flag_has_digitaltuner != 0; - case PVR2_CVAL_INPUT_SVIDEO: - return dsc->flag_has_svideo != 0; - case PVR2_CVAL_INPUT_COMPOSITE: - return dsc->flag_has_composite != 0; - case PVR2_CVAL_INPUT_RADIO: - return dsc->flag_has_fmradio != 0; - default: - return 0; - } + return ((1 << v) & cptr->hdw->input_avail_mask) != 0; } static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) @@ -1835,7 +1819,7 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw) struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, const struct usb_device_id *devid) { - unsigned int idx,cnt1,cnt2; + unsigned int idx,cnt1,cnt2,m; struct pvr2_hdw *hdw; int valid_std_mask; struct pvr2_ctrl *cptr; @@ -1866,6 +1850,15 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->tuner_signal_stale = !0; cx2341x_fill_defaults(&hdw->enc_ctl_state); + /* Calculate which inputs are OK */ + m = 0; + if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV; + if (hdw_desc->flag_has_digitaltuner) m |= 1 << PVR2_CVAL_INPUT_DTV; + if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO; + if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE; + if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO; + hdw->input_avail_mask = m; + hdw->control_cnt = CTRLDEF_COUNT; hdw->control_cnt += MPEGDEF_COUNT; hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt, @@ -3781,6 +3774,12 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) } +unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw) +{ + return hdw->input_avail_mask; +} + + /* Find I2C address of eeprom */ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index d33b313966ef..59f385878ef2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -147,6 +147,10 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *, /* Commit all control changes made up to this point */ int pvr2_hdw_commit_ctl(struct pvr2_hdw *); +/* Return a bit mask of valid input selections for this device. Mask bits + * will be according to PVR_CVAL_INPUT_xxxx definitions. */ +unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *); + /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); -- cgit v1.2.3 From 433d51d6edfc34ca3cfeaf9fe5d96a4ec7d7e51d Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:43 -0300 Subject: V4L/DVB (7300): pvrusb2: v4l2 implementation fixes for input selection Now that the pvrusb2 driver can dynamically choose which inputs to make available depending on the hardware, the enumeration of input choices is no longer a contiguous range of integers. Unfortunately this causes a problem in the v4l2 implementation since the input enumeration requires continuity in the API. This change implements a mapping in order to preserve the v4l2 interface requirement. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 70 ++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 5e2292726e94..e878c6445ae2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -67,6 +67,10 @@ struct pvr2_v4l2 { struct v4l2_prio_state prio; + /* Map contiguous ordinal value to input id */ + unsigned char *input_map; + unsigned int input_cnt; + /* streams - Note that these must be separately, individually, * allocated pointers. This is because the v4l core is going to * manage their deletion - separately, individually... */ @@ -259,13 +263,19 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, struct v4l2_input *vi = (struct v4l2_input *)arg; struct v4l2_input tmp; unsigned int cnt; + int val; cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); memset(&tmp,0,sizeof(tmp)); tmp.index = vi->index; ret = 0; - switch (vi->index) { + if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { + ret = -EINVAL; + break; + } + val = vp->input_map[vi->index]; + switch (val) { case PVR2_CVAL_INPUT_TV: case PVR2_CVAL_INPUT_DTV: case PVR2_CVAL_INPUT_RADIO: @@ -282,7 +292,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, if (ret < 0) break; cnt = 0; - pvr2_ctrl_get_valname(cptr,vi->index, + pvr2_ctrl_get_valname(cptr,val, tmp.name,sizeof(tmp.name)-1,&cnt); tmp.name[cnt] = 0; @@ -304,22 +314,33 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_INPUT: { + unsigned int idx; struct pvr2_ctrl *cptr; struct v4l2_input *vi = (struct v4l2_input *)arg; int val; cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); val = 0; ret = pvr2_ctrl_get_value(cptr,&val); - vi->index = val; + vi->index = 0; + for (idx = 0; idx < vp->input_cnt; idx++) { + if (vp->input_map[idx] == val) { + vi->index = idx; + break; + } + } break; } case VIDIOC_S_INPUT: { struct v4l2_input *vi = (struct v4l2_input *)arg; + if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { + ret = -ERANGE; + break; + } ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), - vi->index); + vp->input_map[vi->index]); break; } @@ -818,6 +839,10 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) pvr2_v4l2_dev_destroy(vp->dev_radio); vp->dev_radio = NULL; } + if (vp->input_map) { + kfree(vp->input_map); + vp->input_map = NULL; + } pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); pvr2_channel_done(&vp->channel); @@ -1199,27 +1224,46 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) { struct pvr2_v4l2 *vp; + struct pvr2_hdw *hdw; + unsigned int input_mask,input_cnt,idx; vp = kzalloc(sizeof(*vp),GFP_KERNEL); if (!vp) return vp; - vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); - vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); - if (!(vp->dev_video && vp->dev_radio)) { - kfree(vp->dev_video); - kfree(vp->dev_radio); - kfree(vp); - return NULL; - } pvr2_channel_init(&vp->channel,mnp); pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); vp->channel.check_func = pvr2_v4l2_internal_check; + hdw = vp->channel.mc_head->hdw; + input_mask = pvr2_hdw_get_input_available(hdw); + input_cnt = 0; + for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { + if (input_mask & (1 << idx)) input_cnt++; + } + vp->input_cnt = input_cnt; + vp->input_map = kzalloc(input_cnt,GFP_KERNEL); + if (!vp->input_map) goto fail; + input_cnt = 0; + for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { + if (!(input_mask & (1 << idx))) continue; + vp->input_map[input_cnt++] = idx; + } + /* register streams */ + vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); + if (!vp->dev_video) goto fail; pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); - pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); + if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) { + vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); + if (!vp->dev_radio) goto fail; + pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); + } return vp; + fail: + pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp); + pvr2_v4l2_destroy_no_lock(vp); + return 0; } /* -- cgit v1.2.3 From 15e21cd23ae59b516cf4930f482e0b4fe194f266 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:43 -0300 Subject: V4L/DVB (7301): pvrusb2: Implement addition sysfs tracing Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 7a1cd878e31a..24e25bb7a90b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -288,6 +288,8 @@ static ssize_t store_val_norm(int id,struct device *class_dev, struct pvr2_sysfs *sfp; int ret; sfp = (struct pvr2_sysfs *)class_dev->driver_data; + pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"", + sfp,id,count,buf); ret = store_val_any(id,0,sfp,buf,count); if (!ret) ret = count; return ret; @@ -299,6 +301,8 @@ static ssize_t store_val_custom(int id,struct device *class_dev, struct pvr2_sysfs *sfp; int ret; sfp = (struct pvr2_sysfs *)class_dev->driver_data; + pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"", + sfp,id,count,buf); ret = store_val_any(id,1,sfp,buf,count); if (!ret) ret = count; return ret; -- cgit v1.2.3 From 9948e36eaac9462e0d52dbfdf9a2c69e3a4f2ae2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:44 -0300 Subject: V4L/DVB (7302): pvrusb2: Improve control validation for enumerations When an enumeration control is changed, the pvrusb2 driver assumed that the enumeration values were continuous. That is no longer true; this change allows for properly input validation even when not all enumeration values are legal (which can happen with input selection based on what the hardware supports). Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-ctrl.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 5a3e8d21a38a..91a42f2473a7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -30,6 +30,9 @@ static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val) { if (cptr->info->check_value) { if (!cptr->info->check_value(cptr,val)) return -ERANGE; + } else if (cptr->info->type == pvr2_ctl_enum) { + if (val < 0) return -ERANGE; + if (val >= cptr->info->def.type_enum.count) return -ERANGE; } else { int lim; lim = cptr->info->def.type_int.min_value; @@ -63,13 +66,10 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val) if (cptr->info->set_value) { if (cptr->info->type == pvr2_ctl_bitmask) { mask &= cptr->info->def.type_bitmask.valid_bits; - } else if (cptr->info->type == pvr2_ctl_int) { + } else if ((cptr->info->type == pvr2_ctl_int)|| + (cptr->info->type == pvr2_ctl_enum)) { ret = pvr2_ctrl_range_check(cptr,val); if (ret < 0) break; - } else if (cptr->info->type == pvr2_ctl_enum) { - if (val >= cptr->info->def.type_enum.count) { - break; - } } else if (cptr->info->type != pvr2_ctl_bool) { break; } @@ -204,8 +204,7 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val, if (cptr->info->type == pvr2_ctl_enum) { const char **names; names = cptr->info->def.type_enum.value_names; - if ((val >= 0) && - (val < cptr->info->def.type_enum.count)) { + if (pvr2_ctrl_range_check(cptr,val) == 0) { if (names[val]) { *blen = scnprintf( bptr,bmax,"%s", @@ -528,10 +527,8 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, ptr,len,valptr, cptr->info->def.type_enum.value_names, cptr->info->def.type_enum.count); - if ((ret >= 0) && - ((*valptr < 0) || - (*valptr >= cptr->info->def.type_enum.count))) { - ret = -ERANGE; + if (ret >= 0) { + ret = pvr2_ctrl_range_check(cptr,*valptr); } if (maskptr) *maskptr = ~0; } else if (cptr->info->type == pvr2_ctl_bitmask) { -- cgit v1.2.3 From f0dcd177aebd420f8c1680fcd19c9fadbb5f39f8 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:44 -0300 Subject: V4L/DVB (7303): pvrusb2: Ensure that default input selection is actually valid Previously the pvrusb2 driver just started with the default input to be "television". But if the device doesn't support an analog tuner then this default must be different. New logic here selects a reasonable default based on the actual valid set of available inputs. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 9 +++++++++ drivers/media/video/pvrusb2/pvrusb2-hdw.h | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 8cc0b9d05ab4..ebc0ad1bd640 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1876,6 +1876,15 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, cptr = hdw->controls + idx; cptr->info = control_defs+idx; } + + /* Ensure that default input choice is a valid one. */ + m = hdw->input_avail_mask; + if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) { + if (!((1 << idx) & m)) continue; + hdw->input_val = idx; + break; + } + /* Define and configure additional controls from cx2341x module. */ hdw->mpeg_ctrl_info = kzalloc( sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 59f385878ef2..2919a1d9ed0f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -41,8 +41,8 @@ /* Legal values for the INPUT state variable */ #define PVR2_CVAL_INPUT_TV 0 #define PVR2_CVAL_INPUT_DTV 1 -#define PVR2_CVAL_INPUT_SVIDEO 2 -#define PVR2_CVAL_INPUT_COMPOSITE 3 +#define PVR2_CVAL_INPUT_COMPOSITE 2 +#define PVR2_CVAL_INPUT_SVIDEO 3 #define PVR2_CVAL_INPUT_RADIO 4 enum pvr2_config { -- cgit v1.2.3 From 1794220f8b5a79b944640c336605cc7172d7b5fd Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:44 -0300 Subject: V4L/DVB (7304): pvrusb2: add function pvr2_hdw_cmd_powerdown Call pvr2_hdw_cmd_powerdown to power down the device Signed-off-by: Michael Krufky Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 23 +++++++++++++++++++---- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 3 +++ 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index ebc0ad1bd640..2ecbd6e3c226 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3194,17 +3194,32 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw) } -int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw) +static int pvr2_hdw_cmd_power_ctrl(struct pvr2_hdw *hdw, int onoff) { int status; LOCK_TAKE(hdw->ctl_lock); do { - pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup"); - hdw->cmd_buffer[0] = FX2CMD_POWER_ON; - status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); + if (onoff) { + pvr2_trace(PVR2_TRACE_INIT, "Requesting powerup"); + hdw->cmd_buffer[0] = FX2CMD_POWER_ON; + } else { + pvr2_trace(PVR2_TRACE_INIT, "Requesting powerdown"); + hdw->cmd_buffer[0] = FX2CMD_POWER_OFF; + } + status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0); } while (0); LOCK_GIVE(hdw->ctl_lock); return status; } +int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw) +{ + return pvr2_hdw_cmd_power_ctrl(hdw, 1); +} + +int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw) +{ + return pvr2_hdw_cmd_power_ctrl(hdw, 0); +} + int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 2919a1d9ed0f..57e1ff491497 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -255,6 +255,9 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *); /* Execute simple reset command */ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *); +/* suspend */ +int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *); + /* Order decoder to reset */ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *); -- cgit v1.2.3 From 38c7a06cee76763a48021f3469bd164952e79627 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:44 -0300 Subject: V4L/DVB (7305): pvrusb2: whitespace fixup Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index aa374c7e08fd..4971335c46d3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -237,9 +237,9 @@ struct pvr2_hdw { int state_usbstream_run; /* FX2 is streaming */ int state_decoder_quiescent; /* Decoder idle for > 50msec */ int state_pipeline_config; /* Pipeline is configured */ - int state_pipeline_req; /* Somebody wants to stream */ - int state_pipeline_pause; /* Pipeline must be paused */ - int state_pipeline_idle; /* Pipeline not running */ + int state_pipeline_req; /* Somebody wants to stream */ + int state_pipeline_pause; /* Pipeline must be paused */ + int state_pipeline_idle; /* Pipeline not running */ /* This is the master state of the driver. It is the combined result of other bits of state. Examining this will indicate the -- cgit v1.2.3 From 39d2c8daad17d3181ebe1d01d28764681e27f309 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:45 -0300 Subject: V4L/DVB (7306): pvrusb2: Fix oops possible when claiming a NULL stream Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index 9d94aed2e12d..f2cffcdc7aba 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -174,7 +174,7 @@ int pvr2_channel_claim_stream(struct pvr2_channel *cp, int code = 0; pvr2_context_enter(cp->mc_head); do { if (sp == cp->stream) break; - if (sp->user) { + if (sp && sp->user) { code = -EBUSY; break; } -- cgit v1.2.3 From e190969235bc34da26d88d4913c02565f6d13cef Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:45 -0300 Subject: V4L/DVB (7307): pvrusb2: New functions for additional FX2 digital-related commands This code is actually part of a larger set from Mike Krufky , to support ATSC streaming from within the pvrusb2 driver. More to come... Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h | 9 +++++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 55 +++++++++++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-hdw.h | 8 ++++ 3 files changed, 72 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h index ffbc6d096108..a866c949243c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h +++ b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h @@ -49,6 +49,15 @@ #define FX2CMD_GET_EEPROM_ADDR 0xeb #define FX2CMD_GET_IR_CODE 0xec +#define FX2CMD_HCW_DEMOD_RESETIN 0xf0 +#define FX2CMD_HCW_DTV_STREAMING_ON 0xf1 +#define FX2CMD_HCW_DTV_STREAMING_OFF 0xf2 + +#define FX2CMD_ONAIR_DTV_STREAMING_ON 0xa0 +#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1 +#define FX2CMD_ONAIR_DTV_POWER_ON 0xa2 +#define FX2CMD_ONAIR_DTV_POWER_OFF 0xa3 + #endif /* _PVRUSB2_FX2_CMD_H_ */ /* diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 2ecbd6e3c226..307043f44211 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3242,6 +3242,61 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) } +int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff) +{ + int status; + + LOCK_TAKE(hdw->ctl_lock); do { + pvr2_trace(PVR2_TRACE_INIT, "Issuing fe demod wake command"); + hdw->flag_ok = !0; + hdw->cmd_buffer[0] = FX2CMD_HCW_DEMOD_RESETIN; + hdw->cmd_buffer[1] = onoff; + status = pvr2_send_request(hdw, hdw->cmd_buffer, 2, NULL, 0); + } while (0); LOCK_GIVE(hdw->ctl_lock); + + return status; +} + +int pvr2_hdw_cmd_hcw_usbstream_dvb(struct pvr2_hdw *hdw, int onoff) +{ + int status; + LOCK_TAKE(hdw->ctl_lock); do { + hdw->cmd_buffer[0] = + (onoff ? FX2CMD_HCW_DTV_STREAMING_ON : + FX2CMD_HCW_DTV_STREAMING_OFF); + status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0); + } while (0); LOCK_GIVE(hdw->ctl_lock); + return status; +} + +int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff) +{ + int status; + + LOCK_TAKE(hdw->ctl_lock); do { + pvr2_trace(PVR2_TRACE_INIT, "Issuing fe power command to CPLD"); + hdw->flag_ok = !0; + hdw->cmd_buffer[0] = + (onoff ? FX2CMD_ONAIR_DTV_POWER_ON : + FX2CMD_ONAIR_DTV_POWER_OFF); + status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0); + } while (0); LOCK_GIVE(hdw->ctl_lock); + + return status; +} + +int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw, int onoff) +{ + int status; + LOCK_TAKE(hdw->ctl_lock); do { + hdw->cmd_buffer[0] = + (onoff ? FX2CMD_ONAIR_DTV_STREAMING_ON : + FX2CMD_ONAIR_DTV_STREAMING_OFF); + status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0); + } while (0); LOCK_GIVE(hdw->ctl_lock); + return status; +} + /* Stop / start video stream transport */ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 57e1ff491497..e9090c5064d8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -258,6 +258,14 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *); /* suspend */ int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *); +/* Hauppauge - specific */ +int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff); +int pvr2_hdw_cmd_hcw_usbstream_dvb(struct pvr2_hdw *hdw, int onoff); + +/* onair - specific */ +int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff); +int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw, int onoff); + /* Order decoder to reset */ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *); -- cgit v1.2.3 From 95ec1139cfdfca50dd1166536855c6537d2bde5b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:45 -0300 Subject: V4L/DVB (7308): pvrusb2: Define digital control scheme device attributes Unlike analog control, control of the digital side is not nearly as uniform among different devices. So we have to specify the correct digital control scheme as a new device attribute. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 6 +++--- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 16 ++++++++++++++-- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 +++- 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index e9bf2f4c54fc..e1dad8699dca 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -137,11 +137,11 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { .client_modules.lst = pvr2_client_onair_creator, .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator), .default_tuner_type = TUNER_LG_TDVS_H06XF, - .flag_has_digitaltuner = !0, .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, }; #endif @@ -163,11 +163,11 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .client_modules.lst = pvr2_client_onair_usb2, .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2), .default_tuner_type = TUNER_PHILIPS_ATSC, - .flag_has_digitaltuner = !0, .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, }; #endif @@ -194,11 +194,11 @@ static const struct pvr2_device_desc pvr2_device_75xxx = { .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), .flag_has_cx25840 = !0, .flag_has_hauppauge_rom = !0, - .flag_has_digitaltuner = !0, .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, .default_std_mask = V4L2_STD_NTSC_M, }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index b564121803bb..4e4798d6139f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -39,6 +39,10 @@ struct pvr2_string_table { #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0 #define PVR2_ROUTING_SCHEME_GOTVIEW 1 +#define PVR2_DIGITAL_SCHEME_NONE 0 +#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 +#define PVR2_DIGITAL_SCHEME_ONAIR 2 + /* This describes a particular hardware type (except for the USB device ID which must live in a separate structure due to environmental constraints). See the top of pvrusb2-hdw.c for where this is @@ -66,6 +70,13 @@ struct pvr2_device_desc { drivers (search for things which touch this field). */ unsigned int signal_routing_scheme; + /* Control scheme to use if there is a digital tuner. This + contains one of PVR2_DIGITAL_SCHEME_XXX. This is an arbitrary + integer scheme id; its meaning is contained entirely within the + driver and is interpreted by logic which must control the + streaming pathway (search for things which touch this field). */ + unsigned int digital_control_scheme; + /* V4L tuner type ID to use with this device (only used if the driver could not discover the type any other way). */ int default_tuner_type; @@ -103,10 +114,11 @@ struct pvr2_device_desc { commands. */ char flag_has_hauppauge_custom_ir; - /* These bits define which kinds of sources the device can handle. */ + /* These bits define which kinds of sources the device can handle. + Note: Digital tuner presence is inferred by the + digital_control_scheme enumeration. */ char flag_has_fmradio; /* Has FM radio receiver */ char flag_has_analogtuner; /* Has analog tuner */ - char flag_has_digitaltuner; /* Has digital tuner */ char flag_has_composite; /* Has composite input */ char flag_has_svideo; /* Has s-video input */ }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 307043f44211..72da5fcb3b66 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1853,7 +1853,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, /* Calculate which inputs are OK */ m = 0; if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV; - if (hdw_desc->flag_has_digitaltuner) m |= 1 << PVR2_CVAL_INPUT_DTV; + if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) { + m |= 1 << PVR2_CVAL_INPUT_DTV; + } if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO; if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE; if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO; -- cgit v1.2.3 From ce220af06885b798bcd6e6183a952c9ac85c015c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:46 -0300 Subject: V4L/DVB (7309): pvrusb2: Enhance core logic to also control digital streaming This is a major pvrusb2 change. The driver core has an algorithm that is used to cleanly sequence the changes needed to enable / disable video streaming. The algorithm had originally been written for analog streaming, but when in digital mode the pipeline is considerably Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 7 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 196 +++++++++++++++++---- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 8 - 3 files changed, 164 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 4971335c46d3..af06e6c4b8d5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -163,6 +163,11 @@ struct pvr2_decoder_ctrl { #define FW1_STATE_RELOAD 3 #define FW1_STATE_OK 4 +/* What state the device is in if it is a hybrid */ +#define PVR2_PATHWAY_UNKNOWN 0 +#define PVR2_PATHWAY_ANALOG 1 +#define PVR2_PATHWAY_DIGITAL 2 + typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16); #define PVR2_I2C_FUNC_CNT 128 @@ -229,6 +234,7 @@ struct pvr2_hdw { /* Bits of state that describe what is going on with various parts of the driver. */ + int state_pathway_ok; /* Pathway config is ok */ int state_encoder_ok; /* Encoder is operational */ int state_encoder_run; /* Encoder is running */ int state_encoder_config; /* Encoder is configured */ @@ -267,6 +273,7 @@ struct pvr2_hdw { int flag_disconnected; /* flag_ok == 0 due to disconnect */ int flag_init_ok; /* true if structure is fully initialized */ int fw1_state; /* current situation with fw1 */ + int pathway_state; /* one of PVR2_PATHWAY_xxx */ int flag_decoder_missed;/* We've noticed missing decoder */ int flag_tripped; /* Indicates overall failure to start */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 72da5fcb3b66..f47649274cc7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1861,6 +1861,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO; hdw->input_avail_mask = m; + /* If not a hybrid device, pathway_state never changes. So + initialize it here to what it should forever be. */ + if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) { + hdw->pathway_state = PVR2_PATHWAY_ANALOG; + } else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) { + hdw->pathway_state = PVR2_PATHWAY_DIGITAL; + } + hdw->control_cnt = CTRLDEF_COUNT; hdw->control_cnt += MPEGDEF_COUNT; hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt, @@ -2381,6 +2389,17 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) } } + if (hdw->input_dirty && + (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ? + PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) != + hdw->pathway_state)) { + /* Change of mode being asked for... */ + hdw->state_pathway_ok = 0; + } + if (!hdw->state_pathway_ok) { + /* Can't commit anything until pathway is ok. */ + return 0; + } /* If any of the below has changed, then we can't do the update while the pipeline is running. Pipeline must be paused first and decoder -> encoder connection be made quiescent before we @@ -2437,9 +2456,11 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) /* Now execute i2c core update */ pvr2_i2c_core_sync(hdw); - if (hdw->state_encoder_run) { - /* If encoder isn't running, then this will get worked out - later when we start the encoder. */ + if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) && + hdw->state_encoder_run) { + /* If encoder isn't running or it can't be touched, then + this will get worked out later when we start the + encoder. */ if (pvr2_encoder_adjust(hdw) < 0) return !0; } @@ -3244,12 +3265,14 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) } -int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff) +static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff) { int status; LOCK_TAKE(hdw->ctl_lock); do { - pvr2_trace(PVR2_TRACE_INIT, "Issuing fe demod wake command"); + pvr2_trace(PVR2_TRACE_INIT, + "Issuing fe demod wake command (%s)", + (onoff ? "on" : "off")); hdw->flag_ok = !0; hdw->cmd_buffer[0] = FX2CMD_HCW_DEMOD_RESETIN; hdw->cmd_buffer[1] = onoff; @@ -3259,24 +3282,15 @@ int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff) return status; } -int pvr2_hdw_cmd_hcw_usbstream_dvb(struct pvr2_hdw *hdw, int onoff) -{ - int status; - LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = - (onoff ? FX2CMD_HCW_DTV_STREAMING_ON : - FX2CMD_HCW_DTV_STREAMING_OFF); - status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0); - } while (0); LOCK_GIVE(hdw->ctl_lock); - return status; -} -int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff) +static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff) { int status; LOCK_TAKE(hdw->ctl_lock); do { - pvr2_trace(PVR2_TRACE_INIT, "Issuing fe power command to CPLD"); + pvr2_trace(PVR2_TRACE_INIT, + "Issuing fe power command to CPLD (%s)", + (onoff ? "on" : "off")); hdw->flag_ok = !0; hdw->cmd_buffer[0] = (onoff ? FX2CMD_ONAIR_DTV_POWER_ON : @@ -3287,10 +3301,15 @@ int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff) return status; } -int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw, int onoff) + +static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw, + int onoff) { int status; LOCK_TAKE(hdw->ctl_lock); do { + pvr2_trace(PVR2_TRACE_INIT, + "Issuing onair digital setup command (%s)", + (onoff ? "on" : "off")); hdw->cmd_buffer[0] = (onoff ? FX2CMD_ONAIR_DTV_STREAMING_ON : FX2CMD_ONAIR_DTV_STREAMING_OFF); @@ -3299,19 +3318,85 @@ int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw, int onoff) return status; } + +static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl) +{ + int cmode; + /* Compare digital/analog desired setting with current setting. If + they don't match, fix it... */ + cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG); + if (cmode == hdw->pathway_state) { + /* They match; nothing to do */ + return; + } + + switch (hdw->hdw_desc->digital_control_scheme) { + case PVR2_DIGITAL_SCHEME_HAUPPAUGE: + pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl); + if (cmode == PVR2_PATHWAY_ANALOG) { + /* If moving to analog mode, also force the decoder + to reset. If no decoder is attached, then it's + ok to ignore this because if/when the decoder + attaches, it will reset itself at that time. */ + pvr2_hdw_cmd_decoder_reset(hdw); + } + break; + case PVR2_DIGITAL_SCHEME_ONAIR: + /* Supposedly we should always have the power on whether in + digital or analog mode. But for now do what appears to + work... */ + if (digitalFl) pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,!0); + pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,digitalFl); + if (!digitalFl) pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,0); + break; + default: break; + } + + hdw->pathway_state = cmode; +} + + /* Stop / start video stream transport */ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) { - int status; + int status,cc; + if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) && + hdw->hdw_desc->digital_control_scheme == + PVR2_DIGITAL_SCHEME_HAUPPAUGE) { + cc = (runFl ? + FX2CMD_HCW_DTV_STREAMING_ON : + FX2CMD_HCW_DTV_STREAMING_OFF); + } else { + cc = (runFl ? + FX2CMD_STREAMING_ON : + FX2CMD_STREAMING_OFF); + } + LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = - (runFl ? FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF); + hdw->cmd_buffer[0] = cc; status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); } while (0); LOCK_GIVE(hdw->ctl_lock); return status; } +/* Evaluate whether or not state_pathway_ok can change */ +static int state_eval_pathway_ok(struct pvr2_hdw *hdw) +{ + if (hdw->state_pathway_ok) { + /* Nothing to do if pathway is already ok */ + return 0; + } + if (!hdw->state_pipeline_idle) { + /* Not allowed to change anything if pipeline is not idle */ + return 0; + } + pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV); + hdw->state_pathway_ok = !0; + return !0; +} + + /* Evaluate whether or not state_encoder_ok can change */ static int state_eval_encoder_ok(struct pvr2_hdw *hdw) { @@ -3321,6 +3406,7 @@ static int state_eval_encoder_ok(struct pvr2_hdw *hdw) if (hdw->state_encoder_config) return 0; if (hdw->state_decoder_run) return 0; if (hdw->state_usbstream_run) return 0; + if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) return 0; if (pvr2_upload_firmware2(hdw) < 0) { hdw->flag_tripped = !0; trace_stbit("flag_tripped",hdw->flag_tripped); @@ -3346,7 +3432,9 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw) /* paranoia - solve race if timer just completed */ del_timer_sync(&hdw->encoder_wait_timer); } else { - if (!hdw->state_encoder_ok || + if (!hdw->state_pathway_ok || + (hdw->pathway_state != PVR2_PATHWAY_ANALOG) || + !hdw->state_encoder_ok || !hdw->state_pipeline_idle || hdw->state_pipeline_pause || !hdw->state_pipeline_req || @@ -3400,13 +3488,16 @@ static int state_eval_encoder_run(struct pvr2_hdw *hdw) { if (hdw->state_encoder_run) { if (hdw->state_encoder_ok) { - if (hdw->state_decoder_run) return 0; + if (hdw->state_decoder_run && + hdw->state_pathway_ok) return 0; if (pvr2_encoder_stop(hdw) < 0) return !0; } hdw->state_encoder_run = 0; } else { if (!hdw->state_encoder_ok) return 0; if (!hdw->state_decoder_run) return 0; + if (!hdw->state_pathway_ok) return 0; + if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) return 0; if (pvr2_encoder_start(hdw) < 0) return !0; hdw->state_encoder_run = !0; } @@ -3443,7 +3534,8 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) if (hdw->state_decoder_run) { if (hdw->state_encoder_ok) { if (hdw->state_pipeline_req && - !hdw->state_pipeline_pause) return 0; + !hdw->state_pipeline_pause && + hdw->state_pathway_ok) return 0; } if (!hdw->flag_decoder_missed) { pvr2_decoder_enable(hdw,0); @@ -3476,7 +3568,9 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) hopefully further stabilize the encoder. */ return 0; } - if (!hdw->state_pipeline_req || + if (!hdw->state_pathway_ok || + (hdw->pathway_state != PVR2_PATHWAY_ANALOG) || + !hdw->state_pipeline_req || hdw->state_pipeline_pause || !hdw->state_pipeline_config || !hdw->state_encoder_config || @@ -3497,16 +3591,25 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) static int state_eval_usbstream_run(struct pvr2_hdw *hdw) { if (hdw->state_usbstream_run) { - if (hdw->state_encoder_ok) { - if (hdw->state_encoder_run) return 0; + if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { + if (hdw->state_encoder_ok && + hdw->state_encoder_run && + hdw->state_pathway_ok) return 0; + } else { + if (hdw->state_pipeline_req && + !hdw->state_pipeline_pause && + hdw->state_pathway_ok) return 0; } pvr2_hdw_cmd_usbstream(hdw,0); hdw->state_usbstream_run = 0; } else { - if (!hdw->state_encoder_ok || - !hdw->state_encoder_run || - !hdw->state_pipeline_req || - hdw->state_pipeline_pause) return 0; + if (!hdw->state_pipeline_req || + hdw->state_pipeline_pause || + !hdw->state_pathway_ok) return 0; + if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { + if (!hdw->state_encoder_ok || + !hdw->state_encoder_run) return 0; + } if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0; hdw->state_usbstream_run = !0; } @@ -3553,6 +3656,7 @@ typedef int (*state_eval_func)(struct pvr2_hdw *); /* Set of functions to be run to evaluate various states in the driver. */ const static state_eval_func eval_funcs[] = { + state_eval_pathway_ok, state_eval_pipeline_config, state_eval_encoder_ok, state_eval_encoder_config, @@ -3600,6 +3704,16 @@ static int pvr2_hdw_state_update(struct pvr2_hdw *hdw) } +static const char *pvr2_pathway_state_name(int id) +{ + switch (id) { + case PVR2_PATHWAY_ANALOG: return "analog"; + case PVR2_PATHWAY_DIGITAL: return "digital"; + default: return "unknown"; + } +} + + static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, char *buf,unsigned int acnt) { @@ -3607,13 +3721,15 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, case 0: return scnprintf( buf,acnt, - "driver:%s%s%s%s%s", + "driver:%s%s%s%s%s", (hdw->flag_ok ? " " : " "), (hdw->flag_init_ok ? " " : " "), (hdw->flag_disconnected ? " " : " "), (hdw->flag_tripped ? " " : ""), - (hdw->flag_decoder_missed ? " " : "")); + (hdw->flag_decoder_missed ? " " : ""), + pvr2_pathway_state_name(hdw->pathway_state)); + case 1: return scnprintf( buf,acnt, @@ -3626,7 +3742,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, case 2: return scnprintf( buf,acnt, - "worker:%s%s%s%s%s%s", + "worker:%s%s%s%s%s%s%s", (hdw->state_decoder_run ? " " : (hdw->state_decoder_quiescent ? @@ -3642,7 +3758,9 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, (hdw->state_encoder_waitok ? "" : " ")), (hdw->state_usbstream_run ? - " " : " ")); + " " : " "), + (hdw->state_pathway_ok ? + "" : "")); break; case 3: return scnprintf( @@ -3714,9 +3832,9 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw) st = PVR2_STATE_WARM; } else if (hdw->flag_tripped || hdw->flag_decoder_missed) { st = PVR2_STATE_ERROR; - } else if (hdw->state_encoder_run && - hdw->state_decoder_run && - hdw->state_usbstream_run) { + } else if (hdw->state_usbstream_run && + ((hdw->pathway_state != PVR2_PATHWAY_ANALOG) || + (hdw->state_encoder_run && hdw->state_decoder_run))) { st = PVR2_STATE_RUN; } else { st = PVR2_STATE_READY; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index e9090c5064d8..57e1ff491497 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -258,14 +258,6 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *); /* suspend */ int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *); -/* Hauppauge - specific */ -int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff); -int pvr2_hdw_cmd_hcw_usbstream_dvb(struct pvr2_hdw *hdw, int onoff); - -/* onair - specific */ -int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff); -int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw, int onoff); - /* Order decoder to reset */ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *); -- cgit v1.2.3 From 8bd2d945a5603fa4dff53bda17eafb5dca2c6a65 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:46 -0300 Subject: V4L/DVB (7310): pvrusb2: trace print cosmetic cleanup / improvements Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f47649274cc7..216c205afb43 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2395,6 +2395,7 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) hdw->pathway_state)) { /* Change of mode being asked for... */ hdw->state_pathway_ok = 0; + trace_stbit("state_pathway_ok",hdw->state_pathway_ok); } if (!hdw->state_pathway_ok) { /* Can't commit anything until pathway is ok. */ @@ -3393,6 +3394,7 @@ static int state_eval_pathway_ok(struct pvr2_hdw *hdw) } pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV); hdw->state_pathway_ok = !0; + trace_stbit("state_pathway_ok",hdw->state_pathway_ok); return !0; } @@ -3721,7 +3723,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, case 0: return scnprintf( buf,acnt, - "driver:%s%s%s%s%s", + "driver:%s%s%s%s%s ", (hdw->flag_ok ? " " : " "), (hdw->flag_init_ok ? " " : " "), (hdw->flag_disconnected ? " " : @@ -3760,7 +3762,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, (hdw->state_usbstream_run ? " " : " "), (hdw->state_pathway_ok ? - "" : "")); + " " : "")); break; case 3: return scnprintf( -- cgit v1.2.3 From 25cd6c6fa71b9dcaa923e2f188e18bf71f3c4352 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:47 -0300 Subject: V4L/DVB (7311): pvrusb2: Allow digital streaming without encoder firmware The encoder is not a part of the pipeline when in digital mode, so streaming is OK in this case even when the encoder's firmware is not loaded. Modify the driver core handling of this scenario to permit streaming. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 216c205afb43..f738096fde69 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3353,6 +3353,7 @@ static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl) default: break; } + pvr2_hdw_untrip_unlocked(hdw); hdw->pathway_state = cmode; } @@ -3815,6 +3816,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw) unsigned int st; int state_updated = 0; int callback_flag = 0; + int analog_mode; pvr2_trace(PVR2_TRACE_STBITS, "Drive state check START"); @@ -3825,17 +3827,20 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw) /* Process all state and get back over disposition */ state_updated = pvr2_hdw_state_update(hdw); + analog_mode = (hdw->pathway_state != PVR2_PATHWAY_DIGITAL); + /* Update master state based upon all other states. */ if (!hdw->flag_ok) { st = PVR2_STATE_DEAD; } else if (hdw->fw1_state != FW1_STATE_OK) { st = PVR2_STATE_COLD; - } else if (!hdw->state_encoder_ok) { + } else if (analog_mode && !hdw->state_encoder_ok) { st = PVR2_STATE_WARM; - } else if (hdw->flag_tripped || hdw->flag_decoder_missed) { + } else if (hdw->flag_tripped || + (analog_mode && hdw->flag_decoder_missed)) { st = PVR2_STATE_ERROR; } else if (hdw->state_usbstream_run && - ((hdw->pathway_state != PVR2_PATHWAY_ANALOG) || + (!analog_mode || (hdw->state_encoder_run && hdw->state_decoder_run))) { st = PVR2_STATE_RUN; } else { -- cgit v1.2.3 From 0cb4cf214fa218b4ef83bbd06eb46cd2d9cd2317 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:50 -0300 Subject: V4L/DVB (7312): pvrusb2: Indicate streaming status via LED Most of this originates from Michael Krufky ; these changes move LED control into separate functions. This is the first step in new work to make LED control a device-specific attribute. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-encoder.c | 10 ++-------- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 21 +++++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-hdw.h | 3 +++ 3 files changed, 26 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 64062879981e..ccb5d14ddf85 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -480,9 +480,7 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw) /* unmask some interrupts */ pvr2_write_register(hdw, 0x0048, 0xbfffffff); - /* change some GPIO data */ - pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481); - pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); + pvr2_led_ctrl(hdw, 1); pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1, hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0); @@ -526,11 +524,7 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) break; } - /* change some GPIO data */ - /* Note: Bit d7 of dir appears to control the LED. So we shut it - off here. */ - pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401); - pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); + pvr2_led_ctrl(hdw, 0); return status; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f738096fde69..c2b6e34e25c5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3358,6 +3358,27 @@ static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl) } +/* Toggle LED */ +int pvr2_led_ctrl(struct pvr2_hdw *hdw, int onoff) +{ + /* change some GPIO data + * + * note: bit d7 of dir appears to control the LED, + * so we shut it off here. + * + * FIXME: is this device-specific? + */ + if (onoff) + pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481); + else + pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401); + + pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000); + + return 0; +} + + /* Stop / start video stream transport */ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 57e1ff491497..4fc9db3efff2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -258,6 +258,9 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *); /* suspend */ int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *); +/* toggle LED */ +int pvr2_led_ctrl(struct pvr2_hdw *hdw, int onoff); + /* Order decoder to reset */ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *); -- cgit v1.2.3 From 1cee333c4f37aa7e361b23177c7d97420bca09f3 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:50 -0300 Subject: V4L/DVB (7313): pvrusb2: Make LED control into a device-specific attribute The pvrusb2 driver has used hardcoded logic to control the LED on the device. However this is really Hauppauge-specific behavior. This change defines a new device attribute for LED control and sets things up appropriately for Hauppauge devices. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 3 ++ drivers/media/video/pvrusb2/pvrusb2-devattr.h | 8 +++++ drivers/media/video/pvrusb2/pvrusb2-encoder.c | 4 --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 3 ++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 39 ++++++++++++++++++---- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 3 -- 6 files changed, 46 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index e1dad8699dca..da17554e7b0a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -61,6 +61,7 @@ static const struct pvr2_device_desc pvr2_device_29xxx = { .flag_has_composite = !0, .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, }; @@ -94,6 +95,7 @@ static const struct pvr2_device_desc pvr2_device_24xxx = { .flag_has_composite = !0, .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, }; @@ -200,6 +202,7 @@ static const struct pvr2_device_desc pvr2_device_75xxx = { .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, .default_std_mask = V4L2_STD_NTSC_M, + .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 4e4798d6139f..ce4004978a92 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -43,6 +43,9 @@ struct pvr2_string_table { #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 #define PVR2_DIGITAL_SCHEME_ONAIR 2 +#define PVR2_LED_SCHEME_NONE 0 +#define PVR2_LED_SCHEME_HAUPPAUGE 1 + /* This describes a particular hardware type (except for the USB device ID which must live in a separate structure due to environmental constraints). See the top of pvrusb2-hdw.c for where this is @@ -70,6 +73,11 @@ struct pvr2_device_desc { drivers (search for things which touch this field). */ unsigned int signal_routing_scheme; + /* Indicates scheme for controlling device's LED (if any). The + driver will turn on the LED when streaming is underway. This + contains one of PVR2_LED_SCHEME_XXX. */ + unsigned int led_scheme; + /* Control scheme to use if there is a digital tuner. This contains one of PVR2_DIGITAL_SCHEME_XXX. This is an arbitrary integer scheme id; its meaning is contained entirely within the diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index ccb5d14ddf85..324d1bd8500d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -480,8 +480,6 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw) /* unmask some interrupts */ pvr2_write_register(hdw, 0x0048, 0xbfffffff); - pvr2_led_ctrl(hdw, 1); - pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1, hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0); @@ -524,8 +522,6 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) break; } - pvr2_led_ctrl(hdw, 0); - return status; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index af06e6c4b8d5..bc341ae5c79a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -253,6 +253,9 @@ struct pvr2_hdw { PVR2_STATE_xxxx */ unsigned int master_state; + /* True if device led is currently on */ + int led_on; + /* True if states must be re-evaluated */ int state_stale; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index c2b6e34e25c5..defe0bec9bf8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3358,24 +3358,48 @@ static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl) } -/* Toggle LED */ -int pvr2_led_ctrl(struct pvr2_hdw *hdw, int onoff) +void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff) { /* change some GPIO data * * note: bit d7 of dir appears to control the LED, * so we shut it off here. * - * FIXME: is this device-specific? */ - if (onoff) + if (onoff) { pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481); - else + } else { pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401); - + } pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000); +} - return 0; + +typedef void (*led_method_func)(struct pvr2_hdw *,int); + +static led_method_func led_methods[] = { + [PVR2_LED_SCHEME_HAUPPAUGE] = pvr2_led_ctrl_hauppauge, +}; + + +/* Toggle LED */ +static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff) +{ + unsigned int scheme_id; + led_method_func fp; + + if ((!onoff) == (!hdw->led_on)) return; + + hdw->led_on = onoff != 0; + + scheme_id = hdw->hdw_desc->led_scheme; + if (scheme_id < ARRAY_SIZE(led_methods)) { + fp = led_methods[scheme_id]; + } else { + fp = NULL; + } + + if (fp) (*fp)(hdw,onoff); } @@ -3872,6 +3896,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw) "Device state change from %s to %s", pvr2_get_state_name(hdw->master_state), pvr2_get_state_name(st)); + pvr2_led_ctrl(hdw,st == PVR2_STATE_RUN); hdw->master_state = st; state_updated = !0; callback_flag = !0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 4fc9db3efff2..57e1ff491497 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -258,9 +258,6 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *); /* suspend */ int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *); -/* toggle LED */ -int pvr2_led_ctrl(struct pvr2_hdw *hdw, int onoff); - /* Order decoder to reset */ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *); -- cgit v1.2.3 From 5296b4d0779733a84adc9947d94dbbe9ee4656cb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:50 -0300 Subject: V4L/DVB (7314): pvrusb2: Make device attribute structure more compact Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 46 +++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index ce4004978a92..fb5f5d17e8cb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -65,52 +65,52 @@ struct pvr2_device_desc { was initialized from internal ROM. */ struct pvr2_string_table fx2_firmware; + /* Initial standard bits to use for this device, if not zero. + Anything set here is also implied as an available standard. + Note: This is ignored if overridden on the module load line via + the video_std module option. */ + v4l2_std_id default_std_mask; + + /* V4L tuner type ID to use with this device (only used if the + driver could not discover the type any other way). */ + int default_tuner_type; + /* Signal routing scheme used by device, contains one of PVR2_ROUTING_SCHEME_XXX. Schemes have to be defined as we encounter them. This is an arbitrary integer scheme id; its meaning is contained entirely within the driver and is interpreted by logic which must send commands to the chip-level drivers (search for things which touch this field). */ - unsigned int signal_routing_scheme; + unsigned char signal_routing_scheme; /* Indicates scheme for controlling device's LED (if any). The driver will turn on the LED when streaming is underway. This contains one of PVR2_LED_SCHEME_XXX. */ - unsigned int led_scheme; + unsigned char led_scheme; /* Control scheme to use if there is a digital tuner. This contains one of PVR2_DIGITAL_SCHEME_XXX. This is an arbitrary integer scheme id; its meaning is contained entirely within the driver and is interpreted by logic which must control the streaming pathway (search for things which touch this field). */ - unsigned int digital_control_scheme; - - /* V4L tuner type ID to use with this device (only used if the - driver could not discover the type any other way). */ - int default_tuner_type; - - /* Initial standard bits to use for this device, if not zero. - Anything set here is also implied as an available standard. - Note: This is ignored if overridden on the module load line via - the video_std module option. */ - v4l2_std_id default_std_mask; + unsigned char digital_control_scheme; /* If set, we don't bother trying to load cx23416 firmware. */ - char flag_skip_cx23416_firmware; + int flag_skip_cx23416_firmware:1; /* Device has a hauppauge eeprom which we can interrogate. */ - char flag_has_hauppauge_rom; + int flag_has_hauppauge_rom:1; /* Device does not require a powerup command to be issued. */ - char flag_no_powerup; + int flag_no_powerup:1; /* Device has a cx25840 - this enables special additional logic to handle it. */ - char flag_has_cx25840; + int flag_has_cx25840:1; /* Device has a wm8775 - this enables special additional logic to ensure that it is found. */ - char flag_has_wm8775; + int flag_has_wm8775:1; /* Device has IR hardware that can be faked into looking like a normal Hauppauge i2c IR receiver. This is currently very @@ -120,15 +120,15 @@ struct pvr2_device_desc { to virtualize the presence of the non-existant IR receiver chip and implement the virtual receiver in terms of appropriate FX2 commands. */ - char flag_has_hauppauge_custom_ir; + int flag_has_hauppauge_custom_ir:1; /* These bits define which kinds of sources the device can handle. Note: Digital tuner presence is inferred by the digital_control_scheme enumeration. */ - char flag_has_fmradio; /* Has FM radio receiver */ - char flag_has_analogtuner; /* Has analog tuner */ - char flag_has_composite; /* Has composite input */ - char flag_has_svideo; /* Has s-video input */ + int flag_has_fmradio:1; /* Has FM radio receiver */ + int flag_has_analogtuner:1; /* Has analog tuner */ + int flag_has_composite:1; /* Has composite input */ + int flag_has_svideo:1; /* Has s-video input */ }; extern struct usb_device_id pvr2_device_table[]; -- cgit v1.2.3 From 6a6eb66001e818a7d33f765289631c36be28f9dd Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:50 -0300 Subject: V4L/DVB (7315): pvrusb2: Add Gotview USB 2.0 DVD Deluxe to supported devices Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index da17554e7b0a..08fd5dcf7d59 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -123,6 +123,26 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = { +/*------------------------------------------------------------------------*/ +/* GOTVIEW USB2.0 DVD Deluxe */ + +/* (same module list as gotview_2) */ + +static const struct pvr2_device_desc pvr2_device_gotview_2d = { + .description = "Gotview USB 2.0 DVD Deluxe", + .shortname = "gv2d", + .client_modules.lst = pvr2_client_gotview_2, + .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2), + .flag_has_cx25840 = !0, + .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .flag_has_analogtuner = !0, + .flag_has_composite = !0, + .flag_has_svideo = !0, + .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW, +}; + + + #ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR /*------------------------------------------------------------------------*/ /* OnAir Creator */ @@ -216,6 +236,8 @@ struct usb_device_id pvr2_device_table[] = { .driver_info = (kernel_ulong_t)&pvr2_device_24xxx}, { USB_DEVICE(0x1164, 0x0622), .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2}, + { USB_DEVICE(0x1164, 0x0602), + .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d}, #ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR { USB_DEVICE(0x11ba, 0x1003), .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator}, -- cgit v1.2.3 From 42ae6f58fbfb80213bb45af8027b0601dbfa0473 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:51 -0300 Subject: V4L/DVB (7316): pvrusb2: Handle ATSC video standard bits The pvrusb2 driver dynamically generates an enumeration of support video standard combinations based on which video standard bits are set. ATSC modes don't fall into this since they are by nature not analog. The pvrusb2 driver has been warning about an inability to classify ATSC standards. This change causes the classification algorithm to ignore any ATSC standards (such things are better handled elsewhere anyway). Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-std.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c index da309288daa4..ddd3fc38a419 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-std.c +++ b/drivers/media/video/pvrusb2/pvrusb2-std.c @@ -79,7 +79,7 @@ struct std_name { #define TSTD_Nc (V4L2_STD_PAL_Nc) #define TSTD_60 (V4L2_STD_PAL_60) -#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM) +#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM) /* Mapping of standard bits to color system */ static const struct std_name std_groups[] = { @@ -328,7 +328,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, struct v4l2_standard *stddefs; if (pvrusb2_debug & PVR2_TRACE_STD) { - char buf[50]; + char buf[80]; bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id); pvr2_trace( PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)", @@ -352,8 +352,11 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++; } + /* Don't complain about ATSC standard values */ + fmsk &= ~CSTD_ATSC; + if (fmsk) { - char buf[50]; + char buf[80]; bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk); pvr2_trace( PVR2_TRACE_ERROR_LEGS, -- cgit v1.2.3 From a9988fdec78c68e7381fb0227b2f1430510d2b01 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:51 -0300 Subject: V4L/DVB (7317): pvrusb2: Increase buffer size for printing video standard strings Buffer size for printing pvrusb2 video standard strings was too small before. This is cosmetic; the printing logic is not able to overrun a too-short buffer. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-std.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c index ddd3fc38a419..fdc5a2b49ca8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-std.c +++ b/drivers/media/video/pvrusb2/pvrusb2-std.c @@ -328,7 +328,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, struct v4l2_standard *stddefs; if (pvrusb2_debug & PVR2_TRACE_STD) { - char buf[80]; + char buf[100]; bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id); pvr2_trace( PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)", @@ -356,7 +356,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, fmsk &= ~CSTD_ATSC; if (fmsk) { - char buf[80]; + char buf[100]; bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk); pvr2_trace( PVR2_TRACE_ERROR_LEGS, -- cgit v1.2.3 From f2c57a1b387c589446844422646f7d2a232bc830 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:51 -0300 Subject: V4L/DVB (7318): pvrusb2: Remove dead code Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-context.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h index a04187a93225..96b255f02381 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.h +++ b/drivers/media/video/pvrusb2/pvrusb2-context.h @@ -30,7 +30,6 @@ struct pvr2_stream; /* stream interface - defined elsewhere */ struct pvr2_context; /* All central state */ struct pvr2_channel; /* One I/O pathway to a user */ struct pvr2_context_stream; /* Wrapper for a stream */ -struct pvr2_crit_reg; /* Critical region pointer */ struct pvr2_ioread; /* Low level stream structure */ struct pvr2_context_stream { -- cgit v1.2.3 From c8ad8d7db5fdfe60796a34e37a7fef4350286b9a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:52 -0300 Subject: V4L/DVB (7319): pvrusb2: Close potential race condition during initialization There is a callback that is issued to into pvr2_context from pvr2_hdw after initialization is done. There was a probability that this callback could get missed. Fixed. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-context.c | 7 +++--- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 31 +++++++++++++++------------ drivers/media/video/pvrusb2/pvrusb2-hdw.h | 11 +++++----- 3 files changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index f2cffcdc7aba..c321ca2af81d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -76,10 +76,9 @@ struct pvr2_context *pvr2_context_create( mp = NULL; goto done; } - pvr2_hdw_set_state_callback(mp->hdw, - (void (*)(void *))pvr2_context_state_check, - mp); - pvr2_context_state_check(mp); + pvr2_hdw_initialize(mp->hdw, + (void (*)(void *))pvr2_context_state_check, + mp); done: return mp; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index defe0bec9bf8..87ba262eb2b8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1814,8 +1814,23 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw) } -/* Create and return a structure for interacting with the underlying - hardware */ +/* Perform second stage initialization. Set callback pointer first so that + we can avoid a possible initialization race (if the kernel thread runs + before the callback has been set). */ +void pvr2_hdw_initialize(struct pvr2_hdw *hdw, + void (*callback_func)(void *), + void *callback_data) +{ + LOCK_TAKE(hdw->big_lock); do { + hdw->state_data = callback_data; + hdw->state_func = callback_func; + } while (0); LOCK_GIVE(hdw->big_lock); + queue_work(hdw->workqueue,&hdw->workinit); +} + + +/* Create, set up, and return a structure for interacting with the + underlying hardware. */ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, const struct usb_device_id *devid) { @@ -2040,7 +2055,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, mutex_init(&hdw->ctl_lock_mutex); mutex_init(&hdw->big_lock_mutex); - queue_work(hdw->workqueue,&hdw->workinit); return hdw; fail: if (hdw) { @@ -2522,17 +2536,6 @@ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state) } -void pvr2_hdw_set_state_callback(struct pvr2_hdw *hdw, - void (*callback_func)(void *), - void *callback_data) -{ - LOCK_TAKE(hdw->big_lock); do { - hdw->state_data = callback_data; - hdw->state_func = callback_func; - } while (0); LOCK_GIVE(hdw->big_lock); -} - - /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 57e1ff491497..597ee5033149 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -101,14 +101,15 @@ struct pvr2_hdw; struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, const struct usb_device_id *devid); +/* Perform second stage initialization, passing in a notification callback + for when the master state changes. */ +void pvr2_hdw_initialize(struct pvr2_hdw *, + void (*callback_func)(void *), + void *callback_data); + /* Destroy hardware interaction structure */ void pvr2_hdw_destroy(struct pvr2_hdw *); -/* Register a function to be called whenever the master state changes. */ -void pvr2_hdw_set_state_callback(struct pvr2_hdw *, - void (*callback_func)(void *), - void *callback_data); - /* Return true if in the ready (normal) state */ int pvr2_hdw_dev_ok(struct pvr2_hdw *); -- cgit v1.2.3 From 02bc26ba9451a353fd25d4cc1da039b7833f5861 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:52 -0300 Subject: V4L/DVB (7320): pvrusb2: Eliminate timer race during tear-down The pvrusb2 tear-down logic was clearing two timers before stopping its internal work queue. That left a tiny window open where the work queue might run after the timers are stopped, possibly starting them again. This could lead to dangling pointers and an oops. Solution: Kill the work queue first, then delete the timers. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 87ba262eb2b8..24a85964214f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2115,13 +2115,13 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) { if (!hdw) return; pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw); - del_timer_sync(&hdw->quiescent_timer); - del_timer_sync(&hdw->encoder_wait_timer); if (hdw->workqueue) { flush_workqueue(hdw->workqueue); destroy_workqueue(hdw->workqueue); hdw->workqueue = NULL; } + del_timer_sync(&hdw->quiescent_timer); + del_timer_sync(&hdw->encoder_wait_timer); if (hdw->fw_buffer) { kfree(hdw->fw_buffer); hdw->fw_buffer = NULL; -- cgit v1.2.3 From 012308646417bd2985c995a48364080e80819e0e Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 2 Apr 2008 14:27:52 -0300 Subject: V4L/DVB (7321): pvrusb2: Rework context handling and initialization This change significantly rearranges pvr2_context level initialization and operation: 1. A new kernel thread is set up for management of the context. 2. Destruction of the pvr2_context instance is moved into the kernel thread. No other context is able to remove the instance; doing this simplifies lock handling. 3. The callback into pvrusb2-main, which is used to trigger initialization of each interface, is now issued from this kernel thread. Previously it had been indirectly issued out of the work queue thread in pvr2_hdw, which led to deadlock issues if the interface needed to change a control setting (which in turn requires dispatch of another work queue entry). 4. Callbacks into the interfaces (via the pvr2_channel structure) are now issued strictly from this thread. The net result of this is that such callback functions can now also safely operate driver controls without deadlocking the work queue. (At the moment this is not actually a problem, but I'm anticipating issues with this in the future). 5. There is no longer any need for anyone to enter / exit the pvr2_context structure. Implementation of the kernel thread here allows this all to be internal now, simplifying other logic. 6. A very very longstanding issue involving a mutex deadlock between the pvrusb2 driver and v4l should now be solved. The deadlock involved the pvr2_context mutex and a globals-protecting mutex in v4l. During initialization the driver would take the pvr2_context mutex first then the v4l2 interface would register with v4l and implicitly take the v4l mutex. Later when v4l would call back into the driver, the two mutexes could possibly be taken in the opposite order, a situation that can lead to deadlock. In practice this really wasn't an issue unless a v4l app tried to start VERY early after the driver appeared. However it still needed to be solved, and with the use of the kernel thread relieving need for pvr2_context mutex, the problem should be finally solved. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-context.c | 113 ++++++++++++-------- drivers/media/video/pvrusb2/pvrusb2-context.h | 7 +- drivers/media/video/pvrusb2/pvrusb2-debug.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 1 - drivers/media/video/pvrusb2/pvrusb2-hdw.c | 20 +--- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 6 +- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 115 ++++++++++----------- 7 files changed, 137 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index c321ca2af81d..d0e6430aef5a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -23,6 +23,7 @@ #include "pvrusb2-ioread.h" #include "pvrusb2-hdw.h" #include "pvrusb2-debug.h" +#include #include #include #include @@ -31,32 +32,65 @@ static void pvr2_context_destroy(struct pvr2_context *mp) { - pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp); + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp); if (mp->hdw) pvr2_hdw_destroy(mp->hdw); kfree(mp); } -static void pvr2_context_state_check(struct pvr2_context *mp) +static void pvr2_context_notify(struct pvr2_context *mp) { - if (mp->init_flag) return; - - switch (pvr2_hdw_get_state(mp->hdw)) { - case PVR2_STATE_WARM: break; - case PVR2_STATE_ERROR: break; - case PVR2_STATE_READY: break; - case PVR2_STATE_RUN: break; - default: return; + mp->notify_flag = !0; + wake_up(&mp->wait_data); +} + + +static int pvr2_context_thread(void *_mp) +{ + struct pvr2_channel *ch1,*ch2; + struct pvr2_context *mp = _mp; + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread start)",mp); + + /* Finish hardware initialization */ + if (pvr2_hdw_initialize(mp->hdw, + (void (*)(void *))pvr2_context_notify,mp)) { + mp->video_stream.stream = + pvr2_hdw_get_video_stream(mp->hdw); + /* Trigger interface initialization. By doing this here + initialization runs in our own safe and cozy thread + context. */ + if (mp->setup_func) mp->setup_func(mp); + } else { + pvr2_trace(PVR2_TRACE_CTXT, + "pvr2_context %p (thread skipping setup)",mp); + /* Even though initialization did not succeed, we're still + going to enter the wait loop anyway. We need to do this + in order to await the expected disconnect (which we will + detect in the normal course of operation). */ } - pvr2_context_enter(mp); do { - mp->init_flag = !0; - mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw); - if (mp->setup_func) { - mp->setup_func(mp); + /* Now just issue callbacks whenever hardware state changes or if + there is a disconnect. If there is a disconnect and there are + no channels left, then there's no reason to stick around anymore + so we'll self-destruct - tearing down the rest of this driver + instance along the way. */ + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread enter loop)",mp); + while (!mp->disconnect_flag || mp->mc_first) { + if (mp->notify_flag) { + mp->notify_flag = 0; + pvr2_trace(PVR2_TRACE_CTXT, + "pvr2_context %p (thread notify)",mp); + for (ch1 = mp->mc_first; ch1; ch1 = ch2) { + ch2 = ch1->mc_next; + if (ch1->check_func) ch1->check_func(ch1); + } } - } while (0); pvr2_context_exit(mp); - } + wait_event_interruptible(mp->wait_data, mp->notify_flag); + } + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread end)",mp); + pvr2_context_destroy(mp); + return 0; +} struct pvr2_context *pvr2_context_create( @@ -64,10 +98,12 @@ struct pvr2_context *pvr2_context_create( const struct usb_device_id *devid, void (*setup_func)(struct pvr2_context *)) { + struct task_struct *thread; struct pvr2_context *mp = NULL; mp = kzalloc(sizeof(*mp),GFP_KERNEL); if (!mp) goto done; - pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp); + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp); + init_waitqueue_head(&mp->wait_data); mp->setup_func = setup_func; mutex_init(&mp->mutex); mp->hdw = pvr2_hdw_create(intf,devid); @@ -76,57 +112,45 @@ struct pvr2_context *pvr2_context_create( mp = NULL; goto done; } - pvr2_hdw_initialize(mp->hdw, - (void (*)(void *))pvr2_context_state_check, - mp); + thread = kthread_run(pvr2_context_thread, mp, "pvrusb2-context"); + if (!thread) { + pvr2_context_destroy(mp); + mp = NULL; + goto done; + } done: return mp; } -void pvr2_context_enter(struct pvr2_context *mp) +static void pvr2_context_enter(struct pvr2_context *mp) { mutex_lock(&mp->mutex); - pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp); } -void pvr2_context_exit(struct pvr2_context *mp) +static void pvr2_context_exit(struct pvr2_context *mp) { int destroy_flag = 0; if (!(mp->mc_first || !mp->disconnect_flag)) { destroy_flag = !0; } - pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp); mutex_unlock(&mp->mutex); - if (destroy_flag) pvr2_context_destroy(mp); -} - - -static void pvr2_context_run_checks(struct pvr2_context *mp) -{ - struct pvr2_channel *ch1,*ch2; - for (ch1 = mp->mc_first; ch1; ch1 = ch2) { - ch2 = ch1->mc_next; - if (ch1->check_func) { - ch1->check_func(ch1); - } - } + if (destroy_flag) pvr2_context_notify(mp); } void pvr2_context_disconnect(struct pvr2_context *mp) { - pvr2_context_enter(mp); do { - pvr2_hdw_disconnect(mp->hdw); - mp->disconnect_flag = !0; - pvr2_context_run_checks(mp); - } while (0); pvr2_context_exit(mp); + pvr2_hdw_disconnect(mp->hdw); + mp->disconnect_flag = !0; + pvr2_context_notify(mp); } void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp) { + pvr2_context_enter(mp); cp->hdw = mp->hdw; cp->mc_head = mp; cp->mc_next = NULL; @@ -137,6 +161,7 @@ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp) mp->mc_first = cp; } mp->mc_last = cp; + pvr2_context_exit(mp); } @@ -152,6 +177,7 @@ static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp) void pvr2_channel_done(struct pvr2_channel *cp) { struct pvr2_context *mp = cp->mc_head; + pvr2_context_enter(mp); pvr2_channel_disclaim_stream(cp); if (cp->mc_next) { cp->mc_next->mc_prev = cp->mc_prev; @@ -164,6 +190,7 @@ void pvr2_channel_done(struct pvr2_channel *cp) mp->mc_first = cp->mc_next; } cp->hdw = NULL; + pvr2_context_exit(mp); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h index 96b255f02381..127ec53e0913 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.h +++ b/drivers/media/video/pvrusb2/pvrusb2-context.h @@ -43,8 +43,10 @@ struct pvr2_context { struct pvr2_hdw *hdw; struct pvr2_context_stream video_stream; struct mutex mutex; + int notify_flag; int disconnect_flag; - int init_flag; + + wait_queue_head_t wait_data; /* Called after pvr2_context initialization is complete */ void (*setup_func)(struct pvr2_context *); @@ -60,9 +62,6 @@ struct pvr2_channel { void (*check_func)(struct pvr2_channel *); }; -void pvr2_context_enter(struct pvr2_context *); -void pvr2_context_exit(struct pvr2_context *); - struct pvr2_context *pvr2_context_create(struct usb_interface *intf, const struct usb_device_id *devid, void (*setup_func)(struct pvr2_context *)); diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h index fca49d8a9311..11537ddf8aa3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debug.h +++ b/drivers/media/video/pvrusb2/pvrusb2-debug.h @@ -39,7 +39,7 @@ extern int pvrusb2_debug; #define PVR2_TRACE_EEPROM (1 << 10) /* eeprom parsing / report */ #define PVR2_TRACE_STRUCT (1 << 11) /* internal struct creation */ #define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */ -#define PVR2_TRACE_CREG (1 << 13) /* Main critical region entry / exit */ +#define PVR2_TRACE_CTXT (1 << 13) /* Main context tracking */ #define PVR2_TRACE_SYSFS (1 << 14) /* Sysfs driven I/O */ #define PVR2_TRACE_FIRMWARE (1 << 15) /* firmware upload actions */ #define PVR2_TRACE_CHIPS (1 << 16) /* chip broadcast operation */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index bc341ae5c79a..c725495826ce 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -187,7 +187,6 @@ struct pvr2_hdw { struct workqueue_struct *workqueue; struct work_struct workpoll; /* Update driver state */ struct work_struct worki2csync; /* Update i2c clients */ - struct work_struct workinit; /* Driver initialization sequence */ /* Video spigot */ struct pvr2_stream *vid_stream; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 24a85964214f..07f6aeaec2ab 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -222,7 +222,6 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *); static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); static void pvr2_hdw_worker_i2c(struct work_struct *work); static void pvr2_hdw_worker_poll(struct work_struct *work); -static void pvr2_hdw_worker_init(struct work_struct *work); static int pvr2_hdw_wait(struct pvr2_hdw *,int state); static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *); static void pvr2_hdw_state_log_state(struct pvr2_hdw *); @@ -1817,15 +1816,16 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw) /* Perform second stage initialization. Set callback pointer first so that we can avoid a possible initialization race (if the kernel thread runs before the callback has been set). */ -void pvr2_hdw_initialize(struct pvr2_hdw *hdw, - void (*callback_func)(void *), - void *callback_data) +int pvr2_hdw_initialize(struct pvr2_hdw *hdw, + void (*callback_func)(void *), + void *callback_data) { LOCK_TAKE(hdw->big_lock); do { hdw->state_data = callback_data; hdw->state_func = callback_func; } while (0); LOCK_GIVE(hdw->big_lock); - queue_work(hdw->workqueue,&hdw->workinit); + pvr2_hdw_setup(hdw); + return hdw->flag_init_ok; } @@ -2033,7 +2033,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->workqueue = create_singlethread_workqueue(hdw->name); INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll); INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c); - INIT_WORK(&hdw->workinit,pvr2_hdw_worker_init); pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s", hdw->unit_number,hdw->name); @@ -2518,15 +2517,6 @@ static void pvr2_hdw_worker_poll(struct work_struct *work) } -static void pvr2_hdw_worker_init(struct work_struct *work) -{ - struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workinit); - LOCK_TAKE(hdw->big_lock); do { - pvr2_hdw_setup(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); -} - - static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state) { return wait_event_interruptible( diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 597ee5033149..a868e52a73a3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -103,9 +103,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, /* Perform second stage initialization, passing in a notification callback for when the master state changes. */ -void pvr2_hdw_initialize(struct pvr2_hdw *, - void (*callback_func)(void *), - void *callback_data); +int pvr2_hdw_initialize(struct pvr2_hdw *, + void (*callback_func)(void *), + void *callback_data); /* Destroy hardware interaction structure */ void pvr2_hdw_destroy(struct pvr2_hdw *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index e878c6445ae2..249d7488e482 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -884,7 +884,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) { struct pvr2_v4l2_fh *fhp = file->private_data; struct pvr2_v4l2 *vp = fhp->vhead; - struct pvr2_context *mp = fhp->vhead->channel.mc_head; struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw; pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release"); @@ -901,42 +900,40 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) v4l2_prio_close(&vp->prio, &fhp->prio); file->private_data = NULL; - pvr2_context_enter(mp); do { - /* Restore the previous input selection, if it makes sense - to do so. */ - if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) { - struct pvr2_ctrl *cp; - int pval; - cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); - pvr2_ctrl_get_value(cp,&pval); - /* Only restore if we're still selecting the radio */ - if (pval == PVR2_CVAL_INPUT_RADIO) { - pvr2_ctrl_set_value(cp,fhp->prev_input_val); - pvr2_hdw_commit_ctl(hdw); - } + /* Restore the previous input selection, if it makes sense + to do so. */ + if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) { + struct pvr2_ctrl *cp; + int pval; + cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); + pvr2_ctrl_get_value(cp,&pval); + /* Only restore if we're still selecting the radio */ + if (pval == PVR2_CVAL_INPUT_RADIO) { + pvr2_ctrl_set_value(cp,fhp->prev_input_val); + pvr2_hdw_commit_ctl(hdw); } + } - if (fhp->vnext) { - fhp->vnext->vprev = fhp->vprev; - } else { - vp->vlast = fhp->vprev; - } - if (fhp->vprev) { - fhp->vprev->vnext = fhp->vnext; - } else { - vp->vfirst = fhp->vnext; - } - fhp->vnext = NULL; - fhp->vprev = NULL; - fhp->vhead = NULL; - pvr2_channel_done(&fhp->channel); - pvr2_trace(PVR2_TRACE_STRUCT, - "Destroying pvr_v4l2_fh id=%p",fhp); - kfree(fhp); - if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { - pvr2_v4l2_destroy_no_lock(vp); - } - } while (0); pvr2_context_exit(mp); + if (fhp->vnext) { + fhp->vnext->vprev = fhp->vprev; + } else { + vp->vlast = fhp->vprev; + } + if (fhp->vprev) { + fhp->vprev->vnext = fhp->vnext; + } else { + vp->vfirst = fhp->vnext; + } + fhp->vnext = NULL; + fhp->vprev = NULL; + fhp->vhead = NULL; + pvr2_channel_done(&fhp->channel); + pvr2_trace(PVR2_TRACE_STRUCT, + "Destroying pvr_v4l2_fh id=%p",fhp); + kfree(fhp); + if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { + pvr2_v4l2_destroy_no_lock(vp); + } return 0; } @@ -969,32 +966,30 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) init_waitqueue_head(&fhp->wait_data); fhp->dev_info = dip; - pvr2_context_enter(vp->channel.mc_head); do { - pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); - pvr2_channel_init(&fhp->channel,vp->channel.mc_head); + pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); + pvr2_channel_init(&fhp->channel,vp->channel.mc_head); - fhp->vnext = NULL; - fhp->vprev = vp->vlast; - if (vp->vlast) { - vp->vlast->vnext = fhp; - } else { - vp->vfirst = fhp; - } - vp->vlast = fhp; - fhp->vhead = vp; - - /* Opening the /dev/radioX device implies a mode switch. - So execute that here. Note that you can get the - IDENTICAL effect merely by opening the normal video - device and setting the input appropriately. */ - if (dip->v4l_type == VFL_TYPE_RADIO) { - struct pvr2_ctrl *cp; - cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); - pvr2_ctrl_get_value(cp,&fhp->prev_input_val); - pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO); - pvr2_hdw_commit_ctl(hdw); - } - } while (0); pvr2_context_exit(vp->channel.mc_head); + fhp->vnext = NULL; + fhp->vprev = vp->vlast; + if (vp->vlast) { + vp->vlast->vnext = fhp; + } else { + vp->vfirst = fhp; + } + vp->vlast = fhp; + fhp->vhead = vp; + + /* Opening the /dev/radioX device implies a mode switch. + So execute that here. Note that you can get the + IDENTICAL effect merely by opening the normal video + device and setting the input appropriately. */ + if (dip->v4l_type == VFL_TYPE_RADIO) { + struct pvr2_ctrl *cp; + cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); + pvr2_ctrl_get_value(cp,&fhp->prev_input_val); + pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO); + pvr2_hdw_commit_ctl(hdw); + } fhp->file = file; file->private_data = fhp; -- cgit v1.2.3 From 7e3b1df9c8129f38f59225697afd52f02ac9f2b0 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 2 Apr 2008 14:27:52 -0300 Subject: V4L/DVB (7322): pvrusb2: Fix storage-class as per C99 spec The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 07f6aeaec2ab..7be32cc1d146 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1503,7 +1503,7 @@ struct pvr2_std_hack { default - which can always be overridden explicitly - and if the user has otherwise named a default then that default will always be used in place of this table. */ -const static struct pvr2_std_hack std_eeprom_maps[] = { +static const struct pvr2_std_hack std_eeprom_maps[] = { { /* PAL(B/G) */ .pat = V4L2_STD_B|V4L2_STD_GH, .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G, @@ -3696,7 +3696,7 @@ static int state_update_pipeline_state(struct pvr2_hdw *hdw) typedef int (*state_eval_func)(struct pvr2_hdw *); /* Set of functions to be run to evaluate various states in the driver. */ -const static state_eval_func eval_funcs[] = { +static const state_eval_func eval_funcs[] = { state_eval_pathway_ok, state_eval_pipeline_config, state_eval_encoder_ok, -- cgit v1.2.3 From 5c4f86e0da152a6e07254bd0ee84923a3ed554a9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:53 -0300 Subject: V4L/DVB (7323): pvrusb2: set default video standard to NTSC for OnAir HDTV / Creator The pvrusb2 driver normally picks up the default video standard from the eeprom on Hauppauge devices, but the OnAir HDTV and OnAir Creator are not Hauppauge devices, and do not store this information in any eeprom. These devices support NTSC/ATSC, so we should use NTSC by default when in analog mode. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 08fd5dcf7d59..c54b23787ef1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -164,6 +164,7 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, + .default_std_mask = V4L2_STD_NTSC_M, }; #endif @@ -190,6 +191,7 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, + .default_std_mask = V4L2_STD_NTSC_M, }; #endif -- cgit v1.2.3 From d69bad9d3fffb777d64b79ccc727e9f7c3c0bad0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:27:53 -0300 Subject: V4L/DVB (7325): cx88-dvb: fix an OOPS for xc3028 devices, when dvb_attach fails If dvb_attach fails, dev->dvb.frontend is NULL. This will produce an OOPS, as reported. Thanks to Vanessa Ezekowitz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index cf6b9b05f496..d72b817bf886 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -461,6 +461,13 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) .video_dev = dev->core, }; + if (!dev->dvb.frontend) { + printk(KERN_ERR "%s/2: dvb frontend not attached. " + "Can't attach xc3028\n", + dev->core->name); + return -EINVAL; + } + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", -- cgit v1.2.3 From 5a7441d0c87d6426b6e3cb3ca945eadad8fc64d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:27:53 -0300 Subject: V4L/DVB (7326): Fix bad whitespaces Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 264 +++++++++++++++++----------------- 1 file changed, 132 insertions(+), 132 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 7a2b0f26921a..3e7ddee9aba6 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1437,140 +1437,140 @@ static const struct cx88_board cx88_boards[] = { .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_PINNACLE_HYBRID_PCTV] = { - .name = "Pinnacle Hybrid PCTV", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x004ff, - .gpio1 = 0x010ff, - .gpio2 = 0x0ff, - }, - }, - [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { - .name = "Winfast TV2000 XP Global", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ - .gpio1 = 0x0000, - .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ - - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ - .gpio1 = 0x0000, - .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ - - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x004ff, - .gpio1 = 0x010ff, - .gpio2 = 0x0ff, - }, - }, - [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { - .name = "PowerColor Real Angel 330", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ - .gpio1 = 0xf35d, - .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ - .gpio1 = 0x0000, - .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000ff, - .gpio1 = 0x0f37d, - .gpio2 = 0x00019, - .gpio3 = 0x00000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x000ff, - .gpio1 = 0x0f35d, - .gpio2 = 0x00019, - .gpio3 = 0x00000, - }, - }, - [CX88_BOARD_GENIATECH_X8000_MT] = { + .name = "Pinnacle Hybrid PCTV", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + }, + [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { + .name = "Winfast TV2000 XP Global", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio1 = 0x0000, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio1 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + }, + [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { + .name = "PowerColor Real Angel 330", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio1 = 0xf35d, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio1 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000ff, + .gpio1 = 0x0f37d, + .gpio2 = 0x00019, + .gpio3 = 0x00000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000ff, + .gpio1 = 0x0f35d, + .gpio2 = 0x00019, + .gpio3 = 0x00000, + }, + }, + [CX88_BOARD_GENIATECH_X8000_MT] = { /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */ - .name = "Geniatech X8000-MT DVBT", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00000000, - .gpio1 = 0x00e3e341, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00000000, - .gpio1 = 0x00e3e361, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00000000, - .gpio1 = 0x00e3e361, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x00000000, - .gpio1 = 0x00e3e341, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { - .name = "DViCO FusionHDTV DVB-T PRO", - .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */ - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000067df, + .name = "Geniatech X8000-MT DVBT", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e341, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e361, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000067df, - } }, - .mpeg = CX88_MPEG_DVB, - }, + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e361, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e341, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, + .mpeg = CX88_MPEG_DVB, + }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { + .name = "DViCO FusionHDTV DVB-T PRO", + .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = { { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000067df, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000067df, + } }, + .mpeg = CX88_MPEG_DVB, + }, [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = { .name = "DViCO FusionHDTV 7 Gold", .tuner_type = TUNER_XC5000, -- cgit v1.2.3 From 9a9bbdcb4ffdbbeeedc0bffb9baabd2f219c3169 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:27:53 -0300 Subject: V4L/DVB (7327): cx88: Fix memset for tuner-xc3028 control Fix a cut-and-paste error Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 3e7ddee9aba6..4c1e876a9232 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2416,7 +2416,7 @@ static void cx88_card_setup(struct cx88_core *core) struct v4l2_priv_tun_config xc2028_cfg; struct xc2028_ctrl ctl; - memset(&xc2028_cfg, 0, sizeof(ctl)); + memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); memset(&ctl, 0, sizeof(ctl)); ctl.fname = XC2028_DEFAULT_FIRMWARE; -- cgit v1.2.3 From 75e5cf5025b2b0ef63a657f70dbb1443780fd844 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Wed, 2 Apr 2008 14:27:54 -0300 Subject: V4L/DVB (7329): add flag to allow software demux to recognize the output type Previously, the macro DVR_FEED, which is used to recognize and filter out duplicate packets going to the DVR device, used the TS_PAYLOAD_ONLY flag to identify a packet's destination. This kind of filtering was introduced by the following two changesets: Now, that it is possible to record TS PIDs using the demux device by setting the output type to DMX_OUT_TSDEMUX_TAP, checking TS_PAYLOAD_ONLY is not sufficient anymore. Therefore another flag, TS_DEMUX, is added to specify the output type of a feed. This allows multiple clients to filter the same TS PID on a demux device simultaneously. Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/demux.h | 2 ++ drivers/media/dvb/dvb-core/dmxdev.c | 9 +++++---- drivers/media/dvb/dvb-core/dvb_demux.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h index 0c1d87c5227a..b0d347daae47 100644 --- a/drivers/media/dvb/dvb-core/demux.h +++ b/drivers/media/dvb/dvb-core/demux.h @@ -80,6 +80,8 @@ enum dmx_success { #define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS payload (<=184 bytes per packet) to callback */ #define TS_DECODER 4 /* send stream to built-in decoder (if present) */ +#define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to + the demux device, not to the dvr device */ /* PES type for filters which write to built-in decoder */ /* these should be kept identical to the types in dmx.h */ diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index e7f7aef862a8..716735f03f55 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -619,11 +619,12 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) else ts_type = 0; - if (otype == DMX_OUT_TS_TAP || otype == DMX_OUT_TSDEMUX_TAP) + if (otype == DMX_OUT_TS_TAP) ts_type |= TS_PACKET; - - if (otype == DMX_OUT_TAP) - ts_type |= TS_PAYLOAD_ONLY | TS_PACKET; + else if (otype == DMX_OUT_TSDEMUX_TAP) + ts_type |= TS_PACKET | TS_DEMUX; + else if (otype == DMX_OUT_TAP) + ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY; ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, tsfeed, diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 7959020f9317..988d14302cb1 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -368,7 +368,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, #define DVR_FEED(f) \ (((f)->type == DMX_TYPE_TS) && \ ((f)->feed.ts.is_filtering) && \ - (((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET)) + (((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET)) static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) { -- cgit v1.2.3 From 41608b1d9fc3047b8a7b84fc44d1bc63a4b40778 Mon Sep 17 00:00:00 2001 From: Sascha Sommer Date: Wed, 2 Apr 2008 14:27:54 -0300 Subject: V4L/DVB (7331): Fix em2800 altsetting selection Signed-off-by: Sascha Sommer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index dbea89c115b1..4ebef10b5722 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -813,19 +813,27 @@ int em28xx_set_alternate(struct em28xx *dev) { int errCode, prev_alt = dev->alt; int i; - unsigned int min_pkt_size = dev->bytesperline+4; + unsigned int min_pkt_size = dev->bytesperline + 4; - /* When image size is bigger than a ceirtain value, + /* When image size is bigger than a certain value, the frame size should be increased, otherwise, only green screen will be received. */ if (dev->frame_size > 720*240*2) min_pkt_size *= 2; - for (i = 0; i < dev->num_alt; i++) - if (dev->alt_max_pkt_size[i] >= min_pkt_size) + for (i = 0; i < dev->num_alt; i++) { + /* stop when the selected alt setting offers enough bandwidth */ + if (dev->alt_max_pkt_size[i] >= min_pkt_size) { + dev->alt = i; break; - dev->alt = i; + /* otherwise make sure that we end up with the maximum bandwidth + because the min_pkt_size equation might be wrong... + */ + } else if (dev->alt_max_pkt_size[i] > + dev->alt_max_pkt_size[dev->alt]) + dev->alt = i; + } if (dev->alt != prev_alt) { em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", -- cgit v1.2.3 From 94eb0632691844f51d9f5de3c6a02313b331eb23 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 2 Apr 2008 14:27:54 -0300 Subject: V4L/DVB (7332): ir-kbd-i2c: Minor optimization in ir_probe This saves an initialization and a comparison. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ir-kbd-i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index d17f0d4e6544..81458fb405e2 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -509,7 +509,7 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_em28XX[] = { 0x30, 0x47, -1 }; static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 }; static const int probe_cx23885[] = { 0x6b, -1 }; - const int *probe = NULL; + const int *probe; struct i2c_client *c; unsigned char buf; int i, rc; @@ -533,9 +533,9 @@ static int ir_probe(struct i2c_adapter *adap) case I2C_HW_B_CX23885: probe = probe_cx23885; break; - } - if (NULL == probe) + default: return 0; + } c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) -- cgit v1.2.3 From 4fe3bbdd8d2c2f17bf03f411b16c59dd24c534ef Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 2 Apr 2008 14:27:55 -0300 Subject: V4L/DVB (7335): usb-video: checkpatch fixes Please run checkpatch prior to sending patches Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvideo/usbvideo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index f1ccf59545d4..7f3cdc9a0624 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -1035,10 +1035,10 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits); } if (uvd->dev == NULL) { - err("%s: uvd->dev == NULL", __FUNCTION__); + err("%s: uvd->dev == NULL", __func__); return -EINVAL; } - uvd->vdev.dev=&(uvd->dev->dev); + uvd->vdev.dev = &uvd->dev->dev; if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { err("%s: video_register_device failed", __FUNCTION__); return -EPIPE; -- cgit v1.2.3 From a2e9f6120bb0ae3bc45c7af1f396fa0ba6e7aeef Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:27:55 -0300 Subject: V4L/DVB (7336): soc-camera: streamline hardware parameter negotiation Improve hardware parameter negotiation between the camera host driver and camera drivers. Parameters like horizontal and vertical synchronisation, pixel clock polarity shall be set depending on capabilities of the parties. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 77 +++++++++++-------- drivers/media/video/mt9v022.c | 129 +++++++++++++++++++------------- drivers/media/video/pxa_camera.c | 156 ++++++++++++++++++++++++++++----------- drivers/media/video/soc_camera.c | 49 ++++++------ include/media/soc_camera.h | 52 +++++++++---- 5 files changed, 301 insertions(+), 162 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 4ad834326fa8..acb5454b57eb 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -210,40 +210,64 @@ static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) #endif } -static int mt9m001_set_capture_format(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +static int bus_switch_possible(struct mt9m001 *mt9m001) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + return gpio_is_valid(mt9m001->switch_gpio); +#else + return 0; +#endif +} + +static int mt9m001_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | - IS_DATAWIDTH_8); + unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; - const u16 hblank = 9, vblank = 25; - /* MT9M001 has all capture_format parameters fixed */ - if (!(flags & IS_MASTER) || - !(flags & IS_PCLK_SAMPLE_RISING) || - !(flags & IS_HSYNC_ACTIVE_HIGH) || - !(flags & IS_VSYNC_ACTIVE_HIGH)) - return -EINVAL; - - /* Only one width bit may be set */ - if (!is_power_of_2(width_flag)) - return -EINVAL; + /* Flags validity verified in test_bus_param */ - if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || - (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || - (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { + if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || + (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || + (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { /* Well, we actually only can do 10 or 8 bits... */ - if (width_flag == IS_DATAWIDTH_9) + if (width_flag == SOCAM_DATAWIDTH_9) return -EINVAL; ret = bus_switch_act(mt9m001, - width_flag == IS_DATAWIDTH_8); + width_flag == SOCAM_DATAWIDTH_8); if (ret < 0) return ret; - mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; + mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; } + return 0; +} + +static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + unsigned int width_flag = SOCAM_DATAWIDTH_10; + + if (bus_switch_possible(mt9m001)) + width_flag |= SOCAM_DATAWIDTH_8; + + /* MT9M001 has all capture_format parameters fixed */ + return SOCAM_PCLK_SAMPLE_RISING | + SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_MASTER | + width_flag; +} + +static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + int ret; + const u16 hblank = 9, vblank = 25; + /* Blanking and start values - default... */ ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); if (ret >= 0) @@ -348,12 +372,6 @@ static int mt9m001_set_register(struct soc_camera_device *icd, } #endif -static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd) -{ - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - return mt9m001->datawidth; -} - const struct v4l2_queryctrl mt9m001_controls[] = { { .id = V4L2_CID_VFLIP, @@ -401,11 +419,12 @@ static struct soc_camera_ops mt9m001_ops = { .release = mt9m001_release, .start_capture = mt9m001_start_capture, .stop_capture = mt9m001_stop_capture, - .set_capture_format = mt9m001_set_capture_format, + .set_fmt_cap = mt9m001_set_fmt_cap, .try_fmt_cap = mt9m001_try_fmt_cap, + .set_bus_param = mt9m001_set_bus_param, + .query_bus_param = mt9m001_query_bus_param, .formats = NULL, /* Filled in later depending on the */ .num_formats = 0, /* camera type and data widths */ - .get_datawidth = mt9m001_get_datawidth, .controls = mt9m001_controls, .num_controls = ARRAY_SIZE(mt9m001_controls), .get_control = mt9m001_get_control, diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index d677344d233d..a2f161dcc72d 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -241,19 +241,89 @@ static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit) #endif } -static int mt9v022_set_capture_format(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +static int bus_switch_possible(struct mt9v022 *mt9v022) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + return gpio_is_valid(mt9v022->switch_gpio); +#else + return 0; +#endif +} + +static int mt9v022_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | - IS_DATAWIDTH_8); - u16 pixclk = 0; + unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; + u16 pixclk = 0; /* Only one width bit may be set */ if (!is_power_of_2(width_flag)) return -EINVAL; + if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || + (mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || + (mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { + /* Well, we actually only can do 10 or 8 bits... */ + if (width_flag == SOCAM_DATAWIDTH_9) + return -EINVAL; + + ret = bus_switch_act(mt9v022, + width_flag == SOCAM_DATAWIDTH_8); + if (ret < 0) + return ret; + + mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; + } + + if (flags & SOCAM_PCLK_SAMPLE_RISING) + pixclk |= 0x10; + + if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH)) + pixclk |= 0x1; + + if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH)) + pixclk |= 0x2; + + ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); + if (ret < 0) + return ret; + + if (!(flags & SOCAM_MASTER)) + mt9v022->chip_control &= ~0x8; + + ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + if (ret < 0) + return ret; + + dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", + pixclk, mt9v022->chip_control); + + return 0; +} + +static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + unsigned int width_flag = SOCAM_DATAWIDTH_10; + + if (bus_switch_possible(mt9v022)) + width_flag |= SOCAM_DATAWIDTH_8; + + return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | + SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_MASTER | SOCAM_SLAVE | + width_flag; +} + +static int mt9v022_set_fmt_cap(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + int ret; + /* The caller provides a supported format, as verified per call to * icd->try_fmt_cap(), datawidth is from our supported format list */ switch (pixfmt) { @@ -308,44 +378,6 @@ static int mt9v022_set_capture_format(struct soc_camera_device *icd, dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); - if ((mt9v022->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || - (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || - (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { - /* Well, we actually only can do 10 or 8 bits... */ - if (width_flag == IS_DATAWIDTH_9) - return -EINVAL; - - ret = bus_switch_act(mt9v022, - width_flag == IS_DATAWIDTH_8); - if (ret < 0) - return ret; - - mt9v022->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; - } - - if (flags & IS_PCLK_SAMPLE_RISING) - pixclk |= 0x10; - - if (!(flags & IS_HSYNC_ACTIVE_HIGH)) - pixclk |= 0x1; - - if (!(flags & IS_VSYNC_ACTIVE_HIGH)) - pixclk |= 0x2; - - ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); - if (ret < 0) - return ret; - - if (!(flags & IS_MASTER)) - mt9v022->chip_control &= ~0x8; - - ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); - if (ret < 0) - return ret; - - dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", - pixclk, mt9v022->chip_control); - return 0; } @@ -420,12 +452,6 @@ static int mt9v022_set_register(struct soc_camera_device *icd, } #endif -static unsigned int mt9v022_get_datawidth(struct soc_camera_device *icd) -{ - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - return mt9v022->datawidth; -} - const struct v4l2_queryctrl mt9v022_controls[] = { { .id = V4L2_CID_VFLIP, @@ -491,11 +517,12 @@ static struct soc_camera_ops mt9v022_ops = { .release = mt9v022_release, .start_capture = mt9v022_start_capture, .stop_capture = mt9v022_stop_capture, - .set_capture_format = mt9v022_set_capture_format, + .set_fmt_cap = mt9v022_set_fmt_cap, .try_fmt_cap = mt9v022_try_fmt_cap, + .set_bus_param = mt9v022_set_bus_param, + .query_bus_param = mt9v022_query_bus_param, .formats = NULL, /* Filled in later depending on the */ .num_formats = 0, /* sensor type and data widths */ - .get_datawidth = mt9v022_get_datawidth, .controls = mt9v022_controls, .num_controls = ARRAY_SIZE(mt9v022_controls), .get_control = mt9v022_get_control, diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index a34a193249f6..4756699d16aa 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -581,64 +581,109 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) pcdev->icd = NULL; } -static int pxa_camera_set_capture_format(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int test_platform_param(struct pxa_camera_dev *pcdev, + unsigned char buswidth, unsigned long *flags) { - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); - struct pxa_camera_dev *pcdev = ici->priv; - unsigned int datawidth = 0, dw, bpp; - u32 cicr0, cicr4 = 0; - int ret; + /* + * Platform specified synchronization and pixel clock polarities are + * only a recommendation and are only used during probing. The PXA270 + * quick capture interface supports both. + */ + *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ? + SOCAM_MASTER : SOCAM_SLAVE) | + SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_HSYNC_ACTIVE_LOW | + SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_PCLK_SAMPLE_RISING | + SOCAM_PCLK_SAMPLE_FALLING; /* If requested data width is supported by the platform, use it */ - switch (icd->cached_datawidth) { + switch (buswidth) { case 10: - if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) - datawidth = IS_DATAWIDTH_10; + if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_10; break; case 9: - if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) - datawidth = IS_DATAWIDTH_9; + if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_9; break; case 8: - if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) - datawidth = IS_DATAWIDTH_8; + if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_8; } - if (!datawidth) + + return 0; +} + +static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned long dw, bpp, bus_flags, camera_flags, common_flags; + u32 cicr0, cicr4 = 0; + int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); + if (!common_flags) return -EINVAL; - ret = icd->ops->set_capture_format(icd, pixfmt, rect, - datawidth | - (pcdev->platform_flags & PXA_CAMERA_MASTER ? - IS_MASTER : 0) | - (pcdev->platform_flags & PXA_CAMERA_HSP ? - 0 : IS_HSYNC_ACTIVE_HIGH) | - (pcdev->platform_flags & PXA_CAMERA_VSP ? - 0 : IS_VSYNC_ACTIVE_HIGH) | - (pcdev->platform_flags & PXA_CAMERA_PCP ? - 0 : IS_PCLK_SAMPLE_RISING)); + /* Make choises, based on platform preferences */ + if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & PXA_CAMERA_HSP) + common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & PXA_CAMERA_VSP) + common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && + (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { + if (pcdev->platform_flags & PXA_CAMERA_PCP) + common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; + else + common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; + } + + ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) return ret; /* Datawidth is now guaranteed to be equal to one of the three values. * We fix bit-per-pixel equal to data-width... */ - switch (datawidth) { - case IS_DATAWIDTH_10: - icd->cached_datawidth = 10; + switch (common_flags & SOCAM_DATAWIDTH_MASK) { + case SOCAM_DATAWIDTH_10: + icd->buswidth = 10; dw = 4; bpp = 0x40; break; - case IS_DATAWIDTH_9: - icd->cached_datawidth = 9; + case SOCAM_DATAWIDTH_9: + icd->buswidth = 9; dw = 3; bpp = 0x20; break; default: /* Actually it can only be 8 now, * default is just to silence compiler warnings */ - case IS_DATAWIDTH_8: - icd->cached_datawidth = 8; + case SOCAM_DATAWIDTH_8: + icd->buswidth = 8; dw = 2; bpp = 0; } @@ -647,19 +692,19 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd, cicr4 |= CICR4_PCLK_EN; if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) cicr4 |= CICR4_MCLK_EN; - if (pcdev->platform_flags & PXA_CAMERA_PCP) + if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) cicr4 |= CICR4_PCP; - if (pcdev->platform_flags & PXA_CAMERA_HSP) + if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) cicr4 |= CICR4_HSP; - if (pcdev->platform_flags & PXA_CAMERA_VSP) + if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) cicr4 |= CICR4_VSP; cicr0 = CICR0; if (cicr0 & CICR0_ENB) CICR0 = cicr0 & ~CICR0_ENB; - CICR1 = CICR1_PPL_VAL(rect->width - 1) | bpp | dw; + CICR1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw; CICR2 = 0; - CICR3 = CICR3_LPF_VAL(rect->height - 1) | + CICR3 = CICR3_LPF_VAL(icd->height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); CICR4 = mclk_get_divisor(pcdev) | cicr4; @@ -671,7 +716,29 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd, return 0; } -static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, +static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned long bus_flags, camera_flags; + int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; +} + +static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + return icd->ops->set_fmt_cap(icd, pixfmt, rect); +} + +static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, struct v4l2_format *f) { /* limit to pxa hardware capabilities */ @@ -685,7 +752,8 @@ static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, f->fmt.pix.width = 2048; f->fmt.pix.width &= ~0x01; - return 0; + /* limit to sensor capabilities */ + return icd->ops->try_fmt_cap(icd, f); } static int pxa_camera_reqbufs(struct soc_camera_file *icf, @@ -742,11 +810,13 @@ static struct soc_camera_host pxa_soc_camera_host = { .add = pxa_camera_add_device, .remove = pxa_camera_remove_device, .msize = sizeof(struct pxa_buffer), - .set_capture_format = pxa_camera_set_capture_format, + .set_fmt_cap = pxa_camera_set_fmt_cap, .try_fmt_cap = pxa_camera_try_fmt_cap, .reqbufs = pxa_camera_reqbufs, .poll = pxa_camera_poll, .querycap = pxa_camera_querycap, + .try_bus_param = pxa_camera_try_bus_param, + .set_bus_param = pxa_camera_set_bus_param, }; static int pxa_camera_probe(struct platform_device *pdev) @@ -782,8 +852,8 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->pdata = pdev->dev.platform_data; pcdev->platform_flags = pcdev->pdata->flags; - if (!pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | - PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10)) { + if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | + PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { /* Platform hasn't set available data widths. This is bad. * Warn and use a default. */ dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 322f837bcfea..bd8677cb1cab 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -75,12 +75,13 @@ static int soc_camera_try_fmt_cap(struct file *file, void *priv, return -EINVAL; } - /* limit to host capabilities */ - ret = ici->try_fmt_cap(ici, f); + /* test physical bus parameters */ + ret = ici->try_bus_param(icd, f->fmt.pix.pixelformat); + if (ret) + return ret; - /* limit to sensor capabilities */ - if (!ret) - ret = icd->ops->try_fmt_cap(icd, f); + /* limit format to hardware capabilities */ + ret = ici->try_fmt_cap(icd, f); /* calculate missing fields */ f->fmt.pix.field = field; @@ -344,8 +345,8 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, if (!data_fmt) return -EINVAL; - /* cached_datawidth may be further adjusted by the ici */ - icd->cached_datawidth = data_fmt->depth; + /* buswidth may be further adjusted by the ici */ + icd->buswidth = data_fmt->depth; ret = soc_camera_try_fmt_cap(file, icf, f); if (ret < 0) @@ -355,22 +356,23 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, rect.top = icd->y_current; rect.width = f->fmt.pix.width; rect.height = f->fmt.pix.height; - ret = ici->set_capture_format(icd, f->fmt.pix.pixelformat, &rect); + ret = ici->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); + if (ret < 0) + return ret; - if (!ret) { - icd->current_fmt = data_fmt; - icd->width = rect.width; - icd->height = rect.height; - icf->vb_vidq.field = f->fmt.pix.field; - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) - dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", - f->type); - - dev_dbg(&icd->dev, "set width: %d height: %d\n", - icd->width, icd->height); - } + icd->current_fmt = data_fmt; + icd->width = rect.width; + icd->height = rect.height; + icf->vb_vidq.field = f->fmt.pix.field; + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) + dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", + f->type); - return ret; + dev_dbg(&icd->dev, "set width: %d height: %d\n", + icd->width, icd->height); + + /* set physical bus parameters */ + return ici->set_bus_param(icd, f->fmt.pix.pixelformat); } static int soc_camera_enum_fmt_cap(struct file *file, void *priv, @@ -577,7 +579,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = ici->set_capture_format(icd, 0, &a->c); + ret = ici->set_fmt_cap(icd, 0, &a->c); if (!ret) { icd->width = a->c.width; icd->height = a->c.height; @@ -860,9 +862,6 @@ int soc_camera_device_register(struct soc_camera_device *icd) icd->dev.release = dummy_release; - if (icd->ops->get_datawidth) - icd->cached_datawidth = icd->ops->get_datawidth(icd); - return scan_add_device(icd); } EXPORT_SYMBOL(soc_camera_device_register); diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index c886b1e64872..3e48e435b21a 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -34,7 +34,7 @@ struct soc_camera_device { unsigned short exposure; unsigned char iface; /* Host number */ unsigned char devnum; /* Device number per host */ - unsigned char cached_datawidth; /* See comment in .c */ + unsigned char buswidth; /* See comment in .c */ struct soc_camera_ops *ops; struct video_device *vdev; const struct soc_camera_data_format *current_fmt; @@ -61,11 +61,13 @@ struct soc_camera_host { char *drv_name; int (*add)(struct soc_camera_device *); void (*remove)(struct soc_camera_device *); - int (*set_capture_format)(struct soc_camera_device *, __u32, - struct v4l2_rect *); - int (*try_fmt_cap)(struct soc_camera_host *, struct v4l2_format *); + int (*set_fmt_cap)(struct soc_camera_device *, __u32, + struct v4l2_rect *); + int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); + int (*try_bus_param)(struct soc_camera_device *, __u32); + int (*set_bus_param)(struct soc_camera_device *, __u32); unsigned int (*poll)(struct file *, poll_table *); }; @@ -108,9 +110,11 @@ struct soc_camera_ops { int (*release)(struct soc_camera_device *); int (*start_capture)(struct soc_camera_device *); int (*stop_capture)(struct soc_camera_device *); - int (*set_capture_format)(struct soc_camera_device *, __u32, - struct v4l2_rect *, unsigned int); + int (*set_fmt_cap)(struct soc_camera_device *, __u32, + struct v4l2_rect *); int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); + unsigned long (*query_bus_param)(struct soc_camera_device *); + int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*get_chip_id)(struct soc_camera_device *, struct v4l2_chip_ident *); #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -123,7 +127,6 @@ struct soc_camera_ops { int (*set_control)(struct soc_camera_device *, struct v4l2_control *); const struct v4l2_queryctrl *controls; int num_controls; - unsigned int(*get_datawidth)(struct soc_camera_device *icd); }; static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( @@ -138,12 +141,33 @@ static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( return NULL; } -#define IS_MASTER (1<<0) -#define IS_HSYNC_ACTIVE_HIGH (1<<1) -#define IS_VSYNC_ACTIVE_HIGH (1<<2) -#define IS_DATAWIDTH_8 (1<<3) -#define IS_DATAWIDTH_9 (1<<4) -#define IS_DATAWIDTH_10 (1<<5) -#define IS_PCLK_SAMPLE_RISING (1<<6) +#define SOCAM_MASTER (1 << 0) +#define SOCAM_SLAVE (1 << 1) +#define SOCAM_HSYNC_ACTIVE_HIGH (1 << 2) +#define SOCAM_HSYNC_ACTIVE_LOW (1 << 3) +#define SOCAM_VSYNC_ACTIVE_HIGH (1 << 4) +#define SOCAM_VSYNC_ACTIVE_LOW (1 << 5) +#define SOCAM_DATAWIDTH_8 (1 << 6) +#define SOCAM_DATAWIDTH_9 (1 << 7) +#define SOCAM_DATAWIDTH_10 (1 << 8) +#define SOCAM_PCLK_SAMPLE_RISING (1 << 9) +#define SOCAM_PCLK_SAMPLE_FALLING (1 << 10) + +#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \ + SOCAM_DATAWIDTH_10) + +static inline unsigned long soc_camera_bus_param_compatible( + unsigned long camera_flags, unsigned long bus_flags) +{ + unsigned long common_flags, hsync, vsync, pclk; + + common_flags = camera_flags & bus_flags; + + hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW); + vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW); + pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING); + + return (!hsync || !vsync || !pclk) ? 0 : common_flags; +} #endif -- cgit v1.2.3 From f076607df84ed858c92dd9181a1c239759aa3802 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:27:55 -0300 Subject: V4L/DVB (7337): ivtv: fix polling bug The q_io queue was never taken into account by the poll function. Thanks to Andy Walls for finding this bug. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-fileops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 6fb96f19a866..d949a81339d5 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -753,7 +753,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) IVTV_DEBUG_HI_FILE("Encoder poll\n"); poll_wait(filp, &s->waitq, wait); - if (eof || s->q_full.length) + if (eof || s->q_full.length || s->q_io.length) return POLLIN | POLLRDNORM; return 0; } -- cgit v1.2.3 From 5cef6c00515cd9712904aa6b913120c6704b2828 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:27:55 -0300 Subject: V4L/DVB (7338): ivtv: improve pal/secam module options, add tunerhz module option Allow options like pal=bgh, improve description of those options. Add tunerhz option: 50=card has 50Hz tuner, 60=card has 60Hz tuner. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 37 +++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index d0bb5b18797a..baa3aeed8a23 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -101,7 +101,7 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, static unsigned int cardtype_c = 1; static unsigned int tuner_c = 1; static unsigned int radio_c = 1; -static char pal[] = "--"; +static char pal[] = "---"; static char secam[] = "--"; static char ntsc[] = "-"; @@ -132,6 +132,7 @@ static int ivtv_pci_latency = 1; int ivtv_debug; +static int tunerhz; static int newi2c = -1; module_param_array(tuner, int, &tuner_c, 0644); @@ -154,6 +155,7 @@ module_param(dec_mpg_buffers, int, 0644); module_param(dec_yuv_buffers, int, 0644); module_param(dec_vbi_buffers, int, 0644); +module_param(tunerhz, int, 0644); module_param(newi2c, int, 0644); MODULE_PARM_DESC(tuner, "Tuner type selection,\n" @@ -190,9 +192,14 @@ MODULE_PARM_DESC(cardtype, "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); -MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); -MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC"); -MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K"); +MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); +MODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC"); +MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)"); +MODULE_PARM_DESC(tunerhz, + "Specify tuner type:\n" + "\t\t\t50 = 50 Hz tuner (PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc)\n" + "\t\t\t60 = 60 Hz tuner (NTSC-M/J/K, PAL-M/N/Nc/60)\n" + "\t\t\t 0 = Autodetect (default)\n"); MODULE_PARM_DESC(debug, "Debug level (bitmask). Default: 0\n" "\t\t\t 1/0x0001: warning\n" @@ -490,30 +497,35 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv) { switch (pal[0]) { case '6': + tunerhz = 60; return V4L2_STD_PAL_60; case 'b': case 'B': case 'g': case 'G': - return V4L2_STD_PAL_BG; case 'h': case 'H': - return V4L2_STD_PAL_H; + tunerhz = 50; + return V4L2_STD_PAL_BG | V4L2_STD_PAL_H; case 'n': case 'N': + tunerhz = 60; if (pal[1] == 'c' || pal[1] == 'C') return V4L2_STD_PAL_Nc; return V4L2_STD_PAL_N; case 'i': case 'I': + tunerhz = 50; return V4L2_STD_PAL_I; case 'd': case 'D': case 'k': case 'K': + tunerhz = 50; return V4L2_STD_PAL_DK; case 'M': case 'm': + tunerhz = 60; return V4L2_STD_PAL_M; case '-': break; @@ -529,14 +541,17 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv) case 'G': case 'h': case 'H': + tunerhz = 50; return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; case 'd': case 'D': case 'k': case 'K': + tunerhz = 50; return V4L2_STD_SECAM_DK; case 'l': case 'L': + tunerhz = 50; if (secam[1] == 'C' || secam[1] == 'c') return V4L2_STD_SECAM_LC; return V4L2_STD_SECAM_L; @@ -550,12 +565,15 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv) switch (ntsc[0]) { case 'm': case 'M': + tunerhz = 60; return V4L2_STD_NTSC_M; case 'j': case 'J': + tunerhz = 60; return V4L2_STD_NTSC_M_JP; case 'k': case 'K': + tunerhz = 60; return V4L2_STD_NTSC_M_KR; case '-': break; @@ -584,8 +602,13 @@ static void ivtv_process_options(struct ivtv *itv) itv->options.tuner = tuner[itv->num]; itv->options.radio = radio[itv->num]; itv->options.newi2c = newi2c; - + if (tunerhz != 0 && tunerhz != 50 && tunerhz != 60) { + IVTV_WARN("Invalid tunerhz argument, will autodetect instead\n"); + tunerhz = 0; + } itv->std = ivtv_parse_std(itv); + if (itv->std == 0 && tunerhz) + itv->std = (tunerhz == 60) ? V4L2_STD_525_60 : V4L2_STD_625_50; itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15); chipname = itv->has_cx23415 ? "cx23415" : "cx23416"; if (itv->options.cardtype == -1) { -- cgit v1.2.3 From 125ed44763cc840a90da22f45d3226692e8fd008 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:27:56 -0300 Subject: V4L/DVB (7339): ivtv: add support for Japanese variant of the Adaptec AVC-2410 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-cards.c | 7 +++---- drivers/media/video/ivtv/ivtv-cards.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index f23c6b8d6911..e908649ea37c 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -416,11 +416,10 @@ static const struct ivtv_card ivtv_card_avc2410 = { on the country/region setting of the user to decide which tuner is available. */ .tuners = { - /* This tuner has been verified for the AVC2410 */ { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, - /* This is a good guess, but I'm not totally sure this is - the correct tuner for NTSC. */ - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, + { .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP, + .tuner = TUNER_PHILIPS_FM1236_MK3 }, + { .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 }, }, .pci_list = ivtv_pci_avc2410, .i2c = &ivtv_i2c_std, diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 191aafdd9968..9186fa2ee5fc 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h @@ -119,7 +119,7 @@ #define IVTV_CARD_MAX_VIDEO_INPUTS 6 #define IVTV_CARD_MAX_AUDIO_INPUTS 3 -#define IVTV_CARD_MAX_TUNERS 2 +#define IVTV_CARD_MAX_TUNERS 3 /* SAA71XX HW inputs */ #define IVTV_SAA71XX_COMPOSITE0 0 -- cgit v1.2.3 From acec8681d495a41f3f6496433bd510eb40ff27b4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:27:56 -0300 Subject: V4L/DVB (7340): ivtv: fix tunerhz bug: PAL-N(c) is 50 Hz, not 60 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index baa3aeed8a23..3e4f55a9edfa 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -509,7 +509,7 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv) return V4L2_STD_PAL_BG | V4L2_STD_PAL_H; case 'n': case 'N': - tunerhz = 60; + tunerhz = 50; if (pal[1] == 'c' || pal[1] == 'C') return V4L2_STD_PAL_Nc; return V4L2_STD_PAL_N; -- cgit v1.2.3 From af249fcc59a1b13558ac036bb11f2ef5424eab75 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:27:56 -0300 Subject: V4L/DVB (7341): ivtv: rename tunerhz to tunertype There are two tuner types: those for M/N standards and those for all others. However, M/N standards are not always 60 Hz (PAL-N/Nc are 50 Hz), so rename the module option accordingly. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 46 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 3e4f55a9edfa..1ed77167b125 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -132,7 +132,7 @@ static int ivtv_pci_latency = 1; int ivtv_debug; -static int tunerhz; +static int tunertype = -1; static int newi2c = -1; module_param_array(tuner, int, &tuner_c, 0644); @@ -155,7 +155,7 @@ module_param(dec_mpg_buffers, int, 0644); module_param(dec_yuv_buffers, int, 0644); module_param(dec_vbi_buffers, int, 0644); -module_param(tunerhz, int, 0644); +module_param(tunertype, int, 0644); module_param(newi2c, int, 0644); MODULE_PARM_DESC(tuner, "Tuner type selection,\n" @@ -195,11 +195,11 @@ MODULE_PARM_DESC(cardtype, MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); MODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC"); MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)"); -MODULE_PARM_DESC(tunerhz, +MODULE_PARM_DESC(tunertype, "Specify tuner type:\n" - "\t\t\t50 = 50 Hz tuner (PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc)\n" - "\t\t\t60 = 60 Hz tuner (NTSC-M/J/K, PAL-M/N/Nc/60)\n" - "\t\t\t 0 = Autodetect (default)\n"); + "\t\t\t 0 = tuner for PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc\n" + "\t\t\t 1 = tuner for NTSC-M/J/K, PAL-M/N/Nc\n" + "\t\t\t-1 = Autodetect (default)\n"); MODULE_PARM_DESC(debug, "Debug level (bitmask). Default: 0\n" "\t\t\t 1/0x0001: warning\n" @@ -497,7 +497,7 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv) { switch (pal[0]) { case '6': - tunerhz = 60; + tunertype = 0; return V4L2_STD_PAL_60; case 'b': case 'B': @@ -505,27 +505,27 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv) case 'G': case 'h': case 'H': - tunerhz = 50; + tunertype = 0; return V4L2_STD_PAL_BG | V4L2_STD_PAL_H; case 'n': case 'N': - tunerhz = 50; + tunertype = 1; if (pal[1] == 'c' || pal[1] == 'C') return V4L2_STD_PAL_Nc; return V4L2_STD_PAL_N; case 'i': case 'I': - tunerhz = 50; + tunertype = 0; return V4L2_STD_PAL_I; case 'd': case 'D': case 'k': case 'K': - tunerhz = 50; + tunertype = 0; return V4L2_STD_PAL_DK; case 'M': case 'm': - tunerhz = 60; + tunertype = 1; return V4L2_STD_PAL_M; case '-': break; @@ -541,17 +541,17 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv) case 'G': case 'h': case 'H': - tunerhz = 50; + tunertype = 0; return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; case 'd': case 'D': case 'k': case 'K': - tunerhz = 50; + tunertype = 0; return V4L2_STD_SECAM_DK; case 'l': case 'L': - tunerhz = 50; + tunertype = 0; if (secam[1] == 'C' || secam[1] == 'c') return V4L2_STD_SECAM_LC; return V4L2_STD_SECAM_L; @@ -565,15 +565,15 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv) switch (ntsc[0]) { case 'm': case 'M': - tunerhz = 60; + tunertype = 1; return V4L2_STD_NTSC_M; case 'j': case 'J': - tunerhz = 60; + tunertype = 1; return V4L2_STD_NTSC_M_JP; case 'k': case 'K': - tunerhz = 60; + tunertype = 1; return V4L2_STD_NTSC_M_KR; case '-': break; @@ -602,13 +602,13 @@ static void ivtv_process_options(struct ivtv *itv) itv->options.tuner = tuner[itv->num]; itv->options.radio = radio[itv->num]; itv->options.newi2c = newi2c; - if (tunerhz != 0 && tunerhz != 50 && tunerhz != 60) { - IVTV_WARN("Invalid tunerhz argument, will autodetect instead\n"); - tunerhz = 0; + if (tunertype < -1 || tunertype > 1) { + IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); + tunertype = -1; } itv->std = ivtv_parse_std(itv); - if (itv->std == 0 && tunerhz) - itv->std = (tunerhz == 60) ? V4L2_STD_525_60 : V4L2_STD_625_50; + if (itv->std == 0 && tunertype >= 0) + itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN); itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15); chipname = itv->has_cx23415 ? "cx23415" : "cx23416"; if (itv->options.cardtype == -1) { -- cgit v1.2.3 From 87fb4d4d9ad466012e0742e1c2933c2c2c29e995 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:27:57 -0300 Subject: V4L/DVB (7342): saa7115: fix PAL-Nc handling Fsc 3.58 refers to Combination PAL-N (aka PAL-Nc), not to plain PAL-N (that uses Fsc 4.43). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index aaec17f9d4eb..416d05d4a969 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -957,7 +957,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) if (std == V4L2_STD_PAL_M) { reg |= 0x30; - } else if (std == V4L2_STD_PAL_N) { + } else if (std == V4L2_STD_PAL_Nc) { reg |= 0x20; } else if (std == V4L2_STD_PAL_60) { reg |= 0x10; -- cgit v1.2.3 From 53c2751c7e8757b958e38d19971681e42b77ee00 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:27:57 -0300 Subject: V4L/DVB (7343): msp3400: fix SECAM D/K handling The 6.5 MHz carrier was interpreted as SECAM-L even if SECAM-D/K was selected. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-kthreads.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 61ec794a737e..7f5568592793 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -833,11 +833,6 @@ static int msp34xxg_modus(struct i2c_client *client) v4l_dbg(1, msp_debug, client, "selected radio modus\n"); return 0x0001; } - - if (state->v4l2_std & V4L2_STD_PAL) { - v4l_dbg(1, msp_debug, client, "selected PAL modus\n"); - return 0x7001; - } if (state->v4l2_std == V4L2_STD_NTSC_M_JP) { v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n"); return 0x4001; @@ -846,15 +841,15 @@ static int msp34xxg_modus(struct i2c_client *client) v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n"); return 0x0001; } + if (state->v4l2_std == V4L2_STD_SECAM_L) { + v4l_dbg(1, msp_debug, client, "selected SECAM-L modus\n"); + return 0x6001; + } if (state->v4l2_std & V4L2_STD_MN) { v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n"); return 0x2001; } - if (state->v4l2_std & V4L2_STD_SECAM) { - v4l_dbg(1, msp_debug, client, "selected SECAM modus\n"); - return 0x6001; - } - return 0x0001; + return 0x7001; } static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) -- cgit v1.2.3 From fe4107f10aacfe1b721c6a4c0c7c2db7089a6a73 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 2 Apr 2008 14:27:57 -0300 Subject: V4L/DVB (7344): cx25840: better PAL-M and NTSC-KR handling Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 91 +++++++++++------------------- drivers/media/video/cx25840/cx25840-core.h | 2 +- drivers/media/video/cx25840/cx25840-vbi.c | 6 +- 3 files changed, 38 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 756a1eeb274e..ae395f8cf292 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -352,7 +352,7 @@ static void cx23885_initialize(struct i2c_client *client) static void input_change(struct i2c_client *client) { struct cx25840_state *state = i2c_get_clientdata(client); - v4l2_std_id std = cx25840_get_v4lstd(client); + v4l2_std_id std = state->std; /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ if (std & V4L2_STD_SECAM) { @@ -523,32 +523,34 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp /* ----------------------------------------------------------------------- */ -static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) +static int set_v4lstd(struct i2c_client *client) { - u8 fmt=0; /* zero is autodetect */ + struct cx25840_state *state = i2c_get_clientdata(client); + u8 fmt = 0; /* zero is autodetect */ + u8 pal_m = 0; /* First tests should be against specific std */ - if (std == V4L2_STD_NTSC_M_JP) { - fmt=0x2; - } else if (std == V4L2_STD_NTSC_443) { - fmt=0x3; - } else if (std == V4L2_STD_PAL_M) { - fmt=0x5; - } else if (std == V4L2_STD_PAL_N) { - fmt=0x6; - } else if (std == V4L2_STD_PAL_Nc) { - fmt=0x7; - } else if (std == V4L2_STD_PAL_60) { - fmt=0x8; + if (state->std == V4L2_STD_NTSC_M_JP) { + fmt = 0x2; + } else if (state->std == V4L2_STD_NTSC_443) { + fmt = 0x3; + } else if (state->std == V4L2_STD_PAL_M) { + pal_m = 1; + fmt = 0x5; + } else if (state->std == V4L2_STD_PAL_N) { + fmt = 0x6; + } else if (state->std == V4L2_STD_PAL_Nc) { + fmt = 0x7; + } else if (state->std == V4L2_STD_PAL_60) { + fmt = 0x8; } else { /* Then, test against generic ones */ - if (std & V4L2_STD_NTSC) { - fmt=0x1; - } else if (std & V4L2_STD_PAL) { - fmt=0x4; - } else if (std & V4L2_STD_SECAM) { - fmt=0xc; - } + if (state->std & V4L2_STD_NTSC) + fmt = 0x1; + else if (state->std & V4L2_STD_PAL) + fmt = 0x4; + else if (state->std & V4L2_STD_SECAM) + fmt = 0xc; } v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt); @@ -563,42 +565,13 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) cx25840_and_or(client, 0x47b, ~6, 0); } cx25840_and_or(client, 0x400, ~0xf, fmt); + cx25840_and_or(client, 0x403, ~0x3, pal_m); cx25840_vbi_setup(client); + if (!state->is_cx25836) + input_change(client); return 0; } -v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) -{ - struct cx25840_state *state = i2c_get_clientdata(client); - /* check VID_FMT_SEL first */ - u8 fmt = cx25840_read(client, 0x400) & 0xf; - - if (!fmt) { - /* check AFD_FMT_STAT if set to autodetect */ - fmt = cx25840_read(client, 0x40d) & 0xf; - } - - switch (fmt) { - case 0x1: - { - /* if the audio std is A2-M, then this is the South Korean - NTSC standard */ - if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2) - return V4L2_STD_NTSC_M_KR; - return V4L2_STD_NTSC_M; - } - case 0x2: return V4L2_STD_NTSC_M_JP; - case 0x3: return V4L2_STD_NTSC_443; - case 0x4: return V4L2_STD_PAL; - case 0x5: return V4L2_STD_PAL_M; - case 0x6: return V4L2_STD_PAL_N; - case 0x7: return V4L2_STD_PAL_Nc; - case 0x8: return V4L2_STD_PAL_60; - case 0xc: return V4L2_STD_SECAM; - default: return V4L2_STD_UNKNOWN; - } -} - /* ----------------------------------------------------------------------- */ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) @@ -718,9 +691,10 @@ static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) { + struct cx25840_state *state = i2c_get_clientdata(client); struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; - int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); + int is_50Hz = !(state->std & V4L2_STD_525_60); switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -1096,12 +1070,15 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, } case VIDIOC_G_STD: - *(v4l2_std_id *)arg = cx25840_get_v4lstd(client); + *(v4l2_std_id *)arg = state->std; break; case VIDIOC_S_STD: + if (state->radio == 0 && state->std == *(v4l2_std_id *)arg) + return 0; state->radio = 0; - return set_v4lstd(client, *(v4l2_std_id *)arg); + state->std = *(v4l2_std_id *)arg; + return set_v4lstd(client); case AUDC_SET_RADIO: state->radio = 1; diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 95093edc9186..8bf797f48b09 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h @@ -38,6 +38,7 @@ struct cx25840_state { struct i2c_client *c; int pvr150_workaround; int radio; + v4l2_std_id std; enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; u32 audclk_freq; @@ -60,7 +61,6 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); u8 cx25840_read(struct i2c_client *client, u16 addr); u32 cx25840_read4(struct i2c_client *client, u16 addr); int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); -v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client); /* ----------------------------------------------------------------------- */ /* cx25850-firmware.c */ diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 6828f59b9d83..c754b9d13369 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p) void cx25840_vbi_setup(struct i2c_client *client) { struct cx25840_state *state = i2c_get_clientdata(client); - v4l2_std_id std = cx25840_get_v4lstd(client); + v4l2_std_id std = state->std; int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation; int luma_lpf,uv_lpf, comb; u32 pll_int,pll_frac,pll_post; @@ -242,7 +242,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ 0, 0, 0, 0 }; - int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); + int is_pal = !(state->std & V4L2_STD_525_60); int i; fmt = arg; @@ -279,7 +279,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_S_FMT: { - int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); + int is_pal = !(state->std & V4L2_STD_525_60); int vbi_offset = is_pal ? 1 : 0; int i, x; u8 lcr[24]; -- cgit v1.2.3 From 99ad84933acd6b01e0ba5108a29c2aefe637fc6a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:58 -0300 Subject: V4L/DVB (7346): tda9887: allow multiple driver instances for the same hardware to share state Convert tda9887 to use the new hybrid_tuner_request_state and hybrid_tuner_release_state macros to manage state sharing between hybrid tuner instances. Some ATSC/DVB cards need to put the analog demodulator into standby before tuning digital. This patch allows us to attach the tda9887 driver to the digital side of the bridge driver and be able to put it into standby without jeopardizing the analog demod driver's state. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda9887.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 75d08404d238..a0545ba957b0 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -25,8 +25,12 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); +static DEFINE_MUTEX(tda9887_list_mutex); +static LIST_HEAD(hybrid_tuner_instance_list); + struct tda9887_priv { struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; unsigned char data[4]; unsigned int config; @@ -642,7 +646,15 @@ static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg) static void tda9887_release(struct dvb_frontend *fe) { - kfree(fe->analog_demod_priv); + struct tda9887_priv *priv = fe->analog_demod_priv; + + mutex_lock(&tda9887_list_mutex); + + if (priv) + hybrid_tuner_release_state(priv); + + mutex_unlock(&tda9887_list_mutex); + fe->analog_demod_priv = NULL; } @@ -663,18 +675,29 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, u8 i2c_addr) { struct tda9887_priv *priv = NULL; + int instance; - priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); - if (priv == NULL) - return NULL; - fe->analog_demod_priv = priv; + mutex_lock(&tda9887_list_mutex); - priv->i2c_props.addr = i2c_addr; - priv->i2c_props.adap = i2c_adap; - priv->i2c_props.name = "tda9887"; - priv->mode = T_STANDBY; + instance = hybrid_tuner_request_state(struct tda9887_priv, priv, + hybrid_tuner_instance_list, + i2c_adap, i2c_addr, "tda9887"); + switch (instance) { + case 0: + mutex_unlock(&tda9887_list_mutex); + return NULL; + break; + case 1: + fe->analog_demod_priv = priv; + priv->mode = T_STANDBY; + tuner_info("tda988[5/6/7] found\n"); + break; + default: + fe->analog_demod_priv = priv; + break; + } - tuner_info("tda988[5/6/7] found\n"); + mutex_unlock(&tda9887_list_mutex); memcpy(&fe->ops.analog_ops, &tda9887_ops, sizeof(struct analog_demod_ops)); -- cgit v1.2.3 From 49e6752c53ada5e45d29c4bf4ebbd38f3d78e207 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:58 -0300 Subject: V4L/DVB (7347): tuner-simple: add basic support for digital tuning of hybrid devices Add entry points used for digital tuning via the dvb_frontend. Share state data between multiple instances of the driver for hybrid tuners. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 156 ++++++++++++++++++++++++++++++++++--- include/media/tuner-types.h | 14 +++- 2 files changed, 156 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index ee5ef860700a..d6d922c32bce 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -88,14 +88,20 @@ MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner"); #define TUNER_PLL_LOCKED 0x40 #define TUNER_STEREO_MK3 0x04 +static DEFINE_MUTEX(tuner_simple_list_mutex); +static LIST_HEAD(hybrid_tuner_instance_list); + struct tuner_simple_priv { u16 last_div; + struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; unsigned int type; struct tunertype *tun; u32 frequency; + u32 bandwidth; }; /* ---------------------------------------------------------------------- */ @@ -188,6 +194,9 @@ static inline char *tuner_param_name(enum param_type type) case TUNER_PARAM_TYPE_NTSC: name = "ntsc"; break; + case TUNER_PARAM_TYPE_DIGITAL: + name = "digital"; + break; default: name = "unknown"; break; @@ -687,14 +696,118 @@ static int simple_set_params(struct dvb_frontend *fe, priv->frequency = params->frequency * 62500; break; } + priv->bandwidth = 0; return ret; } +static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, + const struct dvb_frontend_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + struct tunertype *tun = priv->tun; + static struct tuner_params *t_params; + u8 config, cb; + u32 div; + int ret, frequency = params->frequency / 62500; + + t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL); + ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb); + if (ret < 0) + return ret; + + div = ((frequency + t_params->iffreq) * 62500 + offset + + tun->stepsize/2) / tun->stepsize; + + buf[0] = div >> 8; + buf[1] = div & 0xff; + buf[2] = config; + buf[3] = cb; + + tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", + tun->name, div, buf[0], buf[1], buf[2], buf[3]); + + /* calculate the frequency we set it to */ + return (div * tun->stepsize) - t_params->iffreq; +} + +static int simple_dvb_calc_regs(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + u8 *buf, int buf_len) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int ret; + u32 frequency; + + if (buf_len < 5) + return -EINVAL; + + ret = simple_dvb_configure(fe, buf+1, params); + if (ret < 0) + return ret; + else + frequency = ret; + + buf[0] = priv->i2c_props.addr; + + priv->frequency = frequency; + priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? + params->u.ofdm.bandwidth : 0; + + return 5; +} + +static int simple_dvb_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u32 prev_freq, prev_bw; + int ret; + u8 buf[5]; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + prev_freq = priv->frequency; + prev_bw = priv->bandwidth; + + ret = simple_dvb_calc_regs(fe, params, buf, 5); + if (ret != 5) + goto fail; + + /* put analog demod in standby when tuning digital */ + if (fe->ops.analog_ops.standby) + fe->ops.analog_ops.standby(fe); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* buf[0] contains the i2c address, but * + * we already have it in i2c_props.addr */ + ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4); + if (ret != 4) + goto fail; + + return 0; +fail: + /* calc_regs sets frequency and bandwidth. if we failed, unset them */ + priv->frequency = prev_freq; + priv->bandwidth = prev_bw; + + return ret; +} static int simple_release(struct dvb_frontend *fe) { - kfree(fe->tuner_priv); + struct tuner_simple_priv *priv = fe->tuner_priv; + + mutex_lock(&tuner_simple_list_mutex); + + if (priv) + hybrid_tuner_release_state(priv); + + mutex_unlock(&tuner_simple_list_mutex); + fe->tuner_priv = NULL; return 0; @@ -707,10 +820,20 @@ static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency) return 0; } +static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + *bandwidth = priv->bandwidth; + return 0; +} + static struct dvb_tuner_ops simple_tuner_ops = { .set_analog_params = simple_set_params, + .set_params = simple_dvb_set_params, + .calc_regs = simple_dvb_calc_regs, .release = simple_release, .get_frequency = simple_get_frequency, + .get_bandwidth = simple_get_bandwidth, .get_status = simple_get_status, .get_rf_strength = simple_get_rf_strength, }; @@ -721,6 +844,7 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, unsigned int type) { struct tuner_simple_priv *priv = NULL; + int instance; if (type >= tuner_count) { printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n", @@ -728,22 +852,34 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, return NULL; } - priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL); - if (priv == NULL) + mutex_lock(&tuner_simple_list_mutex); + + instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv, + hybrid_tuner_instance_list, + i2c_adap, i2c_addr, + "tuner-simple"); + switch (instance) { + case 0: + mutex_unlock(&tuner_simple_list_mutex); return NULL; - fe->tuner_priv = priv; + break; + case 1: + fe->tuner_priv = priv; - priv->i2c_props.addr = i2c_addr; - priv->i2c_props.adap = i2c_adap; - priv->i2c_props.name = "tuner-simple"; + priv->type = type; + priv->tun = &tuners[type]; + break; + default: + fe->tuner_priv = priv; + break; + } - priv->type = type; - priv->tun = &tuners[type]; + mutex_unlock(&tuner_simple_list_mutex); memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); - tuner_info("type set to %d (%s)\n", priv->type, priv->tun->name); + tuner_info("type set to %d (%s)\n", type, priv->tun->name); strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name, sizeof(fe->ops.tuner_ops.info.name)); diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index b201371416a0..4b5e5cf780c8 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -6,10 +6,11 @@ #define __TUNER_TYPES_H__ enum param_type { - TUNER_PARAM_TYPE_RADIO, \ - TUNER_PARAM_TYPE_PAL, \ - TUNER_PARAM_TYPE_SECAM, \ - TUNER_PARAM_TYPE_NTSC + TUNER_PARAM_TYPE_RADIO, + TUNER_PARAM_TYPE_PAL, + TUNER_PARAM_TYPE_SECAM, + TUNER_PARAM_TYPE_NTSC, + TUNER_PARAM_TYPE_DIGITAL, }; struct tuner_range { @@ -105,6 +106,7 @@ struct tuner_params { the SECAM-L/L' standards. Range: -16:+15 */ signed int default_top_secam_high:5; + u16 iffreq; unsigned int count; struct tuner_range *ranges; @@ -114,6 +116,10 @@ struct tunertype { char *name; unsigned int count; struct tuner_params *params; + + u16 min; + u16 max; + u16 stepsize; }; extern struct tunertype tuners[]; -- cgit v1.2.3 From a91adf530ae1b1bd35c3640c40b4d622fa97325b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:58 -0300 Subject: V4L/DVB (7348): tuner-simple: do not send i2c commands if there is no i2c adapter if (priv->i2c_props.adap == NULL) then exit any function that would send commands over the i2c bus. We allow drivers to attach without an i2c adapter for cases where the dvb demod accesses the tuner directly via calc_regs. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index d6d922c32bce..3ec76391a60d 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -149,7 +149,12 @@ static inline int tuner_afcstatus(const int status) static int simple_get_status(struct dvb_frontend *fe, u32 *status) { struct tuner_simple_priv *priv = fe->tuner_priv; - int tuner_status = tuner_read_status(fe); + int tuner_status; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + tuner_status = tuner_read_status(fe); *status = 0; @@ -166,7 +171,12 @@ static int simple_get_status(struct dvb_frontend *fe, u32 *status) static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength) { struct tuner_simple_priv *priv = fe->tuner_priv; - int signal = tuner_signal(tuner_read_status(fe)); + int signal; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + signal = tuner_signal(tuner_read_status(fe)); *strength = signal; @@ -685,6 +695,9 @@ static int simple_set_params(struct dvb_frontend *fe, struct tuner_simple_priv *priv = fe->tuner_priv; int ret = -EINVAL; + if (priv->i2c_props.adap == NULL) + return -EINVAL; + switch (params->mode) { case V4L2_TUNER_RADIO: ret = simple_set_radio_freq(fe, params); -- cgit v1.2.3 From 61326983d5f296ef8cef5ee52ca49874c1d40637 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:58 -0300 Subject: V4L/DVB (7349): tuner-simple: enable digital tuning support for LG TDVS-H06xF Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 9276ad33d03b..40cc43e82887 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -915,6 +915,11 @@ static struct tuner_range tuner_tua6034_ntsc_ranges[] = { { 16 * 999.99 , 0x8e, 0x04 }, }; +static struct tuner_range tuner_tua6034_atsc_ranges[] = { + { 16 * 165.00 /*MHz*/, 0xce, 0x01 }, + { 16 * 450.00 /*MHz*/, 0xce, 0x02 }, + { 16 * 999.99 , 0xce, 0x04 }, +}; static struct tuner_params tuner_lg_tdvs_h06xf_params[] = { { @@ -922,6 +927,12 @@ static struct tuner_params tuner_lg_tdvs_h06xf_params[] = { .ranges = tuner_tua6034_ntsc_ranges, .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges), }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_tua6034_atsc_ranges, + .count = ARRAY_SIZE(tuner_tua6034_atsc_ranges), + .iffreq = 16 * 44.00, + }, }; /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ @@ -1419,6 +1430,9 @@ struct tunertype tuners[] = { .name = "LG TDVS-H06xF", /* H061F, H062F & H064F */ .params = tuner_lg_tdvs_h06xf_params, .count = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params), + .min = 16 * 54.00, + .max = 16 * 863.00, + .stepsize = 62500, }, [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ .name = "Ymec TVF66T5-B/DFF", -- cgit v1.2.3 From 5be5b1b36f3a090e97ace4ca8d2511d0ed45c1d2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:59 -0300 Subject: V4L/DVB (7350): tuner-simple: enable digital tuning support for Thomson DTT 761X Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 40cc43e82887..8b53d0d05b23 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -855,6 +855,11 @@ static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = { { 16 * 999.99 , 0x8e, 0x3c, }, }; +static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = { + { 16 * 147.00 /*MHz*/, 0x8e, 0x39, }, + { 16 * 417.00 /*MHz*/, 0x8e, 0x3a, }, + { 16 * 999.99 , 0x8e, 0x3c, }, +}; static struct tuner_params tuner_thomson_dtt761x_params[] = { { @@ -865,6 +870,12 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = { .fm_gain_normal = 1, .radio_if = 2, /* 41.3 MHz */ }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_thomson_dtt761x_atsc_ranges, + .count = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges), + .iffreq = 16 * 44.00, /*MHz*/ + }, }; /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */ @@ -1411,6 +1422,9 @@ struct tunertype tuners[] = { .name = "Thomson DTT 761X (ATSC/NTSC)", .params = tuner_thomson_dtt761x_params, .count = ARRAY_SIZE(tuner_thomson_dtt761x_params), + .min = 16 * 57.00, + .max = 16 * 863.00, + .stepsize = 62500, }, [TUNER_TENA_9533_DI] = { /* Philips PAL */ .name = "Tena TNF9533-D/IF/TNF9533-B/DF", -- cgit v1.2.3 From 096dc3522255301546aa20a73139d6c4d7ec6ff5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:59 -0300 Subject: V4L/DVB (7351): tuner-simple: add init and sleep methods taken from dvb-pll Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 48 ++++++++++++++++++++++++++++++++++++++ drivers/media/video/tuner-types.c | 25 ++++++++++++++++++++ include/media/tuner-types.h | 3 +++ 3 files changed, 76 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 3ec76391a60d..3a27d4a8ce38 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -810,6 +810,52 @@ fail: return ret; } +static int simple_init(struct dvb_frontend *fe) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + if (priv->tun->initdata) { + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = tuner_i2c_xfer_send(&priv->i2c_props, + priv->tun->initdata + 1, + priv->tun->initdata[0]); + if (ret != priv->tun->initdata[0]) + return ret; + } + + return 0; +} + +static int simple_sleep(struct dvb_frontend *fe) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + if (priv->tun->sleepdata) { + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = tuner_i2c_xfer_send(&priv->i2c_props, + priv->tun->sleepdata + 1, + priv->tun->sleepdata[0]); + if (ret != priv->tun->sleepdata[0]) + return ret; + } + + return 0; +} + static int simple_release(struct dvb_frontend *fe) { struct tuner_simple_priv *priv = fe->tuner_priv; @@ -841,6 +887,8 @@ static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) } static struct dvb_tuner_ops simple_tuner_ops = { + .init = simple_init, + .sleep = simple_sleep, .set_analog_params = simple_set_params, .set_params = simple_dvb_set_params, .calc_regs = simple_dvb_calc_regs, diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 8b53d0d05b23..13c76a57d8e2 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -35,6 +35,27 @@ * based on the video standard in use. */ +/* The following was taken from dvb-pll.c: */ + +/* Set AGC TOP value to 103 dBuV: + * 0x80 = Control Byte + * 0x40 = 250 uA charge pump (irrelevant) + * 0x18 = Aux Byte to follow + * 0x06 = 64.5 kHz divider (irrelevant) + * 0x01 = Disable Vt (aka sleep) + * + * 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA) + * 0x50 = AGC Take over point = 103 dBuV + */ +static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 }; + +/* 0x04 = 166.67 kHz divider + * + * 0x80 = AGC Time constant 50ms Iagc = 9 uA + * 0x20 = AGC Take over point = 112 dBuV + */ +static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 }; + /* 0-9 */ /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */ @@ -1425,6 +1446,7 @@ struct tunertype tuners[] = { .min = 16 * 57.00, .max = 16 * 863.00, .stepsize = 62500, + .initdata = tua603x_agc103, }, [TUNER_TENA_9533_DI] = { /* Philips PAL */ .name = "Tena TNF9533-D/IF/TNF9533-B/DF", @@ -1439,6 +1461,8 @@ struct tunertype tuners[] = { .name = "Philips FMD1216ME MK3 Hybrid Tuner", .params = tuner_philips_fmd1216me_mk3_params, .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), + .initdata = tua603x_agc112, + .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, }, [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */ .name = "LG TDVS-H06xF", /* H061F, H062F & H064F */ @@ -1447,6 +1471,7 @@ struct tunertype tuners[] = { .min = 16 * 54.00, .max = 16 * 863.00, .stepsize = 62500, + .initdata = tua603x_agc103, }, [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ .name = "Ymec TVF66T5-B/DFF", diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 4b5e5cf780c8..fda12093cab3 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -120,6 +120,9 @@ struct tunertype { u16 min; u16 max; u16 stepsize; + + u8 *initdata; + u8 *sleepdata; }; extern struct tunertype tuners[]; -- cgit v1.2.3 From fb62f7127b5b0f96259e5b4ce66de645bca273ca Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:27:59 -0300 Subject: V4L/DVB (7352): tuner-simple: enable digital tuning support for Philips FMD1216ME Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 18 ++++++++++++++++++ drivers/media/video/tuner-types.c | 18 ++++++++++++++++++ include/media/tuner-types.h | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 3a27d4a8ce38..b6587300bb8f 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -714,6 +714,22 @@ static int simple_set_params(struct dvb_frontend *fe, return ret; } +static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, + const struct dvb_frontend_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + switch (priv->type) { + case TUNER_PHILIPS_FMD1216ME_MK3: + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ && + params->frequency >= 158870000) + buf[3] |= 0x08; + break; + default: + break; + } +} + static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params) { @@ -737,6 +753,8 @@ static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, buf[2] = config; buf[3] = cb; + simple_set_dvb(fe, buf, params); + tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", tun->name, div, buf[0], buf[1], buf[2], buf[3]); diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 13c76a57d8e2..f2e6630731bf 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -923,6 +923,15 @@ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { { 16 * 999.99 , 0x86, 0x54, }, }; +static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = { + { 16 * 143.87 /*MHz*/, 0xbc, 0x41 }, + { 16 * 158.87 /*MHz*/, 0xf4, 0x41 }, + { 16 * 329.87 /*MHz*/, 0xbc, 0x42 }, + { 16 * 441.87 /*MHz*/, 0xf4, 0x42 }, + { 16 * 625.87 /*MHz*/, 0xbc, 0x44 }, + { 16 * 803.87 /*MHz*/, 0xf4, 0x44 }, + { 16 * 999.99 , 0xfc, 0x44 }, +}; static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { { @@ -936,6 +945,12 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { .port2_invert_for_secam_lc = 1, .port1_set_for_fm_mono = 1, }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges, + .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges), + .iffreq = 16 * 36.125, /*MHz*/ + }, }; @@ -1461,6 +1476,9 @@ struct tunertype tuners[] = { .name = "Philips FMD1216ME MK3 Hybrid Tuner", .params = tuner_philips_fmd1216me_mk3_params, .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), + .min = 16 * 50.87, + .max = 16 * 858.00, + .stepsize = 166667, .initdata = tua603x_agc112, .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, }, diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index fda12093cab3..ab03c5344209 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -119,7 +119,7 @@ struct tunertype { u16 min; u16 max; - u16 stepsize; + u32 stepsize; u8 *initdata; u8 *sleepdata; -- cgit v1.2.3 From e17b8862dc7048c888278b15b5b79e1ac593ea57 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:00 -0300 Subject: V4L/DVB (7353): tuner-simple: enable digital tuning support for Philips TUV1236D Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index f2e6630731bf..e61fc37a03d9 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1048,6 +1048,11 @@ static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = { { 16 * 999.99 , 0xce, 0x04, }, }; +static struct tuner_range tuner_tuv1236d_atsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0xc6, 0x41, }, + { 16 * 454.00 /*MHz*/, 0xc6, 0x42, }, + { 16 * 999.99 , 0xc6, 0x44, }, +}; static struct tuner_params tuner_tuv1236d_params[] = { { @@ -1055,6 +1060,12 @@ static struct tuner_params tuner_tuv1236d_params[] = { .ranges = tuner_tuv1236d_ntsc_ranges, .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges), }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_tuv1236d_atsc_ranges, + .count = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges), + .iffreq = 16 * 44.00, + }, }; /* ------------ TUNER_TNF_xxx5 - Texas Instruments--------- */ @@ -1510,6 +1521,9 @@ struct tunertype tuners[] = { .name = "Philips TUV1236D ATSC/NTSC dual in", .params = tuner_tuv1236d_params, .count = ARRAY_SIZE(tuner_tuv1236d_params), + .min = 16 * 54.00, + .max = 16 * 864.00, + .stepsize = 62500, }, [TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */ .name = "Tena TNF 5335 and similar models", -- cgit v1.2.3 From 3f2ce651ba300c4df8c4c63d3b8db8862cd06e9d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:00 -0300 Subject: V4L/DVB (7354): tuner-simple: enable digital tuning support for Philips FCV1236D Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index e61fc37a03d9..7a8a828bf89b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -617,17 +617,29 @@ static struct tuner_params tuner_philips_pal_mk_params[] = { /* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */ -static struct tuner_range tuner_philips_fcv1236d_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 451.25 /*MHz*/, 0x8e, 0x90, }, +static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x8e, 0xa2, }, + { 16 * 451.25 /*MHz*/, 0x8e, 0x92, }, + { 16 * 999.99 , 0x8e, 0x32, }, +}; + +static struct tuner_range tuner_philips_fcv1236d_atsc_ranges[] = { + { 16 * 159.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_fcv1236d_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_philips_fcv1236d_ranges, - .count = ARRAY_SIZE(tuner_philips_fcv1236d_ranges), + .ranges = tuner_philips_fcv1236d_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_fcv1236d_ntsc_ranges), + }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_philips_fcv1236d_atsc_ranges, + .count = ARRAY_SIZE(tuner_philips_fcv1236d_atsc_ranges), + .iffreq = 16 * 44.00, }, }; @@ -1376,6 +1388,9 @@ struct tunertype tuners[] = { .name = "Philips FCV1236D ATSC/NTSC dual in", .params = tuner_philips_fcv1236d_params, .count = ARRAY_SIZE(tuner_philips_fcv1236d_params), + .min = 16 * 53.00, + .max = 16 * 803.00, + .stepsize = 62500, }, [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", -- cgit v1.2.3 From 635fc567f548417617fc21e8fec62085f5fe3df5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:00 -0300 Subject: V4L/DVB (7355): tuner-simple: use separate inputs for vsb and qam on tuv1236d & fcv1236d Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index b6587300bb8f..8ecd92324c49 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -268,6 +268,37 @@ static int simple_config_lookup(struct dvb_frontend *fe, /* ---------------------------------------------------------------------- */ +static void simple_set_rf_input(struct dvb_frontend *fe, + u8 *config, u8 *cb, unsigned int rf) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + switch (priv->type) { + case TUNER_PHILIPS_TUV1236D: + switch (rf) { + case 1: + *cb |= 0x08; + break; + default: + *cb &= ~0x08; + break; + } + break; + case TUNER_PHILIPS_ATSC: + switch (rf) { + case 1: + *cb |= 0x01; + break; + default: + *cb &= ~0x01; + break; + } + break; + default: + break; + } +} + static int simple_std_setup(struct dvb_frontend *fe, struct analog_parameters *params, u8 *config, u8 *cb) @@ -725,6 +756,24 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, params->frequency >= 158870000) buf[3] |= 0x08; break; + case TUNER_PHILIPS_TUV1236D: + case TUNER_PHILIPS_ATSC: + { + unsigned int new_rf; + + switch (params->u.vsb.modulation) { + case QAM_64: + case QAM_256: + new_rf = 1; + break; + case VSB_8: + default: + new_rf = 0; + break; + } + simple_set_rf_input(fe, &buf[2], &buf[3], new_rf); + break; + } default: break; } -- cgit v1.2.3 From 83413dafa146019dba7b8ffa26e242bb8ca36d19 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:00 -0300 Subject: V4L/DVB (7356): tuner-simple: enable digital tuning support for Thomson DTT 7610 Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 7a8a828bf89b..71cadd84bcdd 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -773,6 +773,7 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = { /* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */ +/* single range used for both ntsc and atsc */ static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = { { 16 * 157.25 /*MHz*/, 0x8e, 0x39, }, { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, }, @@ -785,6 +786,12 @@ static struct tuner_params tuner_thomson_dtt7610_params[] = { .ranges = tuner_thomson_dtt7610_ntsc_ranges, .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges), }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_thomson_dtt7610_ntsc_ranges, + .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges), + .iffreq = 16 * 44.00 /*MHz*/, + }, }; /* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */ @@ -1443,6 +1450,9 @@ struct tunertype tuners[] = { .name = "Thomson DTT 7610 (ATSC/NTSC)", .params = tuner_thomson_dtt7610_params, .count = ARRAY_SIZE(tuner_thomson_dtt7610_params), + .min = 16 * 44.00, + .max = 16 * 958.00, + .stepsize = 62500, }, [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */ .name = "Philips FQ1286", -- cgit v1.2.3 From 39e037d07bba1549d53d269cda7e5b08c0ee3973 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:01 -0300 Subject: V4L/DVB (7357): tuner-simple: enable digital tuning support for Microtune 4042 FI5 Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 71cadd84bcdd..db3320519f8c 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -734,12 +734,24 @@ static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = { { 16 * 999.99 , 0x8e, 0x31, }, }; +static struct tuner_range tuner_microtune_4042fi5_atsc_ranges[] = { + { 16 * 162.00 /*MHz*/, 0x8e, 0xa1, }, + { 16 * 457.00 /*MHz*/, 0x8e, 0x91, }, + { 16 * 999.99 , 0x8e, 0x31, }, +}; + static struct tuner_params tuner_microtune_4042fi5_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_microtune_4042fi5_ntsc_ranges, .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges), }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_microtune_4042fi5_atsc_ranges, + .count = ARRAY_SIZE(tuner_microtune_4042fi5_atsc_ranges), + .iffreq = 16 * 44.00 /*MHz*/, + }, }; /* 50-59 */ @@ -1433,6 +1445,9 @@ struct tunertype tuners[] = { .name = "Microtune 4042 FI5 ATSC/NTSC dual in", .params = tuner_microtune_4042fi5_params, .count = ARRAY_SIZE(tuner_microtune_4042fi5_params), + .min = 16 * 57.00, + .max = 16 * 858.00, + .stepsize = 62500, }, /* 50-59 */ -- cgit v1.2.3 From 95917ffd273aa54d4b8051ee057cec2fbef82a6d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:01 -0300 Subject: V4L/DVB (7358): tuner-simple: enable digital tuning support for Philips TD1316 Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 9 +++++++++ drivers/media/video/tuner-types.c | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 8ecd92324c49..5356c8a92413 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -756,6 +756,15 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, params->frequency >= 158870000) buf[3] |= 0x08; break; + case TUNER_PHILIPS_TD1316: + /* determine band */ + buf[3] |= (params->frequency < 161000000) ? 1 : + (params->frequency < 444000000) ? 2 : 4; + + /* setup PLL filter */ + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) + buf[3] |= 1 << 3; + break; case TUNER_PHILIPS_TUV1236D: case TUNER_PHILIPS_ATSC: { diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index db3320519f8c..afb88ff7db50 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1063,12 +1063,30 @@ static struct tuner_range tuner_philips_td1316_pal_ranges[] = { { 16 * 999.99 , 0xc8, 0xa4, }, }; +static struct tuner_range tuner_philips_td1316_dvb_ranges[] = { + { 16 * 93.834 /*MHz*/, 0xca, 0x60, }, + { 16 * 123.834 /*MHz*/, 0xca, 0xa0, }, + { 16 * 163.834 /*MHz*/, 0xca, 0xc0, }, + { 16 * 253.834 /*MHz*/, 0xca, 0x60, }, + { 16 * 383.834 /*MHz*/, 0xca, 0xa0, }, + { 16 * 443.834 /*MHz*/, 0xca, 0xc0, }, + { 16 * 583.834 /*MHz*/, 0xca, 0x60, }, + { 16 * 793.834 /*MHz*/, 0xca, 0xa0, }, + { 16 * 999.999 , 0xca, 0xe0, }, +}; + static struct tuner_params tuner_philips_td1316_params[] = { { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_td1316_pal_ranges, .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges), }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_philips_td1316_dvb_ranges, + .count = ARRAY_SIZE(tuner_philips_td1316_dvb_ranges), + .iffreq = 16 * 36.166667 /*MHz*/, + }, }; /* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */ @@ -1556,6 +1574,9 @@ struct tunertype tuners[] = { .name = "Philips TD1316 Hybrid Tuner", .params = tuner_philips_td1316_params, .count = ARRAY_SIZE(tuner_philips_td1316_params), + .min = 16 * 87.00, + .max = 16 * 895.00, + .stepsize = 166667, }, [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ .name = "Philips TUV1236D ATSC/NTSC dual in", -- cgit v1.2.3 From d1a0f6b654c175775995ea3c82c9a2450b95377a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:01 -0300 Subject: V4L/DVB (7359): tuner-simple: enable digital tuning support for Thomson FE6600 Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index afb88ff7db50..ad16bc25197a 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1168,17 +1168,30 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { /* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */ -static struct tuner_range tuner_thomson_fe6600_ranges[] = { +static struct tuner_range tuner_thomson_fe6600_pal_ranges[] = { { 16 * 160.00 /*MHz*/, 0xfe, 0x11, }, { 16 * 442.00 /*MHz*/, 0xf6, 0x12, }, { 16 * 999.99 , 0xf6, 0x18, }, }; +static struct tuner_range tuner_thomson_fe6600_dvb_ranges[] = { + { 16 * 250.00 /*MHz*/, 0xb4, 0x12, }, + { 16 * 455.00 /*MHz*/, 0xfe, 0x11, }, + { 16 * 775.50 /*MHz*/, 0xbc, 0x18, }, + { 16 * 999.99 , 0xf4, 0x18, }, +}; + static struct tuner_params tuner_thomson_fe6600_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_thomson_fe6600_ranges, - .count = ARRAY_SIZE(tuner_thomson_fe6600_ranges), + .ranges = tuner_thomson_fe6600_pal_ranges, + .count = ARRAY_SIZE(tuner_thomson_fe6600_pal_ranges), + }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_thomson_fe6600_dvb_ranges, + .count = ARRAY_SIZE(tuner_thomson_fe6600_dvb_ranges), + .iffreq = 16 * 36.125 /*MHz*/, }, }; @@ -1606,6 +1619,9 @@ struct tunertype tuners[] = { .name = "Thomson FE6600", .params = tuner_thomson_fe6600_params, .count = ARRAY_SIZE(tuner_thomson_fe6600_params), + .min = 16 * 44.25, + .max = 16 * 858.00, + .stepsize = 166667, }, [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */ .name = "Samsung TCPG 6121P30A", -- cgit v1.2.3 From 1beee846bba239e2684e9277f6adc063f65569ad Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:01 -0300 Subject: V4L/DVB (7360): tuner-simple: fix return value of simple_dvb_configure simple_dvb_configure returns the actual tuned frequency to its caller, so it must be declared as a u32 rather than an int. As a result, we will return 0 to indicate a failure. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 5356c8a92413..b95ed1f489a0 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -788,9 +788,10 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, } } -static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, +static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params) { + /* This function returns the tuned frequency on success, 0 on error */ struct tuner_simple_priv *priv = fe->tuner_priv; struct tunertype *tun = priv->tun; static struct tuner_params *t_params; @@ -801,7 +802,7 @@ static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL); ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb); if (ret < 0) - return ret; + return 0; /* failure */ div = ((frequency + t_params->iffreq) * 62500 + offset + tun->stepsize/2) / tun->stepsize; @@ -825,17 +826,14 @@ static int simple_dvb_calc_regs(struct dvb_frontend *fe, u8 *buf, int buf_len) { struct tuner_simple_priv *priv = fe->tuner_priv; - int ret; u32 frequency; if (buf_len < 5) return -EINVAL; - ret = simple_dvb_configure(fe, buf+1, params); - if (ret < 0) - return ret; - else - frequency = ret; + frequency = simple_dvb_configure(fe, buf+1, params); + if (frequency == 0) + return -EINVAL; buf[0] = priv->i2c_props.addr; -- cgit v1.2.3 From 0fb08b254963b38b1433d26659d881b68962cd9b Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Wed, 2 Apr 2008 14:28:02 -0300 Subject: V4L/DVB (7363): fix coding style violations in v4l1-compat.c fix most coding style violations found by checkpatch Signed-off-by: Marcin Slusarz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l1-compat.c | 184 +++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index ffd3f106dd4f..6455b2f43bed 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -41,13 +41,16 @@ static unsigned int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug,"enable debug messages"); +MODULE_PARM_DESC(debug, "enable debug messages"); MODULE_AUTHOR("Bill Dirks"); MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers."); MODULE_LICENSE("GPL"); -#define dprintk(fmt, arg...) if (debug) \ - printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg) +#define dprintk(fmt, arg...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\ + } while (0) /* * I O C T L T R A N S L A T I O N @@ -69,14 +72,12 @@ get_v4l_control(struct inode *inode, qctrl2.id = cid; err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2); if (err < 0) - dprintk("VIDIOC_QUERYCTRL: %d\n",err); - if (err == 0 && - !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) - { + dprintk("VIDIOC_QUERYCTRL: %d\n", err); + if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) { ctrl2.id = qctrl2.id; err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2); if (err < 0) { - dprintk("VIDIOC_G_CTRL: %d\n",err); + dprintk("VIDIOC_G_CTRL: %d\n", err); return 0; } return ((ctrl2.value - qctrl2.minimum) * 65535 @@ -100,11 +101,10 @@ set_v4l_control(struct inode *inode, qctrl2.id = cid; err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2); if (err < 0) - dprintk("VIDIOC_QUERYCTRL: %d\n",err); + dprintk("VIDIOC_QUERYCTRL: %d\n", err); if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) && - !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) - { + !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) { if (value < 0) value = 0; if (value > 65535) @@ -119,7 +119,7 @@ set_v4l_control(struct inode *inode, ctrl2.value += qctrl2.minimum; err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2); if (err < 0) - dprintk("VIDIOC_S_CTRL: %d\n",err); + dprintk("VIDIOC_S_CTRL: %d\n", err); } return 0; } @@ -157,8 +157,7 @@ static unsigned int __attribute_const__ pixelformat_to_palette(unsigned int pixelformat) { int palette = 0; - switch (pixelformat) - { + switch (pixelformat) { case V4L2_PIX_FMT_GREY: palette = VIDEO_PALETTE_GREY; break; @@ -234,9 +233,9 @@ static int count_inputs(struct inode *inode, int i; for (i = 0;; i++) { - memset(&input2,0,sizeof(input2)); + memset(&input2, 0, sizeof(input2)); input2.index = i; - if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2)) + if (0 != drv(inode, file, VIDIOC_ENUMINPUT, &input2)) break; } return i; @@ -250,18 +249,18 @@ static int check_size(struct inode *inode, struct v4l2_fmtdesc desc2; struct v4l2_format fmt2; - memset(&desc2,0,sizeof(desc2)); - memset(&fmt2,0,sizeof(fmt2)); + memset(&desc2, 0, sizeof(desc2)); + memset(&fmt2, 0, sizeof(fmt2)); desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2)) + if (0 != drv(inode, file, VIDIOC_ENUM_FMT, &desc2)) goto done; fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt2.fmt.pix.width = 10000; fmt2.fmt.pix.height = 10000; fmt2.fmt.pix.pixelformat = desc2.pixelformat; - if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2)) + if (0 != drv(inode, file, VIDIOC_TRY_FMT, &fmt2)) goto done; *maxw = fmt2.fmt.pix.width; @@ -313,13 +312,13 @@ v4l_compat_translate_ioctl(struct inode *inode, err = drv(inode, file, VIDIOC_QUERYCAP, cap2); if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err); + dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err); break; } if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err); + dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err); memset(&fbuf2, 0, sizeof(fbuf2)); } err = 0; @@ -339,9 +338,9 @@ v4l_compat_translate_ioctl(struct inode *inode, if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING) cap->type |= VID_TYPE_CLIPPING; - cap->channels = count_inputs(inode,file,drv); - check_size(inode,file,drv, - &cap->maxwidth,&cap->maxheight); + cap->channels = count_inputs(inode, file, drv); + check_size(inode, file, drv, + &cap->maxwidth, &cap->maxheight); cap->audios = 0; /* FIXME */ cap->minwidth = 48; /* FIXME */ cap->minheight = 32; /* FIXME */ @@ -356,7 +355,7 @@ v4l_compat_translate_ioctl(struct inode *inode, err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); if (err < 0) { - dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err); + dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err); break; } buffer->base = fbuf2.base; @@ -386,8 +385,8 @@ v4l_compat_translate_ioctl(struct inode *inode, buffer->bytesperline = fbuf2.fmt.bytesperline; if (!buffer->depth && buffer->width) buffer->depth = ((fbuf2.fmt.bytesperline<<3) - + (buffer->width-1) ) - /buffer->width; + + (buffer->width-1)) + / buffer->width; } else { buffer->bytesperline = (buffer->width * buffer->depth + 7) & 7; @@ -423,7 +422,7 @@ v4l_compat_translate_ioctl(struct inode *inode, fbuf2.fmt.bytesperline = buffer->bytesperline; err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); if (err < 0) - dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err); + dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err); break; } case VIDIOCGWIN: /* get window or capture dimensions */ @@ -435,12 +434,12 @@ v4l_compat_translate_ioctl(struct inode *inode, err = -ENOMEM; break; } - memset(win,0,sizeof(*win)); + memset(win, 0, sizeof(*win)); fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) - dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err); + dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err); if (err == 0) { win->x = fmt2->fmt.win.w.left; win->y = fmt2->fmt.win.w.top; @@ -455,7 +454,7 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { - dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err); + dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err); break; } win->x = 0; @@ -470,7 +469,7 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCSWIN: /* set window and/or capture dimensions */ { struct video_window *win = arg; - int err1,err2; + int err1, err2; fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); if (!fmt2) { @@ -481,7 +480,7 @@ v4l_compat_translate_ioctl(struct inode *inode, drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type); err1 = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err1 < 0) - dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err); + dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err); if (err1 == 0) { fmt2->fmt.pix.width = win->width; fmt2->fmt.pix.height = win->height; @@ -495,7 +494,7 @@ v4l_compat_translate_ioctl(struct inode *inode, win->height = fmt2->fmt.pix.height; } - memset(fmt2,0,sizeof(*fmt2)); + memset(fmt2, 0, sizeof(*fmt2)); fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; fmt2->fmt.win.w.left = win->x; fmt2->fmt.win.w.top = win->y; @@ -506,7 +505,7 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt2->fmt.win.clipcount = win->clipcount; err2 = drv(inode, file, VIDIOC_S_FMT, fmt2); if (err2 < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err); + dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err); if (err1 != 0 && err2 != 0) err = err1; @@ -524,19 +523,19 @@ v4l_compat_translate_ioctl(struct inode *inode, } err = drv(inode, file, VIDIOC_OVERLAY, arg); if (err < 0) - dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err); + dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); break; } case VIDIOCGCHAN: /* get input information */ { struct video_channel *chan = arg; - memset(&input2,0,sizeof(input2)); + memset(&input2, 0, sizeof(input2)); input2.index = chan->channel; err = drv(inode, file, VIDIOC_ENUMINPUT, &input2); if (err < 0) { dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " - "channel=%d err=%d\n",chan->channel,err); + "channel=%d err=%d\n", chan->channel, err); break; } chan->channel = input2.index; @@ -557,7 +556,7 @@ v4l_compat_translate_ioctl(struct inode *inode, chan->norm = 0; err = drv(inode, file, VIDIOC_G_STD, &sid); if (err < 0) - dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err); + dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err); if (err == 0) { if (sid & V4L2_STD_PAL) chan->norm = VIDEO_MODE_PAL; @@ -575,7 +574,7 @@ v4l_compat_translate_ioctl(struct inode *inode, sid = 0; err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel); if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err); + dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err); switch (chan->norm) { case VIDEO_MODE_PAL: sid = V4L2_STD_PAL; @@ -590,7 +589,7 @@ v4l_compat_translate_ioctl(struct inode *inode, if (0 != sid) { err = drv(inode, file, VIDIOC_S_STD, &sid); if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err); + dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err); } break; } @@ -605,7 +604,7 @@ v4l_compat_translate_ioctl(struct inode *inode, } pict->brightness = get_v4l_control(inode, file, - V4L2_CID_BRIGHTNESS,drv); + V4L2_CID_BRIGHTNESS, drv); pict->hue = get_v4l_control(inode, file, V4L2_CID_HUE, drv); pict->contrast = get_v4l_control(inode, file, @@ -618,13 +617,13 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { - dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err); + dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err); break; } - pict->depth = ((fmt2->fmt.pix.bytesperline<<3) - + (fmt2->fmt.pix.width-1) ) - /fmt2->fmt.pix.width; + pict->depth = ((fmt2->fmt.pix.bytesperline << 3) + + (fmt2->fmt.pix.width - 1)) + / fmt2->fmt.pix.width; pict->palette = pixelformat_to_palette( fmt2->fmt.pix.pixelformat); break; @@ -664,7 +663,7 @@ v4l_compat_translate_ioctl(struct inode *inode, support memory capture. Trying to set the memory capture parameters would be pointless. */ if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err); + dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err); mem_err = -1000; /* didn't even try */ } else if (fmt2->fmt.pix.pixelformat != palette_to_pixelformat(pict->palette)) { @@ -681,7 +680,7 @@ v4l_compat_translate_ioctl(struct inode *inode, support overlay. Trying to set the overlay parameters would be quite pointless. */ if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err); + dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err); ovl_err = -1000; /* didn't even try */ } else if (fbuf2.fmt.pixelformat != palette_to_pixelformat(pict->palette)) { @@ -692,16 +691,15 @@ v4l_compat_translate_ioctl(struct inode *inode, dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", ovl_err); } - if (ovl_err < 0 && mem_err < 0) + if (ovl_err < 0 && mem_err < 0) { /* ioctl failed, couldn't set either parameter */ - if (mem_err != -1000) { - err = mem_err; - } else if (ovl_err == -EPERM) { - err = 0; - } else { - err = ovl_err; - } - else + if (mem_err != -1000) + err = mem_err; + else if (ovl_err == -EPERM) + err = 0; + else + err = ovl_err; + } else err = 0; break; } @@ -709,10 +707,10 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct video_tuner *tun = arg; - memset(&tun2,0,sizeof(tun2)); + memset(&tun2, 0, sizeof(tun2)); err = drv(inode, file, VIDIOC_G_TUNER, &tun2); if (err < 0) { - dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err); + dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err); break; } memcpy(tun->name, tun2.name, @@ -724,7 +722,7 @@ v4l_compat_translate_ioctl(struct inode *inode, tun->mode = VIDEO_MODE_AUTO; for (i = 0; i < 64; i++) { - memset(&std2,0,sizeof(std2)); + memset(&std2, 0, sizeof(std2)); std2.index = i; if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2)) break; @@ -738,7 +736,7 @@ v4l_compat_translate_ioctl(struct inode *inode, err = drv(inode, file, VIDIOC_G_STD, &sid); if (err < 0) - dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err); + dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err); if (err == 0) { if (sid & V4L2_STD_PAL) tun->mode = VIDEO_MODE_PAL; @@ -759,25 +757,25 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct video_tuner *tun = arg; struct v4l2_tuner t; - memset(&t,0,sizeof(t)); + memset(&t, 0, sizeof(t)); - t.index=tun->tuner; + t.index = tun->tuner; err = drv(inode, file, VIDIOC_S_INPUT, &t); if (err < 0) - dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err); + dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err); break; } case VIDIOCGFREQ: /* get frequency */ { unsigned long *freq = arg; - memset(&freq2,0,sizeof(freq2)); + memset(&freq2, 0, sizeof(freq2)); freq2.tuner = 0; err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); if (err < 0) - dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err); + dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err); if (0 == err) *freq = freq2.frequency; break; @@ -785,23 +783,23 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCSFREQ: /* set frequency */ { unsigned long *freq = arg; - memset(&freq2,0,sizeof(freq2)); + memset(&freq2, 0, sizeof(freq2)); drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); freq2.frequency = *freq; err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); if (err < 0) - dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err); + dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err); break; } case VIDIOCGAUDIO: /* get audio properties/controls */ { struct video_audio *aud = arg; - memset(&aud2,0,sizeof(aud2)); + memset(&aud2, 0, sizeof(aud2)); err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err); + dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err); break; } memcpy(aud->name, aud2.name, @@ -842,10 +840,10 @@ v4l_compat_translate_ioctl(struct inode *inode, aud->step = qctrl2.step; aud->mode = 0; - memset(&tun2,0,sizeof(tun2)); + memset(&tun2, 0, sizeof(tun2)); err = drv(inode, file, VIDIOC_G_TUNER, &tun2); if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err); + dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err); err = 0; break; } @@ -862,13 +860,13 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct video_audio *aud = arg; - memset(&aud2,0,sizeof(aud2)); - memset(&tun2,0,sizeof(tun2)); + memset(&aud2, 0, sizeof(aud2)); + memset(&tun2, 0, sizeof(tun2)); aud2.index = aud->audio; err = drv(inode, file, VIDIOC_S_AUDIO, &aud2); if (err < 0) { - dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err); + dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err); break; } @@ -885,7 +883,7 @@ v4l_compat_translate_ioctl(struct inode *inode, err = drv(inode, file, VIDIOC_G_TUNER, &tun2); if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err); + dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err); if (err == 0) { switch (aud->mode) { default: @@ -902,7 +900,7 @@ v4l_compat_translate_ioctl(struct inode *inode, } err = drv(inode, file, VIDIOC_S_TUNER, &tun2); if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err); + dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err); } err = 0; break; @@ -916,19 +914,19 @@ v4l_compat_translate_ioctl(struct inode *inode, err = -ENOMEM; break; } - memset(&buf2,0,sizeof(buf2)); + memset(&buf2, 0, sizeof(buf2)); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err); + dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err); break; } if (mm->width != fmt2->fmt.pix.width || mm->height != fmt2->fmt.pix.height || palette_to_pixelformat(mm->format) != - fmt2->fmt.pix.pixelformat) - {/* New capture format... */ + fmt2->fmt.pix.pixelformat) { + /* New capture format... */ fmt2->fmt.pix.width = mm->width; fmt2->fmt.pix.height = mm->height; fmt2->fmt.pix.pixelformat = @@ -937,7 +935,7 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt2->fmt.pix.bytesperline = 0; err = drv(inode, file, VIDIOC_S_FMT, fmt2); if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err); + dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err); break; } } @@ -945,30 +943,30 @@ v4l_compat_translate_ioctl(struct inode *inode, buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err); + dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err); break; } err = drv(inode, file, VIDIOC_QBUF, &buf2); if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err); + dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err); break; } err = drv(inode, file, VIDIOC_STREAMON, &captype); if (err < 0) - dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err); + dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err); break; } case VIDIOCSYNC: /* wait for a frame */ { int *i = arg; - memset(&buf2,0,sizeof(buf2)); + memset(&buf2, 0, sizeof(buf2)); buf2.index = *i; buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); if (err < 0) { /* No such buffer */ - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err); + dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); break; } if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) { @@ -980,29 +978,28 @@ v4l_compat_translate_ioctl(struct inode *inode, /* make sure capture actually runs so we don't block forever */ err = drv(inode, file, VIDIOC_STREAMON, &captype); if (err < 0) { - dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err); + dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err); break; } /* Loop as long as the buffer is queued, but not done */ while ((buf2.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) - == V4L2_BUF_FLAG_QUEUED) - { + == V4L2_BUF_FLAG_QUEUED) { err = poll_one(file); if (err < 0 || /* error or sleep was interrupted */ err == 0) /* timeout? Shouldn't occur. */ break; err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err); + dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); } if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */ break; do { err = drv(inode, file, VIDIOC_DQBUF, &buf2); if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err); + dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err); } while (err == 0 && buf2.index != *i); break; } @@ -1093,7 +1090,6 @@ v4l_compat_translate_ioctl(struct inode *inode, kfree(fmt2); return err; } - EXPORT_SYMBOL(v4l_compat_translate_ioctl); /* -- cgit v1.2.3 From 76292d49524c2d540be125c91089128316f01817 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Wed, 2 Apr 2008 14:28:02 -0300 Subject: V4L/DVB (7364): reduce stack usage of v4l_compat_translate_ioctl v4l_compat_translate_ioctl used 1376 bytes of stack (x86_64), so split this 800 lines long function into ~20 small noinline functions; the biggest function takes now 712 bytes (v4l1_compat_sync) fix VIDIOCSWIN handler which printked wrong errors Signed-off-by: Marcin Slusarz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l1-compat.c | 1681 +++++++++++++++++++++---------------- 1 file changed, 938 insertions(+), 743 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 6455b2f43bed..e42cea987964 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -203,7 +203,7 @@ static int poll_one(struct file *file) { int retval = 1; poll_table *table; - struct poll_wqueues pwq; + struct poll_wqueues pwq; /*TODO: allocate dynamically*/ poll_initwait(&pwq); table = &pwq.pt; @@ -225,9 +225,10 @@ static int poll_one(struct file *file) return retval; } -static int count_inputs(struct inode *inode, - struct file *file, - v4l2_kioctl drv) +static int count_inputs( + struct inode *inode, + struct file *file, + v4l2_kioctl drv) { struct v4l2_input input2; int i; @@ -241,10 +242,12 @@ static int count_inputs(struct inode *inode, return i; } -static int check_size(struct inode *inode, - struct file *file, - v4l2_kioctl drv, - int *maxw, int *maxh) +static int check_size( + struct inode *inode, + struct file *file, + v4l2_kioctl drv, + int *maxw, + int *maxh) { struct v4l2_fmtdesc desc2; struct v4l2_format fmt2; @@ -266,828 +269,1020 @@ static int check_size(struct inode *inode, *maxw = fmt2.fmt.pix.width; *maxh = fmt2.fmt.pix.height; - done: +done: return 0; } /* ----------------------------------------------------------------- */ -/* - * This function is exported. - */ -int -v4l_compat_translate_ioctl(struct inode *inode, - struct file *file, - int cmd, - void *arg, - v4l2_kioctl drv) +static noinline int v4l1_compat_get_capabilities( + struct video_capability *cap, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) { - struct v4l2_capability *cap2 = NULL; - struct v4l2_format *fmt2 = NULL; - enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - struct v4l2_framebuffer fbuf2; - struct v4l2_input input2; - struct v4l2_tuner tun2; - struct v4l2_standard std2; - struct v4l2_frequency freq2; - struct v4l2_audio aud2; - struct v4l2_queryctrl qctrl2; - struct v4l2_buffer buf2; - v4l2_std_id sid; - int i, err = 0; - - switch (cmd) { - case VIDIOCGCAP: /* capability */ - { - struct video_capability *cap = arg; - - cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL); - if (!cap2) { - err = -ENOMEM; - break; - } - memset(cap, 0, sizeof(*cap)); - memset(&fbuf2, 0, sizeof(fbuf2)); + int err; + struct v4l2_framebuffer fbuf; + struct v4l2_capability *cap2; + + cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL); + if (!cap2) { + err = -ENOMEM; + return err; + } + memset(cap, 0, sizeof(*cap)); + memset(&fbuf, 0, sizeof(fbuf)); - err = drv(inode, file, VIDIOC_QUERYCAP, cap2); + err = drv(inode, file, VIDIOC_QUERYCAP, cap2); + if (err < 0) { + dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err); + goto done; + } + if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { + err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err); - break; - } - if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { - err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); - if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err); - memset(&fbuf2, 0, sizeof(fbuf2)); - } - err = 0; + dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err); + memset(&fbuf, 0, sizeof(fbuf)); } - - memcpy(cap->name, cap2->card, - min(sizeof(cap->name), sizeof(cap2->card))); - cap->name[sizeof(cap->name) - 1] = 0; - if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE) - cap->type |= VID_TYPE_CAPTURE; - if (cap2->capabilities & V4L2_CAP_TUNER) - cap->type |= VID_TYPE_TUNER; - if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE) - cap->type |= VID_TYPE_TELETEXT; - if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) - cap->type |= VID_TYPE_OVERLAY; - if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING) - cap->type |= VID_TYPE_CLIPPING; - - cap->channels = count_inputs(inode, file, drv); - check_size(inode, file, drv, - &cap->maxwidth, &cap->maxheight); - cap->audios = 0; /* FIXME */ - cap->minwidth = 48; /* FIXME */ - cap->minheight = 32; /* FIXME */ - break; + err = 0; } - case VIDIOCGFBUF: /* get frame buffer */ - { - struct video_buffer *buffer = arg; - memset(buffer, 0, sizeof(*buffer)); - memset(&fbuf2, 0, sizeof(fbuf2)); + memcpy(cap->name, cap2->card, + min(sizeof(cap->name), sizeof(cap2->card))); + cap->name[sizeof(cap->name) - 1] = 0; + if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE) + cap->type |= VID_TYPE_CAPTURE; + if (cap2->capabilities & V4L2_CAP_TUNER) + cap->type |= VID_TYPE_TUNER; + if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE) + cap->type |= VID_TYPE_TELETEXT; + if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) + cap->type |= VID_TYPE_OVERLAY; + if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING) + cap->type |= VID_TYPE_CLIPPING; + + cap->channels = count_inputs(inode, file, drv); + check_size(inode, file, drv, + &cap->maxwidth, &cap->maxheight); + cap->audios = 0; /* FIXME */ + cap->minwidth = 48; /* FIXME */ + cap->minheight = 32; /* FIXME */ + +done: + kfree(cap2); + return err; +} - err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); - if (err < 0) { - dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err); - break; - } - buffer->base = fbuf2.base; - buffer->height = fbuf2.fmt.height; - buffer->width = fbuf2.fmt.width; +static noinline int v4l1_compat_get_frame_buffer( + struct video_buffer *buffer, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_framebuffer fbuf; - switch (fbuf2.fmt.pixelformat) { - case V4L2_PIX_FMT_RGB332: - buffer->depth = 8; - break; - case V4L2_PIX_FMT_RGB555: - buffer->depth = 15; - break; - case V4L2_PIX_FMT_RGB565: - buffer->depth = 16; - break; - case V4L2_PIX_FMT_BGR24: - buffer->depth = 24; - break; - case V4L2_PIX_FMT_BGR32: - buffer->depth = 32; - break; - default: - buffer->depth = 0; - } - if (fbuf2.fmt.bytesperline) { - buffer->bytesperline = fbuf2.fmt.bytesperline; - if (!buffer->depth && buffer->width) - buffer->depth = ((fbuf2.fmt.bytesperline<<3) - + (buffer->width-1)) - / buffer->width; - } else { - buffer->bytesperline = - (buffer->width * buffer->depth + 7) & 7; - buffer->bytesperline >>= 3; - } + memset(buffer, 0, sizeof(*buffer)); + memset(&fbuf, 0, sizeof(fbuf)); + + err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); + if (err < 0) { + dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err); + goto done; + } + buffer->base = fbuf.base; + buffer->height = fbuf.fmt.height; + buffer->width = fbuf.fmt.width; + + switch (fbuf.fmt.pixelformat) { + case V4L2_PIX_FMT_RGB332: + buffer->depth = 8; break; + case V4L2_PIX_FMT_RGB555: + buffer->depth = 15; + break; + case V4L2_PIX_FMT_RGB565: + buffer->depth = 16; + break; + case V4L2_PIX_FMT_BGR24: + buffer->depth = 24; + break; + case V4L2_PIX_FMT_BGR32: + buffer->depth = 32; + break; + default: + buffer->depth = 0; } - case VIDIOCSFBUF: /* set frame buffer */ - { - struct video_buffer *buffer = arg; - - memset(&fbuf2, 0, sizeof(fbuf2)); - fbuf2.base = buffer->base; - fbuf2.fmt.height = buffer->height; - fbuf2.fmt.width = buffer->width; - switch (buffer->depth) { - case 8: - fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332; - break; - case 15: - fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555; - break; - case 16: - fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565; - break; - case 24: - fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24; - break; - case 32: - fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32; - break; - } - fbuf2.fmt.bytesperline = buffer->bytesperline; - err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); - if (err < 0) - dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err); + if (fbuf.fmt.bytesperline) { + buffer->bytesperline = fbuf.fmt.bytesperline; + if (!buffer->depth && buffer->width) + buffer->depth = ((fbuf.fmt.bytesperline<<3) + + (buffer->width-1)) + / buffer->width; + } else { + buffer->bytesperline = + (buffer->width * buffer->depth + 7) & 7; + buffer->bytesperline >>= 3; + } +done: + return err; +} + +static noinline int v4l1_compat_set_frame_buffer( + struct video_buffer *buffer, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_framebuffer fbuf; + + memset(&fbuf, 0, sizeof(fbuf)); + fbuf.base = buffer->base; + fbuf.fmt.height = buffer->height; + fbuf.fmt.width = buffer->width; + switch (buffer->depth) { + case 8: + fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332; + break; + case 15: + fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555; + break; + case 16: + fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565; + break; + case 24: + fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24; + break; + case 32: + fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32; break; } - case VIDIOCGWIN: /* get window or capture dimensions */ - { - struct video_window *win = arg; + fbuf.fmt.bytesperline = buffer->bytesperline; + err = drv(inode, file, VIDIOC_S_FBUF, &fbuf); + if (err < 0) + dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err); + return err; +} - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - break; - } - memset(win, 0, sizeof(*win)); +static noinline int v4l1_compat_get_win_cap_dimensions( + struct video_window *win, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_format *fmt; - fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - err = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err < 0) - dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err); - if (err == 0) { - win->x = fmt2->fmt.win.w.left; - win->y = fmt2->fmt.win.w.top; - win->width = fmt2->fmt.win.w.width; - win->height = fmt2->fmt.win.w.height; - win->chromakey = fmt2->fmt.win.chromakey; - win->clips = NULL; - win->clipcount = 0; - break; - } + fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); + if (!fmt) { + err = -ENOMEM; + return err; + } + memset(win, 0, sizeof(*win)); - fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err); - break; - } - win->x = 0; - win->y = 0; - win->width = fmt2->fmt.pix.width; - win->height = fmt2->fmt.pix.height; - win->chromakey = 0; + fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + err = drv(inode, file, VIDIOC_G_FMT, fmt); + if (err < 0) + dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err); + if (err == 0) { + win->x = fmt->fmt.win.w.left; + win->y = fmt->fmt.win.w.top; + win->width = fmt->fmt.win.w.width; + win->height = fmt->fmt.win.w.height; + win->chromakey = fmt->fmt.win.chromakey; win->clips = NULL; win->clipcount = 0; - break; + goto done; } - case VIDIOCSWIN: /* set window and/or capture dimensions */ - { - struct video_window *win = arg; - int err1, err2; - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - break; - } - fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type); - err1 = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err1 < 0) - dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err); - if (err1 == 0) { - fmt2->fmt.pix.width = win->width; - fmt2->fmt.pix.height = win->height; - fmt2->fmt.pix.field = V4L2_FIELD_ANY; - fmt2->fmt.pix.bytesperline = 0; - err = drv(inode, file, VIDIOC_S_FMT, fmt2); - if (err < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n", - err); - win->width = fmt2->fmt.pix.width; - win->height = fmt2->fmt.pix.height; - } + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + err = drv(inode, file, VIDIOC_G_FMT, fmt); + if (err < 0) { + dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err); + goto done; + } + win->x = 0; + win->y = 0; + win->width = fmt->fmt.pix.width; + win->height = fmt->fmt.pix.height; + win->chromakey = 0; + win->clips = NULL; + win->clipcount = 0; +done: + kfree(fmt); + return err; +} - memset(fmt2, 0, sizeof(*fmt2)); - fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - fmt2->fmt.win.w.left = win->x; - fmt2->fmt.win.w.top = win->y; - fmt2->fmt.win.w.width = win->width; - fmt2->fmt.win.w.height = win->height; - fmt2->fmt.win.chromakey = win->chromakey; - fmt2->fmt.win.clips = (void __user *)win->clips; - fmt2->fmt.win.clipcount = win->clipcount; - err2 = drv(inode, file, VIDIOC_S_FMT, fmt2); - if (err2 < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err); - - if (err1 != 0 && err2 != 0) - err = err1; - break; +static noinline int v4l1_compat_set_win_cap_dimensions( + struct video_window *win, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err, err1, err2; + struct v4l2_format *fmt; + + fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); + if (!fmt) { + err = -ENOMEM; + return err; } - case VIDIOCCAPTURE: /* turn on/off preview */ - { - int *on = arg; - - if (0 == *on) { - /* dirty hack time. But v4l1 has no STREAMOFF - * equivalent in the API, and this one at - * least comes close ... */ - drv(inode, file, VIDIOC_STREAMOFF, &captype); - } - err = drv(inode, file, VIDIOC_OVERLAY, arg); + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + drv(inode, file, VIDIOC_STREAMOFF, &fmt->type); + err1 = drv(inode, file, VIDIOC_G_FMT, fmt); + if (err1 < 0) + dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1); + if (err1 == 0) { + fmt->fmt.pix.width = win->width; + fmt->fmt.pix.height = win->height; + fmt->fmt.pix.field = V4L2_FIELD_ANY; + fmt->fmt.pix.bytesperline = 0; + err = drv(inode, file, VIDIOC_S_FMT, fmt); if (err < 0) - dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); - break; + dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n", + err); + win->width = fmt->fmt.pix.width; + win->height = fmt->fmt.pix.height; } - case VIDIOCGCHAN: /* get input information */ - { - struct video_channel *chan = arg; - memset(&input2, 0, sizeof(input2)); - input2.index = chan->channel; - err = drv(inode, file, VIDIOC_ENUMINPUT, &input2); - if (err < 0) { - dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " - "channel=%d err=%d\n", chan->channel, err); - break; - } - chan->channel = input2.index; - memcpy(chan->name, input2.name, - min(sizeof(chan->name), sizeof(input2.name))); - chan->name[sizeof(chan->name) - 1] = 0; - chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0; - chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0; - switch (input2.type) { - case V4L2_INPUT_TYPE_TUNER: - chan->type = VIDEO_TYPE_TV; - break; - default: - case V4L2_INPUT_TYPE_CAMERA: - chan->type = VIDEO_TYPE_CAMERA; - break; - } - chan->norm = 0; - err = drv(inode, file, VIDIOC_G_STD, &sid); - if (err < 0) - dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err); - if (err == 0) { - if (sid & V4L2_STD_PAL) - chan->norm = VIDEO_MODE_PAL; - if (sid & V4L2_STD_NTSC) - chan->norm = VIDEO_MODE_NTSC; - if (sid & V4L2_STD_SECAM) - chan->norm = VIDEO_MODE_SECAM; - } - break; - } - case VIDIOCSCHAN: /* set input */ - { - struct video_channel *chan = arg; + memset(fmt, 0, sizeof(*fmt)); + fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + fmt->fmt.win.w.left = win->x; + fmt->fmt.win.w.top = win->y; + fmt->fmt.win.w.width = win->width; + fmt->fmt.win.w.height = win->height; + fmt->fmt.win.chromakey = win->chromakey; + fmt->fmt.win.clips = (void __user *)win->clips; + fmt->fmt.win.clipcount = win->clipcount; + err2 = drv(inode, file, VIDIOC_S_FMT, fmt); + if (err2 < 0) + dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2); + + if (err1 != 0 && err2 != 0) + err = err1; + else + err = 0; + kfree(fmt); + return err; +} - sid = 0; - err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel); - if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err); - switch (chan->norm) { - case VIDEO_MODE_PAL: - sid = V4L2_STD_PAL; - break; - case VIDEO_MODE_NTSC: - sid = V4L2_STD_NTSC; - break; - case VIDEO_MODE_SECAM: - sid = V4L2_STD_SECAM; - break; - } - if (0 != sid) { - err = drv(inode, file, VIDIOC_S_STD, &sid); - if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err); - } - break; +static noinline int v4l1_compat_turn_preview_on_off( + int *on, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (0 == *on) { + /* dirty hack time. But v4l1 has no STREAMOFF + * equivalent in the API, and this one at + * least comes close ... */ + drv(inode, file, VIDIOC_STREAMOFF, &captype); } - case VIDIOCGPICT: /* get tone controls & partial capture format */ - { - struct video_picture *pict = arg; - - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - break; - } + err = drv(inode, file, VIDIOC_OVERLAY, on); + if (err < 0) + dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); + return err; +} - pict->brightness = get_v4l_control(inode, file, - V4L2_CID_BRIGHTNESS, drv); - pict->hue = get_v4l_control(inode, file, - V4L2_CID_HUE, drv); - pict->contrast = get_v4l_control(inode, file, - V4L2_CID_CONTRAST, drv); - pict->colour = get_v4l_control(inode, file, - V4L2_CID_SATURATION, drv); - pict->whiteness = get_v4l_control(inode, file, - V4L2_CID_WHITENESS, drv); - - fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err); - break; - } +static noinline int v4l1_compat_get_input_info( + struct video_channel *chan, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_input input2; + v4l2_std_id sid; - pict->depth = ((fmt2->fmt.pix.bytesperline << 3) - + (fmt2->fmt.pix.width - 1)) - / fmt2->fmt.pix.width; - pict->palette = pixelformat_to_palette( - fmt2->fmt.pix.pixelformat); + memset(&input2, 0, sizeof(input2)); + input2.index = chan->channel; + err = drv(inode, file, VIDIOC_ENUMINPUT, &input2); + if (err < 0) { + dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " + "channel=%d err=%d\n", chan->channel, err); + goto done; + } + chan->channel = input2.index; + memcpy(chan->name, input2.name, + min(sizeof(chan->name), sizeof(input2.name))); + chan->name[sizeof(chan->name) - 1] = 0; + chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0; + chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0; + switch (input2.type) { + case V4L2_INPUT_TYPE_TUNER: + chan->type = VIDEO_TYPE_TV; + break; + default: + case V4L2_INPUT_TYPE_CAMERA: + chan->type = VIDEO_TYPE_CAMERA; break; } - case VIDIOCSPICT: /* set tone controls & partial capture format */ - { - struct video_picture *pict = arg; - int mem_err = 0, ovl_err = 0; + chan->norm = 0; + err = drv(inode, file, VIDIOC_G_STD, &sid); + if (err < 0) + dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err); + if (err == 0) { + if (sid & V4L2_STD_PAL) + chan->norm = VIDEO_MODE_PAL; + if (sid & V4L2_STD_NTSC) + chan->norm = VIDEO_MODE_NTSC; + if (sid & V4L2_STD_SECAM) + chan->norm = VIDEO_MODE_SECAM; + } +done: + return err; +} - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - break; - } - memset(&fbuf2, 0, sizeof(fbuf2)); - - set_v4l_control(inode, file, - V4L2_CID_BRIGHTNESS, pict->brightness, drv); - set_v4l_control(inode, file, - V4L2_CID_HUE, pict->hue, drv); - set_v4l_control(inode, file, - V4L2_CID_CONTRAST, pict->contrast, drv); - set_v4l_control(inode, file, - V4L2_CID_SATURATION, pict->colour, drv); - set_v4l_control(inode, file, - V4L2_CID_WHITENESS, pict->whiteness, drv); - /* - * V4L1 uses this ioctl to set both memory capture and overlay - * pixel format, while V4L2 has two different ioctls for this. - * Some cards may not support one or the other, and may support - * different pixel formats for memory vs overlay. - */ - - fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt2); - /* If VIDIOC_G_FMT failed, then the driver likely doesn't - support memory capture. Trying to set the memory capture - parameters would be pointless. */ - if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err); - mem_err = -1000; /* didn't even try */ - } else if (fmt2->fmt.pix.pixelformat != - palette_to_pixelformat(pict->palette)) { - fmt2->fmt.pix.pixelformat = palette_to_pixelformat( - pict->palette); - mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2); - if (mem_err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", - mem_err); - } +static noinline int v4l1_compat_set_input( + struct video_channel *chan, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + v4l2_std_id sid = 0; - err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); - /* If VIDIOC_G_FBUF failed, then the driver likely doesn't - support overlay. Trying to set the overlay parameters - would be quite pointless. */ - if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err); - ovl_err = -1000; /* didn't even try */ - } else if (fbuf2.fmt.pixelformat != - palette_to_pixelformat(pict->palette)) { - fbuf2.fmt.pixelformat = palette_to_pixelformat( - pict->palette); - ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); - if (ovl_err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", - ovl_err); - } - if (ovl_err < 0 && mem_err < 0) { - /* ioctl failed, couldn't set either parameter */ - if (mem_err != -1000) - err = mem_err; - else if (ovl_err == -EPERM) - err = 0; - else - err = ovl_err; - } else - err = 0; + err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel); + if (err < 0) + dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err); + switch (chan->norm) { + case VIDEO_MODE_PAL: + sid = V4L2_STD_PAL; + break; + case VIDEO_MODE_NTSC: + sid = V4L2_STD_NTSC; + break; + case VIDEO_MODE_SECAM: + sid = V4L2_STD_SECAM; break; } - case VIDIOCGTUNER: /* get tuner information */ - { - struct video_tuner *tun = arg; - - memset(&tun2, 0, sizeof(tun2)); - err = drv(inode, file, VIDIOC_G_TUNER, &tun2); - if (err < 0) { - dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err); - break; - } - memcpy(tun->name, tun2.name, - min(sizeof(tun->name), sizeof(tun2.name))); - tun->name[sizeof(tun->name) - 1] = 0; - tun->rangelow = tun2.rangelow; - tun->rangehigh = tun2.rangehigh; - tun->flags = 0; - tun->mode = VIDEO_MODE_AUTO; - - for (i = 0; i < 64; i++) { - memset(&std2, 0, sizeof(std2)); - std2.index = i; - if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2)) - break; - if (std2.id & V4L2_STD_PAL) - tun->flags |= VIDEO_TUNER_PAL; - if (std2.id & V4L2_STD_NTSC) - tun->flags |= VIDEO_TUNER_NTSC; - if (std2.id & V4L2_STD_SECAM) - tun->flags |= VIDEO_TUNER_SECAM; - } - - err = drv(inode, file, VIDIOC_G_STD, &sid); + if (0 != sid) { + err = drv(inode, file, VIDIOC_S_STD, &sid); if (err < 0) - dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err); - if (err == 0) { - if (sid & V4L2_STD_PAL) - tun->mode = VIDEO_MODE_PAL; - if (sid & V4L2_STD_NTSC) - tun->mode = VIDEO_MODE_NTSC; - if (sid & V4L2_STD_SECAM) - tun->mode = VIDEO_MODE_SECAM; - } - - if (tun2.capability & V4L2_TUNER_CAP_LOW) - tun->flags |= VIDEO_TUNER_LOW; - if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) - tun->flags |= VIDEO_TUNER_STEREO_ON; - tun->signal = tun2.signal; - break; + dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err); } - case VIDIOCSTUNER: /* select a tuner input */ - { - struct video_tuner *tun = arg; - struct v4l2_tuner t; - memset(&t, 0, sizeof(t)); - - t.index = tun->tuner; + return err; +} - err = drv(inode, file, VIDIOC_S_INPUT, &t); - if (err < 0) - dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err); +static noinline int v4l1_compat_get_picture( + struct video_picture *pict, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_format *fmt; - break; + fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); + if (!fmt) { + err = -ENOMEM; + return err; } - case VIDIOCGFREQ: /* get frequency */ - { - unsigned long *freq = arg; - memset(&freq2, 0, sizeof(freq2)); - freq2.tuner = 0; - err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); - if (err < 0) - dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err); - if (0 == err) - *freq = freq2.frequency; - break; + pict->brightness = get_v4l_control(inode, file, + V4L2_CID_BRIGHTNESS, drv); + pict->hue = get_v4l_control(inode, file, + V4L2_CID_HUE, drv); + pict->contrast = get_v4l_control(inode, file, + V4L2_CID_CONTRAST, drv); + pict->colour = get_v4l_control(inode, file, + V4L2_CID_SATURATION, drv); + pict->whiteness = get_v4l_control(inode, file, + V4L2_CID_WHITENESS, drv); + + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + err = drv(inode, file, VIDIOC_G_FMT, fmt); + if (err < 0) { + dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err); + goto done; } - case VIDIOCSFREQ: /* set frequency */ - { - unsigned long *freq = arg; - memset(&freq2, 0, sizeof(freq2)); - drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); - freq2.frequency = *freq; - err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); - if (err < 0) - dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err); - break; + pict->depth = ((fmt->fmt.pix.bytesperline << 3) + + (fmt->fmt.pix.width - 1)) + / fmt->fmt.pix.width; + pict->palette = pixelformat_to_palette( + fmt->fmt.pix.pixelformat); +done: + kfree(fmt); + return err; +} + +static noinline int v4l1_compat_set_picture( + struct video_picture *pict, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_framebuffer fbuf; + int mem_err = 0, ovl_err = 0; + struct v4l2_format *fmt; + + fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); + if (!fmt) { + err = -ENOMEM; + return err; + } + memset(&fbuf, 0, sizeof(fbuf)); + + set_v4l_control(inode, file, + V4L2_CID_BRIGHTNESS, pict->brightness, drv); + set_v4l_control(inode, file, + V4L2_CID_HUE, pict->hue, drv); + set_v4l_control(inode, file, + V4L2_CID_CONTRAST, pict->contrast, drv); + set_v4l_control(inode, file, + V4L2_CID_SATURATION, pict->colour, drv); + set_v4l_control(inode, file, + V4L2_CID_WHITENESS, pict->whiteness, drv); + /* + * V4L1 uses this ioctl to set both memory capture and overlay + * pixel format, while V4L2 has two different ioctls for this. + * Some cards may not support one or the other, and may support + * different pixel formats for memory vs overlay. + */ + + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + err = drv(inode, file, VIDIOC_G_FMT, fmt); + /* If VIDIOC_G_FMT failed, then the driver likely doesn't + support memory capture. Trying to set the memory capture + parameters would be pointless. */ + if (err < 0) { + dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err); + mem_err = -1000; /* didn't even try */ + } else if (fmt->fmt.pix.pixelformat != + palette_to_pixelformat(pict->palette)) { + fmt->fmt.pix.pixelformat = palette_to_pixelformat( + pict->palette); + mem_err = drv(inode, file, VIDIOC_S_FMT, fmt); + if (mem_err < 0) + dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", + mem_err); } - case VIDIOCGAUDIO: /* get audio properties/controls */ - { - struct video_audio *aud = arg; - memset(&aud2, 0, sizeof(aud2)); - err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); - if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err); - break; - } - memcpy(aud->name, aud2.name, - min(sizeof(aud->name), sizeof(aud2.name))); - aud->name[sizeof(aud->name) - 1] = 0; - aud->audio = aud2.index; - aud->flags = 0; - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv); - if (i >= 0) { - aud->volume = i; - aud->flags |= VIDEO_AUDIO_VOLUME; - } - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv); - if (i >= 0) { - aud->bass = i; - aud->flags |= VIDEO_AUDIO_BASS; - } - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv); - if (i >= 0) { - aud->treble = i; - aud->flags |= VIDEO_AUDIO_TREBLE; - } - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv); - if (i >= 0) { - aud->balance = i; - aud->flags |= VIDEO_AUDIO_BALANCE; - } - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv); - if (i >= 0) { - if (i) - aud->flags |= VIDEO_AUDIO_MUTE; - aud->flags |= VIDEO_AUDIO_MUTABLE; - } - aud->step = 1; - qctrl2.id = V4L2_CID_AUDIO_VOLUME; - if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && - !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) - aud->step = qctrl2.step; - aud->mode = 0; - - memset(&tun2, 0, sizeof(tun2)); - err = drv(inode, file, VIDIOC_G_TUNER, &tun2); - if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err); + err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); + /* If VIDIOC_G_FBUF failed, then the driver likely doesn't + support overlay. Trying to set the overlay parameters + would be quite pointless. */ + if (err < 0) { + dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err); + ovl_err = -1000; /* didn't even try */ + } else if (fbuf.fmt.pixelformat != + palette_to_pixelformat(pict->palette)) { + fbuf.fmt.pixelformat = palette_to_pixelformat( + pict->palette); + ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf); + if (ovl_err < 0) + dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", + ovl_err); + } + if (ovl_err < 0 && mem_err < 0) { + /* ioctl failed, couldn't set either parameter */ + if (mem_err != -1000) + err = mem_err; + else if (ovl_err == -EPERM) err = 0; + else + err = ovl_err; + } else + err = 0; + kfree(fmt); + return err; +} + +static noinline int v4l1_compat_get_tuner( + struct video_tuner *tun, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err, i; + struct v4l2_tuner tun2; + struct v4l2_standard std2; + v4l2_std_id sid; + + memset(&tun2, 0, sizeof(tun2)); + err = drv(inode, file, VIDIOC_G_TUNER, &tun2); + if (err < 0) { + dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err); + goto done; + } + memcpy(tun->name, tun2.name, + min(sizeof(tun->name), sizeof(tun2.name))); + tun->name[sizeof(tun->name) - 1] = 0; + tun->rangelow = tun2.rangelow; + tun->rangehigh = tun2.rangehigh; + tun->flags = 0; + tun->mode = VIDEO_MODE_AUTO; + + for (i = 0; i < 64; i++) { + memset(&std2, 0, sizeof(std2)); + std2.index = i; + if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2)) break; - } + if (std2.id & V4L2_STD_PAL) + tun->flags |= VIDEO_TUNER_PAL; + if (std2.id & V4L2_STD_NTSC) + tun->flags |= VIDEO_TUNER_NTSC; + if (std2.id & V4L2_STD_SECAM) + tun->flags |= VIDEO_TUNER_SECAM; + } - if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) - aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) - aud->mode = VIDEO_SOUND_STEREO; - else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO) - aud->mode = VIDEO_SOUND_MONO; - break; + err = drv(inode, file, VIDIOC_G_STD, &sid); + if (err < 0) + dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err); + if (err == 0) { + if (sid & V4L2_STD_PAL) + tun->mode = VIDEO_MODE_PAL; + if (sid & V4L2_STD_NTSC) + tun->mode = VIDEO_MODE_NTSC; + if (sid & V4L2_STD_SECAM) + tun->mode = VIDEO_MODE_SECAM; } - case VIDIOCSAUDIO: /* set audio controls */ - { - struct video_audio *aud = arg; - memset(&aud2, 0, sizeof(aud2)); - memset(&tun2, 0, sizeof(tun2)); + if (tun2.capability & V4L2_TUNER_CAP_LOW) + tun->flags |= VIDEO_TUNER_LOW; + if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) + tun->flags |= VIDEO_TUNER_STEREO_ON; + tun->signal = tun2.signal; +done: + return err; +} - aud2.index = aud->audio; - err = drv(inode, file, VIDIOC_S_AUDIO, &aud2); - if (err < 0) { - dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err); - break; - } +static noinline int v4l1_compat_select_tuner( + struct video_tuner *tun, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_tuner t;/*84 bytes on x86_64*/ + memset(&t, 0, sizeof(t)); - set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, - aud->volume, drv); - set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, - aud->bass, drv); - set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, - aud->treble, drv); - set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, - aud->balance, drv); - set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, - !!(aud->flags & VIDEO_AUDIO_MUTE), drv); - - err = drv(inode, file, VIDIOC_G_TUNER, &tun2); - if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err); - if (err == 0) { - switch (aud->mode) { - default: - case VIDEO_SOUND_MONO: - case VIDEO_SOUND_LANG1: - tun2.audmode = V4L2_TUNER_MODE_MONO; - break; - case VIDEO_SOUND_STEREO: - tun2.audmode = V4L2_TUNER_MODE_STEREO; - break; - case VIDEO_SOUND_LANG2: - tun2.audmode = V4L2_TUNER_MODE_LANG2; - break; - } - err = drv(inode, file, VIDIOC_S_TUNER, &tun2); - if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err); - } + t.index = tun->tuner; + + err = drv(inode, file, VIDIOC_S_INPUT, &t); + if (err < 0) + dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err); + return err; +} + +static noinline int v4l1_compat_get_frequency( + unsigned long *freq, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_frequency freq2; + memset(&freq2, 0, sizeof(freq2)); + + freq2.tuner = 0; + err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); + if (err < 0) + dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err); + if (0 == err) + *freq = freq2.frequency; + return err; +} + +static noinline int v4l1_compat_set_frequency( + unsigned long *freq, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_frequency freq2; + memset(&freq2, 0, sizeof(freq2)); + + drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); + freq2.frequency = *freq; + err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); + if (err < 0) + dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err); + return err; +} + +static noinline int v4l1_compat_get_audio( + struct video_audio *aud, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err, i; + struct v4l2_queryctrl qctrl2; + struct v4l2_audio aud2; + struct v4l2_tuner tun2; + memset(&aud2, 0, sizeof(aud2)); + + err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); + if (err < 0) { + dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err); + goto done; + } + memcpy(aud->name, aud2.name, + min(sizeof(aud->name), sizeof(aud2.name))); + aud->name[sizeof(aud->name) - 1] = 0; + aud->audio = aud2.index; + aud->flags = 0; + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv); + if (i >= 0) { + aud->volume = i; + aud->flags |= VIDEO_AUDIO_VOLUME; + } + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv); + if (i >= 0) { + aud->bass = i; + aud->flags |= VIDEO_AUDIO_BASS; + } + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv); + if (i >= 0) { + aud->treble = i; + aud->flags |= VIDEO_AUDIO_TREBLE; + } + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv); + if (i >= 0) { + aud->balance = i; + aud->flags |= VIDEO_AUDIO_BALANCE; + } + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv); + if (i >= 0) { + if (i) + aud->flags |= VIDEO_AUDIO_MUTE; + aud->flags |= VIDEO_AUDIO_MUTABLE; + } + aud->step = 1; + qctrl2.id = V4L2_CID_AUDIO_VOLUME; + if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && + !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) + aud->step = qctrl2.step; + aud->mode = 0; + + memset(&tun2, 0, sizeof(tun2)); + err = drv(inode, file, VIDIOC_G_TUNER, &tun2); + if (err < 0) { + dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err); err = 0; - break; + goto done; } - case VIDIOCMCAPTURE: /* capture a frame */ - { - struct video_mmap *mm = arg; - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - break; - } - memset(&buf2, 0, sizeof(buf2)); + if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) + aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) + aud->mode = VIDEO_SOUND_STEREO; + else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO) + aud->mode = VIDEO_SOUND_MONO; +done: + return err; +} - fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err); +static noinline int v4l1_compat_set_audio( + struct video_audio *aud, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_audio aud2; + struct v4l2_tuner tun2; + + memset(&aud2, 0, sizeof(aud2)); + memset(&tun2, 0, sizeof(tun2)); + + aud2.index = aud->audio; + err = drv(inode, file, VIDIOC_S_AUDIO, &aud2); + if (err < 0) { + dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err); + goto done; + } + + set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, + aud->volume, drv); + set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, + aud->bass, drv); + set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, + aud->treble, drv); + set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, + aud->balance, drv); + set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, + !!(aud->flags & VIDEO_AUDIO_MUTE), drv); + + err = drv(inode, file, VIDIOC_G_TUNER, &tun2); + if (err < 0) + dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err); + if (err == 0) { + switch (aud->mode) { + default: + case VIDEO_SOUND_MONO: + case VIDEO_SOUND_LANG1: + tun2.audmode = V4L2_TUNER_MODE_MONO; break; - } - if (mm->width != fmt2->fmt.pix.width || - mm->height != fmt2->fmt.pix.height || - palette_to_pixelformat(mm->format) != - fmt2->fmt.pix.pixelformat) { - /* New capture format... */ - fmt2->fmt.pix.width = mm->width; - fmt2->fmt.pix.height = mm->height; - fmt2->fmt.pix.pixelformat = - palette_to_pixelformat(mm->format); - fmt2->fmt.pix.field = V4L2_FIELD_ANY; - fmt2->fmt.pix.bytesperline = 0; - err = drv(inode, file, VIDIOC_S_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err); - break; - } - } - buf2.index = mm->frame; - buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err); + case VIDEO_SOUND_STEREO: + tun2.audmode = V4L2_TUNER_MODE_STEREO; break; - } - err = drv(inode, file, VIDIOC_QBUF, &buf2); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err); + case VIDEO_SOUND_LANG2: + tun2.audmode = V4L2_TUNER_MODE_LANG2; break; } - err = drv(inode, file, VIDIOC_STREAMON, &captype); + err = drv(inode, file, VIDIOC_S_TUNER, &tun2); if (err < 0) - dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err); - break; + dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err); } - case VIDIOCSYNC: /* wait for a frame */ - { - int *i = arg; + err = 0; +done: + return err; +} - memset(&buf2, 0, sizeof(buf2)); - buf2.index = *i; - buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); - if (err < 0) { - /* No such buffer */ - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); - break; - } - if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) { - /* Buffer is not mapped */ - err = -EINVAL; - break; - } +static noinline int v4l1_compat_capture_frame( + struct video_mmap *mm, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; + struct v4l2_buffer buf; + struct v4l2_format *fmt; - /* make sure capture actually runs so we don't block forever */ - err = drv(inode, file, VIDIOC_STREAMON, &captype); + fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); + if (!fmt) { + err = -ENOMEM; + return err; + } + memset(&buf, 0, sizeof(buf)); + + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + err = drv(inode, file, VIDIOC_G_FMT, fmt); + if (err < 0) { + dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err); + goto done; + } + if (mm->width != fmt->fmt.pix.width || + mm->height != fmt->fmt.pix.height || + palette_to_pixelformat(mm->format) != + fmt->fmt.pix.pixelformat) { + /* New capture format... */ + fmt->fmt.pix.width = mm->width; + fmt->fmt.pix.height = mm->height; + fmt->fmt.pix.pixelformat = + palette_to_pixelformat(mm->format); + fmt->fmt.pix.field = V4L2_FIELD_ANY; + fmt->fmt.pix.bytesperline = 0; + err = drv(inode, file, VIDIOC_S_FMT, fmt); if (err < 0) { - dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err); - break; + dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err); + goto done; } + } + buf.index = mm->frame; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + err = drv(inode, file, VIDIOC_QUERYBUF, &buf); + if (err < 0) { + dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err); + goto done; + } + err = drv(inode, file, VIDIOC_QBUF, &buf); + if (err < 0) { + dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err); + goto done; + } + err = drv(inode, file, VIDIOC_STREAMON, &captype); + if (err < 0) + dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err); +done: + kfree(fmt); + return err; +} - /* Loop as long as the buffer is queued, but not done */ - while ((buf2.flags & - (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) - == V4L2_BUF_FLAG_QUEUED) { - err = poll_one(file); - if (err < 0 || /* error or sleep was interrupted */ - err == 0) /* timeout? Shouldn't occur. */ - break; - err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); - if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); - } - if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */ - break; - do { - err = drv(inode, file, VIDIOC_DQBUF, &buf2); - if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err); - } while (err == 0 && buf2.index != *i); - break; +static noinline int v4l1_compat_sync( + int *i, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; + struct v4l2_buffer buf; + + memset(&buf, 0, sizeof(buf)); + buf.index = *i; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + err = drv(inode, file, VIDIOC_QUERYBUF, &buf); + if (err < 0) { + /* No such buffer */ + dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); + goto done; + } + if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) { + /* Buffer is not mapped */ + err = -EINVAL; + goto done; } - case VIDIOCGVBIFMT: /* query VBI data capture format */ - { - struct vbi_format *fmt = arg; + /* make sure capture actually runs so we don't block forever */ + err = drv(inode, file, VIDIOC_STREAMON, &captype); + if (err < 0) { + dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err); + goto done; + } - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; + /* Loop as long as the buffer is queued, but not done */ + while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) + == V4L2_BUF_FLAG_QUEUED) { + err = poll_one(file); + if (err < 0 || /* error or sleep was interrupted */ + err == 0) /* timeout? Shouldn't occur. */ break; - } - fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; + err = drv(inode, file, VIDIOC_QUERYBUF, &buf); + if (err < 0) + dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); + } + if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */ + goto done; + do { + err = drv(inode, file, VIDIOC_DQBUF, &buf); + if (err < 0) + dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err); + } while (err == 0 && buf.index != *i); +done: + return err; +} - err = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); - break; - } - if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { - err = -EINVAL; - break; - } - memset(fmt, 0, sizeof(*fmt)); - fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; - fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; - fmt->sample_format = VIDEO_PALETTE_RAW; - fmt->start[0] = fmt2->fmt.vbi.start[0]; - fmt->count[0] = fmt2->fmt.vbi.count[0]; - fmt->start[1] = fmt2->fmt.vbi.start[1]; - fmt->count[1] = fmt2->fmt.vbi.count[1]; - fmt->flags = fmt2->fmt.vbi.flags & 0x03; - break; +static noinline int v4l1_compat_get_vbi_format( + struct vbi_format *fmt, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_format *fmt2; + + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + return err; } - case VIDIOCSVBIFMT: - { - struct vbi_format *fmt = arg; + fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - if (VIDEO_PALETTE_RAW != fmt->sample_format) { - err = -EINVAL; - break; - } + err = drv(inode, file, VIDIOC_G_FMT, fmt2); + if (err < 0) { + dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); + goto done; + } + if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { + err = -EINVAL; + goto done; + } + memset(fmt, 0, sizeof(*fmt)); + fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; + fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; + fmt->sample_format = VIDEO_PALETTE_RAW; + fmt->start[0] = fmt2->fmt.vbi.start[0]; + fmt->count[0] = fmt2->fmt.vbi.count[0]; + fmt->start[1] = fmt2->fmt.vbi.start[1]; + fmt->count[1] = fmt2->fmt.vbi.count[1]; + fmt->flags = fmt2->fmt.vbi.flags & 0x03; +done: + kfree(fmt2); + return err; +} - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - break; - } - fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; - fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; - fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - fmt2->fmt.vbi.start[0] = fmt->start[0]; - fmt2->fmt.vbi.count[0] = fmt->count[0]; - fmt2->fmt.vbi.start[1] = fmt->start[1]; - fmt2->fmt.vbi.count[1] = fmt->count[1]; - fmt2->fmt.vbi.flags = fmt->flags; - err = drv(inode, file, VIDIOC_TRY_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err); - break; - } +static noinline int v4l1_compat_set_vbi_format( + struct vbi_format *fmt, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + int err; + struct v4l2_format *fmt2 = NULL; - if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || - fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || - fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY || - fmt2->fmt.vbi.start[0] != fmt->start[0] || - fmt2->fmt.vbi.count[0] != fmt->count[0] || - fmt2->fmt.vbi.start[1] != fmt->start[1] || - fmt2->fmt.vbi.count[1] != fmt->count[1] || - fmt2->fmt.vbi.flags != fmt->flags) { - err = -EINVAL; - break; - } - err = drv(inode, file, VIDIOC_S_FMT, fmt2); - if (err < 0) - dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err); - break; + if (VIDEO_PALETTE_RAW != fmt->sample_format) { + err = -EINVAL; + return err; + } + + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + return err; } + fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; + fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; + fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; + fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; + fmt2->fmt.vbi.start[0] = fmt->start[0]; + fmt2->fmt.vbi.count[0] = fmt->count[0]; + fmt2->fmt.vbi.start[1] = fmt->start[1]; + fmt2->fmt.vbi.count[1] = fmt->count[1]; + fmt2->fmt.vbi.flags = fmt->flags; + err = drv(inode, file, VIDIOC_TRY_FMT, fmt2); + if (err < 0) { + dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err); + goto done; + } + + if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || + fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || + fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY || + fmt2->fmt.vbi.start[0] != fmt->start[0] || + fmt2->fmt.vbi.count[0] != fmt->count[0] || + fmt2->fmt.vbi.start[1] != fmt->start[1] || + fmt2->fmt.vbi.count[1] != fmt->count[1] || + fmt2->fmt.vbi.flags != fmt->flags) { + err = -EINVAL; + goto done; + } + err = drv(inode, file, VIDIOC_S_FMT, fmt2); + if (err < 0) + dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err); +done: + kfree(fmt2); + return err; +} + +/* + * This function is exported. + */ +int +v4l_compat_translate_ioctl(struct inode *inode, + struct file *file, + int cmd, + void *arg, + v4l2_kioctl drv) +{ + int err; + switch (cmd) { + case VIDIOCGCAP: /* capability */ + err = v4l1_compat_get_capabilities(arg, inode, file, drv); + break; + case VIDIOCGFBUF: /* get frame buffer */ + err = v4l1_compat_get_frame_buffer(arg, inode, file, drv); + break; + case VIDIOCSFBUF: /* set frame buffer */ + err = v4l1_compat_set_frame_buffer(arg, inode, file, drv); + break; + case VIDIOCGWIN: /* get window or capture dimensions */ + err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv); + break; + case VIDIOCSWIN: /* set window and/or capture dimensions */ + err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv); + break; + case VIDIOCCAPTURE: /* turn on/off preview */ + err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv); + break; + case VIDIOCGCHAN: /* get input information */ + err = v4l1_compat_get_input_info(arg, inode, file, drv); + break; + case VIDIOCSCHAN: /* set input */ + err = v4l1_compat_set_input(arg, inode, file, drv); + break; + case VIDIOCGPICT: /* get tone controls & partial capture format */ + err = v4l1_compat_get_picture(arg, inode, file, drv); + break; + case VIDIOCSPICT: /* set tone controls & partial capture format */ + err = v4l1_compat_set_picture(arg, inode, file, drv); + break; + case VIDIOCGTUNER: /* get tuner information */ + err = v4l1_compat_get_tuner(arg, inode, file, drv); + break; + case VIDIOCSTUNER: /* select a tuner input */ + err = v4l1_compat_select_tuner(arg, inode, file, drv); + break; + case VIDIOCGFREQ: /* get frequency */ + err = v4l1_compat_get_frequency(arg, inode, file, drv); + break; + case VIDIOCSFREQ: /* set frequency */ + err = v4l1_compat_set_frequency(arg, inode, file, drv); + break; + case VIDIOCGAUDIO: /* get audio properties/controls */ + err = v4l1_compat_get_audio(arg, inode, file, drv); + break; + case VIDIOCSAUDIO: /* set audio controls */ + err = v4l1_compat_set_audio(arg, inode, file, drv); + break; + case VIDIOCMCAPTURE: /* capture a frame */ + err = v4l1_compat_capture_frame(arg, inode, file, drv); + break; + case VIDIOCSYNC: /* wait for a frame */ + err = v4l1_compat_sync(arg, inode, file, drv); + break; + case VIDIOCGVBIFMT: /* query VBI data capture format */ + err = v4l1_compat_get_vbi_format(arg, inode, file, drv); + break; + case VIDIOCSVBIFMT: + err = v4l1_compat_set_vbi_format(arg, inode, file, drv); + break; default: err = -ENOIOCTLCMD; break; } - kfree(cap2); - kfree(fmt2); return err; } EXPORT_SYMBOL(v4l_compat_translate_ioctl); -- cgit v1.2.3 From 868f44e1a5c2e272dab804acf3f1fa98c7be7f0c Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Wed, 2 Apr 2008 14:28:03 -0300 Subject: V4L/DVB (7365): reduce stack usage of v4l1_compat_sync poll_one allocated on stack struct poll_wqueues which is pretty big structure (>500 bytes on x86_64). v4l1_compat_sync invokes poll_one in a loop, so allocate struct poll_wqueues in v4l1_compat_sync (with kmalloc) and pass it to poll_one. Signed-off-by: Marcin Slusarz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l1-compat.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index e42cea987964..a0f6c60279ec 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -199,14 +199,13 @@ pixelformat_to_palette(unsigned int pixelformat) /* ----------------------------------------------------------------- */ -static int poll_one(struct file *file) +static int poll_one(struct file *file, struct poll_wqueues *pwq) { int retval = 1; poll_table *table; - struct poll_wqueues pwq; /*TODO: allocate dynamically*/ - poll_initwait(&pwq); - table = &pwq.pt; + poll_initwait(pwq); + table = &pwq->pt; for (;;) { int mask; set_current_state(TASK_INTERRUPTIBLE); @@ -221,7 +220,7 @@ static int poll_one(struct file *file) schedule(); } set_current_state(TASK_RUNNING); - poll_freewait(&pwq); + poll_freewait(pwq); return retval; } @@ -1068,6 +1067,7 @@ static noinline int v4l1_compat_sync( int err; enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; struct v4l2_buffer buf; + struct poll_wqueues *pwq; memset(&buf, 0, sizeof(buf)); buf.index = *i; @@ -1091,10 +1091,11 @@ static noinline int v4l1_compat_sync( goto done; } + pwq = kmalloc(sizeof(*pwq), GFP_KERNEL); /* Loop as long as the buffer is queued, but not done */ while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) == V4L2_BUF_FLAG_QUEUED) { - err = poll_one(file); + err = poll_one(file, pwq); if (err < 0 || /* error or sleep was interrupted */ err == 0) /* timeout? Shouldn't occur. */ break; @@ -1102,6 +1103,7 @@ static noinline int v4l1_compat_sync( if (err < 0) dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); } + kfree(pwq); if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */ goto done; do { -- cgit v1.2.3 From efaf24fd6b1e177b0daf2dd775d9514644fb5f1a Mon Sep 17 00:00:00 2001 From: Ernesto Hernández-Novich Date: Wed, 2 Apr 2008 14:28:04 -0300 Subject: V4L/DVB (7366): Support for a 16-channel bt878 card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have what looks like a Geovision GV-600 (or 650) card. It has a large chip in the middle labeled CONEXANT FUSION 878A 25878-13 E345881.1 0312 TAIWAN It has an audio connector coming out from a chip labeled ATMEL 0242 AT89C2051-24PI It is identified as follows on my Debian GNU/Linux Etch (kernel 2.6.18) ... 01:0a.0 Multimedia video controller: Brooktree Corporation Bt878 Video Capture (rev 11) 01:0a.1 Multimedia controller: Brooktree Corporation Bt878 Audio Capture (rev 11) ... 01:0a.0 0400: 109e:036e (rev 11) Subsystem: 008a:763c Flags: bus master, medium devsel, latency 64, IRQ 58 Memory at dfffe000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 01:0a.1 0480: 109e:0878 (rev 11) Subsystem: 008a:763c Flags: bus master, medium devsel, latency 64, IRQ 58 Memory at dffff000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 It was being detected as a GENERIC UNKNOWN CARD both by the 2.6.18 kernel and the latest v4l-dvb drivers, but it did not work at all. The card has sixteen (16) BNC video inputs, four of them on the board itself and twelve on three daughter-cards. It has a single bt878 chip, no tuner and what looks like and audio input. After doing some research I managed to get only eight channels working by forcing card=125 and those DID NOT match channels 0-7 on the card, and no audio. Based on what was working for card=125, I added the card definition block, added a specific muxsel routine and got the card working fully with xawtv, where the sixteen channels show up as Composite0 to Composite15, matching the channel labels in the card and daughter-cards. I have made no efforts yet to get audio working, but would appreciate any pointers. Signed-off-by: Ernesto Hernández-Novich Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/bt8xx/bttv-cards.c | 28 ++++++++++++++++++++++++++++ drivers/media/video/bt8xx/bttv.h | 1 + 3 files changed, 30 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index d97cf7cc6088..17911d038765 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -148,3 +148,4 @@ 147 -> VoodooTV 200 (USA) [121a:3000] 148 -> DViCO FusionHDTV 2 [dbc0:d200] 149 -> Typhoon TV-Tuner PCI (50684) +150 -> Geovision GV-600 [008a:763c] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index b963bde97412..417dd552dba9 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -71,6 +71,8 @@ static void kodicom4400r_init(struct bttv *btv); static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input); static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input); +static void geovision_muxsel(struct bttv *btv, unsigned int input); + static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); static int tea5757_write(struct bttv *btv, int value); @@ -301,6 +303,7 @@ static struct CARD { { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, + { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, { 0, -1, NULL } }; @@ -2994,6 +2997,24 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, + [BTTV_BOARD_GEOVISION_GV600] = { + /* emhn@usb.ve */ + .name = "Geovision GV-600", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = UNSET, + .svhs = UNSET, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2 }, + .muxsel_hook = geovision_muxsel, + .gpiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -3333,6 +3354,13 @@ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input) gpio_bits( 3<<9, inmux<<9 ); } +static void geovision_muxsel(struct bttv *btv, unsigned int input) +{ + unsigned int inmux = input % 16; + gpio_inout(0xf, 0xf); + gpio_bits(0xf, inmux); +} + /* ----------------------------------------------------------------------- */ static void bttv_reset_audio(struct bttv *btv) diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index bf4c339a520c..ed0cd3b1a01e 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -173,6 +173,7 @@ #define BTTV_BOARD_VOODOOTV_200 0x93 #define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94 #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 +#define BTTV_BOARD_GEOVISION_GV600 0x96 /* more card-specific defines */ -- cgit v1.2.3 From afe80868f30737b42c084a5a54bbbb36850949a5 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Wed, 2 Apr 2008 14:28:04 -0300 Subject: V4L/DVB (7368): bttv: added support for Kozumi KTV-01C card Signed-off-by: Mauro Lacy Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/common/ir-keymaps.c | 8 +++++++- drivers/media/video/bt8xx/bttv-cards.c | 23 +++++++++++++++++++++++ drivers/media/video/bt8xx/bttv-input.c | 6 ++++++ drivers/media/video/bt8xx/bttv.h | 1 + 5 files changed, 38 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 17911d038765..f32efb6fb12c 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -149,3 +149,4 @@ 148 -> DViCO FusionHDTV 2 [dbc0:d200] 149 -> Typhoon TV-Tuner PCI (50684) 150 -> Geovision GV-600 [008a:763c] +151 -> Kozumi KTV-01C diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 2ab5a120470d..107565c47274 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -1157,7 +1157,8 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv); /* Mapping for the 28 key remote control as seen at http://www.sednacomputer.com/photo/cardbus-tv.jpg - Pavel Mihaylov */ + Pavel Mihaylov + Also for the remote bundled with Kozumi KTV-01C card */ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [ 0x00 ] = KEY_0, [ 0x01 ] = KEY_1, @@ -1188,6 +1189,11 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [ 0x1c ] = KEY_RADIO, /* FM Radio */ [ 0x1d ] = KEY_RECORD, [ 0x1e ] = KEY_PAUSE, + /* additional codes for Kozumi's remote */ + [0x14] = KEY_INFO, /* OSD */ + [0x16] = KEY_OK, /* OK */ + [0x17] = KEY_DIGITS, /* Plus */ + [0x1f] = KEY_PLAY, /* Play */ }; EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 417dd552dba9..22c2708e42ab 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -3015,6 +3015,29 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, + [BTTV_BOARD_KOZUMI_KTV_01C] = { + /* Mauro Lacy + * Based on MagicTV and Conceptronic CONTVFMi */ + + .name = "Kozumi KTV-01C", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x008007, + .muxsel = { 2, 3, 1, 1 }, + .gpiomux = { 0, 1, 2, 2 }, /* CONTVFMi */ + /*gpiomux = { 0, 1, 2, 3 }, /* MagicTV */ + .gpiomute = 3, /* CONTVFMi */ + /*gpiomute = 4, /* MagicTV */ + .needs_tvaudio = 0, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */ + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + .has_remote = 1, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index fc9ecb21eec6..a38af98f4cae 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -278,6 +278,12 @@ int bttv_input_init(struct bttv *btv) ir->mask_keyup = 0x004000; ir->polling = 50; /* ms */ break; + case BTTV_BOARD_KOZUMI_KTV_01C: + ir_codes = ir_codes_pctv_sedna; + ir->mask_keycode = 0x001f00; + ir->mask_keyup = 0x006000; + ir->polling = 50; /* ms */ + break; } if (NULL == ir_codes) { dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index ed0cd3b1a01e..0c859d949c78 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -174,6 +174,7 @@ #define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94 #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 #define BTTV_BOARD_GEOVISION_GV600 0x96 +#define BTTV_BOARD_KOZUMI_KTV_01C 0x97 /* more card-specific defines */ -- cgit v1.2.3 From f151af2b6d864a2fed88c03919b350a4b909f0c1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 2 Apr 2008 14:28:05 -0300 Subject: V4L/DVB (7369): drivers/media/video/soc_camera.c: reads return size_t Signed-off-by: Andrew Morton CC: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index bd8677cb1cab..91e1ab36fe5d 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -269,7 +269,7 @@ static int soc_camera_close(struct inode *inode, struct file *file) return 0; } -static int soc_camera_read(struct file *file, char __user *buf, +static ssize_t soc_camera_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct soc_camera_file *icf = file->private_data; -- cgit v1.2.3 From 876b2feb04a673ec20d06c8b5748ceb99de1d31b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:05 -0300 Subject: V4L/DVB (7370): Add basic support for Prolink Pixelview MPEG 8000GT TV reception ok. S-video and Composite not tested. Audio not tested. IR not implemented yet. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 70 +++++++++++++++++++++++++++++++-- drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 68 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index da7f70dfad2a..a01991dcb317 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -64,3 +64,4 @@ 63 -> Geniatech X8000-MT DVBT [14f1:8852] 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] + 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 4c1e876a9232..98d3475a4b32 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1591,6 +1591,29 @@ static const struct cx88_board cx88_boards[] = { .gpio0 = 0x16d9, }}, }, + [CX88_BOARD_PROLINK_PV_8000GT] = { + .name = "Prolink Pixelview MPEG 8000GT", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0ff, + .gpio2 = 0x0cfb, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio2 = 0x0cfb, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio2 = 0x0cfb, + } }, + .radio = { + .type = CX88_RADIO, + .gpio2 = 0x0cfb, + }, + }, }; /* ------------------------------------------------------------------ */ @@ -1928,11 +1951,15 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x14f1, .subdevice = 0x8852, .card = CX88_BOARD_GENIATECH_X8000_MT, - },{ + }, { .subvendor = 0x18ac, .subdevice = 0xd610, .card = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD, - } + }, { + .subvendor = 0x1554, + .subdevice = 0x4935, + .card = CX88_BOARD_PROLINK_PV_8000GT, + }, }; /* ----------------------------------------------------------------------- */ @@ -2063,9 +2090,10 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) /* ------------------------------------------------------------------- */ /* some Divco specific stuff */ -static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg) +static int cx88_dvico_xc2028_callback(void *priv, int command, int arg) { - struct cx88_core *core = ptr; + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; switch (command) { case XC2028_TUNER_RESET: @@ -2113,6 +2141,28 @@ static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mod return -EINVAL; } +/* ------------------------------------------------------------------- */ +/* some Divco specific stuff */ +static int cx88_pv_8000gt_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + switch (command) { + case XC2028_TUNER_RESET: + cx_write(MO_GP2_IO, 0xcf7); + mdelay(50); + cx_write(MO_GP2_IO, 0xef5); + mdelay(50); + cx_write(MO_GP2_IO, 0xcf7); + break; + default: + return -EINVAL; + } + + return 0; +} + /* ----------------------------------------------------------------------- */ /* some DViCO specific stuff */ @@ -2159,6 +2209,8 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: return cx88_xc3028_geniatech_tuner_callback(priv, command, arg); + case CX88_BOARD_PROLINK_PV_8000GT: + return cx88_pv_8000gt_callback(priv, command, arg); case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: return cx88_dvico_xc2028_callback(priv, command, arg); } @@ -2291,6 +2343,16 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ udelay(1000); break; + + case CX88_BOARD_PROLINK_PV_8000GT: + cx_write(MO_GP2_IO, 0xcf7); + mdelay(50); + cx_write(MO_GP2_IO, 0xef5); + mdelay(50); + cx_write(MO_GP2_IO, 0xcf7); + msleep(10); + break; + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: /* Enable the xc5000 tuner */ cx_set(MO_GP0_IO, 0x00001010); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 85a95a0a94d9..c0f4912793e9 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -218,6 +218,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_GENIATECH_X8000_MT 63 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 +#define CX88_BOARD_PROLINK_PV_8000GT 66 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 8bd22464184ad8d86f053ca3b3dd53b970c796e5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:05 -0300 Subject: V4L/DVB (7371): cx88: Fix audio on Prolink Pixelview Mpeg 8000GT This board works only with non-mts firmware Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 98d3475a4b32..603b3664381a 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2495,6 +2495,11 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: ctl.demod = XC3028_FE_OREN538; break; + case CX88_BOARD_PROLINK_PV_8000GT: + /* + * This board uses non-MTS firmware + */ + break; default: ctl.demod = XC3028_FE_OREN538; ctl.mts = 1; -- cgit v1.2.3 From 09dc15a2c0a8c3b7f4c5e8a8f319dadc533289a1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:05 -0300 Subject: V4L/DVB (7372): cx88: Add IR support for Pixelview MPEG 8000GT Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 45 +++++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88-input.c | 7 ++++++ include/media/ir-common.h | 1 + 3 files changed, 53 insertions(+) (limited to 'drivers') diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 107565c47274..35793185630b 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -212,6 +212,51 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_pixelview); +/* + Mauro Carvalho Chehab + present on PV MPEG 8000GT + */ +IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { + [0x3c] = KEY_PAUSE, /* Timeshift */ + [0x12] = KEY_POWER, + + [0x3d] = KEY_1, + [0x38] = KEY_2, + [0x18] = KEY_3, + [0x35] = KEY_4, + [0x39] = KEY_5, + [0x15] = KEY_6, + [0x36] = KEY_7, + [0x3a] = KEY_8, + [0x1e] = KEY_9, + [0x3e] = KEY_0, + + [0x1c] = KEY_AGAIN, /* LOOP */ + [0x3f] = KEY_MEDIA, /* Source */ + [0x1f] = KEY_LAST, /* +100 */ + [0x1b] = KEY_MUTE, + + [0x17] = KEY_CHANNELDOWN, + [0x16] = KEY_CHANNELUP, + [0x10] = KEY_VOLUMEUP, + [0x14] = KEY_VOLUMEDOWN, + [0x13] = KEY_ZOOM, + + [0x19] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x1a] = KEY_SEARCH, /* scan */ + + [0x37] = KEY_REWIND, /* << */ + [0x32] = KEY_RECORD, /* o (red) */ + [0x33] = KEY_FORWARD, /* >> */ + [0x11] = KEY_STOP, /* square */ + [0x3b] = KEY_PLAY, /* > */ + [0x30] = KEY_PLAYPAUSE, /* || */ + + [0x31] = KEY_TV, + [0x34] = KEY_RADIO, +}; +EXPORT_SYMBOL_GPL(ir_codes_pixelview_new); + IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { [ 0x00 ] = KEY_0, [ 0x01 ] = KEY_1, diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index d2e42c77b5a8..6b25b8c9bb6d 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -258,6 +258,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keyup = 0x80; ir->polling = 1; /* ms */ break; + case CX88_BOARD_PROLINK_PV_8000GT: + ir_codes = ir_codes_pixelview_new; + ir->gpio_addr = MO_GP1_IO; + ir->mask_keycode = 0x3f; + ir->mask_keyup = 0x80; + ir->polling = 1; /* ms */ + break; case CX88_BOARD_KWORLD_LTV883: ir_codes = ir_codes_pixelview; ir->gpio_addr = MO_GP1_IO; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index a4274203f252..20f1afe2140e 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -107,6 +107,7 @@ extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE]; -- cgit v1.2.3 From 4916e616ec1cfe278a2ab04f167d36980547b1d8 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Wed, 2 Apr 2008 14:28:06 -0300 Subject: V4L/DVB (7373): logical-bitwise & confusion in se401_init() logical-bitwise & confusion Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/se401.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index 312a01a1f095..f17a539857d4 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -1279,7 +1279,7 @@ static int se401_init(struct usb_se401 *se401, int button) rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); se401->cheight=cp[0]+cp[1]*256; - if (!cp[2] && SE401_FORMAT_BAYER) { + if (!(cp[2] & SE401_FORMAT_BAYER)) { err("Bayer format not supported!"); return 1; } -- cgit v1.2.3 From 095c3804f9cac2dc9c3bd31179b8805f81954fb7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:28:06 -0300 Subject: V4L/DVB (7374): Fix left-overs from the videobuf-dma-sg.c conversion to generic DMA The dev element of the struct videobuf_queue is now of type struct device implicitly. Fix left-over casts. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-core.c | 2 +- drivers/media/video/cx88/cx88-core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 7f10b273598f..a77505daaed2 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -952,7 +952,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf) videobuf_waiton(&buf->vb, 0, 0); videobuf_dma_unmap(q, dma); videobuf_dma_free(dma); - btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); + btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); buf->vb.state = VIDEOBUF_NEEDS_INIT; } diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 12440b91e4b3..75b581048f6e 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -219,7 +219,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) videobuf_waiton(&buf->vb,0,0); videobuf_dma_unmap(q, dma); videobuf_dma_free(dma); - btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); + btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); buf->vb.state = VIDEOBUF_NEEDS_INIT; } -- cgit v1.2.3 From 0c9bf950a0c73bdf1fcd1ee4c7ff0d43d6cf7724 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:06 -0300 Subject: V4L/DVB (7375): cx88/saa7134: fix magic number for xc3028 reusage detection tuner-xc2028 needs to know when a DVB module is sharing the same analog tuner. This is done by comparing a magic number that needs to be the same on analog and on digital. To make easier, this magic number is a pointer to some data struct. With the previous code, two different pointers were using, causing a miss-detection. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index d72b817bf886..37ebfcc6be55 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -458,7 +458,7 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, .i2c_addr = addr, - .video_dev = dev->core, + .video_dev = dev->core->i2c_adap.algo_data, }; if (!dev->dvb.frontend) { diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 97d9178dca2b..00f325ad565a 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1166,7 +1166,7 @@ static int dvb_init(struct saa7134_dev *dev) struct xc2028_config cfg = { .i2c_adap = &dev->i2c_adap, .i2c_addr = 0x61, - .video_dev = dev, + .video_dev = dev->i2c_adap.algo_data, }; fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); if (!fe) { -- cgit v1.2.3 From 10761a7e30b7ec7dc432207426340aeeeec262e3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:28:07 -0300 Subject: V4L/DVB (7376): Improve compile-time type-checking in videobuf Make the dev member of the struct videobuf_queue of type "struct device *" to avoid future problems. Also change the prototype of the videobuf_queue_core_init() function. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 2 +- include/media/videobuf-core.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 5ea635fac236..137a1ff4a149 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -120,7 +120,7 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, void videobuf_queue_core_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 99033945cdee..fcdffdd63304 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -151,7 +151,7 @@ struct videobuf_qtype_ops { struct videobuf_queue { struct mutex vb_lock; spinlock_t *irqlock; - void *dev; /* on pci, points to struct pci_dev */ + struct device *dev; enum v4l2_buf_type type; unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ @@ -185,7 +185,7 @@ void *videobuf_alloc(struct videobuf_queue* q); void videobuf_queue_core_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, -- cgit v1.2.3 From 8119067db1349d1d3922deefb621d59135aa4bae Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:07 -0300 Subject: V4L/DVB (7377): radio-sf16fmr2.c: fix volume handling As reported by Roel Kluin <12o3l@tiscali.nl>: in drivers/media/radio/radio-sf16fmr2.c:319: for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { if ((fmr2->card_type != 11) && V4L2_CID_AUDIO_VOLUME) radio_qctrl[i].step = 65535; ... I don't understand this '&& V4L2_CID_AUDIO_VOLUME' While fixing this issue, I've revisited the volume control code and fixed CodingStyle on the changed procedures. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-sf16fmr2.c | 102 ++++++++++++++--------------------- 1 file changed, 39 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index ebc5fbbc38bb..7bf7d534c042 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -29,6 +29,8 @@ static struct mutex lock; #include /* for KERNEL_VERSION MACRO */ #define RADIO_VERSION KERNEL_VERSION(0,0,2) +#define AUD_VOL_INDEX 1 + static struct v4l2_queryctrl radio_qctrl[] = { { .id = V4L2_CID_AUDIO_MUTE, @@ -37,13 +39,14 @@ static struct v4l2_queryctrl radio_qctrl[] = { .maximum = 1, .default_value = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ + }, + [AUD_VOL_INDEX] = { .id = V4L2_CID_AUDIO_VOLUME, .name = "Volume", .minimum = 0, - .maximum = 65535, - .step = 1<<12, - .default_value = 0xff, + .maximum = 15, + .step = 1, + .default_value = 0, .type = V4L2_CTRL_TYPE_INTEGER, } }; @@ -61,7 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = { struct fmr2_device { int port; - int curvol; /* 0-65535, if not volume 0 or 65535 */ + int curvol; /* 0-15 */ int mute; int stereo; /* card is producing stereo audio */ unsigned long curfreq; /* freq in kHz */ @@ -176,51 +179,35 @@ static int fmr2_setfreq(struct fmr2_device *dev) /* !!! not tested, in my card this does't work !!! */ static int fmr2_setvolume(struct fmr2_device *dev) { - int i,a,n, port = dev->port; + int vol[16] = { 0x021, 0x084, 0x090, 0x104, + 0x110, 0x204, 0x210, 0x402, + 0x404, 0x408, 0x410, 0x801, + 0x802, 0x804, 0x808, 0x810 }; + int i, a, port = dev->port; + int n = vol[dev->curvol & 0x0f]; - if (dev->card_type != 11) return 1; + if (dev->card_type != 11) + return 1; - switch( (dev->curvol+(1<<11)) >> 12 ) - { - case 0: case 1: n = 0x21; break; - case 2: n = 0x84; break; - case 3: n = 0x90; break; - case 4: n = 0x104; break; - case 5: n = 0x110; break; - case 6: n = 0x204; break; - case 7: n = 0x210; break; - case 8: n = 0x402; break; - case 9: n = 0x404; break; - default: - case 10: n = 0x408; break; - case 11: n = 0x410; break; - case 12: n = 0x801; break; - case 13: n = 0x802; break; - case 14: n = 0x804; break; - case 15: n = 0x808; break; - case 16: n = 0x810; break; - } - for(i=12;--i>=0;) - { + for (i = 12; --i >= 0; ) { a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ - outb(a|4, port); - wait(4,port); - outb(a|0x24, port); - wait(4,port); - outb(a|4, port); - wait(4,port); + outb(a | 4, port); + wait(4, port); + outb(a | 0x24, port); + wait(4, port); + outb(a | 4, port); + wait(4, port); } - for(i=6;--i>=0;) - { + for (i = 6; --i >= 0; ) { a = ((0x18 >> i) & 1) << 6; - outb(a|4, port); + outb(a | 4, port); wait(4,port); - outb(a|0x24, port); + outb(a | 0x24, port); wait(4,port); outb(a|4, port); wait(4,port); } - wait(4,port); + wait(4, port); outb(0x14, port); return 0; @@ -312,16 +299,10 @@ static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { int i; - struct video_device *dev = video_devdata(file); - struct fmr2_device *fmr2 = dev->priv; for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if ((fmr2->card_type != 11) - && V4L2_CID_AUDIO_VOLUME) - radio_qctrl[i].step = 65535; if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); + memcpy(qc, &radio_qctrl[i], sizeof(*qc)); return 0; } } @@ -354,24 +335,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: fmr2->mute = ctrl->value; - if (fmr2->card_type != 11) { - if (!fmr2->mute) - fmr2->curvol = 65535; - else - fmr2->curvol = 0; - } break; case V4L2_CID_AUDIO_VOLUME: - fmr2->curvol = ctrl->value; - if (fmr2->card_type != 11) { - if (fmr2->curvol) { - fmr2->curvol = 65535; - fmr2->mute = 0; - } else { - fmr2->curvol = 0; - fmr2->mute = 1; - } - } + if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum) + fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum; + else + fmr2->curvol = ctrl->value; + break; default: return -EINVAL; @@ -387,6 +357,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, mutex_lock(&lock); if (fmr2->curvol && !fmr2->mute) { fmr2_setvolume(fmr2); + /* Set frequency and unmute card */ fmr2_setfreq(fmr2); } else fmr2_mute(fmr2->port); @@ -487,6 +458,11 @@ static int __init fmr2_init(void) fmr2_product_info(&fmr2_unit); mutex_unlock(&lock); debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); + + /* Only card_type == 11 implements volume */ + if (fmr2_unit.card_type != 11) + radio_qctrl[AUD_VOL_INDEX].maximum = 1; + return 0; } -- cgit v1.2.3 From 72619931b915a0cb703395a5279e24914c69dd9e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:28:07 -0300 Subject: V4L/DVB (7378): cleanup variable initialization flags used for spinlocks don't need to be initialized, except where the compiler has no way to see, that the spin_unlock_irqrestore is only called if the spin_lock_irqsave has been called before. Local variable initialization doesn't have to be protected. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-queue.c | 4 ++-- drivers/media/video/videobuf-core.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c index 39a216713244..3e1deec67a5e 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/video/ivtv/ivtv-queue.c @@ -51,7 +51,7 @@ void ivtv_queue_init(struct ivtv_queue *q) void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q) { - unsigned long flags = 0; + unsigned long flags; /* clear the buffer if it is going to be enqueued to the free queue */ if (q == &s->q_free) { @@ -71,7 +71,7 @@ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_qu struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q) { struct ivtv_buffer *buf = NULL; - unsigned long flags = 0; + unsigned long flags; spin_lock_irqsave(&s->qlock, flags); if (!list_empty(&q->list)) { diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 137a1ff4a149..fe742fdfae07 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -742,14 +742,13 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, { enum v4l2_field field; unsigned long flags = 0; - unsigned size, nbufs; + unsigned size = 0, nbufs = 1; int retval; MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); mutex_lock(&q->vb_lock); - nbufs = 1; size = 0; q->ops->buf_setup(q, &nbufs, &size); if (NULL == q->read_buf && -- cgit v1.2.3 From 3c68d9530368a89aba7993e11061a81d209c3c6a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:07 -0300 Subject: V4L/DVB (7379): tuner: prevent instance sharing if i2c adapter is NULL We currently do not have a method to enable instance staring if i2c adapter is NULL, in the cases of dvb demods that write to the tuner directly using calc_regs. Prevent possible wrong instance sharing for these cases until a better solution can be found. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-i2c.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index 60ba794809fe..3ad6c8e0b04c 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -129,10 +129,10 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, ({ \ int __ret = 0; \ list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \ - if ((state->i2c_props.addr == i2caddr) && \ - ((state->i2c_props.adap ? \ - i2c_adapter_id(state->i2c_props.adap) : -1) == \ - (i2cadap ? i2c_adapter_id(i2cadap) : -1))) { \ + if (((i2cadap) && (state->i2c_props.adap)) && \ + ((i2c_adapter_id(state->i2c_props.adap) == \ + i2c_adapter_id(i2cadap)) && \ + (i2caddr == state->i2c_props.addr))) { \ __tuner_info(state->i2c_props, \ "attaching existing instance\n"); \ state->i2c_props.count++; \ -- cgit v1.2.3 From 8f825f5146bf6288944781e15ff9081554b2cc80 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:08 -0300 Subject: V4L/DVB (7380): tuner-simple: warn if tuner can't be probed during attach Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index b95ed1f489a0..07007d67d45f 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -987,6 +987,28 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, return NULL; } + /* If i2c_adap is set, check that the tuner is at the correct address. + * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly + * by the digital demod via calc_regs. + */ + if (i2c_adap != NULL) { + u8 b[1]; + struct i2c_msg msg = { + .addr = i2c_addr, .flags = I2C_M_RD, + .buf = b, .len = 1, + }; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (1 != i2c_transfer(i2c_adap, &msg, 1)) + tuner_warn("unable to probe %s, proceeding anyway.", + tuners[type].name); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + mutex_lock(&tuner_simple_list_mutex); instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv, -- cgit v1.2.3 From 6b5210bc5e185669108dc6e19e974cf136fd6d83 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:08 -0300 Subject: V4L/DVB (7381): tuner: rename TUNER_PHILIPS_ATSC to TUNER_PHILIPS_FCV1236D TUNER_PHILIPS_ATSC is an ambiguous name for a tuner. Rename it to TUNER_PHILIPS_FCV1236D to be more descriptive. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 4 ++-- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- drivers/media/video/tuner-simple.c | 6 +++--- drivers/media/video/tuner-types.c | 4 ++-- include/media/tuner.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 22c2708e42ab..4a82cd2dd66a 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -2327,7 +2327,7 @@ struct tvcard bttv_tvcards[] = { .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, - .tuner_type = TUNER_PHILIPS_ATSC, + .tuner_type = TUNER_PHILIPS_FCV1236D, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_dvb = 1, @@ -2966,7 +2966,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_DVICO_FUSIONHDTV_2] = { .name = "DViCO FusionHDTV 2", .tuner = 0, - .tuner_type = TUNER_PHILIPS_ATSC, /* FCV1236D */ + .tuner_type = TUNER_PHILIPS_FCV1236D, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .video_inputs = 3, diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index aae7753fef11..94aed008f83b 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -331,7 +331,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Kworld USB2800", .is_em2800 = 1, .vchannels = 3, - .tuner_type = TUNER_PHILIPS_ATSC, + .tuner_type = TUNER_PHILIPS_FCV1236D, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, .input = { { diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index c54b23787ef1..c7a6bc01dd5f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -185,7 +185,7 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .shortname = "oa2", .client_modules.lst = pvr2_client_onair_usb2, .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2), - .default_tuner_type = TUNER_PHILIPS_ATSC, + .default_tuner_type = TUNER_PHILIPS_FCV1236D, .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 6fde042ee317..55b056bc4e69 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3333,7 +3333,7 @@ struct saa7134_board saa7134_boards[] = { /* Juan Pablo Sormani */ .name = "Encore ENLTV-FM", .audio_clock = 0x00200000, - .tuner_type = TUNER_PHILIPS_ATSC, + .tuner_type = TUNER_PHILIPS_FCV1236D, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 07007d67d45f..273030bda6d9 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -284,7 +284,7 @@ static void simple_set_rf_input(struct dvb_frontend *fe, break; } break; - case TUNER_PHILIPS_ATSC: + case TUNER_PHILIPS_FCV1236D: switch (rf) { case 1: *cb |= 0x01; @@ -356,7 +356,7 @@ static int simple_std_setup(struct dvb_frontend *fe, } break; - case TUNER_PHILIPS_ATSC: + case TUNER_PHILIPS_FCV1236D: /* 0x00 -> ATSC antenna input 1 */ /* 0x01 -> ATSC antenna input 2 */ /* 0x02 -> NTSC antenna input 1 */ @@ -766,7 +766,7 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, buf[3] |= 1 << 3; break; case TUNER_PHILIPS_TUV1236D: - case TUNER_PHILIPS_ATSC: + case TUNER_PHILIPS_FCV1236D: { unsigned int new_rf; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index ad16bc25197a..10dddca8b5d1 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -615,7 +615,7 @@ static struct tuner_params tuner_philips_pal_mk_params[] = { }, }; -/* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */ +/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */ static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = { { 16 * 157.25 /*MHz*/, 0x8e, 0xa2, }, @@ -1434,7 +1434,7 @@ struct tunertype tuners[] = { .params = tuner_philips_pal_mk_params, .count = ARRAY_SIZE(tuner_philips_pal_mk_params), }, - [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ + [TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */ .name = "Philips FCV1236D ATSC/NTSC dual in", .params = tuner_philips_fcv1236d_params, .count = ARRAY_SIZE(tuner_philips_fcv1236d_params), diff --git a/include/media/tuner.h b/include/media/tuner.h index 1bf24a6ed8f1..77068fcc86bd 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -78,7 +78,7 @@ #define TUNER_HITACHI_NTSC 40 #define TUNER_PHILIPS_PAL_MK 41 -#define TUNER_PHILIPS_ATSC 42 +#define TUNER_PHILIPS_FCV1236D 42 #define TUNER_PHILIPS_FM1236_MK3 43 #define TUNER_PHILIPS_4IN1 44 /* ATI TV Wonder Pro - Conexant */ -- cgit v1.2.3 From 7693e8552d13a0ecd6a010e8de1e3b7f9ea567ce Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:08 -0300 Subject: V4L/DVB (7383): tda18271: add attach-time parameter to limit i2c transfer size Add attach-time parameter, "small_i2c" to limit i2c transfer size to write at most 16 registers at a time during initialization. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-common.c | 7 ++++++- drivers/media/dvb/frontends/tda18271-fe.c | 3 +++ drivers/media/dvb/frontends/tda18271-priv.h | 1 + drivers/media/dvb/frontends/tda18271.h | 3 +++ 4 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c index 39496463ccf3..bbfc22a5f6db 100644 --- a/drivers/media/dvb/frontends/tda18271-common.c +++ b/drivers/media/dvb/frontends/tda18271-common.c @@ -311,7 +311,12 @@ int tda18271_init_regs(struct dvb_frontend *fe) regs[R_EB22] = 0x48; regs[R_EB23] = 0xb0; - tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); + if (priv->small_i2c) { + tda18271_write_regs(fe, 0x00, 0x10); + tda18271_write_regs(fe, 0x10, 0x10); + tda18271_write_regs(fe, 0x20, 0x07); + } else + tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); /* setup agc1 gain */ regs[R_EB17] = 0x00; diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index b5d69a8108d9..bb0a65310b71 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -1081,6 +1081,9 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, fe->tuner_priv = priv; + if (cfg) + priv->small_i2c = cfg->small_i2c; + if (tda18271_get_id(fe) < 0) goto fail; diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index 840b1803d171..ecb588e5f7d5 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -110,6 +110,7 @@ struct tda18271_priv { unsigned int tm_rfcal; unsigned int cal_initialized:1; + unsigned int small_i2c:1; struct tda18271_map_layout *maps; struct tda18271_std_map std; diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index 24b0e35a2ab3..e79441e22718 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -58,6 +58,9 @@ struct tda18271_config { /* use i2c gate provided by analog or digital demod */ enum tda18271_i2c_gate gate; + + /* some i2c providers cant write all 39 registers at once */ + unsigned int small_i2c:1; }; #if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE)) -- cgit v1.2.3 From a3f00d9960665aca8eaaf6577659fd211e643034 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:09 -0300 Subject: V4L/DVB (7384): tda18271: store FM_RFn setting in struct tda18271_std_map_item All standard related configuration is stored within struct tda18271_std_map_item. Pass a pointer to this structure rather than its individual members. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 76 ++++++++++----------------- drivers/media/dvb/frontends/tda18271-tables.c | 56 ++++++++++---------- drivers/media/dvb/frontends/tda18271.h | 1 + 3 files changed, 58 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index bb0a65310b71..fef225abee96 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -37,8 +37,8 @@ static LIST_HEAD(hybrid_tuner_instance_list); /*---------------------------------------------------------------------*/ static int tda18271_channel_configuration(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, - int radio) + struct tda18271_std_map_item *map, + u32 freq, u32 bw) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; @@ -48,7 +48,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, /* set standard */ regs[R_EP3] &= ~0x1f; /* clear std bits */ - regs[R_EP3] |= std; + regs[R_EP3] |= map->std_bits; /* set cal mode to normal */ regs[R_EP4] &= ~0x03; @@ -66,10 +66,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, break; } - if (radio) - regs[R_EP4] |= 0x80; - else - regs[R_EP4] &= ~0x80; + /* update FM_RFn */ + regs[R_EP4] &= ~0x80; + regs[R_EP4] |= map->fm_rfn << 7; /* update RF_TOP / IF_TOP */ switch (priv->mode) { @@ -114,7 +113,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, /* --------------------------------------------------------------- */ - N = freq + ifc; + N = map->if_freq * 1000 + freq; /* FIXME: assumes master */ tda18271_calc_main_pll(fe, N); @@ -728,12 +727,12 @@ static int tda18271_init(struct dvb_frontend *fe) } static int tda18271_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) + struct tda18271_std_map_item *map, u32 freq, u32 bw) { struct tda18271_priv *priv = fe->tuner_priv; tda_dbg("freq = %d, ifc = %d, bw = %d, std = 0x%02x\n", - freq, ifc, bw, std); + freq, map->if_freq, bw, map->std_bits); tda18271_init(fe); @@ -747,7 +746,7 @@ static int tda18271_tune(struct dvb_frontend *fe, tda18271c2_rf_tracking_filters_correction(fe, freq); break; } - tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); + tda18271_channel_configuration(fe, map, freq, bw); mutex_unlock(&priv->lock); @@ -761,9 +760,8 @@ static int tda18271_set_params(struct dvb_frontend *fe, { struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_std_map *std_map = &priv->std; + struct tda18271_std_map_item *map; int ret; - u8 std; - u16 sgIF; u32 bw, freq = params->frequency; priv->mode = TDA18271_DIGITAL; @@ -772,13 +770,11 @@ static int tda18271_set_params(struct dvb_frontend *fe, switch (params->u.vsb.modulation) { case VSB_8: case VSB_16: - std = std_map->atsc_6.std_bits; - sgIF = std_map->atsc_6.if_freq; + map = &std_map->atsc_6; break; case QAM_64: case QAM_256: - std = std_map->qam_6.std_bits; - sgIF = std_map->qam_6.if_freq; + map = &std_map->qam_6; break; default: tda_warn("modulation not set!\n"); @@ -793,18 +789,15 @@ static int tda18271_set_params(struct dvb_frontend *fe, switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: bw = 6000000; - std = std_map->dvbt_6.std_bits; - sgIF = std_map->dvbt_6.if_freq; + map = &std_map->dvbt_6; break; case BANDWIDTH_7_MHZ: bw = 7000000; - std = std_map->dvbt_7.std_bits; - sgIF = std_map->dvbt_7.if_freq; + map = &std_map->dvbt_7; break; case BANDWIDTH_8_MHZ: bw = 8000000; - std = std_map->dvbt_8.std_bits; - sgIF = std_map->dvbt_8.if_freq; + map = &std_map->dvbt_8; break; default: tda_warn("bandwidth not set!\n"); @@ -819,7 +812,7 @@ static int tda18271_set_params(struct dvb_frontend *fe, if (fe->ops.analog_ops.standby) fe->ops.analog_ops.standby(fe); - ret = tda18271_tune(fe, sgIF * 1000, freq, bw, std, 0); + ret = tda18271_tune(fe, map, freq, bw); if (ret < 0) goto fail; @@ -836,57 +829,46 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe, { struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_std_map *std_map = &priv->std; + struct tda18271_std_map_item *map; char *mode; - int ret, radio = 0; - u8 std; - u16 sgIF; + int ret; u32 freq = params->frequency * 62500; priv->mode = TDA18271_ANALOG; if (params->mode == V4L2_TUNER_RADIO) { - radio = 1; freq = freq / 1000; - std = std_map->fm_radio.std_bits; - sgIF = std_map->fm_radio.if_freq; + map = &std_map->fm_radio; mode = "fm"; } else if (params->std & V4L2_STD_MN) { - std = std_map->atv_mn.std_bits; - sgIF = std_map->atv_mn.if_freq; + map = &std_map->atv_mn; mode = "MN"; } else if (params->std & V4L2_STD_B) { - std = std_map->atv_b.std_bits; - sgIF = std_map->atv_b.if_freq; + map = &std_map->atv_b; mode = "B"; } else if (params->std & V4L2_STD_GH) { - std = std_map->atv_gh.std_bits; - sgIF = std_map->atv_gh.if_freq; + map = &std_map->atv_gh; mode = "GH"; } else if (params->std & V4L2_STD_PAL_I) { - std = std_map->atv_i.std_bits; - sgIF = std_map->atv_i.if_freq; + map = &std_map->atv_i; mode = "I"; } else if (params->std & V4L2_STD_DK) { - std = std_map->atv_dk.std_bits; - sgIF = std_map->atv_dk.if_freq; + map = &std_map->atv_dk; mode = "DK"; } else if (params->std & V4L2_STD_SECAM_L) { - std = std_map->atv_l.std_bits; - sgIF = std_map->atv_l.if_freq; + map = &std_map->atv_l; mode = "L"; } else if (params->std & V4L2_STD_SECAM_LC) { - std = std_map->atv_lc.std_bits; - sgIF = std_map->atv_lc.if_freq; + map = &std_map->atv_lc; mode = "L'"; } else { - std = std_map->atv_i.std_bits; - sgIF = std_map->atv_i.if_freq; + map = &std_map->atv_i; mode = "xx"; } tda_dbg("setting tda18271 to system %s\n", mode); - ret = tda18271_tune(fe, sgIF * 1000, freq, 0, std, radio); + ret = tda18271_tune(fe, map, freq, 0); if (ret < 0) goto fail; diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c index e94afcfdc5bc..462f20b41728 100644 --- a/drivers/media/dvb/frontends/tda18271-tables.c +++ b/drivers/media/dvb/frontends/tda18271-tables.c @@ -1187,37 +1187,37 @@ fail: /*---------------------------------------------------------------------*/ static struct tda18271_std_map tda18271c1_std_map = { - .fm_radio = { .if_freq = 1250, .std_bits = 0x18 }, - .atv_b = { .if_freq = 6750, .std_bits = 0x0e }, - .atv_dk = { .if_freq = 7750, .std_bits = 0x0f }, - .atv_gh = { .if_freq = 7750, .std_bits = 0x0f }, - .atv_i = { .if_freq = 7750, .std_bits = 0x0f }, - .atv_l = { .if_freq = 7750, .std_bits = 0x0f }, - .atv_lc = { .if_freq = 1250, .std_bits = 0x0f }, - .atv_mn = { .if_freq = 5750, .std_bits = 0x0d }, - .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c }, - .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c }, - .dvbt_7 = { .if_freq = 3800, .std_bits = 0x1d }, - .dvbt_8 = { .if_freq = 4300, .std_bits = 0x1e }, - .qam_6 = { .if_freq = 4000, .std_bits = 0x1d }, - .qam_8 = { .if_freq = 5000, .std_bits = 0x1f }, + .fm_radio = { .if_freq = 1250, .std_bits = 0x18, .fm_rfn = 1 }, + .atv_b = { .if_freq = 6750, .std_bits = 0x0e, .fm_rfn = 0 }, + .atv_dk = { .if_freq = 7750, .std_bits = 0x0f, .fm_rfn = 0 }, + .atv_gh = { .if_freq = 7750, .std_bits = 0x0f, .fm_rfn = 0 }, + .atv_i = { .if_freq = 7750, .std_bits = 0x0f, .fm_rfn = 0 }, + .atv_l = { .if_freq = 7750, .std_bits = 0x0f, .fm_rfn = 0 }, + .atv_lc = { .if_freq = 1250, .std_bits = 0x0f, .fm_rfn = 0 }, + .atv_mn = { .if_freq = 5750, .std_bits = 0x0d, .fm_rfn = 0 }, + .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c, .fm_rfn = 0 }, + .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c, .fm_rfn = 0 }, + .dvbt_7 = { .if_freq = 3800, .std_bits = 0x1d, .fm_rfn = 0 }, + .dvbt_8 = { .if_freq = 4300, .std_bits = 0x1e, .fm_rfn = 0 }, + .qam_6 = { .if_freq = 4000, .std_bits = 0x1d, .fm_rfn = 0 }, + .qam_8 = { .if_freq = 5000, .std_bits = 0x1f, .fm_rfn = 0 }, }; static struct tda18271_std_map tda18271c2_std_map = { - .fm_radio = { .if_freq = 1250, .std_bits = 0x18 }, - .atv_b = { .if_freq = 6000, .std_bits = 0x0d }, - .atv_dk = { .if_freq = 6900, .std_bits = 0x0e }, - .atv_gh = { .if_freq = 7100, .std_bits = 0x0e }, - .atv_i = { .if_freq = 7250, .std_bits = 0x0e }, - .atv_l = { .if_freq = 6900, .std_bits = 0x0e }, - .atv_lc = { .if_freq = 1250, .std_bits = 0x0e }, - .atv_mn = { .if_freq = 5400, .std_bits = 0x0c }, - .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c }, - .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c }, - .dvbt_7 = { .if_freq = 3500, .std_bits = 0x1c }, - .dvbt_8 = { .if_freq = 4000, .std_bits = 0x1d }, - .qam_6 = { .if_freq = 4000, .std_bits = 0x1d }, - .qam_8 = { .if_freq = 5000, .std_bits = 0x1f }, + .fm_radio = { .if_freq = 1250, .std_bits = 0x18, .fm_rfn = 1 }, + .atv_b = { .if_freq = 6000, .std_bits = 0x0d, .fm_rfn = 0 }, + .atv_dk = { .if_freq = 6900, .std_bits = 0x0e, .fm_rfn = 0 }, + .atv_gh = { .if_freq = 7100, .std_bits = 0x0e, .fm_rfn = 0 }, + .atv_i = { .if_freq = 7250, .std_bits = 0x0e, .fm_rfn = 0 }, + .atv_l = { .if_freq = 6900, .std_bits = 0x0e, .fm_rfn = 0 }, + .atv_lc = { .if_freq = 1250, .std_bits = 0x0e, .fm_rfn = 0 }, + .atv_mn = { .if_freq = 5400, .std_bits = 0x0c, .fm_rfn = 0 }, + .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c, .fm_rfn = 0 }, + .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c, .fm_rfn = 0 }, + .dvbt_7 = { .if_freq = 3500, .std_bits = 0x1c, .fm_rfn = 0 }, + .dvbt_8 = { .if_freq = 4000, .std_bits = 0x1d, .fm_rfn = 0 }, + .qam_6 = { .if_freq = 4000, .std_bits = 0x1d, .fm_rfn = 0 }, + .qam_8 = { .if_freq = 5000, .std_bits = 0x1f, .fm_rfn = 0 }, }; /*---------------------------------------------------------------------*/ diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index e79441e22718..a33095757ea8 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -27,6 +27,7 @@ struct tda18271_std_map_item { u16 if_freq; u8 std_bits; + unsigned int fm_rfn:1; }; struct tda18271_std_map { -- cgit v1.2.3 From 70325be633a7aebf963367d7f017a5ee1d892412 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:09 -0300 Subject: V4L/DVB (7385): tda18271: store agc_mode configuration independently of std_bits Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 14 +++-- drivers/media/dvb/frontends/tda18271-tables.c | 84 ++++++++++++++++++--------- drivers/media/dvb/frontends/tda18271.h | 7 ++- drivers/media/video/cx23885/cx23885-dvb.c | 4 +- 4 files changed, 72 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index fef225abee96..eb44ab71ff74 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -48,7 +48,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, /* set standard */ regs[R_EP3] &= ~0x1f; /* clear std bits */ - regs[R_EP3] |= map->std_bits; + regs[R_EP3] |= (map->agc_mode << 3) | map->std; /* set cal mode to normal */ regs[R_EP4] &= ~0x03; @@ -731,8 +731,8 @@ static int tda18271_tune(struct dvb_frontend *fe, { struct tda18271_priv *priv = fe->tuner_priv; - tda_dbg("freq = %d, ifc = %d, bw = %d, std = 0x%02x\n", - freq, map->if_freq, bw, map->std_bits); + tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n", + freq, map->if_freq, bw, map->agc_mode, map->std); tda18271_init(fe); @@ -927,15 +927,17 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) /* ------------------------------------------------------------------ */ #define tda18271_update_std(std_cfg, name) do { \ - if (map->std_cfg.if_freq + map->std_cfg.std_bits > 0) { \ + if (map->std_cfg.if_freq + \ + map->std_cfg.agc_mode + map->std_cfg.std > 0) { \ tda_dbg("Using custom std config for %s\n", name); \ memcpy(&std->std_cfg, &map->std_cfg, \ sizeof(struct tda18271_std_map_item)); \ } } while (0) #define tda18271_dump_std_item(std_cfg, name) do { \ - tda_dbg("(%s) if freq = %d, std bits = 0x%02x\n", \ - name, std->std_cfg.if_freq, std->std_cfg.std_bits); \ + tda_dbg("(%s) if freq = %d, agc_mode = %d, std = %d\n", \ + name, std->std_cfg.if_freq, \ + std->std_cfg.agc_mode, std->std_cfg.std); \ } while (0) static int tda18271_dump_std_map(struct dvb_frontend *fe) diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c index 462f20b41728..b402abd15bb2 100644 --- a/drivers/media/dvb/frontends/tda18271-tables.c +++ b/drivers/media/dvb/frontends/tda18271-tables.c @@ -1187,37 +1187,65 @@ fail: /*---------------------------------------------------------------------*/ static struct tda18271_std_map tda18271c1_std_map = { - .fm_radio = { .if_freq = 1250, .std_bits = 0x18, .fm_rfn = 1 }, - .atv_b = { .if_freq = 6750, .std_bits = 0x0e, .fm_rfn = 0 }, - .atv_dk = { .if_freq = 7750, .std_bits = 0x0f, .fm_rfn = 0 }, - .atv_gh = { .if_freq = 7750, .std_bits = 0x0f, .fm_rfn = 0 }, - .atv_i = { .if_freq = 7750, .std_bits = 0x0f, .fm_rfn = 0 }, - .atv_l = { .if_freq = 7750, .std_bits = 0x0f, .fm_rfn = 0 }, - .atv_lc = { .if_freq = 1250, .std_bits = 0x0f, .fm_rfn = 0 }, - .atv_mn = { .if_freq = 5750, .std_bits = 0x0d, .fm_rfn = 0 }, - .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c, .fm_rfn = 0 }, - .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c, .fm_rfn = 0 }, - .dvbt_7 = { .if_freq = 3800, .std_bits = 0x1d, .fm_rfn = 0 }, - .dvbt_8 = { .if_freq = 4300, .std_bits = 0x1e, .fm_rfn = 0 }, - .qam_6 = { .if_freq = 4000, .std_bits = 0x1d, .fm_rfn = 0 }, - .qam_8 = { .if_freq = 5000, .std_bits = 0x1f, .fm_rfn = 0 }, + .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0 }, + /* EP3[4:0] 0x18 */ + .atv_b = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, + /* EP3[4:0] 0x0e */ + .atv_dk = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, + /* EP3[4:0] 0x0f */ + .atv_gh = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, + /* EP3[4:0] 0x0f */ + .atv_i = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, + /* EP3[4:0] 0x0f */ + .atv_l = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, + /* EP3[4:0] 0x0f */ + .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, + /* EP3[4:0] 0x0f */ + .atv_mn = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5 }, + /* EP3[4:0] 0x0d */ + .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, + /* EP3[4:0] 0x1c */ + .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, + /* EP3[4:0] 0x1c */ + .dvbt_7 = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5 }, + /* EP3[4:0] 0x1d */ + .dvbt_8 = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6 }, + /* EP3[4:0] 0x1e */ + .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5 }, + /* EP3[4:0] 0x1d */ + .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7 }, + /* EP3[4:0] 0x1f */ }; static struct tda18271_std_map tda18271c2_std_map = { - .fm_radio = { .if_freq = 1250, .std_bits = 0x18, .fm_rfn = 1 }, - .atv_b = { .if_freq = 6000, .std_bits = 0x0d, .fm_rfn = 0 }, - .atv_dk = { .if_freq = 6900, .std_bits = 0x0e, .fm_rfn = 0 }, - .atv_gh = { .if_freq = 7100, .std_bits = 0x0e, .fm_rfn = 0 }, - .atv_i = { .if_freq = 7250, .std_bits = 0x0e, .fm_rfn = 0 }, - .atv_l = { .if_freq = 6900, .std_bits = 0x0e, .fm_rfn = 0 }, - .atv_lc = { .if_freq = 1250, .std_bits = 0x0e, .fm_rfn = 0 }, - .atv_mn = { .if_freq = 5400, .std_bits = 0x0c, .fm_rfn = 0 }, - .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c, .fm_rfn = 0 }, - .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c, .fm_rfn = 0 }, - .dvbt_7 = { .if_freq = 3500, .std_bits = 0x1c, .fm_rfn = 0 }, - .dvbt_8 = { .if_freq = 4000, .std_bits = 0x1d, .fm_rfn = 0 }, - .qam_6 = { .if_freq = 4000, .std_bits = 0x1d, .fm_rfn = 0 }, - .qam_8 = { .if_freq = 5000, .std_bits = 0x1f, .fm_rfn = 0 }, + .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0 }, + /* EP3[4:0] 0x18 */ + .atv_b = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5 }, + /* EP3[4:0] 0x0d */ + .atv_dk = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, + /* EP3[4:0] 0x0e */ + .atv_gh = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, + /* EP3[4:0] 0x0e */ + .atv_i = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, + /* EP3[4:0] 0x0e */ + .atv_l = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, + /* EP3[4:0] 0x0e */ + .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, + /* EP3[4:0] 0x0e */ + .atv_mn = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4 }, + /* EP3[4:0] 0x0c */ + .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, + /* EP3[4:0] 0x1c */ + .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, + /* EP3[4:0] 0x1c */ + .dvbt_7 = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, + /* EP3[4:0] 0x1c */ + .dvbt_8 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5 }, + /* EP3[4:0] 0x1d */ + .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5 }, + /* EP3[4:0] 0x1d */ + .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7 }, + /* EP3[4:0] 0x1f */ }; /*---------------------------------------------------------------------*/ diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index a33095757ea8..3a743b0f0e8b 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -26,7 +26,12 @@ struct tda18271_std_map_item { u16 if_freq; - u8 std_bits; + + /* EP3[4:3] */ + unsigned int agc_mode:2; + /* EP3[2:0] */ + unsigned int std:3; + /* EP4[7] */ unsigned int fm_rfn:1; }; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 6c21779852fb..22381de7359e 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -164,8 +164,8 @@ static struct tda829x_config tda829x_no_probe = { }; static struct tda18271_std_map hauppauge_tda18271_std_map = { - .atsc_6 = { .if_freq = 5380, .std_bits = 0x1b }, - .qam_6 = { .if_freq = 4000, .std_bits = 0x18 }, + .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3 }, + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0 }, }; static struct tda18271_config hauppauge_tda18271_config = { -- cgit v1.2.3 From b15474b498fc6354b0592250fc8444bb156e1a41 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:09 -0300 Subject: V4L/DVB (7387): saa7134: Fix xc3028 entries Tuner addresses were incorrect. Fix the entries. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 55b056bc4e69..4b8bbb4a2f76 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4068,9 +4068,11 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = { - .name = "AVerMedia Cardbus TV/Radio (E506R)", - .audio_clock = 0x187de7, - .tuner_type = TUNER_XC2028, + .name = "AVerMedia Cardbus TV/Radio (E506R)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, /* TODO: .mpeg = SAA7134_MPEG_DVB, @@ -4099,6 +4101,8 @@ struct saa7134_board saa7134_boards[] = { .name = "AVerMedia Hybrid TV/Radio (A16D)", .audio_clock = 0x187de7, .tuner_type = TUNER_XC2028, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .inputs = {{ .name = name_tv, .vmux = 1, @@ -4118,6 +4122,8 @@ struct saa7134_board saa7134_boards[] = { .name = "Avermedia M115", .audio_clock = 0x187de7, .tuner_type = TUNER_XC2028, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .inputs = {{ .name = name_tv, .vmux = 1, @@ -4138,6 +4144,8 @@ struct saa7134_board saa7134_boards[] = { .name = "Compro VideoMate T750", .audio_clock = 0x00187de7, .tuner_type = TUNER_XC2028, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, -- cgit v1.2.3 From 251428519dd7cc163f14145f7cc18ea1f6d3e6df Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:09 -0300 Subject: V4L/DVB (7388): saa7134: fix radio entry for xc2028/3028 boards If left in blank, the driver will use value 0 (Temic PAL) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 4b8bbb4a2f76..e30f34e019b0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4071,6 +4071,7 @@ struct saa7134_board saa7134_boards[] = { .name = "AVerMedia Cardbus TV/Radio (E506R)", .audio_clock = 0x187de7, .tuner_type = TUNER_XC2028, + .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, /* @@ -4101,6 +4102,7 @@ struct saa7134_board saa7134_boards[] = { .name = "AVerMedia Hybrid TV/Radio (A16D)", .audio_clock = 0x187de7, .tuner_type = TUNER_XC2028, + .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ @@ -4122,6 +4124,7 @@ struct saa7134_board saa7134_boards[] = { .name = "Avermedia M115", .audio_clock = 0x187de7, .tuner_type = TUNER_XC2028, + .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ @@ -4144,6 +4147,7 @@ struct saa7134_board saa7134_boards[] = { .name = "Compro VideoMate T750", .audio_clock = 0x00187de7, .tuner_type = TUNER_XC2028, + .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, -- cgit v1.2.3 From 1280f3add084e69c244e9cacac64af04ba7bbf5c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 2 Apr 2008 14:28:10 -0300 Subject: V4L/DVB (7389): git-dvb: drivers/media/video/bt8xx/bttv-cards.c: fix warnings drivers/media/video/bt8xx/bttv-cards.c:3030:38: warning: "/*" within comment drivers/media/video/bt8xx/bttv-cards.c:3032:20: warning: "/*" within comment Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 4a82cd2dd66a..f20a01cfc73e 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -3027,9 +3027,7 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0x008007, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 0, 1, 2, 2 }, /* CONTVFMi */ - /*gpiomux = { 0, 1, 2, 3 }, /* MagicTV */ .gpiomute = 3, /* CONTVFMi */ - /*gpiomute = 4, /* MagicTV */ .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */ .tuner_addr = ADDR_UNSET, -- cgit v1.2.3 From e59212871fd57535f2325ef986931def600ba4a8 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:28:10 -0300 Subject: V4L/DVB (7390): saa7134: clear audio DSP interface after access error In the case of an access error to the high latency registers of the audio DSP, the interface needs to be cleared, otherwise a cascade of errors occurs. This patch is closely modeled after a proposal by Mirek Slugen Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-reg.h | 3 +++ drivers/media/video/saa7134/saa7134-tvaudio.c | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index ac6431ba4fc3..86f5eefdb0f6 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h @@ -365,6 +365,9 @@ #define SAA7135_DSP_RWSTATE_RDB (1 << 1) #define SAA7135_DSP_RWSTATE_WRR (1 << 0) +#define SAA7135_DSP_RWCLEAR 0x586 +#define SAA7135_DSP_RWCLEAR_RERR 1 + /* ------------------------------------------------------------------ */ /* * Local variables: diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index b90c55c0536e..232af598d947 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -653,6 +653,17 @@ static char *stdres[0x20] = { #define DSP_RETRY 32 #define DSP_DELAY 16 +#define SAA7135_DSP_RWCLEAR_RERR 1 + +static inline int saa_dsp_reset_error_bit(struct saa7134_dev *dev) +{ + int state = saa_readb(SAA7135_DSP_RWSTATE); + if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) { + d2printk("%s: resetting error bit\n", dev->name); + saa_writeb(SAA7135_DSP_RWCLEAR, SAA7135_DSP_RWCLEAR_RERR); + } + return 0; +} static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit) { @@ -660,8 +671,8 @@ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit) state = saa_readb(SAA7135_DSP_RWSTATE); if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) { - printk("%s: dsp access error\n",dev->name); - /* FIXME: send ack ... */ + printk(KERN_WARNING "%s: dsp access error\n", dev->name); + saa_dsp_reset_error_bit(dev); return -EIO; } while (0 == (state & bit)) { -- cgit v1.2.3 From aca311b6ec6197518306f5e334cbbd5b649411c3 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:28:10 -0300 Subject: V4L/DVB (7391): saa7134: Add DVB-S support for the MD 1734 cards with 2 saa7134 Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 7 ++----- drivers/media/video/saa7134/saa7134-dvb.c | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e30f34e019b0..1b6c7d697f04 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2911,15 +2911,13 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_MD7134_BRIDGE_2] = { - /* This card has two saa7134 chips on it, - but only one of them is currently working. - The programming for the primary decoder is - in SAA7134_BOARD_MD7134 */ + /* The second saa7134 on this card only serves as DVB-S host bridge */ .name = "Medion 7134 Bridge #2", .audio_clock = 0x00187de7, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, }, [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = { .name = "LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB", @@ -5438,7 +5436,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) dev->has_remote = SAA7134_REMOTE_I2C; break; case SAA7134_BOARD_AVERMEDIA_A169_B: - case SAA7134_BOARD_MD7134_BRIDGE_2: printk("%s: %s: dual saa713x broadcast decoders\n" "%s: Sorry, none of the inputs to this chip are supported yet.\n" "%s: Dual decoder functionality is disabled for now, use the other chip.\n", diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 00f325ad565a..a29d800616b1 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1156,6 +1156,29 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap); attach_xc3028 = 1; break; + case SAA7134_BOARD_MD7134_BRIDGE_2: + dev->dvb.frontend = dvb_attach(tda10086_attach, + &flydvbs, &dev->i2c_adap); + if (dev->dvb.frontend) { + struct dvb_frontend *fe; + if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, + &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) + wprintk("%s: MD7134 DVB-S, no SD1878 " + "found !\n", __FUNCTION__); + /* we need to open the i2c gate (we know it exists) */ + fe = dev->dvb.frontend; + fe->ops.i2c_gate_ctrl(fe, 1); + if (dvb_attach(isl6405_attach, fe, + &dev->i2c_adap, 0x08, 0, 0) == NULL) + wprintk("%s: MD7134 DVB-S, no ISL6405 " + "found !\n", __FUNCTION__); + fe->ops.i2c_gate_ctrl(fe, 0); + dev->original_set_voltage = fe->ops.set_voltage; + fe->ops.set_voltage = md8800_set_voltage; + dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage; + fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage; + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; -- cgit v1.2.3 From 125d57189b1ce91c99a3401709e9b8975ea1c51a Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:28:11 -0300 Subject: V4L/DVB (7392): saa7134: support 2nd DVB-S section of the MD8800 There are some restrictions: - The 2nd DVB-S section will only work if the 1st is configured for DVB-S too. so "options saa7134-dvb use_frontend=0,1" won't work. - Currently it is not possible to set the higher LNB supply voltages, so 14V instead of 13V in the 2nd section. - It is not possibe to turn off the 2nd LNB supply independently. This comes from the problem that the 2nd section can't access the i2c interface of the LNB supply chip. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 106 ++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index a29d800616b1..8e55c7572b4b 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -33,6 +33,7 @@ #include "saa7134.h" #include #include "dvb-pll.h" +#include #include "mt352.h" #include "mt352_priv.h" /* FIXME */ @@ -94,7 +95,7 @@ static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28)); udelay(10); ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27); - dprintk("%s %s\n", __FUNCTION__, ok ? "on" : "off"); + dprintk("%s %s\n", __func__, ok ? "on" : "off"); if (!ok) saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26)); @@ -114,7 +115,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe) static u8 irq_cfg [] = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 }; struct saa7134_dev *dev= fe->dvb->priv; - dprintk("%s called\n", __FUNCTION__); + dprintk("%s called\n", __func__); mt352_write(fe, clock_config, sizeof(clock_config)); udelay(200); @@ -882,6 +883,33 @@ static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg) return res; }; +static int md8800_set_voltage2(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct saa7134_dev *dev = fe->dvb->priv; + u8 wbuf[2] = { 0x1f, 00 }; + u8 rbuf; + struct i2c_msg msg[] = { { .addr = 0x08, .flags = 0, .buf = wbuf, .len = 1 }, + { .addr = 0x08, .flags = I2C_M_RD, .buf = &rbuf, .len = 1 } }; + + if (i2c_transfer(&dev->i2c_adap, msg, 2) != 2) + return -EIO; + /* NOTE: this assumes that gpo1 is used, it might be bit 5 (gpo2) */ + if (voltage == SEC_VOLTAGE_18) + wbuf[1] = rbuf | 0x10; + else + wbuf[1] = rbuf & 0xef; + msg[0].len = 2; + i2c_transfer(&dev->i2c_adap, msg, 1); + return 0; +} + +static int md8800_set_high_voltage2(struct dvb_frontend *fe, long arg) +{ + struct saa7134_dev *dev = fe->dvb->priv; + wprintk("%s: sorry can't set high LNB supply voltage from here\n", __func__); + return -EIO; +} + /* ================================================================== * nxt200x based ATSC cards, helper functions */ @@ -1003,11 +1031,11 @@ static int dvb_init(struct saa7134_dev *dev) if (dev->dvb.frontend) { if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, &dev->i2c_adap, 0) == NULL) { - wprintk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__); + wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__); } if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { - wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__); + wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__); } } } @@ -1036,27 +1064,35 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); if (dev->dvb.frontend) { - struct dvb_frontend *fe; + struct dvb_frontend *fe = dev->dvb.frontend; + u8 dev_id = dev->eedata[2]; + u8 data = 0xc4; + struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1}; + if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) wprintk("%s: Medion Quadro, no tda826x " - "found !\n", __FUNCTION__); - /* Note 10.2. Hac - * up to here. configuration for ctx948 and and one branch - * of md8800 should be identical - */ - /* we need to open the i2c gate (we know it exists) */ - fe = dev->dvb.frontend; - fe->ops.i2c_gate_ctrl(fe, 1); - if (dvb_attach(isl6405_attach, fe, - &dev->i2c_adap, 0x08, 0, 0) == NULL) - wprintk("%s: Medion Quadro, no ISL6405 " - "found !\n", __FUNCTION__); - fe->ops.i2c_gate_ctrl(fe, 0); - dev->original_set_voltage = fe->ops.set_voltage; - fe->ops.set_voltage = md8800_set_voltage; - dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage; - fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage; + "found !\n", __func__); + if (dev_id != 0x08) { + /* we need to open the i2c gate (we know it exists) */ + fe->ops.i2c_gate_ctrl(fe, 1); + if (dvb_attach(isl6405_attach, fe, + &dev->i2c_adap, 0x08, 0, 0) == NULL) + wprintk("%s: Medion Quadro, no ISL6405 " + "found !\n", __func__); + /* fire up the 2nd section of the LNB supply since we can't do + this from the other section */ + msg.buf = &data; + i2c_transfer(&dev->i2c_adap, &msg, 1); + fe->ops.i2c_gate_ctrl(fe, 0); + dev->original_set_voltage = fe->ops.set_voltage; + fe->ops.set_voltage = md8800_set_voltage; + dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage; + fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage; + } else { + fe->ops.set_voltage = md8800_set_voltage2; + fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage2; + } } } break; @@ -1082,11 +1118,11 @@ static int dvb_init(struct saa7134_dev *dev) if (dev->dvb.frontend) { if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { - wprintk("%s: No tda826x found!\n", __FUNCTION__); + wprintk("%s: No tda826x found!\n", __func__); } if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { - wprintk("%s: No ISL6421 found!\n", __FUNCTION__); + wprintk("%s: No ISL6421 found!\n", __func__); } } break; @@ -1138,10 +1174,10 @@ static int dvb_init(struct saa7134_dev *dev) if (dev->dvb.frontend) { if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) - wprintk("%s: No tda826x found!\n", __FUNCTION__); + wprintk("%s: No tda826x found!\n", __func__); if (dvb_attach(lnbp21_attach, dev->dvb.frontend, &dev->i2c_adap, 0, 0) == NULL) - wprintk("%s: No lnbp21 found!\n", __FUNCTION__); + wprintk("%s: No lnbp21 found!\n", __func__); } break; case SAA7134_BOARD_CREATIX_CTX953: @@ -1164,14 +1200,14 @@ static int dvb_init(struct saa7134_dev *dev) if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) wprintk("%s: MD7134 DVB-S, no SD1878 " - "found !\n", __FUNCTION__); + "found !\n", __func__); /* we need to open the i2c gate (we know it exists) */ fe = dev->dvb.frontend; fe->ops.i2c_gate_ctrl(fe, 1); if (dvb_attach(isl6405_attach, fe, &dev->i2c_adap, 0x08, 0, 0) == NULL) wprintk("%s: MD7134 DVB-S, no ISL6405 " - "found !\n", __FUNCTION__); + "found !\n", __func__); fe->ops.i2c_gate_ctrl(fe, 0); dev->original_set_voltage = fe->ops.set_voltage; fe->ops.set_voltage = md8800_set_voltage; @@ -1239,8 +1275,20 @@ static int dvb_fini(struct saa7134_dev *dev) /* otherwise we don't detect the tuner on next insmod */ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tda9887_cfg); + } else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) { + if ((dev->eedata[2] != 0x08) && use_frontend) { + /* turn off the 2nd lnb supply */ + u8 data = 0x80; + struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1}; + struct dvb_frontend *fe; + fe = dev->dvb.frontend; + if (fe->ops.i2c_gate_ctrl) { + fe->ops.i2c_gate_ctrl(fe, 1); + i2c_transfer(&dev->i2c_adap, &msg, 1); + fe->ops.i2c_gate_ctrl(fe, 0); + } + } } - videobuf_dvb_unregister(&dev->dvb); return 0; } -- cgit v1.2.3 From 226bf8f0a966fed7e54b85a696c437d9a48c356f Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:28:11 -0300 Subject: V4L/DVB (7393): tda827x: fixed support of tuners with LNA Tuner refactoring broke support of tuners with LNA configurations 1 and 2 for both, analog TV and DVB-T. Additionally, this patch initializes the saa713x gpios defined by the gpiomask at driver init to avoid undefined stated at dvb. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.h | 1 - drivers/media/dvb/frontends/tda827x.c | 163 ++++++++++++++-------------- drivers/media/dvb/frontends/tda827x.h | 4 +- drivers/media/video/saa7134/saa7134-cards.c | 13 ++- drivers/media/video/saa7134/saa7134-core.c | 6 + drivers/media/video/saa7134/saa7134-dvb.c | 160 +++++++++++---------------- drivers/media/video/saa7134/saa7134-video.c | 7 +- drivers/media/video/tda8290.c | 9 +- drivers/media/video/tda8290.h | 2 +- drivers/media/video/tuner-core.c | 2 +- 10 files changed, 172 insertions(+), 195 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index abae84350142..ebb2c5f5a261 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -94,7 +94,6 @@ struct tda1004x_config /* slave address and configuration of the tuner */ u8 tuner_address; - u8 tuner_config; u8 antenna_switch; /* if the board uses another I2c Bridge (tda8290), its address */ diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index 967ac8b28efd..d30d2c9094d9 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -142,7 +142,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe, int i, tuner_freq, if_freq; u32 N; - dprintk("%s:\n", __FUNCTION__); + dprintk("%s:\n", __func__); switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: if_freq = 4000000; @@ -186,7 +186,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe, fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { printk("%s: could not write to tuner at addr: 0x%02x\n", - __FUNCTION__, priv->i2c_addr << 1); + __func__, priv->i2c_addr << 1); return -EIO; } msleep(500); @@ -212,7 +212,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe) struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, .buf = buf, .len = sizeof(buf) }; - dprintk("%s:\n", __FUNCTION__); + dprintk("%s:\n", __func__); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(priv->i2c_adap, &msg, 1); @@ -389,6 +389,79 @@ static struct tda827xa_data tda827xa_analog[] = { { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} }; +static int tda827xa_sleep(struct dvb_frontend *fe) +{ + struct tda827x_priv *priv = fe->tuner_priv; + static u8 buf[] = { 0x30, 0x90 }; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + + dprintk("%s:\n", __func__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + i2c_transfer(priv->i2c_adap, &msg, 1); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (priv->cfg && priv->cfg->sleep) + priv->cfg->sleep(fe); + + return 0; +} + +static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, + struct analog_parameters *params) +{ + struct tda827x_priv *priv = fe->tuner_priv; + unsigned char buf[] = {0x22, 0x01}; + int arg; + int gp_func; + struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + + if (NULL == priv->cfg) { + dprintk("tda827x_config not defined, cannot set LNA gain!\n"); + return; + } + if (priv->cfg->config) { + if (high) + dprintk("setting LNA to high gain\n"); + else + dprintk("setting LNA to low gain\n"); + } + switch (priv->cfg->config) { + case 0: /* no LNA */ + break; + case 1: /* switch is GPIO 0 of tda8290 */ + case 2: + if (params == NULL) { + gp_func = 0; + arg = 0; + } else { + /* turn Vsync on */ + gp_func = 1; + if (params->std & V4L2_STD_MN) + arg = 1; + else + arg = 0; + } + if (priv->cfg->tuner_callback) + priv->cfg->tuner_callback(priv->i2c_adap->algo_data, + gp_func, arg); + buf[1] = high ? 0 : 1; + if (priv->cfg->config == 2) + buf[1] = high ? 1 : 0; + i2c_transfer(priv->i2c_adap, &msg, 1); + break; + case 3: /* switch with GPIO of saa713x */ + if (priv->cfg->tuner_callback) + priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high); + break; + } +} + static int tda827xa_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { @@ -401,9 +474,9 @@ static int tda827xa_set_params(struct dvb_frontend *fe, int i, tuner_freq, if_freq; u32 N; - dprintk("%s:\n", __FUNCTION__); - if (priv->cfg && priv->cfg->lna_gain) - priv->cfg->lna_gain(fe, 1); + dprintk("%s:\n", __func__); + + tda827xa_lna_gain(fe, 1, NULL); msleep(20); switch (params->u.ofdm.bandwidth) { @@ -444,7 +517,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { printk("%s: could not write to tuner at addr: 0x%02x\n", - __FUNCTION__, priv->i2c_addr << 1); + __func__, priv->i2c_addr << 1); return -EIO; } buf[0] = 0x90; @@ -474,8 +547,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, buf[1] >>= 4; dprintk("tda8275a AGC2 gain is: %d\n", buf[1]); if ((buf[1]) < 2) { - if (priv->cfg && priv->cfg->lna_gain) - priv->cfg->lna_gain(fe, 0); + tda827xa_lna_gain(fe, 0, NULL); buf[0] = 0x60; buf[1] = 0x0c; if (fe->ops.i2c_gate_ctrl) @@ -523,73 +595,6 @@ static int tda827xa_set_params(struct dvb_frontend *fe, return 0; } -static int tda827xa_sleep(struct dvb_frontend *fe) -{ - struct tda827x_priv *priv = fe->tuner_priv; - static u8 buf[] = { 0x30, 0x90 }; - struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, - .buf = buf, .len = sizeof(buf) }; - - dprintk("%s:\n", __FUNCTION__); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - i2c_transfer(priv->i2c_adap, &msg, 1); - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - - if (priv->cfg && priv->cfg->sleep) - priv->cfg->sleep(fe); - - return 0; -} - -/* ------------------------------------------------------------------ */ - -static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, - struct analog_parameters *params) -{ - struct tda827x_priv *priv = fe->tuner_priv; - unsigned char buf[] = {0x22, 0x01}; - int arg; - struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, - .buf = buf, .len = sizeof(buf) }; - - if (NULL == priv->cfg) { - dprintk("tda827x_config not defined, cannot set LNA gain!\n"); - return; - } - - if (priv->cfg->config) { - if (high) - dprintk("setting LNA to high gain\n"); - else - dprintk("setting LNA to low gain\n"); - } - switch (*priv->cfg->config) { - case 0: /* no LNA */ - break; - case 1: /* switch is GPIO 0 of tda8290 */ - case 2: - /* turn Vsync on */ - if (params->std & V4L2_STD_MN) - arg = 1; - else - arg = 0; - if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv, 1, arg); - buf[1] = high ? 0 : 1; - if (*priv->cfg->config == 2) - buf[1] = high ? 1 : 0; - i2c_transfer(priv->i2c_adap, &msg, 1); - break; - case 3: /* switch with GPIO of saa713x */ - if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv, 0, high); - break; - } -} static int tda827xa_set_analog_params(struct dvb_frontend *fe, struct analog_parameters *params) @@ -724,7 +729,7 @@ static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) static int tda827x_init(struct dvb_frontend *fe) { struct tda827x_priv *priv = fe->tuner_priv; - dprintk("%s:\n", __FUNCTION__); + dprintk("%s:\n", __func__); if (priv->cfg && priv->cfg->init) priv->cfg->init(fe); @@ -792,7 +797,7 @@ static int tda827x_probe_version(struct dvb_frontend *fe) fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { printk("%s: could not read from tuner at addr: 0x%02x\n", - __FUNCTION__, msg.addr << 1); + __func__, msg.addr << 1); return -EIO; } if ((data & 0x3c) == 0) { @@ -816,7 +821,7 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, { struct tda827x_priv *priv = NULL; - dprintk("%s:\n", __FUNCTION__); + dprintk("%s:\n", __func__); priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL); if (priv == NULL) return NULL; diff --git a/drivers/media/dvb/frontends/tda827x.h b/drivers/media/dvb/frontends/tda827x.h index 92eb65b4012b..cd3032f985cd 100644 --- a/drivers/media/dvb/frontends/tda827x.h +++ b/drivers/media/dvb/frontends/tda827x.h @@ -30,12 +30,12 @@ struct tda827x_config { /* saa7134 - provided callbacks */ - void (*lna_gain) (struct dvb_frontend *fe, int high); int (*init) (struct dvb_frontend *fe); int (*sleep) (struct dvb_frontend *fe); /* interface to tda829x driver */ - unsigned int *config; + unsigned int config; + int switch_addr; int (*tuner_callback) (void *dev, int command, int arg); void (*agcf)(struct dvb_frontend *fe); diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 1b6c7d697f04..bab8498046c8 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5260,12 +5260,13 @@ int saa7134_tuner_callback(void *priv, int command, int arg) { struct i2c_algo_bit_data *i2c_algo = priv; struct saa7134_dev *dev = i2c_algo->data; - - switch (dev->tuner_type) { - case TUNER_PHILIPS_TDA8290: - return saa7134_tda8290_callback(dev, command, arg); - case TUNER_XC2028: - return saa7134_xc2028_callback(dev, command, arg); + if (dev != NULL) { + switch (dev->tuner_type) { + case TUNER_PHILIPS_TDA8290: + return saa7134_tda8290_callback(dev, command, arg); + case TUNER_XC2028: + return saa7134_xc2028_callback(dev, command, arg); + } } return -EINVAL; } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index ed96ce775a9b..599273894f34 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -864,6 +864,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, struct saa7134_dev *dev; struct saa7134_mpeg_ops *mops; int err; + int mask; dev = kzalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) @@ -1061,6 +1062,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (TUNER_ABSENT != dev->tuner_type) saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + if (card(dev).gpiomask != 0) { + mask = card(dev).gpiomask; + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, 0); + } return 0; fail4: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 8e55c7572b4b..f95f5f2fbf72 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -439,8 +439,6 @@ static struct tda1004x_config philips_europa_config = { .request_firmware = philips_tda1004x_request_firmware }; -/* ------------------------------------------------------------------ */ - static struct tda1004x_config medion_cardbus = { .demod_address = 0x08, .invert = 1, @@ -456,47 +454,6 @@ static struct tda1004x_config medion_cardbus = { * tda 1004x based cards with philips silicon tuner */ -static void philips_tda827x_lna_gain(struct dvb_frontend *fe, int high) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->i2c_gate; - u8 config = state->config->tuner_config; - u8 GP00_CF[] = {0x20, 0x01}; - u8 GP00_LEV[] = {0x22, 0x00}; - - struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = GP00_CF, .len = 2}; - if (config) { - if (high) { - dprintk("setting LNA to high gain\n"); - } else { - dprintk("setting LNA to low gain\n"); - } - } - switch (config) { - case 0: /* no LNA */ - break; - case 1: /* switch is GPIO 0 of tda8290 */ - case 2: - /* turn Vsync off */ - saa7134_set_gpio(dev, 22, 0); - GP00_LEV[1] = high ? 0 : 1; - if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { - wprintk("could not access tda8290 at addr: 0x%02x\n", - addr << 1); - return; - } - msg.buf = GP00_LEV; - if (config == 2) - GP00_LEV[1] = high ? 1 : 0; - i2c_transfer(&dev->i2c_adap, &msg, 1); - break; - case 3: /* switch with GPIO of saa713x */ - saa7134_set_gpio(dev, 22, high); - break; - } -} - static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable) { struct tda1004x_state *state = fe->demodulator_priv; @@ -519,8 +476,6 @@ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable) return 0; } -/* ------------------------------------------------------------------ */ - static int philips_tda827x_tuner_init(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; @@ -555,28 +510,57 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe) return 0; } -static struct tda827x_config tda827x_cfg = { - .lna_gain = philips_tda827x_lna_gain, - .init = philips_tda827x_tuner_init, - .sleep = philips_tda827x_tuner_sleep -}; - -static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *tda_conf) +static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf, + struct tda827x_config *tuner_conf) { - dev->dvb.frontend = dvb_attach(tda10046_attach, tda_conf, &dev->i2c_adap); + dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); if (dev->dvb.frontend) { - if (tda_conf->i2c_gate) + if (cdec_conf->i2c_gate) dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - if (dvb_attach(tda827x_attach, dev->dvb.frontend, tda_conf->tuner_address, - &dev->i2c_adap,&tda827x_cfg) == NULL) { + if (dvb_attach(tda827x_attach, dev->dvb.frontend, cdec_conf->tuner_address, + &dev->i2c_adap, tuner_conf) == NULL) { wprintk("no tda827x tuner found at addr: %02x\n", - tda_conf->tuner_address); + cdec_conf->tuner_address); } } } /* ------------------------------------------------------------------ */ +static struct tda827x_config tda827x_cfg_0 = { + .tuner_callback = saa7134_tuner_callback, + .init = philips_tda827x_tuner_init, + .sleep = philips_tda827x_tuner_sleep, + .config = 0, + .switch_addr = 0 +}; + +static struct tda827x_config tda827x_cfg_1 = { + .tuner_callback = saa7134_tuner_callback, + .init = philips_tda827x_tuner_init, + .sleep = philips_tda827x_tuner_sleep, + .config = 1, + .switch_addr = 0x4b +}; + +static struct tda827x_config tda827x_cfg_2 = { + .tuner_callback = saa7134_tuner_callback, + .init = philips_tda827x_tuner_init, + .sleep = philips_tda827x_tuner_sleep, + .config = 2, + .switch_addr = 0x4b +}; + +static struct tda827x_config tda827x_cfg_2_sw42 = { + .tuner_callback = saa7134_tuner_callback, + .init = philips_tda827x_tuner_init, + .sleep = philips_tda827x_tuner_sleep, + .config = 2, + .switch_addr = 0x42 +}; + +/* ------------------------------------------------------------------ */ + static struct tda1004x_config tda827x_lifeview_config = { .demod_address = 0x08, .invert = 1, @@ -599,7 +583,6 @@ static struct tda1004x_config philips_tiger_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 0, .antenna_switch= 1, .request_firmware = philips_tda1004x_request_firmware }; @@ -614,7 +597,6 @@ static struct tda1004x_config cinergy_ht_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 0, .request_firmware = philips_tda1004x_request_firmware }; @@ -628,7 +610,6 @@ static struct tda1004x_config cinergy_ht_pci_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x60, - .tuner_config = 0, .request_firmware = philips_tda1004x_request_firmware }; @@ -642,7 +623,6 @@ static struct tda1004x_config philips_tiger_s_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 2, .antenna_switch= 1, .request_firmware = philips_tda1004x_request_firmware }; @@ -657,7 +637,6 @@ static struct tda1004x_config pinnacle_pctv_310i_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 1, .request_firmware = philips_tda1004x_request_firmware }; @@ -671,7 +650,6 @@ static struct tda1004x_config hauppauge_hvr_1110_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 1, .request_firmware = philips_tda1004x_request_firmware }; @@ -685,7 +663,6 @@ static struct tda1004x_config asus_p7131_dual_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 0, .antenna_switch= 2, .request_firmware = philips_tda1004x_request_firmware }; @@ -724,7 +701,6 @@ static struct tda1004x_config md8800_dvbt_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x60, - .tuner_config = 0, .request_firmware = philips_tda1004x_request_firmware }; @@ -738,7 +714,6 @@ static struct tda1004x_config asus_p7131_4871_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 2, .antenna_switch= 2, .request_firmware = philips_tda1004x_request_firmware }; @@ -753,7 +728,6 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 2, .antenna_switch= 2, .request_firmware = philips_tda1004x_request_firmware }; @@ -768,7 +742,6 @@ static struct tda1004x_config kworld_dvb_t_210_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x61, - .tuner_config = 2, .antenna_switch= 1, .request_firmware = philips_tda1004x_request_firmware }; @@ -783,7 +756,6 @@ static struct tda1004x_config avermedia_super_007_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x4b, .tuner_address = 0x60, - .tuner_config = 0, .antenna_switch= 1, .request_firmware = philips_tda1004x_request_firmware }; @@ -798,7 +770,6 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = { .if_freq = TDA10046_FREQ_045, .i2c_gate = 0x42, .tuner_address = 0x61, - .tuner_config = 2, .antenna_switch = 1, .request_firmware = philips_tda1004x_request_firmware }; @@ -826,9 +797,10 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe) } static struct tda827x_config ads_duo_cfg = { - .lna_gain = philips_tda827x_lna_gain, + .tuner_callback = saa7134_tuner_callback, .init = ads_duo_tuner_init, - .sleep = ads_duo_tuner_sleep + .sleep = ads_duo_tuner_sleep, + .config = 0 }; static struct tda1004x_config ads_tech_duo_config = { @@ -981,7 +953,7 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_FLYDVBTDUO: case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: - configure_tda827x_fe(dev, &tda827x_lifeview_config); + configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0); break; case SAA7134_BOARD_PHILIPS_EUROPA: case SAA7134_BOARD_VIDEOMATE_DVBT_300: @@ -1006,27 +978,27 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_KWORLD_DVBT_210: - configure_tda827x_fe(dev, &kworld_dvb_t_210_config); + configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2); break; case SAA7134_BOARD_PHILIPS_TIGER: - configure_tda827x_fe(dev, &philips_tiger_config); + configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0); break; case SAA7134_BOARD_PINNACLE_PCTV_310i: - configure_tda827x_fe(dev, &pinnacle_pctv_310i_config); + configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1); break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: - configure_tda827x_fe(dev, &hauppauge_hvr_1110_config); + configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1); break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: - configure_tda827x_fe(dev, &asus_p7131_dual_config); + configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0); break; case SAA7134_BOARD_FLYDVBT_LR301: - configure_tda827x_fe(dev, &tda827x_lifeview_config); + configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0); break; case SAA7134_BOARD_FLYDVB_TRIO: if(! use_frontend) { /* terrestrial */ - configure_tda827x_fe(dev, &lifeview_trio_config); - } else { /* satellite */ + configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0); + } else { /* satellite */ dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); if (dev->dvb.frontend) { if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, @@ -1047,19 +1019,19 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap); if (dev->dvb.frontend) { if (dvb_attach(tda827x_attach,dev->dvb.frontend, - ads_tech_duo_config.tuner_address, - &dev->i2c_adap,&ads_duo_cfg) == NULL) { + ads_tech_duo_config.tuner_address, &dev->i2c_adap, + &ads_duo_cfg) == NULL) { wprintk("no tda827x tuner found at addr: %02x\n", ads_tech_duo_config.tuner_address); } } break; case SAA7134_BOARD_TEVION_DVBT_220RF: - configure_tda827x_fe(dev, &tevion_dvbt220rf_config); + configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0); break; case SAA7134_BOARD_MEDION_MD8800_QUADRO: if (!use_frontend) { /* terrestrial */ - configure_tda827x_fe(dev, &md8800_dvbt_config); + configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0); } else { /* satellite */ dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); @@ -1148,25 +1120,25 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_CINERGY_HT_PCMCIA: - configure_tda827x_fe(dev, &cinergy_ht_config); + configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0); break; case SAA7134_BOARD_CINERGY_HT_PCI: - configure_tda827x_fe(dev, &cinergy_ht_pci_config); + configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0); break; case SAA7134_BOARD_PHILIPS_TIGER_S: - configure_tda827x_fe(dev, &philips_tiger_s_config); + configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2); break; case SAA7134_BOARD_ASUS_P7131_4871: - configure_tda827x_fe(dev, &asus_p7131_4871_config); + configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2); break; case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: - configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config); + configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2); break; case SAA7134_BOARD_AVERMEDIA_SUPER_007: - configure_tda827x_fe(dev, &avermedia_super_007_config); + configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0); break; case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: - configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config); + configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42); break; case SAA7134_BOARD_PHILIPS_SNAKE: dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, @@ -1181,10 +1153,10 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_CREATIX_CTX953: - configure_tda827x_fe(dev, &md8800_dvbt_config); + configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0); break; case SAA7134_BOARD_MSI_TVANYWHERE_AD11: - configure_tda827x_fe(dev, &philips_tiger_s_config); + configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2); break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: dev->dvb.frontend = dvb_attach(mt352_attach, diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index ecc5243da57e..a0baf2d0ba7f 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -626,13 +626,8 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) { saa7134_set_decoder(dev); - if (card_in(dev, dev->ctl_input).tv) { - if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290) - && ((card(dev).tuner_config == 1) - || (card(dev).tuner_config == 2))) - saa7134_set_gpio(dev, 22, 5); + if (card_in(dev, dev->ctl_input).tv) saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); - } } static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 6f2449ab46a0..89afb19c9468 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -172,7 +172,7 @@ static void tda8290_set_params(struct dvb_frontend *fe, set_audio(fe, params); if (priv->cfg.config) - tuner_dbg("tda827xa config is 0x%02x\n", *priv->cfg.config); + tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config); tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); @@ -442,8 +442,7 @@ static void tda8290_init_if(struct dvb_frontend *fe) unsigned char set_GP00_CF[] = { 0x20, 0x01 }; unsigned char set_GP01_CF[] = { 0x20, 0x0B }; - if ((priv->cfg.config) && - ((*priv->cfg.config == 1) || (*priv->cfg.config == 2))) + if ((priv->cfg.config == 1) || (priv->cfg.config == 2)) tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2); else tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2); @@ -588,8 +587,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) else priv->ver |= TDA8275A; - tda827x_attach(fe, priv->tda827x_addr, - priv->i2c_props.adap, &priv->cfg); + tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg); + priv->cfg.switch_addr = priv->i2c_props.addr; } if (fe->ops.tuner_ops.init) fe->ops.tuner_ops.init(fe); diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h index dc8ef310b7b2..9dd8b73eb8c6 100644 --- a/drivers/media/video/tda8290.h +++ b/drivers/media/video/tda8290.h @@ -21,7 +21,7 @@ #include "dvb_frontend.h" struct tda829x_config { - unsigned int *lna_cfg; + unsigned int lna_cfg; int (*tuner_callback) (void *dev, int command, int arg); unsigned int probe_tuner:1; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 335a971298a3..4b936b809d78 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -320,7 +320,7 @@ static void tuner_i2c_address_check(struct tuner *t) static void attach_tda829x(struct tuner *t) { struct tda829x_config cfg = { - .lna_cfg = &t->config, + .lna_cfg = t->config, .tuner_callback = t->tuner_callback, }; tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); -- cgit v1.2.3 From 01a7e8e40f37d7d7710407b6c2fd7da1e5993786 Mon Sep 17 00:00:00 2001 From: Alan McIvor Date: Wed, 2 Apr 2008 14:28:11 -0300 Subject: V4L/DVB (7394): saa7134: add number of devices check This patch fixes reported problems when trying to add a 9th device into a system. Signed-off-by: Alan McIvor Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 599273894f34..eec127864fe3 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -866,6 +866,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, int err; int mask; + if (saa7134_devcount == SAA7134_MAXBOARDS) + return -ENOMEM; + dev = kzalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) return -ENOMEM; -- cgit v1.2.3 From 557f721b5e5967441c83bf39a7c63ef61243b14f Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:28:11 -0300 Subject: V4L/DVB (7395): saa7134: start 2nd LND supply of Medion cards only if needed The ISL6405 LNB supply is used on several Creatix / Medion cards. But only the MD8800 needs its second section. So don't start it unless it is needed. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index f95f5f2fbf72..07614a8d8949 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1052,10 +1052,12 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap, 0x08, 0, 0) == NULL) wprintk("%s: Medion Quadro, no ISL6405 " "found !\n", __func__); - /* fire up the 2nd section of the LNB supply since we can't do - this from the other section */ - msg.buf = &data; - i2c_transfer(&dev->i2c_adap, &msg, 1); + if (dev_id == 0x07) { + /* fire up the 2nd section of the LNB supply since + we can't do this from the other section */ + msg.buf = &data; + i2c_transfer(&dev->i2c_adap, &msg, 1); + } fe->ops.i2c_gate_ctrl(fe, 0); dev->original_set_voltage = fe->ops.set_voltage; fe->ops.set_voltage = md8800_set_voltage; @@ -1248,7 +1250,7 @@ static int dvb_fini(struct saa7134_dev *dev) /* otherwise we don't detect the tuner on next insmod */ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tda9887_cfg); } else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) { - if ((dev->eedata[2] != 0x08) && use_frontend) { + if ((dev->eedata[2] == 0x07) && use_frontend) { /* turn off the 2nd lnb supply */ u8 data = 0x80; struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1}; -- cgit v1.2.3 From a6467061412abfed69677e8d16802efe9ab53709 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 2 Apr 2008 14:28:12 -0300 Subject: V4L/DVB (7396): saa7134: fixed pointer in tuner callback The pointer transferred directly points to the saa7134_dev structure Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 3 +-- drivers/media/video/saa7134/saa7134-dvb.c | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index bab8498046c8..b622d979e634 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5258,8 +5258,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, int saa7134_tuner_callback(void *priv, int command, int arg) { - struct i2c_algo_bit_data *i2c_algo = priv; - struct saa7134_dev *dev = i2c_algo->data; + struct saa7134_dev *dev = priv; if (dev != NULL) { switch (dev->tuner_type) { case TUNER_PHILIPS_TDA8290: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 07614a8d8949..e26c3bc2d210 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1199,7 +1199,6 @@ static int dvb_init(struct saa7134_dev *dev) struct xc2028_config cfg = { .i2c_adap = &dev->i2c_adap, .i2c_addr = 0x61, - .video_dev = dev->i2c_adap.algo_data, }; fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); if (!fe) { -- cgit v1.2.3 From c0b01dcffe23ac40a029ee1d492a59f362eb287a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:12 -0300 Subject: V4L/DVB (7398): Adds an error if priv argument of tuner_callback is NULL Adds a consistency check to avoid OOPS, if tuner_callback priv argument is NULL. Also, simplifies callback codes on cx88. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 55 +++++++++++++++-------------- drivers/media/video/saa7134/saa7134-cards.c | 3 ++ 2 files changed, 32 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 603b3664381a..6b83e3457b70 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2090,11 +2090,9 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) /* ------------------------------------------------------------------- */ /* some Divco specific stuff */ -static int cx88_dvico_xc2028_callback(void *priv, int command, int arg) +static int cx88_dvico_xc2028_callback(struct cx88_core *core, + int command, int arg) { - struct i2c_algo_bit_data *i2c_algo = priv; - struct cx88_core *core = i2c_algo->data; - switch (command) { case XC2028_TUNER_RESET: cx_write(MO_GP0_IO, 0x101000); @@ -2112,11 +2110,9 @@ static int cx88_dvico_xc2028_callback(void *priv, int command, int arg) /* ----------------------------------------------------------------------- */ /* some Geniatech specific stuff */ -static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mode) +static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core, + int command, int mode) { - struct i2c_algo_bit_data *i2c_algo = priv; - struct cx88_core *core = i2c_algo->data; - switch (command) { case XC2028_TUNER_RESET: switch (INPUT(core->input).type) { @@ -2143,11 +2139,9 @@ static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mod /* ------------------------------------------------------------------- */ /* some Divco specific stuff */ -static int cx88_pv_8000gt_callback(void *priv, int command, int arg) +static int cx88_pv_8000gt_callback(struct cx88_core *core, + int command, int arg) { - struct i2c_algo_bit_data *i2c_algo = priv; - struct cx88_core *core = i2c_algo->data; - switch (command) { case XC2028_TUNER_RESET: cx_write(MO_GP2_IO, 0xcf7); @@ -2198,21 +2192,20 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) } } -static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) +static int cx88_xc2028_tuner_callback(struct cx88_core *core, + int command, int arg) { - struct i2c_algo_bit_data *i2c_algo = priv; - struct cx88_core *core = i2c_algo->data; - /* Board-specific callbacks */ switch (core->boardnr) { case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: - return cx88_xc3028_geniatech_tuner_callback(priv, command, arg); + return cx88_xc3028_geniatech_tuner_callback(core, + command, arg); case CX88_BOARD_PROLINK_PV_8000GT: - return cx88_pv_8000gt_callback(priv, command, arg); + return cx88_pv_8000gt_callback(core, command, arg); case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - return cx88_dvico_xc2028_callback(priv, command, arg); + return cx88_dvico_xc2028_callback(core, command, arg); } switch (command) { @@ -2246,11 +2239,9 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both * * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */ -static int cx88_xc5000_tuner_callback(void *priv, int command, int arg) +static int cx88_xc5000_tuner_callback(struct cx88_core *core, + int command, int arg) { - struct i2c_algo_bit_data *i2c_algo = priv; - struct cx88_core *core = i2c_algo->data; - switch (core->boardnr) { case CX88_BOARD_PINNACLE_PCTV_HD_800i: if (command == 0) { /* This is the reset command from xc5000 */ @@ -2284,15 +2275,27 @@ static int cx88_xc5000_tuner_callback(void *priv, int command, int arg) int cx88_tuner_callback(void *priv, int command, int arg) { struct i2c_algo_bit_data *i2c_algo = priv; - struct cx88_core *core = i2c_algo->data; + struct cx88_core *core; + + if (!i2c_algo) { + printk(KERN_ERR "cx88: Error - i2c private data undefined.\n"); + return -EINVAL; + } + + core = i2c_algo->data; + + if (!core) { + printk(KERN_ERR "cx88: Error - device struct undefined.\n"); + return -EINVAL; + } switch (core->board.tuner_type) { case TUNER_XC2028: info_printk(core, "Calling XC2028/3028 callback\n"); - return cx88_xc2028_tuner_callback(priv, command, arg); + return cx88_xc2028_tuner_callback(core, command, arg); case TUNER_XC5000: info_printk(core, "Calling XC5000 callback\n"); - return cx88_xc5000_tuner_callback(priv, command, arg); + return cx88_xc5000_tuner_callback(core, command, arg); } err_printk(core, "Error: Calling callback for tuner %d\n", core->board.tuner_type); diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index b622d979e634..c323ca005f72 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5266,6 +5266,9 @@ int saa7134_tuner_callback(void *priv, int command, int arg) case TUNER_XC2028: return saa7134_xc2028_callback(dev, command, arg); } + } else { + printk(KERN_ERR "saa7134: Error - device struct undefined.\n"); + return -EINVAL; } return -EINVAL; } -- cgit v1.2.3 From 7190bc3642ad3fc4d6f6b9260bc98089d2006cc9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:13 -0300 Subject: V4L/DVB (7399): Removes video_dev from tuner-xc2028 config struct The video_dev parameter, on tuner-xc2028 were used to pass i2c private data to tuner_callback. Since the driver already have a pointer to i2c_adap->algo_data, uses this instead. This parameter were used also as a magic number to idenfity if two drivers are trying to register the same xc3028 tuner. This occurs with boards with DVB support, where both DVB and V4L drivers will share the same tuner. Instead of using the algo_data as a private number, after this patch, the driver will use i2c_adap->dev, with seems more consistent. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 1 - drivers/media/video/cx23885/cx23885-dvb.c | 1 - drivers/media/video/cx88/cx88-dvb.c | 2 -- drivers/media/video/tuner-core.c | 1 - drivers/media/video/tuner-xc2028.c | 15 ++++++++++++--- 5 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index c58365005ac1..8aff70217635 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -509,7 +509,6 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) struct xc2028_config cfg = { .i2c_adap = &adap->dev->i2c_adap, .i2c_addr = 0x61, - .video_dev = adap->dev, .callback = dvico_bluebird_xc2028_callback, }; static struct xc2028_ctrl ctl = { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 22381de7359e..5549a9d73a5c 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -297,7 +297,6 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, - .video_dev = port, .callback = cx23885_hvr1500_xc3028_callback, }; static struct xc2028_ctrl ctl = { diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 37ebfcc6be55..bbbde6d7dab9 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -458,7 +458,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, .i2c_addr = addr, - .video_dev = dev->core->i2c_adap.algo_data, }; if (!dev->dvb.frontend) { @@ -780,7 +779,6 @@ static int dvb_register(struct cx8802_dev *dev) struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, .i2c_addr = 0x61, - .video_dev = dev->core, .callback = cx88_pci_nano_callback, }; static struct xc2028_ctrl ctl = { diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 4b936b809d78..225e8f8df1a5 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -419,7 +419,6 @@ static void set_type(struct i2c_client *c, unsigned int type, struct xc2028_config cfg = { .i2c_adap = t->i2c->adapter, .i2c_addr = t->i2c->addr, - .video_dev = c->adapter->algo_data, .callback = t->tuner_callback, }; if (!xc2028_attach(&t->fe, &cfg)) { diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index a9caae1af49d..0b5ba67a4da5 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -1155,7 +1155,7 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, if (debug) printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n"); - if (NULL == cfg || NULL == cfg->video_dev) + if (NULL == cfg) return NULL; if (!fe) { @@ -1163,13 +1163,19 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, return NULL; } - video_dev = cfg->video_dev; + video_dev = cfg->i2c_adap->algo_data; + + if (debug) + printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev); mutex_lock(&xc2028_list_mutex); list_for_each_entry(priv, &xc2028_list, xc2028_list) { - if (priv->video_dev == cfg->video_dev) { + if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) { video_dev = NULL; + if (debug) + printk(KERN_DEBUG "xc2028: reusing device\n"); + break; } } @@ -1197,6 +1203,9 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, fe->tuner_priv = priv; priv->count++; + if (debug) + printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count); + memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops, sizeof(xc2028_dvb_tuner_ops)); -- cgit v1.2.3 From c915bdb39c5e037ee263a50251bb10fe3477f817 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Wed, 2 Apr 2008 14:28:14 -0300 Subject: V4L/DVB (7401): radio-si470x: unplugging fixed This patch fixes several kernel oops, when unplugging device while it is in use: Basically the patch delays freeing of the internal variables in si470x_usb_driver_disconnect, until the the last user closed the device in si470x_fops_release. This was implemented a while ago with the help of Oliver Neukum. I tested the patch five times (unplugging while in use) without oops coming from the radio-si470x driver anymore. A remaining oops was coming from the usbaudio driver, but this is someone else task. Hopefully this fixed all unplugging issues. Signed-off-by: Tobias Lorenz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-si470x.c | 57 ++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 649f14d2c013..4ad88ee616fd 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -85,6 +85,7 @@ * Oliver Neukum * Version 1.0.7 * - usb autosuspend support + * - unplugging fixed * * ToDo: * - add seeking support @@ -97,10 +98,10 @@ /* driver definitions */ #define DRIVER_AUTHOR "Tobias Lorenz " #define DRIVER_NAME "radio-si470x" -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6) +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7) #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" -#define DRIVER_VERSION "1.0.6" +#define DRIVER_VERSION "1.0.7" /* kernel includes */ @@ -424,6 +425,7 @@ struct si470x_device { /* driver management */ unsigned int users; + unsigned char disconnected; /* Silabs internal registers (0..15) */ unsigned short registers[RADIO_REGISTER_NUM]; @@ -439,6 +441,12 @@ struct si470x_device { }; +/* + * Lock to prevent kfree of data before all users have releases the device. + */ +static DEFINE_MUTEX(open_close_lock); + + /* * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, * 62.5 kHz otherwise. @@ -577,7 +585,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio) usb_rcvintpipe(radio->usbdev, 1), (void *) &buf, sizeof(buf), &size, usb_timeout); if (size != sizeof(buf)) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: " + printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " "return size differs: %d != %zu\n", size, sizeof(buf)); if (retval < 0) printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " @@ -875,6 +883,8 @@ static void si470x_work(struct work_struct *work) struct si470x_device *radio = container_of(work, struct si470x_device, work.work); + if (radio->disconnected) + return; if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) return; @@ -1001,13 +1011,21 @@ static int si470x_fops_open(struct inode *inode, struct file *file) static int si470x_fops_release(struct inode *inode, struct file *file) { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); - int retval; + int retval = 0; if (!radio) return -ENODEV; + mutex_lock(&open_close_lock); radio->users--; if (radio->users == 0) { + if (radio->disconnected) { + video_unregister_device(radio->videodev); + kfree(radio->buffer); + kfree(radio); + goto done; + } + /* stop rds reception */ cancel_delayed_work_sync(&radio->work); @@ -1016,10 +1034,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file) retval = si470x_stop(radio); usb_autopm_put_interface(radio->intf); - return retval; } - return 0; +done: + mutex_unlock(&open_close_lock); + return retval; } @@ -1157,6 +1176,9 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv, { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + if (radio->disconnected) + return -EIO; + switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: ctrl->value = radio->registers[SYSCONFIG2] & @@ -1181,6 +1203,9 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv, struct si470x_device *radio = video_get_drvdata(video_devdata(file)); int retval; + if (radio->disconnected) + return -EIO; + switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; @@ -1243,6 +1268,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, struct si470x_device *radio = video_get_drvdata(video_devdata(file)); int retval; + if (radio->disconnected) + return -EIO; if (tuner->index > 0) return -EINVAL; @@ -1299,6 +1326,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, struct si470x_device *radio = video_get_drvdata(video_devdata(file)); int retval; + if (radio->disconnected) + return -EIO; if (tuner->index > 0) return -EINVAL; @@ -1324,6 +1353,9 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv, { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + if (radio->disconnected) + return -EIO; + freq->type = V4L2_TUNER_RADIO; freq->frequency = si470x_get_freq(radio); @@ -1340,6 +1372,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, struct si470x_device *radio = video_get_drvdata(video_devdata(file)); int retval; + if (radio->disconnected) + return -EIO; if (freq->type != V4L2_TUNER_RADIO) return -EINVAL; @@ -1510,11 +1544,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf) { struct si470x_device *radio = usb_get_intfdata(intf); + mutex_lock(&open_close_lock); + radio->disconnected = 1; cancel_delayed_work_sync(&radio->work); usb_set_intfdata(intf, NULL); - video_unregister_device(radio->videodev); - kfree(radio->buffer); - kfree(radio); + if (radio->users == 0) { + video_unregister_device(radio->videodev); + kfree(radio->buffer); + kfree(radio); + } + mutex_unlock(&open_close_lock); } -- cgit v1.2.3 From e477406da73499ee46644e06d487bb1127b7b12e Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 2 Apr 2008 14:28:15 -0300 Subject: V4L/DVB (7402): add macro validation for v4l_compat_ioctl32 Added macro CONFIG_COMPAT for v4l_compat_ioctl32. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/dsbr100.c | 2 ++ drivers/media/radio/miropcm20-radio.c | 2 ++ drivers/media/radio/radio-aimslab.c | 2 ++ drivers/media/radio/radio-aztech.c | 2 ++ drivers/media/radio/radio-cadet.c | 2 ++ drivers/media/radio/radio-gemtek-pci.c | 2 ++ drivers/media/radio/radio-gemtek.c | 2 ++ drivers/media/radio/radio-maestro.c | 2 ++ drivers/media/radio/radio-maxiradio.c | 2 ++ drivers/media/radio/radio-rtrack2.c | 2 ++ drivers/media/radio/radio-sf16fmi.c | 2 ++ drivers/media/radio/radio-sf16fmr2.c | 2 ++ drivers/media/radio/radio-si470x.c | 2 ++ drivers/media/radio/radio-terratec.c | 2 ++ drivers/media/radio/radio-trust.c | 2 ++ drivers/media/radio/radio-typhoon.c | 2 ++ drivers/media/radio/radio-zoltrix.c | 2 ++ drivers/media/video/arv.c | 2 ++ drivers/media/video/bw-qcam.c | 2 ++ drivers/media/video/c-qcam.c | 2 ++ drivers/media/video/cpia.c | 2 ++ drivers/media/video/cpia2/cpia2_v4l.c | 2 ++ drivers/media/video/et61x251/et61x251_core.c | 2 ++ drivers/media/video/meye.c | 2 ++ drivers/media/video/ov511.c | 2 ++ drivers/media/video/pms.c | 2 ++ drivers/media/video/pwc/pwc-if.c | 2 ++ drivers/media/video/saa5249.c | 2 ++ drivers/media/video/se401.c | 2 ++ drivers/media/video/sn9c102/sn9c102_core.c | 2 ++ drivers/media/video/stradis.c | 2 ++ drivers/media/video/stv680.c | 2 ++ drivers/media/video/usbvideo/usbvideo.c | 2 ++ drivers/media/video/usbvideo/vicam.c | 2 ++ drivers/media/video/w9966.c | 2 ++ drivers/media/video/w9968cf.c | 2 ++ drivers/media/video/zc0301/zc0301_core.c | 2 ++ drivers/media/video/zoran_driver.c | 2 ++ 38 files changed, 76 insertions(+) (limited to 'drivers') diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 36c0e3651502..4e3f83e4e48f 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -438,7 +438,9 @@ static const struct file_operations usb_dsbr100_fops = { .open = usb_dsbr100_open, .release = usb_dsbr100_close, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c index 3ae56fef8c92..09fe6f1cdf14 100644 --- a/drivers/media/radio/miropcm20-radio.c +++ b/drivers/media/radio/miropcm20-radio.c @@ -221,7 +221,9 @@ static const struct file_operations pcm20_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = pcm20_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index f0a67e93d7fd..edfa117521c7 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -383,7 +383,9 @@ static const struct file_operations rtrack_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 9b1f7a99dac0..46cdb549eac7 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -346,7 +346,9 @@ static const struct file_operations aztech_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 265c4ea95502..b14db53ea456 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -563,7 +563,9 @@ static const struct file_operations cadet_fops = { .read = cadet_read, .ioctl = video_ioctl2, .poll = cadet_poll, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 99a323131333..de49be971480 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -368,7 +368,9 @@ static const struct file_operations gemtek_pci_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 246422b49267..81f6aeb1cd11 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -397,7 +397,9 @@ static const struct file_operations gemtek_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek }; diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index bc51f4d23a5a..bddd3c409aa9 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -100,7 +100,9 @@ static const struct file_operations maestro_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 8e184cfc1c94..0133ecf3e040 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -103,7 +103,9 @@ static const struct file_operations maxiradio_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 82aedfc95d4f..070802103dc3 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -288,7 +288,9 @@ static const struct file_operations rtrack2_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 53e114857377..66e052fd3909 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -288,7 +288,9 @@ static const struct file_operations fmi_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 7bf7d534c042..b0ccf7cb5952 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -404,7 +404,9 @@ static const struct file_operations fmr2_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 4ad88ee616fd..77354ca6e8e9 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -1051,7 +1051,9 @@ static const struct file_operations si470x_fops = { .read = si470x_fops_read, .poll = si470x_fops_poll, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .open = si470x_fops_open, .release = si470x_fops_release, }; diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 535ffe8c8102..acc32080e9bd 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -360,7 +360,9 @@ static const struct file_operations terratec_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index c11981fed827..4ebdfbadeb9c 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -340,7 +340,9 @@ static const struct file_operations trust_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 02e3a2f05eee..8b9888337bd1 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -340,7 +340,9 @@ static const struct file_operations typhoon_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 203f4373eeb8..43773c56c62f 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -401,7 +401,9 @@ static const struct file_operations zoltrix_fops = .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index e4d891b29f63..8c7d1958856b 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -747,7 +747,9 @@ static const struct file_operations ar_fops = { .release = video_exclusive_release, .read = ar_read, .ioctl = ar_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 40a8e92a01b9..b364adaae78d 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -898,7 +898,9 @@ static const struct file_operations qcam_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = qcam_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .read = qcam_read, .llseek = no_llseek, }; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index d4d5adfb0351..2c85ced61150 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -689,7 +689,9 @@ static const struct file_operations qcam_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = qcam_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .read = qcam_read, .llseek = no_llseek, }; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 7c630f5ee725..2a81376ef503 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -3792,7 +3792,9 @@ static const struct file_operations cpia_fops = { .read = cpia_read, .mmap = cpia_mmap, .ioctl = cpia_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index e378abec806d..7ce2789fa976 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -1927,7 +1927,9 @@ static const struct file_operations fops_template = { .poll = cpia2_v4l_poll, .ioctl = cpia2_ioctl, .llseek = no_llseek, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .mmap = cpia2_mmap, }; diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 32ebb71097b5..5e749c528a62 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2523,7 +2523,9 @@ static const struct file_operations et61x251_fops = { .open = et61x251_open, .release = et61x251_release, .ioctl = et61x251_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .read = et61x251_read, .poll = et61x251_poll, .mmap = et61x251_mmap, diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index caa9a7ac6184..61c980193c10 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1761,7 +1761,9 @@ static const struct file_operations meye_fops = { .release = meye_release, .mmap = meye_mmap, .ioctl = meye_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .poll = meye_poll, .llseek = no_llseek, }; diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index d55d5800efb4..7e69e4393fe9 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -4660,7 +4660,9 @@ static const struct file_operations ov511_fops = { .read = ov51x_v4l1_read, .mmap = ov51x_v4l1_mmap, .ioctl = ov51x_v4l1_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 4a6c5723f7cc..51b1461d8fb6 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -885,7 +885,9 @@ static const struct file_operations pms_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = pms_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .read = pms_read, .llseek = no_llseek, }; diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index b6240a1a606f..d2941c5656ca 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -159,7 +159,9 @@ static const struct file_operations pwc_fops = { .poll = pwc_video_poll, .mmap = pwc_video_mmap, .ioctl = pwc_video_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; static struct video_device pwc_template = { diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index f55d6e85f20f..ec8c65dc8408 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -701,7 +701,9 @@ static const struct file_operations saa_fops = { .open = saa5249_open, .release = saa5249_release, .ioctl = saa5249_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index f17a539857d4..7b8cd30437c3 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -1224,7 +1224,9 @@ static const struct file_operations se401_fops = { .read = se401_read, .mmap = se401_mmap, .ioctl = se401_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; static struct video_device se401_template = { diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 94f393eebd51..898ae5f578cb 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -3224,7 +3224,9 @@ static const struct file_operations sn9c102_fops = { .open = sn9c102_open, .release = sn9c102_release, .ioctl = sn9c102_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .read = sn9c102_read, .poll = sn9c102_poll, .mmap = sn9c102_mmap, diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 3118dd322b24..c109511f21ea 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -1906,7 +1906,9 @@ static const struct file_operations saa_fops = { .open = saa_open, .release = saa_release, .ioctl = saa_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .read = saa_read, .llseek = no_llseek, .write = saa_write, diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 1542797c048f..78730294454e 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -1394,7 +1394,9 @@ static const struct file_operations stv680_fops = { .read = stv680_read, .mmap = stv680_mmap, .ioctl = stv680_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; static struct video_device stv680_template = { diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index 7f3cdc9a0624..300188097de6 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -946,7 +946,9 @@ static const struct file_operations usbvideo_fops = { .read = usbvideo_v4l_read, .mmap = usbvideo_v4l_mmap, .ioctl = usbvideo_v4l_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; static const struct video_device usbvideo_template = { diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index da1ba0211108..4d4795ae3bc7 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -1066,7 +1066,9 @@ static const struct file_operations vicam_fops = { .read = vicam_read, .mmap = vicam_mmap, .ioctl = vicam_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, }; diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index cc8c8246c30e..cdb396d9203c 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -188,7 +188,9 @@ static const struct file_operations w9966_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = w9966_v4l_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .read = w9966_v4l_read, .llseek = no_llseek, }; diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index cce23d24e6fc..840522442d07 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -3461,7 +3461,9 @@ static const struct file_operations w9968cf_fops = { .release = w9968cf_release, .read = w9968cf_read, .ioctl = w9968cf_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .mmap = w9968cf_mmap, .llseek = no_llseek, }; diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index af357cbcb9bb..363dd2b9475c 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -1925,7 +1925,9 @@ static const struct file_operations zc0301_fops = { .open = zc0301_open, .release = zc0301_release, .ioctl = zc0301_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .read = zc0301_read, .poll = zc0301_poll, .mmap = zc0301_mmap, diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 5cca61cb8ba8..8c0a379071e5 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -4644,7 +4644,9 @@ static const struct file_operations zoran_fops = { .open = zoran_open, .release = zoran_close, .ioctl = zoran_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek, .read = zoran_read, .write = zoran_write, -- cgit v1.2.3 From edfdf678f1d320edf80eb36d53dcf3abccb81e1f Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 2 Apr 2008 14:28:15 -0300 Subject: V4L/DVB (7404): saa7134.h: Remove unnecessary validation Removed unnecessary VIDIOC_G_PRIORITY validation. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ba88a1093d14..3394c47cea60 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -388,9 +388,7 @@ struct saa7134_fh { unsigned int radio; enum v4l2_buf_type type; unsigned int resources; -#ifdef VIDIOC_G_PRIORITY enum v4l2_priority prio; -#endif /* video overlay */ struct v4l2_window win; @@ -462,9 +460,7 @@ struct saa7134_dev { struct list_head devlist; struct mutex lock; spinlock_t slock; -#ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; -#endif /* workstruct for loading modules */ struct work_struct request_module_wk; -- cgit v1.2.3 From 293230cdbfa6a251e0b87144764cc698cd93721b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 2 Apr 2008 14:28:15 -0300 Subject: V4L/DVB (7406): soc-camera: improve separation between soc_camera_ops and soc_camera_device In case of muliple cameras, handled by the same driver, they can support Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 24 ++++++++++++------------ drivers/media/video/mt9v022.c | 26 ++++++++++++-------------- drivers/media/video/soc_camera.c | 20 ++++++++++---------- include/media/soc_camera.h | 8 ++++---- 4 files changed, 38 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index acb5454b57eb..2ea133e8a625 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -410,11 +410,15 @@ const struct v4l2_queryctrl mt9m001_controls[] = { } }; -static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); -static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); +static int mt9m001_video_probe(struct soc_camera_device *); +static void mt9m001_video_remove(struct soc_camera_device *); +static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); +static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9m001_ops = { .owner = THIS_MODULE, + .probe = mt9m001_video_probe, + .remove = mt9m001_video_remove, .init = mt9m001_init, .release = mt9m001_release, .start_capture = mt9m001_start_capture, @@ -423,8 +427,6 @@ static struct soc_camera_ops mt9m001_ops = { .try_fmt_cap = mt9m001_try_fmt_cap, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, - .formats = NULL, /* Filled in later depending on the */ - .num_formats = 0, /* camera type and data widths */ .controls = mt9m001_controls, .num_controls = ARRAY_SIZE(mt9m001_controls), .get_control = mt9m001_get_control, @@ -573,19 +575,19 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) case 0x8411: case 0x8421: mt9m001->model = V4L2_IDENT_MT9M001C12ST; - mt9m001_ops.formats = mt9m001_colour_formats; + icd->formats = mt9m001_colour_formats; if (mt9m001->client->dev.platform_data) - mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_colour_formats); + icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats); else - mt9m001_ops.num_formats = 1; + icd->num_formats = 1; break; case 0x8431: mt9m001->model = V4L2_IDENT_MT9M001C12STM; - mt9m001_ops.formats = mt9m001_monochrome_formats; + icd->formats = mt9m001_monochrome_formats; if (mt9m001->client->dev.platform_data) - mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); + icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); else - mt9m001_ops.num_formats = 1; + icd->num_formats = 1; break; default: ret = -ENODEV; @@ -646,8 +648,6 @@ static int mt9m001_probe(struct i2c_client *client) /* Second stage probe - when a capture adapter is there */ icd = &mt9m001->icd; - icd->probe = mt9m001_video_probe; - icd->remove = mt9m001_video_remove; icd->ops = &mt9m001_ops; icd->control = &client->dev; icd->x_min = 20; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index a2f161dcc72d..d4b9e2744343 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -506,13 +506,15 @@ const struct v4l2_queryctrl mt9v022_controls[] = { } }; -static int mt9v022_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl); -static int mt9v022_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl); +static int mt9v022_video_probe(struct soc_camera_device *); +static void mt9v022_video_remove(struct soc_camera_device *); +static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); +static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9v022_ops = { .owner = THIS_MODULE, + .probe = mt9v022_video_probe, + .remove = mt9v022_video_remove, .init = mt9v022_init, .release = mt9v022_release, .start_capture = mt9v022_start_capture, @@ -521,8 +523,6 @@ static struct soc_camera_ops mt9v022_ops = { .try_fmt_cap = mt9v022_try_fmt_cap, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, - .formats = NULL, /* Filled in later depending on the */ - .num_formats = 0, /* sensor type and data widths */ .controls = mt9v022_controls, .num_controls = ARRAY_SIZE(mt9v022_controls), .get_control = mt9v022_get_control, @@ -705,19 +705,19 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) !strcmp("color", sensor_type))) { ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; - mt9v022_ops.formats = mt9v022_colour_formats; + icd->formats = mt9v022_colour_formats; if (mt9v022->client->dev.platform_data) - mt9v022_ops.num_formats = ARRAY_SIZE(mt9v022_colour_formats); + icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats); else - mt9v022_ops.num_formats = 1; + icd->num_formats = 1; } else { ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; - mt9v022_ops.formats = mt9v022_monochrome_formats; + icd->formats = mt9v022_monochrome_formats; if (mt9v022->client->dev.platform_data) - mt9v022_ops.num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); + icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); else - mt9v022_ops.num_formats = 1; + icd->num_formats = 1; } if (ret >= 0) @@ -773,8 +773,6 @@ static int mt9v022_probe(struct i2c_client *client) i2c_set_clientdata(client, mt9v022); icd = &mt9v022->icd; - icd->probe = mt9v022_video_probe; - icd->remove = mt9v022_video_remove; icd->ops = &mt9v022_ops; icd->control = &client->dev; icd->x_min = 1; diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 91e1ab36fe5d..4af38d444e0c 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -38,9 +38,9 @@ format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) { unsigned int i; - for (i = 0; i < icd->ops->num_formats; i++) - if (icd->ops->formats[i].fourcc == fourcc) - return icd->ops->formats + i; + for (i = 0; i < icd->num_formats; i++) + if (icd->formats[i].fourcc == fourcc) + return icd->formats + i; return NULL; } @@ -384,10 +384,10 @@ static int soc_camera_enum_fmt_cap(struct file *file, void *priv, WARN_ON(priv != file->private_data); - if (f->index >= icd->ops->num_formats) + if (f->index >= icd->num_formats) return -EINVAL; - format = &icd->ops->formats[f->index]; + format = &icd->formats[f->index]; strlcpy(f->description, format->name, sizeof(f->description)); f->pixelformat = format->fourcc; @@ -701,7 +701,7 @@ static int soc_camera_probe(struct device *dev) to_soc_camera_host(icd->dev.parent); int ret; - if (!icd->probe) + if (!icd->ops->probe) return -ENODEV; /* We only call ->add() here to activate and probe the camera. @@ -710,7 +710,7 @@ static int soc_camera_probe(struct device *dev) if (ret < 0) return ret; - ret = icd->probe(icd); + ret = icd->ops->probe(icd); if (ret >= 0) { const struct v4l2_queryctrl *qctrl; @@ -731,8 +731,8 @@ static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); - if (icd->remove) - icd->remove(icd); + if (icd->ops->remove) + icd->ops->remove(icd); return 0; } @@ -928,7 +928,7 @@ int soc_camera_video_start(struct soc_camera_device *icd) vdev->vidioc_s_register = soc_camera_s_register; #endif - icd->current_fmt = &icd->ops->formats[0]; + icd->current_fmt = &icd->formats[0]; err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); if (err < 0) { diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 3e48e435b21a..7a2fa3ed849e 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -38,8 +38,8 @@ struct soc_camera_device { struct soc_camera_ops *ops; struct video_device *vdev; const struct soc_camera_data_format *current_fmt; - int (*probe)(struct soc_camera_device *icd); - void (*remove)(struct soc_camera_device *icd); + const struct soc_camera_data_format *formats; + int num_formats; struct module *owner; /* soc_camera.c private count. Only accessed with video_lock held */ int use_count; @@ -106,6 +106,8 @@ struct soc_camera_data_format { struct soc_camera_ops { struct module *owner; + int (*probe)(struct soc_camera_device *); + void (*remove)(struct soc_camera_device *); int (*init)(struct soc_camera_device *); int (*release)(struct soc_camera_device *); int (*start_capture)(struct soc_camera_device *); @@ -121,8 +123,6 @@ struct soc_camera_ops { int (*get_register)(struct soc_camera_device *, struct v4l2_register *); int (*set_register)(struct soc_camera_device *, struct v4l2_register *); #endif - const struct soc_camera_data_format *formats; - int num_formats; int (*get_control)(struct soc_camera_device *, struct v4l2_control *); int (*set_control)(struct soc_camera_device *, struct v4l2_control *); const struct v4l2_queryctrl *controls; -- cgit v1.2.3 From 5bff03b3479005e69f9ff0b130e2992b15aff3d7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:15 -0300 Subject: V4L/DVB (7407): tuner-simple: add module options to specify rf input Add module options to tuner-simple, called "atv_input" and "dtv_input" to specify which rf input to use on devices with multiple rf inputs. If the module option is not specified, then the driver will autoselect the rf input, as per previous behavior. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 59 ++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 273030bda6d9..8d6d2c803f92 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -17,10 +17,22 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); +#define TUNER_SIMPLE_MAX 64 +static unsigned int simple_devcount; + static int offset; module_param(offset, int, 0664); MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner"); +static unsigned int atv_input[TUNER_SIMPLE_MAX] = \ + { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 }; +static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \ + { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 }; +module_param_array(atv_input, int, NULL, 0644); +module_param_array(dtv_input, int, NULL, 0644); +MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect"); +MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect"); + /* ---------------------------------------------------------------------- */ /* tv standard selection for Temic 4046 FM5 @@ -92,6 +104,7 @@ static DEFINE_MUTEX(tuner_simple_list_mutex); static LIST_HEAD(hybrid_tuner_instance_list); struct tuner_simple_priv { + unsigned int nr; u16 last_div; struct tuner_i2c_props i2c_props; @@ -364,7 +377,6 @@ static int simple_std_setup(struct dvb_frontend *fe, *cb &= ~0x03; if (!(params->std & V4L2_STD_ATSC)) *cb |= 2; - /* FIXME: input */ break; case TUNER_MICROTUNE_4042FI5: @@ -396,10 +408,11 @@ static int simple_std_setup(struct dvb_frontend *fe, tuner_warn("i2c i/o error: rc == %d " "(should be 2)\n", rc); priv->i2c_props.addr = tuneraddr; - /* FIXME: input */ break; } } + if (atv_input[priv->nr]) + simple_set_rf_input(fe, config, cb, atv_input[priv->nr]); return 0; } @@ -770,16 +783,19 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, { unsigned int new_rf; - switch (params->u.vsb.modulation) { - case QAM_64: - case QAM_256: - new_rf = 1; - break; - case VSB_8: - default: - new_rf = 0; - break; - } + if (dtv_input[priv->nr]) + new_rf = dtv_input[priv->nr]; + else + switch (params->u.vsb.modulation) { + case QAM_64: + case QAM_256: + new_rf = 1; + break; + case VSB_8: + default: + new_rf = 0; + break; + } simple_set_rf_input(fe, &buf[2], &buf[3], new_rf); break; } @@ -1025,6 +1041,7 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, priv->type = type; priv->tun = &tuners[type]; + priv->nr = simple_devcount++; break; default: fe->tuner_priv = priv; @@ -1038,6 +1055,24 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, tuner_info("type set to %d (%s)\n", type, priv->tun->name); + if ((debug) || ((atv_input[priv->nr] > 0) || + (dtv_input[priv->nr] > 0))) { + if (0 == atv_input[priv->nr]) + tuner_info("tuner %d atv rf input will be " + "autoselected\n", priv->nr); + else + tuner_info("tuner %d atv rf input will be " + "set to input %d (insmod option)\n", + priv->nr, atv_input[priv->nr]); + if (0 == dtv_input[priv->nr]) + tuner_info("tuner %d dtv rf input will be " + "autoselected\n", priv->nr); + else + tuner_info("tuner %d dtv rf input will be " + "set to input %d (insmod option)\n", + priv->nr, dtv_input[priv->nr]); + } + strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name, sizeof(fe->ops.tuner_ops.info.name)); -- cgit v1.2.3 From af5c9add8b71c62b0bf6155ebb367a12e881f20e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:16 -0300 Subject: V4L/DVB (7408): use tuner-simple for Thomson DTT 761X digital tuning support Convert cx88-dvb to use tuner-simple instead of dvb-pll for Thomson DTT 761X Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index bbbde6d7dab9..49ada3667d93 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -47,6 +47,7 @@ #include "isl6421.h" #include "tuner-xc2028.h" #include "tuner-xc2028-types.h" +#include "tuner-simple.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -630,9 +631,9 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - DVB_PLL_THOMSON_DTT761X); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_THOMSON_DTT761X); } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: @@ -672,9 +673,9 @@ static int dvb_register(struct cx8802_dev *dev) &fusionhdtv_3_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - DVB_PLL_THOMSON_DTT761X); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_THOMSON_DTT761X); } } break; -- cgit v1.2.3 From c44e30d670efb522dc8c904123d622a9fd963ea2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:16 -0300 Subject: V4L/DVB (7409): use tuner-simple for Microtune 4042 FI5 digital tuning support Convert cx88-dvb to use tuner-simple instead of dvb-pll for Microtune 4042 FI5 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 49ada3667d93..de49de3a41f2 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -653,9 +653,9 @@ static int dvb_register(struct cx8802_dev *dev) &fusionhdtv_3_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - DVB_PLL_MICROTUNE_4042); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_MICROTUNE_4042FI5); } } break; -- cgit v1.2.3 From 5b7d73c5491527aea0a8a75d6353ec8884869e91 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:16 -0300 Subject: V4L/DVB (7410): use tuner-simple for Thomson FE6600 digital tuning support Convert cx88-dvb to use tuner-simple instead of dvb-pll for Thomson FE6600 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index de49de3a41f2..9c0d20aef27a 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -604,9 +604,9 @@ static int dvb_register(struct cx8802_dev *dev) &dvico_fusionhdtv_hybrid, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - DVB_PLL_THOMSON_FE6600); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_THOMSON_FE6600); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: -- cgit v1.2.3 From 67925dff2bb7332455693544e0f4b494e26d9cb0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:16 -0300 Subject: V4L/DVB (7411): use tuner-simple for Philips FCV1236D digital tuning support Convert dvb-bt8xx to use tuner-simple instead of dvb-pll for Philips FCV1236D Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 5 +++-- drivers/media/dvb/bt8xx/dvb-bt8xx.h | 1 + drivers/media/video/bt8xx/bttv.h | 1 + drivers/media/video/bt8xx/bttvp.h | 1 - 4 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 209356be5828..6d8b84490fa8 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -692,8 +692,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) case BTTV_BOARD_PC_HDTV: card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter); if (card->fe != NULL) - dvb_attach(dvb_pll_attach, card->fe, 0x61, - card->i2c_adapter, DVB_PLL_FCV1236D); + dvb_attach(simple_tuner_attach, card->fe, + card->i2c_adapter, 0x61, + TUNER_PHILIPS_FCV1236D); break; } diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 436880e68672..25a23c3c7c66 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -39,6 +39,7 @@ #include "lgdt330x.h" #include "zl10353.h" #include "dvb-pll.h" +#include "tuner-simple.h" struct dvb_bt8xx_card { struct mutex lock; diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 0c859d949c78..f2393202904b 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -19,6 +19,7 @@ #include #include #include +#include /* ---------------------------------------------------------- */ /* exported by bttv-cards.c */ diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 1305d315cfc5..03816b73f847 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -42,7 +42,6 @@ #include #include -#include #include #include -- cgit v1.2.3 From 52f68115ad7f16b5cbca75860e761b6320ad906a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:17 -0300 Subject: V4L/DVB (7412): use tuner-simple for LG TDVS-H06xF digital tuning support Convert cx88-dvb, dvb-bt8xx, b2c2-flexcop, cxusb and cx23885 to use tuner-simple instead of dvb-pll for LG TDVS-H06xF Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/Makefile | 1 + drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 6 +++++- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 5 +++-- drivers/media/dvb/dvb-usb/cxusb.c | 7 +++++-- drivers/media/video/cx23885/cx23885-dvb.c | 6 ++++-- drivers/media/video/cx88/cx88-dvb.c | 17 +++++++++++------ 6 files changed, 29 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile index e97ff60a1eff..7d5334106d5a 100644 --- a/drivers/media/dvb/b2c2/Makefile +++ b/drivers/media/dvb/b2c2/Makefile @@ -13,3 +13,4 @@ b2c2-flexcop-usb-objs = flexcop-usb.o obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ +EXTRA_CFLAGS += -Idrivers/media/video/ diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 0378fd646591..441ffdf0d9c9 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -5,6 +5,8 @@ * * see flexcop.c for copyright information. */ +#include + #include "flexcop.h" #include "stv0299.h" @@ -15,6 +17,7 @@ #include "mt312.h" #include "lgdt330x.h" #include "dvb-pll.h" +#include "tuner-simple.h" /* lnb control */ @@ -506,7 +509,8 @@ int flexcop_frontend_init(struct flexcop_device *fc) /* try the air atsc 3nd generation (lgdt3303) */ if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC3; - dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, DVB_PLL_LG_TDVS_H06XF); + dvb_attach(simple_tuner_attach, fc->fe, + &fc->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF); info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); } else /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 6d8b84490fa8..65081f161544 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -609,8 +609,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) lgdt330x_reset(card); card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); if (card->fe != NULL) { - dvb_attach(dvb_pll_attach, card->fe, 0x61, - card->i2c_adapter, DVB_PLL_LG_TDVS_H06XF); + dvb_attach(simple_tuner_attach, card->fe, + card->i2c_adapter, 0x61, + TUNER_LG_TDVS_H06XF); dprintk ("dvb_bt8xx: lgdt330x detected\n"); } break; diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 8aff70217635..8b4243a1fca8 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -23,6 +23,8 @@ * * see Documentation/dvb/README.dvb-usb for more information */ +#include + #include "cxusb.h" #include "cx22702.h" @@ -32,6 +34,7 @@ #include "zl10353.h" #include "tuner-xc2028.h" #include "tuner-xc2028-types.h" +#include "tuner-simple.h" /* debug */ static int dvb_usb_cxusb_debug; @@ -477,8 +480,8 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) { - dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap, - DVB_PLL_LG_TDVS_H06XF); + dvb_attach(simple_tuner_attach, adap->fe, + &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF); return 0; } diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 5549a9d73a5c..42e6bdd25354 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -39,6 +39,7 @@ #include "dvb-pll.h" #include "tuner-xc2028.h" #include "tuner-xc2028-types.h" +#include "tuner-simple.h" static unsigned int debug; @@ -271,8 +272,9 @@ static int dvb_register(struct cx23885_tsport *port) &fusionhdtv_5_express, &i2c_bus->i2c_adap); if (port->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, port->dvb.frontend, 0x61, - &i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF); + dvb_attach(simple_tuner_attach, port->dvb.frontend, + &i2c_bus->i2c_adap, 0x61, + TUNER_LG_TDVS_H06XF); } break; case CX23885_BOARD_HAUPPAUGE_HVR1500Q: diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 9c0d20aef27a..0b19384c72f1 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -48,6 +48,7 @@ #include "tuner-xc2028.h" #include "tuner-xc2028-types.h" #include "tuner-simple.h" +#include "tda9887.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -693,9 +694,11 @@ static int dvb_register(struct cx8802_dev *dev) &fusionhdtv_5_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - DVB_PLL_LG_TDVS_H06XF); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_LG_TDVS_H06XF); + dvb_attach(tda9887_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x43); } } break; @@ -713,9 +716,11 @@ static int dvb_register(struct cx8802_dev *dev) &pchdtv_hd5500, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - DVB_PLL_LG_TDVS_H06XF); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_LG_TDVS_H06XF); + dvb_attach(tda9887_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x43); } } break; -- cgit v1.2.3 From 263f97d5fab12c10889c59e3aef27343702f9c8b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:17 -0300 Subject: V4L/DVB (7413): use tuner-simple for Philips FMD1216ME digital tuning support Convert cxusb, cx88-dvb and saa7134-dvb to use tuner-simple instead of dvb-pll for Philips FMD1216ME Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 5 +++-- drivers/media/video/cx88/cx88-dvb.c | 10 ++++++---- drivers/media/video/saa7134/saa7134-dvb.c | 11 +++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 8b4243a1fca8..b75b2b7a1330 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -453,8 +453,9 @@ static struct mt352_config cxusb_mt352_xc3028_config = { /* Callbacks for DVB USB */ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) { - dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap, - DVB_PLL_FMD1216ME); + dvb_attach(simple_tuner_attach, adap->fe, + &adap->dev->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3); return 0; } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 0b19384c72f1..676cf7ce08f2 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -525,8 +525,9 @@ static int dvb_register(struct cx8802_dev *dev) &hauppauge_hvr_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, DVB_PLL_FMD1216ME); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: @@ -593,8 +594,9 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &dev->vp3054->adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, DVB_PLL_FMD1216ME); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3); } #else printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index e26c3bc2d210..5b65aa255bb1 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -47,6 +47,7 @@ #include "isl6421.h" #include "isl6405.h" #include "lnbp21.h" +#include "tuner-simple.h" MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -938,8 +939,9 @@ static int dvb_init(struct saa7134_dev *dev) &medion_cardbus, &dev->i2c_adap); if (dev->dvb.frontend) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address, - &dev->i2c_adap, DVB_PLL_FMD1216ME); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->i2c_adap, medion_cardbus.tuner_address, + TUNER_PHILIPS_FMD1216ME_MK3); } break; case SAA7134_BOARD_PHILIPS_TOUGH: @@ -1108,8 +1110,9 @@ static int dvb_init(struct saa7134_dev *dev) dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; - dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address, - &dev->i2c_adap, DVB_PLL_FMD1216ME); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->i2c_adap, medion_cardbus.tuner_address, + TUNER_PHILIPS_FMD1216ME_MK3); } break; case SAA7134_BOARD_VIDEOMATE_DVBT_200A: -- cgit v1.2.3 From 4b573afb97e17a04c9e8be2a3ed552b71b39febe Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:17 -0300 Subject: V4L/DVB (7414): use tuner-simple for Philips TD1316 digital tuning support Convert saa7134-dvb to use tuner-simple instead of dvb-pll for Philips TD1316 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 5b65aa255bb1..16ea09a87283 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -930,8 +930,9 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777, &dev->i2c_adap); if (dev->dvb.frontend) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, DVB_PLL_PHILIPS_TD1316); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->i2c_adap, 0x61, + TUNER_PHILIPS_TD1316); } break; case SAA7134_BOARD_MD7134: -- cgit v1.2.3 From 2c316f1489a211aa244a88a52bb3c0eb2ee68616 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:18 -0300 Subject: V4L/DVB (7415): use tuner-simple for Philips TUV1236D digital tuning support Convert cx88-dvb and saa7134-dvb to use tuner-simple instead of dvb-pll for Philips TUV1236D Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 5 +++-- drivers/media/video/saa7134/saa7134-dvb.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 676cf7ce08f2..8dca20b944dd 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -731,8 +731,9 @@ static int dvb_register(struct cx8802_dev *dev) &ati_hdtvwonder, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, DVB_PLL_TUV1236D); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_PHILIPS_TUV1236D); } break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 16ea09a87283..9f8730bc6e5f 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1085,8 +1085,9 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, &dev->i2c_adap); if (dev->dvb.frontend) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, DVB_PLL_TUV1236D); + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->i2c_adap, 0x61, + TUNER_PHILIPS_TUV1236D); } break; case SAA7134_BOARD_FLYDVBS_LR300: -- cgit v1.2.3 From 6c029b9395f380130856b60e4135c648888c4f39 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:19 -0300 Subject: V4L/DVB (7416): dvb-pll: remove support for Thomson dtt7610 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 13 ------------- drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index decf798994e9..b6ecf53abf6f 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -112,18 +112,6 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { }, }; -static struct dvb_pll_desc dvb_pll_thomson_dtt7610 = { - .name = "Thomson dtt7610", - .min = 44000000, - .max = 958000000, - .iffreq= 44000000, - .count = 3, - .entries = { - { 157250000, 62500, 0x8e, 0x39 }, - { 454000000, 62500, 0x8e, 0x3a }, - { 999999999, 62500, 0x8e, 0x3c }, - }, -}; static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params) @@ -584,7 +572,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_UNDEFINED] = NULL, [DVB_PLL_THOMSON_DTT7579] = &dvb_pll_thomson_dtt7579, [DVB_PLL_THOMSON_DTT759X] = &dvb_pll_thomson_dtt759x, - [DVB_PLL_THOMSON_DTT7610] = &dvb_pll_thomson_dtt7610, [DVB_PLL_LG_Z201] = &dvb_pll_lg_z201, [DVB_PLL_MICROTUNE_4042] = &dvb_pll_microtune_4042, [DVB_PLL_THOMSON_DTT761X] = &dvb_pll_thomson_dtt761x, diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index e93a8104052b..e2e59d7477da 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -11,7 +11,6 @@ #define DVB_PLL_UNDEFINED 0 #define DVB_PLL_THOMSON_DTT7579 1 #define DVB_PLL_THOMSON_DTT759X 2 -#define DVB_PLL_THOMSON_DTT7610 3 #define DVB_PLL_LG_Z201 4 #define DVB_PLL_MICROTUNE_4042 5 #define DVB_PLL_THOMSON_DTT761X 6 -- cgit v1.2.3 From 65021b86cacfe93db4f0dce9441aafd086ac6034 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:19 -0300 Subject: V4L/DVB (7417): dvb-pll: remove support for Thomson dtt761x Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 15 --------------- drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b6ecf53abf6f..5e41dbb6fd70 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -166,20 +166,6 @@ static struct dvb_pll_desc dvb_pll_microtune_4042 = { }, }; -static struct dvb_pll_desc dvb_pll_thomson_dtt761x = { - /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ - .name = "Thomson dtt761x", - .min = 57000000, - .max = 863000000, - .iffreq= 44000000, - .count = 3, - .initdata = tua603x_agc103, - .entries = { - { 147000000, 62500, 0x8e, 0x39 }, - { 417000000, 62500, 0x8e, 0x3a }, - { 999999999, 62500, 0x8e, 0x3c }, - }, -}; static struct dvb_pll_desc dvb_pll_unknown_1 = { .name = "unknown 1", /* used by dntv live dvb-t */ @@ -574,7 +560,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_THOMSON_DTT759X] = &dvb_pll_thomson_dtt759x, [DVB_PLL_LG_Z201] = &dvb_pll_lg_z201, [DVB_PLL_MICROTUNE_4042] = &dvb_pll_microtune_4042, - [DVB_PLL_THOMSON_DTT761X] = &dvb_pll_thomson_dtt761x, [DVB_PLL_UNKNOWN_1] = &dvb_pll_unknown_1, [DVB_PLL_TUA6010XS] = &dvb_pll_tua6010xs, [DVB_PLL_ENV57H1XD5] = &dvb_pll_env57h1xd5, diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index e2e59d7477da..ecaa38051080 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -13,7 +13,6 @@ #define DVB_PLL_THOMSON_DTT759X 2 #define DVB_PLL_LG_Z201 4 #define DVB_PLL_MICROTUNE_4042 5 -#define DVB_PLL_THOMSON_DTT761X 6 #define DVB_PLL_UNKNOWN_1 7 #define DVB_PLL_TUA6010XS 8 #define DVB_PLL_ENV57H1XD5 9 -- cgit v1.2.3 From 392086f1ce92ad5bd9655c4493d4632a8bb3ee06 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:19 -0300 Subject: V4L/DVB (7418): dvb-pll: remove support for Microtune 4042 FI5 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 14 -------------- drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 5e41dbb6fd70..f50e1de2401b 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -153,19 +153,6 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = { }, }; -static struct dvb_pll_desc dvb_pll_microtune_4042 = { - .name = "Microtune 4042 FI5", - .min = 57000000, - .max = 858000000, - .iffreq= 44000000, - .count = 3, - .entries = { - { 162000000, 62500, 0x8e, 0xa1 }, - { 457000000, 62500, 0x8e, 0x91 }, - { 999999999, 62500, 0x8e, 0x31 }, - }, -}; - static struct dvb_pll_desc dvb_pll_unknown_1 = { .name = "unknown 1", /* used by dntv live dvb-t */ @@ -559,7 +546,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_THOMSON_DTT7579] = &dvb_pll_thomson_dtt7579, [DVB_PLL_THOMSON_DTT759X] = &dvb_pll_thomson_dtt759x, [DVB_PLL_LG_Z201] = &dvb_pll_lg_z201, - [DVB_PLL_MICROTUNE_4042] = &dvb_pll_microtune_4042, [DVB_PLL_UNKNOWN_1] = &dvb_pll_unknown_1, [DVB_PLL_TUA6010XS] = &dvb_pll_tua6010xs, [DVB_PLL_ENV57H1XD5] = &dvb_pll_env57h1xd5, diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index ecaa38051080..f37f477d07f0 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -12,7 +12,6 @@ #define DVB_PLL_THOMSON_DTT7579 1 #define DVB_PLL_THOMSON_DTT759X 2 #define DVB_PLL_LG_Z201 4 -#define DVB_PLL_MICROTUNE_4042 5 #define DVB_PLL_UNKNOWN_1 7 #define DVB_PLL_TUA6010XS 8 #define DVB_PLL_ENV57H1XD5 9 -- cgit v1.2.3 From 3d632b05e1950c3d0096da2218c922c80898a138 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:19 -0300 Subject: V4L/DVB (7419): dvb-pll: remove support for Thomson FE6600 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 15 --------------- drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index f50e1de2401b..b29505e75bb9 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -480,20 +480,6 @@ static struct dvb_pll_desc dvb_pll_philips_td1316 = { }, }; -/* FE6600 used on DViCO Hybrid */ -static struct dvb_pll_desc dvb_pll_thomson_fe6600 = { - .name = "Thomson FE6600", - .min = 44250000, - .max = 858000000, - .iffreq= 36125000, - .count = 4, - .entries = { - { 250000000, 166667, 0xb4, 0x12 }, - { 455000000, 166667, 0xfe, 0x11 }, - { 775500000, 166667, 0xbc, 0x18 }, - { 999999999, 166667, 0xf4, 0x18 }, - } -}; static void opera1_bw(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params) @@ -559,7 +545,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv, [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261, [DVB_PLL_PHILIPS_TD1316] = &dvb_pll_philips_td1316, - [DVB_PLL_THOMSON_FE6600] = &dvb_pll_thomson_fe6600, [DVB_PLL_OPERA1] = &dvb_pll_opera1, [DVB_PLL_FCV1236D] = &dvb_pll_fcv1236d, }; diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index f37f477d07f0..b4b6a7ec258c 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -25,7 +25,6 @@ #define DVB_PLL_SAMSUNG_TBMV 17 #define DVB_PLL_PHILIPS_SD1878_TDA8261 18 #define DVB_PLL_PHILIPS_TD1316 19 -#define DVB_PLL_THOMSON_FE6600 20 #define DVB_PLL_OPERA1 21 #define DVB_PLL_FCV1236D 22 -- cgit v1.2.3 From d4eee1724f880da27de95010362a656a5c8d3731 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:20 -0300 Subject: V4L/DVB (7420): dvb-pll: remove support for Philips FCV1236D Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 18 ------------------ drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b29505e75bb9..60801f75edb6 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -507,23 +507,6 @@ static struct dvb_pll_desc dvb_pll_opera1 = { } }; -/* Philips FCV1236D - */ -static struct dvb_pll_desc dvb_pll_fcv1236d = { -/* Bit_0: RF Input select - * Bit_1: 0=digital, 1=analog - */ - .name = "Philips FCV1236D", - .min = 53000000, - .max = 803000000, - .iffreq= 44000000, - .count = 3, - .entries = { - { 159000000, 62500, 0x8e, 0xa0 }, - { 453000000, 62500, 0x8e, 0x90 }, - { 999999999, 62500, 0x8e, 0x30 }, - }, -}; /* ----------------------------------------------------------- */ @@ -546,7 +529,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261, [DVB_PLL_PHILIPS_TD1316] = &dvb_pll_philips_td1316, [DVB_PLL_OPERA1] = &dvb_pll_opera1, - [DVB_PLL_FCV1236D] = &dvb_pll_fcv1236d, }; /* ----------------------------------------------------------- */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index b4b6a7ec258c..df9aab9bd497 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -26,7 +26,6 @@ #define DVB_PLL_PHILIPS_SD1878_TDA8261 18 #define DVB_PLL_PHILIPS_TD1316 19 #define DVB_PLL_OPERA1 21 -#define DVB_PLL_FCV1236D 22 /** * Attach a dvb-pll to the supplied frontend structure. -- cgit v1.2.3 From 5f2fd7abe584a3e8bc074a07a8f5b49000a7bd8a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:20 -0300 Subject: V4L/DVB (7421): dvb-pll: remove support for LG TDVS-H06xF Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 27 --------------------------- drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 28 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 60801f75edb6..7a25f872c094 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -80,16 +80,6 @@ struct dvb_pll_desc { /* ----------------------------------------------------------- */ /* descriptions */ -/* Set AGC TOP value to 103 dBuV: - 0x80 = Control Byte - 0x40 = 250 uA charge pump (irrelevant) - 0x18 = Aux Byte to follow - 0x06 = 64.5 kHz divider (irrelevant) - 0x01 = Disable Vt (aka sleep) - - 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA) - 0x50 = AGC Take over point = 103 dBuV */ -static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 }; /* 0x04 = 166.67 kHz divider @@ -262,22 +252,6 @@ static struct dvb_pll_desc dvb_pll_tua6034 = { }, }; -/* Infineon TUA6034 - * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F - */ -static struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = { - .name = "LG TDVS-H06xF", - .min = 54000000, - .max = 863000000, - .iffreq= 44000000, - .initdata = tua603x_agc103, - .count = 3, - .entries = { - { 165000000, 62500, 0xce, 0x01 }, - { 450000000, 62500, 0xce, 0x02 }, - { 999999999, 62500, 0xce, 0x04 }, - }, -}; /* Philips FMD1216ME * used in Medion Hybrid PCMCIA card and USB Box @@ -519,7 +493,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_TUA6010XS] = &dvb_pll_tua6010xs, [DVB_PLL_ENV57H1XD5] = &dvb_pll_env57h1xd5, [DVB_PLL_TUA6034] = &dvb_pll_tua6034, - [DVB_PLL_LG_TDVS_H06XF] = &dvb_pll_lg_tdvs_h06xf, [DVB_PLL_TDA665X] = &dvb_pll_tda665x, [DVB_PLL_FMD1216ME] = &dvb_pll_fmd1216me, [DVB_PLL_TDED4] = &dvb_pll_tded4, diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index df9aab9bd497..ec50671907a1 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -16,7 +16,6 @@ #define DVB_PLL_TUA6010XS 8 #define DVB_PLL_ENV57H1XD5 9 #define DVB_PLL_TUA6034 10 -#define DVB_PLL_LG_TDVS_H06XF 11 #define DVB_PLL_TDA665X 12 #define DVB_PLL_FMD1216ME 13 #define DVB_PLL_TDED4 14 -- cgit v1.2.3 From f4abc449997a9f37c7b6c9fa39927566805bf12d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:20 -0300 Subject: V4L/DVB (7422): dvb-pll: remove support for Philips FMD1216ME Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 38 ----------------------------------- drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 39 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 7a25f872c094..7735e7484e78 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -81,12 +81,6 @@ struct dvb_pll_desc { /* descriptions */ -/* 0x04 = 166.67 kHz divider - - 0x80 = AGC Time constant 50ms Iagc = 9 uA - 0x20 = AGC Take over point = 112 dBuV */ -static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 }; - static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { .name = "Thomson dtt7579", .min = 177000000, @@ -253,37 +247,6 @@ static struct dvb_pll_desc dvb_pll_tua6034 = { }; -/* Philips FMD1216ME - * used in Medion Hybrid PCMCIA card and USB Box - */ -static void fmd1216me_bw(struct dvb_frontend *fe, u8 *buf, - const struct dvb_frontend_parameters *params) -{ - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ && - params->frequency >= 158870000) - buf[3] |= 0x08; -} - -static struct dvb_pll_desc dvb_pll_fmd1216me = { - .name = "Philips FMD1216ME", - .min = 50870000, - .max = 858000000, - .iffreq= 36125000, - .set = fmd1216me_bw, - .initdata = tua603x_agc112, - .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, - .count = 7, - .entries = { - { 143870000, 166667, 0xbc, 0x41 }, - { 158870000, 166667, 0xf4, 0x41 }, - { 329870000, 166667, 0xbc, 0x42 }, - { 441870000, 166667, 0xf4, 0x42 }, - { 625870000, 166667, 0xbc, 0x44 }, - { 803870000, 166667, 0xf4, 0x44 }, - { 999999999, 166667, 0xfc, 0x44 }, - } -}; - /* ALPS TDED4 * used in Nebula-Cards and USB boxes */ @@ -494,7 +457,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_ENV57H1XD5] = &dvb_pll_env57h1xd5, [DVB_PLL_TUA6034] = &dvb_pll_tua6034, [DVB_PLL_TDA665X] = &dvb_pll_tda665x, - [DVB_PLL_FMD1216ME] = &dvb_pll_fmd1216me, [DVB_PLL_TDED4] = &dvb_pll_tded4, [DVB_PLL_TUV1236D] = &dvb_pll_tuv1236d, [DVB_PLL_TDHU2] = &dvb_pll_tdhu2, diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index ec50671907a1..48cd41fac1e1 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -17,7 +17,6 @@ #define DVB_PLL_ENV57H1XD5 9 #define DVB_PLL_TUA6034 10 #define DVB_PLL_TDA665X 12 -#define DVB_PLL_FMD1216ME 13 #define DVB_PLL_TDED4 14 #define DVB_PLL_TUV1236D 15 #define DVB_PLL_TDHU2 16 -- cgit v1.2.3 From cda368690c3b8b79ab0eb27975cfc9c6acde5738 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:20 -0300 Subject: V4L/DVB (7423): dvb-pll: remove support for Philips TD1316 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 43 ----------------------------------- drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 44 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 7735e7484e78..b2491f106cef 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -374,48 +374,6 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = { }, }; -/* - * Philips TD1316 Tuner. - */ -static void td1316_bw(struct dvb_frontend *fe, u8 *buf, - const struct dvb_frontend_parameters *params) -{ - u8 band; - - /* determine band */ - if (params->frequency < 161000000) - band = 1; - else if (params->frequency < 444000000) - band = 2; - else - band = 4; - - buf[3] |= band; - - /* setup PLL filter */ - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) - buf[3] |= 1 << 3; -} - -static struct dvb_pll_desc dvb_pll_philips_td1316 = { - .name = "Philips TD1316", - .min = 87000000, - .max = 895000000, - .iffreq= 36166667, - .set = td1316_bw, - .count = 9, - .entries = { - { 93834000, 166667, 0xca, 0x60}, - { 123834000, 166667, 0xca, 0xa0}, - { 163834000, 166667, 0xca, 0xc0}, - { 253834000, 166667, 0xca, 0x60}, - { 383834000, 166667, 0xca, 0xa0}, - { 443834000, 166667, 0xca, 0xc0}, - { 583834000, 166667, 0xca, 0x60}, - { 793834000, 166667, 0xca, 0xa0}, - { 858834000, 166667, 0xca, 0xe0}, - }, -}; static void opera1_bw(struct dvb_frontend *fe, u8 *buf, @@ -462,7 +420,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_TDHU2] = &dvb_pll_tdhu2, [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv, [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261, - [DVB_PLL_PHILIPS_TD1316] = &dvb_pll_philips_td1316, [DVB_PLL_OPERA1] = &dvb_pll_opera1, }; diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 48cd41fac1e1..8736ccb9954b 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -22,7 +22,6 @@ #define DVB_PLL_TDHU2 16 #define DVB_PLL_SAMSUNG_TBMV 17 #define DVB_PLL_PHILIPS_SD1878_TDA8261 18 -#define DVB_PLL_PHILIPS_TD1316 19 #define DVB_PLL_OPERA1 21 /** -- cgit v1.2.3 From 15414999f830b778441474a3b30a635cc087e6c6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:21 -0300 Subject: V4L/DVB (7424): dvb-pll: remove support for Philips TUV1236D Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 49 ----------------------------------- drivers/media/dvb/frontends/dvb-pll.h | 1 - 2 files changed, 50 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b2491f106cef..288ecb29425e 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -289,54 +289,6 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = { } }; -/* Philips TUV1236D - * used in ATI HDTV Wonder - */ -static void tuv1236d_rf(struct dvb_frontend *fe, u8 *buf, - const struct dvb_frontend_parameters *params) -{ - struct dvb_pll_priv *priv = fe->tuner_priv; - unsigned int new_rf = input[priv->nr]; - - if ((new_rf == 0) || (new_rf > 2)) { - switch (params->u.vsb.modulation) { - case QAM_64: - case QAM_256: - new_rf = 1; - break; - case VSB_8: - default: - new_rf = 2; - } - } - - switch (new_rf) { - case 1: - buf[3] |= 0x08; - break; - case 2: - buf[3] &= ~0x08; - break; - default: - printk(KERN_WARNING - "%s: unhandled rf input selection: %d", - __FUNCTION__, new_rf); - } -} - -static struct dvb_pll_desc dvb_pll_tuv1236d = { - .name = "Philips TUV1236D", - .min = 54000000, - .max = 864000000, - .iffreq= 44000000, - .set = tuv1236d_rf, - .count = 3, - .entries = { - { 157250000, 62500, 0xc6, 0x41 }, - { 454000000, 62500, 0xc6, 0x42 }, - { 999999999, 62500, 0xc6, 0x44 }, - }, -}; /* Samsung TBMV30111IN / TBMV30712IN1 * used in Air2PC ATSC - 2nd generation (nxt2002) @@ -416,7 +368,6 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_TUA6034] = &dvb_pll_tua6034, [DVB_PLL_TDA665X] = &dvb_pll_tda665x, [DVB_PLL_TDED4] = &dvb_pll_tded4, - [DVB_PLL_TUV1236D] = &dvb_pll_tuv1236d, [DVB_PLL_TDHU2] = &dvb_pll_tdhu2, [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv, [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261, diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 8736ccb9954b..704ea46b466e 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -18,7 +18,6 @@ #define DVB_PLL_TUA6034 10 #define DVB_PLL_TDA665X 12 #define DVB_PLL_TDED4 14 -#define DVB_PLL_TUV1236D 15 #define DVB_PLL_TDHU2 16 #define DVB_PLL_SAMSUNG_TBMV 17 #define DVB_PLL_PHILIPS_SD1878_TDA8261 18 -- cgit v1.2.3 From 53fa91c5024f5697fe239bb52271017dbc0e35b3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:21 -0300 Subject: V4L/DVB (7425): dvb-pll: remove dead code remove #if 0'd support for: Philips TUV1236D Philips TD1316 Philips FMD1216ME LG TDVS-H06xF Philips FCV1236D Thomson FE6600 Microtune 4042 FI5 Thomson dtt761x Support for these tuners has been moved into the 'tuner-simple' module. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 288ecb29425e..72ef6bc5e3f9 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -80,7 +80,6 @@ struct dvb_pll_desc { /* ----------------------------------------------------------- */ /* descriptions */ - static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { .name = "Thomson dtt7579", .min = 177000000, @@ -96,7 +95,6 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { }, }; - static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params) { @@ -137,7 +135,6 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = { }, }; - static struct dvb_pll_desc dvb_pll_unknown_1 = { .name = "unknown 1", /* used by dntv live dvb-t */ .min = 174000000, @@ -246,7 +243,6 @@ static struct dvb_pll_desc dvb_pll_tua6034 = { }, }; - /* ALPS TDED4 * used in Nebula-Cards and USB boxes */ @@ -289,7 +285,6 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = { } }; - /* Samsung TBMV30111IN / TBMV30712IN1 * used in Air2PC ATSC - 2nd generation (nxt2002) */ @@ -326,8 +321,6 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = { }, }; - - static void opera1_bw(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params) { @@ -354,7 +347,6 @@ static struct dvb_pll_desc dvb_pll_opera1 = { } }; - /* ----------------------------------------------------------- */ static struct dvb_pll_desc *pll_list[] = { -- cgit v1.2.3 From 4dc667b67ba725e8a6a430ec6d55b5fb2244c106 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:21 -0300 Subject: V4L/DVB (7426): dvb-pll: renumber remaining description id's Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 704ea46b466e..435146d9fa12 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -11,17 +11,17 @@ #define DVB_PLL_UNDEFINED 0 #define DVB_PLL_THOMSON_DTT7579 1 #define DVB_PLL_THOMSON_DTT759X 2 -#define DVB_PLL_LG_Z201 4 -#define DVB_PLL_UNKNOWN_1 7 -#define DVB_PLL_TUA6010XS 8 -#define DVB_PLL_ENV57H1XD5 9 -#define DVB_PLL_TUA6034 10 -#define DVB_PLL_TDA665X 12 -#define DVB_PLL_TDED4 14 -#define DVB_PLL_TDHU2 16 -#define DVB_PLL_SAMSUNG_TBMV 17 -#define DVB_PLL_PHILIPS_SD1878_TDA8261 18 -#define DVB_PLL_OPERA1 21 +#define DVB_PLL_LG_Z201 3 +#define DVB_PLL_UNKNOWN_1 4 +#define DVB_PLL_TUA6010XS 5 +#define DVB_PLL_ENV57H1XD5 6 +#define DVB_PLL_TUA6034 7 +#define DVB_PLL_TDA665X 8 +#define DVB_PLL_TDED4 9 +#define DVB_PLL_TDHU2 10 +#define DVB_PLL_SAMSUNG_TBMV 11 +#define DVB_PLL_PHILIPS_SD1878_TDA8261 12 +#define DVB_PLL_OPERA1 13 /** * Attach a dvb-pll to the supplied frontend structure. -- cgit v1.2.3 From 23608bd3a04adff25a16b3ebaea918ed9c43dc03 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:21 -0300 Subject: V4L/DVB (7427): dvb-pll: remove rf input module options The ability to select RF input was a supported feature only available on Philips TUV1236d and Philips FCV1236d. This feature, along with support for the tuners that used it, was moved into the tuner-simple module. This can now be removed from dvb-pll. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 72ef6bc5e3f9..a054894ff481 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -48,10 +48,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -static unsigned int input[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = 0 }; -module_param_array(input, int, NULL, 0644); -MODULE_PARM_DESC(input,"specify rf input choice, 0 for autoselect (default)"); - static unsigned int id[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED }; module_param_array(id, int, NULL, 0644); @@ -609,20 +605,6 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, id[priv->nr] == pll_desc_id ? "insmod option" : "autodetected"); } - if ((debug) || (input[priv->nr] > 0)) { - printk("dvb-pll[%d]", priv->nr); - if (i2c != NULL) - printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr); - printk(": tuner rf input will be "); - switch (input[priv->nr]) { - case 0: - printk("autoselected\n"); - break; - default: - printk("set to input %d (insmod option)\n", - input[priv->nr]); - } - } return fe; } -- cgit v1.2.3 From dd8b2b66379465537933d78136c17fcf75c4b248 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:22 -0300 Subject: V4L/DVB (7429): tda18271: write EP3 thru MD3 for image rejection low band initialization Both the tda18271 c1 and c2 parts only need EP3 through MD3 to be written for the image rejection calibration's low band initialization. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-common.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c index bbfc22a5f6db..84d430c52854 100644 --- a/drivers/media/dvb/frontends/tda18271-common.c +++ b/drivers/media/dvb/frontends/tda18271-common.c @@ -355,14 +355,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) regs[R_MD2] = 0x08; regs[R_MD3] = 0x00; - switch (priv->id) { - case TDA18271HDC1: - tda18271_write_regs(fe, R_EP3, 11); - break; - case TDA18271HDC2: - tda18271_write_regs(fe, R_EP3, 12); - break; - }; + tda18271_write_regs(fe, R_EP3, 11); if ((priv->id) == TDA18271HDC2) { /* main pll cp source on */ @@ -404,6 +397,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) tda18271_write_regs(fe, R_EP3, 11); msleep(5); /* pll locking */ + /* launch detector */ tda18271_write_regs(fe, R_EP1, 1); msleep(5); /* wanted mid measurement */ -- cgit v1.2.3 From 5940568bd4467111f445d0e4a936d30fb052dfc0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:22 -0300 Subject: V4L/DVB (7430): tda18271: fix typo in tda18271_calibrate_rf The internal calibration signal must be set on the cal pll. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index eb44ab71ff74..2bbf277f5cfc 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -305,8 +305,8 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) /* set the internal calibration signal */ N = freq; - tda18271_calc_main_pll(fe, N); - tda18271_write_regs(fe, R_MPD, 4); + tda18271_calc_cal_pll(fe, N); + tda18271_write_regs(fe, R_CPD, 4); /* downconvert internal calibration */ N += 1000000; @@ -331,7 +331,7 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) regs[R_EB7] &= ~0x20; tda18271_write_regs(fe, R_EB7, 1); - msleep(5); /* plls locking */ + msleep(10); /* plls locking */ /* launch the rf tracking filters calibration */ regs[R_EB20] |= 0x20; -- cgit v1.2.3 From c818ebbd1c14a1ff0bfdf608fccb17ff248a3545 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:23 -0300 Subject: V4L/DVB (7431): tda18271: allow device-specific configuration of IF level Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 2 +- drivers/media/dvb/frontends/tda18271-tables.c | 112 +++++++++++++------------- drivers/media/dvb/frontends/tda18271.h | 2 + drivers/media/video/cx23885/cx23885-dvb.c | 4 +- 4 files changed, 61 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 2bbf277f5cfc..b5a422ef4ff6 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -55,13 +55,13 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, /* update IF output level & IF notch frequency */ regs[R_EP4] &= ~0x1c; /* clear if level bits */ + regs[R_EP4] |= (map->if_lvl << 2); switch (priv->mode) { case TDA18271_ANALOG: regs[R_MPD] &= ~0x80; /* IF notch = 0 */ break; case TDA18271_DIGITAL: - regs[R_EP4] |= 0x04; /* IF level = 1 */ regs[R_MPD] |= 0x80; /* IF notch = 1 */ break; } diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c index b402abd15bb2..342fb31b64c4 100644 --- a/drivers/media/dvb/frontends/tda18271-tables.c +++ b/drivers/media/dvb/frontends/tda18271-tables.c @@ -1187,65 +1187,65 @@ fail: /*---------------------------------------------------------------------*/ static struct tda18271_std_map tda18271c1_std_map = { - .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0 }, - /* EP3[4:0] 0x18 */ - .atv_b = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, - /* EP3[4:0] 0x0e */ - .atv_dk = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, - /* EP3[4:0] 0x0f */ - .atv_gh = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, - /* EP3[4:0] 0x0f */ - .atv_i = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, - /* EP3[4:0] 0x0f */ - .atv_l = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, - /* EP3[4:0] 0x0f */ - .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7 }, - /* EP3[4:0] 0x0f */ - .atv_mn = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5 }, - /* EP3[4:0] 0x0d */ - .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, - /* EP3[4:0] 0x1c */ - .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, - /* EP3[4:0] 0x1c */ - .dvbt_7 = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5 }, - /* EP3[4:0] 0x1d */ - .dvbt_8 = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6 }, - /* EP3[4:0] 0x1e */ - .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5 }, - /* EP3[4:0] 0x1d */ - .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7 }, - /* EP3[4:0] 0x1f */ + .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .if_lvl = 0, + .agc_mode = 3, .std = 0 }, /* EP3[4:0] 0x18 */ + .atv_b = { .if_freq = 6750, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ + .atv_dk = { .if_freq = 7750, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ + .atv_gh = { .if_freq = 7750, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ + .atv_i = { .if_freq = 7750, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ + .atv_l = { .if_freq = 7750, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ + .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ + .atv_mn = { .if_freq = 5750, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 5 }, /* EP3[4:0] 0x0d */ + .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ + .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ + .dvbt_7 = { .if_freq = 3800, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 5 }, /* EP3[4:0] 0x1d */ + .dvbt_8 = { .if_freq = 4300, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 6 }, /* EP3[4:0] 0x1e */ + .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 5 }, /* EP3[4:0] 0x1d */ + .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 7 }, /* EP3[4:0] 0x1f */ }; static struct tda18271_std_map tda18271c2_std_map = { - .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0 }, - /* EP3[4:0] 0x18 */ - .atv_b = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5 }, - /* EP3[4:0] 0x0d */ - .atv_dk = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, - /* EP3[4:0] 0x0e */ - .atv_gh = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, - /* EP3[4:0] 0x0e */ - .atv_i = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, - /* EP3[4:0] 0x0e */ - .atv_l = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, - /* EP3[4:0] 0x0e */ - .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6 }, - /* EP3[4:0] 0x0e */ - .atv_mn = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4 }, - /* EP3[4:0] 0x0c */ - .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, - /* EP3[4:0] 0x1c */ - .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, - /* EP3[4:0] 0x1c */ - .dvbt_7 = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4 }, - /* EP3[4:0] 0x1c */ - .dvbt_8 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5 }, - /* EP3[4:0] 0x1d */ - .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5 }, - /* EP3[4:0] 0x1d */ - .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7 }, - /* EP3[4:0] 0x1f */ + .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .if_lvl = 0, + .agc_mode = 3, .std = 0 }, /* EP3[4:0] 0x18 */ + .atv_b = { .if_freq = 6000, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 5 }, /* EP3[4:0] 0x0d */ + .atv_dk = { .if_freq = 6900, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ + .atv_gh = { .if_freq = 7100, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ + .atv_i = { .if_freq = 7250, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ + .atv_l = { .if_freq = 6900, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ + .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ + .atv_mn = { .if_freq = 5400, .fm_rfn = 0, .if_lvl = 0, + .agc_mode = 1, .std = 4 }, /* EP3[4:0] 0x0c */ + .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ + .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ + .dvbt_7 = { .if_freq = 3500, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ + .dvbt_8 = { .if_freq = 4000, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 5 }, /* EP3[4:0] 0x1d */ + .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 5 }, /* EP3[4:0] 0x1d */ + .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .if_lvl = 1, + .agc_mode = 3, .std = 7 }, /* EP3[4:0] 0x1f */ }; /*---------------------------------------------------------------------*/ diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index 3a743b0f0e8b..60d63ba285f8 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -33,6 +33,8 @@ struct tda18271_std_map_item { unsigned int std:3; /* EP4[7] */ unsigned int fm_rfn:1; + /* EP4[4:2] */ + unsigned int if_lvl:3; }; struct tda18271_std_map { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 42e6bdd25354..417a30c7a04d 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -165,8 +165,8 @@ static struct tda829x_config tda829x_no_probe = { }; static struct tda18271_std_map hauppauge_tda18271_std_map = { - .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3 }, - .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0 }, + .atsc_6 = { .if_freq = 5380, .if_lvl = 6, .agc_mode = 3, .std = 3 }, + .qam_6 = { .if_freq = 4000, .if_lvl = 6, .agc_mode = 3, .std = 0 }, }; static struct tda18271_config hauppauge_tda18271_config = { -- cgit v1.2.3 From dc8945db26f87600c3ddb8e89e9b4087a45e610f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:23 -0300 Subject: V4L/DVB (7432): tda18271: allow device-specific configuration of rf agc top allow device-specific configuration of rf agc rf top and if top Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 12 +-- drivers/media/dvb/frontends/tda18271-tables.c | 112 +++++++++++++------------- drivers/media/dvb/frontends/tda18271.h | 2 + drivers/media/video/cx23885/cx23885-dvb.c | 6 +- 4 files changed, 65 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index b5a422ef4ff6..3c455795d1ac 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -70,15 +70,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, regs[R_EP4] &= ~0x80; regs[R_EP4] |= map->fm_rfn << 7; - /* update RF_TOP / IF_TOP */ - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_EB22] = 0x2c; - break; - case TDA18271_DIGITAL: - regs[R_EB22] = 0x37; - break; - } + /* update rf top / if top */ + regs[R_EB22] = 0x00; + regs[R_EB22] |= map->rfagc_top; tda18271_write_regs(fe, R_EB22, 1); /* --------------------------------------------------------------- */ diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c index 342fb31b64c4..83e7561960c1 100644 --- a/drivers/media/dvb/frontends/tda18271-tables.c +++ b/drivers/media/dvb/frontends/tda18271-tables.c @@ -1187,65 +1187,65 @@ fail: /*---------------------------------------------------------------------*/ static struct tda18271_std_map tda18271c1_std_map = { - .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .if_lvl = 0, - .agc_mode = 3, .std = 0 }, /* EP3[4:0] 0x18 */ - .atv_b = { .if_freq = 6750, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ - .atv_dk = { .if_freq = 7750, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ - .atv_gh = { .if_freq = 7750, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ - .atv_i = { .if_freq = 7750, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ - .atv_l = { .if_freq = 7750, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ - .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 7 }, /* EP3[4:0] 0x0f */ - .atv_mn = { .if_freq = 5750, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 5 }, /* EP3[4:0] 0x0d */ - .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ - .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ - .dvbt_7 = { .if_freq = 3800, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 5 }, /* EP3[4:0] 0x1d */ - .dvbt_8 = { .if_freq = 4300, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 6 }, /* EP3[4:0] 0x1e */ - .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 5 }, /* EP3[4:0] 0x1d */ - .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 7 }, /* EP3[4:0] 0x1f */ + .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */ + .atv_b = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ + .atv_dk = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ + .atv_gh = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ + .atv_i = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ + .atv_l = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ + .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ + .atv_mn = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */ + .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ + .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ + .dvbt_7 = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */ + .dvbt_8 = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */ + .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */ + .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */ }; static struct tda18271_std_map tda18271c2_std_map = { - .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .if_lvl = 0, - .agc_mode = 3, .std = 0 }, /* EP3[4:0] 0x18 */ - .atv_b = { .if_freq = 6000, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 5 }, /* EP3[4:0] 0x0d */ - .atv_dk = { .if_freq = 6900, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ - .atv_gh = { .if_freq = 7100, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ - .atv_i = { .if_freq = 7250, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ - .atv_l = { .if_freq = 6900, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ - .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 6 }, /* EP3[4:0] 0x0e */ - .atv_mn = { .if_freq = 5400, .fm_rfn = 0, .if_lvl = 0, - .agc_mode = 1, .std = 4 }, /* EP3[4:0] 0x0c */ - .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ - .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ - .dvbt_7 = { .if_freq = 3500, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 4 }, /* EP3[4:0] 0x1c */ - .dvbt_8 = { .if_freq = 4000, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 5 }, /* EP3[4:0] 0x1d */ - .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 5 }, /* EP3[4:0] 0x1d */ - .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .if_lvl = 1, - .agc_mode = 3, .std = 7 }, /* EP3[4:0] 0x1f */ + .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */ + .atv_b = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */ + .atv_dk = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ + .atv_gh = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ + .atv_i = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ + .atv_l = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ + .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ + .atv_mn = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4, + .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0c */ + .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ + .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ + .dvbt_7 = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ + .dvbt_8 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */ + .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */ + .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7, + .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */ }; /*---------------------------------------------------------------------*/ diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index 60d63ba285f8..44d41dce9e10 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -35,6 +35,8 @@ struct tda18271_std_map_item { unsigned int fm_rfn:1; /* EP4[4:2] */ unsigned int if_lvl:3; + /* EB22[6:0] */ + unsigned int rfagc_top:7; }; struct tda18271_std_map { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 417a30c7a04d..7bcd37aa8c90 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -165,8 +165,10 @@ static struct tda829x_config tda829x_no_probe = { }; static struct tda18271_std_map hauppauge_tda18271_std_map = { - .atsc_6 = { .if_freq = 5380, .if_lvl = 6, .agc_mode = 3, .std = 3 }, - .qam_6 = { .if_freq = 4000, .if_lvl = 6, .agc_mode = 3, .std = 0 }, + .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3, + .if_lvl = 6, .rfagc_top = 0x37 }, + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, + .if_lvl = 6, .rfagc_top = 0x37 }, }; static struct tda18271_config hauppauge_tda18271_config = { -- cgit v1.2.3 From 425ebda3b8e3c8346cbb1d7c8d8efdbde798cb3f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:24 -0300 Subject: V4L/DVB (7433): tda18271: fix comparison bug in tda18271_powerscan Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 3c455795d1ac..4a025849a327 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -422,7 +422,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe, count += 200; - if (count < count_limit) + if (count <= count_limit) continue; if (sgn <= 0) -- cgit v1.2.3 From edca3f3448c9b8943780ef6fb36b0237d6f47ab0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:24 -0300 Subject: V4L/DVB (7434): tda18271: set rfagc modes during channel configuration Set rfagc to high speed mode before setting the pll. Set rfagc to normal speed mode at the end of the function. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 4a025849a327..b3b0425dbbed 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -50,6 +50,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, regs[R_EP3] &= ~0x1f; /* clear std bits */ regs[R_EP3] |= (map->agc_mode << 3) | map->std; + /* set rfagc to high speed mode */ + regs[R_EP3] &= ~0x04; + /* set cal mode to normal */ regs[R_EP4] &= ~0x03; @@ -125,7 +128,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, regs[R_EB4] &= ~0x20; tda18271_write_regs(fe, R_EB4, 1); - msleep(5); + msleep(20); + + /* set rfagc to normal speed mode */ + if (map->fm_rfn) + regs[R_EP3] &= ~0x04; + else + regs[R_EP3] |= 0x04; + tda18271_write_regs(fe, R_EP3, 1); return 0; } -- cgit v1.2.3 From 6ed59131e8f33825222d55dc21d3ae78890cc7cb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:24 -0300 Subject: V4L/DVB (7435): tda18271: add function tda18271_charge_pump_source Force the main pll charge pump or cal pll charge pump to source current to the main pll loop filter or cal pll loop filter, respectively. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-common.c | 21 +++++++++++++++++---- drivers/media/dvb/frontends/tda18271-fe.c | 18 ++++++------------ drivers/media/dvb/frontends/tda18271-priv.h | 7 +++++++ 3 files changed, 30 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c index 84d430c52854..e27a7620a32f 100644 --- a/drivers/media/dvb/frontends/tda18271-common.c +++ b/drivers/media/dvb/frontends/tda18271-common.c @@ -217,6 +217,21 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) /*---------------------------------------------------------------------*/ +int tda18271_charge_pump_source(struct dvb_frontend *fe, + enum tda18271_pll pll, int force) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + + int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4; + + regs[r_cp] &= ~0x20; + regs[r_cp] |= ((force & 1) << 5); + tda18271_write_regs(fe, r_cp, 1); + + return 0; +} + int tda18271_init_regs(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; @@ -359,13 +374,11 @@ int tda18271_init_regs(struct dvb_frontend *fe) if ((priv->id) == TDA18271HDC2) { /* main pll cp source on */ - regs[R_EB4] = 0x61; - tda18271_write_regs(fe, R_EB4, 1); + tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); msleep(1); /* main pll cp source off */ - regs[R_EB4] = 0x41; - tda18271_write_regs(fe, R_EB4, 1); + tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); } msleep(5); /* pll locking */ diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index b3b0425dbbed..46905a773e46 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -119,14 +119,12 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, tda18271_write_regs(fe, R_TM, 7); /* main pll charge pump source */ - regs[R_EB4] |= 0x20; - tda18271_write_regs(fe, R_EB4, 1); + tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); msleep(1); /* normal operation for the main pll */ - regs[R_EB4] &= ~0x20; - tda18271_write_regs(fe, R_EB4, 1); + tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); msleep(20); @@ -285,12 +283,10 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) tda18271_write_regs(fe, R_EB13, 1); /* main pll charge pump source */ - regs[R_EB4] |= 0x20; - tda18271_write_regs(fe, R_EB4, 1); + tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); /* cal pll charge pump source */ - regs[R_EB7] |= 0x20; - tda18271_write_regs(fe, R_EB7, 1); + tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1); /* force dcdc converter to 0 V */ regs[R_EB14] = 0x00; @@ -328,12 +324,10 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) /* --------------------------------------------------------------- */ /* normal operation for the main pll */ - regs[R_EB4] &= ~0x20; - tda18271_write_regs(fe, R_EB4, 1); + tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); /* normal operation for the cal pll */ - regs[R_EB7] &= ~0x20; - tda18271_write_regs(fe, R_EB7, 1); + tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0); msleep(10); /* plls locking */ diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index ecb588e5f7d5..2a37f794e1b6 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -86,6 +86,11 @@ struct tda18271_rf_tracking_filter_cal { int rf_b2; }; +enum tda18271_pll { + TDA18271_MAIN_PLL, + TDA18271_CAL_PLL, +}; + enum tda18271_mode { TDA18271_ANALOG, TDA18271_DIGITAL, @@ -188,6 +193,8 @@ extern int tda18271_read_extended(struct dvb_frontend *fe); extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len); extern int tda18271_init_regs(struct dvb_frontend *fe); +extern int tda18271_charge_pump_source(struct dvb_frontend *fe, + enum tda18271_pll pll, int force); extern int tda18271_set_standby_mode(struct dvb_frontend *fe, int sm, int sm_lt, int sm_xt); -- cgit v1.2.3 From 63ba8668f7b9be1ce59ab5719b36f4de2b85770c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:24 -0300 Subject: V4L/DVB (7436): tda18271: add basic support for slave tuner configurations Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 44 +++++++++++++++++++++++------ drivers/media/dvb/frontends/tda18271-priv.h | 1 + drivers/media/dvb/frontends/tda18271.h | 8 ++++++ 3 files changed, 44 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 46905a773e46..5b1cb7f5745c 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -36,6 +36,15 @@ static LIST_HEAD(hybrid_tuner_instance_list); /*---------------------------------------------------------------------*/ +static inline int charge_pump_source(struct dvb_frontend *fe, int force) +{ + struct tda18271_priv *priv = fe->tuner_priv; + return tda18271_charge_pump_source(fe, + (priv->role == TDA18271_SLAVE) ? + TDA18271_CAL_PLL : + TDA18271_MAIN_PLL, force); +} + static int tda18271_channel_configuration(struct dvb_frontend *fe, struct tda18271_std_map_item *map, u32 freq, u32 bw) @@ -97,8 +106,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, /* dual tuner and agc1 extra configuration */ - /* main vco when Master, cal vco when slave */ - regs[R_EB1] |= 0x04; /* FIXME: assumes master */ + switch (priv->role) { + case TDA18271_MASTER: + regs[R_EB1] |= 0x04; /* main vco */ + break; + case TDA18271_SLAVE: + regs[R_EB1] &= ~0x04; /* cal vco */ + break; + } /* agc1 always active */ regs[R_EB1] &= ~0x02; @@ -112,19 +127,29 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, N = map->if_freq * 1000 + freq; - /* FIXME: assumes master */ - tda18271_calc_main_pll(fe, N); - tda18271_write_regs(fe, R_MPD, 4); + switch (priv->role) { + case TDA18271_MASTER: + tda18271_calc_main_pll(fe, N); + tda18271_write_regs(fe, R_MPD, 4); + break; + case TDA18271_SLAVE: + tda18271_calc_cal_pll(fe, N); + tda18271_write_regs(fe, R_CPD, 4); + + regs[R_MPD] = regs[R_CPD] & 0x7f; + tda18271_write_regs(fe, R_MPD, 1); + break; + } tda18271_write_regs(fe, R_TM, 7); - /* main pll charge pump source */ - tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); + /* force charge pump source */ + charge_pump_source(fe, 1); msleep(1); - /* normal operation for the main pll */ - tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); + /* return pll to normal operation */ + charge_pump_source(fe, 0); msleep(20); @@ -1058,6 +1083,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, case 1: /* new tuner instance */ priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; + priv->role = (cfg) ? cfg->role : TDA18271_MASTER; priv->cal_initialized = false; mutex_init(&priv->lock); diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index 2a37f794e1b6..4b153bc557fe 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -110,6 +110,7 @@ struct tda18271_priv { struct tuner_i2c_props i2c_props; enum tda18271_mode mode; + enum tda18271_role role; enum tda18271_i2c_gate gate; enum tda18271_ver id; diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index 44d41dce9e10..b547318c951b 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -56,6 +56,11 @@ struct tda18271_std_map { struct tda18271_std_map_item qam_8; }; +enum tda18271_role { + TDA18271_MASTER = 0, + TDA18271_SLAVE, +}; + enum tda18271_i2c_gate { TDA18271_GATE_AUTO = 0, TDA18271_GATE_ANALOG, @@ -66,6 +71,9 @@ struct tda18271_config { /* override default if freq / std settings (optional) */ struct tda18271_std_map *std_map; + /* master / slave tuner: master uses main pll, slave uses cal pll */ + enum tda18271_role role; + /* use i2c gate provided by analog or digital demod */ enum tda18271_i2c_gate gate; -- cgit v1.2.3 From 093344642a1f002ec873d404320f2441af907d16 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:25 -0300 Subject: V4L/DVB (7437): tda18271: increment module version minor Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 5b1cb7f5745c..48ec5f08c3c9 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -1139,7 +1139,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach); MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.2"); +MODULE_VERSION("0.3"); /* * Overrides for Emacs so that we follow Linus's tabbing style. -- cgit v1.2.3 From 04a9abeea102dae38997d26e236b9be01d5e3237 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Apr 2008 14:28:25 -0300 Subject: V4L/DVB (7439): tuner-xc2028: Adds an option to allow forcing to load an specific firmware name There are a number of different firmware versions and variants, shipped together with boards. This patch adds an extra parameter to the tuner-xc2028 to allow specifying for an specific firmware name to be loaded. This helps to test for a firmware that better fits some board. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-xc2028.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 0b5ba67a4da5..098a9956a2bc 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -41,6 +41,11 @@ MODULE_PARM_DESC(audio_std, "NICAM/A\n" "NICAM/B\n"); +static char firmware_name[FIRMWARE_NAME_MAX]; +module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0); +MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the " + "default firmware name\n"); + static LIST_HEAD(xc2028_list); static DEFINE_MUTEX(xc2028_list_mutex); @@ -253,19 +258,24 @@ static int load_all_firmwares(struct dvb_frontend *fe) int rc = 0; int n, n_array; char name[33]; + char *fname; tuner_dbg("%s called\n", __FUNCTION__); - tuner_dbg("Reading firmware %s\n", priv->ctrl.fname); - rc = request_firmware(&fw, priv->ctrl.fname, - &priv->i2c_props.adap->dev); + if (!firmware_name[0]) + fname = priv->ctrl.fname; + else + fname = firmware_name; + + tuner_dbg("Reading firmware %s\n", fname); + rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev); if (rc < 0) { if (rc == -ENOENT) tuner_err("Error: firmware %s not found.\n", - priv->ctrl.fname); + fname); else tuner_err("Error %d while requesting firmware %s \n", - rc, priv->ctrl.fname); + rc, fname); return rc; } @@ -274,7 +284,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) if (fw->size < sizeof(name) - 1 + 2 + 2) { tuner_err("Error: firmware file %s has invalid size!\n", - priv->ctrl.fname); + fname); goto corrupt; } @@ -289,7 +299,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) p += 2; tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n", - n_array, priv->ctrl.fname, name, + n_array, fname, name, priv->firm_version >> 8, priv->firm_version & 0xff); priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL); -- cgit v1.2.3 From 8c6a11472d3bd62c23100b3475f112cf0ffefd5a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:25 -0300 Subject: V4L/DVB (7440): dvb-bt8xx: fix build error Fix the following build error: In file included from dvb-bt8xx.c:35: dvb-bt8xx.h:42:26: error: tuner-simple.h: No such file or directory dvb-bt8xx.c: In function 'frontend_init': dvb-bt8xx.c:612: error: 'simple_tuner_attach' undeclared (first use in this function) dvb-bt8xx.c:612: error: (Each undeclared identifier is reported only once dvb-bt8xx.c:612: error: for each function it appears in.) dvb-bt8xx.c:612: warning: type defaults to 'int' in declaration of '__a' dvb-bt8xx.c:612: warning: type defaults to 'int' in declaration of 'type name' dvb-bt8xx.c:612: warning: cast from pointer to integer of different size dvb-bt8xx.c:612: warning: type defaults to 'int' in declaration of 'type name' dvb-bt8xx.c:612: warning: cast from pointer to integer of different size dvb-bt8xx.c:612: error: called object '__a' is not a function dvb-bt8xx.c:696: warning: type defaults to 'int' in declaration of '__a' dvb-bt8xx.c:696: warning: type defaults to 'int' in declaration of 'type name' dvb-bt8xx.c:696: warning: cast from pointer to integer of different size dvb-bt8xx.c:696: warning: type defaults to 'int' in declaration of 'type name' dvb-bt8xx.c:696: warning: cast from pointer to integer of different size dvb-bt8xx.c:696: error: called object '__a' is not a function Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile index 84cf70504d17..9d3e68b5d6eb 100644 --- a/drivers/media/dvb/bt8xx/Makefile +++ b/drivers/media/dvb/bt8xx/Makefile @@ -1,3 +1,6 @@ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o -EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/video/bt8xx +EXTRA_CFLAGS += -Idrivers/media/video -- cgit v1.2.3 From b092ed1b20d6369df1a097f6d625a94ba1e369fb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 14:28:25 -0300 Subject: V4L/DVB (7441): kconfig fixes for tuner-simple Update Kconfig for the hybrid devices recently converted to use tuner-simple rather than dvb-pll. dvb-bt8xx no longer uses dvb-pll at all, so remove all references to dvb-pll within that driver. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/Kconfig | 1 + drivers/media/dvb/bt8xx/Kconfig | 2 +- drivers/media/dvb/bt8xx/dvb-bt8xx.h | 1 - drivers/media/dvb/dvb-usb/Kconfig | 1 + drivers/media/video/cx88/Kconfig | 1 + drivers/media/video/saa7134/Kconfig | 1 + 6 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 3197aeb61d1f..ffcbc7610856 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_BCM3510 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select TUNER_SIMPLE if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index ea666174e988..902c762e0b7f 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -7,8 +7,8 @@ config DVB_BT8XX select DVB_CX24110 if !DVB_FE_CUSTOMISE select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE + select TUNER_SIMPLE if !DVB_FE_CUSTOMISE select FW_LOADER help Support for PCI cards based on the Bt8xx PCI bridge. Examples are diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 25a23c3c7c66..4499ed2ac0ed 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -38,7 +38,6 @@ #include "or51211.h" #include "lgdt330x.h" #include "zl10353.h" -#include "dvb-pll.h" #include "tuner-simple.h" struct dvb_bt8xx_card { diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index d73934dd4c57..3c8493d2026d 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -105,6 +105,7 @@ config DVB_USB_CXUSB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE + select TUNER_SIMPLE if !DVB_FE_CUSTOMISE help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 49d3813a9b48..bcf6d9ba063d 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -57,6 +57,7 @@ config VIDEO_CX88_DVB select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE + select TUNER_SIMPLE if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 96bc3b1298a2..e086f14d5663 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -37,6 +37,7 @@ config VIDEO_SAA7134_DVB select DVB_TDA826X if !DVB_FE_CUSTOMISE select DVB_TDA827X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE + select TUNER_SIMPLE if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. -- cgit v1.2.3 From d737b14b768269785904c44ae56c8446900be1bc Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 8 Mar 2008 01:02:20 -0300 Subject: V4L/DVB (7447): pvrusb2: Fix compilation warning Fix use of a non-int (size_t) being passed in a printf width field. This benign issue has apparently been around for a long time, but went undetected until now. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 24e25bb7a90b..4dd544ac85bf 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -289,7 +289,7 @@ static ssize_t store_val_norm(int id,struct device *class_dev, int ret; sfp = (struct pvr2_sysfs *)class_dev->driver_data; pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"", - sfp,id,count,buf); + sfp,id,(int)count,buf); ret = store_val_any(id,0,sfp,buf,count); if (!ret) ret = count; return ret; @@ -302,7 +302,7 @@ static ssize_t store_val_custom(int id,struct device *class_dev, int ret; sfp = (struct pvr2_sysfs *)class_dev->driver_data; pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"", - sfp,id,count,buf); + sfp,id,(int)count,buf); ret = store_val_any(id,1,sfp,buf,count); if (!ret) ret = count; return ret; -- cgit v1.2.3 From db7fefb883d2773682efd33209b0f73ee6136b64 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Mar 2008 20:18:30 -0300 Subject: V4L/DVB (7448): Add support for Kworld ATSC 120 This board has a s5h1409 demod, plus a xc30x8 tuner (probably, xc3018). This patch adds proper support for radio, video, s-video, composite and ATSC. However, support for radio and video depends on having s5h1409 i2c gate open, otherwise, xc30x8 chip won't be visible. For a better support, some rework is needed on cx88 driver, to allow adding xc30x8 to i2c bus without sending i2c 0 byte reading to 0xc2 address. Thanks to Vanessa Ezekowitz for helping to figure out the proper parameters for s5h1409 and the GPIO pins used by each configuration. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 110 ++++++++++++++++++++++++-------- drivers/media/video/cx88/cx88-dvb.c | 30 ++++++++- drivers/media/video/cx88/cx88.h | 3 + 4 files changed, 114 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index a01991dcb317..543957346469 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -65,3 +65,4 @@ 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] + 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 6b83e3457b70..70505b4e5b46 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -27,7 +27,6 @@ #include "cx88.h" #include "tea5767.h" -#include "tuner-xc2028.h" static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; @@ -1614,6 +1613,45 @@ static const struct cx88_board cx88_boards[] = { .gpio2 = 0x0cfb, }, }, + /* Both radio, analog and ATSC work with this board. + However, for analog to work, s5h1409 gate should be open, + otherwise, tuner-xc3028 won't be detected. + A proper fix require using the newer i2c methods to add + tuner-xc3028 without doing an i2c probe. + */ + [CX88_BOARD_KWORLD_ATSC_120] = { + .name = "Kworld PlusTV HD PCI 120 (ATSC 120)", + .tuner_type = TUNER_XC2028, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x000000ff, + .gpio1 = 0x0000f35d, + .gpio2 = 0x00000000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000000ff, + .gpio1 = 0x0000f37e, + .gpio2 = 0x00000000, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000000ff, + .gpio1 = 0x0000f37e, + .gpio2 = 0x00000000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000000ff, + .gpio1 = 0x0000f35d, + .gpio2 = 0x00000000, + }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -1959,6 +1997,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x1554, .subdevice = 0x4935, .card = CX88_BOARD_PROLINK_PV_8000GT, + }, { + .subvendor = 0x17de, + .subdevice = 0x08c1, + .card = CX88_BOARD_KWORLD_ATSC_120, }, }; @@ -2200,6 +2242,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: + case CX88_BOARD_KWORLD_ATSC_120: return cx88_xc3028_geniatech_tuner_callback(core, command, arg); case CX88_BOARD_PROLINK_PV_8000GT: @@ -2363,6 +2406,40 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) } } +/* + * Sets board-dependent xc3028 configuration + */ +void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) +{ + memset(ctl, 0, sizeof(*ctl)); + + ctl->fname = XC2028_DEFAULT_FIRMWARE; + ctl->max_len = 64; + + switch (core->boardnr) { + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + /* Doesn't work with firmware version 2.7 */ + ctl->fname = "xc3028-v25.fw"; + break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + ctl->scode_table = XC3028_FE_ZARLINK456; + break; + case CX88_BOARD_KWORLD_ATSC_120: + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + ctl->demod = XC3028_FE_OREN538; + break; + case CX88_BOARD_PROLINK_PV_8000GT: + /* + * This board uses non-MTS firmware + */ + break; + default: + ctl->demod = XC3028_FE_OREN538; + ctl->mts = 1; + } +} +EXPORT_SYMBOL_GPL(cx88_setup_xc3028); + static void cx88_card_setup(struct cx88_core *core) { static u8 eeprom[256]; @@ -2481,36 +2558,13 @@ static void cx88_card_setup(struct cx88_core *core) struct v4l2_priv_tun_config xc2028_cfg; struct xc2028_ctrl ctl; - memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); - memset(&ctl, 0, sizeof(ctl)); - - ctl.fname = XC2028_DEFAULT_FIRMWARE; - ctl.max_len = 64; - - switch (core->boardnr) { - case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - /* Doesn't work with firmware version 2.7 */ - ctl.fname = "xc3028-v25.fw"; - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - ctl.scode_table = XC3028_FE_ZARLINK456; - break; - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - ctl.demod = XC3028_FE_OREN538; - break; - case CX88_BOARD_PROLINK_PV_8000GT: - /* - * This board uses non-MTS firmware - */ - break; - default: - ctl.demod = XC3028_FE_OREN538; - ctl.mts = 1; - } + /* Fills device-dependent initialization parameters */ + cx88_setup_xc3028(core, &ctl); + /* Sends parameters to xc2028/3028 tuner */ + memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; - info_printk(core, "Asking xc2028/3028 to load firmware %s\n", ctl.fname); cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 8dca20b944dd..13cc395ca656 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -45,7 +45,6 @@ #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" -#include "tuner-xc2028.h" #include "tuner-xc2028-types.h" #include "tuner-simple.h" #include "tda9887.h" @@ -443,6 +442,16 @@ static struct s5h1409_config dvico_hdtv5_pci_nano_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, }; +static struct s5h1409_config kworld_atsc_120_config = { + .demod_address = 0x32 >> 1, + .qam_if = 44000, + .output_mode = S5H1409_SERIAL_OUTPUT, + .gpio = S5H1409_GPIO_OFF, + .inversion = S5H1409_INVERSION_OFF, + .status_mode = S5H1409_DEMODLOCKING, + .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, +}; + static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .i2c_address = 0x64, .if_khz = 5380, @@ -457,9 +466,12 @@ static struct zl10353_config cx88_geniatech_x8000_mt = { static int attach_xc3028(u8 addr, struct cx8802_dev *dev) { struct dvb_frontend *fe; + struct xc2028_ctrl ctl; struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, .i2c_addr = addr, + .ctrl = &ctl, + .callback = cx88_tuner_callback, }; if (!dev->dvb.frontend) { @@ -469,6 +481,13 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) return -EINVAL; } + /* + * Some xc3028 devices may be hidden by an I2C gate. This is known + * to happen with some s5h1409-based devices. + * Now that I2C gate is open, sets up xc3028 configuration + */ + cx88_setup_xc3028(dev->core, &ctl); + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", @@ -810,7 +829,7 @@ static int dvb_register(struct cx8802_dev *dev) return -EINVAL; break; case CX88_BOARD_GENIATECH_X8000_MT: - dev->ts_gen_cntrl = 0x00; + dev->ts_gen_cntrl = 0x00; dev->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, @@ -818,6 +837,13 @@ static int dvb_register(struct cx8802_dev *dev) if (attach_xc3028(0x61, dev) < 0) return -EINVAL; break; + case CX88_BOARD_KWORLD_ATSC_120: + dev->dvb.frontend = dvb_attach(s5h1409_attach, + &kworld_atsc_120_config, + &dev->core->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) + return -EINVAL; + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index c0f4912793e9..d17ca71c5d95 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -37,6 +37,7 @@ #include "btcx-risc.h" #include "cx88-reg.h" +#include "tuner-xc2028.h" #include #include @@ -219,6 +220,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 #define CX88_BOARD_PROLINK_PV_8000GT 66 +#define CX88_BOARD_KWORLD_ATSC_120 67 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -603,6 +605,7 @@ extern int cx88_tuner_callback(void *dev, int command, int arg); extern int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci); extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); +extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl); /* ----------------------------------------------------------- */ /* cx88-tvaudio.c */ -- cgit v1.2.3 From 1b57702cf1df71fa2b26b6fe1d522f55f2bb79e6 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 25 Mar 2008 23:07:35 -0300 Subject: V4L/DVB (7449): cx88: fix oops on module removal caused by IR worker If the IR worker is not stopped before the removal of the cx88xx module, an OOPS may occur, because the worker function cx88_ir_work gets called. So stop the ir worker. Signed-off-by: Marton Balint Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 327c0a87c081..1eea044969a1 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1920,6 +1920,9 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) core->kthread = NULL; } + if (core->ir) + cx88_ir_stop(core, core->ir); + cx88_shutdown(core); /* FIXME */ pci_disable_device(pci_dev); -- cgit v1.2.3 From 35a2c13e5d3e99578e6b654b1ab66d2e97ed2d9f Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 19:43:21 -0300 Subject: V4L/DVB (7451): cx88: Add user control for chroma AGC The cx2388x family has support for chroma AGC. This patch implements a the V4L2_CID_CHROMA_AGC control for the cx2388x family. By default chroma AGC is disabled, as in previous versions of the driver. Signed-off-by: "Frej Drejhammar " Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 4 ++-- drivers/media/video/cx88/cx88-core.c | 6 +++++- drivers/media/video/cx88/cx88-video.c | 30 ++++++++++++++++++++++++++++-- drivers/media/video/cx88/cx88.h | 3 ++- 4 files changed, 37 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index d582395805df..8d54e7a90dc7 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -693,7 +693,7 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc return -EINVAL; /* Standard V4L2 controls */ - if (cx8800_ctrl_query(qctrl) == 0) + if (cx8800_ctrl_query(dev->core, qctrl) == 0) return 0; /* MPEG V4L2 controls */ @@ -933,7 +933,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); if (unlikely(qctrl->id == 0)) return -EINVAL; - return cx8800_ctrl_query(qctrl); + return cx8800_ctrl_query(dev->core, qctrl); } static int vidioc_enum_input (struct file *file, void *priv, diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 75b581048f6e..dca9f3ae5fdf 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -929,7 +929,11 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n", cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f); - cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat); + /* Chroma AGC must be disabled if SECAM is used */ + if (norm & V4L2_STD_SECAM) + cx_andor(MO_INPUT_FORMAT, 0x40f, cxiformat); + else + cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat); // FIXME: as-is from DScaler dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n", diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 1eea044969a1..7ec6763f0e79 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -228,6 +228,18 @@ static struct cx88_ctrl cx8800_ctls[] = { .mask = 0x00ff, .shift = 0, },{ + .v = { + .id = V4L2_CID_CHROMA_AGC, + .name = "Chroma AGC", + .minimum = 0, + .maximum = 1, + .default_value = 0x0, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, + .reg = MO_INPUT_FORMAT, + .mask = 1 << 10, + .shift = 10, + }, { /* --- audio --- */ .v = { .id = V4L2_CID_AUDIO_MUTE, @@ -282,6 +294,7 @@ const u32 cx88_user_ctrls[] = { V4L2_CID_AUDIO_VOLUME, V4L2_CID_AUDIO_BALANCE, V4L2_CID_AUDIO_MUTE, + V4L2_CID_CHROMA_AGC, 0 }; EXPORT_SYMBOL(cx88_user_ctrls); @@ -291,7 +304,7 @@ static const u32 *ctrl_classes[] = { NULL }; -int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl) +int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl) { int i; @@ -306,6 +319,11 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl) return 0; } *qctrl = cx8800_ctls[i].v; + /* Report chroma AGC as inactive when SECAM is selected */ + if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC && + core->tvnorm & V4L2_STD_SECAM) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; } EXPORT_SYMBOL(cx8800_ctrl_query); @@ -976,6 +994,12 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) } mask=0xffff; break; + case V4L2_CID_CHROMA_AGC: + /* Do not allow chroma AGC to be enabled for SECAM */ + value = ((ctl->value - c->off) << c->shift) & c->mask; + if (core->tvnorm & V4L2_STD_SECAM && value) + return -EINVAL; + break; default: value = ((ctl->value - c->off) << c->shift) & c->mask; break; @@ -1268,10 +1292,12 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i) static int vidioc_queryctrl (struct file *file, void *priv, struct v4l2_queryctrl *qctrl) { + struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; + qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); if (unlikely(qctrl->id == 0)) return -EINVAL; - return cx8800_ctrl_query(qctrl); + return cx8800_ctrl_query(core, qctrl); } static int vidioc_g_ctrl (struct file *file, void *priv, diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index d17ca71c5d95..14ac173f4071 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -651,7 +651,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev); /* ----------------------------------------------------------- */ /* cx88-video.c*/ extern const u32 cx88_user_ctrls[]; -extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); +extern int cx8800_ctrl_query(struct cx88_core *core, + struct v4l2_queryctrl *qctrl); int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl); -- cgit v1.2.3 From 853e8519be2119ba2147353b0301bff74275ef15 Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 19:43:22 -0300 Subject: V4L/DVB (7452): cx88: Enable chroma AGC by default for all non-SECAM modes An enabled chroma AGC will not degrade picture quality if enabled on a color PAL or NTSC signal with nominal signal levels. It will give a significant color reproduction improvement if the chroma signals diverge from nominal levels. Therefore enable chroma AGC by default for PAL and NTSC standards. Signed-off-by: "Frej Drejhammar " Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-core.c | 9 ++++----- drivers/media/video/cx88/cx88-video.c | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index dca9f3ae5fdf..6039a8f57b48 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -929,11 +929,10 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n", cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f); - /* Chroma AGC must be disabled if SECAM is used */ - if (norm & V4L2_STD_SECAM) - cx_andor(MO_INPUT_FORMAT, 0x40f, cxiformat); - else - cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat); + /* Chroma AGC must be disabled if SECAM is used, we enable it + by default on PAL and NTSC */ + cx_andor(MO_INPUT_FORMAT, 0x40f, + norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400); // FIXME: as-is from DScaler dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n", diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 7ec6763f0e79..f9bcb9dc8582 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -233,7 +233,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .name = "Chroma AGC", .minimum = 0, .maximum = 1, - .default_value = 0x0, + .default_value = 0x1, .type = V4L2_CTRL_TYPE_BOOLEAN, }, .reg = MO_INPUT_FORMAT, -- cgit v1.2.3 From d53228abcda32f824e71df3448de4b756da61d4e Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 19:43:24 -0300 Subject: V4L/DVB (7454): cx88: Add user control for color killer The cx2388x family has a color killer. This patch implements the V4L2_CID_COLOR_KILLER control for the cx2388x family. By default the color killer is disabled, as in previous versions of the driver. Signed-off-by: "Frej Drejhammar " Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index f9bcb9dc8582..548ec492c6b6 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -239,6 +239,18 @@ static struct cx88_ctrl cx8800_ctls[] = { .reg = MO_INPUT_FORMAT, .mask = 1 << 10, .shift = 10, + }, { + .v = { + .id = V4L2_CID_COLOR_KILLER, + .name = "Color killer", + .minimum = 0, + .maximum = 1, + .default_value = 0x0, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, + .reg = MO_INPUT_FORMAT, + .mask = 1 << 9, + .shift = 9, }, { /* --- audio --- */ .v = { @@ -295,6 +307,7 @@ const u32 cx88_user_ctrls[] = { V4L2_CID_AUDIO_BALANCE, V4L2_CID_AUDIO_MUTE, V4L2_CID_CHROMA_AGC, + V4L2_CID_COLOR_KILLER, 0 }; EXPORT_SYMBOL(cx88_user_ctrls); -- cgit v1.2.3 From 289a1bddbd8071567bb0cf3cb16a863134f1a874 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Mar 2008 11:21:04 -0300 Subject: V4L/DVB (7455): cx88_dvb: qam doesn't apply on Kword ATSC 120 Thanks to Michael Krufky for pointing this. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 13cc395ca656..5e7c7fdb38ae 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -444,7 +444,6 @@ static struct s5h1409_config dvico_hdtv5_pci_nano_config = { static struct s5h1409_config kworld_atsc_120_config = { .demod_address = 0x32 >> 1, - .qam_if = 44000, .output_mode = S5H1409_SERIAL_OUTPUT, .gpio = S5H1409_GPIO_OFF, .inversion = S5H1409_INVERSION_OFF, -- cgit v1.2.3 From 2d7a6b0fdd223877f6e5f7fd7019aefc124f2f43 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Mar 2008 14:45:51 -0300 Subject: V4L/DVB (7456): vivi: Add 32bit compatibility to the module Thanks to Jiri Slaby for pointing this issue. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 1db067c02815..0e623179f8a5 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1182,6 +1182,7 @@ static const struct file_operations vivi_fops = { .read = vivi_read, .poll = vivi_poll, .ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .compat_ioctl = v4l_compat_ioctl32, .mmap = vivi_mmap, .llseek = no_llseek, }; -- cgit v1.2.3 From eece39c408077542fb8bef96dd32288a9f91a519 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Mar 2008 14:52:44 -0300 Subject: V4L/DVB (7458): saa7134: Adds analog support for Avermedia A16D Thanks to timf , "Richard (MQ)" and gian luca rasponi for their tests. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 25 +++++++++++++++++---- drivers/media/video/saa7134/saa7134-dvb.c | 35 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c323ca005f72..cfa13c2fb14f 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5217,6 +5217,13 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev, case XC2028_TUNER_RESET: saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); + mdelay(250); + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0); + mdelay(250); + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); + mdelay(250); saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02); saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81); saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7); @@ -5413,10 +5420,15 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: case SAA7134_BOARD_AVERMEDIA_M115: case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + case SAA7134_BOARD_AVERMEDIA_A16D: + /* power-down tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0); + msleep(10); /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0xffffffff); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); - msleep(1); + msleep(10); break; case SAA7134_BOARD_RTD_VFG7350: @@ -5709,9 +5721,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) ctl.fname = XC2028_DEFAULT_FIRMWARE; ctl.max_len = 64; - /* FIXME: This should be device-dependent */ - ctl.demod = XC3028_FE_OREN538; - ctl.mts = 1; + switch (dev->board) { + case SAA7134_BOARD_AVERMEDIA_A16D: + ctl.demod = XC3028_FE_ZARLINK456; + break; + default: + ctl.demod = XC3028_FE_OREN538; + ctl.mts = 1; + } xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 9f8730bc6e5f..5c84f45ecbe2 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -151,6 +151,26 @@ static int mt352_aver777_init(struct dvb_frontend* fe) return 0; } +static int mt352_aver_a16d_init(struct dvb_frontend *fe) +{ + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; + static u8 reset [] = { RESET, 0x80 }; + static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0xa0 }; + static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 }; + + mt352_write(fe, clock_config, sizeof(clock_config)); + udelay(200); + mt352_write(fe, reset, sizeof(reset)); + mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); + mt352_write(fe, agc_cfg, sizeof(agc_cfg)); + mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); + + return 0; +} + + + static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { @@ -193,6 +213,11 @@ static struct mt352_config avermedia_777 = { .demod_init = mt352_aver777_init, }; +static struct mt352_config avermedia_16d = { + .demod_address = 0xf, + .demod_init = mt352_aver_a16d_init, +}; + static struct mt352_config avermedia_e506r_mt352_dev = { .demod_address = (0x1e >> 1), .no_tuner = 1, @@ -935,6 +960,12 @@ static int dvb_init(struct saa7134_dev *dev) TUNER_PHILIPS_TD1316); } break; + case SAA7134_BOARD_AVERMEDIA_A16D: + dprintk("avertv A16D dvb setup\n"); + dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_16d, + &dev->i2c_adap); + attach_xc3028 = 1; + break; case SAA7134_BOARD_MD7134: dev->dvb.frontend = dvb_attach(tda10046_attach, &medion_cardbus, @@ -1205,6 +1236,10 @@ static int dvb_init(struct saa7134_dev *dev) .i2c_adap = &dev->i2c_adap, .i2c_addr = 0x61, }; + + if (!dev->dvb.frontend) + return -1; + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", -- cgit v1.2.3 From 7529f556ab1edf6698704a51f550ad4b73baa302 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Thu, 27 Mar 2008 20:51:05 -0300 Subject: V4L/DVB (7459): Test cmd, not definition in decoder_command(), drivers/media/video/zoran_device.c include/linux/video_decoder.h: 34:#define DECODER_SET_NORM _IOW('d', 3, int) 35:#define DECODER_SET_INPUT _IOW('d', 4, int) untested, please confirm it's right. Test cmd value, not definition of DECODER_SET_INPUT Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 10686c68a65b..05b16a254cb3 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -1727,7 +1727,7 @@ decoder_command (struct zoran *zr, return -EIO; if (zr->card.type == LML33 && - (cmd == DECODER_SET_NORM || DECODER_SET_INPUT)) { + (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) { int res; // Bt819 needs to reset its FIFO buffer using #FRST pin and -- cgit v1.2.3 From 9c5029a6b0e8c8bd08ad6b8e4a7451d9f2d5f634 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Tue, 1 Apr 2008 13:48:23 -0300 Subject: V4L/DVB (7460): bttv: Bt832 - fix possible NULL pointer deref This patch does fix potential NULL pointer dereference Signed-off-by: Cyrill Gorcunov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bt832.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bt832.c b/drivers/media/video/bt8xx/bt832.c index a51876137880..f92f06dec0d0 100644 --- a/drivers/media/video/bt8xx/bt832.c +++ b/drivers/media/video/bt8xx/bt832.c @@ -97,6 +97,11 @@ int bt832_init(struct i2c_client *i2c_client_s) int rc; buf=kmalloc(65,GFP_KERNEL); + if (!buf) { + v4l_err(&t->client, + "Unable to allocate memory. Detaching.\n"); + return 0; + } bt832_hexdump(i2c_client_s,buf); if(buf[0x40] != 0x31) { @@ -211,7 +216,12 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) switch (cmd) { case BT832_HEXDUMP: { unsigned char *buf; - buf=kmalloc(65,GFP_KERNEL); + buf = kmalloc(65, GFP_KERNEL); + if (!buf) { + v4l_err(&t->client, + "Unable to allocate memory\n"); + break; + } bt832_hexdump(&t->client,buf); kfree(buf); } -- cgit v1.2.3 From cf0ac10c05a04d65106c76539a3fb02862b79f78 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 1 Apr 2008 17:30:24 -0300 Subject: V4L/DVB (7462): bttv: Fix some API non-compliances for some audio/input V4L2 calls Thanks to Cyrill Gorcunov for pointing this Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index af2c0c994186..79da9d01d715 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3117,12 +3117,18 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) 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, struct v4l2_audio *a) { + if (unlikely(a->index)) + return -EINVAL; + return 0; } @@ -3510,7 +3516,7 @@ static int radio_enum_input(struct file *file, void *priv, return -EINVAL; strcpy(i->name, "Radio"); - i->type = V4L2_INPUT_TYPE_TUNER; + i->type = V4L2_INPUT_TYPE_TUNER; return 0; } @@ -3518,10 +3524,9 @@ static int radio_enum_input(struct file *file, void *priv, static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) + if (unlikely(a->index)) return -EINVAL; - memset(a, 0, sizeof(*a)); strcpy(a->name, "Radio"); return 0; @@ -3543,11 +3548,17 @@ static int radio_s_tuner(struct file *file, void *priv, static int radio_s_audio(struct file *file, void *priv, 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; } -- cgit v1.2.3 From d537ae1af6d3610905cf44470c5ec3c4b4d3e61e Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 19:43:25 -0300 Subject: V4L/DVB (7463): cx88: Enable color killer by default An enabled color killer will not degrade picture quality for color input signals, only suppress bogus color information on black-and-white input. Therefore enable it by default. Signed-off-by: Frej Drejhammar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 548ec492c6b6..eea23f95edb7 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -245,7 +245,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .name = "Color killer", .minimum = 0, .maximum = 1, - .default_value = 0x0, + .default_value = 0x1, .type = V4L2_CTRL_TYPE_BOOLEAN, }, .reg = MO_INPUT_FORMAT, -- cgit v1.2.3 From 874211ac2f65f87494304c98da2cfce371814dce Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 29 Mar 2008 17:49:57 -0300 Subject: V4L/DVB (7469): Preparation for supporting new devices, cleanup and saneness To prepare the support for new device to the flexcop-family some preparation and cleanups was done + some saneness: - created an i2c-adapter for each i2c-port available. Easier usage for devices with several device on different i2c-busses - initialize i2c before doing the eeprom read - changed the way to attach the different frontends, easier to read now - enabled support for i2c-devices having no register address (1-byte access) Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-common.h | 17 ++- drivers/media/dvb/b2c2/flexcop-eeprom.c | 9 +- drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 111 ++++++++++-------- drivers/media/dvb/b2c2/flexcop-i2c.c | 180 ++++++++++++++++++++---------- drivers/media/dvb/b2c2/flexcop-usb.c | 17 +-- drivers/media/dvb/b2c2/flexcop.c | 10 +- 6 files changed, 221 insertions(+), 123 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h index 5a6c4fe249e7..8ce06336e76f 100644 --- a/drivers/media/dvb/b2c2/flexcop-common.h +++ b/drivers/media/dvb/b2c2/flexcop-common.h @@ -44,6 +44,14 @@ struct flexcop_dma { u32 size; /* size of each address in bytes */ }; +struct flexcop_i2c_adapter { + struct flexcop_device *fc; + struct i2c_adapter i2c_adap; + + u8 no_base_addr; + flexcop_i2c_port_t port; +}; + /* Control structure for data definitions that are common to * the B2C2-based PCI and USB devices. */ @@ -72,7 +80,7 @@ struct flexcop_device { struct dmx_frontend mem_frontend; int (*fe_sleep) (struct dvb_frontend *); - struct i2c_adapter i2c_adap; + struct flexcop_i2c_adapter fc_i2c_adap[3]; struct mutex i2c_mutex; struct module *owner; @@ -87,7 +95,8 @@ struct flexcop_device { int (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value); - int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); + int (*i2c_request) (struct flexcop_i2c_adapter*, + flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); int (*stream_control) (struct flexcop_device*, int); int (*get_mac_addr) (struct flexcop_device *fc, int extended); @@ -128,8 +137,8 @@ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended); * one. We have it in flexcop-i2c.c, because it is going via the actual * I2C-channel of the flexcop. */ -int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t, - flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); +int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t, + u8 chipaddr, u8 addr, u8 *buf, u16 len); /* from flexcop-sram.c */ int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target); diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c index bbcf070a178d..8a8ae8a3e6ba 100644 --- a/drivers/media/dvb/b2c2/flexcop-eeprom.c +++ b/drivers/media/dvb/b2c2/flexcop-eeprom.c @@ -114,15 +114,18 @@ static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t { int i,ret = 0; u8 chipaddr = 0x50 | ((addr >> 8) & 3); - for (i = 0; i < retries; i++) - if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0) + for (i = 0; i < retries; i++) { + ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr, + addr & 0xff, buf, len); + if (ret == 0) break; + } return ret; } static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries) { - int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries); + int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries); if (ret == 0) if (calc_lrc(buf, len - 1) != buf[len - 1]) ret = -EINVAL; diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 441ffdf0d9c9..46d6f5d8cd1c 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -183,13 +183,13 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv buf[2] = 0x84; /* 0xC4 */ buf[3] = 0x08; - if (params->frequency < 1500000) buf[3] |= 0x10; + if (params->frequency < 1500000) + buf[3] |= 0x10; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) { + if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1) return -EIO; - } return 0; } @@ -340,7 +340,7 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) + if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -389,10 +389,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]); - ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3); + ret = fc->i2c_request(&fc->fc_i2c_adap[2], + FC_WRITE, 0x61, buf[0], &buf[1], 3); deb_tuner("tuner write returned: %d\n",ret); - return 0; + return ret; } static u8 alps_tdee4_stv0297_inittab[] = { @@ -479,53 +480,67 @@ static struct stv0297_config alps_tdee4_stv0297_config = { int flexcop_frontend_init(struct flexcop_device *fc) { struct dvb_frontend_ops *ops; + struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap; /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ - if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) { + fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); + if (fc->fe != NULL) { ops = &fc->fe->ops; ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params; ops->set_voltage = flexcop_set_voltage; - fc->fe_sleep = ops->sleep; - ops->sleep = flexcop_sleep; + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; + + fc->dev_type = FC_SKY; + goto fe_found; + } - fc->dev_type = FC_SKY; - info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address); - } else /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */ - if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) { - fc->dev_type = FC_AIR_DVB; + fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); + if (fc->fe != NULL) { + fc->dev_type = FC_AIR_DVB; fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; - info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); - } else + goto fe_found; + } + /* try the air atsc 2nd generation (nxt2002) */ - if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) { - fc->dev_type = FC_AIR_ATSC2; + fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); + if (fc->fe != NULL) { + fc->dev_type = FC_AIR_ATSC2; dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV); - info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); - } else - /* try the air atsc 3nd generation (lgdt3303) */ - if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { - fc->dev_type = FC_AIR_ATSC3; - dvb_attach(simple_tuner_attach, fc->fe, - &fc->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF); - info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); - } else + goto fe_found; + } + + fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); + if (fc->fe != NULL) { + fc->dev_type = FC_AIR_ATSC3; + dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, + TUNER_LG_TDVS_H06XF); + goto fe_found; + } + /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ - if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) { - fc->dev_type = FC_AIR_ATSC1; - info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address); - } else + fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); + if (fc->fe != NULL) { + fc->dev_type = FC_AIR_ATSC1; + goto fe_found; + } + /* try the cable dvb (stv0297) */ - if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) { - fc->dev_type = FC_CABLE; + fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); + if (fc->fe != NULL) { + fc->dev_type = FC_CABLE; fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; - info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address); - } else + goto fe_found; + } + /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ - if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { + fc->fe = dvb_attach(vp310_mt312_attach, + &skystar23_samsung_tbdu18132_config, i2c); + if (fc->fe != NULL) { ops = &fc->fe->ops; ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params; @@ -539,19 +554,21 @@ int flexcop_frontend_init(struct flexcop_device *fc) ops->sleep = flexcop_sleep; fc->dev_type = FC_SKY_OLD; - info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address); + goto fe_found; } - if (fc->fe == NULL) { - err("no frontend driver found for this B2C2/FlexCop adapter"); - return -ENODEV; - } else { - if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { - err("frontend registration failed!"); - dvb_frontend_detach(fc->fe); - fc->fe = NULL; - return -EINVAL; - } + err("no frontend driver found for this B2C2/FlexCop adapter"); + return -ENODEV; + +fe_found: + info("found '%s' .", fc->fe->ops.info.name); + if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { + err("frontend registration failed!"); + ops = &fc->fe->ops; + if (ops->release != NULL) + ops->release(fc->fe); + fc->fe = NULL; + return -EINVAL; } fc->init_state |= FC_STATE_FE_INIT; return 0; diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c index 6bf858a436c9..55973eaf3711 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -9,6 +9,8 @@ #define FC_MAX_I2C_RETRIES 100000 +/* #define DUMP_I2C_MESSAGES */ + static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100) { int i; @@ -38,30 +40,25 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r return -EREMOTEIO; } -static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf) +static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c, + flexcop_ibi_value r100, u8 *buf) { flexcop_ibi_value r104; int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ ret; - if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) { - /* The Cablestar needs a different kind of i2c-transfer (does not - * support "Repeat Start"): - * wait for the ACK failure, - * and do a subsequent read with the Bit 30 enabled - */ - r100.tw_sm_c_100.no_base_addr_ack_error = 1; - if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) { - deb_i2c("no_base_addr read failed. %d\n",ret); - return ret; - } + r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; + ret = flexcop_i2c_operation(i2c->fc, &r100); + if (ret != 0) { + deb_i2c("read failed. %d\n", ret); + return ret; } buf[0] = r100.tw_sm_c_100.data1_reg; if (len > 0) { - r104 = fc->read_ibi_reg(fc,tw_sm_c_104); - deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw); + r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104); + deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw); /* there is at least one more byte, otherwise we wouldn't be here */ buf[1] = r104.tw_sm_c_104.data2_reg; @@ -85,17 +82,22 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0; r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0; - deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw); + deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw); /* write the additional i2c data before doing the actual i2c operation */ - fc->write_ibi_reg(fc,tw_sm_c_104,r104); - return flexcop_i2c_operation(fc,&r100); + fc->write_ibi_reg(fc, tw_sm_c_104, r104); + return flexcop_i2c_operation(fc, &r100); } -int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, - flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len) +int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c, + flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) { int ret; + +#ifdef DUMP_I2C_MESSAGES + int i; +#endif + u16 bytes_to_transfer; flexcop_ibi_value r100; @@ -103,7 +105,25 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, r100.raw = 0; r100.tw_sm_c_100.chipaddr = chipaddr; r100.tw_sm_c_100.twoWS_rw = op; - r100.tw_sm_c_100.twoWS_port_reg = port; + r100.tw_sm_c_100.twoWS_port_reg = i2c->port; + +#ifdef DUMP_I2C_MESSAGES + printk(KERN_DEBUG "%d ", i2c->port); + if (op == FC_READ) + printk("rd("); + else + printk("wr("); + + printk("%02x): %02x ", chipaddr, addr); +#endif + + /* in that case addr is the only value -> + * we write it twice as baseaddr and val0 + * BBTI is doing it like that for ISL6421 at least */ + if (i2c->no_base_addr && len == 0 && op == FC_WRITE) { + buf = &addr; + len = 1; + } while (len != 0) { bytes_to_transfer = len > 4 ? 4 : len; @@ -112,9 +132,14 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, r100.tw_sm_c_100.baseaddr = addr; if (op == FC_READ) - ret = flexcop_i2c_read4(fc, r100, buf); + ret = flexcop_i2c_read4(i2c, r100, buf); else - ret = flexcop_i2c_write4(fc,r100, buf); + ret = flexcop_i2c_write4(i2c->fc, r100, buf); + +#ifdef DUMP_I2C_MESSAGES + for (i = 0; i < bytes_to_transfer; i++) + printk("%02x ", buf[i]); +#endif if (ret < 0) return ret; @@ -122,7 +147,11 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, buf += bytes_to_transfer; addr += bytes_to_transfer; len -= bytes_to_transfer; - }; + } + +#ifdef DUMP_I2C_MESSAGES + printk("\n"); +#endif return 0; } @@ -132,7 +161,7 @@ EXPORT_SYMBOL(flexcop_i2c_request); /* master xfer callback for demodulator */ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) { - struct flexcop_device *fc = i2c_get_adapdata(i2c_adap); + struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); int i, ret = 0; /* Some drivers use 1 byte or 0 byte reads as probes, which this @@ -142,34 +171,29 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1) return 1; - if (mutex_lock_interruptible(&fc->i2c_mutex)) + if (mutex_lock_interruptible(&i2c->fc->i2c_mutex)) return -ERESTARTSYS; - /* reading */ - if (num == 2 && - msgs[0].flags == 0 && - msgs[1].flags == I2C_M_RD && - msgs[0].buf != NULL && - msgs[1].buf != NULL) { - - ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len); - - } else for (i = 0; i < num; i++) { /* writing command */ - if (msgs[i].flags != 0 || msgs[i].buf == NULL || msgs[i].len < 2) { - ret = -EINVAL; + for (i = 0; i < num; i++) { + /* reading */ + if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) { + ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr, + msgs[i].buf[0], msgs[i+1].buf, msgs[i+1].len); + i++; /* skip the following message */ + } else /* writing */ + ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr, + msgs[i].buf[0], &msgs[i].buf[1], + msgs[i].len - 1); + if (ret < 0) { + err("i2c master_xfer failed"); break; } - - ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_DEMOD, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1); } - if (ret < 0) - err("i2c master_xfer failed"); - else - ret = num; - - mutex_unlock(&fc->i2c_mutex); + mutex_unlock(&i2c->fc->i2c_mutex); + if (ret == 0) + ret = num; return ret; } @@ -189,28 +213,68 @@ int flexcop_i2c_init(struct flexcop_device *fc) mutex_init(&fc->i2c_mutex); - memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter)); - strncpy(fc->i2c_adap.name, "B2C2 FlexCop device", - sizeof(fc->i2c_adap.name)); - - i2c_set_adapdata(&fc->i2c_adap,fc); + fc->fc_i2c_adap[0].fc = fc; + fc->fc_i2c_adap[1].fc = fc; + fc->fc_i2c_adap[2].fc = fc; + + fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD; + fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM; + fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER; + + strncpy(fc->fc_i2c_adap[0].i2c_adap.name, + "B2C2 FlexCop I2C to demod", I2C_NAME_SIZE); + strncpy(fc->fc_i2c_adap[1].i2c_adap.name, + "B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE); + strncpy(fc->fc_i2c_adap[2].i2c_adap.name, + "B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE); + + i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]); + i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]); + i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]); + + fc->fc_i2c_adap[0].i2c_adap.class = + fc->fc_i2c_adap[1].i2c_adap.class = + fc->fc_i2c_adap[2].i2c_adap.class = I2C_CLASS_TV_DIGITAL; + fc->fc_i2c_adap[0].i2c_adap.algo = + fc->fc_i2c_adap[1].i2c_adap.algo = + fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo; + fc->fc_i2c_adap[0].i2c_adap.algo_data = + fc->fc_i2c_adap[1].i2c_adap.algo_data = + fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL; + fc->fc_i2c_adap[0].i2c_adap.dev.parent = + fc->fc_i2c_adap[1].i2c_adap.dev.parent = + fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev; + + ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap); + if (ret < 0) + return ret; - fc->i2c_adap.class = I2C_CLASS_TV_DIGITAL; - fc->i2c_adap.algo = &flexcop_algo; - fc->i2c_adap.algo_data = NULL; - fc->i2c_adap.dev.parent = fc->dev; + ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap); + if (ret < 0) + goto adap_1_failed; - if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0) - return ret; + ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap); + if (ret < 0) + goto adap_2_failed; fc->init_state |= FC_STATE_I2C_INIT; return 0; + +adap_2_failed: + i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); +adap_1_failed: + i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); + + return ret; } void flexcop_i2c_exit(struct flexcop_device *fc) { - if (fc->init_state & FC_STATE_I2C_INIT) - i2c_del_adapter(&fc->i2c_adap); + if (fc->init_state & FC_STATE_I2C_INIT) { + i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap); + i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); + i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); + } fc->init_state &= ~FC_STATE_I2C_INIT; } diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c index 87fb75f0d1cf..449fb5c3d0b1 100644 --- a/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/drivers/media/dvb/b2c2/flexcop-usb.c @@ -211,10 +211,11 @@ static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set, #endif /* usb i2c stuff */ -static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb, +static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, - flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 buflen) + u8 chipaddr, u8 addr, u8 *buf, u8 buflen) { + struct flexcop_usb *fc_usb = i2c->fc->bus_specific; u16 wValue, wIndex; int nWaitTime,pipe,len; // u8 dwRequestType; @@ -242,7 +243,7 @@ static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb, deb_info("unsupported function for i2c_req %x\n",func); return -EINVAL; } - wValue = (func << 8 ) | (port << 4); + wValue = (func << 8) | (i2c->port << 4); wIndex = (chipaddr << 8 ) | addr; deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req, @@ -274,13 +275,15 @@ static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0); } -static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, - flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len) +static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c, + flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) { if (op == FC_READ) - return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len); + return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST, + USB_FUNC_I2C_READ, chipaddr, addr, buf, len); else - return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len); + return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST, + USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len); } static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length) diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index 2ddafd071c97..205146c24129 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c @@ -257,6 +257,12 @@ int flexcop_device_initialize(struct flexcop_device *fc) if ((ret = flexcop_dvb_init(fc))) goto error; + /* i2c has to be done before doing EEProm stuff - + * because the EEProm is accessed via i2c */ + ret = flexcop_i2c_init(fc); + if (ret) + goto error; + /* do the MAC address reading after initializing the dvb_adapter */ if (fc->get_mac_addr(fc, 0) == 0) { u8 *b = fc->dvb_adapter.proposed_mac; @@ -266,10 +272,6 @@ int flexcop_device_initialize(struct flexcop_device *fc) } else warn("reading of MAC address failed.\n"); - - if ((ret = flexcop_i2c_init(fc))) - goto error; - if ((ret = flexcop_frontend_init(fc))) goto error; -- cgit v1.2.3 From d097148fc9d91c66a422227e8c581b17f2a62741 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 29 Mar 2008 18:01:12 -0300 Subject: V4L/DVB (7470): CX24123: preparing support for CX24113 tuner To support a new device based on CX24123 (using the CX24113-tuner) the following was done: - added two parameters to de-select the internal PLL-driver (for CX24108) and a AGC-function callback. - added a virtual i2c-adapter which allow simple access behind the i2c-gate - cleanup up some code Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24123.c | 304 +++++++++++++++++++++++----------- drivers/media/dvb/frontends/cx24123.h | 21 ++- 2 files changed, 220 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index d74fdbd63361..7f68d78c6558 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -1,24 +1,26 @@ /* - Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver - - Copyright (C) 2005 Steven Toth - - Support for KWorld DVB-S 100 by Vadim Catana - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ + * Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver + * + * Copyright (C) 2005 Steven Toth + * + * Support for KWorld DVB-S 100 by Vadim Catana + * + * Support for CX24123/CX24113-NIM by Patrick Boettcher + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ #include #include @@ -32,9 +34,16 @@ static int force_band; static int debug; + +#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0) +#define err(args...) do { printk(KERN_ERR "CX24123: " args); } while (0) + #define dprintk(args...) \ do { \ - if (debug) printk (KERN_DEBUG "cx24123: " args); \ + if (debug) { \ + printk(KERN_DEBUG "CX24123: %s: ", __func__); \ + printk(args); \ + } \ } while (0) struct cx24123_state @@ -51,6 +60,10 @@ struct cx24123_state u32 pllarg; u32 FILTune; + struct i2c_adapter tuner_i2c_adapter; + + u8 demod_rev; + /* The Demod/Tuner can't easily provide these, we cache them */ u32 currentfreq; u32 currentsymbolrate; @@ -225,48 +238,52 @@ static struct { {0x67, 0x83}, /* Non-DCII symbol clock */ }; -static int cx24123_writereg(struct cx24123_state* state, int reg, int data) +static int cx24123_i2c_writereg(struct cx24123_state *state, + u8 i2c_addr, int reg, int data) { u8 buf[] = { reg, data }; - struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; + struct i2c_msg msg = { + .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2 + }; int err; - if (debug>1) - printk("cx24123: %s: write reg 0x%02x, value 0x%02x\n", - __FUNCTION__,reg, data); + /* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { printk("%s: writereg error(err == %i, reg == 0x%02x," - " data == 0x%02x)\n", __FUNCTION__, err, reg, data); - return -EREMOTEIO; + " data == 0x%02x)\n", __func__, err, reg, data); + return err; } return 0; } -static int cx24123_readreg(struct cx24123_state* state, u8 reg) +static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg) { int ret; - u8 b0[] = { reg }; - u8 b1[] = { 0 }; + u8 b = 0; struct i2c_msg msg[] = { - { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } + { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 }, + { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &b, .len = 1 } }; ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { - printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret); + err("%s: reg=0x%x (error=%d)\n", __func__, reg, ret); return ret; } - if (debug>1) - printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret); + /* printk(KERN_DEBUG "rd(%02x): %02x %02x\n", i2c_addr, reg, b); */ - return b1[0]; + return b; } +#define cx24123_readreg(state, reg) \ + cx24123_i2c_readreg(state, state->config->demod_address, reg) +#define cx24123_writereg(state, reg, val) \ + cx24123_i2c_writereg(state, state->config->demod_address, reg, val) + static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) { u8 nom_reg = cx24123_readreg(state, 0x0e); @@ -274,17 +291,17 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers switch (inversion) { case INVERSION_OFF: - dprintk("%s: inversion off\n",__FUNCTION__); + dprintk("inversion off\n"); cx24123_writereg(state, 0x0e, nom_reg & ~0x80); cx24123_writereg(state, 0x10, auto_reg | 0x80); break; case INVERSION_ON: - dprintk("%s: inversion on\n",__FUNCTION__); + dprintk("inversion on\n"); cx24123_writereg(state, 0x0e, nom_reg | 0x80); cx24123_writereg(state, 0x10, auto_reg | 0x80); break; case INVERSION_AUTO: - dprintk("%s: inversion auto\n",__FUNCTION__); + dprintk("inversion auto\n"); cx24123_writereg(state, 0x10, auto_reg & ~0x80); break; default: @@ -301,10 +318,10 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers val = cx24123_readreg(state, 0x1b) >> 7; if (val == 0) { - dprintk("%s: read inversion off\n",__FUNCTION__); + dprintk("read inversion off\n"); *inversion = INVERSION_OFF; } else { - dprintk("%s: read inversion on\n",__FUNCTION__); + dprintk("read inversion on\n"); *inversion = INVERSION_ON; } @@ -326,42 +343,42 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) switch (fec) { case FEC_1_2: - dprintk("%s: set FEC to 1/2\n",__FUNCTION__); + dprintk("set FEC to 1/2\n"); cx24123_writereg(state, 0x0e, nom_reg | 0x01); cx24123_writereg(state, 0x0f, 0x02); break; case FEC_2_3: - dprintk("%s: set FEC to 2/3\n",__FUNCTION__); + dprintk("set FEC to 2/3\n"); cx24123_writereg(state, 0x0e, nom_reg | 0x02); cx24123_writereg(state, 0x0f, 0x04); break; case FEC_3_4: - dprintk("%s: set FEC to 3/4\n",__FUNCTION__); + dprintk("set FEC to 3/4\n"); cx24123_writereg(state, 0x0e, nom_reg | 0x03); cx24123_writereg(state, 0x0f, 0x08); break; case FEC_4_5: - dprintk("%s: set FEC to 4/5\n",__FUNCTION__); + dprintk("set FEC to 4/5\n"); cx24123_writereg(state, 0x0e, nom_reg | 0x04); cx24123_writereg(state, 0x0f, 0x10); break; case FEC_5_6: - dprintk("%s: set FEC to 5/6\n",__FUNCTION__); + dprintk("set FEC to 5/6\n"); cx24123_writereg(state, 0x0e, nom_reg | 0x05); cx24123_writereg(state, 0x0f, 0x20); break; case FEC_6_7: - dprintk("%s: set FEC to 6/7\n",__FUNCTION__); + dprintk("set FEC to 6/7\n"); cx24123_writereg(state, 0x0e, nom_reg | 0x06); cx24123_writereg(state, 0x0f, 0x40); break; case FEC_7_8: - dprintk("%s: set FEC to 7/8\n",__FUNCTION__); + dprintk("set FEC to 7/8\n"); cx24123_writereg(state, 0x0e, nom_reg | 0x07); cx24123_writereg(state, 0x0f, 0x80); break; case FEC_AUTO: - dprintk("%s: set FEC to auto\n",__FUNCTION__); + dprintk("set FEC to auto\n"); cx24123_writereg(state, 0x0f, 0xfe); break; default: @@ -490,7 +507,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) tmp = cx24123_readreg(state, 0x0c) & ~0xe0; cx24123_writereg(state, 0x0c, tmp | sample_gain << 5); - dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain); + dprintk("srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", + srate, ratio, sample_rate, sample_gain); return 0; } @@ -570,7 +588,7 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par struct cx24123_state *state = fe->demodulator_priv; unsigned long timeout; - dprintk("%s: pll writereg called, data=0x%08x\n",__FUNCTION__,data); + dprintk("pll writereg called, data=0x%08x\n", data); /* align the 21 bytes into to bit23 boundary */ data = data << 3; @@ -583,7 +601,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par cx24123_writereg(state, 0x22, (data >> 16) & 0xff); while ((cx24123_readreg(state, 0x20) & 0x40) == 0) { if (time_after(jiffies, timeout)) { - printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__); + err("%s: demodulator is not responding, "\ + "possibly hung, aborting.\n", __func__); return -EREMOTEIO; } msleep(10); @@ -594,7 +613,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par cx24123_writereg(state, 0x22, (data>>8) & 0xff ); while ((cx24123_readreg(state, 0x20) & 0x40) == 0) { if (time_after(jiffies, timeout)) { - printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__); + err("%s: demodulator is not responding, "\ + "possibly hung, aborting.\n", __func__); return -EREMOTEIO; } msleep(10); @@ -605,7 +625,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par cx24123_writereg(state, 0x22, (data) & 0xff ); while ((cx24123_readreg(state, 0x20) & 0x80)) { if (time_after(jiffies, timeout)) { - printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__); + err("%s: demodulator is not responding," \ + "possibly hung, aborting.\n", __func__); return -EREMOTEIO; } msleep(10); @@ -626,7 +647,7 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet dprintk("frequency=%i\n", p->frequency); if (cx24123_pll_calculate(fe, p) != 0) { - printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); + err("%s: cx24123_pll_calcutate failed\n", __func__); return -EINVAL; } @@ -643,18 +664,38 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet cx24123_writereg(state, 0x27, state->FILTune >> 2); cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3)); - dprintk("%s: pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg, - state->bandselectarg,state->pllarg); + dprintk("pll tune VCA=%d, band=%d, pll=%d\n", state->VCAarg, + state->bandselectarg, state->pllarg); return 0; } + +/* + * 0x23: + * [7:7] = BTI enabled + * [6:6] = I2C repeater enabled + * [5:5] = I2C repeater start + * [0:0] = BTI start + */ + +/* mode == 1 -> i2c-repeater, 0 -> bti */ +static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start) +{ + u8 r = cx24123_readreg(state, 0x23) & 0x1e; + if (mode) + r |= (1 << 6) | (start << 5); + else + r |= (1 << 7) | (start); + return cx24123_writereg(state, 0x23, r); +} + static int cx24123_initfe(struct dvb_frontend* fe) { struct cx24123_state *state = fe->demodulator_priv; int i; - dprintk("%s: init frontend\n",__FUNCTION__); + dprintk("init frontend\n"); /* Configure the demod to a good set of defaults */ for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++) @@ -664,6 +705,9 @@ static int cx24123_initfe(struct dvb_frontend* fe) if(state->config->lnb_polarity) cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02); + if (state->config->dont_use_pll) + cx24123_repeater_mode(state, 1, 0); + return 0; } @@ -676,10 +720,10 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage switch (voltage) { case SEC_VOLTAGE_13: - dprintk("%s: setting voltage 13V\n", __FUNCTION__); + dprintk("setting voltage 13V\n"); return cx24123_writereg(state, 0x29, val & 0x7f); case SEC_VOLTAGE_18: - dprintk("%s: setting voltage 18V\n", __FUNCTION__); + dprintk("setting voltage 18V\n"); return cx24123_writereg(state, 0x29, val | 0x80); case SEC_VOLTAGE_OFF: /* already handled in cx88-dvb */ @@ -697,7 +741,8 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state) unsigned long timeout = jiffies + msecs_to_jiffies(200); while (!(cx24123_readreg(state, 0x29) & 0x40)) { if(time_after(jiffies, timeout)) { - printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__); + err("%s: diseqc queue not ready, " \ + "command may be lost.\n", __func__); break; } msleep(10); @@ -709,7 +754,7 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma struct cx24123_state *state = fe->demodulator_priv; int i, val, tone; - dprintk("%s:\n",__FUNCTION__); + dprintk("\n"); /* stop continuous tone if enabled */ tone = cx24123_readreg(state, 0x29); @@ -744,7 +789,7 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t struct cx24123_state *state = fe->demodulator_priv; int val, tone; - dprintk("%s:\n", __FUNCTION__); + dprintk("\n"); /* stop continuous tone if enabled */ tone = cx24123_readreg(state, 0x29); @@ -778,13 +823,21 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct cx24123_state *state = fe->demodulator_priv; - int sync = cx24123_readreg(state, 0x14); - int lock = cx24123_readreg(state, 0x20); *status = 0; - if (lock & 0x01) - *status |= FE_HAS_SIGNAL; + if (state->config->dont_use_pll) { + u32 tun_status = 0; + if (fe->ops.tuner_ops.get_status) + fe->ops.tuner_ops.get_status(fe, &tun_status); + if (tun_status & TUNER_STATUS_LOCKED) + *status |= FE_HAS_SIGNAL; + } else { + int lock = cx24123_readreg(state, 0x20); + if (lock & 0x01) + *status |= FE_HAS_SIGNAL; + } + if (sync & 0x02) *status |= FE_HAS_CARRIER; /* Phase locked */ if (sync & 0x04) @@ -803,7 +856,7 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) * Configured to return the measurement of errors in blocks, because no UCBLOCKS value * is available, so this value doubles up to satisfy both measurements */ -static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber) +static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber) { struct cx24123_state *state = fe->demodulator_priv; @@ -813,23 +866,24 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber) (cx24123_readreg(state, 0x1d) << 8 | cx24123_readreg(state, 0x1e)); - dprintk("%s: BER = %d\n",__FUNCTION__,*ber); + dprintk("BER = %d\n", *ber); return 0; } -static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) +static int cx24123_read_signal_strength(struct dvb_frontend *fe, + u16 *signal_strength) { struct cx24123_state *state = fe->demodulator_priv; *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */ - dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength); + dprintk("Signal strength = %d\n", *signal_strength); return 0; } -static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr) +static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr) { struct cx24123_state *state = fe->demodulator_priv; @@ -838,16 +892,17 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr) *snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) | (u16)cx24123_readreg(state, 0x19)); - dprintk("%s: read S/N index = %d\n",__FUNCTION__,*snr); + dprintk("read S/N index = %d\n", *snr); return 0; } -static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +static int cx24123_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) { struct cx24123_state *state = fe->demodulator_priv; - dprintk("%s: set_frontend\n",__FUNCTION__); + dprintk("\n"); if (state->config->set_ts_params) state->config->set_ts_params(fe, 0); @@ -858,13 +913,22 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par cx24123_set_inversion(state, p->inversion); cx24123_set_fec(state, p->u.qpsk.fec_inner); cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate); - cx24123_pll_tune(fe, p); + + if (!state->config->dont_use_pll) + cx24123_pll_tune(fe, p); + else if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, p); + else + err("it seems I don't have a tuner..."); /* Enable automatic aquisition and reset cycle */ cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07)); cx24123_writereg(state, 0x00, 0x10); cx24123_writereg(state, 0x00, 0); + if (state->config->agc_callback) + state->config->agc_callback(fe); + return 0; } @@ -872,14 +936,14 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par { struct cx24123_state *state = fe->demodulator_priv; - dprintk("%s: get_frontend\n",__FUNCTION__); + dprintk("\n"); if (cx24123_get_inversion(state, &p->inversion) != 0) { - printk("%s: Failed to get inversion status\n",__FUNCTION__); + err("%s: Failed to get inversion status\n", __func__); return -EREMOTEIO; } if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) { - printk("%s: Failed to get fec status\n",__FUNCTION__); + err("%s: Failed to get fec status\n", __func__); return -EREMOTEIO; } p->frequency = state->currentfreq; @@ -900,13 +964,13 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) switch (tone) { case SEC_TONE_ON: - dprintk("%s: setting tone on\n", __FUNCTION__); + dprintk("setting tone on\n"); return cx24123_writereg(state, 0x29, val | 0x10); case SEC_TONE_OFF: - dprintk("%s: setting tone off\n",__FUNCTION__); + dprintk("setting tone off\n"); return cx24123_writereg(state, 0x29, val & 0xef); default: - printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); + err("CASE reached default with tone=%d\n", tone); return -EINVAL; } @@ -939,47 +1003,86 @@ static int cx24123_get_algo(struct dvb_frontend *fe) static void cx24123_release(struct dvb_frontend* fe) { struct cx24123_state* state = fe->demodulator_priv; - dprintk("%s\n",__FUNCTION__); + dprintk("\n"); + i2c_del_adapter(&state->tuner_i2c_adapter); kfree(state); } +static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) +{ + struct cx24123_state *state = i2c_get_adapdata(i2c_adap); + /* this repeater closes after the first stop */ + cx24123_repeater_mode(state, 1, 1); + return i2c_transfer(state->i2c, msg, num); +} + +static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm cx24123_tuner_i2c_algo = { + .master_xfer = cx24123_tuner_i2c_tuner_xfer, + .functionality = cx24123_tuner_i2c_func, +}; + +struct i2c_adapter * + cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe) +{ + struct cx24123_state *state = fe->demodulator_priv; + return &state->tuner_i2c_adapter; +} +EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter); + static struct dvb_frontend_ops cx24123_ops; struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, struct i2c_adapter* i2c) { - struct cx24123_state* state = NULL; - int ret; - - dprintk("%s\n",__FUNCTION__); + struct cx24123_state *state = + kzalloc(sizeof(struct cx24123_state), GFP_KERNEL); + dprintk("\n"); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL); if (state == NULL) { - printk("Unable to kmalloc\n"); + err("Unable to kmalloc\n"); goto error; } /* setup the state */ state->config = config; state->i2c = i2c; - state->VCAarg = 0; - state->VGAarg = 0; - state->bandselectarg = 0; - state->pllarg = 0; - state->currentfreq = 0; - state->currentsymbolrate = 0; /* check if the demod is there */ - ret = cx24123_readreg(state, 0x00); - if ((ret != 0xd1) && (ret != 0xe1)) { - printk("Version != d1 or e1\n"); + state->demod_rev = cx24123_readreg(state, 0x00); + switch (state->demod_rev) { + case 0xe1: info("detected CX24123C\n"); break; + case 0xd1: info("detected CX24123\n"); break; + default: + err("wrong demod revision: %x\n", state->demod_rev); goto error; } /* create dvb_frontend */ memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; + + /* create tuner i2c adapter */ + if (config->dont_use_pll) + cx24123_repeater_mode(state, 1, 0); + + strncpy(state->tuner_i2c_adapter.name, + "CX24123 tuner I2C bus", I2C_NAME_SIZE); + state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL, + state->tuner_i2c_adapter.algo = &cx24123_tuner_i2c_algo; + state->tuner_i2c_adapter.algo_data = NULL; + i2c_set_adapdata(&state->tuner_i2c_adapter, state); + if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) { + err("tuner i2c bus could not be initialized\n"); + goto error; + } + return &state->frontend; error: @@ -1029,7 +1132,8 @@ MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); module_param(force_band, int, 0644); MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off)."); -MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware"); +MODULE_DESCRIPTION("DVB Frontend module for Conexant " \ + "CX24123/CX24109/CX24113 hardware"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h index 84f9e4f5c15e..81ebc3d2f19f 100644 --- a/drivers/media/dvb/frontends/cx24123.h +++ b/drivers/media/dvb/frontends/cx24123.h @@ -33,16 +33,27 @@ struct cx24123_config /* 0 = LNB voltage normal, 1 = LNB voltage inverted */ int lnb_polarity; + + /* this device has another tuner */ + u8 dont_use_pll; + void (*agc_callback) (struct dvb_frontend *); }; #if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE)) -extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, - struct i2c_adapter* i2c); +extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config, + struct i2c_adapter *i2c); +extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *); #else -static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, - struct i2c_adapter* i2c) +static inline struct dvb_frontend *cx24123_attach( + const struct cx24123_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +static struct i2c_adapter * + cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif // CONFIG_DVB_CX24123 -- cgit v1.2.3 From 7a79ce4668635c94c0cc793225412a3f4a0e74da Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 29 Mar 2008 18:28:07 -0300 Subject: V4L/DVB (7471): SkyStar2: preparing support for the rev2.8 Support is prepared, but the CX24113-driver .c-file is missing. After sorting out the NDA problems, the file will be there immediatly. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/Kconfig | 2 ++ drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 48 +++++++++++++++++++++++++++++++ drivers/media/dvb/b2c2/flexcop-misc.c | 2 ++ drivers/media/dvb/b2c2/flexcop-reg.h | 2 ++ drivers/media/dvb/frontends/cx24113.h | 48 +++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 drivers/media/dvb/frontends/cx24113.h (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index ffcbc7610856..8193d88d171c 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -10,6 +10,8 @@ config DVB_B2C2_FLEXCOP select DVB_BCM3510 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select DVB_ISL6421 if !DVB_FE_CUSTOMISE + select DVB_CX24123 if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 46d6f5d8cd1c..6759c3ad234a 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -19,6 +19,11 @@ #include "dvb-pll.h" #include "tuner-simple.h" +#include "cx24123.h" +#include "cx24113.h" + +#include "isl6421.h" + /* lnb control */ static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) @@ -476,11 +481,54 @@ static struct stv0297_config alps_tdee4_stv0297_config = { // .pll_set = alps_tdee4_stv0297_pll_set, }; + +static struct cx24123_config skystar2_rev2_8_cx24123_config = { + .demod_address = 0x55, + .dont_use_pll = 1, + .agc_callback = cx24113_agc_callback, +}; + +static const struct cx24113_config skystar2_rev2_8_cx24113_config = { + .i2c_addr = 0x54, + .xtal_khz = 10111, +}; + /* try to figure out the frontend, each card/box can have on of the following list */ int flexcop_frontend_init(struct flexcop_device *fc) { struct dvb_frontend_ops *ops; struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap; + struct i2c_adapter *i2c_tuner; + + /* try the sky v2.8 (cx24123, isl6421) */ + fc->fe = dvb_attach(cx24123_attach, + &skystar2_rev2_8_cx24123_config, i2c); + if (fc->fe != NULL) { + i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe); + if (i2c_tuner != NULL) { + if (dvb_attach(cx24113_attach, fc->fe, + &skystar2_rev2_8_cx24113_config, + i2c_tuner) == NULL) + err("CX24113 could NOT be attached"); + else + info("CX24113 successfully attached"); + } + + fc->dev_type = FC_SKY_REV28; + + fc->fc_i2c_adap[2].no_base_addr = 1; + if (dvb_attach(isl6421_attach, fc->fe, + &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL) + err("ISL6421 could NOT be attached"); + else + info("ISL6421 successfully attached"); + + /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an + * IR-receiver (PIC16F818) - but the card has no input for + * that ??? */ + + goto fe_found; + } /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c index 167583bf0621..93d20e56f909 100644 --- a/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/drivers/media/dvb/b2c2/flexcop-misc.c @@ -52,6 +52,8 @@ static const char *flexcop_device_names[] = { "Sky2PC/SkyStar 2 DVB-S (old version)", "Cable2PC/CableStar 2 DVB-C", "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", + "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", + "Sky2PC/SkyStar 2 DVB-S rev 2.8", }; static const char *flexcop_bus_names[] = { diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 491f9bd6e195..7599fccc1a5b 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/dvb/b2c2/flexcop-reg.h @@ -25,6 +25,8 @@ typedef enum { FC_SKY_OLD, FC_CABLE, FC_AIR_ATSC3, + FC_SKY_REV27, + FC_SKY_REV28, } flexcop_device_type_t; typedef enum { diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h new file mode 100644 index 000000000000..5ab3dd11076b --- /dev/null +++ b/drivers/media/dvb/frontends/cx24113.h @@ -0,0 +1,48 @@ +/* + * Driver for Conexant CX24113/CX24128 Tuner (Satelite) + * + * Copyright (C) 2007-8 Patrick Boettcher + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + */ + +#ifndef CX24113_H +#define CX24113_H + +struct dvb_frontend; + +struct cx24113_config { + u8 i2c_addr; /* 0x14 or 0x54 */ + + u32 xtal_khz; +}; + +/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \ + * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */ + +static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, + const struct cx24113_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +static inline void cx24113_agc_callback(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); +} + +#endif /* CX24113_H */ -- cgit v1.2.3 From 0dc42fa6b8237c3d348e6994d9ab17cf185690a0 Mon Sep 17 00:00:00 2001 From: Andre Weidemann Date: Sat, 29 Mar 2008 18:30:49 -0300 Subject: V4L/DVB (7472): reworked patch to support TT connect S-2400 Added support for Technotrend connect S-2400. Signed-off-by: Andre Weidemann Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 ++ drivers/media/dvb/dvb-usb/ttusb2.c | 62 ++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index aa4844ef875e..2cbfd6694cf9 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -40,6 +40,7 @@ #define USB_VID_MSI 0x0db0 #define USB_VID_OPERA1 0x695c #define USB_VID_PINNACLE 0x2304 +#define USB_VID_TECHNOTREND 0x0b48 #define USB_VID_TERRATEC 0x0ccd #define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_TWINHAN 0x1822 @@ -134,6 +135,7 @@ #define USB_PID_AVERMEDIA_EXPRESS 0xb568 #define USB_PID_AVERMEDIA_VOLAR 0xa807 #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 +#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c index 3b9da9c25c6e..0eb33378254b 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -176,17 +176,23 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap) /* DVB USB Driver stuff */ static struct dvb_usb_device_properties ttusb2_properties; +static struct dvb_usb_device_properties ttusb2_properties_s2400; static int ttusb2_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL); + if (dvb_usb_device_init(intf, &ttusb2_properties, THIS_MODULE, NULL) == 0 || + dvb_usb_device_init(intf, &ttusb2_properties_s2400, THIS_MODULE, NULL) == 0) + return 0; + return -ENODEV; } static struct usb_device_id ttusb2_table [] = { - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) }, - {} /* Terminating entry */ + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) }, + { USB_DEVICE(USB_VID_TECHNOTREND, + USB_PID_TECHNOTREND_CONNECT_S2400) }, + {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, ttusb2_table); @@ -242,6 +248,54 @@ static struct dvb_usb_device_properties ttusb2_properties = { } }; +static struct dvb_usb_device_properties ttusb2_properties_s2400 = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = CYPRESS_FX2, + .firmware = "dvb-usb-tt-s2400-01.fw", + + .size_of_priv = sizeof(struct ttusb2_state), + + .num_adapters = 1, + .adapter = { + { + .streaming_ctrl = NULL, + + .frontend_attach = ttusb2_frontend_attach, + .tuner_attach = ttusb2_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_ISOC, + .count = 5, + .endpoint = 0x02, + .u = { + .isoc = { + .framesperurb = 4, + .framesize = 940, + .interval = 1, + } + } + } + } + }, + + .power_ctrl = ttusb2_power_ctrl, + .identify_state = ttusb2_identify_state, + + .i2c_algo = &ttusb2_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + + .num_device_descs = 1, + .devices = { + { "Technotrend TT-connect S-2400", + { &ttusb2_table[2], NULL }, + { NULL }, + }, + } +}; + static struct usb_driver ttusb2_driver = { .name = "dvb_usb_ttusb2", .probe = ttusb2_probe, -- cgit v1.2.3 From 01caa1c4df968c523140a6b4c469bb96e535b5e2 Mon Sep 17 00:00:00 2001 From: Albert Comerma Date: Sat, 29 Mar 2008 18:35:57 -0300 Subject: V4L/DVB (7473): PATCH for various Dibcom based devices This patch introduces support for dvb-t for the following DiBcom based cards: - Terratec Cinergy HT USB XE (USB-ID: 0ccd:0058) - Terratec Cinergy HT Express (USB-ID: 0ccd:0060) - Pinnacle 320CX (USB-ID: 2304:022e) - Pinnacle PCTV72e (USB-ID: 2304:0236) - Pinnacle PCTV73e (USB-ID: 2304:0237) - Yuan EC372S (USB-ID: 1164:1edc) Signed-off-by: Hans-Frieder Vogt Signed-off-by: Felix Apitzsch Signed-off-by: Antti Palosaari Signed-off-by: Albert Comerma Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 259 +++++++++++++++++++++++++--- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 9 +- 2 files changed, 238 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index e7093826e975..9fd8399e5d8f 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -13,6 +13,7 @@ #include "dib7000p.h" #include "mt2060.h" #include "mt2266.h" +#include "tuner-xc2028.h" #include "dib0070.h" static int force_lna_activation; @@ -297,6 +298,149 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap) &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;; } +/* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */ +struct dibx000_agc_config xc3028_agc_config = { + BAND_VHF | BAND_UHF, /* band_caps */ + + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0, + * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, + * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | + (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */ + + 712, /* inv_gain */ + 21, /* time_stabiliz */ + + 0, /* alpha_level */ + 118, /* thlock */ + + 0, /* wbd_inv */ + 2867, /* wbd_ref */ + 0, /* wbd_sel */ + 2, /* wbd_alpha */ + + 0, /* agc1_max */ + 0, /* agc1_min */ + 39718, /* agc2_max */ + 9930, /* agc2_min */ + 0, /* agc1_pt1 */ + 0, /* agc1_pt2 */ + 0, /* agc1_pt3 */ + 0, /* agc1_slope1 */ + 0, /* agc1_slope2 */ + 0, /* agc2_pt1 */ + 128, /* agc2_pt2 */ + 29, /* agc2_slope1 */ + 29, /* agc2_slope2 */ + + 17, /* alpha_mant */ + 27, /* alpha_exp */ + 23, /* beta_mant */ + 51, /* beta_exp */ + + 1, /* perform_agc_softsplit */ +}; + +/* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */ +struct dibx000_bandwidth_config xc3028_bw_config = { + 60000, 30000, /* internal, sampling */ + 1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */ + 0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, + modulo */ + (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */ + (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */ + 20452225, /* timf */ + 30000000, /* xtal_hz */ +}; + +static struct dib7000p_config stk7700ph_dib7700_xc3028_config = { + .output_mpeg2_in_188_bytes = 1, + .tuner_is_baseband = 1, + + .agc_config_count = 1, + .agc = &xc3028_agc_config, + .bw = &xc3028_bw_config, + + .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, +}; + +static int stk7700ph_xc3028_callback(void *ptr, int command, int arg) +{ + struct dvb_usb_adapter *adap = ptr; + + switch (command) { + case XC2028_TUNER_RESET: + /* Send the tuner in then out of reset */ + dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10); + dib7000p_set_gpio(adap->fe, 8, 0, 1); + break; + case XC2028_RESET_CLK: + break; + default: + err("%s: unknown command %d, arg %d\n", __func__, + command, arg); + return -EINVAL; + } + return 0; +} + +static struct xc2028_ctrl stk7700ph_xc3028_ctrl = { + .fname = XC2028_DEFAULT_FIRMWARE, + .max_len = 64, + .demod = XC3028_FE_DIBCOM52, +}; + +static struct xc2028_config stk7700ph_xc3028_config = { + .i2c_addr = 0x61, + .callback = stk7700ph_xc3028_callback, + .ctrl = &stk7700ph_xc3028_ctrl, +}; + +static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct usb_device_descriptor *desc = &adap->dev->udev->descriptor; + + if (desc->idVendor == USB_VID_PINNACLE && + desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX) + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); + else + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(20); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(20); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + msleep(10); + + dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, + &stk7700ph_dib7700_xc3028_config); + + adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, + &stk7700ph_dib7700_xc3028_config); + + return adap->fe == NULL ? -ENODEV : 0; +} + +static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct i2c_adapter *tun_i2c; + + tun_i2c = dib7000p_get_i2c_master(adap->fe, + DIBX000_I2C_INTERFACE_TUNER, 1); + + stk7700ph_xc3028_config.i2c_adap = tun_i2c; + stk7700ph_xc3028_config.video_dev = adap; + + return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config) + == NULL ? -ENODEV : 0; +} + #define DEFAULT_RC_INTERVAL 150 static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; @@ -794,6 +938,10 @@ static struct dib7000p_config dib7070p_dib7000p_config = { /* STK7070P */ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) { + if (adap->dev->udev->descriptor.idVendor == USB_VID_PINNACLE && + adap->dev->udev->descriptor.idProduct == USB_PID_PINNACLE_PCTV72E) + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); + else dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); @@ -808,9 +956,11 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) msleep(10); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); - dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config); + dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, + &dib7070p_dib7000p_config); - adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config); + adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, + &dib7070p_dib7000p_config); return adap->fe == NULL ? -ENODEV : 0; } @@ -878,34 +1028,41 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) /* DVB-USB and USB stuff follows */ struct usb_device_id dib0700_usb_id_table[] = { /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, - { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, - - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, /* 5 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, - { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, - { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, - { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, + { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, + { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, + { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, /* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) }, - { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) }, - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) }, - { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) }, + { USB_DEVICE(USB_VID_TERRATEC, + USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) }, /* 15 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070P) }, - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) }, - { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) }, - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) }, - { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) }, + { USB_DEVICE(USB_VID_PINNACLE, + USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) }, + { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) }, /* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) }, - { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U7000) }, - { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) }, - { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000) }, - { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100) }, -/* 25 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) }, - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) }, - { 0 } /* Terminating entry */ + { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U7000) }, + { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) }, + { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000) }, + { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100) }, +/* 25 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_USB_XE) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_EXPRESSCARD_320CX) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV72E) }, +/* 30 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73E) }, + { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_EC372S) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) }, + { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1069,12 +1226,16 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 1, + .num_device_descs = 2, .devices = { { "ASUS My Cinema U3000 Mini DVBT Tuner", { &dib0700_usb_id_table[23], NULL }, { NULL }, }, + { "Yuan EC372S", + { &dib0700_usb_id_table[31], NULL }, + { NULL }, + } } }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -1090,7 +1251,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 6, + .num_device_descs = 8, .devices = { { "DiBcom STK7070P reference design", { &dib0700_usb_id_table[15], NULL }, @@ -1116,6 +1277,14 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[26], NULL }, { NULL }, }, + { "Pinnacle PCTV 72e", + { &dib0700_usb_id_table[29], NULL }, + { NULL }, + }, + { "Pinnacle PCTV 73e", + { &dib0700_usb_id_table[30], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, @@ -1155,6 +1324,40 @@ struct dvb_usb_device_properties dib0700_devices[] = { { NULL }, } } + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + + .num_adapters = 1, + .adapter = { + { + .frontend_attach = stk7700ph_frontend_attach, + .tuner_attach = stk7700ph_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + + .size_of_priv = sizeof(struct + dib0700_adapter_state), + }, + }, + + .num_device_descs = 3, + .devices = { + { "Terratec Cinergy HT USB XE", + { &dib0700_usb_id_table[27], NULL }, + { NULL }, + }, + { "Pinnacle Expresscard 320cx", + { &dib0700_usb_id_table[28], NULL }, + { NULL }, + }, + { "Terratec Cinergy HT Express", + { &dib0700_usb_id_table[32], NULL }, + { NULL }, + }, + }, + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_key_map = dib0700_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), + .rc_query = dib0700_rc_query }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 2cbfd6694cf9..2214bfe80940 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -47,8 +47,8 @@ #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 #define USB_VID_UNIWILL 0x1584 #define USB_VID_WIDEVIEW 0x14aa -/* dom : pour gigabyte u7000 */ #define USB_VID_GIGABYTE 0x1044 +#define USB_VID_YUAN 0x1164 /* Product IDs */ @@ -137,9 +137,14 @@ #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a +#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 +#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 +#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 +#define USB_PID_PINNACLE_PCTV72E 0x0236 +#define USB_PID_PINNACLE_PCTV73E 0x0237 #define USB_PID_PCTV_200E 0x020e #define USB_PID_PCTV_400E 0x020f #define USB_PID_PCTV_450E 0x0222 @@ -185,9 +190,9 @@ #define USB_PID_OPERA1_WARM 0x3829 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 -/* dom pour gigabyte u7000 */ #define USB_PID_GIGABYTE_U7000 0x7001 #define USB_PID_ASUS_U3000 0x171f #define USB_PID_ASUS_U3100 0x173f +#define USB_PID_YUAN_EC372S 0x1edc #endif -- cgit v1.2.3 From c32e228e1dc49387a1e8e30d3cd4127c40ec7e1a Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 29 Mar 2008 18:37:01 -0300 Subject: V4L/DVB (7474): support key repeat with dib0700 ir receiver This patch enables support for repeating last event when a key is holded down with dib0700 devices. It works with rc5 and nec remotes. It also fixes an annoying bug that floods kernel log with "Unknown key" messages after each keypress. This happened because the driver was not resetting infrared register after each poll so it kept polling last key even if nothing was being pressed. Fixing this, (calling rc_setup after each poll), permits to implement key repeat. Signed-off-by: Filippo Argiolas Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700.h | 4 ++ drivers/media/dvb/dvb-usb/dib0700_core.c | 4 +- drivers/media/dvb/dvb-usb/dib0700_devices.c | 58 +++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 4a903ea95896..66d4dc6ba46f 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -37,6 +37,7 @@ struct dib0700_state { u8 channel_state; u16 mt2060_if1[2]; u8 rc_toggle; + u8 rc_counter; u8 is_dib7000pc; }; @@ -44,12 +45,15 @@ extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen); extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); +extern int dib0700_rc_setup(struct dvb_usb_device *d); extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); extern struct i2c_algorithm dib0700_i2c_algo; extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold); extern int dib0700_device_count; +extern int dvb_usb_dib0700_ir_proto; extern struct dvb_usb_device_properties dib0700_devices[]; extern struct usb_device_id dib0700_usb_id_table[]; + #endif diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index c9857d5c6982..4b3836e63be9 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -13,7 +13,7 @@ int dvb_usb_dib0700_debug; module_param_named(debug,dvb_usb_dib0700_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS); -static int dvb_usb_dib0700_ir_proto = 1; +int dvb_usb_dib0700_ir_proto = 1; module_param(dvb_usb_dib0700_ir_proto, int, 0644); MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6)."); @@ -261,7 +261,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return dib0700_ctrl_wr(adap->dev, b, 4); } -static int dib0700_rc_setup(struct dvb_usb_device *d) +int dib0700_rc_setup(struct dvb_usb_device *d) { u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0}; int i = dib0700_ctrl_wr(d, rc_setup, 3); diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 9fd8399e5d8f..fe96f795792b 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -445,6 +445,9 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; +/* Number of keypresses to ignore before start repeating */ +#define RC_REPEAT_DELAY 2 + static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { u8 key[4]; @@ -458,18 +461,67 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) err("RC Query Failed"); return -1; } + + /* losing half of KEY_0 events from Philipps rc5 remotes.. */ if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0; - if (key[3-1]!=st->rc_toggle) { + + /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */ + + dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */ + + switch (dvb_usb_dib0700_ir_proto) { + case 0: { + /* NEC protocol sends repeat code as 0 0 0 FF */ + if ((key[3-2] == 0x00) && (key[3-3] == 0x00) && + (key[3] == 0xFF)) { + st->rc_counter++; + if (st->rc_counter > RC_REPEAT_DELAY) { + *event = d->last_event; + *state = REMOTE_KEY_PRESSED; + st->rc_counter = RC_REPEAT_DELAY; + } + return 0; + } for (i=0;iprops.rc_key_map_size; i++) { if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) { + st->rc_counter = 0; + *event = keymap[i].event; + *state = REMOTE_KEY_PRESSED; + d->last_event = keymap[i].event; + return 0; + } + } + break; + } + default: { + /* RC-5 protocol changes toggle bit on new keypress */ + for (i = 0; i < d->props.rc_key_map_size; i++) { + if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) { + if (d->last_event == keymap[i].event && + key[3-1] == st->rc_toggle) { + st->rc_counter++; + /* prevents unwanted double hits */ + if (st->rc_counter > RC_REPEAT_DELAY) { + *event = d->last_event; + *state = REMOTE_KEY_PRESSED; + st->rc_counter = RC_REPEAT_DELAY; + } + + return 0; + } + st->rc_counter = 0; *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; - st->rc_toggle=key[3-1]; + st->rc_toggle = key[3-1]; + d->last_event = keymap[i].event; return 0; } } - err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]); + break; + } } + err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]); + d->last_event = 0; return 0; } -- cgit v1.2.3 From f89aac5aca05af57f871e6a5e7df66fa4688e5f6 Mon Sep 17 00:00:00 2001 From: Alexander Simon Date: Sat, 29 Mar 2008 18:37:54 -0300 Subject: V4L/DVB (7475): Added support for Terratec Cinergy T USB XXS Alexander Simon found out that the Terratec Cinergy T USB XXS is just a clone of another DiB7070P-based device. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index fe96f795792b..e052e89bfb34 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1114,6 +1114,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 30 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73E) }, { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_EC372S) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1303,7 +1304,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 8, + .num_device_descs = 9, .devices = { { "DiBcom STK7070P reference design", { &dib0700_usb_id_table[15], NULL }, @@ -1337,6 +1338,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[30], NULL }, { NULL }, }, + { "Terratec Cinergy T USB XXS", + { &dib0700_usb_id_table[33], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 2214bfe80940..9757fb2c3b4c 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -139,6 +139,7 @@ #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 +#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 @@ -193,6 +194,6 @@ #define USB_PID_GIGABYTE_U7000 0x7001 #define USB_PID_ASUS_U3000 0x171f #define USB_PID_ASUS_U3100 0x173f -#define USB_PID_YUAN_EC372S 0x1edc +#define USB_PID_YUAN_EC372S 0x1edc #endif -- cgit v1.2.3 From 1572365b2b72accdd94946f78adfd9963e00394f Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Sat, 29 Mar 2008 18:47:43 -0300 Subject: V4L/DVB (7476): New USB ID for Leadtek DVB-T USB Detect Leadtek Winfast USB DTV Dongle with ID of 0x6f01 Signed-off-by: Darryl Green Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 3 ++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index e052e89bfb34..6477fc66cc23 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1115,6 +1115,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_EC372S) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) }, + { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1179,7 +1180,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { { NULL }, }, { "Leadtek Winfast DTV Dongle (STK7700P based)", - { &dib0700_usb_id_table[8], NULL }, + { &dib0700_usb_id_table[8], &dib0700_usb_id_table[34] }, { NULL }, }, { "AVerMedia AVerTV DVB-T Express", diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 9757fb2c3b4c..34245d1b7dd9 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -180,6 +180,7 @@ #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 +#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 #define USB_PID_GENPIX_8PSK_REV_2 0x0202 -- cgit v1.2.3 From 5d3b5a49d49c60f21c898f8784a4d56d2908a34d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 30 Mar 2008 20:28:59 -0300 Subject: V4L/DVB (7479): proper prototype for zoran_device.c:zr36016_write() This patch adds a proper prototype for zr36016_write() in drivers/media/video/zoran_card.h Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran_card.h | 2 ++ drivers/media/video/zoran_device.c | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran_card.h index 8444ca0a5f3f..1b5c4171cf9c 100644 --- a/drivers/media/video/zoran_card.h +++ b/drivers/media/video/zoran_card.h @@ -50,4 +50,6 @@ extern int zoran_check_jpg_settings(struct zoran *zr, extern void zoran_open_init_params(struct zoran *zr); extern void zoran_vdev_release(struct video_device *vdev); +void zr36016_write(struct videocodec *codec, u16 reg, u32 val); + #endif /* __ZORAN_CARD_H__ */ diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 05b16a254cb3..7b60533efe45 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -928,11 +928,6 @@ count_reset_interrupt (struct zoran *zr) return isr; } -/* hack */ -extern void zr36016_write (struct videocodec *codec, - u16 reg, - u32 val); - void jpeg_start (struct zoran *zr) { -- cgit v1.2.3 From acc1ff883ff4e9f73d16cd9d01d7586bb39eefa8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 30 Mar 2008 20:29:02 -0300 Subject: V4L/DVB (7480): make sn9c102_i2c_try_write() static This patch makes the needlessly global sn9c102_i2c_try_write() static. Signed-off-by: Adrian Bunk CC: Luca Risolia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sn9c102/sn9c102_core.c | 6 +++--- drivers/media/video/sn9c102/sn9c102_sensor.h | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 898ae5f578cb..5748b1e1a128 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -464,9 +464,9 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam, } -int -sn9c102_i2c_try_write(struct sn9c102_device* cam, - const struct sn9c102_sensor* sensor, u8 address, u8 value) +static int sn9c102_i2c_try_write(struct sn9c102_device* cam, + const struct sn9c102_sensor* sensor, + u8 address, u8 value) { return sn9c102_i2c_try_raw_write(cam, sensor, 3, sensor->i2c_slave_id, address, diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 2dc7c6869484..4af7382da5c5 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -85,9 +85,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, */ /* The "try" I2C I/O versions are used when probing the sensor */ -extern int sn9c102_i2c_try_write(struct sn9c102_device*, - const struct sn9c102_sensor*, u8 address, - u8 value); extern int sn9c102_i2c_try_read(struct sn9c102_device*, const struct sn9c102_sensor*, u8 address); -- cgit v1.2.3 From e268448380603c3780ec28fbaf7bd91d85409704 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 30 Mar 2008 16:40:20 -0300 Subject: V4L/DVB (7481): tda18271: fix standard map debug Show IF level and rf agc top settings in standard map dumps. Dump standard map during attach if DBG_MAP or DBG_ADV is set. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 48ec5f08c3c9..b262100ae897 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -951,16 +951,19 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) #define tda18271_update_std(std_cfg, name) do { \ if (map->std_cfg.if_freq + \ - map->std_cfg.agc_mode + map->std_cfg.std > 0) { \ + map->std_cfg.agc_mode + map->std_cfg.std + \ + map->std_cfg.if_lvl + map->std_cfg.rfagc_top > 0) { \ tda_dbg("Using custom std config for %s\n", name); \ memcpy(&std->std_cfg, &map->std_cfg, \ sizeof(struct tda18271_std_map_item)); \ } } while (0) #define tda18271_dump_std_item(std_cfg, name) do { \ - tda_dbg("(%s) if freq = %d, agc_mode = %d, std = %d\n", \ + tda_dbg("(%s) if_freq = %d, agc_mode = %d, std = %d, " \ + "if_lvl = %d, rfagc_top = 0x%02x\n", \ name, std->std_cfg.if_freq, \ - std->std_cfg.agc_mode, std->std_cfg.std); \ + std->std_cfg.agc_mode, std->std_cfg.std, \ + std->std_cfg.if_lvl, std->std_cfg.rfagc_top); \ } while (0) static int tda18271_dump_std_map(struct dvb_frontend *fe) @@ -969,20 +972,20 @@ static int tda18271_dump_std_map(struct dvb_frontend *fe) struct tda18271_std_map *std = &priv->std; tda_dbg("========== STANDARD MAP SETTINGS ==========\n"); - tda18271_dump_std_item(fm_radio, "fm"); - tda18271_dump_std_item(atv_b, "pal b"); - tda18271_dump_std_item(atv_dk, "pal dk"); - tda18271_dump_std_item(atv_gh, "pal gh"); - tda18271_dump_std_item(atv_i, "pal i"); - tda18271_dump_std_item(atv_l, "pal l"); - tda18271_dump_std_item(atv_lc, "pal l'"); + tda18271_dump_std_item(fm_radio, " fm "); + tda18271_dump_std_item(atv_b, "atv b "); + tda18271_dump_std_item(atv_dk, "atv dk"); + tda18271_dump_std_item(atv_gh, "atv gh"); + tda18271_dump_std_item(atv_i, "atv i "); + tda18271_dump_std_item(atv_l, "atv l "); + tda18271_dump_std_item(atv_lc, "atv l'"); tda18271_dump_std_item(atv_mn, "atv mn"); tda18271_dump_std_item(atsc_6, "atsc 6"); tda18271_dump_std_item(dvbt_6, "dvbt 6"); tda18271_dump_std_item(dvbt_7, "dvbt 7"); tda18271_dump_std_item(dvbt_8, "dvbt 8"); - tda18271_dump_std_item(qam_6, "qam 6"); - tda18271_dump_std_item(qam_8, "qam 8"); + tda18271_dump_std_item(qam_6, "qam 6 "); + tda18271_dump_std_item(qam_8, "qam 8 "); return 0; } @@ -1125,7 +1128,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, sizeof(struct dvb_tuner_ops)); - if (tda18271_debug & DBG_MAP) + if (tda18271_debug & (DBG_MAP | DBG_ADV)) tda18271_dump_std_map(fe); return fe; -- cgit v1.2.3 From a58dc56a6ce290bf0d7dae88e908531c7c74721f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 30 Mar 2008 14:00:45 -0300 Subject: V4L/DVB (7483): tuner-simple: fix broken build dependency tuner-simple is the only module that uses tuner-types - these will be merged to a single module in the future. For now, build both of them if TUNER_SIMPLE is selected. This fixes the following build warning, if tuner-simple is selected without tuner-types: WARNING: "tuner_count" [tuner-simple.ko] undefined! WARNING: "tuners" [tuner-simple.ko] undefined! Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 5 ----- drivers/media/video/Makefile | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index b9b38d9ff650..1f7244cffe2f 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -71,13 +71,9 @@ source "drivers/media/dvb/Kconfig" source "drivers/media/common/Kconfig" -config VIDEO_TUNER_TYPES - tristate - config VIDEO_TUNER tristate depends on I2C - select VIDEO_TUNER_TYPES select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE @@ -140,7 +136,6 @@ config TUNER_TEA5767 config TUNER_SIMPLE tristate "Simple tuner support" depends on I2C - select VIDEO_TUNER_TYPES select TUNER_TDA9887 default m if VIDEO_TUNER_CUSTOMIZE help diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 77cfaff76420..8b1e97a7caa3 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -84,10 +84,11 @@ obj-$(CONFIG_VIDEO_DPC) += dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEO_TUNER) += tuner.o -obj-$(CONFIG_VIDEO_TUNER_TYPES) += tuner-types.o obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o +# tuner-types will be merged into tuner-simple, in the future +obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o obj-$(CONFIG_TUNER_TDA8290) += tda8290.o obj-$(CONFIG_TUNER_TEA5767) += tea5767.o -- cgit v1.2.3 From b58e98e793b0cd46e55e76b1b98df86ad40a6f28 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 15:10:57 -0300 Subject: V4L/DVB (7487): videobuf: Wakeup queues after changing the state to ERROR The waitqueues must be woken up every time state changes. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index fe742fdfae07..e4a864e0d96b 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -204,6 +204,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q) if (q->bufs[i]->state == VIDEOBUF_QUEUED) { list_del(&q->bufs[i]->queue); q->bufs[i]->state = VIDEOBUF_ERROR; + wake_up_all(&q->bufs[i]->done); } } if (q->irqlock) -- cgit v1.2.3 From b5daa9d514f3af33b73b33babe7f1106cd843c27 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 15:10:59 -0300 Subject: V4L/DVB (7488): videobuf: Simplify videobuf_waiton logic and possibly avoid missed wakeup Possible missed wakeup- use kernel helpers for wait queues http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg27983.html Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index e4a864e0d96b..1ba3aaa29dd0 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -64,32 +64,25 @@ void *videobuf_alloc(struct videobuf_queue *q) return vb; } +#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\ + vb->state != VIDEOBUF_QUEUED) int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) { - int retval = 0; - DECLARE_WAITQUEUE(wait, current); - MAGIC_CHECK(vb->magic, MAGIC_BUFFER); - add_wait_queue(&vb->done, &wait); - while (vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) { - if (non_blocking) { - retval = -EAGAIN; - break; - } - set_current_state(intr ? TASK_INTERRUPTIBLE - : TASK_UNINTERRUPTIBLE); - if (vb->state == VIDEOBUF_ACTIVE || - vb->state == VIDEOBUF_QUEUED) - schedule(); - set_current_state(TASK_RUNNING); - if (intr && signal_pending(current)) { - dprintk(1, "buffer waiton: -EINTR\n"); - retval = -EINTR; - break; - } + + if (non_blocking) { + if (WAITON_CONDITION) + return 0; + else + return -EAGAIN; } - remove_wait_queue(&vb->done, &wait); - return retval; + + if (intr) + return wait_event_interruptible(vb->done, WAITON_CONDITION); + else + wait_event(vb->done, WAITON_CONDITION); + + return 0; } int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, -- cgit v1.2.3 From 63f4f32ae6a1a04ce72552a286fa7ba9e00aa8d3 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 15:10:59 -0300 Subject: V4L/DVB (7489): videobuf-vmalloc.c: Remove buf_release from videobuf_vm_close Remove the buf_release on vm_close because it will lead to a buffer being released multiple times since all buffers are already freed under the two possible cases: device close or STREAMOFF. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-vmalloc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 4a2508dfa0e3..e23335f2919d 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -78,8 +78,6 @@ videobuf_vm_close(struct vm_area_struct *vma) if (q->bufs[i]->map != map) continue; - q->ops->buf_release(q,q->bufs[i]); - q->bufs[i]->map = NULL; q->bufs[i]->baddr = 0; } -- cgit v1.2.3 From 18e217c41a63d3af0117e2ea687d07dbc1cc606b Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 15:10:59 -0300 Subject: V4L/DVB (7490): videobuf-vmalloc.c: Fix hack of postponing mmap on remap failure In videobuf-vmalloc.c remap_vmalloc_range is failing when applications are trying to mmap buffers immediately after reqbuf. It fails because the vmalloc area isn't setup until the first QBUF when drivers call iolock. This patch introduces mmap_setup to the qtype_ops and it is called in __videobuf_mmap_setup if the buffer type is mmap. In the case of vmalloc buffers this calls iolock, and sets the state to idle. I don't think this is needed for dma-sg buffers and it defaults to a no-op for everything but vmalloc. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 29 ++++++++++------------- drivers/media/video/videobuf-vmalloc.c | 43 +++++++++++++++++----------------- include/media/videobuf-core.h | 3 ++- 3 files changed, 35 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 1ba3aaa29dd0..7d13c4da8fb3 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -91,25 +91,17 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, MAGIC_CHECK(vb->magic, MAGIC_BUFFER); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - /* This is required to avoid OOPS on some cases, - since mmap_mapper() method should be called before _iolock. - On some cases, the mmap_mapper() is called only after scheduling. - */ - if (vb->memory == V4L2_MEMORY_MMAP) { - wait_event_timeout(vb->done, q->is_mmapped, - msecs_to_jiffies(100)); - if (!q->is_mmapped) { - printk(KERN_ERR - "Error: mmap_mapper() never called!\n"); - return -EINVAL; - } - } - return CALL(q, iolock, q, vb, fbuf); } /* --------------------------------------------------------------------- */ +static int videobuf_mmap_setup_default(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + return 0; +} + void videobuf_queue_core_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, @@ -131,6 +123,9 @@ void videobuf_queue_core_init(struct videobuf_queue *q, q->priv_data = priv; q->int_ops = int_ops; + if (!q->int_ops->mmap_setup) + q->int_ops->mmap_setup = videobuf_mmap_setup_default; + /* All buffer operations are mandatory */ BUG_ON(!q->ops->buf_setup); BUG_ON(!q->ops->buf_prepare); @@ -303,8 +298,6 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) rc = CALL(q, mmap_free, q); - q->is_mmapped = 0; - if (rc < 0) return rc; @@ -356,6 +349,9 @@ static int __videobuf_mmap_setup(struct videobuf_queue *q, switch (memory) { case V4L2_MEMORY_MMAP: q->bufs[i]->boff = bsize * i; + err = q->int_ops->mmap_setup(q, q->bufs[i]); + if (err) + break; break; case V4L2_MEMORY_USERPTR: case V4L2_MEMORY_OVERLAY: @@ -1027,7 +1023,6 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, mutex_lock(&q->vb_lock); retval = CALL(q, mmap_mapper, q, vma); - q->is_mmapped = 1; mutex_unlock(&q->vb_lock); return retval; diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index e23335f2919d..0bd447d9abe9 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -151,21 +151,26 @@ static int __videobuf_iolock (struct videobuf_queue* q, (unsigned long)mem->vmalloc, pages << PAGE_SHIFT); - /* It seems that some kernel versions need to do remap *after* - the mmap() call - */ - if (mem->vma) { - int retval=remap_vmalloc_range(mem->vma, mem->vmalloc,0); - kfree(mem->vma); - mem->vma=NULL; - if (retval<0) { - dprintk(1,"mmap app bug: remap_vmalloc_range area %p error %d\n", - mem->vmalloc,retval); - return retval; + return 0; +} + +static int __videobuf_mmap_setup(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + int retval = 0; + BUG_ON(vb->memory != V4L2_MEMORY_MMAP); + if (vb->state == VIDEOBUF_NEEDS_INIT) { + /* bsize == size since the buffer needs to be large enough to + * hold an entire frame, not the case in the read case for + * example*/ + vb->size = vb->bsize; + retval = __videobuf_iolock(q, vb, NULL); + if (!retval) { + /* Don't IOLOCK later */ + vb->state = VIDEOBUF_IDLE; } } - - return 0; + return retval; } static int __videobuf_sync(struct videobuf_queue *q, @@ -238,15 +243,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, /* Try to remap memory */ retval=remap_vmalloc_range(vma, mem->vmalloc,0); if (retval<0) { - dprintk(1,"mmap: postponing remap_vmalloc_range\n"); - - mem->vma=kmalloc(sizeof(*vma),GFP_KERNEL); - if (!mem->vma) { - kfree(map); - q->bufs[first]->map=NULL; - return -ENOMEM; - } - memcpy(mem->vma,vma,sizeof(*vma)); + dprintk(1, "mmap: failed to remap_vmalloc_range\n"); + return -EINVAL; } dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", @@ -314,6 +312,7 @@ static struct videobuf_qtype_ops qops = { .alloc = __videobuf_alloc, .iolock = __videobuf_iolock, .sync = __videobuf_sync, + .mmap_setup = __videobuf_mmap_setup, .mmap_free = __videobuf_mmap_free, .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index fcdffdd63304..ddf963c92e3e 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -144,6 +144,8 @@ struct videobuf_qtype_ops { int vbihack, int nonblocking); int (*mmap_free) (struct videobuf_queue *q); + int (*mmap_setup) (struct videobuf_queue *q, + struct videobuf_buffer *vb); int (*mmap_mapper) (struct videobuf_queue *q, struct vm_area_struct *vma); }; @@ -164,7 +166,6 @@ struct videobuf_queue { unsigned int streaming:1; unsigned int reading:1; - unsigned int is_mmapped:1; /* capture via mmap() + ioctl(QBUF/DQBUF) */ struct list_head stream; -- cgit v1.2.3 From 3b52b8d71d8d96f02bd4c1d897bc35f1cc449986 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 15:10:59 -0300 Subject: V4L/DVB (7491): vivi: make vivi openable only once vivi currently doesn't have the infrastructure to handle being opened more than one time and will crash if it is. So, make it openable only once. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 0e623179f8a5..02a232768e3b 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -164,6 +164,7 @@ struct vivi_dev { struct mutex lock; spinlock_t slock; + struct mutex mutex; int users; @@ -1036,6 +1037,7 @@ static int vivi_open(struct inode *inode, struct file *file) struct vivi_dev *dev; struct vivi_fh *fh; int i; + int retval = 0; printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor); @@ -1045,9 +1047,15 @@ static int vivi_open(struct inode *inode, struct file *file) return -ENODEV; found: - /* If more than one user, mutex should be added */ + mutex_lock(&dev->mutex); dev->users++; + if (dev->users > 1) { + dev->users--; + retval = -EBUSY; + goto unlock; + } + dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor, v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); @@ -1055,8 +1063,13 @@ found: fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { dev->users--; - return -ENOMEM; + retval = -ENOMEM; + goto unlock; } +unlock: + mutex_unlock(&dev->mutex); + if (retval) + return retval; file->private_data = fh; fh->dev = dev; @@ -1128,7 +1141,9 @@ static int vivi_close(struct inode *inode, struct file *file) kfree(fh); + mutex_lock(&dev->mutex); dev->users--; + mutex_unlock(&dev->mutex); dprintk(dev, 1, "close called (minor=%d, users=%d)\n", minor, dev->users); @@ -1243,6 +1258,7 @@ static int __init vivi_init(void) /* initialize locks */ mutex_init(&dev->lock); spin_lock_init(&dev->slock); + mutex_init(&dev->mutex); dev->vidq.timeout.function = vivi_vid_timeout; dev->vidq.timeout.data = (unsigned long)dev; -- cgit v1.2.3 From bdc1261e29a2b3f19be8b2c5559f618f05c68b03 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 15:10:59 -0300 Subject: V4L/DVB (7492): vivi: Simplify the vivi driver and avoid deadlocks vivi previously had a very complex queuing system and held spinlocks while doing copy_to_user, kmalloc, etc. This caused the driver to easily deadlock when a multi-threaded application used it and revealed bugs in videobuf too. This replaces the copy_to_user with memcpy since we were never copying to user space addresses. And makes the kmalloc atomic. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 313 ++++++++++++--------------------------------- 1 file changed, 81 insertions(+), 232 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 02a232768e3b..8353deb8a1d4 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -146,8 +146,6 @@ struct vivi_buffer { struct vivi_dmaqueue { struct list_head active; - struct list_head queued; - struct timer_list timeout; /* thread for generating video stream*/ struct task_struct *kthread; @@ -162,7 +160,6 @@ static LIST_HEAD(vivi_devlist); struct vivi_dev { struct list_head vivi_devlist; - struct mutex lock; spinlock_t slock; struct mutex mutex; @@ -323,24 +320,26 @@ static void gen_line(char *basep, int inipos, int wmax, end: return; } + static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) { int h , pos = 0; int hmax = buf->vb.height; int wmax = buf->vb.width; struct timeval ts; - char *tmpbuf = kmalloc(wmax * 2, GFP_KERNEL); + char *tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC); void *vbuf = videobuf_to_vmalloc(&buf->vb); if (!tmpbuf) return; + if (!vbuf) + return; + for (h = 0; h < hmax; h++) { gen_line(tmpbuf, 0, wmax, hmax, h, dev->mv_count, dev->timestr); - /* FIXME: replacing to __copy_to_user */ - if (copy_to_user(vbuf + pos, tmpbuf, wmax * 2) != 0) - dprintk(dev, 2, "vivifill copy_to_user failed.\n"); + memcpy(vbuf + pos, tmpbuf, wmax * 2); pos += wmax*2; } @@ -373,67 +372,58 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) dev->timestr, (unsigned long)tmpbuf, pos); /* Advice that buffer was filled */ - buf->vb.state = VIDEOBUF_DONE; buf->vb.field_count++; do_gettimeofday(&ts); buf->vb.ts = ts; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); + buf->vb.state = VIDEOBUF_DONE; } -static int restart_video_queue(struct vivi_dmaqueue *dma_q); - -static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) +static void vivi_thread_tick(struct vivi_fh *fh) { - struct vivi_buffer *buf; - struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + struct vivi_buffer *buf; + struct vivi_dev *dev = fh->dev; + struct vivi_dmaqueue *dma_q = &dev->vidq; - int bc; + unsigned long flags = 0; - spin_lock(&dev->slock); - /* Announces videobuf that all went ok */ - for (bc = 0;; bc++) { - if (list_empty(&dma_q->active)) { - dprintk(dev, 1, "No active queue to serve\n"); - break; - } + dprintk(dev, 1, "Thread tick\n"); - buf = list_entry(dma_q->active.next, - struct vivi_buffer, vb.queue); + spin_lock_irqsave(&dev->slock, flags); + if (list_empty(&dma_q->active)) { + dprintk(dev, 1, "No active queue to serve\n"); + goto unlock; + } - /* Nobody is waiting something to be done, just return */ - if (!waitqueue_active(&buf->vb.done)) { - mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); - spin_unlock(&dev->slock); - return; - } + buf = list_entry(dma_q->active.next, + struct vivi_buffer, vb.queue); - do_gettimeofday(&buf->vb.ts); - dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); + /* Nobody is waiting on this buffer, return */ + if (!waitqueue_active(&buf->vb.done)) + goto unlock; - /* Fill buffer */ - vivi_fillbuff(dev, buf); + list_del(&buf->vb.queue); - if (list_empty(&dma_q->active)) { - del_timer(&dma_q->timeout); - } else { - mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT); - } - } - if (bc != 1) - dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n", - __FUNCTION__, bc); - spin_unlock(&dev->slock); + do_gettimeofday(&buf->vb.ts); + + /* Fill buffer */ + vivi_fillbuff(dev, buf); + dprintk(dev, 1, "filled buffer %p\n", buf); + + wake_up(&buf->vb.done); + dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); +unlock: + spin_unlock_irqrestore(&dev->slock, flags); + return; } #define frames_to_ms(frames) \ ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) -static void vivi_sleep(struct vivi_dmaqueue *dma_q) +static void vivi_sleep(struct vivi_fh *fh) { - struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); - int timeout, running_time; + struct vivi_dev *dev = fh->dev; + struct vivi_dmaqueue *dma_q = &dev->vidq; + int timeout; DECLARE_WAITQUEUE(wait, current); dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__, @@ -443,37 +433,10 @@ static void vivi_sleep(struct vivi_dmaqueue *dma_q) if (kthread_should_stop()) goto stop_task; - running_time = jiffies - dma_q->ini_jiffies; - dma_q->frame++; - /* Calculate time to wake up */ - timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - running_time; + timeout = msecs_to_jiffies(frames_to_ms(1)); - if (timeout > msecs_to_jiffies(frames_to_ms(2)) || timeout <= 0) { - int old = dma_q->frame; - int nframes; - - dma_q->frame = (jiffies_to_msecs(running_time) / - frames_to_ms(1)) + 1; - - timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - - running_time; - - if (unlikely (timeout <= 0)) - timeout = 1; - - nframes = (dma_q->frame > old)? - dma_q->frame - old : old - dma_q->frame; - - dprintk(dev, 1, "%ld: %s %d frames. " - "Current frame is %d. Will sleep for %d jiffies\n", - jiffies, - (dma_q->frame > old)? "Underrun, losed" : "Overrun of", - nframes, dma_q->frame, timeout); - } else - dprintk(dev, 1, "will sleep for %d jiffies\n", timeout); - - vivi_thread_tick(dma_q); + vivi_thread_tick(fh); schedule_timeout_interruptible(timeout); @@ -484,16 +447,15 @@ stop_task: static int vivi_thread(void *data) { - struct vivi_dmaqueue *dma_q = data; - struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + struct vivi_fh *fh = data; + struct vivi_dev *dev = fh->dev; dprintk(dev, 1, "thread started\n"); - mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); set_freezable(); for (;;) { - vivi_sleep(dma_q); + vivi_sleep(fh); if (kthread_should_stop()) break; @@ -502,16 +464,17 @@ static int vivi_thread(void *data) return 0; } -static int vivi_start_thread(struct vivi_dmaqueue *dma_q) +static int vivi_start_thread(struct vivi_fh *fh) { - struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + struct vivi_dev *dev = fh->dev; + struct vivi_dmaqueue *dma_q = &dev->vidq; dma_q->frame = 0; dma_q->ini_jiffies = jiffies; dprintk(dev, 1, "%s\n", __FUNCTION__); - dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi"); + dma_q->kthread = kthread_run(vivi_thread, fh, "vivi"); if (IS_ERR(dma_q->kthread)) { printk(KERN_ERR "vivi: kernel_thread() failed\n"); @@ -536,91 +499,6 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) } } -static int restart_video_queue(struct vivi_dmaqueue *dma_q) -{ - struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); - struct vivi_buffer *buf, *prev; - - dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__, - (unsigned long)dma_q); - - if (!list_empty(&dma_q->active)) { - buf = list_entry(dma_q->active.next, - struct vivi_buffer, vb.queue); - dprintk(dev, 2, "restart_queue [%p/%d]: restart dma\n", - buf, buf->vb.i); - - dprintk(dev, 1, "Restarting video dma\n"); - vivi_stop_thread(dma_q); - - /* cancel all outstanding capture / vbi requests */ - list_for_each_entry_safe(buf, prev, &dma_q->active, vb.queue) { - list_del(&buf->vb.queue); - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - } - mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); - - return 0; - } - - prev = NULL; - for (;;) { - if (list_empty(&dma_q->queued)) - return 0; - buf = list_entry(dma_q->queued.next, - struct vivi_buffer, vb.queue); - if (NULL == prev) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue, &dma_q->active); - - dprintk(dev, 1, "Restarting video dma\n"); - vivi_stop_thread(dma_q); - vivi_start_thread(dma_q); - - buf->vb.state = VIDEOBUF_ACTIVE; - mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(dev, 2, - "[%p/%d] restart_queue - first active\n", - buf, buf->vb.i); - - } else if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue, &dma_q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - dprintk(dev, 2, - "[%p/%d] restart_queue - move to active\n", - buf, buf->vb.i); - } else { - return 0; - } - prev = buf; - } -} - -static void vivi_vid_timeout(unsigned long data) -{ - struct vivi_dev *dev = (struct vivi_dev *)data; - struct vivi_dmaqueue *vidq = &dev->vidq; - struct vivi_buffer *buf; - - spin_lock(&dev->slock); - - while (!list_empty(&vidq->active)) { - buf = list_entry(vidq->active.next, - struct vivi_buffer, vb.queue); - list_del(&buf->vb.queue); - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - printk(KERN_INFO "vivi/0: [%p/%d] timeout\n", buf, buf->vb.i); - } - restart_video_queue(vidq); - - spin_unlock(&dev->slock); -} - /* ------------------------------------------------------------------ Videobuf operations ------------------------------------------------------------------*/ @@ -649,13 +527,13 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) struct vivi_fh *fh = vq->priv_data; struct vivi_dev *dev = fh->dev; - dprintk(dev, 1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s, state: %i\n", __FUNCTION__, buf->vb.state); if (in_interrupt()) BUG(); - videobuf_waiton(&buf->vb, 0, 0); videobuf_vmalloc_free(&buf->vb); + dprintk(dev, 1, "free_buffer: freed"); buf->vb.state = VIDEOBUF_NEEDS_INIT; } @@ -668,28 +546,25 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, struct vivi_fh *fh = vq->priv_data; struct vivi_dev *dev = fh->dev; struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); - int rc, init_buffer = 0; + int rc; dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field); BUG_ON(NULL == fh->fmt); + if (fh->width < 48 || fh->width > norm_maxw() || fh->height < 32 || fh->height > norm_maxh()) return -EINVAL; + buf->vb.size = fh->width*fh->height*2; if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; - if (buf->fmt != fh->fmt || - buf->vb.width != fh->width || - buf->vb.height != fh->height || - buf->vb.field != field) { - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; - buf->vb.field = field; - init_buffer = 1; - } + /* These properties only change when queue is idle, see s_fmt */ + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); @@ -712,45 +587,12 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); struct vivi_fh *fh = vq->priv_data; struct vivi_dev *dev = fh->dev; - struct vivi_dmaqueue *vidq = &dev->vidq; - struct vivi_buffer *prev; - - if (!list_empty(&vidq->queued)) { - dprintk(dev, 1, "adding vb queue=0x%08lx\n", - (unsigned long)&buf->vb.queue); - list_add_tail(&buf->vb.queue, &vidq->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(dev, 2, "[%p/%d] buffer_queue - append to queued\n", - buf, buf->vb.i); - } else if (list_empty(&vidq->active)) { - list_add_tail(&buf->vb.queue, &vidq->active); - - buf->vb.state = VIDEOBUF_ACTIVE; - mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(dev, 2, "[%p/%d] buffer_queue - first active\n", - buf, buf->vb.i); - - vivi_start_thread(vidq); - } else { - prev = list_entry(vidq->active.prev, - struct vivi_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &vidq->active); - buf->vb.state = VIDEOBUF_ACTIVE; - dprintk(dev, 2, - "[%p/%d] buffer_queue - append to active\n", - buf, buf->vb.i); - - } else { - list_add_tail(&buf->vb.queue, &vidq->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(dev, 2, - "[%p/%d] buffer_queue - first queued\n", - buf, buf->vb.i); - } - } + struct vivi_dmaqueue *vidq = &dev->vidq; + + dprintk(dev, 1, "%s\n", __FUNCTION__); + + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vidq->active); } static void buffer_release(struct videobuf_queue *vq, @@ -759,12 +601,9 @@ static void buffer_release(struct videobuf_queue *vq, struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); struct vivi_fh *fh = vq->priv_data; struct vivi_dev *dev = (struct vivi_dev *)fh->dev; - struct vivi_dmaqueue *vidq = &dev->vidq; dprintk(dev, 1, "%s\n", __FUNCTION__); - vivi_stop_thread(vidq); - free_buffer(vq, buf); } @@ -870,17 +709,31 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { struct vivi_fh *fh = priv; + struct videobuf_queue *q = &fh->vb_vidq; + int ret = vidioc_try_fmt_cap(file, fh, f); if (ret < 0) return (ret); + mutex_lock(&q->vb_lock); + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + dprintk(fh->dev, 1, "%s queue busy\n", __FUNCTION__); + ret = -EBUSY; + goto out; + } + fh->fmt = &format; fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; fh->vb_vidq.field = f->fmt.pix.field; fh->type = f->type; - return (0); + ret = 0; +out: + mutex_unlock(&q->vb_lock); + + return (ret); } static int vidioc_reqbufs(struct file *file, void *priv, @@ -1097,6 +950,8 @@ unlock: NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, sizeof(struct vivi_buffer), fh); + vivi_start_thread(fh); + return 0; } @@ -1252,18 +1107,12 @@ static int __init vivi_init(void) /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vidq.queued); init_waitqueue_head(&dev->vidq.wq); /* initialize locks */ - mutex_init(&dev->lock); spin_lock_init(&dev->slock); mutex_init(&dev->mutex); - dev->vidq.timeout.function = vivi_vid_timeout; - dev->vidq.timeout.data = (unsigned long)dev; - init_timer(&dev->vidq.timeout); - vfd = video_device_alloc(); if (NULL == vfd) break; -- cgit v1.2.3 From 66b54ec51005e2a793ccd2569435f7c65e732dc9 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 15:10:59 -0300 Subject: V4L/DVB (7493): videobuf: Avoid deadlock with QBUF and bring up to spec for empty queue Add a waitqueue to wait on when there are no buffers in the buffer queue. DQBUF waits on this queue without holding vb_lock to allow a QBUF to happen. Once a buffer has been queued we recheck that the queue is still streaming and wait on the new buffer's waitqueue while holding the vb_lock. The driver should come along in a timely manner and put the buffer into its next state finishing the DQBUF. By implementing this waitqueue it also brings the videobuf DQBUF up to spec and it now blocks on O_NONBLOCK even when no buffers have been queued via QBUF: "By default VIDIOC_DQBUF blocks when no buffer is in the outgoing queue." - V4L2 spec Signed-off-by: Brandon Philips CC: Trent Piepho CC: Carl Karsten CC: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 96 +++++++++++++++++++++++++++++-------- include/media/videobuf-core.h | 2 + 2 files changed, 78 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 7d13c4da8fb3..0e252cd29eff 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -136,6 +136,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q, BUG_ON(!q->int_ops); mutex_init(&q->vb_lock); + init_waitqueue_head(&q->wait); INIT_LIST_HEAD(&q->stream); } @@ -183,6 +184,10 @@ void videobuf_queue_cancel(struct videobuf_queue *q) unsigned long flags = 0; int i; + q->streaming = 0; + q->reading = 0; + wake_up_interruptible_sync(&q->wait); + /* remove queued buffers from list */ if (q->irqlock) spin_lock_irqsave(q->irqlock, flags); @@ -561,6 +566,7 @@ int videobuf_qbuf(struct videobuf_queue *q, } dprintk(1, "qbuf: succeded\n"); retval = 0; + wake_up_interruptible_sync(&q->wait); done: mutex_unlock(&q->vb_lock); @@ -571,37 +577,88 @@ int videobuf_qbuf(struct videobuf_queue *q, return retval; } -int videobuf_dqbuf(struct videobuf_queue *q, - struct v4l2_buffer *b, int nonblocking) + +/* Locking: Caller holds q->vb_lock */ +static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) { - struct videobuf_buffer *buf; int retval; - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - mutex_lock(&q->vb_lock); - retval = -EBUSY; - if (q->reading) { - dprintk(1, "dqbuf: Reading running...\n"); - goto done; - } - retval = -EINVAL; - if (b->type != q->type) { - dprintk(1, "dqbuf: Wrong type.\n"); +checks: + if (!q->streaming) { + dprintk(1, "next_buffer: Not streaming\n"); + retval = -EINVAL; goto done; } + if (list_empty(&q->stream)) { - dprintk(1, "dqbuf: stream running\n"); - goto done; + if (noblock) { + retval = -EAGAIN; + dprintk(2, "next_buffer: no buffers to dequeue\n"); + goto done; + } else { + dprintk(2, "next_buffer: waiting on buffer\n"); + + /* Drop lock to avoid deadlock with qbuf */ + mutex_unlock(&q->vb_lock); + + /* Checking list_empty and streaming is safe without + * locks because we goto checks to validate while + * holding locks before proceeding */ + retval = wait_event_interruptible(q->wait, + !list_empty(&q->stream) || !q->streaming); + mutex_lock(&q->vb_lock); + + if (retval) + goto done; + + goto checks; + } } + + retval = 0; + +done: + return retval; +} + + +/* Locking: Caller holds q->vb_lock */ +static int stream_next_buffer(struct videobuf_queue *q, + struct videobuf_buffer **vb, int nonblocking) +{ + int retval; + struct videobuf_buffer *buf = NULL; + + retval = stream_next_buffer_check_queue(q, nonblocking); + if (retval) + goto done; + buf = list_entry(q->stream.next, struct videobuf_buffer, stream); - mutex_unlock(&q->vb_lock); retval = videobuf_waiton(buf, nonblocking, 1); + if (retval < 0) + goto done; + + *vb = buf; +done: + return retval; +} + +int videobuf_dqbuf(struct videobuf_queue *q, + struct v4l2_buffer *b, int nonblocking) +{ + struct videobuf_buffer *buf = NULL; + int retval; + + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); + mutex_lock(&q->vb_lock); + + retval = stream_next_buffer(q, &buf, nonblocking); if (retval < 0) { - dprintk(1, "dqbuf: waiton returned %d\n", retval); + dprintk(1, "dqbuf: next_buffer error: %i\n", retval); goto done; } + switch (buf->state) { case VIDEOBUF_ERROR: dprintk(1, "dqbuf: state is error\n"); @@ -650,6 +707,7 @@ int videobuf_streamon(struct videobuf_queue *q) if (q->irqlock) spin_unlock_irqrestore(q->irqlock, flags); + wake_up_interruptible_sync(&q->wait); done: mutex_unlock(&q->vb_lock); return retval; @@ -662,7 +720,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q) return -EINVAL; videobuf_queue_cancel(q); - q->streaming = 0; return 0; } @@ -865,7 +922,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q) q->bufs[i] = NULL; } q->read_buf = NULL; - q->reading = 0; } diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index ddf963c92e3e..53caa3102146 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -155,6 +155,8 @@ struct videobuf_queue { spinlock_t *irqlock; struct device *dev; + wait_queue_head_t wait; /* wait if queue is empty */ + enum v4l2_buf_type type; unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ unsigned int msize; -- cgit v1.2.3 From 4d53308ce1acf1072a6df2f9c239d052ede51d54 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 15:10:59 -0300 Subject: V4L/DVB (7494): videobuf-dma-sg.c: Avoid NULL dereference and add comment about backwards compatibility Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-sg.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 717783fa8b3e..e6ce99ff7fd1 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -546,6 +546,14 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, goto done; } + /* This function maintains backwards compatibility with V4L1 and will + * map more than one buffer if the vma length is equal to the combined + * size of multiple buffers than it will map them together. See + * VIDIOCGMBUF in the v4l spec + * + * TODO: Allow drivers to specify if they support this mode + */ + /* look for first buffer to map */ for (first = 0; first < VIDEO_MAX_FRAME; first++) { if (NULL == q->bufs[first]) @@ -590,10 +598,16 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); if (NULL == map) goto done; - for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) { + + size = 0; + for (i = first; i <= last; i++) { + if (NULL == q->bufs[i]) + continue; q->bufs[i]->map = map; q->bufs[i]->baddr = vma->vm_start + size; + size += q->bufs[i]->bsize; } + map->count = 1; map->start = vma->vm_start; map->end = vma->vm_end; -- cgit v1.2.3