From 9ba0a3c0e8147e5c8d04f2b284c44222af517307 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:44 -0300 Subject: [PATCH 001/452] 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(-) 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"); From 5eedc466758b5743512d38b5d1eab6f799a39e00 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 22 Apr 2008 14:41:44 -0300 Subject: [PATCH 002/452] 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(-) 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; From 763896c4b4d030b71880f5cb0ea0dfa7bb5ab96f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 22 Apr 2008 14:41:45 -0300 Subject: [PATCH 003/452] 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(-) 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}, From 29bec0bff50d8f8b108ed22e9981eb4635efc566 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 22 Apr 2008 14:41:45 -0300 Subject: [PATCH 004/452] 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(-) 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 "); From ff699e6bd02eb1c6d02c7c2b576c2ee6caab201c Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 22 Apr 2008 14:41:48 -0300 Subject: [PATCH 005/452] 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(-) 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 1a4d8319773c..1ca250378664 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 dabafdf71e60..ba7a74979dfb 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -50,7 +50,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 2404053a4d85..9199b5defb6b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -43,13 +43,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 e3ac5e686075..ffd3f106dd4f 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 */ From be71f7dc73d3afe6d6998a04d5c46d415c3bc62c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:48 -0300 Subject: [PATCH 006/452] 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(-) 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; From 7f8447d13d3abaeb46d0e6ae2890a843aa09561f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:49 -0300 Subject: [PATCH 007/452] 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(-) 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; } From 82b3083d2673e5fe8ac508071038b2b4c10bbf9c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:49 -0300 Subject: [PATCH 008/452] 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(-) 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: + */ From 65e8d29f7a37faaf9c73c633447bebd4b31b2c89 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:50 -0300 Subject: [PATCH 009/452] 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(-) 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; From 060a5bd764a1d798c20eceeaac5399c672334960 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:51 -0300 Subject: [PATCH 010/452] 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(-) 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; From b65aa2605683d90966a16abc68112c1fd9e3f3d8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:51 -0300 Subject: [PATCH 011/452] 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(-) 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; } From c7a9f3aa1e1b6c7ade5208b30683bec3553c3079 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:51 -0300 Subject: [PATCH 012/452] 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 | 381 ++++++++++++++++------------- 1 file changed, 209 insertions(+), 172 deletions(-) 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,11 +251,216 @@ 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) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u8 tuneraddr; + int rc; + + /* tv norm specific stuff for multi-norm tuners */ + switch (priv->type) { + 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 */ + *cb |= PHILIPS_MF_SET_STD_L; + else if (params->std & V4L2_STD_SECAM_LC) + *cb |= PHILIPS_MF_SET_STD_LC; + else /* V4L2_STD_B|V4L2_STD_GH */ + *cb |= PHILIPS_MF_SET_STD_BG; + break; + + case TUNER_TEMIC_4046FM5: + *cb &= ~0x0f; + + if (params->std & V4L2_STD_PAL_BG) { + *cb |= TEMIC_SET_PAL_BG; + + } else if (params->std & V4L2_STD_PAL_I) { + *cb |= TEMIC_SET_PAL_I; + + } else if (params->std & V4L2_STD_PAL_DK) { + *cb |= TEMIC_SET_PAL_DK; + + } else if (params->std & V4L2_STD_SECAM_L) { + *cb |= TEMIC_SET_PAL_L; + + } + break; + + case TUNER_PHILIPS_FQ1216ME: + *cb &= ~0x0f; + + if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { + *cb |= PHILIPS_SET_PAL_BGDK; + + } else if (params->std & V4L2_STD_PAL_I) { + *cb |= PHILIPS_SET_PAL_I; + + } else if (params->std & V4L2_STD_SECAM_L) { + *cb |= PHILIPS_SET_PAL_L; + + } + break; + + case TUNER_PHILIPS_ATSC: + /* 0x00 -> ATSC antenna input 1 */ + /* 0x01 -> ATSC antenna input 2 */ + /* 0x02 -> NTSC antenna input 1 */ + /* 0x03 -> NTSC antenna input 2 */ + *cb &= ~0x03; + if (!(params->std & V4L2_STD_ATSC)) + *cb |= 2; + /* FIXME: input */ + break; + + case TUNER_MICROTUNE_4042FI5: + /* Set the charge pump for fast tuning */ + *config |= TUNER_CHARGE_PUMP; + 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; + *cb &= ~0x40; + if (params->std & V4L2_STD_ATSC) { + *cb |= 0x40; + buffer[1] = 0x04; + } + /* set to the correct mode (analog or digital) */ + tuneraddr = priv->i2c_props.addr; + priv->i2c_props.addr = 0x0a; + 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; + } + + 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, tuneraddr; + u8 config, cb; u16 div; struct tunertype *tun; u8 buffer[4]; @@ -306,99 +511,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 */ - switch (priv->type) { - 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 */ - cb |= PHILIPS_MF_SET_STD_L; - else if (params->std & V4L2_STD_SECAM_LC) - cb |= PHILIPS_MF_SET_STD_LC; - else /* V4L2_STD_B|V4L2_STD_GH */ - cb |= PHILIPS_MF_SET_STD_BG; - break; - - case TUNER_TEMIC_4046FM5: - cb &= ~0x0f; - - if (params->std & V4L2_STD_PAL_BG) { - cb |= TEMIC_SET_PAL_BG; - - } else if (params->std & V4L2_STD_PAL_I) { - cb |= TEMIC_SET_PAL_I; - - } else if (params->std & V4L2_STD_PAL_DK) { - cb |= TEMIC_SET_PAL_DK; - - } else if (params->std & V4L2_STD_SECAM_L) { - cb |= TEMIC_SET_PAL_L; - - } - break; - - case TUNER_PHILIPS_FQ1216ME: - cb &= ~0x0f; - - if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { - cb |= PHILIPS_SET_PAL_BGDK; - - } else if (params->std & V4L2_STD_PAL_I) { - cb |= PHILIPS_SET_PAL_I; - - } else if (params->std & V4L2_STD_SECAM_L) { - cb |= PHILIPS_SET_PAL_L; - - } - break; - - case TUNER_PHILIPS_ATSC: - /* 0x00 -> ATSC antenna input 1 */ - /* 0x01 -> ATSC antenna input 2 */ - /* 0x02 -> NTSC antenna input 1 */ - /* 0x03 -> NTSC antenna input 2 */ - cb &= ~0x03; - if (!(params->std & V4L2_STD_ATSC)) - cb |= 2; - /* FIXME: input */ - break; - - case TUNER_MICROTUNE_4042FI5: - /* Set the charge pump for fast tuning */ - config |= TUNER_CHARGE_PUMP; - 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; - cb &= ~0x40; - if (params->std & V4L2_STD_ATSC) { - cb |= 0x40; - buffer[1] = 0x04; - } - /* set to the correct mode (analog or digital) */ - tuneraddr = priv->i2c_props.addr; - priv->i2c_props.addr = 0x0a; - 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; - } + simple_std_setup(fe, params, &buffer[1], &config, &cb); if (t_params->cb_first_if_lower_freq && div < priv->last_div) { buffer[0] = config; @@ -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]); + simple_post_tune(fe, &buffer[0], div, config, cb); - 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; } @@ -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 */ From 2e43c953bfd31f0104f916b2f39e6d3d8b1a3099 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:52 -0300 Subject: [PATCH 013/452] 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(-) 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: - */ From 3c2a0865d06df23f755a7d36a1076965500e1228 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:52 -0300 Subject: [PATCH 014/452] 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(-) 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__ */ From 2756665c28a7d2e25d92745195b5171866e12da9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:53 -0300 Subject: [PATCH 015/452] 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(-) 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; From f9e315a16a5536120bac09a6d4217b8381c73c5c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:54 -0300 Subject: [PATCH 016/452] 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(-) 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; From c1b4d92789ada9ea6b7f1156ede7022eab309eab Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:42:00 -0300 Subject: [PATCH 017/452] 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(-) 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__ */ From 27a643b1a9eded6a1b54df2743a7fb4383fd0cf9 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 22 Apr 2008 14:42:01 -0300 Subject: [PATCH 018/452] V4L/DVB (7140): 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(-) 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, From 26d507fcfef7f7d0cd2eec874a87169cc121c835 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Tue, 22 Apr 2008 14:42:02 -0300 Subject: [PATCH 019/452] V4L/DVB (7166): [v4l] Add new user class controls and deprecate others These changes should appear in the next update of the v4l2spec. HCENTER and VCENTER are unused in the tree so I added a _DEPRECATED postfix so applications can remove their use. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 17a80177a674..777bcb0daa11 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -849,21 +849,34 @@ struct v4l2_querymenu #define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) #define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) #define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) -#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) /* Deprecated */ #define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) #define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) #define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) #define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) #define V4L2_CID_GAMMA (V4L2_CID_BASE+16) -#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */ +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* Deprecated */ #define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) #define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) #define V4L2_CID_GAIN (V4L2_CID_BASE+19) #define V4L2_CID_HFLIP (V4L2_CID_BASE+20) #define V4L2_CID_VFLIP (V4L2_CID_BASE+21) -#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) -#define V4L2_CID_VCENTER (V4L2_CID_BASE+23) -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */ + +/* Deprecated, use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */ +#define V4L2_CID_HCENTER_DEPRECATED (V4L2_CID_BASE+22) +#define V4L2_CID_VCENTER_DEPRECATED (V4L2_CID_BASE+23) + +#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) +enum v4l2_power_line_frequency { + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, +}; +#define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) +#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) +#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) +#define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+29) /* last CID + 1 */ /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) From f9bd5843658e18a7097fc7258c60fb840109eaa8 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Tue, 22 Apr 2008 14:42:02 -0300 Subject: [PATCH 020/452] V4L/DVB (7167): [v4l] Add camera class control definitions Add all of the recently proposed camera class controls. These controls should appear in the next version of the v4l2spec. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 777bcb0daa11..b17f314a557e 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -793,6 +793,7 @@ struct v4l2_ext_controls /* Values for ctrl_class field */ #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ +#define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ #define V4L2_CTRL_ID_MASK (0x0fffffff) #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) @@ -1064,6 +1065,32 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type { #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) #define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11) +/* Camera class control IDs */ +#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) +#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1) + +#define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) +enum v4l2_exposure_auto_type { + V4L2_EXPOSURE_AUTO = 0, + V4L2_EXPOSURE_MANUAL = 1, + V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, + V4L2_EXPOSURE_APERTURE_PRIORITY = 3 +}; +#define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) +#define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) + +#define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4) +#define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5) +#define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6) +#define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7) + +#define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+8) +#define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+9) + +#define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10) +#define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) +#define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) + /* * T U N I N G */ From a7c7402f68cf97c9a021466c04029f039f9f4f27 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:03 -0300 Subject: [PATCH 021/452] V4L/DVB (7169): Add chip IDs for Micron mt9m001 and mt9v022 CMOS cameras Add V4L2_IDENT chip IDs for mt9m001 and mt9v022 cameras, will be used by future patches, primarily to implement the g_chip_ident ioctl. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-chip-ident.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 032bb75f69c2..0ea0bd85c036 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -153,6 +153,12 @@ enum { V4L2_IDENT_MSP4428G = 44287, V4L2_IDENT_MSP4448G = 44487, V4L2_IDENT_MSP4458G = 44587, + + /* Micron CMOS sensor chips: 45000-45099 */ + V4L2_IDENT_MT9M001C12ST = 45000, + V4L2_IDENT_MT9M001C12STM = 45005, + V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ + V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ }; #endif From e55222ef27a2390d8abce27a3ce2d4c719ad5f1b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:03 -0300 Subject: [PATCH 022/452] 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 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 From 3bc43840c3fbffaf8216883a37b336a41050d7f7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sun, 6 Apr 2008 21:24:56 -0300 Subject: [PATCH 023/452] V4L/DVB (7578a): V4L: V4L2 soc_camera driver for PXA270 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 it also supports the V4L2 API. This patch depends on a complementary patch, submitted to the ARM tree, providing PXA270 camera platform bindings. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 7 + drivers/media/video/Makefile | 1 + drivers/media/video/pxa_camera.c | 937 +++++++++++++++++++++++++++++++ 3 files changed, 945 insertions(+) create mode 100644 drivers/media/video/pxa_camera.c 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"); From f523dd0da985ef618d6f986217f0dd0975072515 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:04 -0300 Subject: [PATCH 024/452] 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 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"); From 7397bfbe10b52a47f1f6c69aa87192d97ffa1910 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:04 -0300 Subject: [PATCH 025/452] 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 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"); From bdb0aace95d42571ea054a56ed053f868336e13a Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 22 Apr 2008 14:42:05 -0300 Subject: [PATCH 026/452] V4L/DVB (7178): Add two new fourcc codes for 16bpp formats This adds two new fourcc codes (as per info at fourcc.org) for 16bpp mono and 16bpp Bayer formats. Signed-off-by: Steven Whitehouse Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index b17f314a557e..50e6c35f8907 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -282,6 +282,7 @@ struct v4l2_pix_format #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y','1','6',' ') /* 16 Greyscale */ #define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P','A','L','8') /* 8 8-bit palette */ #define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ #define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ @@ -308,6 +309,7 @@ struct v4l2_pix_format /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16 BGBG.. GRGR.. */ /* compressed formats */ #define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */ From ab6c46e24a3c89c1e2d0d3959e119583e1bc92d9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:42:05 -0300 Subject: [PATCH 027/452] 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(-) 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++; \ From 6d43cec87f9d9679a5c4adca7935dc8cf207f6ce Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:06 -0300 Subject: [PATCH 028/452] 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(-) 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 From e723ee00893f242cbccf5ef2faffdaa6afb8f244 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Tue, 22 Apr 2008 14:42:06 -0300 Subject: [PATCH 029/452] 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(-) 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) From a60b866567001e97b5bdc9811aee155ae759e48f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:42:06 -0300 Subject: [PATCH 030/452] 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(-) 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 */ + tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); - 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_write_regs(fe, R_TM, 15); - msleep(5); mutex_unlock(&priv->lock); return 0; From 4d2d42bcd8c73273f22d16ef4e619ce3f07f07d0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:42:07 -0300 Subject: [PATCH 031/452] 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(-) 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); From d1c53424f3ba9cc46bf3dbc550a916dc1b8355ee Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:42:07 -0300 Subject: [PATCH 032/452] 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 | 62 +++++++---------------- 1 file changed, 17 insertions(+), 45 deletions(-) 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,19 +727,28 @@ 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); - + switch (priv->id) { + case TDA18271HDC1: + tda18271c1_rf_tracking_filter_calibration(fe, freq, bw); + break; + case TDA18271HDC2: + tda18271c2_rf_tracking_filters_correction(fe, freq); + break; + } tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); mutex_unlock(&priv->lock); @@ -767,23 +756,6 @@ static int tda18271c1_tune(struct dvb_frontend *fe, 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); - break; - case TDA18271HDC2: - ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio); - break; - } - return ret; -} - /* ------------------------------------------------------------------ */ static int tda18271_set_params(struct dvb_frontend *fe, From 12afe3781870cad7b6bbe83a2f8c4dd9ec7bf214 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:42:07 -0300 Subject: [PATCH 033/452] 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(-) 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; From b4333a3baecfeee35317c03cf08952cc04bd149a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:08 -0300 Subject: [PATCH 034/452] 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(-) 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... */ From ef6ad5c35ed7233e7aafcc5645a1470199b10cc7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:08 -0300 Subject: [PATCH 035/452] 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(-) 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; From 05b207924d558935080ac08776236e42aca1708c Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Tue, 22 Apr 2008 14:42:08 -0300 Subject: [PATCH 036/452] 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(-) 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); From 26ec394e7c528e6f71e53a1335846328b8453ef5 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:42:09 -0300 Subject: [PATCH 037/452] 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(+) 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 From 4b1431ca1c98e26569c9b6cd6d06265cef9495ec Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:42:09 -0300 Subject: [PATCH 038/452] 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 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, From 6ab465a821756691009e58a51f1b4543cf1ae21a Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:42:11 -0300 Subject: [PATCH 039/452] 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(-) 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 From 1b1cee35defe792da9aab2757c28338731c46e84 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:42:12 -0300 Subject: [PATCH 040/452] 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(-) 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 }; From 7b5b3f1765c9773ec9b10c3e5299ac001211a80d Mon Sep 17 00:00:00 2001 From: Hermann Pitton Date: Tue, 22 Apr 2008 14:42:12 -0300 Subject: [PATCH 041/452] 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(+) 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 From 6a6179b6db401acde5798b4da0fdff32b126ee15 Mon Sep 17 00:00:00 2001 From: Russell Kliese Date: Tue, 22 Apr 2008 14:42:12 -0300 Subject: [PATCH 042/452] 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(+) 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 From f13613acfb1a71895ac886dc831d6ae4e20e241a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:42:13 -0300 Subject: [PATCH 043/452] 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(-) 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; From 0705135e59f8503e4dade4b3580fed77b1743b7c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:13 -0300 Subject: [PATCH 044/452] 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(-) 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); From 4d34dccd5e8af3db8dbb594d6cd1ea74446dbf20 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 22 Apr 2008 14:42:13 -0300 Subject: [PATCH 045/452] 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(-) 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)) From 491215d81049bfda749ebda007ecd3ae8bee19e3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:42:14 -0300 Subject: [PATCH 046/452] 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(-) 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 From 520ebe5f72ff450d7a73e8f669190254a5836093 Mon Sep 17 00:00:00 2001 From: Tyler Trafford Date: Tue, 22 Apr 2008 14:42:14 -0300 Subject: [PATCH 047/452] 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(-) 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); From 88ab075aee974f70b7b0273a964810698c8a5b95 Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Tue, 22 Apr 2008 14:42:14 -0300 Subject: [PATCH 048/452] 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(-) 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; From c9aec06f4a6029edd84022276e2bfadab5e85ade Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:42:15 -0300 Subject: [PATCH 049/452] 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(-) 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: { From 9b2e5c6bea4e2ddd5d66d23341f9763cbcad8de6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:42:16 -0300 Subject: [PATCH 050/452] 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(-) 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); From b1daf7e1233845db556ace20f80c7c531143498c Mon Sep 17 00:00:00 2001 From: maximilian attems Date: Tue, 22 Apr 2008 14:45:13 -0300 Subject: [PATCH 051/452] 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(+) 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[] = { From bb55de3b0e3523469491a48c51dcf7c6738162b2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:45:13 -0300 Subject: [PATCH 052/452] 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(-) 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) From 7102b773d538c1f064da22ae9a1fb86704747388 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 15 Apr 2008 02:57:48 -0300 Subject: [PATCH 053/452] 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 +++++++++++++------------------ 1 file changed, 64 insertions(+), 86 deletions(-) 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__); + dev_info(&pdev->dev, "PXA Camera driver unloaded\n"); 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, }; From 5c00fac0bab95a378e60c1a67e3d3c5ac44df412 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 22 Apr 2008 14:45:14 -0300 Subject: [PATCH 054/452] 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(+) 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, From 8efd2e28265ca031072d8d94cdbdd53904ce9b2d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:14 -0300 Subject: [PATCH 055/452] 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(-) 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 */ From c2cb8fcc006ce59255de67e3fe9f65fb79db633b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:14 -0300 Subject: [PATCH 056/452] 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(-) 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); From 9507901ef329b2dd3417372c7c9b2abcfd5c1885 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:15 -0300 Subject: [PATCH 057/452] 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(-) 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, From b3fb91d20ca111316854a166ff88b0c8c0f2388b Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Tue, 22 Apr 2008 14:45:15 -0300 Subject: [PATCH 058/452] 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(-) 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, From 8765561fc88131bbc9a6246010c15b63595ec35e Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Tue, 22 Apr 2008 14:45:15 -0300 Subject: [PATCH 059/452] 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(-) 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: From 1fe8736955515f5075bef05c366b2d145d29cd44 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:20 -0300 Subject: [PATCH 060/452] 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(-) 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); From 446018d80736ab16a117ce0db5a20467c91a0f90 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:20 -0300 Subject: [PATCH 061/452] 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(-) 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: From bc36a686a65dd9b941463ff894a3868c62851186 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:27 -0300 Subject: [PATCH 062/452] 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(-) 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); /* ----------------------------------------------------------- */ From c450e50e8d6a0876431a744f1df9fdd5c2732b07 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:28 -0300 Subject: [PATCH 063/452] 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(-) 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; } From 0f19e65bc5dcd30f1c5d72f56f6a9a2dc01698f3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:29 -0300 Subject: [PATCH 064/452] 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(-) 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); From 64016330b60e44db1383122a11611073fe98f261 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:30 -0300 Subject: [PATCH 065/452] 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(-) 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 */ From 23fb348d00da9c1558b4a9b234b9ac941091b0f1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:30 -0300 Subject: [PATCH 066/452] 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(-) 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 */ From 8cd7bf333671196e191bda62907b3b26e21da395 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:30 -0300 Subject: [PATCH 067/452] 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(+) 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; From c4a3ce1cd0c0ac394d1d56d8e0980b6836661341 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:31 -0300 Subject: [PATCH 068/452] 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(-) 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", From b573ea0a936eb2a7c6c57cdacb0d02bd358495a7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:31 -0300 Subject: [PATCH 069/452] 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(-) 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, From 1744a7770c27a709c464ce51617c2b31721db165 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 22 Apr 2008 14:45:32 -0300 Subject: [PATCH 070/452] 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(-) 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 */ From 6f2896756c4f1d4df5bd30599e6444c9513cfe8d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 22 Apr 2008 14:45:32 -0300 Subject: [PATCH 071/452] 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(-) 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; From 9dc4e48fbea5412127ce2eb30d688c4fc55f5565 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:45:32 -0300 Subject: [PATCH 072/452] 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(-) 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 { From e43d76b40d3fda146b9cd1192c5504a257603b70 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Tue, 22 Apr 2008 14:45:32 -0300 Subject: [PATCH 073/452] 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(+) 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; From 1c3bf598cf794558694c8beb0c8c7056a81dbe04 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 22 Apr 2008 14:45:33 -0300 Subject: [PATCH 074/452] 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(-) 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; From a58858556deb03ea4a464f84fe888692867ce377 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Tue, 22 Apr 2008 14:45:33 -0300 Subject: [PATCH 075/452] 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(-) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index ba7a74979dfb..58a1ddddb09e 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -509,9 +509,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: @@ -536,19 +536,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; } From 1117d6ba1313b8821b10403de114c38764008c45 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 22 Apr 2008 14:45:34 -0300 Subject: [PATCH 076/452] 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(+) 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, From 76464d412a5a51633881078d4109212e4463e8d4 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:35 -0300 Subject: [PATCH 077/452] 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(-) 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, }}, }, }; From 3c66e4e18b250f4524f24fd5b4ccdcd12bef9cc2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:35 -0300 Subject: [PATCH 078/452] 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(+) 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: From b01cd937895ad4114a07114cfb6b8b5d2be52241 Mon Sep 17 00:00:00 2001 From: Peter Hartley Date: Tue, 22 Apr 2008 14:45:36 -0300 Subject: [PATCH 079/452] 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(-) 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; From 27dea3eb667c058eebf2eb8a090f0e20333386e9 Mon Sep 17 00:00:00 2001 From: Wojciech Migda Date: Tue, 22 Apr 2008 14:45:36 -0300 Subject: [PATCH 080/452] 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(+) 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", From d068c6eec94c370a445a32f2f092c90798d47ca3 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:36 -0300 Subject: [PATCH 081/452] 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(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index fe9991c10cf4..87526666bc9e 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 @@ -210,6 +214,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[]; From 1aaac60fec0d3ba8043838c6eac86de987cfe5c1 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:36 -0300 Subject: [PATCH 082/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 87526666bc9e..4522ad6320c2 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 @@ -215,6 +230,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[]; From 29bf5b1d754a9a64f68c37938e1a0b7b63b724ba Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:37 -0300 Subject: [PATCH 083/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 9199b5defb6b..66945f7d2218 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -182,6 +182,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", @@ -367,6 +368,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; @@ -382,7 +404,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; } @@ -803,6 +826,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 */ From 895c3e8bfec9738251da9a2a8592dab15ec3a1bd Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:37 -0300 Subject: [PATCH 084/452] 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(+) 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; From 7fb20fa38caaf5c9d1b1d60b181c99ca30122520 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:37 -0300 Subject: [PATCH 085/452] V4L/DVB (7299): pvrusb2: Improve logic which handles input choice availability Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- .../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(-) 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 66945f7d2218..94cb0a76e77e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -370,23 +370,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) @@ -1834,7 +1818,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; @@ -1865,6 +1849,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, @@ -3780,6 +3773,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 *); From beb0ecd7f02f1a2da174b450d096e00530b3e8e8 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:38 -0300 Subject: [PATCH 086/452] 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(-) 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; } /* From bedbbf8be2f28c9f8a8cf1e2ead4fda8b5f47103 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:38 -0300 Subject: [PATCH 087/452] 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(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 07f4eae18433..17616f79f34e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -287,6 +287,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; @@ -298,6 +300,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; From fdf256f3374d5060e3714651b45b8450b7dc4349 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:38 -0300 Subject: [PATCH 088/452] 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(-) 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) { From dbc40a0e582a88d2561d13d1fea4f3496bff9650 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:39 -0300 Subject: [PATCH 089/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 94cb0a76e77e..ae36948c6c1d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1875,6 +1875,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 { From e1edb19a001b25c0ce2e52a669cba6b6eb31883c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:39 -0300 Subject: [PATCH 090/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index ae36948c6c1d..9408e8db98ef 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3193,17 +3193,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 *); From 7f421fe475726f0de55588a22c870e5cf35dc4f5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:39 -0300 Subject: [PATCH 091/452] 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(-) 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 From 99a6acf9a7a80da49e85be964b15ffed9ab7643e Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:39 -0300 Subject: [PATCH 092/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index 160437b21e6d..2a6726e403f0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -173,7 +173,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; } From 84147f3dd9187cd0c9810801be1282419a8ea00a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:40 -0300 Subject: [PATCH 093/452] 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(+) 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 9408e8db98ef..8eabb67e5895 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3241,6 +3241,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 *); From e8f5bacfcf2ba9a98674f3cd51b63020920e16aa Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:40 -0300 Subject: [PATCH 094/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 4522ad6320c2..1a60591e38b5 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 @@ -229,11 +229,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 8eabb67e5895..7016d3eda324 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1852,7 +1852,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; From 62433e312076d4ff4f2df357b2a6fac29974344a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:40 -0300 Subject: [PATCH 095/452] 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 --- .../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(-) 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 7016d3eda324..0941f0b434b7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1860,6 +1860,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, @@ -2380,6 +2388,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 @@ -2436,9 +2455,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; } @@ -3243,12 +3264,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; @@ -3258,24 +3281,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 : @@ -3286,10 +3300,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); @@ -3298,19 +3317,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) { @@ -3320,6 +3405,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); @@ -3345,7 +3431,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 || @@ -3399,13 +3487,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; } @@ -3442,7 +3533,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); @@ -3475,7 +3567,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 || @@ -3496,16 +3590,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; } @@ -3552,6 +3655,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, @@ -3599,6 +3703,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) { @@ -3606,13 +3720,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, @@ -3625,7 +3741,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 ? @@ -3641,7 +3757,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( @@ -3713,9 +3831,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 *); From e9db1ff23507d3e430db2bd130bd7861baa8c87e Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:41 -0300 Subject: [PATCH 096/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 0941f0b434b7..85e61d4b644e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2394,6 +2394,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. */ @@ -3392,6 +3393,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; } @@ -3720,7 +3722,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 ? " " : @@ -3759,7 +3761,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( From 1b9c18c54d68cc22f090948fc47890c56d22153d Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:41 -0300 Subject: [PATCH 097/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 85e61d4b644e..a85ffdaadccb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3352,6 +3352,7 @@ static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl) default: break; } + pvr2_hdw_untrip_unlocked(hdw); hdw->pathway_state = cmode; } @@ -3814,6 +3815,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"); @@ -3824,17 +3826,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 { From c55a97d7538d5f3abbee5486e37e56e896478fbd Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:41 -0300 Subject: [PATCH 098/452] 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(-) 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 a85ffdaadccb..9b1e22f2e555 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3357,6 +3357,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 *); From 40381cb02fb7fc0b46c55e3a71325b5d930580fa Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:42 -0300 Subject: [PATCH 099/452] 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 -- .../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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 1a60591e38b5..638c577e3268 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, }; @@ -235,6 +237,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 9b1e22f2e555..c51c5cef82dd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3357,24 +3357,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); } @@ -3871,6 +3895,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 *); From 5fd782af71876562c098aab0b240ceef2779d888 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:42 -0300 Subject: [PATCH 100/452] 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 | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) 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; - /* 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; - - /* 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 - 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; + /* 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 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 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 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[]; From fd1da7897999826d7491cdfd5b882ca8e9a965cb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:42 -0300 Subject: [PATCH 101/452] 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(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 638c577e3268..1edb066142b4 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 */ @@ -251,6 +271,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}, From ef7c37009225776e92979f464bfbf5d796d3a5ea Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:42 -0300 Subject: [PATCH 102/452] 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(-) 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, From a00199fb3fe41c8190c38e548a178e965f582cda Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:43 -0300 Subject: [PATCH 103/452] 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(-) 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, From ee9ca4b24f03b4da04cae1a24ea445ceb8a1f3d2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:43 -0300 Subject: [PATCH 104/452] 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(-) 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 { From c4a8828ddbf5fb445d2679ab006d5743540fc41a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:44 -0300 Subject: [PATCH 105/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index 2a6726e403f0..953784c08abb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -75,10 +75,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 c51c5cef82dd..f2d2677936b3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1813,8 +1813,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) { @@ -2039,7 +2054,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) { @@ -2521,17 +2535,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 *); From 8f59100a42576c49e2170e9dc04f8b7ac922a74d Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:45 -0300 Subject: [PATCH 106/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f2d2677936b3..1dff2d04a5d9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2114,13 +2114,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; From 794b16072e00d0a40a8c773dd4319fb1e460a632 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 22 Apr 2008 14:45:45 -0300 Subject: [PATCH 107/452] 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 | 111 ++++++++++------- drivers/media/video/pvrusb2/pvrusb2-context.h | 7 +- drivers/media/video/pvrusb2/pvrusb2-debug.h | 2 +- .../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 | 113 +++++++++--------- 7 files changed, 135 insertions(+), 125 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index 953784c08abb..22bd8302c4aa 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 @@ -30,32 +31,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; + mp->notify_flag = !0; + wake_up(&mp->wait_data); +} - 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; + +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( @@ -63,10 +97,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); @@ -75,57 +111,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; @@ -136,6 +160,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); } @@ -151,6 +176,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; @@ -163,6 +189,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 1dff2d04a5d9..7e7c570cf830 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -221,7 +221,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 *); @@ -1816,15 +1815,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; } @@ -2032,7 +2032,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); @@ -2517,15 +2516,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; + 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); + /* 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; From ebff033039b654b7b5493499babe22c7c1b0d36e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 22 Apr 2008 14:45:45 -0300 Subject: [PATCH 108/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 7e7c570cf830..8bdb807b19b8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1502,7 +1502,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, @@ -3695,7 +3695,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, From f0910c744324e3e853d7a80da876784319d9a1c8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:45 -0300 Subject: [PATCH 109/452] 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(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 1edb066142b4..17f461a78f13 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 From ddd5441df4127d5af45f6b2c58c2020b60bd52de Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:46 -0300 Subject: [PATCH 110/452] 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(+) 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", From 000e27a639f16e2df70a3b0bec7edfab79e5e717 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:46 -0300 Subject: [PATCH 111/452] V4L/DVB (7326): Fix bad whitespaces Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 266 +++++++++++++------------- 1 file changed, 133 insertions(+), 133 deletions(-) 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] = { - /* 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 = "Pinnacle Hybrid PCTV", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000067df, - } }, - .mpeg = CX88_MPEG_DVB, - }, + .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, + }, { + .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, From a9317abfba0850b006aed000e2acc4bee150410a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:46 -0300 Subject: [PATCH 112/452] 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(-) 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; From 4a24ce3a17ee713056db0a24cf558bd595211302 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Tue, 22 Apr 2008 14:45:47 -0300 Subject: [PATCH 113/452] 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(-) 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) { From 2c4a07b2da61bcd33f18195ff7f355c5bb285904 Mon Sep 17 00:00:00 2001 From: Sascha Sommer Date: Tue, 22 Apr 2008 14:45:47 -0300 Subject: [PATCH 114/452] 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(-) 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", From d6f34d7adddb144c3b450e15df3749f0e0a651c6 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 22 Apr 2008 14:45:47 -0300 Subject: [PATCH 115/452] 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(-) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 58a1ddddb09e..7942bd078513 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -508,7 +508,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; @@ -532,9 +532,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) From 1c659689fe9959c017bfaaa8301243f7d99f1a46 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 22 Apr 2008 14:45:47 -0300 Subject: [PATCH 116/452] 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(-) 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; From ad5f2e859d76dccb7eb1aa942171b1a32211efc2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 7 Mar 2008 21:57:18 -0300 Subject: [PATCH 117/452] 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 | 162 ++++++++++++++++++++++--------- drivers/media/video/soc_camera.c | 47 +++++---- include/media/soc_camera.h | 52 +++++++--- 5 files changed, 303 insertions(+), 164 deletions(-) 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; + /* Flags validity verified in test_bus_param */ - /* 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))) { + 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) +{ + /* + * 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 (buswidth) { + case 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)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_9; + break; + case 8: + if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_8; + } + + 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 int datawidth = 0, dw, bpp; + unsigned long dw, bpp, bus_flags, camera_flags, common_flags; u32 cicr0, cicr4 = 0; - int ret; + int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); - /* 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) + 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); + 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); - } + dev_dbg(&icd->dev, "set width: %d height: %d\n", + icd->width, icd->height); - return ret; + /* 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 From 0358d7c580370c5eaf081ac42a41c6e347709051 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:45:48 -0300 Subject: [PATCH 118/452] 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(-) 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; } From c0038ce025e1d70076894e6a206a73fd37ad493d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:45:49 -0300 Subject: [PATCH 119/452] 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(-) 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) { From d00573bbe9ce97798e08e6718f3459c2c2ceacc0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:45:50 -0300 Subject: [PATCH 120/452] 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(-) 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 From cd9fa026606848b2238a56e37b2c4aa4f371e152 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:45:50 -0300 Subject: [PATCH 121/452] 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(-) 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; From 11305d590895f22c30545ee0ff3fb434128fefb0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:45:50 -0300 Subject: [PATCH 122/452] 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(-) 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) { From e0028027c6e4a8aa8b3b77001b982a97ac35bbd7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:45:51 -0300 Subject: [PATCH 123/452] 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(-) 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; From 2fd3c14cf53c379602d1a8a1a0aed7737a48c5c6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:45:51 -0300 Subject: [PATCH 124/452] 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(-) 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) From 081b496a75fec134657f036f585738a1ca869047 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Apr 2008 14:45:51 -0300 Subject: [PATCH 125/452] 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(-) 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]; From ac8b63b30a320699e602a18af6101528b408d41d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:51 -0300 Subject: [PATCH 126/452] 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(-) 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) + mutex_lock(&tda9887_list_mutex); + + 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; - fe->analog_demod_priv = priv; + 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; + } - 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"); + mutex_unlock(&tda9887_list_mutex); memcpy(&fe->ops.analog_ops, &tda9887_ops, sizeof(struct analog_demod_ops)); From 62325497db6ef3b13cae41d5038e2693997d7d3e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:52 -0300 Subject: [PATCH 127/452] 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(-) 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[]; From a81df363554fb6439b5eb4ada06ad546a1df5ce3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:52 -0300 Subject: [PATCH 128/452] 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(-) 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); From bed6d189b965974a13c8c13313f9ebce06c12c3c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:52 -0300 Subject: [PATCH 129/452] 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(+) 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", From 22ef8fc945b28398d93a5d362e54915b66eba23f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:52 -0300 Subject: [PATCH 130/452] 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(+) 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", From 6f4a57292f4f0a0fef5e4e39cb394fedcf2acf9f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:53 -0300 Subject: [PATCH 131/452] 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(+) 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[]; From 23a88108cf6d5fa8073a3b2af804fff7305e86e3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:53 -0300 Subject: [PATCH 132/452] 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(-) 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; From dbe3127d72b42a81749efb48aa315bbacfbf89b8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:54 -0300 Subject: [PATCH 133/452] 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(+) 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", From f4173d0f75e55091d8b52145005bee11bc26c046 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:55 -0300 Subject: [PATCH 134/452] 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(-) 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)", From 02f5f4448464fea9c19e6b5ff5c67e874c898834 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:55 -0300 Subject: [PATCH 135/452] 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(+) 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; } From 0db5fd4b063e8ea746c08f8630fd6f64cb511a55 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:55 -0300 Subject: [PATCH 136/452] 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(+) 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", From a33b42c6bbe6c5b9067489df9e5650de751b798e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:56 -0300 Subject: [PATCH 137/452] 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(+) 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 */ From 0e5d383b0aca78c70c46b378f6b0e9d03a28c1af Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:56 -0300 Subject: [PATCH 138/452] 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(+) 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", From 26cd8972fb5cf673489005bf9b7d16e6f273422b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:56 -0300 Subject: [PATCH 139/452] 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(-) 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", From a2a7f84b7908c6dba998b43a1ed343aff1d2fd98 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:56 -0300 Subject: [PATCH 140/452] 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(-) 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; From 8b3b90aca293418171297ae14efac5817ba02bd3 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Tue, 22 Apr 2008 14:45:57 -0300 Subject: [PATCH 141/452] 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(-) 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); /* From b524f7b02d70204444441e4805fb3a71981e9018 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Tue, 22 Apr 2008 14:45:57 -0300 Subject: [PATCH 142/452] 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 | 1731 ++++++++++++++++------------- 1 file changed, 963 insertions(+), 768 deletions(-) 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,12 +269,942 @@ static int check_size(struct inode *inode, *maxw = fmt2.fmt.pix.width; *maxh = fmt2.fmt.pix.height; - done: +done: return 0; } /* ----------------------------------------------------------------- */ +static noinline int v4l1_compat_get_capabilities( + struct video_capability *cap, + struct inode *inode, + struct file *file, + v4l2_kioctl drv) +{ + 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); + 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_G_FBUF: %d\n", err); + memset(&fbuf, 0, sizeof(fbuf)); + } + err = 0; + } + + 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; +} + +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; + + 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; + } + 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; + } + 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; +} + +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; + + fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); + if (!fmt) { + err = -ENOMEM; + return err; + } + memset(win, 0, sizeof(*win)); + + 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; + goto done; + } + + 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; +} + +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; + } + 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("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n", + err); + win->width = fmt->fmt.pix.width; + win->height = fmt->fmt.pix.height; + } + + 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; +} + +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); + } + err = drv(inode, file, VIDIOC_OVERLAY, on); + if (err < 0) + dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); + return err; +} + +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; + + 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; + } + 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; +} + +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_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); + } + return 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; + + fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); + if (!fmt) { + err = -ENOMEM; + 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); + + 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; + } + + 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); + } + + 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; + } + + 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; + } + + 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; +} + +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)); + + 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; + goto done; + } + + 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; +} + +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; + 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); + } + err = 0; +done: + return err; +} + +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; + + 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("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; +} + +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; + } + + /* 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; + } + + /* 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; + 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; +} + +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; + } + fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; + + 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; +} + +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 (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. */ @@ -282,812 +1215,74 @@ v4l_compat_translate_ioctl(struct inode *inode, void *arg, 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; + int err; 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)); - - err = drv(inode, file, VIDIOC_QUERYCAP, cap2); - 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; - } - - 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 */ + err = v4l1_compat_get_capabilities(arg, inode, file, drv); break; - } case VIDIOCGFBUF: /* get frame buffer */ - { - struct video_buffer *buffer = arg; - - memset(buffer, 0, sizeof(*buffer)); - memset(&fbuf2, 0, sizeof(fbuf2)); - - 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; - - 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; - } + err = v4l1_compat_get_frame_buffer(arg, inode, file, drv); break; - } 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); + err = v4l1_compat_set_frame_buffer(arg, inode, file, drv); break; - } case VIDIOCGWIN: /* get window or capture dimensions */ - { - struct video_window *win = arg; - - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - break; - } - 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); - 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; - } - - 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; - win->clips = NULL; - win->clipcount = 0; + err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv); break; - } 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; - } - - 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; + err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv); break; - } 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); - if (err < 0) - dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); + err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv); break; - } 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; - } + err = v4l1_compat_get_input_info(arg, inode, file, drv); break; - } case VIDIOCSCHAN: /* set input */ - { - struct video_channel *chan = arg; - - 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); - } + err = v4l1_compat_set_input(arg, inode, file, drv); break; - } case VIDIOCGPICT: /* get tone controls & partial capture format */ - { - struct video_picture *pict = arg; - - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - 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); - - 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; - } - - 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); + err = v4l1_compat_get_picture(arg, inode, file, drv); break; - } case VIDIOCSPICT: /* set tone controls & partial capture format */ - { - struct video_picture *pict = arg; - int mem_err = 0, ovl_err = 0; - - 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); - } - - 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 = v4l1_compat_set_picture(arg, inode, file, drv); 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 (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; + err = v4l1_compat_get_tuner(arg, inode, file, drv); break; - } case VIDIOCSTUNER: /* select a tuner input */ - { - struct video_tuner *tun = arg; - struct v4l2_tuner t; - memset(&t, 0, sizeof(t)); - - t.index = tun->tuner; - - err = drv(inode, file, VIDIOC_S_INPUT, &t); - if (err < 0) - dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err); - + err = v4l1_compat_select_tuner(arg, inode, file, drv); break; - } 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; + err = v4l1_compat_get_frequency(arg, inode, file, drv); break; - } 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); + err = v4l1_compat_set_frequency(arg, inode, file, drv); break; - } 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 = 0; - break; - } - - 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; + err = v4l1_compat_get_audio(arg, inode, file, drv); break; - } case VIDIOCSAUDIO: /* set audio controls */ - { - struct video_audio *aud = arg; - - 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); - break; - } - - 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); - } - err = 0; + err = v4l1_compat_set_audio(arg, inode, file, drv); break; - } 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)); - - 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); - 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); - break; - } - err = drv(inode, file, VIDIOC_QBUF, &buf2); - if (err < 0) { - 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); + err = v4l1_compat_capture_frame(arg, inode, file, drv); break; - } case VIDIOCSYNC: /* wait for a frame */ - { - int *i = arg; - - 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; - } - - /* 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); - 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) { - 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); + err = v4l1_compat_sync(arg, inode, file, drv); break; - } - case VIDIOCGVBIFMT: /* query VBI data capture format */ - { - struct vbi_format *fmt = arg; - - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - break; - } - fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - - 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; + err = v4l1_compat_get_vbi_format(arg, inode, file, drv); break; - } case VIDIOCSVBIFMT: - { - struct vbi_format *fmt = arg; - - if (VIDEO_PALETTE_RAW != fmt->sample_format) { - err = -EINVAL; - break; - } - - 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; - } - - 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); + 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); From 76e41e4851e0c8b642e348d8489d7645b8dae21e Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Tue, 22 Apr 2008 14:45:57 -0300 Subject: [PATCH 143/452] 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(-) 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 { From 97275ac514c7f1131f42f8b06e073b144c744e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernesto=20Hern=C3=A1ndez-Novich?= Date: Tue, 22 Apr 2008 14:45:58 -0300 Subject: [PATCH 144/452] 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(+) 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 */ From e80faad3d7a332b7fe5a72dd64a81d28dd5c2e44 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Tue, 22 Apr 2008 14:45:58 -0300 Subject: [PATCH 145/452] 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(-) 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 */ From aba360d8cc086e12c3eb832f32d9e9813514e295 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 22 Apr 2008 14:45:59 -0300 Subject: [PATCH 146/452] 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(-) 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; From 2422a9b3f47c75d3915e6af78ebe25b7d2540262 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:00 -0300 Subject: [PATCH 147/452] 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(-) 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, From ceb63a4fda646faea60e34fa4c3abf8455add013 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:01 -0300 Subject: [PATCH 148/452] 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(+) 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; From 7f0dd17913eda77961fc8213b64cb8af4a155d3e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:01 -0300 Subject: [PATCH 149/452] 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(+) 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]; From 33b4af918a1ad73db47efec3cd23184d58f6ab31 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Tue, 22 Apr 2008 14:46:02 -0300 Subject: [PATCH 150/452] 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(-) 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; } From a920e42f61bdfe9974f3e2f3715d3a6d319eeaba Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:46:02 -0300 Subject: [PATCH 151/452] 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(-) 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; } From 50407f99a1fd7fcca74e53b1852dc70deb5114db Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:02 -0300 Subject: [PATCH 152/452] 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(-) 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) { From e9bcf6675d6da1a1e9925b2bdfc21f8d2330a1c5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:46:02 -0300 Subject: [PATCH 153/452] 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(-) 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, From b2cb200f0d0d5e801b47635554519f6e1b64e847 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:03 -0300 Subject: [PATCH 154/452] 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(-) 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; } From 7daa4a8897e79911f524ddac065adea05c7e9b16 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:46:03 -0300 Subject: [PATCH 155/452] 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(-) 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 && From cac2b0eb18e140e2f63146d0f97691e9238570b6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:04 -0300 Subject: [PATCH 156/452] 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(-) 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++; \ From e827931e37295329be0bc0e6c0283bfa4807b8f9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:05 -0300 Subject: [PATCH 157/452] 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(+) 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, From ab8b870e430d3e2cfb299f81e0ae0aef7fe5bfda Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:05 -0300 Subject: [PATCH 158/452] 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(-) 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 17f461a78f13..c33ba35a4ddf 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 */ From 5555309c9adcf9bb7f6b449ef45b09d5c26ef4ae Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:06 -0300 Subject: [PATCH 159/452] 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(-) 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)) From c293d0a72ecb9dd09037cdf4a9089e455404cf4a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:06 -0300 Subject: [PATCH 160/452] 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(-) 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 { From 7f7203df3f7d056e5f3c4419c6ab3835f44b288c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:06 -0300 Subject: [PATCH 161/452] 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(-) 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 = { From d9ae6dd76325d26a68068f7d8c78e0c7ec7e8f3e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:06 -0300 Subject: [PATCH 162/452] 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(-) 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, From 6e741713913fd28f8291fddb3d32d9353f1f0472 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:07 -0300 Subject: [PATCH 163/452] 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(+) 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, From c1e6393e24e0fcc8047db18dce05758c3fd54515 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 22 Apr 2008 14:46:07 -0300 Subject: [PATCH 164/452] 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(-) 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, From 867bc6cccc511ccbf40609ccb6ede2aafdeb922e Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:46:07 -0300 Subject: [PATCH 165/452] 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(-) 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)) { From 637afdb563a0801b6983650f889c64c074111776 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:46:08 -0300 Subject: [PATCH 166/452] 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(-) 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; From 5823b3a63c7661272ea7fef7635955e2a50d17eb Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:46:08 -0300 Subject: [PATCH 167/452] 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(-) 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; } From 7bff4b4d3ad2b9ff42b4087f409076035af1d165 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:46:08 -0300 Subject: [PATCH 168/452] 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(-) 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); From a4df8e1d6ae460546dfa3b4f23a85cb5a4255109 Mon Sep 17 00:00:00 2001 From: Alan McIvor Date: Tue, 22 Apr 2008 14:46:09 -0300 Subject: [PATCH 169/452] 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(+) 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; From e9c1ac9d8d75eaf15126e38cc7d09db03d1a3fd6 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:46:10 -0300 Subject: [PATCH 170/452] 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(-) 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}; From 0fea03fbd3aeaa9b4a4de8409e5ef3aca43a6d0b Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:46:10 -0300 Subject: [PATCH 171/452] 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(-) 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) { From 0be51b4671b3ae3ae544a0bb3d15b55478b55e72 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:10 -0300 Subject: [PATCH 172/452] 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(-) 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; } From b412ba781adcb484e8d9b19b30ae1d3a6b8c7d29 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:11 -0300 Subject: [PATCH 173/452] 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(-) 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)); From 03dea86de2243d5b3932604b799be26efeff010d Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Tue, 22 Apr 2008 14:46:11 -0300 Subject: [PATCH 174/452] 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(-) 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); } From 078ff7953448163d8779e489bd0119dd9a9b4732 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 22 Apr 2008 14:46:11 -0300 Subject: [PATCH 175/452] 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(+) 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 c69bde39a233..1ec18ed1a733 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -382,7 +382,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 6590058e8ff0..48ee2d892396 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -4659,7 +4659,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, From 8be38c815e181402c777e033f40971a7be19cf8b Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 22 Apr 2008 14:46:12 -0300 Subject: [PATCH 176/452] 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(-) 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; From 26f1b942156766c6ff1a70fb2ac463c6fce31309 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 24 Mar 2008 12:18:36 -0300 Subject: [PATCH 177/452] 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(-) 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; From 65511611dd0a5219b431a8a08cff6f8f7ab83aa5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:12 -0300 Subject: [PATCH 178/452] 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(-) 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)); From 0df31f8330bdaebde5411018f0142cca06ca23a3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:13 -0300 Subject: [PATCH 179/452] 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(-) 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; From 7e35c9ff1362aa4deb0b0a803d661920dcdd6f48 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:13 -0300 Subject: [PATCH 180/452] 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(-) 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; From 0efad8127ac4b32af780d722258b42cfae02cdf2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:13 -0300 Subject: [PATCH 181/452] 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(-) 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: From 967be9a9cd2de3f87dbf960620860143a50c1b64 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:13 -0300 Subject: [PATCH 182/452] 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(-) 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 From 827855d39761889aecc7c29385d9c4989b43d01d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:16 -0300 Subject: [PATCH 183/452] 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(-) 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; From cb89cd332d2f160623c92473945f729d43a70af0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:16 -0300 Subject: [PATCH 184/452] 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(-) 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: From fb147e9755055b1b73b22c3efe87bec075ad3caa Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:16 -0300 Subject: [PATCH 185/452] 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(-) 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: From 62ff817a04a5a08074c0391bdbf7bab48bdaa80e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:17 -0300 Subject: [PATCH 186/452] 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(-) 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: From 24d3980c3a4e073ade5e053d79864bf906c1e481 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:17 -0300 Subject: [PATCH 187/452] 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(-) 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 From 15b3feb73556208aec71569a6ccf9d8147ae6147 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:17 -0300 Subject: [PATCH 188/452] 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(-) 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 From 53f2dd33147c3040e56d4d7a99a876e07b2bc6ac Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:17 -0300 Subject: [PATCH 189/452] 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(-) 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 From 7b844d75dcbf48f22838df41b47d7b387533170f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:18 -0300 Subject: [PATCH 190/452] 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(-) 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 From 89418750f71b5b9bed7bd2bd8572fc54b049e1d5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:18 -0300 Subject: [PATCH 191/452] 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(-) 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. From 75a791925da909d489ef323e3a540ad1f1bca54f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:19 -0300 Subject: [PATCH 192/452] 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(-) 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 From 92d1069f3cfbe4da07d9cf5b1cb29930e6277def Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:19 -0300 Subject: [PATCH 193/452] 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(-) 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 From ad561caafaa02b2e1dfe25f6bae03806051992eb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:19 -0300 Subject: [PATCH 194/452] 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(-) 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 /** From b7f81b2058625b6fe90c9265aabbf0d3bdc15874 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:20 -0300 Subject: [PATCH 195/452] 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(-) 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 From 5e8556de79c509ea2ff3c3be19d3930f9ab5af54 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:20 -0300 Subject: [PATCH 196/452] 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(-) 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[] = { From b6fd549e50e11d91057dc367fa8f9d1352b145be Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:20 -0300 Subject: [PATCH 197/452] 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(-) 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. From 0c3ea9941c4957e4a9c229878bd13a39ac4d0e4b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:20 -0300 Subject: [PATCH 198/452] 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(-) 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; } From e83ebb64eff4636a5eab06a6cc493ab51e900ed0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:21 -0300 Subject: [PATCH 199/452] 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(-) 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 */ From ae07d042f626caa13d5a8a15ac7297b2873f7622 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:21 -0300 Subject: [PATCH 200/452] 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(-) 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; From 14c74b23b6b5a8259c25c8f825e3036f595518d0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:21 -0300 Subject: [PATCH 201/452] 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(-) 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 = { From c0dc0c1122b585193dd6650c749e919542dd3e23 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:22 -0300 Subject: [PATCH 202/452] 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(-) 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 = { From e7809a07663f868f596b5f08a63db9a32240502c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:22 -0300 Subject: [PATCH 203/452] 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(-) 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) From 40194b2b1bdd01358c1e9b5a9b8dd78390cc05f7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:22 -0300 Subject: [PATCH 204/452] 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(-) 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; } From 4efb0ca5d00f2c7a8bf9632556a4b4330cf409c5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:23 -0300 Subject: [PATCH 205/452] 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(-) 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); From 868f5ccd64113d070f09ecf2827a69b81c95ed9d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:23 -0300 Subject: [PATCH 206/452] 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(-) 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; From 5ec96b0c80eced33e7bf69a2d29c044d6dbe9bf5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:23 -0300 Subject: [PATCH 207/452] 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(-) 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. From 5c913c0571034fc08d9a27f4aa3175142352acf6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:24 -0300 Subject: [PATCH 208/452] 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(-) 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); From a03402d8ad1638a0a88c5091a189be146c1ee261 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:25 -0300 Subject: [PATCH 209/452] 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(-) 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 From 2c4963d4fb6103c0589db411fccf5e4f8531f173 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:25 -0300 Subject: [PATCH 210/452] 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(-) 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. From a2401d9eed955d90e682b911c343d7fb4ad22436 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 8 Mar 2008 04:02:20 -0300 Subject: [PATCH 211/452] 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 17616f79f34e..78ecfcbdd0b9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -288,7 +288,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; @@ -301,7 +301,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; From 99e09eac25f752b25f65392da7bd747b77040fea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Mar 2008 23:18:30 -0300 Subject: [PATCH 212/452] 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(-) 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; + /* Fills device-dependent initialization parameters */ + cx88_setup_xc3028(core, &ctl); + + /* Sends parameters to xc2028/3028 tuner */ 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; - } - 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 */ From b12203d253732d282dd97909a1424016694183e9 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 26 Mar 2008 02:07:35 -0300 Subject: [PATCH 213/452] 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(+) 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); From 1c412d1236b98bfc59fc694238cd26e6ed7f4f4b Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 22:43:20 -0300 Subject: [PATCH 214/452] V4L/DVB (7450): v4l2-api: Define a standard control for chroma AGC Define a pre-defined control ID for chroma automatic gain control. Signed-off-by: "Frej Drejhammar " Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 50e6c35f8907..0659661ab6cd 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -879,7 +879,9 @@ enum v4l2_power_line_frequency { #define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) #define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) #define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+29) /* last CID + 1 */ +#define V4L2_CID_CHROMA_AGC (V4L2_CID_BASE+29) +/* last CID + 1 */ +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+30) /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) From 6d04203c7f49a4d93304b5754de5457297fa04eb Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 22:43:21 -0300 Subject: [PATCH 215/452] 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(-) 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); From 87a1738919ef028d16c462437e1480fc67338cd3 Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 22:43:22 -0300 Subject: [PATCH 216/452] 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(-) 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, From a8ac688938b89ab0fa8ffe16da0facdc73a70588 Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 22:43:23 -0300 Subject: [PATCH 217/452] V4L/DVB (7453): v4l2-api: Define a standard control for color killer functionality Define a pre-defined control ID for color killer functionality. Signed-off-by: "Frej Drejhammar " Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 0659661ab6cd..c1411189ba6c 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -880,8 +880,9 @@ enum v4l2_power_line_frequency { #define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) #define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) #define V4L2_CID_CHROMA_AGC (V4L2_CID_BASE+29) +#define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30) /* last CID + 1 */ -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+30) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+31) /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) From 1b879c43811933514130421548fff7640e84d8e5 Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 22:43:24 -0300 Subject: [PATCH 218/452] 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(+) 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); From 0b86755f57bd2cc92d05ba3a613ab6ff44f09980 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Mar 2008 14:21:04 -0300 Subject: [PATCH 219/452] 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(-) 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, From cf8267ff100dd8466fe631f7172969945b654e3f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Mar 2008 17:45:51 -0300 Subject: [PATCH 220/452] 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(+) 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, }; From 95a2fdb6f78c020026b4fa82be506ef92961a9f6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Mar 2008 17:52:44 -0300 Subject: [PATCH 221/452] 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(-) 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", From 7bf9746d936740f9797c810ad75411a6cdeb9f2f Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Thu, 27 Mar 2008 23:51:05 -0300 Subject: [PATCH 222/452] 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(-) 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 From d69b2e41a5f6d934d01cc62f314697a60356b466 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 1 Apr 2008 20:30:24 -0300 Subject: [PATCH 223/452] 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(-) 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; } From 0b5afdd2ea5f52d260d1e42d43fb0fa09ec0da2f Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Sun, 23 Mar 2008 22:43:25 -0300 Subject: [PATCH 224/452] 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(-) 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, From 6394cf53abc0b3a2db9e8b947ef5c77b16861ec8 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 29 Mar 2008 20:49:57 -0300 Subject: [PATCH 225/452] 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 | 176 +++++++++++++++------- drivers/media/dvb/b2c2/flexcop-usb.c | 17 ++- drivers/media/dvb/b2c2/flexcop.c | 10 +- 6 files changed, 219 insertions(+), 121 deletions(-) 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 + mutex_unlock(&i2c->fc->i2c_mutex); + + if (ret == 0) ret = num; - - mutex_unlock(&fc->i2c_mutex); - 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)); + fc->fc_i2c_adap[0].fc = fc; + fc->fc_i2c_adap[1].fc = fc; + fc->fc_i2c_adap[2].fc = fc; - i2c_set_adapdata(&fc->i2c_adap,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; - 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; + 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); - if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0) + 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; + ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap); + if (ret < 0) + goto adap_1_failed; + + 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; From ca06fa79a5babc21f0240979e5b1dd34dcc3c6e4 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 29 Mar 2008 21:01:12 -0300 Subject: [PATCH 226/452] 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(-) 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", __FUNCTION__); + 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", __func__); return NULL; } #endif // CONFIG_DVB_CX24123 From 8c899bce2a5540b19e86dd3b355e5699657da144 Mon Sep 17 00:00:00 2001 From: Andre Weidemann Date: Sat, 29 Mar 2008 21:30:49 -0300 Subject: [PATCH 227/452] 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(-) 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, From 6ca8f0b97473dcef3a754bab5239dcfcdd00b244 Mon Sep 17 00:00:00 2001 From: Albert Comerma Date: Sat, 29 Mar 2008 21:35:57 -0300 Subject: [PATCH 228/452] 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(-) 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 From 58e6f95e613b37372a58fd504646ae1b1964c2ed Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 29 Mar 2008 21:37:01 -0300 Subject: [PATCH 229/452] 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(-) 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; - 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; } + 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]; + d->last_event = keymap[i].event; + return 0; + } + } + 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; } From dc88807ed61ed0fc0d57bd80a92508b9de638f5d Mon Sep 17 00:00:00 2001 From: Alexander Simon Date: Sat, 29 Mar 2008 21:37:54 -0300 Subject: [PATCH 230/452] 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(-) 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 From 5da4e2c645e4324f63fd87a0f93e3d0ad6619798 Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Sat, 29 Mar 2008 21:47:43 -0300 Subject: [PATCH 231/452] 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(-) 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 From d9aedf1fe88c04500fec269557a968e3320dd4b8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 30 Mar 2008 23:28:59 -0300 Subject: [PATCH 232/452] 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(-) 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) { From 762250f884cb927c7f1da4e24052ec43e000d53f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 30 Mar 2008 23:29:02 -0300 Subject: [PATCH 233/452] 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(-) 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); From c735372f5df2dc7b67080881bdc613d199173abf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 30 Mar 2008 19:40:20 -0300 Subject: [PATCH 234/452] 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(-) 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; From 8eb8ff3870ede23b2328ef376023a3542efcb9a5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 30 Mar 2008 17:00:45 -0300 Subject: [PATCH 235/452] 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(-) 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 From b608f4323a0e0440d18fa13aea3db98351137487 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 18:10:57 -0300 Subject: [PATCH 236/452] 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(+) 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) From 009a90597e177320e47154dd0817d201f52bcd46 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 18:10:59 -0300 Subject: [PATCH 237/452] 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(-) 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, From cbcb565f74cf01d680f83af531490bb2c5375af0 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 18:10:59 -0300 Subject: [PATCH 238/452] 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(-) 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; } From aa9dbac426d263b5b86d1684993d18ae187d7588 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 18:10:59 -0300 Subject: [PATCH 239/452] 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(-) 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; From 78718e5d44cd450431d5b16ee36d3a7de1db6dfa Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 18:10:59 -0300 Subject: [PATCH 240/452] 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 | 315 ++++++++++--------------------------- 1 file changed, 82 insertions(+), 233 deletions(-) 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); - - /* 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; - } - - do_gettimeofday(&buf->vb.ts); - dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); - - /* Fill buffer */ - vivi_fillbuff(dev, buf); - - if (list_empty(&dma_q->active)) { - del_timer(&dma_q->timeout); - } else { - mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT); - } + spin_lock_irqsave(&dev->slock, flags); + if (list_empty(&dma_q->active)) { + dprintk(dev, 1, "No active queue to serve\n"); + goto unlock; } - if (bc != 1) - dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n", - __FUNCTION__, bc); - spin_unlock(&dev->slock); + + buf = list_entry(dma_q->active.next, + struct vivi_buffer, vb.queue); + + /* Nobody is waiting on this buffer, return */ + if (!waitqueue_active(&buf->vb.done)) + goto unlock; + + list_del(&buf->vb.queue); + + 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; + struct vivi_dmaqueue *vidq = &dev->vidq; - 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); + dprintk(dev, 1, "%s\n", __FUNCTION__); - 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); - } - } + 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; From 137d1cb19d9da163ce6cb57a6fa1e6a3468af6a4 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 18:10:59 -0300 Subject: [PATCH 241/452] 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 | 100 ++++++++++++++++++++++------ include/media/videobuf-core.h | 2 + 2 files changed, 80 insertions(+), 22 deletions(-) diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 1ba3aaa29dd0..3ab556093ca7 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -141,6 +141,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); } @@ -188,6 +189,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); @@ -565,6 +570,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); @@ -575,37 +581,88 @@ int videobuf_qbuf(struct videobuf_queue *q, return retval; } + +/* Locking: Caller holds q->vb_lock */ +static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) +{ + int retval; + +checks: + if (!q->streaming) { + dprintk(1, "next_buffer: Not streaming\n"); + retval = -EINVAL; + goto done; + } + + if (list_empty(&q->stream)) { + 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); + 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; + struct videobuf_buffer *buf = NULL; 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"); - goto done; - } - if (list_empty(&q->stream)) { - dprintk(1, "dqbuf: stream running\n"); - 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); + + 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"); @@ -654,6 +711,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; @@ -666,7 +724,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q) return -EINVAL; videobuf_queue_cancel(q); - q->streaming = 0; return 0; } @@ -869,7 +926,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 fcdffdd63304..377a6c6e931b 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -153,6 +153,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; From ce54093cefd64c1a2cb6b8c5ed1d68d2bd7a34ab Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 18:10:59 -0300 Subject: [PATCH 242/452] 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(-) 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; From b8d9904c3525c0a149976ffaad48fcb03e8703f7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 4 Apr 2008 13:41:25 -0300 Subject: [PATCH 243/452] V4L/DVB (7500): soc-camera: extract function pointers from host object into operations Function pointers and the driver owner are not expected to change throughout soc-camera host's life. Extract them into an operations struct. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 27 +++++++++++++---------- drivers/media/video/soc_camera.c | 37 ++++++++++++++++---------------- include/media/soc_camera.h | 9 +++++--- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 4756699d16aa..9758f7eb5932 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -803,20 +803,25 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, return 0; } -/* Should beallocated dynamically too, but we have only one. */ +static struct soc_camera_host_ops pxa_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = pxa_camera_add_device, + .remove = pxa_camera_remove_device, + .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, +}; + +/* Should be allocated 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_videobuf_ops, - .add = pxa_camera_add_device, - .remove = pxa_camera_remove_device, .msize = sizeof(struct pxa_buffer), - .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, + .ops = &pxa_soc_camera_host_ops, }; static int pxa_camera_probe(struct platform_device *pdev) @@ -912,7 +917,7 @@ static int pxa_camera_probe(struct platform_device *pdev) 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); + err = soc_camera_host_register(&pxa_soc_camera_host); if (err) goto exit_free_irq; diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 4af38d444e0c..43c8110599e8 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -76,12 +76,12 @@ static int soc_camera_try_fmt_cap(struct file *file, void *priv, } /* test physical bus parameters */ - ret = ici->try_bus_param(icd, f->fmt.pix.pixelformat); + ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat); if (ret) return ret; /* limit format to hardware capabilities */ - ret = ici->try_fmt_cap(icd, f); + ret = ici->ops->try_fmt_cap(icd, f); /* calculate missing fields */ f->fmt.pix.field = field; @@ -143,7 +143,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv, if (ret < 0) return ret; - return ici->reqbufs(icf, p); + return ici->ops->reqbufs(icf, p); return ret; } @@ -203,7 +203,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) goto emgd; } - if (!try_module_get(ici->owner)) { + if (!try_module_get(ici->ops->owner)) { dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); ret = -EINVAL; goto emgi; @@ -215,7 +215,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* Now we really have to activate the camera */ if (icd->use_count == 1) { - ret = ici->add(icd); + ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); icd->use_count--; @@ -238,7 +238,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* All errors are entered with the video_lock held */ eiciadd: - module_put(ici->owner); + module_put(ici->ops->owner); emgi: module_put(icd->ops->owner); emgd: @@ -257,9 +257,9 @@ static int soc_camera_close(struct inode *inode, struct file *file) mutex_lock(&video_lock); icd->use_count--; if (!icd->use_count) - ici->remove(icd); + ici->ops->remove(icd); module_put(icd->ops->owner); - module_put(ici->owner); + module_put(ici->ops->owner); mutex_unlock(&video_lock); vfree(file->private_data); @@ -312,7 +312,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) return POLLERR; } - return ici->poll(file, pt); + return ici->ops->poll(file, pt); } @@ -356,7 +356,7 @@ 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_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); + ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); if (ret < 0) return ret; @@ -372,7 +372,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, icd->width, icd->height); /* set physical bus parameters */ - return ici->set_bus_param(icd, f->fmt.pix.pixelformat); + return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat); } static int soc_camera_enum_fmt_cap(struct file *file, void *priv, @@ -426,7 +426,7 @@ static int soc_camera_querycap(struct file *file, void *priv, WARN_ON(priv != file->private_data); strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver)); - return ici->querycap(ici, cap); + return ici->ops->querycap(ici, cap); } static int soc_camera_streamon(struct file *file, void *priv, @@ -579,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_fmt_cap(icd, 0, &a->c); + ret = ici->ops->set_fmt_cap(icd, 0, &a->c); if (!ret) { icd->width = a->c.width; icd->height = a->c.height; @@ -706,7 +706,7 @@ static int soc_camera_probe(struct device *dev) /* We only call ->add() here to activate and probe the camera. * We shall ->remove() and deactivate it immediately afterwards. */ - ret = ici->add(icd); + ret = ici->ops->add(icd); if (ret < 0) return ret; @@ -720,7 +720,7 @@ static int soc_camera_probe(struct device *dev) icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; } - ici->remove(icd); + ici->ops->remove(icd); return ret; } @@ -762,12 +762,12 @@ static void dummy_release(struct device *dev) { } -int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) +int soc_camera_host_register(struct soc_camera_host *ici) { int ret; struct soc_camera_host *ix; - if (!ici->vbq_ops || !ici->add || !ici->remove || !owner) + if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove) return -EINVAL; /* Number might be equal to the platform device ID */ @@ -785,7 +785,6 @@ int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) list_add_tail(&ici->list, &hosts); mutex_unlock(&list_lock); - ici->owner = owner; ici->dev.release = dummy_release; ret = device_register(&ici->dev); @@ -819,7 +818,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) if (icd->dev.parent == &ici->dev) { device_unregister(&icd->dev); /* Not before device_unregister(), .remove - * needs parent to call ici->remove() */ + * needs parent to call ici->ops->remove() */ icd->dev.parent = NULL; memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 7a2fa3ed849e..80e1193c07d5 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -56,9 +56,13 @@ struct soc_camera_host { unsigned char nr; /* Host number */ size_t msize; struct videobuf_queue_ops *vbq_ops; - struct module *owner; void *priv; char *drv_name; + struct soc_camera_host_ops *ops; +}; + +struct soc_camera_host_ops { + struct module *owner; int (*add)(struct soc_camera_device *); void (*remove)(struct soc_camera_device *); int (*set_fmt_cap)(struct soc_camera_device *, __u32, @@ -88,8 +92,7 @@ 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 int soc_camera_host_register(struct soc_camera_host *ici); 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); From 1a0063a9852380190a7172c1a1cb79e934b06cd4 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 4 Apr 2008 13:46:34 -0300 Subject: [PATCH 244/452] V4L/DVB (7501): soc-camera: use a spinlock for videobuffer queue All drivers should provide a spinlock to be used in videobuf operations. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 10 +++++++ drivers/media/video/soc_camera.c | 46 ++++++++++++++++++++++++++++---- include/media/soc_camera.h | 3 +++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 9758f7eb5932..bef3c9c7902a 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -803,6 +803,15 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, return 0; } +static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icf->icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + + return &pcdev->lock; +} + static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .owner = THIS_MODULE, .add = pxa_camera_add_device, @@ -814,6 +823,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .querycap = pxa_camera_querycap, .try_bus_param = pxa_camera_try_bus_param, .set_bus_param = pxa_camera_set_bus_param, + .spinlock_alloc = pxa_camera_spinlock_alloc, }; /* Should be allocated dynamically too, but we have only one. */ diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 43c8110599e8..1e921578804f 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -184,6 +184,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) struct soc_camera_device *icd; struct soc_camera_host *ici; struct soc_camera_file *icf; + spinlock_t *lock; int ret; icf = vmalloc(sizeof(*icf)); @@ -209,10 +210,16 @@ static int soc_camera_open(struct inode *inode, struct file *file) goto emgi; } - icd->use_count++; - icf->icd = icd; + icf->lock = ici->ops->spinlock_alloc(icf); + if (!icf->lock) { + ret = -ENOMEM; + goto esla; + } + + icd->use_count++; + /* Now we really have to activate the camera */ if (icd->use_count == 1) { ret = ici->ops->add(icd); @@ -229,8 +236,8 @@ static int soc_camera_open(struct inode *inode, struct file *file) 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_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, + * transform to normal dma_* ones. */ + videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, ici->msize, icd); @@ -238,6 +245,11 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* All errors are entered with the video_lock held */ eiciadd: + lock = icf->lock; + icf->lock = NULL; + if (ici->ops->spinlock_free) + ici->ops->spinlock_free(lock); +esla: module_put(ici->ops->owner); emgi: module_put(icd->ops->owner); @@ -253,16 +265,20 @@ static int soc_camera_close(struct inode *inode, struct file *file) 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; + spinlock_t *lock = icf->lock; mutex_lock(&video_lock); icd->use_count--; if (!icd->use_count) ici->ops->remove(icd); + icf->lock = NULL; + if (ici->ops->spinlock_free) + ici->ops->spinlock_free(lock); module_put(icd->ops->owner); module_put(ici->ops->owner); mutex_unlock(&video_lock); - vfree(file->private_data); + vfree(icf); dev_dbg(vdev->dev, "camera device close\n"); @@ -762,6 +778,21 @@ static void dummy_release(struct device *dev) { } +static spinlock_t *spinlock_alloc(struct soc_camera_file *icf) +{ + spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL); + + if (lock) + spin_lock_init(lock); + + return lock; +} + +static void spinlock_free(spinlock_t *lock) +{ + kfree(lock); +} + int soc_camera_host_register(struct soc_camera_host *ici) { int ret; @@ -792,6 +823,11 @@ int soc_camera_host_register(struct soc_camera_host *ici) if (ret) goto edevr; + if (!ici->ops->spinlock_alloc) { + ici->ops->spinlock_alloc = spinlock_alloc; + ici->ops->spinlock_free = spinlock_free; + } + scan_add_host(ici); return 0; diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 80e1193c07d5..6a8c8be7a1ae 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -48,6 +48,7 @@ struct soc_camera_device { struct soc_camera_file { struct soc_camera_device *icd; struct videobuf_queue vb_vidq; + spinlock_t *lock; }; struct soc_camera_host { @@ -73,6 +74,8 @@ struct soc_camera_host_ops { 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 *); + spinlock_t* (*spinlock_alloc)(struct soc_camera_file *); + void (*spinlock_free)(spinlock_t *); }; struct soc_camera_link { From d2db42dd4eb53b86a40b96b0b12a7b2d12377bdd Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Fri, 4 Apr 2008 20:50:07 -0300 Subject: [PATCH 245/452] V4L/DVB (7502): v4l: video/usbvision replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab --- .../media/video/usbvision/usbvision-core.c | 25 ++++++------- .../media/video/usbvision/usbvision-video.c | 36 +++++++++---------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 47f64a031cad..e518d8a35643 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -386,7 +386,7 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision) scratch_reset(usbvision); if(usbvision->scratch == NULL) { err("%s: unable to allocate %d bytes for scratch", - __FUNCTION__, scratch_buf_size); + __func__, scratch_buf_size); return -ENOMEM; } return 0; @@ -495,7 +495,8 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision) int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; usbvision->IntraFrameBuffer = vmalloc_32(IFB_size); if (usbvision->IntraFrameBuffer == NULL) { - err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size); + err("%s: unable to allocate %d for compr. frame buffer", + __func__, IFB_size); return -ENOMEM; } return 0; @@ -1518,7 +1519,7 @@ static void usbvision_isocIrq(struct urb *urb) if(errCode) { err("%s: usb_submit_urb failed: error %d", - __FUNCTION__, errCode); + __func__, errCode); } return; @@ -1549,7 +1550,7 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) 0, (__u16) reg, buffer, 1, HZ); if (errCode < 0) { - err("%s: failed: error %d", __FUNCTION__, errCode); + err("%s: failed: error %d", __func__, errCode); return errCode; } return buffer[0]; @@ -1577,7 +1578,7 @@ int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); if (errCode < 0) { - err("%s: failed: error %d", __FUNCTION__, errCode); + err("%s: failed: error %d", __func__, errCode); } return errCode; } @@ -1853,7 +1854,7 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); if (errCode < 0) { - err("%s failed: error %d", __FUNCTION__, errCode); + err("%s failed: error %d", __func__, errCode); return errCode; } usbvision->curwidth = usbvision->stretch_width * UsbWidth; @@ -2239,7 +2240,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) (__u16) USBVISION_DRM_PRM1, value, 8, HZ); if (rc < 0) { - err("%sERROR=%d", __FUNCTION__, rc); + err("%sERROR=%d", __func__, rc); return rc; } @@ -2488,7 +2489,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); if (urb == NULL) { - err("%s: usb_alloc_urb() failed", __FUNCTION__); + err("%s: usb_alloc_urb() failed", __func__); return -ENOMEM; } usbvision->sbuf[bufIdx].urb = urb; @@ -2522,13 +2523,13 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) GFP_KERNEL); if (errCode) { err("%s: usb_submit_urb(%d) failed: error %d", - __FUNCTION__, bufIdx, errCode); + __func__, bufIdx, errCode); } } usbvision->streaming = Stream_Idle; PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", - __FUNCTION__, + __func__, usbvision->video_endp); return 0; } @@ -2562,7 +2563,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) } - PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__); + PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__); usbvision->streaming = Stream_Off; if (!usbvision->remove_pending) { @@ -2573,7 +2574,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) usbvision->ifaceAlt); if (errCode < 0) { err("%s: usb_set_interface() failed: error %d", - __FUNCTION__, errCode); + __func__, errCode); usbvision->last_error = errCode; } regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 2c2e10639564..13f378c4439e 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -343,7 +343,7 @@ static void usbvision_create_sysfs(struct video_device *vdev) return; } while (0); - err("%s error: %d\n", __FUNCTION__, res); + err("%s error: %d\n", __func__, res); } static void usbvision_remove_sysfs(struct video_device *vdev) @@ -490,7 +490,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) mutex_unlock(&usbvision->lock); if (usbvision->remove_pending) { - printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__); + printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); } @@ -522,7 +522,7 @@ static int vidioc_g_register (struct file *file, void *priv, errCode = usbvision_read_reg(usbvision, reg->reg&0xff); if (errCode < 0) { err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", - __FUNCTION__, errCode); + __func__, errCode); return errCode; } reg->val = errCode; @@ -543,7 +543,7 @@ static int vidioc_s_register (struct file *file, void *priv, errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); if (errCode < 0) { err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", - __FUNCTION__, errCode); + __func__, errCode); return errCode; } return 0; @@ -1102,7 +1102,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, int ret,i; struct usbvision_frame *frame; - PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, + PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__, (unsigned long)count, noblock); if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) @@ -1171,7 +1171,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, } PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", - __FUNCTION__, + __func__, frame->index, frame->bytes_read, frame->scanlength); /* copy bytes to user space; we allow for partials reads */ @@ -1184,7 +1184,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, frame->bytes_read += count; PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", - __FUNCTION__, + __func__, (unsigned long)count, frame->bytes_read); /* For now, forget the frame if it has not been read in one shot. */ @@ -1269,12 +1269,12 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) (struct usb_usbvision *) video_get_drvdata(dev); int errCode = 0; - PDEBUG(DBG_IO, "%s:", __FUNCTION__); + PDEBUG(DBG_IO, "%s:", __func__); mutex_lock(&usbvision->lock); if (usbvision->user) { - err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__); + err("%s: Someone tried to open an already opened USBVision Radio!", __func__); errCode = -EBUSY; } else { @@ -1342,7 +1342,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file) mutex_unlock(&usbvision->lock); if (usbvision->remove_pending) { - printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__); + printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); } @@ -1507,7 +1507,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, struct video_device *vdev; if (usb_dev == NULL) { - err("%s: usbvision->dev is not set", __FUNCTION__); + err("%s: usbvision->dev is not set", __func__); return NULL; } @@ -1759,7 +1759,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, PDEBUG(DBG_PROBE, "model out of bounds %d",model); return -ENODEV; } - printk(KERN_INFO "%s: %s found\n", __FUNCTION__, + printk(KERN_INFO "%s: %s found\n", __func__, usbvision_device_data[model].ModelString); if (usbvision_device_data[model].Interface >= 0) { @@ -1771,20 +1771,20 @@ static int __devinit usbvision_probe(struct usb_interface *intf, if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { err("%s: interface %d. has non-ISO endpoint!", - __FUNCTION__, ifnum); + __func__, ifnum); err("%s: Endpoint attributes %d", - __FUNCTION__, endpoint->bmAttributes); + __func__, endpoint->bmAttributes); return -ENODEV; } if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { err("%s: interface %d. has ISO OUT endpoint!", - __FUNCTION__, ifnum); + __func__, ifnum); return -ENODEV; } if ((usbvision = usbvision_alloc(dev)) == NULL) { - err("%s: couldn't allocate USBVision struct", __FUNCTION__); + err("%s: couldn't allocate USBVision struct", __func__); return -ENOMEM; } @@ -1868,7 +1868,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) PDEBUG(DBG_PROBE, ""); if (usbvision == NULL) { - err("%s: usb_get_intfdata() failed", __FUNCTION__); + err("%s: usb_get_intfdata() failed", __func__); return; } usb_set_intfdata (intf, NULL); @@ -1891,7 +1891,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) if (usbvision->user) { printk(KERN_INFO "%s: In use, disconnect pending\n", - __FUNCTION__); + __func__); wake_up_interruptible(&usbvision->wait_frame); wake_up_interruptible(&usbvision->wait_stream); } else { From df18c3196a1ec1db7a20997d3246a5a8cf535a77 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Fri, 4 Apr 2008 21:00:57 -0300 Subject: [PATCH 246/452] V4L/DVB (7503): usbvision: rename __PRETTY_FUNCTION__ occurrences __PRETTY_FUNCTION__ has no sense in C lang context. Rename it as __func__ Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-core.c | 6 ++++-- drivers/media/video/usbvision/usbvision-i2c.c | 6 ++++-- drivers/media/video/usbvision/usbvision-video.c | 6 +++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index e518d8a35643..a9c5e5adba3a 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -84,8 +84,10 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]"); #ifdef USBVISION_DEBUG - #define PDEBUG(level, fmt, args...) \ - if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) + #define PDEBUG(level, fmt, args...) { \ + if (core_debug & (level)) \ + info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ + } #else #define PDEBUG(level, fmt, args...) do {} while(0) #endif diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index a7ed6f21f119..e2274d77ea29 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -45,8 +45,10 @@ 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]"); -#define PDEBUG(level, fmt, args...) \ - if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) +#define PDEBUG(level, fmt, args...) { \ + if (i2c_debug & (level)) \ + info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ + } static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len); diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 13f378c4439e..d97261ab430f 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -97,10 +97,10 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) #ifdef USBVISION_DEBUG - #define PDEBUG(level, fmt, args...) \ + #define PDEBUG(level, fmt, args...) { \ if (video_debug & (level)) \ - info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ ,\ - ## args) + info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ + } #else #define PDEBUG(level, fmt, args...) do {} while(0) #endif From ab364983087152e53676d914141f30e83ead12ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A2niel=20Fraga?= Date: Tue, 8 Apr 2008 19:54:49 -0300 Subject: [PATCH 247/452] V4L/DVB (7505): Powercolor Real Angel 330 (fixes gpio references) The attached patch fixes gpio references for Powercolor Real Angel 330. Signed-off-by: Daniel Fraga Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 70505b4e5b46..0534f589c725 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1492,28 +1492,26 @@ static const struct cx88_board cx88_boards[] = { .input = { { .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio0 = 0x00ff, .gpio1 = 0xf35d, - .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + .gpio3 = 0x0000, }, { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ - .gpio1 = 0x0000, - .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + .gpio0 = 0x00ff, + .gpio1 = 0xf37d, + .gpio3 = 0x0000, }, { .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, }, }, From ba928034df7e8b603152c896a2f84f9b12e8c290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A2niel=20Fraga?= Date: Tue, 8 Apr 2008 19:56:44 -0300 Subject: [PATCH 248/452] V4L/DVB (7506): Powercolor Real Angel 330 (remote control support) The attached patch adds complete remote control support for Powercolor Real Angel 330. Signed-off-by: Daniel Fraga Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 43 +++++++++++++++++++++++++++ drivers/media/video/cx88/cx88-input.c | 6 ++++ include/media/ir-common.h | 1 + 3 files changed, 50 insertions(+) diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 35793185630b..c5d10bdf4286 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2084,3 +2084,46 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = { [0x50] = KEY_BLUE, }; EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce); + +/* + * Remote control for Powercolor Real Angel 330 + * Daniel Fraga + */ +IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { + [0x38] = KEY_SWITCHVIDEOMODE, /* switch inputs */ + [0x0c] = KEY_MEDIA, /* Turn ON/OFF App */ + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x0a] = KEY_DIGITS, /* single, double, tripple digit */ + [0x29] = KEY_PREVIOUS, /* previous channel */ + [0x12] = KEY_BRIGHTNESSUP, + [0x13] = KEY_BRIGHTNESSDOWN, + [0x2b] = KEY_MODE, /* stereo/mono */ + [0x2c] = KEY_TEXT, /* teletext */ + [0x20] = KEY_UP, /* channel up */ + [0x21] = KEY_DOWN, /* channel down */ + [0x10] = KEY_RIGHT, /* volume up */ + [0x11] = KEY_LEFT, /* volume down */ + [0x0d] = KEY_MUTE, + [0x1f] = KEY_RECORD, + [0x17] = KEY_PLAY, + [0x16] = KEY_PAUSE, + [0x0b] = KEY_STOP, + [0x27] = KEY_FASTFORWARD, + [0x26] = KEY_REWIND, + [0x1e] = KEY_SEARCH, /* autoscan */ + [0x0e] = KEY_SHUFFLE, /* snapshot */ + [0x2d] = KEY_SETUP, + [0x0f] = KEY_SCREEN, /* full screen */ + [0x14] = KEY_RADIO, /* FM radio */ + [0x25] = KEY_POWER, /* power */ +}; +EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 6b25b8c9bb6d..53526d997a4e 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -317,6 +317,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir_type = IR_TYPE_RC5; ir->sampling = 1; break; + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + ir_codes = ir_codes_powercolor_real_angel; + ir->gpio_addr = MO_GP2_IO; + ir->mask_keycode = 0x7e; + ir->polling = 100; /* ms */ + break; } if (NULL == ir_codes) { diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 20f1afe2140e..75a3482866fe 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -144,6 +144,7 @@ extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; #endif From fc9d8ed418619da915ad8a225fa974d813d0ca34 Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Tue, 8 Apr 2008 21:45:08 -0300 Subject: [PATCH 249/452] V4L/DVB (7507): saa7134: add analog support for Avermedia A700 cards Add support for composite and s-video inputs on Avermedia DVB-S Pro and DVB-S Hybrid+FM cards (both labled A700) to the saa7134 driver. XC2028 support for Hybrid+FM is still missing. Signed-off-by: Matthias Schwarzott Reviewed-by: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 + drivers/media/video/saa7134/saa7134-cards.c | 63 ++++++++++++++++++++- drivers/media/video/saa7134/saa7134.h | 2 + 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index c1f9f138d1bb..fe925b335c94 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -138,3 +138,5 @@ 137 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936] 138 -> Avermedia M115 [1461:a836] 139 -> Compro VideoMate T750 [185b:c900] +140 -> Avermedia DVB-S Pro A700 [1461:a7a1] +141 -> Avermedia DVB-S Hybrid+FM A700 [1461:a7a2] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index cfa13c2fb14f..82fe19c3b1db 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4167,7 +4167,47 @@ struct saa7134_board saa7134_boards[] = { .name = name_radio, .amux = TV, } - } + }, + [SAA7134_BOARD_AVERMEDIA_A700_PRO] = { + /* Matthias Schwarzott */ + .name = "Avermedia DVB-S Pro A700", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* no DVB support for now */ + /* .mpeg = SAA7134_MPEG_DVB, */ + .inputs = { { + .name = name_comp, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 6, + .amux = LINE1, + } }, + }, + [SAA7134_BOARD_AVERMEDIA_A700_HYBRID] = { + /* Matthias Schwarzott */ + .name = "Avermedia DVB-S Hybrid+FM A700", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_ABSENT, /* TUNER_XC2028 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* no DVB support for now */ + /* .mpeg = SAA7134_MPEG_DVB, */ + .inputs = { { + .name = name_comp, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 6, + .amux = LINE1, + } }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4399,6 +4439,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0xa70b, .driver_data = SAA7134_BOARD_MD2819, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa7a1, + .driver_data = SAA7134_BOARD_AVERMEDIA_A700_PRO, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa7a2, + .driver_data = SAA7134_BOARD_AVERMEDIA_A700_HYBRID, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x1461, /* Avermedia Technologies Inc */ @@ -5462,6 +5514,15 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x8c040007, 0x8c040007); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd); break; + case SAA7134_BOARD_AVERMEDIA_A700_PRO: + case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: + /* write windows gpio values */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); + printk("%s: %s: hybrid analog/dvb card\n" + "%s: Sorry, only the analog inputs are supported for now.\n", + dev->name, card(dev).name, dev->name); + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 3394c47cea60..924ffd13637e 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -261,6 +261,8 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_A16D 137 #define SAA7134_BOARD_AVERMEDIA_M115 138 #define SAA7134_BOARD_VIDEOMATE_T750 139 +#define SAA7134_BOARD_AVERMEDIA_A700_PRO 140 +#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141 #define SAA7134_MAXBOARDS 8 From 536a0b119527c8af8e3a70b18f7640a21039a0a7 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 250/452] V4L/DVB (7508): media/common/ replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Acked-by: Oliver Endriss Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_core.c | 8 ++++---- drivers/media/common/saa7146_i2c.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 7707b8c7394b..89c7660b85d6 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -74,7 +74,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev, if (err) { printk(KERN_ERR "%s: %s timed out while waiting for " "registers getting programmed\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -ETIMEDOUT; } msleep(1); @@ -89,7 +89,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev, saa7146_read(dev, MC2); if (err) { DEB_S(("%s: %s timed out while waiting for transfer " - "completion\n", dev->name, __FUNCTION__)); + "completion\n", dev->name, __func__)); return -ETIMEDOUT; } msleep(1); @@ -111,7 +111,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev, if (!loops--) { printk(KERN_ERR "%s: %s timed out while waiting for " "registers getting programmed\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -ETIMEDOUT; } udelay(1); @@ -125,7 +125,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev, saa7146_read(dev, MC2); if (!loops--) { DEB_S(("%s: %s timed out while waiting for transfer " - "completion\n", dev->name, __FUNCTION__)); + "completion\n", dev->name, __func__)); return -ETIMEDOUT; } udelay(5); diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 7e7689afae62..35b01ec40a51 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c @@ -203,7 +203,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d return -ERESTARTSYS; printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -EIO; } status = saa7146_read(dev, I2C_STATUS); @@ -221,7 +221,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d } if (time_after(jiffies,timeout)) { printk(KERN_WARNING "%s %s: timed out waiting for MC2\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -EIO; } } @@ -238,7 +238,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d * (no answer from nonexisistant device...) */ printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -EIO; } if (++trial < 50 && short_delay) From 7bca4498f6ec331c2ace79824da8687ad35cd65c Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 251/452] V4L/DVB (7509): media/dvb/b2c2 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-dma.c | 4 ++-- drivers/media/dvb/b2c2/flexcop-sram.c | 28 +++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c index 6f592bc32d22..a91ed28f03a4 100644 --- a/drivers/media/dvb/b2c2/flexcop-dma.c +++ b/drivers/media/dvb/b2c2/flexcop-dma.c @@ -112,7 +112,7 @@ static int flexcop_dma_remap(struct flexcop_device *fc, { flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c; flexcop_ibi_value v = fc->read_ibi_reg(fc,r); - deb_info("%s\n",__FUNCTION__); + deb_info("%s\n",__func__); v.dma_0xc.remap_enable = onoff; fc->write_ibi_reg(fc,r,v); return 0; @@ -162,7 +162,7 @@ int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_remap(fc,dma_idx,0); - deb_info("%s\n",__FUNCTION__); + deb_info("%s\n",__func__); v.dma_0x4_write.dmatimer = cycles; fc->write_ibi_reg(fc,r,v); return 0; diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c index 01570ec80962..cda69528548a 100644 --- a/drivers/media/dvb/b2c2/flexcop-sram.c +++ b/drivers/media/dvb/b2c2/flexcop-sram.c @@ -90,7 +90,7 @@ static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 * }; if (retries == 0) - printk("%s: SRAM timeout\n", __FUNCTION__); + printk("%s: SRAM timeout\n", __func__); write_reg_dw(adapter, 0x700, command); @@ -115,7 +115,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, }; if (retries == 0) - printk("%s: SRAM timeout\n", __FUNCTION__); + printk("%s: SRAM timeout\n", __func__); write_reg_dw(adapter, 0x700, command); @@ -127,7 +127,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, }; if (retries == 0) - printk("%s: SRAM timeout\n", __FUNCTION__); + printk("%s: SRAM timeout\n", __func__); value = read_reg_dw(adapter, 0x700) >> 0x10; @@ -240,13 +240,13 @@ static void sram_init(struct adapter *adapter) adapter->dw_sram_type = tmp & 0x30000; - ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type); + ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); } else { adapter->dw_sram_type = 0x10000; - ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type); + ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); } /* return value is never used? */ @@ -257,7 +257,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) { u8 tmp1, tmp2; - dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr); + dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr); sram_set_size(adapter, mask); sram_init(adapter); @@ -275,7 +275,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) sram_read(adapter, addr, &tmp2, 1); sram_read(adapter, addr, &tmp2, 1); - dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2); + dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2); if (tmp2 != 0xa5) return 0; @@ -293,7 +293,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) sram_read(adapter, addr, &tmp2, 1); sram_read(adapter, addr, &tmp2, 1); - dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2); + dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2); if (tmp2 != 0x5a) return 0; @@ -340,7 +340,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) tmp3 = read_reg_dw(adapter, 0x71c); - dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3); + dprintk("%s: tmp3 = %x\n", __func__, tmp3); write_reg_dw(adapter, 0x71c, tmp2); @@ -351,7 +351,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: sram size = 32K\n", __FUNCTION__); + dprintk("%s: sram size = 32K\n", __func__); return 32; } @@ -361,7 +361,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: sram size = 128K\n", __FUNCTION__); + dprintk("%s: sram size = 128K\n", __func__); return 128; } @@ -371,7 +371,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: sram size = 64K\n", __FUNCTION__); + dprintk("%s: sram size = 64K\n", __func__); return 64; } @@ -381,7 +381,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: sram size = 32K\n", __FUNCTION__); + dprintk("%s: sram size = 32K\n", __func__); return 32; } @@ -390,7 +390,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__); + dprintk("%s: SRAM detection failed. Set to 32K \n", __func__); return 0; } From b2e62e7cdb8022087ae2def06f8023c9f5d3b411 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 252/452] V4L/DVB (7510): media/dvb/bt8xx replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dst.c | 2 +- drivers/media/dvb/bt8xx/dst_ca.c | 10 +++++----- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 307ff35bdf13..75711bde23ad 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1290,7 +1290,7 @@ static int dst_get_signal(struct dst_state *state) { int retval; u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb }; - //dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__); + //dprintk("%s: Getting Signal strength and other parameters\n", __func__); if ((state->diseq_flags & ATTEMPT_TUNE) == 0) { state->decode_lock = state->decode_strength = state->decode_snr = 0; return 0; diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 50bc32a8bd55..0258451423ad 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -36,13 +36,13 @@ #define dprintk(x, y, z, format, arg...) do { \ if (z) { \ if ((x > DST_CA_ERROR) && (x > y)) \ - printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \ + printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ else if ((x > DST_CA_NOTICE) && (x > y)) \ - printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \ + printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ else if ((x > DST_CA_INFO) && (x > y)) \ - printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \ + printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ else if ((x > DST_CA_DEBUG) && (x > y)) \ - printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \ + printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ } else { \ if (x > y) \ printk(format, ## arg); \ @@ -162,7 +162,7 @@ static int ca_get_app_info(struct dst_state *state) dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================"); dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]", state->messages[7], (state->messages[8] << 8) | state->messages[9], - (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12])); + (state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12])); dprintk(verbose, DST_CA_INFO, 1, " =================================================================================================="); // Transform dst message to correct application_info message diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 65081f161544..a39439b5f04c 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -671,7 +671,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) state->dst_ca = NULL; /* DST is not a frontend, attaching the ASIC */ if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) { - printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__); + printk("%s: Could not find a Twinhan DST.\n", __func__); break; } /* Attach other DST peripherals if any */ From 0592e8d3485c4976eaa6db8084e00b0132a34d7e Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 253/452] V4L/DVB (7511): media/dvb/cinergyT2 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/cinergyT2/cinergyT2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index db08b0a8888a..29b2459e0b21 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -62,7 +62,7 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); do { \ if ((debug & level)) { \ printk("%s: %s(): ", KBUILD_MODNAME, \ - __FUNCTION__); \ + __func__); \ printk(args); } \ } while (0) From 46b4f7c176a2dd4c60ddb7c80bd09ea2f3220674 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 254/452] V4L/DVB (7512): media/dvb/dvb-core replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Acked-by: Oliver Endriss Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 10 +++--- drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 36 ++++++++++----------- drivers/media/dvb/dvb-core/dvb_demux.c | 4 +-- drivers/media/dvb/dvb-core/dvb_frontend.c | 30 ++++++++--------- drivers/media/dvb/dvb-core/dvb_net.c | 30 ++++++++--------- drivers/media/dvb/dvb-core/dvbdev.c | 4 +-- 6 files changed, 57 insertions(+), 57 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 716735f03f55..3415a3bb363c 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -126,7 +126,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) struct dmxdev *dmxdev = dvbdev->priv; struct dmx_frontend *front; - dprintk("function : %s\n", __FUNCTION__); + dprintk("function : %s\n", __func__); if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; @@ -551,7 +551,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) dvb_dmxdev_section_callback); if (ret < 0) { printk("DVB (%s): could not alloc feed\n", - __FUNCTION__); + __func__); return ret; } @@ -559,7 +559,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) (para->flags & DMX_CHECK_CRC) ? 1 : 0); if (ret < 0) { printk("DVB (%s): could not set feed\n", - __FUNCTION__); + __func__); dvb_dmxdev_feed_restart(filter); return ret; } @@ -734,7 +734,7 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter, struct dmx_sct_filter_params *params) { - dprintk("function : %s\n", __FUNCTION__); + dprintk("function : %s\n", __func__); dvb_dmxdev_filter_stop(dmxdevfilter); @@ -1040,7 +1040,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) struct dmxdev *dmxdev = dvbdev->priv; unsigned int mask = 0; - dprintk("function : %s\n", __FUNCTION__); + dprintk("function : %s\n", __func__); poll_wait(file, &dmxdev->dvr_buffer.queue, wait); diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 89437fdab8be..8cbdb0ec67e2 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -250,7 +250,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, unsigned long timeout; unsigned long start; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* loop until timeout elapsed */ start = jiffies; @@ -263,7 +263,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, /* if we got the flags, it was successful! */ if (res & waitfor) { - dprintk("%s succeeded timeout:%lu\n", __FUNCTION__, jiffies - start); + dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start); return 0; } @@ -276,7 +276,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, msleep(1); } - dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start); + dprintk("%s failed timeout:%lu\n", __func__, jiffies - start); /* if we get here, we've timed out */ return -ETIMEDOUT; @@ -297,7 +297,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) int buf_size; u8 buf[2]; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* we'll be determining these during this function */ ca->slot_info[slot].da_irq_supported = 0; @@ -549,7 +549,7 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot) { int configoption; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* set the config option */ ca->pub->write_attribute_mem(ca->pub, slot, @@ -587,7 +587,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb u8 buf[HOST_LINK_BUF_SIZE]; int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* check if we have space for a link buf in the rx_buffer */ if (ebuf == NULL) { @@ -708,7 +708,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b int status; int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); // sanity check @@ -785,7 +785,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); */ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); ca->pub->slot_shutdown(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; @@ -892,7 +892,7 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot) static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); ca->wakeup = 1; mb(); @@ -964,7 +964,7 @@ static int dvb_ca_en50221_thread(void *data) int pktcount; void *rxbuf; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* choose the correct initial delay */ dvb_ca_en50221_thread_update_delay(ca); @@ -1172,7 +1172,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, int err = 0; int slot; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); switch (cmd) { case CA_RESET: @@ -1266,7 +1266,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, unsigned long timeout; int written; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ if (count < 2) @@ -1401,7 +1401,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, int pktlen; int dispose = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ if (count < 2) @@ -1490,7 +1490,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) int err; int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (!try_module_get(ca->pub->owner)) return -EIO; @@ -1534,7 +1534,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) struct dvb_ca_private *ca = dvbdev->priv; int err; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* mark the CA device as closed */ ca->open = 0; @@ -1564,7 +1564,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait) int slot; int result = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { mask |= POLLIN; @@ -1626,7 +1626,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_private *ca = NULL; int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (slot_count < 1) return -EINVAL; @@ -1704,7 +1704,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) struct dvb_ca_private *ca = pubca->private; int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* shutdown the thread if there was one */ kthread_stop(ca->thread); diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 988d14302cb1..934e15fffc56 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -553,7 +553,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed) spin_lock_irq(&feed->demux->lock); if (dvb_demux_feed_find(feed)) { printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n", - __FUNCTION__, feed->type, feed->state, feed->pid); + __func__, feed->type, feed->state, feed->pid); goto out; } @@ -567,7 +567,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed) spin_lock_irq(&feed->demux->lock); if (!(dvb_demux_feed_find(feed))) { printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n", - __FUNCTION__, feed->type, feed->state, feed->pid); + __func__, feed->type, feed->state, feed->pid); goto out; } diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 925cfa6221ad..2dddd08c5445 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -135,7 +135,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) struct dvb_frontend_event *e; int wp; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (mutex_lock_interruptible (&events->mtx)) return; @@ -171,7 +171,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_fe_events *events = &fepriv->events; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (events->overflow) { events->overflow = 0; @@ -237,7 +237,7 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr { int q2; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (locked) (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; @@ -329,7 +329,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra dprintk("%s: drift:%i inversion:%i auto_step:%i " "auto_sub_step:%i started_auto_step:%i\n", - __FUNCTION__, fepriv->lnb_drift, fepriv->inversion, + __func__, fepriv->lnb_drift, fepriv->inversion, fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); /* set the frontend itself */ @@ -511,7 +511,7 @@ static int dvb_frontend_thread(void *data) fe_status_t s; struct dvb_frontend_parameters *params; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); fepriv->check_wrapped = 0; fepriv->quality = 0; @@ -597,7 +597,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) { struct dvb_frontend_private *fepriv = fe->frontend_priv; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); fepriv->exit = 1; mb(); @@ -665,7 +665,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe) struct dvb_frontend_private *fepriv = fe->frontend_priv; struct task_struct *fe_thread; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (fepriv->thread) { if (!fepriv->exit) @@ -763,7 +763,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, struct dvb_frontend_private *fepriv = fe->frontend_priv; int err = -EOPNOTSUPP; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (fepriv->exit) return -ENODEV; @@ -895,7 +895,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, int i; u8 last = 1; if (dvb_frontend_debug) - printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd); + printk("%s switch command: 0x%04lx\n", __func__, cmd); do_gettimeofday(&nexttime); if (dvb_frontend_debug) memcpy(&tv[0], &nexttime, sizeof(struct timeval)); @@ -919,7 +919,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, } if (dvb_frontend_debug) { printk("%s(%d): switch delay (should be 32k followed by all 8k\n", - __FUNCTION__, fe->dvb->num); + __func__, fe->dvb->num); for (i = 1; i < 10; i++) printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); } @@ -1037,7 +1037,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); poll_wait (file, &fepriv->events.wait_queue, wait); @@ -1054,7 +1054,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) struct dvb_frontend_private *fepriv = fe->frontend_priv; int ret; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) @@ -1095,7 +1095,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) struct dvb_frontend_private *fepriv = fe->frontend_priv; int ret; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if ((file->f_flags & O_ACCMODE) != O_RDONLY) fepriv->release_jiffies = jiffies; @@ -1135,7 +1135,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb, .kernel_ioctl = dvb_frontend_ioctl }; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (mutex_lock_interruptible(&frontend_mutex)) return -ERESTARTSYS; @@ -1169,7 +1169,7 @@ EXPORT_SYMBOL(dvb_register_frontend); int dvb_unregister_frontend(struct dvb_frontend* fe) { struct dvb_frontend_private *fepriv = fe->frontend_priv; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); mutex_lock(&frontend_mutex); dvb_frontend_stop (fe); diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index efaa297ac34d..56d871cfd7fc 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -965,17 +965,17 @@ static int dvb_net_feed_start(struct net_device *dev) struct dmx_demux *demux = priv->demux; unsigned char *mac = (unsigned char *) dev->dev_addr; - dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode); + dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode); mutex_lock(&priv->mutex); if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) - printk("%s: BUG %d\n", __FUNCTION__, __LINE__); + printk("%s: BUG %d\n", __func__, __LINE__); priv->secfeed=NULL; priv->secfilter=NULL; priv->tsfeed = NULL; if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { - dprintk("%s: alloc secfeed\n", __FUNCTION__); + dprintk("%s: alloc secfeed\n", __func__); ret=demux->allocate_section_feed(demux, &priv->secfeed, dvb_net_sec_callback); if (ret<0) { @@ -993,38 +993,38 @@ static int dvb_net_feed_start(struct net_device *dev) } if (priv->rx_mode != RX_MODE_PROMISC) { - dprintk("%s: set secfilter\n", __FUNCTION__); + dprintk("%s: set secfilter\n", __func__); dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal); } switch (priv->rx_mode) { case RX_MODE_MULTI: for (i = 0; i < priv->multi_num; i++) { - dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i); + dprintk("%s: set multi_secfilter[%d]\n", __func__, i); dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i], priv->multi_macs[i], mask_normal); } break; case RX_MODE_ALL_MULTI: priv->multi_num=1; - dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__); + dprintk("%s: set multi_secfilter[0]\n", __func__); dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0], mac_allmulti, mask_allmulti); break; case RX_MODE_PROMISC: priv->multi_num=0; - dprintk("%s: set secfilter\n", __FUNCTION__); + dprintk("%s: set secfilter\n", __func__); dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc); break; } - dprintk("%s: start filtering\n", __FUNCTION__); + dprintk("%s: start filtering\n", __func__); priv->secfeed->start_filtering(priv->secfeed); } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { struct timespec timeout = { 0, 10000000 }; // 10 msec /* we have payloads encapsulated in TS */ - dprintk("%s: alloc tsfeed\n", __FUNCTION__); + dprintk("%s: alloc tsfeed\n", __func__); ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback); if (ret < 0) { printk("%s: could not allocate ts feed\n", dev->name); @@ -1048,7 +1048,7 @@ static int dvb_net_feed_start(struct net_device *dev) goto error; } - dprintk("%s: start filtering\n", __FUNCTION__); + dprintk("%s: start filtering\n", __func__); priv->tsfeed->start_filtering(priv->tsfeed); } else ret = -EINVAL; @@ -1063,17 +1063,17 @@ static int dvb_net_feed_stop(struct net_device *dev) struct dvb_net_priv *priv = dev->priv; int i, ret = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); mutex_lock(&priv->mutex); if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { if (priv->secfeed) { if (priv->secfeed->is_filtering) { - dprintk("%s: stop secfeed\n", __FUNCTION__); + dprintk("%s: stop secfeed\n", __func__); priv->secfeed->stop_filtering(priv->secfeed); } if (priv->secfilter) { - dprintk("%s: release secfilter\n", __FUNCTION__); + dprintk("%s: release secfilter\n", __func__); priv->secfeed->release_filter(priv->secfeed, priv->secfilter); priv->secfilter=NULL; @@ -1082,7 +1082,7 @@ static int dvb_net_feed_stop(struct net_device *dev) for (i=0; imulti_num; i++) { if (priv->multi_secfilter[i]) { dprintk("%s: release multi_filter[%d]\n", - __FUNCTION__, i); + __func__, i); priv->secfeed->release_filter(priv->secfeed, priv->multi_secfilter[i]); priv->multi_secfilter[i] = NULL; @@ -1096,7 +1096,7 @@ static int dvb_net_feed_stop(struct net_device *dev) } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { if (priv->tsfeed) { if (priv->tsfeed->is_filtering) { - dprintk("%s: stop tsfeed\n", __FUNCTION__); + dprintk("%s: stop tsfeed\n", __func__); priv->tsfeed->stop_filtering(priv->tsfeed); } priv->demux->release_ts_feed(priv->demux, priv->tsfeed); diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index ce5122e220f6..0a2897bc9873 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -196,7 +196,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, if ((id = dvbdev_get_free_id (adap, type)) < 0){ mutex_unlock(&dvbdev_register_lock); *pdvbdev = NULL; - printk(KERN_ERR "%s: couldn't find free device id\n", __FUNCTION__); + printk(KERN_ERR "%s: couldn't find free device id\n", __func__); return -ENFILE; } @@ -235,7 +235,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); if (IS_ERR(clsdev)) { printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", - __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev)); + __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); return PTR_ERR(clsdev); } From 708bebdd3922c6f346b8540f93c73f006d2b947b Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 255/452] V4L/DVB (7513): media/dvb/dvb-usb replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 6 +++--- drivers/media/dvb/dvb-usb/gp8psk-fe.c | 4 ++-- drivers/media/dvb/dvb-usb/m920x.c | 12 ++++++------ drivers/media/dvb/dvb-usb/vp702x-fe.c | 18 +++++++++--------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index b75b2b7a1330..4e5118dfe2e0 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -492,14 +492,14 @@ static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg) switch (command) { case XC2028_TUNER_RESET: - deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg); + deb_info("%s: XC2028_TUNER_RESET %d\n", __func__, arg); cxusb_bluebird_gpio_pulse(d, 0x01, 1); break; case XC2028_RESET_CLK: - deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg); + deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg); break; default: - deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__, + deb_info("%s: unknown command %d, arg %d\n", __func__, command, arg); return -EINVAL; } diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c index e37142d9271a..262a858c3068 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c +++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c @@ -152,7 +152,7 @@ static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe, { struct gp8psk_fe_state *st = fe->demodulator_priv; - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0, m->msg, m->msg_len)) { @@ -167,7 +167,7 @@ static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe, struct gp8psk_fe_state *st = fe->demodulator_priv; u8 cmd; - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); /* These commands are certainly wrong */ cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01; diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index a956bc503a4c..29ec2b967742 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c @@ -477,7 +477,7 @@ static struct qt1010_config m920x_qt1010_config = { /* Callbacks for DVB USB */ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) { - deb("%s\n",__FUNCTION__); + deb("%s\n",__func__); if ((adap->fe = dvb_attach(mt352_attach, &m920x_mt352_config, @@ -489,7 +489,7 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap) { - deb("%s\n",__FUNCTION__); + deb("%s\n",__func__); if ((adap->fe = dvb_attach(tda10046_attach, &m920x_tda10046_08_config, @@ -501,7 +501,7 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap) static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap) { - deb("%s\n",__FUNCTION__); + deb("%s\n",__func__); if ((adap->fe = dvb_attach(tda10046_attach, &m920x_tda10046_0b_config, @@ -513,7 +513,7 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap) static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap) { - deb("%s\n",__FUNCTION__); + deb("%s\n",__func__); if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL) return -ENODEV; @@ -523,7 +523,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap) static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap) { - deb("%s\n",__FUNCTION__); + deb("%s\n",__func__); if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL) return -ENODEV; @@ -533,7 +533,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap) static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap) { - deb("%s\n",__FUNCTION__); + deb("%s\n",__func__); if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) return -ENODEV; diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c index c3fdc7cd094e..ccc7e4452664 100644 --- a/drivers/media/dvb/dvb-usb/vp702x-fe.c +++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c @@ -67,7 +67,7 @@ static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) { struct vp702x_fe_state *st = fe->demodulator_priv; vp702x_fe_refresh_state(st); - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); if (st->lock == 0) *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; @@ -121,7 +121,7 @@ static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr) static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) { - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); tune->min_delay_ms = 2000; return 0; } @@ -183,21 +183,21 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe, static int vp702x_fe_init(struct dvb_frontend *fe) { struct vp702x_fe_state *st = fe->demodulator_priv; - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0); return 0; } static int vp702x_fe_sleep(struct dvb_frontend *fe) { - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); return 0; } static int vp702x_fe_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) { - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); return 0; } @@ -208,7 +208,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, u8 cmd[8],ibuf[10]; memset(cmd,0,8); - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); if (m->msg_len > 4) return -EINVAL; @@ -230,7 +230,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) { - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); return 0; } @@ -238,7 +238,7 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { struct vp702x_fe_state *st = fe->demodulator_priv; u8 ibuf[10]; - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); st->tone_mode = tone; @@ -263,7 +263,7 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t { struct vp702x_fe_state *st = fe->demodulator_priv; u8 ibuf[10]; - deb_fe("%s\n",__FUNCTION__); + deb_fe("%s\n",__func__); st->voltage = voltage; From 271ddbf702c3a4e6b18f6464180eda0f62efd9a5 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 256/452] V4L/DVB (7514): media/dvb/frontends replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Acked-by: Oliver Endriss Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/bcm3510.c | 4 +- drivers/media/dvb/frontends/bcm3510.h | 2 +- drivers/media/dvb/frontends/cx22700.c | 12 ++--- drivers/media/dvb/frontends/cx22700.h | 2 +- drivers/media/dvb/frontends/cx22702.c | 24 ++++----- drivers/media/dvb/frontends/cx22702.h | 2 +- drivers/media/dvb/frontends/cx24110.c | 6 +-- drivers/media/dvb/frontends/cx24110.h | 2 +- drivers/media/dvb/frontends/dib3000.h | 2 +- drivers/media/dvb/frontends/dib3000mc.h | 2 +- drivers/media/dvb/frontends/dvb-pll.h | 2 +- drivers/media/dvb/frontends/isl6405.h | 2 +- drivers/media/dvb/frontends/isl6421.h | 2 +- drivers/media/dvb/frontends/l64781.c | 2 +- drivers/media/dvb/frontends/l64781.h | 2 +- drivers/media/dvb/frontends/lgdt330x.c | 38 +++++++------- drivers/media/dvb/frontends/lgdt330x.h | 2 +- drivers/media/dvb/frontends/lnbp21.h | 2 +- drivers/media/dvb/frontends/mt2060.h | 2 +- drivers/media/dvb/frontends/mt2131.c | 14 +++--- drivers/media/dvb/frontends/mt2131.h | 2 +- drivers/media/dvb/frontends/mt2266.h | 2 +- drivers/media/dvb/frontends/mt312.c | 6 +-- drivers/media/dvb/frontends/mt312.h | 2 +- drivers/media/dvb/frontends/mt352.c | 8 +-- drivers/media/dvb/frontends/mt352.h | 2 +- drivers/media/dvb/frontends/nxt200x.c | 26 +++++----- drivers/media/dvb/frontends/nxt200x.h | 2 +- drivers/media/dvb/frontends/nxt6000.h | 2 +- drivers/media/dvb/frontends/or51132.c | 6 +-- drivers/media/dvb/frontends/or51132.h | 2 +- drivers/media/dvb/frontends/or51211.c | 6 +-- drivers/media/dvb/frontends/or51211.h | 2 +- drivers/media/dvb/frontends/qt1010.h | 2 +- drivers/media/dvb/frontends/s5h1409.c | 48 +++++++++--------- drivers/media/dvb/frontends/s5h1409.h | 2 +- drivers/media/dvb/frontends/s5h1420.c | 2 +- drivers/media/dvb/frontends/s5h1420.h | 2 +- drivers/media/dvb/frontends/sp8870.c | 26 +++++----- drivers/media/dvb/frontends/sp8870.h | 2 +- drivers/media/dvb/frontends/sp887x.c | 18 +++---- drivers/media/dvb/frontends/sp887x.h | 2 +- drivers/media/dvb/frontends/stv0297.c | 14 +++--- drivers/media/dvb/frontends/stv0297.h | 2 +- drivers/media/dvb/frontends/stv0299.c | 40 +++++++-------- drivers/media/dvb/frontends/stv0299.h | 2 +- drivers/media/dvb/frontends/tda10021.c | 4 +- drivers/media/dvb/frontends/tda10023.c | 4 +- drivers/media/dvb/frontends/tda1002x.h | 4 +- drivers/media/dvb/frontends/tda1004x.c | 56 ++++++++++----------- drivers/media/dvb/frontends/tda1004x.h | 4 +- drivers/media/dvb/frontends/tda10086.c | 40 +++++++-------- drivers/media/dvb/frontends/tda10086.h | 2 +- drivers/media/dvb/frontends/tda18271-priv.h | 2 +- drivers/media/dvb/frontends/tda18271.h | 2 +- drivers/media/dvb/frontends/tda8083.c | 4 +- drivers/media/dvb/frontends/tda8083.h | 2 +- drivers/media/dvb/frontends/tda826x.c | 10 ++-- drivers/media/dvb/frontends/tda826x.h | 2 +- drivers/media/dvb/frontends/tda827x.h | 2 +- drivers/media/dvb/frontends/tua6100.c | 2 +- drivers/media/dvb/frontends/tua6100.h | 2 +- drivers/media/dvb/frontends/ves1820.c | 4 +- drivers/media/dvb/frontends/ves1820.h | 2 +- drivers/media/dvb/frontends/ves1x93.c | 6 +-- drivers/media/dvb/frontends/ves1x93.h | 2 +- drivers/media/dvb/frontends/xc5000.c | 44 ++++++++-------- drivers/media/dvb/frontends/xc5000.h | 2 +- drivers/media/dvb/frontends/zl10353.c | 6 +-- drivers/media/dvb/frontends/zl10353.h | 2 +- 70 files changed, 283 insertions(+), 283 deletions(-) diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c index a913f49c062b..d268e65e777d 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb/frontends/bcm3510.c @@ -91,7 +91,7 @@ static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, reg, err); + __func__, state->config->demod_address, reg, err); return -EREMOTEIO; } @@ -110,7 +110,7 @@ static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 l if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) { deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, reg, err); + __func__, state->config->demod_address, reg, err); return -EREMOTEIO; } deb_i2c("i2c rd %02x: ",reg); diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h index 7e4f95e1734b..f4575c0cc446 100644 --- a/drivers/media/dvb/frontends/bcm3510.h +++ b/drivers/media/dvb/frontends/bcm3510.h @@ -41,7 +41,7 @@ extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config, static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config, struct i2c_adapter* i2c) { - 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_BCM3510 diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c index 11a4968f18cb..ace5cb17165d 100644 --- a/drivers/media/dvb/frontends/cx22700.c +++ b/drivers/media/dvb/frontends/cx22700.c @@ -73,13 +73,13 @@ static int cx22700_writereg (struct cx22700_state* state, u8 reg, u8 data) u8 buf [] = { reg, data }; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); ret = i2c_transfer (state->i2c, &msg, 1); if (ret != 1) printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n", - __FUNCTION__, reg, data, ret); + __func__, reg, data, ret); return (ret != 1) ? -1 : 0; } @@ -92,7 +92,7 @@ static int cx22700_readreg (struct cx22700_state* state, u8 reg) 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 } }; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); ret = i2c_transfer (state->i2c, msg, 2); @@ -105,7 +105,7 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion) { u8 val; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); switch (inversion) { case INVERSION_AUTO: @@ -127,7 +127,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 }; u8 val; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8) return -EINVAL; @@ -191,7 +191,7 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet FEC_5_6, FEC_7_8 }; u8 val; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (!(cx22700_readreg(state, 0x07) & 0x20)) /* tps valid? */ return -EAGAIN; diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb/frontends/cx22700.h index 7ac33690cdcc..4757a930ca05 100644 --- a/drivers/media/dvb/frontends/cx22700.h +++ b/drivers/media/dvb/frontends/cx22700.h @@ -38,7 +38,7 @@ extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, struct i2c_adapter* i2c) { - 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_CX22700 diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index 406c4cfa82bb..cc1db4e371c3 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -90,7 +90,7 @@ static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data) if (ret != 1) printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n", - __FUNCTION__, reg, data, ret); + __func__, reg, data, ret); return (ret != 1) ? -1 : 0; } @@ -108,7 +108,7 @@ static u8 cx22702_readreg (struct cx22702_state* state, u8 reg) ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) - printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + printk("%s: readreg error (ret == %i)\n", __func__, ret); return b1[0]; } @@ -195,7 +195,7 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) { struct cx22702_state* state = fe->demodulator_priv; - dprintk ("%s(%d)\n", __FUNCTION__, enable); + dprintk ("%s(%d)\n", __func__, enable); if (enable) return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe); else @@ -228,7 +228,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf ); break; default: - dprintk ("%s: invalid bandwidth\n",__FUNCTION__); + dprintk ("%s: invalid bandwidth\n",__func__); return -EINVAL; } @@ -250,7 +250,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc ); cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 ); cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */ - dprintk("%s: Autodetecting\n",__FUNCTION__); + dprintk("%s: Autodetecting\n",__func__); return 0; } @@ -261,7 +261,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet case QAM_16: val = (val&0xe7)|0x08; break; case QAM_64: val = (val&0xe7)|0x10; break; default: - dprintk ("%s: invalid constellation\n",__FUNCTION__); + dprintk ("%s: invalid constellation\n",__func__); return -EINVAL; } switch(p->u.ofdm.hierarchy_information) { @@ -270,7 +270,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet case HIERARCHY_2: val = (val&0xf8)|2; break; case HIERARCHY_4: val = (val&0xf8)|3; break; default: - dprintk ("%s: invalid hierarchy\n",__FUNCTION__); + dprintk ("%s: invalid hierarchy\n",__func__); return -EINVAL; } cx22702_writereg (state, 0x06, val); @@ -284,7 +284,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet case FEC_5_6: val = (val&0xc7)|0x18; break; case FEC_7_8: val = (val&0xc7)|0x20; break; default: - dprintk ("%s: invalid code_rate_HP\n",__FUNCTION__); + dprintk ("%s: invalid code_rate_HP\n",__func__); return -EINVAL; } switch(p->u.ofdm.code_rate_LP) { @@ -295,7 +295,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet case FEC_5_6: val = (val&0xf8)|3; break; case FEC_7_8: val = (val&0xf8)|4; break; default: - dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__); + dprintk ("%s: invalid code_rate_LP\n",__func__); return -EINVAL; } cx22702_writereg (state, 0x07, val); @@ -307,14 +307,14 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet case GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break; case GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break; default: - dprintk ("%s: invalid guard_interval\n",__FUNCTION__); + dprintk ("%s: invalid guard_interval\n",__func__); return -EINVAL; } switch(p->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: val = (val&0xfc); break; case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break; default: - dprintk ("%s: invalid transmission_mode\n",__FUNCTION__); + dprintk ("%s: invalid transmission_mode\n",__func__); return -EINVAL; } cx22702_writereg(state, 0x08, val); @@ -360,7 +360,7 @@ static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status) reg23 = cx22702_readreg (state, 0x23); dprintk ("%s: status demod=0x%02x agc=0x%02x\n" - ,__FUNCTION__,reg0A,reg23); + ,__func__,reg0A,reg23); if(reg0A & 0x10) { *status |= FE_HAS_LOCK; diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h index 9cd64da6ee40..8af766a31552 100644 --- a/drivers/media/dvb/frontends/cx22702.h +++ b/drivers/media/dvb/frontends/cx22702.h @@ -48,7 +48,7 @@ extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, struct i2c_adapter* i2c) { - 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_CX22702 diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index b03d8283c37d..87ae29db024f 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -121,7 +121,7 @@ static int cx24110_writereg (struct cx24110_state* state, int reg, int data) if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { dprintk ("%s: writereg error (err == %i, reg == 0x%02x," - " data == 0x%02x)\n", __FUNCTION__, err, reg, data); + " data == 0x%02x)\n", __func__, err, reg, data); return -EREMOTEIO; } @@ -247,7 +247,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) static const u32 bands[]={5000000UL,15000000UL,90999000UL/2}; int i; - dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate); + dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate); if (srate>90999000UL/2) srate=90999000UL/2; if (srate<500000) @@ -358,7 +358,7 @@ static int cx24110_initfe(struct dvb_frontend* fe) /* fixme (low): error handling */ int i; - dprintk("%s: init chip\n", __FUNCTION__); + dprintk("%s: init chip\n", __func__); for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) { cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data); diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h index 0ca3af4db513..1792adb23c4d 100644 --- a/drivers/media/dvb/frontends/cx24110.h +++ b/drivers/media/dvb/frontends/cx24110.h @@ -48,7 +48,7 @@ extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, struct i2c_adapter* i2c) { - 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_CX24110 diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h index a6d3854a67bc..ba917359fa65 100644 --- a/drivers/media/dvb/frontends/dib3000.h +++ b/drivers/media/dvb/frontends/dib3000.h @@ -48,7 +48,7 @@ extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops) { - 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_DIB3000MB diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h index 72d4757601d8..4142ed7a47d0 100644 --- a/drivers/media/dvb/frontends/dib3000mc.h +++ b/drivers/media/dvb/frontends/dib3000mc.h @@ -44,7 +44,7 @@ extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i #else static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg) { - 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_DIB3000MC diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 435146d9fa12..872ca29e7cf3 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -43,7 +43,7 @@ static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, unsigned int pll_desc_id) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h index 9d4001a2237e..1c793d37576b 100644 --- a/drivers/media/dvb/frontends/isl6405.h +++ b/drivers/media/dvb/frontends/isl6405.h @@ -66,7 +66,7 @@ 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__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif /* CONFIG_DVB_ISL6405 */ diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h index ea7f78a7d3cd..47e4518a042d 100644 --- a/drivers/media/dvb/frontends/isl6421.h +++ b/drivers/media/dvb/frontends/isl6421.h @@ -47,7 +47,7 @@ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_a static inline struct dvb_frontend *isl6421_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__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif // CONFIG_DVB_ISL6421 diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c index 443d9045d4c9..e1e70e9e0cb9 100644 --- a/drivers/media/dvb/frontends/l64781.c +++ b/drivers/media/dvb/frontends/l64781.c @@ -57,7 +57,7 @@ static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data) if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) dprintk ("%s: write_reg error (reg == %02x) = %02x!\n", - __FUNCTION__, reg, ret); + __func__, reg, ret); return (ret != 1) ? -1 : 0; } diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h index cd15f76ff28d..1305a9e7fb0b 100644 --- a/drivers/media/dvb/frontends/l64781.h +++ b/drivers/media/dvb/frontends/l64781.h @@ -38,7 +38,7 @@ extern struct dvb_frontend* l64781_attach(const struct l64781_config* config, static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config, struct i2c_adapter* i2c) { - 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_L64781 diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index dc897a3903fc..f0195c8272f4 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -88,7 +88,7 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state, for (i=0; ii2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err); + printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err); if (err < 0) return err; else @@ -117,7 +117,7 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state, int ret; ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { - printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret); + printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret); } else { ret = 0; } @@ -256,7 +256,7 @@ static int lgdt330x_init(struct dvb_frontend* fe) printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n"); err = -ENODEV; } - dprintk("%s entered as %s\n", __FUNCTION__, chip_name); + dprintk("%s entered as %s\n", __func__, chip_name); if (err < 0) return err; return lgdt330x_SwReset(state); @@ -334,7 +334,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, if (state->current_modulation != param->u.vsb.modulation) { switch(param->u.vsb.modulation) { case VSB_8: - dprintk("%s: VSB_8 MODE\n", __FUNCTION__); + dprintk("%s: VSB_8 MODE\n", __func__); /* Select VSB mode */ top_ctrl_cfg[1] = 0x03; @@ -350,7 +350,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, break; case QAM_64: - dprintk("%s: QAM_64 MODE\n", __FUNCTION__); + dprintk("%s: QAM_64 MODE\n", __func__); /* Select QAM_64 mode */ top_ctrl_cfg[1] = 0x00; @@ -366,7 +366,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, break; case QAM_256: - dprintk("%s: QAM_256 MODE\n", __FUNCTION__); + dprintk("%s: QAM_256 MODE\n", __func__); /* Select QAM_256 mode */ top_ctrl_cfg[1] = 0x01; @@ -381,7 +381,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, } break; default: - printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation); + printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation); return -1; } /* @@ -431,7 +431,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) /* AGC status register */ i2c_read_demod_bytes(state, AGC_STATUS, buf, 1); - dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); + dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]); if ((buf[0] & 0x0c) == 0x8){ /* Test signal does not exist flag */ /* as well as the AGC lock flag. */ @@ -445,7 +445,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) */ /* signal status */ i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf)); - dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]); + dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]); /* sync status */ @@ -461,7 +461,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) /* Carrier Recovery Lock Status Register */ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1); - dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); + dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]); switch (state->current_modulation) { case QAM_256: case QAM_64: @@ -474,7 +474,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) *status |= FE_HAS_CARRIER; break; default: - printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); + printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__); } return 0; @@ -493,7 +493,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) if (err < 0) return err; - dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); + dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]); if ((buf[0] & 0x21) == 0x01){ /* Test input signal does not exist flag */ /* as well as the AGC lock flag. */ @@ -502,7 +502,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) /* Carrier Recovery Lock Status Register */ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1); - dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); + dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]); switch (state->current_modulation) { case QAM_256: case QAM_64: @@ -533,7 +533,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) } break; default: - printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); + printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__); } return 0; } @@ -607,14 +607,14 @@ static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) break; default: printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", - __FUNCTION__); + __func__); return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ } state->snr = calculate_snr(noise, c); *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ - dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, + dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise, state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); return 0; @@ -651,14 +651,14 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) break; default: printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", - __FUNCTION__); + __func__); return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ } state->snr = calculate_snr(noise, c); *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ - dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, + dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise, state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16); return 0; @@ -743,7 +743,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, error: kfree(state); - dprintk("%s: ERROR\n",__FUNCTION__); + dprintk("%s: ERROR\n",__func__); return NULL; } diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h index 995059004b10..9012504f0f2d 100644 --- a/drivers/media/dvb/frontends/lgdt330x.h +++ b/drivers/media/dvb/frontends/lgdt330x.h @@ -59,7 +59,7 @@ extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, struct i2c_adapter* i2c) { - 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_LGDT330X diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h index 68906acf7d63..8fe094bd9689 100644 --- a/drivers/media/dvb/frontends/lnbp21.h +++ b/drivers/media/dvb/frontends/lnbp21.h @@ -45,7 +45,7 @@ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_ad #else static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) { - 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_LNBP21 diff --git a/drivers/media/dvb/frontends/mt2060.h b/drivers/media/dvb/frontends/mt2060.h index 0a86eab3a954..acba0058f519 100644 --- a/drivers/media/dvb/frontends/mt2060.h +++ b/drivers/media/dvb/frontends/mt2060.h @@ -35,7 +35,7 @@ extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_a #else static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1) { - 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_TUNER_MT2060 diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c index 13cf16668171..e254bcfc2efb 100644 --- a/drivers/media/dvb/frontends/mt2131.c +++ b/drivers/media/dvb/frontends/mt2131.c @@ -110,7 +110,7 @@ static int mt2131_set_params(struct dvb_frontend *fe, priv->bandwidth = 0; freq = params->frequency / 1000; // Hz -> kHz - dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq); + dprintk(1, "%s() freq=%d\n", __func__, freq); f_lo1 = freq + MT2131_IF1 * 1000; f_lo1 = (f_lo1 / 250) * 250; @@ -187,7 +187,7 @@ static int mt2131_set_params(struct dvb_frontend *fe, static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct mt2131_priv *priv = fe->tuner_priv; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); *frequency = priv->frequency; return 0; } @@ -195,7 +195,7 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency) static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) { struct mt2131_priv *priv = fe->tuner_priv; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); *bandwidth = priv->bandwidth; return 0; } @@ -214,7 +214,7 @@ static int mt2131_get_status(struct dvb_frontend *fe, u32 *status) mt2131_readreg(priv, 0x09, &afc_status); dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n", - __FUNCTION__, lock_status, afc_status); + __func__, lock_status, afc_status); return 0; } @@ -223,7 +223,7 @@ static int mt2131_init(struct dvb_frontend *fe) { struct mt2131_priv *priv = fe->tuner_priv; int ret; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if ((ret = mt2131_writeregs(priv, mt2131_config1, sizeof(mt2131_config1))) < 0) @@ -243,7 +243,7 @@ static int mt2131_init(struct dvb_frontend *fe) static int mt2131_release(struct dvb_frontend *fe) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; @@ -273,7 +273,7 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe, struct mt2131_priv *priv = NULL; u8 id = 0; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL); if (priv == NULL) diff --git a/drivers/media/dvb/frontends/mt2131.h b/drivers/media/dvb/frontends/mt2131.h index 1e4ffe7dc8c8..606d8576bc98 100644 --- a/drivers/media/dvb/frontends/mt2131.h +++ b/drivers/media/dvb/frontends/mt2131.h @@ -41,7 +41,7 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe, struct mt2131_config *cfg, u16 if1) { - 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_TUNER_MT2131 */ diff --git a/drivers/media/dvb/frontends/mt2266.h b/drivers/media/dvb/frontends/mt2266.h index f31dd613ad37..c5113efe333c 100644 --- a/drivers/media/dvb/frontends/mt2266.h +++ b/drivers/media/dvb/frontends/mt2266.h @@ -29,7 +29,7 @@ extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_a #else static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg) { - 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_TUNER_MT2266 diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index 1638301fbd6e..daca855c804a 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -76,7 +76,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { - printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret); + printk(KERN_ERR "%s: ret == %d\n", __func__, ret); return -EREMOTEIO; } @@ -117,7 +117,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) { - dprintk("%s: ret == %d\n", __FUNCTION__, ret); + dprintk("%s: ret == %d\n", __func__, ret); return -EREMOTEIO; } @@ -499,7 +499,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe, { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f }; const u8 inv_tab[3] = { 0x00, 0x40, 0x80 }; - dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency); + dprintk("%s: Freq %d\n", __func__, p->frequency); if ((p->frequency < fe->ops.info.frequency_min) || (p->frequency > fe->ops.info.frequency_max)) diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h index f17cb93ba9ba..afe24fd822bd 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb/frontends/mt312.h @@ -40,7 +40,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config, static inline struct dvb_frontend *vp310_mt312_attach( const struct mt312_config *config, struct i2c_adapter *i2c) { - 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_MT312 */ diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c index 7cd190b6f015..beba5aa0db50 100644 --- a/drivers/media/dvb/frontends/mt352.c +++ b/drivers/media/dvb/frontends/mt352.c @@ -95,7 +95,7 @@ static int mt352_read_register(struct mt352_state* state, u8 reg) if (ret != 2) { printk("%s: readreg error (reg=%d, ret==%i)\n", - __FUNCTION__, reg, ret); + __func__, reg, ret); return ret; } @@ -135,7 +135,7 @@ static void mt352_calc_nominal_rate(struct mt352_state* state, value = 64 * bw * (1<<16) / (7 * 8); value = value * 1000 / adc_clock; dprintk("%s: bw %d, adc_clock %d => 0x%x\n", - __FUNCTION__, bw, adc_clock, value); + __func__, bw, adc_clock, value); buf[0] = msb(value); buf[1] = lsb(value); } @@ -161,7 +161,7 @@ static void mt352_calc_input_freq(struct mt352_state* state, } value = -16374 * ife / adc_clock; dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n", - __FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff); + __func__, if2, ife, adc_clock, value, value & 0x3fff); buf[0] = msb(value); buf[1] = lsb(value); } @@ -521,7 +521,7 @@ static int mt352_init(struct dvb_frontend* fe) static u8 mt352_reset_attach [] = { RESET, 0xC0 }; - dprintk("%s: hello\n",__FUNCTION__); + dprintk("%s: hello\n",__func__); if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 || (mt352_read_register(state, CONFIG) & 0x20) == 0) { diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h index e9964081fd84..595092f9f0c4 100644 --- a/drivers/media/dvb/frontends/mt352.h +++ b/drivers/media/dvb/frontends/mt352.h @@ -58,7 +58,7 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config, static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config, struct i2c_adapter* i2c) { - 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_MT352 diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index fcf964fe1d6b..23d022852543 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -74,7 +74,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n", - __FUNCTION__, addr, err); + __func__, addr, err); return -EREMOTEIO; } return 0; @@ -87,7 +87,7 @@ static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len) if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n", - __FUNCTION__, addr, err); + __func__, addr, err); return -EREMOTEIO; } return 0; @@ -104,7 +104,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, err); + __func__, state->config->demod_address, err); return -EREMOTEIO; } return 0; @@ -121,7 +121,7 @@ static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 le if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) { printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, err); + __func__, state->config->demod_address, err); return -EREMOTEIO; } return 0; @@ -146,7 +146,7 @@ static u16 nxt200x_crc(u16 crc, u8 c) static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len) { u8 attr, len2, buf; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* set mutli register register */ nxt200x_writebytes(state, 0x35, ®, 1); @@ -207,7 +207,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d { int i; u8 buf, len2, attr; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* set mutli register register */ nxt200x_writebytes(state, 0x35, ®, 1); @@ -254,7 +254,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d static void nxt200x_microcontroller_stop (struct nxt200x_state* state) { u8 buf, stopval, counter = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* set correct stop value */ switch (state->demod_chip) { @@ -287,7 +287,7 @@ static void nxt200x_microcontroller_stop (struct nxt200x_state* state) static void nxt200x_microcontroller_start (struct nxt200x_state* state) { u8 buf; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); buf = 0x00; nxt200x_writebytes(state, 0x22, &buf, 1); @@ -297,7 +297,7 @@ static void nxt2004_microcontroller_init (struct nxt200x_state* state) { u8 buf[9]; u8 counter = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); buf[0] = 0x00; nxt200x_writebytes(state, 0x2b, buf, 1); @@ -328,7 +328,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data) { u8 buf, count = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]); @@ -387,7 +387,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data) static void nxt200x_agc_reset(struct nxt200x_state* state) { u8 buf; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); switch (state->demod_chip) { case NXT2002: @@ -416,7 +416,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware u8 buf[3], written = 0, chunkpos = 0; u16 rambase, position, crc = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); dprintk("Firmware is %zu bytes\n", fw->size); /* Get the RAM base for this nxt2002 */ @@ -483,7 +483,7 @@ static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware u8 buf[3]; u16 rambase, position, crc=0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); dprintk("Firmware is %zu bytes\n", fw->size); /* set rambase */ diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h index bb0ef58d7972..f3c84583770f 100644 --- a/drivers/media/dvb/frontends/nxt200x.h +++ b/drivers/media/dvb/frontends/nxt200x.h @@ -49,7 +49,7 @@ extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, struct i2c_adapter* i2c) { - 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_NXT200X diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h index 13d22518356e..878eb38a075e 100644 --- a/drivers/media/dvb/frontends/nxt6000.h +++ b/drivers/media/dvb/frontends/nxt6000.h @@ -40,7 +40,7 @@ extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, struct i2c_adapter* i2c) { - 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_NXT6000 diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index 8ffb8daca031..c7b5785f81f2 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c @@ -419,7 +419,7 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) *status = 0; return -EREMOTEIO; } - dprintk("%s: read_status %04x\n", __FUNCTION__, reg); + dprintk("%s: read_status %04x\n", __func__, reg); if (reg & 0x0100) /* Receiver Lock */ *status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI| @@ -504,14 +504,14 @@ start: if (retry--) goto start; return -EREMOTEIO; } - dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__, + dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__, reg&0xff, reg&0x1000?"n":"ff"); /* Calculate SNR using noise, c, and NTSC rejection correction */ state->snr = calculate_snr(noise, c) - usK; *snr = (state->snr) >> 16; - dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, + dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise, state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); return 0; diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h index add24f0a743b..1b8e04d973c8 100644 --- a/drivers/media/dvb/frontends/or51132.h +++ b/drivers/media/dvb/frontends/or51132.h @@ -41,7 +41,7 @@ extern struct dvb_frontend* or51132_attach(const struct or51132_config* config, static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config, struct i2c_adapter* i2c) { - 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_OR51132 diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 6a6b0d727c6f..7eaa4765593f 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c @@ -307,19 +307,19 @@ static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { printk(KERN_WARNING "%s: error writing snr reg\n", - __FUNCTION__); + __func__); return -1; } if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { printk(KERN_WARNING "%s: read_status read error\n", - __FUNCTION__); + __func__); return -1; } state->snr = calculate_snr(rec_buf[0], 89599047); *snr = (state->snr) >> 16; - dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0], + dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0], state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); return 0; diff --git a/drivers/media/dvb/frontends/or51211.h b/drivers/media/dvb/frontends/or51211.h index 8aad8402d615..3ce0508b898e 100644 --- a/drivers/media/dvb/frontends/or51211.h +++ b/drivers/media/dvb/frontends/or51211.h @@ -44,7 +44,7 @@ extern struct dvb_frontend* or51211_attach(const struct or51211_config* config, static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config, struct i2c_adapter* i2c) { - 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_OR51211 diff --git a/drivers/media/dvb/frontends/qt1010.h b/drivers/media/dvb/frontends/qt1010.h index 3ab4aa045c36..cff6a7ca5380 100644 --- a/drivers/media/dvb/frontends/qt1010.h +++ b/drivers/media/dvb/frontends/qt1010.h @@ -45,7 +45,7 @@ static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct qt1010_config *cfg) { - 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_TUNER_QT1010 diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 1ca250378664..b999ec424ff7 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -312,7 +312,7 @@ static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data) if (ret != 1) printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, " - "ret == %i)\n", __FUNCTION__, reg, data, ret); + "ret == %i)\n", __func__, reg, data, ret); return (ret != 1) ? -1 : 0; } @@ -332,7 +332,7 @@ static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg) ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) - printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + printk("%s: readreg error (ret == %i)\n", __func__, ret); return (b1[0] << 8) | b1[1]; } @@ -340,7 +340,7 @@ static int s5h1409_softreset(struct dvb_frontend* fe) { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); s5h1409_writereg(state, 0xf5, 0); s5h1409_writereg(state, 0xf5, 1); @@ -356,7 +356,7 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz) { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s(%d KHz)\n", __FUNCTION__, KHz); + dprintk("%s(%d KHz)\n", __func__, KHz); switch (KHz) { case 4000: @@ -381,7 +381,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted) { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s(%d)\n", __FUNCTION__, inverted); + dprintk("%s(%d)\n", __func__, inverted); if(inverted == 1) return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */ @@ -394,25 +394,25 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe, { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s(0x%08x)\n", __FUNCTION__, m); + dprintk("%s(0x%08x)\n", __func__, m); switch(m) { case VSB_8: - dprintk("%s() VSB_8\n", __FUNCTION__); + dprintk("%s() VSB_8\n", __func__); if (state->if_freq != S5H1409_VSB_IF_FREQ) s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ); s5h1409_writereg(state, 0xf4, 0); break; case QAM_64: case QAM_256: - dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__); + dprintk("%s() QAM_AUTO (64/256)\n", __func__); if (state->if_freq != S5H1409_QAM_IF_FREQ) s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ); s5h1409_writereg(state, 0xf4, 1); s5h1409_writereg(state, 0x85, 0x110); break; default: - dprintk("%s() Invalid modulation\n", __FUNCTION__); + dprintk("%s() Invalid modulation\n", __func__); return -EINVAL; } @@ -426,7 +426,7 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s(%d)\n", __FUNCTION__, enable); + dprintk("%s(%d)\n", __func__, enable); if (enable) return s5h1409_writereg(state, 0xf3, 1); @@ -438,7 +438,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable) { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s(%d)\n", __FUNCTION__, enable); + dprintk("%s(%d)\n", __func__, enable); if (enable) return s5h1409_writereg(state, 0xe3, @@ -452,7 +452,7 @@ static int s5h1409_sleep(struct dvb_frontend* fe, int enable) { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s(%d)\n", __FUNCTION__, enable); + dprintk("%s(%d)\n", __func__, enable); return s5h1409_writereg(state, 0xf2, enable); } @@ -461,7 +461,7 @@ static int s5h1409_register_reset(struct dvb_frontend* fe) { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); return s5h1409_writereg(state, 0xfa, 0); } @@ -534,7 +534,7 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe, { struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency); + dprintk("%s(frequency=%d)\n", __func__, p->frequency); s5h1409_softreset(fe); @@ -565,7 +565,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode) struct s5h1409_state *state = fe->demodulator_priv; u16 val; - dprintk("%s(%d)\n", __FUNCTION__, mode); + dprintk("%s(%d)\n", __func__, mode); val = s5h1409_readreg(state, 0xac) & 0xcfff; switch (mode) { @@ -573,7 +573,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode) val |= 0x0000; break; case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK: - dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode); + dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode); val |= 0x1000; break; case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK: @@ -597,7 +597,7 @@ static int s5h1409_init (struct dvb_frontend* fe) int i; struct s5h1409_state* state = fe->demodulator_priv; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); s5h1409_sleep(fe, 0); s5h1409_register_reset(fe); @@ -663,7 +663,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status) break; } - dprintk("%s() status 0x%08x\n", __FUNCTION__, *status); + dprintk("%s() status 0x%08x\n", __func__, *status); return 0; } @@ -671,7 +671,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status) static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) { int i, ret = -EINVAL; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) { if (v < qam256_snr_tab[i].val) { @@ -686,7 +686,7 @@ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) { int i, ret = -EINVAL; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) { if (v < qam64_snr_tab[i].val) { @@ -701,7 +701,7 @@ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) { int i, ret = -EINVAL; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) { if (v > vsb_snr_tab[i].val) { @@ -710,7 +710,7 @@ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v) break; } } - dprintk("%s() snr=%d\n", __FUNCTION__, *snr); + dprintk("%s() snr=%d\n", __func__, *snr); return ret; } @@ -718,7 +718,7 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr) { struct s5h1409_state* state = fe->demodulator_priv; u16 reg; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); switch(state->current_modulation) { case QAM_64: @@ -812,7 +812,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, if (s5h1409_init(&state->frontend) != 0) { printk(KERN_ERR "%s: Failed to initialize correctly\n", - __FUNCTION__); + __func__); goto error; } diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h index f0bb13fe808b..59f4335964c6 100644 --- a/drivers/media/dvb/frontends/s5h1409.h +++ b/drivers/media/dvb/frontends/s5h1409.h @@ -67,7 +67,7 @@ extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, struct i2c_adapter* i2c) { - 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_S5H1409 */ diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 7c64af91e5ac..1e2d602d371a 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -63,7 +63,7 @@ static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data) int err; if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); + dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data); return -EREMOTEIO; } diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h index 1555870f7226..2cc785012b23 100644 --- a/drivers/media/dvb/frontends/s5h1420.h +++ b/drivers/media/dvb/frontends/s5h1420.h @@ -41,7 +41,7 @@ extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c) { - 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_S5H1420 diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c index f5b3bfc00436..aa78aa14aad9 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb/frontends/sp8870.c @@ -70,7 +70,7 @@ static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data) int err; if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); + dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data); return -EREMOTEIO; } @@ -88,7 +88,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg) ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) { - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + dprintk("%s: readreg error (ret == %i)\n", __func__, ret); return -1; } @@ -104,7 +104,7 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm int tx_len; int err = 0; - dprintk ("%s: ...\n", __FUNCTION__); + dprintk ("%s: ...\n", __func__); if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET) return -EINVAL; @@ -131,14 +131,14 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm msg.buf = tx_buf; msg.len = tx_len + 2; if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - printk("%s: firmware upload failed!\n", __FUNCTION__); - printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err); + printk("%s: firmware upload failed!\n", __func__); + printk ("%s: i2c error (err == %i)\n", __func__, err); return err; } fw_pos += tx_len; } - dprintk ("%s: done!\n", __FUNCTION__); + dprintk ("%s: done!\n", __func__); return 0; }; @@ -310,7 +310,7 @@ static int sp8870_init (struct dvb_frontend* fe) if (state->initialised) return 0; state->initialised = 1; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); /* request the firmware, this will block until someone uploads it */ @@ -475,7 +475,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par int trials = 0; int check_count = 0; - dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency); + dprintk("%s: frequency = %i\n", __func__, p->frequency); for (trials = 1; trials <= MAXTRIALS; trials++) { @@ -487,7 +487,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par valid = sp8870_read_data_valid_signal(state); if (valid) { dprintk("%s: delay = %i usec\n", - __FUNCTION__, check_count * 10); + __func__, check_count * 10); break; } udelay(10); @@ -497,20 +497,20 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par } if (!valid) { - printk("%s: firmware crash!!!!!!\n", __FUNCTION__); + printk("%s: firmware crash!!!!!!\n", __func__); return -EIO; } if (debug) { if (valid) { if (trials > 1) { - printk("%s: firmware lockup!!!\n", __FUNCTION__); - printk("%s: recovered after %i trial(s))\n", __FUNCTION__, trials - 1); + printk("%s: firmware lockup!!!\n", __func__); + printk("%s: recovered after %i trial(s))\n", __func__, trials - 1); lockups++; } } switches++; - printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups); + printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups); } return 0; diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb/frontends/sp8870.h index 909cefe7139e..a764a793c7d8 100644 --- a/drivers/media/dvb/frontends/sp8870.h +++ b/drivers/media/dvb/frontends/sp8870.h @@ -42,7 +42,7 @@ extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config, static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config, struct i2c_adapter* i2c) { - 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_SP8870 diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c index 1aa2539f5099..49f55877f513 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb/frontends/sp887x.c @@ -43,7 +43,7 @@ static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len) if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { printk ("%s: i2c write error (addr %02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, err); + __func__, state->config->demod_address, err); return -EREMOTEIO; } @@ -65,7 +65,7 @@ static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data) { printk("%s: writereg error " "(reg %03x, data %03x, ret == %i)\n", - __FUNCTION__, reg & 0xffff, data & 0xffff, ret); + __func__, reg & 0xffff, data & 0xffff, ret); return ret; } } @@ -82,7 +82,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg) { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }}; if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) { - printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + printk("%s: readreg error (ret == %i)\n", __func__, ret); return -1; } @@ -91,7 +91,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg) static void sp887x_microcontroller_stop (struct sp887x_state* state) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); sp887x_writereg(state, 0xf08, 0x000); sp887x_writereg(state, 0xf09, 0x000); @@ -101,7 +101,7 @@ static void sp887x_microcontroller_stop (struct sp887x_state* state) static void sp887x_microcontroller_start (struct sp887x_state* state) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); sp887x_writereg(state, 0xf08, 0x000); sp887x_writereg(state, 0xf09, 0x000); @@ -112,7 +112,7 @@ static void sp887x_microcontroller_start (struct sp887x_state* state) static void sp887x_setup_agc (struct sp887x_state* state) { /* setup AGC parameters */ - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); sp887x_writereg(state, 0x33c, 0x054); sp887x_writereg(state, 0x33b, 0x04c); sp887x_writereg(state, 0x328, 0x000); @@ -142,7 +142,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware int fw_size = fw->size; unsigned char *mem = fw->data; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */ if (fw_size < FW_SIZE+10) @@ -155,7 +155,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware sp887x_microcontroller_stop (state); - printk ("%s: firmware upload... ", __FUNCTION__); + printk ("%s: firmware upload... ", __func__); /* setup write pointer to -1 (end of memory) */ /* bit 0x8000 in address is set to enable 13bit mode */ @@ -181,7 +181,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware if ((err = i2c_writebytes (state, buf, c+2)) < 0) { printk ("failed.\n"); - printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err); + printk ("%s: i2c error (err == %i)\n", __func__, err); return err; } } diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb/frontends/sp887x.h index 7ee78d7d916d..04eff6e0eef3 100644 --- a/drivers/media/dvb/frontends/sp887x.h +++ b/drivers/media/dvb/frontends/sp887x.h @@ -24,7 +24,7 @@ extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, struct i2c_adapter* i2c) { - 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_SP887X diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index 7c23775f77db..62caf802ed99 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c @@ -58,7 +58,7 @@ static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data) if (ret != 1) dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " - "ret == %i)\n", __FUNCTION__, reg, data, ret); + "ret == %i)\n", __func__, reg, data, ret); return (ret != 1) ? -1 : 0; } @@ -75,16 +75,16 @@ static int stv0297_readreg(struct stv0297_state *state, u8 reg) // this device needs a STOP between the register and data if (state->config->stop_during_read) { if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret); return -1; } if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret); return -1; } } else { if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret); return -1; } } @@ -115,16 +115,16 @@ static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len // this device needs a STOP between the register and data if (state->config->stop_during_read) { if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret); return -1; } if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret); return -1; } } else { if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret); return -1; } } diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h index 69f4515df2b9..3f8f9468f387 100644 --- a/drivers/media/dvb/frontends/stv0297.h +++ b/drivers/media/dvb/frontends/stv0297.h @@ -49,7 +49,7 @@ extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, struct i2c_adapter* i2c) { - 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_STV0297 diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 035dd7ba6519..f7c36741537d 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -86,7 +86,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data) if (ret != 1) dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " - "ret == %i)\n", __FUNCTION__, reg, data, ret); + "ret == %i)\n", __func__, reg, data, ret); return (ret != 1) ? -EREMOTEIO : 0; } @@ -113,7 +113,7 @@ static u8 stv0299_readreg (struct stv0299_state* state, u8 reg) if (ret != 2) dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", - __FUNCTION__, reg, ret); + __func__, reg, ret); return b1[0]; } @@ -127,14 +127,14 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + dprintk("%s: readreg error (ret == %i)\n", __func__, ret); return ret == 2 ? 0 : ret; } static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec) { - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); switch (fec) { case FEC_AUTO: @@ -174,7 +174,7 @@ static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state) FEC_7_8, FEC_1_2 }; u8 index; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); index = stv0299_readreg (state, 0x1b); index &= 0x7; @@ -189,11 +189,11 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout) { unsigned long start = jiffies; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); while (stv0299_readreg(state, 0x0a) & 1) { if (jiffies - start > timeout) { - dprintk ("%s: timeout!!\n", __FUNCTION__); + dprintk ("%s: timeout!!\n", __func__); return -ETIMEDOUT; } msleep(10); @@ -206,11 +206,11 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout) { unsigned long start = jiffies; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) { if (jiffies - start > timeout) { - dprintk ("%s: timeout!!\n", __FUNCTION__); + dprintk ("%s: timeout!!\n", __func__); return -ETIMEDOUT; } msleep(10); @@ -245,7 +245,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state) u8 sfr[3]; s8 rtf; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); stv0299_readregs (state, 0x1f, sfr, 3); stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1); @@ -257,8 +257,8 @@ static int stv0299_get_symbolrate (struct stv0299_state* state) offset = (s32) rtf * (srate / 4096L); offset /= 128; - dprintk ("%s : srate = %i\n", __FUNCTION__, srate); - dprintk ("%s : ofset = %i\n", __FUNCTION__, offset); + dprintk ("%s : srate = %i\n", __func__, srate); + dprintk ("%s : ofset = %i\n", __func__, offset); srate += offset; @@ -276,7 +276,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe, u8 val; int i; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; @@ -305,7 +305,7 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t struct stv0299_state* state = fe->demodulator_priv; u8 val; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; @@ -355,7 +355,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag u8 reg0x08; u8 reg0x0c; - dprintk("%s: %s\n", __FUNCTION__, + dprintk("%s: %s\n", __func__, voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); @@ -408,7 +408,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd = cmd << 1; if (debug_legacy_dish_switch) - printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd); + printk ("%s switch command: 0x%04lx\n",__func__, cmd); do_gettimeofday (&nexttime); if (debug_legacy_dish_switch) @@ -433,7 +433,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long } if (debug_legacy_dish_switch) { printk ("%s(%d): switch delay (should be 32k followed by all 8k\n", - __FUNCTION__, fe->dvb->num); + __func__, fe->dvb->num); for (i = 1; i < 10; i++) printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); } @@ -461,7 +461,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status) u8 signal = 0xff - stv0299_readreg (state, 0x18); u8 sync = stv0299_readreg (state, 0x1b); - dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync); + dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync); *status = 0; if (signal > 10) @@ -499,7 +499,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength) s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8) | stv0299_readreg (state, 0x19)); - dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__, + dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__, stv0299_readreg (state, 0x18), stv0299_readreg (state, 0x19), (int) signal); @@ -536,7 +536,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par struct stv0299_state* state = fe->demodulator_priv; int invval = 0; - dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__); + dprintk ("%s : FE_SET_FRONTEND\n", __func__); // set the inversion if (p->inversion == INVERSION_OFF) invval = 0; diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index 33df9495908f..84eaeb518540 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h @@ -96,7 +96,7 @@ extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, struct i2c_adapter* i2c) { - 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_STV0299 diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 45137d2ebfb9..f648fdb64bb7 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -79,7 +79,7 @@ static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data) if (ret != 1) printk("DVB: TDA10021(%d): %s, writereg error " "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", - state->frontend.dvb->num, __FUNCTION__, reg, data, ret); + state->frontend.dvb->num, __func__, reg, data, ret); msleep(10); return (ret != 1) ? -EREMOTEIO : 0; @@ -97,7 +97,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg) // Don't print an error message if the id is read. if (ret != 2 && reg != 0x1a) printk("DVB: TDA10021: %s: readreg error (ret == %i)\n", - __FUNCTION__, ret); + __func__, ret); return b1[0]; } diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c index 364bc01971a0..0727b80bc4d2 100644 --- a/drivers/media/dvb/frontends/tda10023.c +++ b/drivers/media/dvb/frontends/tda10023.c @@ -118,7 +118,7 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg) ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) printk("DVB: TDA10023: %s: readreg error (ret == %i)\n", - __FUNCTION__, ret); + __func__, ret); return b1[0]; } @@ -132,7 +132,7 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data) if (ret != 1) printk("DVB: TDA10023(%d): %s, writereg error " "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", - state->frontend.dvb->num, __FUNCTION__, reg, data, ret); + state->frontend.dvb->num, __func__, reg, data, ret); return (ret != 1) ? -EREMOTEIO : 0; } diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb/frontends/tda1002x.h index e9094d8123f6..1bcc0d44b90b 100644 --- a/drivers/media/dvb/frontends/tda1002x.h +++ b/drivers/media/dvb/frontends/tda1002x.h @@ -40,7 +40,7 @@ extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, struct i2c_adapter* i2c, u8 pwm) { - 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_TDA10021 @@ -52,7 +52,7 @@ extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, struct i2c_adapter* i2c, u8 pwm) { - 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_TDA10023 diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 8415a8a5247a..49973846373e 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -131,16 +131,16 @@ static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data) u8 buf[] = { reg, data }; struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; - dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data); + dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data); msg.addr = state->config->demod_address; ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", - __FUNCTION__, reg, data, ret); + __func__, reg, data, ret); - dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__, + dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__, reg, data, ret); return (ret != 1) ? -1 : 0; } @@ -153,19 +153,19 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg) struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 }, { .flags = I2C_M_RD, .buf = b1, .len = 1 }}; - dprintk("%s: reg=0x%x\n", __FUNCTION__, reg); + dprintk("%s: reg=0x%x\n", __func__, reg); msg[0].addr = state->config->demod_address; msg[1].addr = state->config->demod_address; ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { - dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg, + dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret); return -1; } - dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__, + dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__, reg, b1[0], ret); return b1[0]; } @@ -173,7 +173,7 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg) static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data) { int val; - dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg, + dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg, mask, data); // read a byte and check @@ -194,7 +194,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch int i; int result; - dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len); + dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len); result = 0; for (i = 0; i < len; i++) { @@ -209,7 +209,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state) { int result; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2); msleep(20); @@ -218,7 +218,7 @@ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state) static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0); } @@ -345,7 +345,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state, } pos += tx_size; - dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos); + dprintk("%s: fw_pos=0x%x\n", __func__, pos); } // give the DSP a chance to settle 03/10/05 Hac msleep(100); @@ -444,10 +444,10 @@ static void tda10046_init_plls(struct dvb_frontend* fe) tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3 } if (state->config->xtal_freq == TDA10046_XTAL_4M ) { - dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__); + dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__); tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 } else { - dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__); + dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__); tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3 } if(tda10046_clk53m) @@ -488,7 +488,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe) if (state->config->xtal_freq == TDA10046_XTAL_4M) { tda1004x_write_byteI(state, TDA1004X_CONFC4, 0); } else { - dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__); + dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__); tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80); } tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); @@ -594,7 +594,7 @@ static int tda10045_init(struct dvb_frontend* fe) { struct tda1004x_state* state = fe->demodulator_priv; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (tda10045_fwupload(fe)) { printk("tda1004x: firmware upload failed\n"); @@ -624,7 +624,7 @@ static int tda10045_init(struct dvb_frontend* fe) static int tda10046_init(struct dvb_frontend* fe) { struct tda1004x_state* state = fe->demodulator_priv; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (tda10046_fwupload(fe)) { printk("tda1004x: firmware upload failed\n"); @@ -686,7 +686,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, int tmp; int inversion; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (state->demod_type == TDA1004X_DEMOD_TDA10046) { // setup auto offset @@ -881,7 +881,7 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete { struct tda1004x_state* state = fe->demodulator_priv; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); // inversion status fe_params->inversion = INVERSION_OFF; @@ -989,7 +989,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status int cber; int vber; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); // read status status = tda1004x_read_byte(state, TDA1004X_STATUS_CD); @@ -1048,7 +1048,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status } // success - dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status); + dprintk("%s: fe_status=0x%x\n", __func__, *fe_status); return 0; } @@ -1058,7 +1058,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal) int tmp; int reg = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); // determine the register to use switch (state->demod_type) { @@ -1077,7 +1077,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal) return -EIO; *signal = (tmp << 8) | tmp; - dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal); + dprintk("%s: signal=0x%x\n", __func__, *signal); return 0; } @@ -1086,7 +1086,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr) struct tda1004x_state* state = fe->demodulator_priv; int tmp; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); // read it tmp = tda1004x_read_byte(state, TDA1004X_SNR); @@ -1095,7 +1095,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr) tmp = 255 - tmp; *snr = ((tmp << 8) | tmp); - dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr); + dprintk("%s: snr=0x%x\n", __func__, *snr); return 0; } @@ -1106,7 +1106,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) int tmp2; int counter; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); // read the UCBLOCKS and reset counter = 0; @@ -1132,7 +1132,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) else *ucblocks = 0xffffffff; - dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks); + dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks); return 0; } @@ -1141,7 +1141,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) struct tda1004x_state* state = fe->demodulator_priv; int tmp; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); // read it in tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB); @@ -1155,7 +1155,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) // The address 0x20 should be read to cope with a TDA10046 bug tda1004x_read_byte(state, TDA1004X_CBER_RESET); - dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); + dprintk("%s: ber=0x%x\n", __func__, *ber); return 0; } diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index ebb2c5f5a261..4e27ffb0f14e 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -127,13 +127,13 @@ extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, struct i2c_adapter* i2c) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, struct i2c_adapter* i2c) { - 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_TDA1004X diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 143af96439b9..5fc26757f393 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -60,7 +60,7 @@ static int tda10086_write_byte(struct tda10086_state *state, int reg, int data) if (ret != 1) dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", - __FUNCTION__, reg, data, ret); + __func__, reg, data, ret); return (ret != 1) ? ret : 0; } @@ -78,7 +78,7 @@ static int tda10086_read_byte(struct tda10086_state *state, int reg) ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { - dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg, + dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret); return ret; } @@ -108,7 +108,7 @@ static int tda10086_init(struct dvb_frontend* fe) struct tda10086_state* state = fe->demodulator_priv; u8 t22k_off = 0x80; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (state->config->diseqc_tone) t22k_off = 0; @@ -173,7 +173,7 @@ static void tda10086_diseqc_wait(struct tda10086_state *state) unsigned long timeout = jiffies + msecs_to_jiffies(200); while (!(tda10086_read_byte(state, 0x50) & 0x01)) { if(time_after(jiffies, timeout)) { - printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__); + printk("%s: diseqc queue not ready, command may be lost.\n", __func__); break; } msleep(10); @@ -185,7 +185,7 @@ static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) struct tda10086_state* state = fe->demodulator_priv; u8 t22k_off = 0x80; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (state->config->diseqc_tone) t22k_off = 0; @@ -211,7 +211,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe, u8 oldval; u8 t22k_off = 0x80; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (state->config->diseqc_tone) t22k_off = 0; @@ -239,7 +239,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic u8 oldval = tda10086_read_byte(state, 0x36); u8 t22k_off = 0x80; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (state->config->diseqc_tone) t22k_off = 0; @@ -266,7 +266,7 @@ static int tda10086_set_inversion(struct tda10086_state *state, { u8 invval = 0x80; - dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert); + dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert); switch(fe_params->inversion) { case INVERSION_OFF: @@ -300,7 +300,7 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state, u32 bdri; u32 symbol_rate = fe_params->u.qpsk.symbol_rate; - dprintk ("%s %i\n", __FUNCTION__, symbol_rate); + dprintk ("%s %i\n", __func__, symbol_rate); // setup the decimation and anti-aliasing filters.. if (symbol_rate < (u32) (SACLK * 0.0137)) { @@ -366,7 +366,7 @@ static int tda10086_set_fec(struct tda10086_state *state, { u8 fecval; - dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner); + dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner); switch(fe_params->u.qpsk.fec_inner) { case FEC_1_2: @@ -412,7 +412,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe, u32 freq = 0; int freqoff; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); // modify parameters for tuning tda10086_write_byte(state, 0x02, 0x35); @@ -459,7 +459,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa int tmp; u64 tmp64; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); // check for invalid symbol rate if (fe_params->u.qpsk.symbol_rate < 500000) @@ -550,7 +550,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status) struct tda10086_state* state = fe->demodulator_priv; u8 val; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); val = tda10086_read_byte(state, 0x0e); *fe_status = 0; @@ -579,7 +579,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal) struct tda10086_state* state = fe->demodulator_priv; u8 _str; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); _str = 0xff - tda10086_read_byte(state, 0x43); *signal = (_str << 8) | _str; @@ -592,7 +592,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr) struct tda10086_state* state = fe->demodulator_priv; u8 _snr; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); _snr = 0xff - tda10086_read_byte(state, 0x1c); *snr = (_snr << 8) | _snr; @@ -604,7 +604,7 @@ static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { struct tda10086_state* state = fe->demodulator_priv; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); // read it *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f; @@ -620,7 +620,7 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber) { struct tda10086_state* state = fe->demodulator_priv; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); // read it *ber = 0; @@ -635,7 +635,7 @@ static int tda10086_sleep(struct dvb_frontend* fe) { struct tda10086_state* state = fe->demodulator_priv; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); tda10086_write_mask(state, 0x00, 0x08, 0x08); @@ -646,7 +646,7 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) { struct tda10086_state* state = fe->demodulator_priv; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); if (enable) { tda10086_write_mask(state, 0x00, 0x10, 0x10); @@ -737,7 +737,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, { struct tda10086_state *state; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __func__); /* allocate memory for the internal state */ state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL); diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h index eeceaeee78ff..197c237e515f 100644 --- a/drivers/media/dvb/frontends/tda10086.h +++ b/drivers/media/dvb/frontends/tda10086.h @@ -45,7 +45,7 @@ extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, struct i2c_adapter* i2c) { - 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_TDA10086 diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index 4b153bc557fe..2bc5eb368ea2 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -139,7 +139,7 @@ extern int tda18271_debug; #define DBG_CAL 16 #define tda_printk(kern, fmt, arg...) \ - printk(kern "%s: " fmt, __FUNCTION__, ##arg) + printk(kern "%s: " fmt, __func__, ##arg) #define dprintk(kern, lvl, fmt, arg...) do {\ if (tda18271_debug & lvl) \ diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index b547318c951b..0e7af8d05a38 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -91,7 +91,7 @@ static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct tda18271_config *cfg) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c index 011b74f798a0..5b843b2e67e8 100644 --- a/drivers/media/dvb/frontends/tda8083.c +++ b/drivers/media/dvb/frontends/tda8083.c @@ -68,7 +68,7 @@ static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data) if (ret != 1) dprintk ("%s: writereg error (reg %02x, ret == %i)\n", - __FUNCTION__, reg, ret); + __func__, reg, ret); return (ret != 1) ? -1 : 0; } @@ -83,7 +83,7 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len if (ret != 2) dprintk ("%s: readreg error (reg %02x, ret == %i)\n", - __FUNCTION__, reg1, ret); + __func__, reg1, ret); return ret == 2 ? 0 : -1; } diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb/frontends/tda8083.h index 2d3307999f21..5a03c14a10e8 100644 --- a/drivers/media/dvb/frontends/tda8083.h +++ b/drivers/media/dvb/frontends/tda8083.h @@ -42,7 +42,7 @@ extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, struct i2c_adapter* i2c) { - 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_TDA8083 diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index 9a91eb0333d9..5a15bb4263fb 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -54,7 +54,7 @@ static int tda826x_sleep(struct dvb_frontend *fe) u8 buf [] = { 0x00, 0x8d }; struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 }; - dprintk("%s:\n", __FUNCTION__); + dprintk("%s:\n", __func__); if (!priv->has_loopthrough) buf[1] = 0xad; @@ -62,7 +62,7 @@ static int tda826x_sleep(struct dvb_frontend *fe) if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) { - dprintk("%s: i2c error\n", __FUNCTION__); + dprintk("%s: i2c error\n", __func__); } if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); @@ -78,7 +78,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param u8 buf [11]; struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 }; - dprintk("%s:\n", __FUNCTION__); + dprintk("%s:\n", __func__); div = (params->frequency + (1000-1)) / 1000; @@ -99,7 +99,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) { - dprintk("%s: i2c error\n", __FUNCTION__); + dprintk("%s: i2c error\n", __func__); } if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); @@ -138,7 +138,7 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2 }; int ret; - dprintk("%s:\n", __FUNCTION__); + dprintk("%s:\n", __func__); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb/frontends/tda826x.h index ad9981195961..89e97926ab23 100644 --- a/drivers/media/dvb/frontends/tda826x.h +++ b/drivers/media/dvb/frontends/tda826x.h @@ -45,7 +45,7 @@ static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, int has_loopthrough) { - 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_TDA826X diff --git a/drivers/media/dvb/frontends/tda827x.h b/drivers/media/dvb/frontends/tda827x.h index cd3032f985cd..b73c23570dab 100644 --- a/drivers/media/dvb/frontends/tda827x.h +++ b/drivers/media/dvb/frontends/tda827x.h @@ -61,7 +61,7 @@ static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct tda827x_config *cfg) { - 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_TDA827X diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c index 6ba0029dcf2e..1790baee014c 100644 --- a/drivers/media/dvb/frontends/tua6100.c +++ b/drivers/media/dvb/frontends/tua6100.c @@ -58,7 +58,7 @@ static int tua6100_sleep(struct dvb_frontend *fe) if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) { - printk("%s: i2c error\n", __FUNCTION__); + printk("%s: i2c error\n", __func__); } if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); diff --git a/drivers/media/dvb/frontends/tua6100.h b/drivers/media/dvb/frontends/tua6100.h index 03a665e7df6d..f83dbd5e42ae 100644 --- a/drivers/media/dvb/frontends/tua6100.h +++ b/drivers/media/dvb/frontends/tua6100.h @@ -39,7 +39,7 @@ extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, st #else static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c) { - 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_TUA6100 diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c index 8791701c8f25..a184597f1d9b 100644 --- a/drivers/media/dvb/frontends/ves1820.c +++ b/drivers/media/dvb/frontends/ves1820.c @@ -66,7 +66,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data) if (ret != 1) printk("ves1820: %s(): writereg error (reg == 0x%02x, " - "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret); + "val == 0x%02x, ret == %i)\n", __func__, reg, data, ret); return (ret != 1) ? -EREMOTEIO : 0; } @@ -85,7 +85,7 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg) if (ret != 2) printk("ves1820: %s(): readreg error (reg == 0x%02x, " - "ret == %i)\n", __FUNCTION__, reg, ret); + "ret == %i)\n", __func__, reg, ret); return b1[0]; } diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h index e4a2a324046a..e902ed634ec3 100644 --- a/drivers/media/dvb/frontends/ves1820.h +++ b/drivers/media/dvb/frontends/ves1820.h @@ -48,7 +48,7 @@ extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, struct i2c_adapter* i2c, u8 pwm) { - 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_VES1820 diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c index c041c81f9686..bd558960bd87 100644 --- a/drivers/media/dvb/frontends/ves1x93.c +++ b/drivers/media/dvb/frontends/ves1x93.c @@ -98,7 +98,7 @@ static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data) int err; if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); + dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data); return -EREMOTEIO; } @@ -179,7 +179,7 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate) u32 tmp; u32 FIN; - dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate); + dprintk("%s: srate == %d\n", __func__, (unsigned int) srate); if (srate > state->config->xin/2) srate = state->config->xin/2; @@ -266,7 +266,7 @@ static int ves1x93_init (struct dvb_frontend* fe) int i; int val; - dprintk("%s: init chip\n", __FUNCTION__); + dprintk("%s: init chip\n", __func__); for (i = 0; i < state->tab_size; i++) { if (state->init_1x93_wtab[i]) { diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb/frontends/ves1x93.h index d507f8966f81..8a5a49e808f6 100644 --- a/drivers/media/dvb/frontends/ves1x93.h +++ b/drivers/media/dvb/frontends/ves1x93.h @@ -47,7 +47,7 @@ extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, struct i2c_adapter* i2c) { - 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_VES1X93 diff --git a/drivers/media/dvb/frontends/xc5000.c b/drivers/media/dvb/frontends/xc5000.c index a5094b7f21fd..43d35bdb221f 100644 --- a/drivers/media/dvb/frontends/xc5000.c +++ b/drivers/media/dvb/frontends/xc5000.c @@ -209,7 +209,7 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) struct xc5000_priv *priv = fe->tuner_priv; int ret; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (priv->cfg->tuner_callback) { ret = priv->cfg->tuner_callback(priv->cfg->priv, @@ -330,7 +330,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[]) static int xc_initialize(struct xc5000_priv *priv) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); return xc_write_reg(priv, XREG_INIT, 0); } @@ -338,9 +338,9 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, u16 VideoMode, u16 AudioMode) { int ret; - dprintk(1, "%s(0x%04x,0x%04x)\n", __FUNCTION__, VideoMode, AudioMode); + dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode); dprintk(1, "%s() Standard = %s\n", - __FUNCTION__, + __func__, XC5000_Standard[priv->video_standard].Name); ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode); @@ -361,7 +361,7 @@ static int xc_shutdown(struct xc5000_priv *priv) static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) { - dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, rf_mode, + dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE"); if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) @@ -369,7 +369,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) rf_mode = XC_RF_MODE_CABLE; printk(KERN_ERR "%s(), Invalid mode, defaulting to CABLE", - __FUNCTION__); + __func__); } return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode); } @@ -380,7 +380,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) { u16 freq_code; - dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz); + dprintk(1, "%s(%u)\n", __func__, freq_hz); if ((freq_hz > xc5000_tuner_ops.info.frequency_max) || (freq_hz < xc5000_tuner_ops.info.frequency_min)) @@ -396,7 +396,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz) { u32 freq_code = (freq_khz * 1024)/1000; dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n", - __FUNCTION__, freq_khz, freq_code); + __func__, freq_khz, freq_code); return xc_write_reg(priv, XREG_IF_OUT, freq_code); } @@ -488,7 +488,7 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) { int found = 0; - dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz); + dprintk(1, "%s(%u)\n", __func__, freq_hz); if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) return 0; @@ -627,12 +627,12 @@ static int xc5000_set_params(struct dvb_frontend *fe, struct xc5000_priv *priv = fe->tuner_priv; int ret; - dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency); + dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); switch(params->u.vsb.modulation) { case VSB_8: case VSB_16: - dprintk(1, "%s() VSB modulation\n", __FUNCTION__); + dprintk(1, "%s() VSB modulation\n", __func__); priv->rf_mode = XC_RF_MODE_AIR; priv->freq_hz = params->frequency - 1750000; priv->bandwidth = BANDWIDTH_6_MHZ; @@ -641,7 +641,7 @@ static int xc5000_set_params(struct dvb_frontend *fe, case QAM_64: case QAM_256: case QAM_AUTO: - dprintk(1, "%s() QAM modulation\n", __FUNCTION__); + dprintk(1, "%s() QAM modulation\n", __func__); priv->rf_mode = XC_RF_MODE_CABLE; priv->freq_hz = params->frequency - 1750000; priv->bandwidth = BANDWIDTH_6_MHZ; @@ -652,7 +652,7 @@ static int xc5000_set_params(struct dvb_frontend *fe, } dprintk(1, "%s() frequency=%d (compensated)\n", - __FUNCTION__, priv->freq_hz); + __func__, priv->freq_hz); ret = xc_SetSignalSource(priv, priv->rf_mode); if (ret != XC_RESULT_SUCCESS) { @@ -697,7 +697,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, xc_load_fw_and_init_tuner(fe); dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", - __FUNCTION__, params->frequency); + __func__, params->frequency); priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */ @@ -775,7 +775,7 @@ tune_channel: static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) { struct xc5000_priv *priv = fe->tuner_priv; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); *freq = priv->freq_hz; return 0; } @@ -783,7 +783,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw) { struct xc5000_priv *priv = fe->tuner_priv; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); *bw = priv->bandwidth; return 0; @@ -796,7 +796,7 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status) xc_get_lock_status(priv, &lock_status); - dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status); + dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status); *status = lock_status; @@ -836,7 +836,7 @@ static int xc5000_sleep(struct dvb_frontend *fe) struct xc5000_priv *priv = fe->tuner_priv; int ret; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized * once shutdown without reloading the driver. Maybe I am not @@ -848,7 +848,7 @@ static int xc5000_sleep(struct dvb_frontend *fe) if(ret != XC_RESULT_SUCCESS) { printk(KERN_ERR "xc5000: %s() unable to shutdown tuner\n", - __FUNCTION__); + __func__); return -EREMOTEIO; } else { @@ -860,7 +860,7 @@ static int xc5000_sleep(struct dvb_frontend *fe) static int xc5000_init(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { printk(KERN_ERR "xc5000: Unable to initialise tuner\n"); @@ -875,7 +875,7 @@ static int xc5000_init(struct dvb_frontend *fe) static int xc5000_release(struct dvb_frontend *fe) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; @@ -907,7 +907,7 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe, struct xc5000_priv *priv = NULL; u16 id = 0; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL); if (priv == NULL) diff --git a/drivers/media/dvb/frontends/xc5000.h b/drivers/media/dvb/frontends/xc5000.h index 32a5f1c86a16..b890883a0cdc 100644 --- a/drivers/media/dvb/frontends/xc5000.h +++ b/drivers/media/dvb/frontends/xc5000.h @@ -55,7 +55,7 @@ static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct xc5000_config *cfg) { - 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_TUNER_XC5000 diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 3d508ff4b292..36a5a1c101d5 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -88,7 +88,7 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg) if (ret != 2) { printk("%s: readreg error (reg=%d, ret==%i)\n", - __FUNCTION__, reg, ret); + __func__, reg, ret); return ret; } @@ -152,7 +152,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe, *nominal_rate = value; dprintk("%s: bw %d, adc_clock %d => 0x%x\n", - __FUNCTION__, bw, adc_clock, *nominal_rate); + __func__, bw, adc_clock, *nominal_rate); } static void zl10353_calc_input_freq(struct dvb_frontend *fe, @@ -181,7 +181,7 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe, *input_freq = -value; dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n", - __FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq); + __func__, if2, ife, adc_clock, -(int)value, *input_freq); } static int zl10353_sleep(struct dvb_frontend *fe) diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index fc734c22b5fa..fdbb88ff75fe 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -47,7 +47,7 @@ extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, struct i2c_adapter *i2c) { - 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_ZL10353 */ From 3ca7fc84e37c5cf446fe4137f885f74e71373d7f Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 257/452] V4L/DVB (7515): media/dvb/ttpci replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Acked-by: Oliver Endriss Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110.c | 12 ++++---- drivers/media/dvb/ttpci/av7110.h | 2 +- drivers/media/dvb/ttpci/av7110_hw.c | 42 +++++++++++++------------- drivers/media/dvb/ttpci/av7110_ir.c | 6 ++-- drivers/media/dvb/ttpci/av7110_v4l.c | 4 +-- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/dvb/ttpci/budget-core.c | 2 +- drivers/media/dvb/ttpci/budget.c | 6 ++-- drivers/media/dvb/ttpci/budget.h | 3 +- drivers/media/dvb/ttpci/ttpci-eeprom.c | 2 +- 10 files changed, 41 insertions(+), 40 deletions(-) diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 0e5701bdff19..78919b9e14dc 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -359,7 +359,7 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir, { dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len); if (saa7146_wait_for_debi_done(av7110->dev, 0)) { - printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__); + printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__); return; } @@ -497,7 +497,7 @@ static void gpioirq(unsigned long data) saa7146_read(av7110->dev, SSR)); if (saa7146_wait_for_debi_done(av7110->dev, 0)) { - printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__); + printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__); BUG(); /* maybe we should try resetting the debi? */ } @@ -827,7 +827,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) if (ret != 0 || handle >= 32) { printk("dvb-ttpci: %s error buf %04x %04x %04x %04x " "ret %d handle %04x\n", - __FUNCTION__, buf[0], buf[1], buf[2], buf[3], + __func__, buf[0], buf[1], buf[2], buf[3], ret, handle); dvbdmxfilter->hw_handle = 0xffff; if (!ret) @@ -854,7 +854,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) handle = dvbdmxfilter->hw_handle; if (handle >= 32) { printk("%s tried to stop invalid filter %04x, filter type = %x\n", - __FUNCTION__, handle, dvbdmxfilter->type); + __func__, handle, dvbdmxfilter->type); return -EINVAL; } @@ -867,7 +867,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) if (ret != 0 || answ[1] != handle) { printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x " "resp %04x %04x pid %d\n", - __FUNCTION__, buf[0], buf[1], buf[2], ret, + __func__, buf[0], buf[1], buf[2], ret, answ[0], answ[1], dvbdmxfilter->feed->pid); if (!ret) ret = -1; @@ -1122,7 +1122,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4); if (ret) { - printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__); + printk(KERN_ERR "%s: av7110_fw_request error\n", __func__); return ret; } dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n", diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index 39fbf7d5cffb..e494e04eeee8 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -40,7 +40,7 @@ extern int av7110_debug; #define dprintk(level,args...) \ - do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __FUNCTION__); printk(args); } } while (0) + do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __func__); printk(args); } } while (0) #define MAXFILT 32 diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index a468aa2e4854..9d81074b31df 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -53,11 +53,11 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config, struct saa7146_dev *dev = av7110->dev; if (count <= 0 || count > 32764) { - printk("%s: invalid count %d\n", __FUNCTION__, count); + printk("%s: invalid count %d\n", __func__, count); return -1; } if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { - printk("%s: wait_for_debi_done failed\n", __FUNCTION__); + printk("%s: wait_for_debi_done failed\n", __func__); return -1; } saa7146_write(dev, DEBI_CONFIG, config); @@ -76,11 +76,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count) u32 result = 0; if (count > 32764 || count <= 0) { - printk("%s: invalid count %d\n", __FUNCTION__, count); + printk("%s: invalid count %d\n", __func__, count); return 0; } if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { - printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__); + printk("%s: wait_for_debi_done #1 failed\n", __func__); return 0; } saa7146_write(dev, DEBI_AD, av7110->debi_bus); @@ -91,7 +91,7 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count) if (count > 4) return count; if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { - printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__); + printk("%s: wait_for_debi_done #2 failed\n", __func__); return 0; } @@ -332,7 +332,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) break; if (err) { printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", - __FUNCTION__, stat & flags); + __func__, stat & flags); return -ETIMEDOUT; } msleep(1); @@ -362,7 +362,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0) break; if (err) { - printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__); + printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__); av7110->arm_errors++; return -ETIMEDOUT; } @@ -379,7 +379,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0) break; if (err) { - printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); + printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__); return -ETIMEDOUT; } msleep(1); @@ -419,14 +419,14 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); if (stat & flags[0]) { printk(KERN_ERR "%s: %s QUEUE overflow\n", - __FUNCTION__, type); + __func__, type); return -1; } if ((stat & flags[1]) == 0) break; if (err) { printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", - __FUNCTION__, type); + __func__, type); return -ETIMEDOUT; } msleep(1); @@ -454,7 +454,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) break; if (err) { printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n", - __FUNCTION__, (buf[0] >> 8) & 0xff); + __func__, (buf[0] >> 8) & 0xff); return -ETIMEDOUT; } msleep(1); @@ -462,11 +462,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); if (stat & GPMQOver) { - printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__); + printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__); return -ENOSPC; } else if (stat & OSDQOver) { - printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__); + printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__); return -ENOSPC; } #endif @@ -491,7 +491,7 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) mutex_unlock(&av7110->dcomlock); if (ret && ret!=-ERESTARTSYS) printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n", - __FUNCTION__, ret); + __func__, ret); return ret; } @@ -575,7 +575,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0) break; if (err) { - printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); + printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__); mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } @@ -591,7 +591,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0) break; if (err) { - printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); + printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__); mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } @@ -602,12 +602,12 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, #ifdef COM_DEBUG stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); if (stat & GPMQOver) { - printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__); + printk(KERN_ERR "%s: GPMQOver\n", __func__); mutex_unlock(&av7110->dcomlock); return -1; } else if (stat & OSDQOver) { - printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__); + printk(KERN_ERR "%s: OSDQOver\n", __func__); mutex_unlock(&av7110->dcomlock); return -1; } @@ -741,7 +741,7 @@ static int FlushText(struct av7110 *av7110) break; if (err) { printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", - __FUNCTION__); + __func__); mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } @@ -768,7 +768,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf) break; if (ret) { printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", - __FUNCTION__); + __func__); mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } @@ -782,7 +782,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf) break; if (ret) { printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", - __FUNCTION__); + __func__); mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index a283e1de83fa..23a1c6380d3f 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -133,7 +133,7 @@ static void av7110_emit_key(unsigned long parm) break; default: - printk("%s invalid protocol %x\n", __FUNCTION__, ir->protocol); + printk("%s invalid protocol %x\n", __func__, ir->protocol); return; } @@ -143,7 +143,7 @@ static void av7110_emit_key(unsigned long parm) keycode = ir->key_map[data]; dprintk(16, "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n", - __FUNCTION__, ircom, addr, data, keycode); + __func__, ircom, addr, data, keycode); /* check device address */ if (!(ir->device_mask & (1 << addr))) @@ -151,7 +151,7 @@ static void av7110_emit_key(unsigned long parm) if (!keycode) { printk ("%s: code %08x -> addr %i data 0x%02x -> unknown key!\n", - __FUNCTION__, ircom, addr, data); + __func__, ircom, addr, data); return; } diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index e2f066fb7967..b4a0cc5dc935 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -573,7 +573,7 @@ static int av7110_vbi_reset(struct inode *inode, struct file *file) struct saa7146_dev *dev = fh->dev; struct av7110 *av7110 = (struct av7110*) dev->ext_priv; - dprintk(2, "%s\n", __FUNCTION__); + dprintk(2, "%s\n", __func__); av7110->wssMode = 0; av7110->wssData = 0; if (FW_VERSION(av7110->arm_app) < 0x2623) @@ -590,7 +590,7 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size struct v4l2_sliced_vbi_data d; int rc; - dprintk(2, "%s\n", __FUNCTION__); + dprintk(2, "%s\n", __func__); if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d) return -EINVAL; if (copy_from_user(&d, data, count)) diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 0f476f75e03d..0323515bfd2a 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -1121,7 +1121,7 @@ static void frontend_init(struct budget_ci *budget_ci) budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) { - printk("%s: No LNBP21 found!\n", __FUNCTION__); + printk("%s: No LNBP21 found!\n", __func__); dvb_frontend_detach(budget_ci->budget.dvb_frontend); budget_ci->budget.dvb_frontend = NULL; } diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 0252081f013c..06bbce42fcd7 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -223,7 +223,7 @@ static void vpeirq(unsigned long data) if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) { printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n", - budget->dev->name, __FUNCTION__, budget->buffer_warnings, count); + budget->dev->name, __func__, budget->buffer_warnings, count); budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT; budget->buffer_warnings = 0; } diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 14b00f57b5de..6cbb52d64244 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -438,7 +438,7 @@ static void frontend_init(struct budget *budget) if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params; if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) { - printk("%s: No LNBP21 found!\n", __FUNCTION__); + printk("%s: No LNBP21 found!\n", __func__); goto error_out; } break; @@ -454,9 +454,9 @@ static void frontend_init(struct budget *budget) budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap); if (budget->dvb_frontend) { if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL) - printk("%s: No tda826x found!\n", __FUNCTION__); + printk("%s: No tda826x found!\n", __func__); if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) { - printk("%s: No LNBP21 found!\n", __FUNCTION__); + printk("%s: No LNBP21 found!\n", __func__); goto error_out; } break; diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index d764ffa728b0..dd450b739bff 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -1,3 +1,4 @@ + #ifndef __BUDGET_DVB__ #define __BUDGET_DVB__ @@ -21,7 +22,7 @@ extern int budget_debug; #endif #define dprintk(level,args...) \ - do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0) + do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __func__); printk(args); } } while (0) struct budget_info { char *name; diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c index 1f31e91195b0..7dd54b3026a2 100644 --- a/drivers/media/dvb/ttpci/ttpci-eeprom.c +++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c @@ -95,7 +95,7 @@ static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encode { .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 } }; - /* dprintk("%s\n", __FUNCTION__); */ + /* dprintk("%s\n", __func__); */ ret = i2c_transfer(adapter, msg, 2); From fb9393b519fb27714d14625bc3042b669933e81a Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 258/452] V4L/DVB (7516): media/dvb/ttusb-budget replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- .../media/dvb/ttusb-budget/dvb-ttusb-budget.c | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 1b3b6c1589f7..317eccbe5c66 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -153,12 +153,12 @@ static int ttusb_cmd(struct ttusb *ttusb, (u8 *) data, len, &actual_len, 1000); if (err != 0) { dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n", - __FUNCTION__, err); + __func__, err); mutex_unlock(&ttusb->semusb); return err; } if (actual_len != len) { - dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__, + dprintk("%s: only wrote %d of %d bytes\n", __func__, actual_len, len); mutex_unlock(&ttusb->semusb); return -1; @@ -168,7 +168,7 @@ static int ttusb_cmd(struct ttusb *ttusb, ttusb->last_result, 32, &actual_len, 1000); if (err != 0) { - printk("%s: failed, receive error %d\n", __FUNCTION__, + printk("%s: failed, receive error %d\n", __func__, err); mutex_unlock(&ttusb->semusb); return err; @@ -229,7 +229,7 @@ static int ttusb_i2c_msg(struct ttusb *ttusb, if (err || b[0] != 0x55 || b[1] != id) { dprintk ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ", - __FUNCTION__, err, id); + __func__, err, id); return -EREMOTEIO; } @@ -273,7 +273,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num snd_buf, snd_len, rcv_buf, rcv_len); if (err < rcv_len) { - dprintk("%s: i == %i\n", __FUNCTION__, i); + dprintk("%s: i == %i\n", __func__, i); break; } @@ -327,7 +327,7 @@ static int ttusb_boot_dsp(struct ttusb *ttusb) done: if (err) { dprintk("%s: usb_bulk_msg() failed, return value %i!\n", - __FUNCTION__, err); + __func__, err); } return err; @@ -427,7 +427,7 @@ static int ttusb_init_controller(struct ttusb *ttusb) if ((err = ttusb_result(ttusb, get_version, sizeof(get_version)))) return err; - dprintk("%s: stc-version: %c%c%c%c%c\n", __FUNCTION__, + dprintk("%s: stc-version: %c%c%c%c%c\n", __func__, get_version[4], get_version[5], get_version[6], get_version[7], get_version[8]); @@ -437,7 +437,7 @@ static int ttusb_init_controller(struct ttusb *ttusb) memcmp(get_version + 4, "V 2.2", 5)) { printk ("%s: unknown STC version %c%c%c%c%c, please report!\n", - __FUNCTION__, get_version[4], get_version[5], + __func__, get_version[4], get_version[5], get_version[6], get_version[7], get_version[8]); } @@ -453,7 +453,7 @@ static int ttusb_init_controller(struct ttusb *ttusb) ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version)); if (err) return err; - printk("%s: dsp-version: %c%c%c\n", __FUNCTION__, + printk("%s: dsp-version: %c%c%c\n", __func__, get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]); return 0; } @@ -476,7 +476,7 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe, /* Diseqc */ if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) { dprintk("%s: usb_bulk_msg() failed, return value %i!\n", - __FUNCTION__, err); + __func__, err); } return err; @@ -494,7 +494,7 @@ static int ttusb_update_lnb(struct ttusb *ttusb) /* SetLNB */ if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) { dprintk("%s: usb_bulk_msg() failed, return value %i!\n", - __FUNCTION__, err); + __func__, err); } return err; @@ -528,7 +528,7 @@ static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq) err = ttusb_cmd(ttusb, b, sizeof(b), 0); if (err) { dprintk("%s: usb_bulk_msg() failed, return value %i!\n", - __FUNCTION__, err); + __func__, err); } } #endif @@ -554,7 +554,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, csum ^= le16_to_cpup((u16 *) (muxpack + i)); if (csum) { printk("%s: muxpack with incorrect checksum, ignoring\n", - __FUNCTION__); + __func__); numinvalid++; return; } @@ -563,7 +563,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, cc &= 0x7FFF; if ((cc != ttusb->cc) && (ttusb->cc != -1)) printk("%s: cc discontinuity (%d frames missing)\n", - __FUNCTION__, (cc - ttusb->cc) & 0x7FFF); + __func__, (cc - ttusb->cc) & 0x7FFF); ttusb->cc = (cc + 1) & 0x7FFF; if (muxpack[0] & 0x80) { #ifdef TTUSB_HWSECTIONS @@ -613,7 +613,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) int maxwork = 1024; while (len) { if (!(maxwork--)) { - printk("%s: too much work\n", __FUNCTION__); + printk("%s: too much work\n", __func__); break; } @@ -632,7 +632,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) #else if (ttusb->insync) { printk("%s: lost sync.\n", - __FUNCTION__); + __func__); ttusb->insync = 0; } #endif @@ -691,7 +691,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) else { dprintk ("%s: invalid state: first byte is %x\n", - __FUNCTION__, + __func__, ttusb->muxpack[0]); ttusb->mux_state = 0; } @@ -740,7 +740,7 @@ static void ttusb_iso_irq(struct urb *urb) #if 0 printk("%s: status %d, errcount == %d, length == %i\n", - __FUNCTION__, + __func__, urb->status, urb->error_count, urb->actual_length); #endif @@ -833,7 +833,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb) int i, j, err, buffer_offset = 0; if (ttusb->iso_streaming) { - printk("%s: iso xfer already running!\n", __FUNCTION__); + printk("%s: iso xfer already running!\n", __func__); return 0; } @@ -869,7 +869,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb) ttusb_stop_iso_xfer(ttusb); printk ("%s: failed urb submission (%i: err = %i)!\n", - __FUNCTION__, i, err); + __func__, i, err); return err; } } @@ -1643,7 +1643,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i struct ttusb *ttusb; int result; - dprintk("%s: TTUSB DVB connected\n", __FUNCTION__); + dprintk("%s: TTUSB DVB connected\n", __func__); udev = interface_to_usbdev(intf); @@ -1773,7 +1773,7 @@ static void ttusb_disconnect(struct usb_interface *intf) kfree(ttusb); - dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__); + dprintk("%s: TTUSB DVB disconnected\n", __func__); } static struct usb_device_id ttusb_table[] = { From e9815ceea9733dfb236629f5b72f2e6486f66242 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 259/452] V4L/DVB (7517): media/dvb/ttusb-dec replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 106 +++++++++++------------ drivers/media/dvb/ttusb-dec/ttusbdecfe.c | 4 +- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 1ec981d98b91..95110c483312 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -217,11 +217,11 @@ static void ttusb_dec_handle_irq( struct urb *urb) case -ETIME: /* this urb is dead, cleanup */ dprintk("%s:urb shutting down with status: %d\n", - __FUNCTION__, urb->status); + __func__, urb->status); return; default: dprintk("%s:nonzero status received: %d\n", - __FUNCTION__,urb->status); + __func__,urb->status); goto exit; } @@ -235,7 +235,7 @@ static void ttusb_dec_handle_irq( struct urb *urb) * keyrepeat signal is recieved for lets say 200ms. * this should/could be added later ... * for now lets report each signal as a key down and up*/ - dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]); + dprintk("%s:rc signal:%d\n", __func__, buffer[4]); input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1); input_sync(dec->rc_input_dev); input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0); @@ -245,7 +245,7 @@ static void ttusb_dec_handle_irq( struct urb *urb) exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if(retval) printk("%s - usb_commit_urb failed with result: %d\n", - __FUNCTION__, retval); + __func__, retval); } static u16 crc16(u16 crc, const u8 *buf, size_t len) @@ -268,7 +268,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, int result, actual_len, i; u8 *b; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); if (!b) @@ -276,7 +276,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if ((result = mutex_lock_interruptible(&dec->usb_mutex))) { kfree(b); - printk("%s: Failed to lock usb mutex.\n", __FUNCTION__); + printk("%s: Failed to lock usb mutex.\n", __func__); return result; } @@ -289,7 +289,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, memcpy(&b[4], params, param_length); if (debug) { - printk("%s: command: ", __FUNCTION__); + printk("%s: command: ", __func__); for (i = 0; i < param_length + 4; i++) printk("0x%02X ", b[i]); printk("\n"); @@ -300,7 +300,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (result) { printk("%s: command bulk message failed: error %d\n", - __FUNCTION__, result); + __func__, result); mutex_unlock(&dec->usb_mutex); kfree(b); return result; @@ -311,13 +311,13 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (result) { printk("%s: result bulk message failed: error %d\n", - __FUNCTION__, result); + __func__, result); mutex_unlock(&dec->usb_mutex); kfree(b); return result; } else { if (debug) { - printk("%s: result: ", __FUNCTION__); + printk("%s: result: ", __func__); for (i = 0; i < actual_len; i++) printk("0x%02X ", b[i]); printk("\n"); @@ -343,7 +343,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode, int result; unsigned int tmp; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c); if (result) @@ -400,7 +400,7 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec) u16 audio = htons(dec->pid[DMX_PES_AUDIO]); u16 video = htons(dec->pid[DMX_PES_VIDEO]); - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); memcpy(&b[0], &pcr, 2); memcpy(&b[2], &audio, 2); @@ -419,12 +419,12 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec) static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) { if (length < 8) { - printk("%s: packet too short - discarding\n", __FUNCTION__); + printk("%s: packet too short - discarding\n", __func__); return; } if (length > 8 + MAX_PVA_LENGTH) { - printk("%s: packet too long - discarding\n", __FUNCTION__); + printk("%s: packet too long - discarding\n", __func__); return; } @@ -507,7 +507,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) break; default: - printk("%s: unknown PVA type: %02x.\n", __FUNCTION__, + printk("%s: unknown PVA type: %02x.\n", __func__, pva[2]); break; } @@ -546,7 +546,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec) u16 packet_id; if (dec->packet_length % 2) { - printk("%s: odd sized packet - discarding\n", __FUNCTION__); + printk("%s: odd sized packet - discarding\n", __func__); return; } @@ -554,7 +554,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec) csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]); if (csum) { - printk("%s: checksum failed - discarding\n", __FUNCTION__); + printk("%s: checksum failed - discarding\n", __func__); return; } @@ -563,7 +563,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec) if ((packet_id != dec->next_packet_id) && dec->next_packet_id) { printk("%s: warning: lost packets between %u and %u\n", - __FUNCTION__, dec->next_packet_id - 1, packet_id); + __func__, dec->next_packet_id - 1, packet_id); } if (packet_id == 0xffff) @@ -652,7 +652,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, dec->packet_state = 7; } else { printk("%s: unknown packet type: " - "%02x%02x\n", __FUNCTION__, + "%02x%02x\n", __func__, dec->packet[0], dec->packet[1]); dec->packet_state = 0; } @@ -724,7 +724,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, default: printk("%s: illegal packet state encountered.\n", - __FUNCTION__); + __func__); dec->packet_state = 0; } } @@ -792,7 +792,7 @@ static void ttusb_dec_process_urb(struct urb *urb) } else { /* -ENOENT is expected when unlinking urbs */ if (urb->status != -ENOENT) - dprintk("%s: urb error: %d\n", __FUNCTION__, + dprintk("%s: urb error: %d\n", __func__, urb->status); } @@ -804,7 +804,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec) { int i, j, buffer_offset = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); for (i = 0; i < ISO_BUF_COUNT; i++) { int frame_offset = 0; @@ -834,7 +834,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) { int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (mutex_lock_interruptible(&dec->iso_mutex)) return; @@ -889,7 +889,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) { int i, result; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (mutex_lock_interruptible(&dec->iso_mutex)) return -EAGAIN; @@ -905,7 +905,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) if ((result = usb_submit_urb(dec->iso_urb[i], GFP_ATOMIC))) { printk("%s: failed urb submission %d: " - "error %d\n", __FUNCTION__, i, result); + "error %d\n", __func__, i, result); while (i) { usb_kill_urb(dec->iso_urb[i - 1]); @@ -932,7 +932,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed) u8 b0[] = { 0x05 }; int result = 0; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); dprintk(" ts_type:"); @@ -1012,7 +1012,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed) unsigned long flags; u8 x = 1; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); pid = htons(dvbdmxfeed->pid); memcpy(&b0[0], &pid, 2); @@ -1052,7 +1052,7 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (!dvbdmx->dmx.frontend) return -EINVAL; @@ -1113,7 +1113,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed) static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); switch (dvbdmxfeed->type) { case DMX_TYPE_TS: @@ -1132,7 +1132,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec) { int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); for (i = 0; i < ISO_BUF_COUNT; i++) usb_free_urb(dec->iso_urb[i]); @@ -1147,7 +1147,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) { int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); dec->iso_buffer = pci_alloc_consistent(NULL, ISO_FRAME_SIZE * @@ -1214,7 +1214,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec) dec->rc_input_dev = input_dev; if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) - printk("%s: usb_submit_urb failed\n",__FUNCTION__); + printk("%s: usb_submit_urb failed\n",__func__); /* enable irq pipe */ ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL); @@ -1223,7 +1223,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec) static void ttusb_dec_init_v_pes(struct ttusb_dec *dec) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); dec->v_pes[0] = 0x00; dec->v_pes[1] = 0x00; @@ -1233,7 +1233,7 @@ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec) static int ttusb_dec_init_usb(struct ttusb_dec *dec) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); mutex_init(&dec->usb_mutex); mutex_init(&dec->iso_mutex); @@ -1281,11 +1281,11 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) u32 crc32_csum, crc32_check, tmp; const struct firmware *fw_entry = NULL; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) { printk(KERN_ERR "%s: Firmware (%s) unavailable.\n", - __FUNCTION__, dec->firmware_name); + __func__, dec->firmware_name); return 1; } @@ -1294,7 +1294,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) if (firmware_size < 60) { printk("%s: firmware size too small for DSP code (%zu < 60).\n", - __FUNCTION__, firmware_size); + __func__, firmware_size); release_firmware(fw_entry); return -1; } @@ -1308,7 +1308,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) if (crc32_csum != crc32_check) { printk("%s: crc32 check of DSP code failed (calculated " "0x%08x != 0x%08x in file), file invalid.\n", - __FUNCTION__, crc32_csum, crc32_check); + __func__, crc32_csum, crc32_check); release_firmware(fw_entry); return -1; } @@ -1376,7 +1376,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec) int result; unsigned int mode, model, version; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); result = ttusb_dec_get_stb_state(dec, &mode, &model, &version); @@ -1415,7 +1415,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec) default: printk(KERN_ERR "%s: unknown model returned " "by firmware (%08x) - please report\n", - __FUNCTION__, model); + __func__, model); return -1; break; } @@ -1434,12 +1434,12 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) { int result; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if ((result = dvb_register_adapter(&dec->adapter, dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) { printk("%s: dvb_register_adapter failed: error %d\n", - __FUNCTION__, result); + __func__, result); return result; } @@ -1454,7 +1454,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) dec->demux.write_to_decoder = NULL; if ((result = dvb_dmx_init(&dec->demux)) < 0) { - printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, + printk("%s: dvb_dmx_init failed: error %d\n", __func__, result); dvb_unregister_adapter(&dec->adapter); @@ -1468,7 +1468,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) { printk("%s: dvb_dmxdev_init failed: error %d\n", - __FUNCTION__, result); + __func__, result); dvb_dmx_release(&dec->demux); dvb_unregister_adapter(&dec->adapter); @@ -1480,7 +1480,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx, &dec->frontend)) < 0) { - printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, + printk("%s: dvb_dmx_init failed: error %d\n", __func__, result); dvb_dmxdev_release(&dec->dmxdev); @@ -1492,7 +1492,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx, &dec->frontend)) < 0) { - printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, + printk("%s: dvb_dmx_init failed: error %d\n", __func__, result); dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); @@ -1510,7 +1510,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); dvb_net_release(&dec->dvb_net); dec->demux.dmx.close(&dec->demux.dmx); @@ -1528,7 +1528,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) static void ttusb_dec_exit_rc(struct ttusb_dec *dec) { - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); /* we have to check whether the irq URB is already submitted. * As the irq is submitted after the interface is changed, * this is the best method i figured out. @@ -1552,7 +1552,7 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec) { int i; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); dec->iso_stream_count = 0; @@ -1612,12 +1612,12 @@ static int ttusb_dec_probe(struct usb_interface *intf, struct usb_device *udev; struct ttusb_dec *dec; - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); udev = interface_to_usbdev(intf); if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) { - printk("%s: couldn't allocate memory.\n", __FUNCTION__); + printk("%s: couldn't allocate memory.\n", __func__); return -ENOMEM; } @@ -1692,7 +1692,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); - dprintk("%s\n", __FUNCTION__); + dprintk("%s\n", __func__); if (dec->active) { ttusb_dec_exit_tasklet(dec); @@ -1749,7 +1749,7 @@ static int __init ttusb_dec_init(void) int result; if ((result = usb_register(&ttusb_dec_driver)) < 0) { - printk("%s: initialisation failed: error %d.\n", __FUNCTION__, + printk("%s: initialisation failed: error %d.\n", __func__, result); return result; } diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c index a6fb1d6a7b5d..eb5eaeccd7c4 100644 --- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c @@ -53,7 +53,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status) return ret; if(len != 4) { - printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__); + printk(KERN_ERR "%s: unexpected reply\n", __func__); return -EIO; } @@ -70,7 +70,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status) break; default: pr_info("%s: returned unknown value: %d\n", - __FUNCTION__, result[3]); + __func__, result[3]); return -EIO; } From 7e28adb2497f6b873516163e2d29210c11777613 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 260/452] V4L/DVB (7518): media/video/ replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cpia.h | 4 ++-- drivers/media/video/cpia_usb.c | 2 +- drivers/media/video/ir-kbd-i2c.c | 2 +- drivers/media/video/mt20xx.h | 2 +- drivers/media/video/mt9m001.c | 2 +- drivers/media/video/ov511.h | 2 +- drivers/media/video/pxa_camera.c | 28 +++++++++++++------------- drivers/media/video/se401.c | 6 +++--- drivers/media/video/soc_camera.c | 8 ++++---- drivers/media/video/stk-webcam.c | 2 +- drivers/media/video/stv680.c | 2 +- drivers/media/video/tcm825x.c | 2 +- drivers/media/video/tda8290.c | 6 +++--- drivers/media/video/tda8290.h | 4 ++-- drivers/media/video/tda9840.c | 2 +- drivers/media/video/tda9887.h | 2 +- drivers/media/video/tea5761.h | 4 ++-- drivers/media/video/tea5767.h | 4 ++-- drivers/media/video/tea6415c.c | 2 +- drivers/media/video/tea6420.c | 2 +- drivers/media/video/tuner-simple.c | 2 +- drivers/media/video/tuner-simple.h | 2 +- drivers/media/video/tuner-xc2028.c | 28 +++++++++++++------------- drivers/media/video/tuner-xc2028.h | 2 +- drivers/media/video/videobuf-core.c | 2 +- drivers/media/video/videobuf-dma-sg.c | 4 ++-- drivers/media/video/videobuf-vmalloc.c | 2 +- drivers/media/video/videodev.c | 4 ++-- drivers/media/video/vivi.c | 22 ++++++++++---------- drivers/media/video/w9966.c | 2 +- drivers/media/video/w9968cf.h | 6 +++--- drivers/media/video/zoran_driver.c | 4 ++-- 32 files changed, 84 insertions(+), 84 deletions(-) diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h index 78392fb6f94e..5096058bf579 100644 --- a/drivers/media/video/cpia.h +++ b/drivers/media/video/cpia.h @@ -412,11 +412,11 @@ void cpia_unregister_camera(struct cam_data *cam); /* ErrorCode */ #define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */ #define ALOG(fmt,args...) printk(fmt, ##args) -#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__ , __LINE__ , ##args) +#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args) #ifdef _CPIA_DEBUG_ #define ADBG(fmt,args...) printk(fmt, jiffies, ##args) -#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __FUNCTION__, __LINE__ , ##args) +#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args) #else #define DBG(fmn,args...) do {} while(0) #endif diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c index 9da4726eb9b9..ef1f89399983 100644 --- a/drivers/media/video/cpia_usb.c +++ b/drivers/media/video/cpia_usb.c @@ -170,7 +170,7 @@ static void cpia_usb_complete(struct urb *urb) /* resubmit */ urb->dev = ucpia->dev; if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) - printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __FUNCTION__, i); + printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__, i); } static int cpia_usb_open(void *privdata) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 7942bd078513..11c5fdedc23b 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -153,7 +153,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) } if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0) - dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__, + dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__, buf[0], buf[1], buf[2], buf[3]); /* no key pressed or signal from other ir remote */ diff --git a/drivers/media/video/mt20xx.h b/drivers/media/video/mt20xx.h index 5e9c825d2e91..aa848e14ce5e 100644 --- a/drivers/media/video/mt20xx.h +++ b/drivers/media/video/mt20xx.h @@ -29,7 +29,7 @@ static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, u8 i2c_addr) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 2ea133e8a625..3fb5f63df1e6 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -123,7 +123,7 @@ static int mt9m001_init(struct soc_camera_device *icd) int ret; /* Disable chip, synchronous option update */ - dev_dbg(icd->vdev->dev, "%s\n", __FUNCTION__); + dev_dbg(icd->vdev->dev, "%s\n", __func__); ret = reg_write(icd, MT9M001_RESET, 1); if (ret >= 0) diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h index 18c64222dd11..1010e51189b7 100644 --- a/drivers/media/video/ov511.h +++ b/drivers/media/video/ov511.h @@ -12,7 +12,7 @@ #ifdef OV511_DEBUG #define PDEBUG(level, fmt, args...) \ if (debug >= (level)) info("[%s:%d] " fmt, \ - __FUNCTION__, __LINE__ , ## args) + __func__, __LINE__ , ## args) #else #define PDEBUG(level, fmt, args...) do {} while(0) #endif diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index bef3c9c7902a..936db67a5b0f 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -148,7 +148,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) BUG_ON(in_interrupt()); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); /* This waits until this buffer is out of danger, i.e., until it is no @@ -175,7 +175,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, 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__, + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* Added list head initialization on alloc */ @@ -281,7 +281,7 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, int nents = dma->sglen; unsigned long flags; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); spin_lock_irqsave(&pcdev->lock, flags); @@ -354,21 +354,21 @@ static void pxa_videobuf_release(struct videobuf_queue *vq, #ifdef DEBUG struct soc_camera_device *icd = vq->priv_data; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); switch (vb->state) { case VIDEOBUF_ACTIVE: - dev_dbg(&icd->dev, "%s (active)\n", __FUNCTION__); + dev_dbg(&icd->dev, "%s (active)\n", __func__); break; case VIDEOBUF_QUEUED: - dev_dbg(&icd->dev, "%s (queued)\n", __FUNCTION__); + dev_dbg(&icd->dev, "%s (queued)\n", __func__); break; case VIDEOBUF_PREPARED: - dev_dbg(&icd->dev, "%s (prepared)\n", __FUNCTION__); + dev_dbg(&icd->dev, "%s (prepared)\n", __func__); break; default: - dev_dbg(&icd->dev, "%s (unknown)\n", __FUNCTION__); + dev_dbg(&icd->dev, "%s (unknown)\n", __func__); break; } #endif @@ -408,7 +408,7 @@ static void pxa_camera_dma_irq_y(int channel, void *data) 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__, + dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ @@ -466,18 +466,18 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) pcdev, pdata); if (pdata && pdata->init) { - dev_dbg(pcdev->dev, "%s: Init gpios\n", __FUNCTION__); + dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__); pdata->init(pcdev->dev); } if (pdata && pdata->power) { - dev_dbg(pcdev->dev, "%s: Power on camera\n", __FUNCTION__); + dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__); pdata->power(pcdev->dev, 1); } if (pdata && pdata->reset) { dev_dbg(pcdev->dev, "%s: Releasing camera reset\n", - __FUNCTION__); + __func__); pdata->reset(pcdev->dev, 1); } @@ -507,12 +507,12 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) if (board && board->reset) { dev_dbg(pcdev->dev, "%s: Asserting camera reset\n", - __FUNCTION__); + __func__); board->reset(pcdev->dev, 0); } if (board && board->power) { - dev_dbg(pcdev->dev, "%s: Power off camera\n", __FUNCTION__); + dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__); board->power(pcdev->dev, 0); } } diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index 7b8cd30437c3..1cd629380f71 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -300,10 +300,10 @@ static void se401_button_irq(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + dbg("%s - urb shutting down with status: %d", __func__, urb->status); return; default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + dbg("%s - nonzero urb status received: %d", __func__, urb->status); goto exit; } @@ -315,7 +315,7 @@ exit: status = usb_submit_urb (urb, GFP_ATOMIC); if (status) err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, status); + __func__, status); } static void se401_video_irq(struct urb *urb) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 1e921578804f..91a1251d904d 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -137,7 +137,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv, WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s: %d\n", __FUNCTION__, p->memory); + dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory); ret = videobuf_reqbufs(&icf->vb_vidq, p); if (ret < 0) @@ -453,7 +453,7 @@ static int soc_camera_streamon(struct file *file, void *priv, WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + dev_dbg(&icd->dev, "%s\n", __func__); if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -472,7 +472,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + dev_dbg(&icd->dev, "%s\n", __func__); if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -985,7 +985,7 @@ void soc_camera_video_stop(struct soc_camera_device *icd) { struct video_device *vdev = icd->vdev; - dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + dev_dbg(&icd->dev, "%s\n", __func__); if (!icd->dev.parent || !vdev) return; diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index d2bf54194b63..9276ed997388 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -1100,7 +1100,7 @@ static int stk_setup_format(struct stk_camera *dev) && i < ARRAY_SIZE(stk_sizes)) i++; if (i == ARRAY_SIZE(stk_sizes)) { - STK_ERROR("Something is broken in %s\n", __FUNCTION__); + STK_ERROR("Something is broken in %s\n", __func__); return -EFAULT; } /* This registers controls some timings, not sure of what. */ diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 78730294454e..d7f130bedb5f 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -83,7 +83,7 @@ static unsigned int debug; #define PDEBUG(level, fmt, args...) \ do { \ if (debug >= level) \ - info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , ## args); \ + info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ } while (0) diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c index fb895f6684a3..6943b447a1bd 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/video/tcm825x.c @@ -906,7 +906,7 @@ static int __init tcm825x_init(void) rval = i2c_add_driver(&tcm825x_i2c_driver); if (rval) printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n", - __FUNCTION__); + __func__); return rval; } diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 89afb19c9468..0ebb5b525e57 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -363,7 +363,7 @@ static void tda8295_set_params(struct dvb_frontend *fe, set_audio(fe, params); - tuner_dbg("%s: freq = %d\n", __FUNCTION__, params->frequency); + tuner_dbg("%s: freq = %d\n", __func__, params->frequency); tda8295_power(fe, 1); tda8295_agc1_out(fe, 1); @@ -613,7 +613,7 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props) if (tda8290_id[1] == TDA8290_ID) { if (debug) printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", - __FUNCTION__, i2c_adapter_id(i2c_props->adap), + __func__, i2c_adapter_id(i2c_props->adap), i2c_props->addr); return 0; } @@ -633,7 +633,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) if (tda8295_id[1] == TDA8295_ID) { if (debug) printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n", - __FUNCTION__, i2c_adapter_id(i2c_props->adap), + __func__, i2c_adapter_id(i2c_props->adap), i2c_props->addr); return 0; } diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h index 9dd8b73eb8c6..d3bbf276a469 100644 --- a/drivers/media/video/tda8290.h +++ b/drivers/media/video/tda8290.h @@ -39,7 +39,7 @@ extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, #else static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -EINVAL; } @@ -49,7 +49,7 @@ static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, struct tda829x_config *cfg) { printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", - __FUNCTION__); + __func__); return NULL; } #endif diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 269761ce84a5..0cee00242782 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -35,7 +35,7 @@ static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ - do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0) + do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) #define SWITCH 0x00 #define LEVEL_ADJUST 0x02 diff --git a/drivers/media/video/tda9887.h b/drivers/media/video/tda9887.h index 8f873a8e6ed2..be49dcbfc70e 100644 --- a/drivers/media/video/tda9887.h +++ b/drivers/media/video/tda9887.h @@ -30,7 +30,7 @@ static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/video/tea5761.h b/drivers/media/video/tea5761.h index 73a03b427843..8eb62722b988 100644 --- a/drivers/media/video/tea5761.h +++ b/drivers/media/video/tea5761.h @@ -31,7 +31,7 @@ static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) { printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", - __FUNCTION__); + __func__); return -EINVAL; } @@ -39,7 +39,7 @@ static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, u8 i2c_addr) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/video/tea5767.h b/drivers/media/video/tea5767.h index a44451f61145..7b547c092e25 100644 --- a/drivers/media/video/tea5767.h +++ b/drivers/media/video/tea5767.h @@ -50,7 +50,7 @@ static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) { printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", - __FUNCTION__); + __func__); return -EINVAL; } @@ -58,7 +58,7 @@ static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, u8 i2c_addr) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index f22620e1872e..9513d8611e87 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -37,7 +37,7 @@ static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ - do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0) + do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) #define TEA6415C_NUM_INPUTS 8 #define TEA6415C_NUM_OUTPUTS 6 diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index dc0f0405f4c9..7fd53367c07c 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -37,7 +37,7 @@ static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ - do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0) + do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 8d6d2c803f92..be8d903171b7 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -999,7 +999,7 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, if (type >= tuner_count) { printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n", - __FUNCTION__, type, tuner_count-1); + __func__, type, tuner_count-1); return NULL; } diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h index bf425f325f87..e46cf0121e03 100644 --- a/drivers/media/video/tuner-simple.h +++ b/drivers/media/video/tuner-simple.h @@ -31,7 +31,7 @@ static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, u8 i2c_addr, unsigned int type) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 098a9956a2bc..62b5de231e0d 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -135,7 +135,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) unsigned char buf[2]; unsigned char ibuf[2]; - tuner_dbg("%s %04x called\n", __FUNCTION__, reg); + tuner_dbg("%s %04x called\n", __func__, reg); buf[0] = reg >> 8; buf[1] = (unsigned char) reg; @@ -260,7 +260,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) char name[33]; char *fname; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); if (!firmware_name[0]) fname = priv->ctrl.fname; @@ -405,7 +405,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, int i, best_i = -1, best_nr_matches = 0; unsigned int ign_firm_type_mask = 0; - tuner_dbg("%s called, want type=", __FUNCTION__); + tuner_dbg("%s called, want type=", __func__); if (debug) { dump_firm_type(type); printk("(%x), id %016llx.\n", type, (unsigned long long)*id); @@ -491,7 +491,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, int pos, rc; unsigned char *p, *endp, buf[priv->ctrl.max_len]; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); pos = seek_firmware(fe, type, id); if (pos < 0) @@ -594,7 +594,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, int pos, rc; unsigned char *p; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); if (!int_freq) { pos = seek_firmware(fe, type, id); @@ -658,7 +658,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, u16 version, hwmodel; v4l2_std_id std0; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); if (!priv->firm) { if (!priv->ctrl.fname) { @@ -832,7 +832,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength) u16 frq_lock, signal = 0; int rc; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); mutex_lock(&priv->lock); @@ -869,7 +869,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, unsigned char buf[4]; u32 div, offset = 0; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); mutex_lock(&priv->lock); @@ -952,7 +952,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe, struct xc2028_data *priv = fe->tuner_priv; unsigned int type=0; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); if (p->mode == V4L2_TUNER_RADIO) { type |= FM; @@ -985,7 +985,7 @@ static int xc2028_set_params(struct dvb_frontend *fe, fe_bandwidth_t bw = BANDWIDTH_8_MHZ; u16 demod = 0; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); if (priv->ctrl.d2633) type |= D2633; @@ -1055,7 +1055,7 @@ static int xc2028_sleep(struct dvb_frontend *fe) struct xc2028_data *priv = fe->tuner_priv; int rc = 0; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); mutex_lock(&priv->lock); @@ -1076,7 +1076,7 @@ static int xc2028_dvb_release(struct dvb_frontend *fe) { struct xc2028_data *priv = fe->tuner_priv; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); mutex_lock(&xc2028_list_mutex); @@ -1101,7 +1101,7 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct xc2028_data *priv = fe->tuner_priv; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); *frequency = priv->frequency; @@ -1114,7 +1114,7 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) struct xc2028_ctrl *p = priv_cfg; int rc = 0; - tuner_dbg("%s called\n", __FUNCTION__); + tuner_dbg("%s called\n", __func__); mutex_lock(&priv->lock); diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h index 3eb8420379a4..612e490634d0 100644 --- a/drivers/media/video/tuner-xc2028.h +++ b/drivers/media/video/tuner-xc2028.h @@ -55,7 +55,7 @@ static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg) { printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", - __FUNCTION__); + __func__); return NULL; } #endif diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 3ab556093ca7..37ddbed8e167 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -970,7 +970,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - dprintk(2, "%s\n", __FUNCTION__); + dprintk(2, "%s\n", __func__); mutex_lock(&q->vb_lock); retval = -EBUSY; if (q->streaming) diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index e6ce99ff7fd1..440c1a8e9c1f 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -252,7 +252,7 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) dma->nr_pages, dma->direction); if (0 == dma->sglen) { printk(KERN_WARNING - "%s: videobuf_map_sg failed\n",__FUNCTION__); + "%s: videobuf_map_sg failed\n",__func__); kfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; @@ -430,7 +430,7 @@ static void *__videobuf_alloc(size_t size) videobuf_dma_init(&mem->dma); dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", - __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), + __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), mem,(long)sizeof(*mem)); return vb; diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index e23335f2919d..9eb7982988a6 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -114,7 +114,7 @@ static void *__videobuf_alloc(size_t size) mem->magic=MAGIC_VMAL_MEM; dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", - __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), + __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), mem,(long)sizeof(*mem)); return vb; diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 0d9b63762a48..0bf056622d6a 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -2019,7 +2019,7 @@ int video_register_device(struct video_device *vfd, int type, int nr) break; default: printk(KERN_ERR "%s called with unknown type: %d\n", - __FUNCTION__, type); + __func__, type); return -1; } @@ -2057,7 +2057,7 @@ int video_register_device(struct video_device *vfd, int type, int nr) ret = device_register(&vfd->class_dev); if (ret < 0) { printk(KERN_ERR "%s: device_register failed\n", - __FUNCTION__); + __func__); goto fail_minor; } diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 8353deb8a1d4..17eb3ec5d704 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -426,7 +426,7 @@ static void vivi_sleep(struct vivi_fh *fh) int timeout; DECLARE_WAITQUEUE(wait, current); - dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__, + dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__, (unsigned long)dma_q); add_wait_queue(&dma_q->wq, &wait); @@ -472,7 +472,7 @@ static int vivi_start_thread(struct vivi_fh *fh) dma_q->frame = 0; dma_q->ini_jiffies = jiffies; - dprintk(dev, 1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __func__); dma_q->kthread = kthread_run(vivi_thread, fh, "vivi"); @@ -483,7 +483,7 @@ static int vivi_start_thread(struct vivi_fh *fh) /* Wakes thread */ wake_up_interruptible(&dma_q->wq); - dprintk(dev, 1, "returning from %s\n", __FUNCTION__); + dprintk(dev, 1, "returning from %s\n", __func__); return 0; } @@ -491,7 +491,7 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) { struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); - dprintk(dev, 1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __func__); /* shutdown control thread */ if (dma_q->kthread) { kthread_stop(dma_q->kthread); @@ -516,7 +516,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) while (*size * *count > vid_limit * 1024 * 1024) (*count)--; - dprintk(dev, 1, "%s, count=%d, size=%d\n", __FUNCTION__, + dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, *count, *size); return 0; @@ -527,7 +527,7 @@ 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, state: %i\n", __FUNCTION__, buf->vb.state); + dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); if (in_interrupt()) BUG(); @@ -548,7 +548,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); int rc; - dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field); + dprintk(dev, 1, "%s, field=%d\n", __func__, field); BUG_ON(NULL == fh->fmt); @@ -589,7 +589,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) struct vivi_dev *dev = fh->dev; struct vivi_dmaqueue *vidq = &dev->vidq; - dprintk(dev, 1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __func__); buf->vb.state = VIDEOBUF_QUEUED; list_add_tail(&buf->vb.queue, &vidq->active); @@ -602,7 +602,7 @@ static void buffer_release(struct videobuf_queue *vq, struct vivi_fh *fh = vq->priv_data; struct vivi_dev *dev = (struct vivi_dev *)fh->dev; - dprintk(dev, 1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __func__); free_buffer(vq, buf); } @@ -718,7 +718,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, mutex_lock(&q->vb_lock); if (videobuf_queue_is_busy(&fh->vb_vidq)) { - dprintk(fh->dev, 1, "%s queue busy\n", __FUNCTION__); + dprintk(fh->dev, 1, "%s queue busy\n", __func__); ret = -EBUSY; goto out; } @@ -974,7 +974,7 @@ vivi_poll(struct file *file, struct poll_table_struct *wait) struct vivi_dev *dev = fh->dev; struct videobuf_queue *q = &fh->vb_vidq; - dprintk(dev, 1, "%s\n", __FUNCTION__); + dprintk(dev, 1, "%s\n", __func__); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) return POLLERR; diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index cdb396d9203c..33f702698a56 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -64,7 +64,7 @@ /*#define DEBUG*/ /* Undef me for production */ #ifdef DEBUG -#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a) +#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a) #else #define DPRINTF(x...) #endif diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h index ec7696e8f1fa..3c95316bc030 100644 --- a/drivers/media/video/w9968cf.h +++ b/drivers/media/video/w9968cf.h @@ -298,7 +298,7 @@ struct w9968cf_device { dev_warn(&cam->dev, fmt "\n", ## args); \ else if ((level) >= 5) \ dev_info(&cam->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + __func__, __LINE__ , ## args); \ } \ } /* For generic kernel (not device specific) messages */ @@ -309,7 +309,7 @@ struct w9968cf_device { if ((level) >= 1 && (level) <= 4) \ pr_info("w9968cf: " fmt "\n", ## args); \ else if ((level) >= 5) \ - pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__, \ + pr_debug("w9968cf: [%s:%d] " fmt "\n", __func__, \ __LINE__ , ## args); \ } \ } @@ -321,7 +321,7 @@ struct w9968cf_device { #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args); +dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args); #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */ diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 8c0a379071e5..1a002eaeb06c 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -4247,7 +4247,7 @@ zoran_poll (struct file *file, dprintk(3, KERN_DEBUG "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n", - ZR_DEVNAME(zr), __FUNCTION__, + ZR_DEVNAME(zr), __func__, "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail, "UPMD"[zr->v4l_buffers.buffer[frame].state], zr->v4l_pend_tail, zr->v4l_pend_head); @@ -4269,7 +4269,7 @@ zoran_poll (struct file *file, dprintk(3, KERN_DEBUG "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n", - ZR_DEVNAME(zr), __FUNCTION__, + ZR_DEVNAME(zr), __func__, "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail, "UPMD"[zr->jpg_buffers.buffer[frame].state], zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head); From 94205c7a48b637ae60bd69ac4cc16743a6dddd09 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 261/452] V4L/DVB (7519): media/video/cpia2 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cpia2/cpia2_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index a439a56c3cc9..c8b9fdb700ff 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -570,7 +570,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd) block_name[block_index]); break; default: - LOG("%s: invalid request mode\n",__FUNCTION__); + LOG("%s: invalid request mode\n",__func__); return -EINVAL; } @@ -952,7 +952,7 @@ static int set_default_user_mode(struct camera_data *cam) frame_rate = CPIA2_VP_FRAMERATE_30; break; default: - LOG("%s: Invalid sensor flag value 0x%0X\n",__FUNCTION__, + LOG("%s: Invalid sensor flag value 0x%0X\n",__func__, cam->params.version.sensor_flags); return -EINVAL; } @@ -2356,12 +2356,12 @@ long cpia2_read(struct camera_data *cam, } if (!buf) { - ERR("%s: buffer NULL\n",__FUNCTION__); + ERR("%s: buffer NULL\n",__func__); return -EINVAL; } if (!cam) { - ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__); + ERR("%s: Internal error, camera_data NULL!\n",__func__); return -EINVAL; } @@ -2370,7 +2370,7 @@ long cpia2_read(struct camera_data *cam, return -ERESTARTSYS; if (!cam->present) { - LOG("%s: camera removed\n",__FUNCTION__); + LOG("%s: camera removed\n",__func__); mutex_unlock(&cam->busy_lock); return 0; /* EOF */ } @@ -2434,7 +2434,7 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, unsigned int status=0; if(!cam) { - ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__); + ERR("%s: Internal error, camera_data not found!\n",__func__); return POLLERR; } From 22b4e64f0a119e94090ef45285a5c311f1f6855f Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 262/452] V4L/DVB (7520): media/video/cx23885 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 2 +- drivers/media/video/cx23885/cx23885-core.c | 98 ++++++++++----------- drivers/media/video/cx23885/cx23885-dvb.c | 10 +-- drivers/media/video/cx23885/cx23885-i2c.c | 16 ++-- drivers/media/video/cx23885/cx23885-video.c | 54 ++++++------ 5 files changed, 90 insertions(+), 90 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index dfa269838e01..77cd452e6e5b 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -264,7 +264,7 @@ int cx23885_tuner_callback(void *priv, int command, int arg) } else { printk(KERN_ERR - "%s(): Unknow command.\n", __FUNCTION__); + "%s(): Unknow command.\n", __func__); return -EINVAL; } break; diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index a77505daaed2..52942d102de4 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -260,7 +260,7 @@ void cx23885_wakeup(struct cx23885_tsport *port, } if (bc != 1) printk("%s: %d buffers handled (should be 1)\n", - __FUNCTION__, bc); + __func__, bc); } int cx23885_sram_channel_setup(struct cx23885_dev *dev, @@ -272,7 +272,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev, if (ch->cmds_start == 0) { - dprintk(1, "%s() Erasing channel [%s]\n", __FUNCTION__, + dprintk(1, "%s() Erasing channel [%s]\n", __func__, ch->name); cx_write(ch->ptr1_reg, 0); cx_write(ch->ptr2_reg, 0); @@ -280,7 +280,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev, cx_write(ch->cnt1_reg, 0); return 0; } else { - dprintk(1, "%s() Configuring channel [%s]\n", __FUNCTION__, + dprintk(1, "%s() Configuring channel [%s]\n", __func__, ch->name); } @@ -297,7 +297,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev, /* write CDT */ for (i = 0; i < lines; i++) { - dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, cdt + 16*i, + dprintk(2, "%s() 0x%08x <- 0x%08x\n", __func__, cdt + 16*i, ch->fifo_start + bpl*i); cx_write(cdt + 16*i, ch->fifo_start + bpl*i); cx_write(cdt + 16*i + 4, 0); @@ -449,7 +449,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev) static void cx23885_reset(struct cx23885_dev *dev) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); cx23885_shutdown(dev); @@ -482,7 +482,7 @@ static void cx23885_reset(struct cx23885_dev *dev) static int cx23885_pci_quirks(struct cx23885_dev *dev) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); /* The cx23885 bridge has a weird bug which causes NMI to be asserted * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not @@ -513,7 +513,7 @@ int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno) { - dprintk(1, "%s(portno=%d)\n", __FUNCTION__, portno); + dprintk(1, "%s(portno=%d)\n", __func__, portno); /* Transport bus init dma queue - Common settings */ port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */ @@ -604,14 +604,14 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev) break; default: printk(KERN_ERR "%s() New hardware revision found 0x%x\n", - __FUNCTION__, dev->hwrevision); + __func__, dev->hwrevision); } if (dev->hwrevision) printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", - __FUNCTION__, dev->hwrevision); + __func__, dev->hwrevision); else printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n", - __FUNCTION__, dev->hwrevision); + __func__, dev->hwrevision); } static int cx23885_dev_setup(struct cx23885_dev *dev) @@ -644,7 +644,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) BUG(); dprintk(1, "%s() Memory configured for PCIe bridge type %d\n", - __FUNCTION__, dev->bridge); + __func__, dev->bridge); /* board config */ dev->board = UNSET; @@ -734,9 +734,9 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) dev->radio_addr = cx23885_boards[dev->board].radio_addr; dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n", - __FUNCTION__, dev->tuner_type, dev->tuner_addr); + __func__, dev->tuner_type, dev->tuner_addr); dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n", - __FUNCTION__, dev->radio_type, dev->radio_addr); + __func__, dev->radio_type, dev->radio_addr); /* init hardware */ cx23885_reset(dev); @@ -751,21 +751,21 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { if (cx23885_video_register(dev) < 0) { printk(KERN_ERR "%s() Failed to register analog " - "video adapters on VID_A\n", __FUNCTION__); + "video adapters on VID_A\n", __func__); } } if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) { if (cx23885_dvb_register(&dev->ts1) < 0) { printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n", - __FUNCTION__); + __func__); } } if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { if (cx23885_dvb_register(&dev->ts2) < 0) { printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n", - __FUNCTION__); + __func__); } } @@ -960,50 +960,50 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; - dprintk(1, "%s() Register Dump\n", __FUNCTION__); - dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() Register Dump\n", __func__); + dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __func__, cx_read(DEV_CNTRL2)); - dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __func__, cx_read(PCI_INT_MSK)); - dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __func__, cx_read(AUDIO_INT_INT_MSK)); - dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __func__, cx_read(AUD_INT_DMA_CTL)); - dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __func__, cx_read(AUDIO_EXT_INT_MSK)); - dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __func__, cx_read(AUD_EXT_DMA_CTL)); - dprintk(1, "%s() PAD_CTRL 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() PAD_CTRL 0x%08X\n", __func__, cx_read(PAD_CTRL)); - dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __func__, cx_read(ALT_PIN_OUT_SEL)); - dprintk(1, "%s() GPIO2 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() GPIO2 0x%08X\n", __func__, cx_read(GPIO2)); - dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __FUNCTION__, + dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __func__, port->reg_gpcnt, cx_read(port->reg_gpcnt)); - dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __func__, port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl)); - dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __func__, port->reg_dma_ctl, cx_read(port->reg_dma_ctl)); - dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __func__, port->reg_src_sel, cx_read(port->reg_src_sel)); - dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __func__, port->reg_lngth, cx_read(port->reg_lngth)); - dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __func__, port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl)); - dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __func__, port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl)); - dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __func__, port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status)); - dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __func__, port->reg_sop_status, cx_read(port->reg_sop_status)); - dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__, port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat)); - dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __func__, port->reg_vld_misc, cx_read(port->reg_vld_misc)); - dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __func__, port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en)); - dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __FUNCTION__, + dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __func__, port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk)); } @@ -1013,7 +1013,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port, { struct cx23885_dev *dev = port->dev; - dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__, + dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__, buf->vb.width, buf->vb.height, buf->vb.field); /* setup fifo + format */ @@ -1031,7 +1031,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port, if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) && (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) { printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n", - __FUNCTION__, + __func__, cx23885_boards[dev->board].portb, cx23885_boards[dev->board].portc ); return -EINVAL; @@ -1058,7 +1058,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port, case CX23885_BRIDGE_885: case CX23885_BRIDGE_887: /* enable irqs */ - dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ ); + dprintk(1, "%s() enabling TS int's and DMA\n", __func__ ); cx_set(port->reg_ts_int_msk, port->ts_int_msk_val); cx_set(port->reg_dma_ctl, port->dma_ctl_val); cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask); @@ -1078,7 +1078,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port, static int cx23885_stop_dma(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); /* Stop interrupts and DMA */ cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val); @@ -1093,13 +1093,13 @@ int cx23885_restart_queue(struct cx23885_tsport *port, struct cx23885_dev *dev = port->dev; struct cx23885_buffer *buf; - dprintk(5, "%s()\n", __FUNCTION__); + dprintk(5, "%s()\n", __func__); if (list_empty(&q->active)) { struct cx23885_buffer *prev; prev = NULL; - dprintk(5, "%s() queue is empty\n", __FUNCTION__); + dprintk(5, "%s() queue is empty\n", __func__); for (;;) { if (list_empty(&q->queued)) @@ -1154,7 +1154,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port, int size = port->ts_packet_size * port->ts_packet_count; int rc; - dprintk(1, "%s: %p\n", __FUNCTION__, buf); + dprintk(1, "%s: %p\n", __func__, buf); if (0 != buf->vb.baddr && buf->vb.bsize < size) return -EINVAL; @@ -1197,7 +1197,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf) buf->count = cx88q->count++; mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT); dprintk(1, "[%p/%d] %s - first active\n", - buf, buf->vb.i, __FUNCTION__); + buf, buf->vb.i, __func__); } else { dprintk( 1, "queue is not empty - append to active\n" ); prev = list_entry(cx88q->active.prev, struct cx23885_buffer, @@ -1208,7 +1208,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf) prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */ dprintk( 1, "[%p/%d] %s - append to active\n", - buf, buf->vb.i, __FUNCTION__); + buf, buf->vb.i, __func__); } } @@ -1245,7 +1245,7 @@ static void cx23885_timeout(unsigned long data) struct cx23885_tsport *port = (struct cx23885_tsport *)data; struct cx23885_dev *dev = port->dev; - dprintk(1, "%s()\n",__FUNCTION__); + dprintk(1, "%s()\n",__func__); if (debug > 5) cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]); diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 7bcd37aa8c90..74baa28d16ab 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -185,7 +185,7 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) case XC2028_TUNER_RESET: /* Send the tuner in then out of reset */ /* GPIO-2 xc3028 tuner */ - dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg); + dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); cx_set(GP0_IO, 0x00040000); cx_clear(GP0_IO, 0x00000004); @@ -195,10 +195,10 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) msleep(5); break; case XC2028_RESET_CLK: - dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg); + dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); break; default: - dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__, + dprintk(1, "%s: unknown command %d, arg %d\n", __func__, command, arg); return -EINVAL; } @@ -341,7 +341,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port) struct cx23885_dev *dev = port->dev; int err; - dprintk(1, "%s\n", __FUNCTION__); + dprintk(1, "%s\n", __func__); dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", dev->board, dev->name, @@ -357,7 +357,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port) sizeof(struct cx23885_buffer), port); err = dvb_register(port); if (err != 0) - printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err); + printk("%s() dvb_register failed err = %d\n", __func__, err); return err; } diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 748c79a46549..8773a1fd97cb 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -87,10 +87,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, int retval, cnt; if (joined_rlen) - dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__, + dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__, msg->len, joined_rlen); else - dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len); + dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len); /* Deal with i2c probe functions with zero payload */ if (msg->len == 0) { @@ -101,7 +101,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (!i2c_slave_did_ack(i2c_adap)) return -EIO; - dprintk(1, "%s() returns 0\n", __FUNCTION__); + dprintk(1, "%s() returns 0\n", __func__); return 0; } @@ -176,7 +176,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, if (i2c_debug && !joined) - dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len); + dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len); /* Deal with i2c probe functions with zero payload */ if (msg->len == 0) { @@ -188,7 +188,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, return -EIO; - dprintk(1, "%s() returns 0\n", __FUNCTION__); + dprintk(1, "%s() returns 0\n", __func__); return 0; } @@ -238,11 +238,11 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct cx23885_dev *dev = bus->dev; int i, retval = 0; - dprintk(1, "%s(num = %d)\n", __FUNCTION__, num); + dprintk(1, "%s(num = %d)\n", __func__, num); for (i = 0 ; i < num; i++) { dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", - __FUNCTION__, num, msgs[i].addr, msgs[i].len); + __func__, num, msgs[i].addr, msgs[i].len); if (msgs[i].flags & I2C_M_RD) { /* read */ retval = i2c_readbytes(i2c_adap, &msgs[i], 0); @@ -383,7 +383,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) { struct cx23885_dev *dev = bus->dev; - dprintk(1, "%s(bus = %d)\n", __FUNCTION__, bus->nr); + dprintk(1, "%s(bus = %d)\n", __func__, bus->nr); memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template, sizeof(bus->i2c_adap)); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 45bf2146a193..84652210a28c 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -141,7 +141,7 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc) if (formats[i].fourcc == fourcc) return formats+i; - printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __FUNCTION__, fourcc); + printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); return NULL; } @@ -292,13 +292,13 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, } if (bc != 1) printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", - __FUNCTION__, bc); + __func__, bc); } int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) { dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", - __FUNCTION__, + __func__, (unsigned int)norm, v4l2_norm_to_name(norm)); @@ -319,7 +319,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, char *type) { struct video_device *vfd; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); vfd = video_device_alloc(); if (NULL == vfd) @@ -358,7 +358,7 @@ EXPORT_SYMBOL(cx23885_ctrl_query); static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh, unsigned int bit) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (fh->resources & bit) /* have it already allocated */ return 1; @@ -392,7 +392,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, unsigned int bits) { BUG_ON((fh->resources & bits) != bits); - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); mutex_lock(&dev->lock); fh->resources &= ~bits; @@ -407,7 +407,7 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) memset(&route, 0, sizeof(route)); dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", - __FUNCTION__, + __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0, INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3); @@ -427,7 +427,7 @@ EXPORT_SYMBOL(cx23885_video_mux); int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, unsigned int height, enum v4l2_field field) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); return 0; } @@ -435,7 +435,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev, struct cx23885_dmaqueue *q, struct cx23885_buffer *buf) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); /* setup fifo + format */ cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01], @@ -463,7 +463,7 @@ static int cx23885_restart_video_queue(struct cx23885_dev *dev, { struct cx23885_buffer *buf, *prev; struct list_head *item; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (!list_empty(&q->active)) { buf = list_entry(q->active.next, struct cx23885_buffer, @@ -579,13 +579,13 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, if (dev->tvnorm & V4L2_STD_NTSC) { /* cx25840 transmits NTSC bottom field first */ dprintk(1, "%s() Creating NTSC risc\n", - __FUNCTION__); + __func__); line0_offset = buf->bpl; line1_offset = 0; } else { /* All other formats are top field first */ dprintk(1, "%s() Creating PAL/SECAM risc\n", - __FUNCTION__); + __func__); line0_offset = 0; line1_offset = buf->bpl; } @@ -885,7 +885,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma) int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) { - dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __FUNCTION__); + dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); return 0; } @@ -894,7 +894,7 @@ EXPORT_SYMBOL(cx23885_get_control); int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl) { dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" - " (disabled - no action)\n", __FUNCTION__); + " (disabled - no action)\n", __func__); return 0; } EXPORT_SYMBOL(cx23885_set_control); @@ -990,7 +990,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; int err; - dprintk(2, "%s()\n", __FUNCTION__); + dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_cap(file, priv, f); if (0 != err) @@ -999,7 +999,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __FUNCTION__, + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f); return 0; @@ -1101,7 +1101,7 @@ static int vidioc_streamon(struct file *file, void *priv, { struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) return -EINVAL; @@ -1118,7 +1118,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; int err, res; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1136,7 +1136,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) { struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); mutex_lock(&dev->lock); cx23885_set_tvnorm(dev, *tvnorms); @@ -1159,7 +1159,7 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) [CX23885_VMUX_DEBUG] = "for debug only", }; unsigned int n; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); n = i->index; if (n >= 4) @@ -1184,7 +1184,7 @@ static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); return cx23885_enum_input(dev, i); } @@ -1193,7 +1193,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; *i = dev->input; - dprintk(1, "%s() returns %d\n", __FUNCTION__, *i); + dprintk(1, "%s() returns %d\n", __func__, *i); return 0; } @@ -1201,10 +1201,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; - dprintk(1, "%s(%d)\n", __FUNCTION__, i); + dprintk(1, "%s(%d)\n", __func__, i); if (i >= 4) { - dprintk(1, "%s() -EINVAL\n", __FUNCTION__); + dprintk(1, "%s() -EINVAL\n", __func__); return -EINVAL; } @@ -1389,7 +1389,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status) return handled; cx_write(VID_A_INT_STAT, status); - dprintk(2, "%s() status = 0x%08x\n", __FUNCTION__, status); + dprintk(2, "%s() status = 0x%08x\n", __func__, status); /* risc op code error */ if (status & (1 << 16)) { printk(KERN_WARNING "%s/0: video risc op code error\n", @@ -1487,7 +1487,7 @@ static const struct file_operations radio_fops = { void cx23885_video_unregister(struct cx23885_dev *dev) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); cx_clear(PCI_INT_MSK, 1); if (dev->video_dev) { @@ -1505,7 +1505,7 @@ int cx23885_video_register(struct cx23885_dev *dev) { int err; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); spin_lock_init(&dev->slock); /* Initialize VBI template */ From 32d83efc1c9e290b3d4627c6ec40529eafa89b46 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 263/452] V4L/DVB (7521): media/video/cx88 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-alsa.c | 2 +- drivers/media/video/cx88/cx88-blackbird.c | 8 ++++---- drivers/media/video/cx88/cx88-core.c | 4 ++-- drivers/media/video/cx88/cx88-dvb.c | 14 ++++++------- drivers/media/video/cx88/cx88-mpeg.c | 16 +++++++-------- drivers/media/video/cx88/cx88-tvaudio.c | 24 +++++++++++------------ 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 2f5a4a4ba407..87c751a9a431 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -494,7 +494,7 @@ static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream) count = atomic_read(&chip->count); -// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__, +// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__, // count, new, count & (runtime->periods-1), // runtime->period_size * (count & (runtime->periods-1))); return runtime->period_size * (count & (runtime->periods-1)); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 8d54e7a90dc7..61c4f72644b8 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -314,7 +314,7 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat u32 value, flag, retval; int i; - dprintk(1,"%s: 0x%X\n", __FUNCTION__, command); + dprintk(1,"%s: 0x%X\n", __func__, command); /* this may not be 100% safe if we can't read any memory location without side effects */ @@ -1055,7 +1055,7 @@ static int mpeg_open(struct inode *inode, struct file *file) dev = cx8802_get_device(inode); - dprintk( 1, "%s\n", __FUNCTION__); + dprintk( 1, "%s\n", __func__); if (dev == NULL) return -ENODEV; @@ -1065,7 +1065,7 @@ static int mpeg_open(struct inode *inode, struct file *file) if (drv) { err = drv->request_acquire(drv); if(err != 0) { - dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err); + dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); return err; } } @@ -1284,7 +1284,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) struct cx8802_dev *dev = core->dvbdev; int err; - dprintk( 1, "%s\n", __FUNCTION__); + dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", core->boardnr, core->name, diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 6039a8f57b48..c4d1aff1fdb4 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -548,7 +548,7 @@ void cx88_wakeup(struct cx88_core *core, mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); } if (bc != 1) - printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); + printk("%s: %d buffers handled (should be 1)\n",__func__,bc); } void cx88_shutdown(struct cx88_core *core) @@ -577,7 +577,7 @@ void cx88_shutdown(struct cx88_core *core) int cx88_reset(struct cx88_core *core) { - dprintk(1,"%s\n",__FUNCTION__); + dprintk(1,"%s\n",__func__); cx88_shutdown(core); /* clear irq status */ diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 5e7c7fdb38ae..8fc929eb47ba 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -282,7 +282,7 @@ static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; - dprintk(1, "%s: index = %d\n", __FUNCTION__, index); + dprintk(1, "%s: index = %d\n", __func__, index); if (index == 0) cx_clear(MO_GP0_IO, 8); else @@ -380,7 +380,7 @@ static int cx88_pci_nano_callback(void *ptr, int command, int arg) switch (command) { case XC2028_TUNER_RESET: /* Send the tuner in then out of reset */ - dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg); + dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: @@ -396,10 +396,10 @@ static int cx88_pci_nano_callback(void *ptr, int command, int arg) break; case XC2028_RESET_CLK: - dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg); + dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); break; default: - dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__, + dprintk(1, "%s: unknown command %d, arg %d\n", __func__, command, arg); return -EINVAL; } @@ -872,7 +872,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; - dprintk( 1, "%s\n", __FUNCTION__); + dprintk( 1, "%s\n", __func__); switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: @@ -895,7 +895,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; - dprintk( 1, "%s\n", __FUNCTION__); + dprintk( 1, "%s\n", __func__); switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: @@ -913,7 +913,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) struct cx8802_dev *dev = drv->core->dvbdev; int err; - dprintk( 1, "%s\n", __FUNCTION__); + dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", core->boardnr, core->name, diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 6467ca336142..a6b061c2644a 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -146,7 +146,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ udelay(100); } else { - printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__, + printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__, core->board.mpeg ); return -EINVAL; } @@ -247,7 +247,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); int rc; - dprintk(1, "%s: %p\n", __FUNCTION__, buf); + dprintk(1, "%s: %p\n", __func__, buf); if (0 != buf->vb.baddr && buf->vb.bsize < size) return -EINVAL; @@ -289,7 +289,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) buf->count = cx88q->count++; mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); dprintk(1,"[%p/%d] %s - first active\n", - buf, buf->vb.i, __FUNCTION__); + buf, buf->vb.i, __func__); } else { dprintk( 1, "queue is not empty - append to active\n" ); @@ -299,7 +299,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) buf->count = cx88q->count++; prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk( 1, "[%p/%d] %s - append to active\n", - buf, buf->vb.i, __FUNCTION__); + buf, buf->vb.i, __func__); } } @@ -342,7 +342,7 @@ static void cx8802_timeout(unsigned long data) { struct cx8802_dev *dev = (struct cx8802_dev*)data; - dprintk(1, "%s\n",__FUNCTION__); + dprintk(1, "%s\n",__func__); if (debug) cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); @@ -625,7 +625,7 @@ static int cx8802_request_acquire(struct cx8802_driver *drv) } mutex_unlock(&drv->core->lock); - mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); + mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); } return 0; @@ -641,7 +641,7 @@ static int cx8802_request_release(struct cx8802_driver *drv) { drv->advise_release(drv); core->active_type_id = CX88_BOARD_NONE; - mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); + mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); } mutex_unlock(&drv->core->lock); @@ -815,7 +815,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev) dev = pci_get_drvdata(pci_dev); - dprintk( 1, "%s\n", __FUNCTION__); + dprintk( 1, "%s\n", __func__); if (!list_empty(&dev->drvlist)) { struct cx8802_driver *drv, *tmp; diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index c574f450498f..3a1977f41e27 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -265,12 +265,12 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, mode |= EN_FMRADIO_EN_RDS; if (sap) { - dprintk("%s SAP (status: unknown)\n", __FUNCTION__); + dprintk("%s SAP (status: unknown)\n", __func__); set_audio_start(core, SEL_SAP); set_audio_registers(core, btsc_sap); set_audio_finish(core, mode); } else { - dprintk("%s (status: known-good)\n", __FUNCTION__); + dprintk("%s (status: known-good)\n", __func__); set_audio_start(core, SEL_BTSC); set_audio_registers(core, btsc); set_audio_finish(core, mode); @@ -351,16 +351,16 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) set_audio_start(core,SEL_NICAM); switch (core->tvaudio) { case WW_L: - dprintk("%s SECAM-L NICAM (status: devel)\n", __FUNCTION__); + dprintk("%s SECAM-L NICAM (status: devel)\n", __func__); set_audio_registers(core, nicam_l); break; case WW_I: - dprintk("%s PAL-I NICAM (status: known-good)\n", __FUNCTION__); + dprintk("%s PAL-I NICAM (status: known-good)\n", __func__); set_audio_registers(core, nicam_bgdki_common); set_audio_registers(core, nicam_i); break; default: - dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __FUNCTION__); + dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__); set_audio_registers(core, nicam_bgdki_common); set_audio_registers(core, nicam_default); break; @@ -600,28 +600,28 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode) set_audio_start(core, SEL_A2); switch (core->tvaudio) { case WW_BG: - dprintk("%s PAL-BG A1/2 (status: known-good)\n", __FUNCTION__); + dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__); set_audio_registers(core, a2_bgdk_common); set_audio_registers(core, a2_bg); set_audio_registers(core, a2_deemph50); break; case WW_DK: - dprintk("%s PAL-DK A1/2 (status: known-good)\n", __FUNCTION__); + dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__); set_audio_registers(core, a2_bgdk_common); set_audio_registers(core, a2_dk); set_audio_registers(core, a2_deemph50); break; case WW_I: - dprintk("%s PAL-I A1 (status: known-good)\n", __FUNCTION__); + dprintk("%s PAL-I A1 (status: known-good)\n", __func__); set_audio_registers(core, a1_i); set_audio_registers(core, a2_deemph50); break; case WW_L: - dprintk("%s AM-L (status: devel)\n", __FUNCTION__); + dprintk("%s AM-L (status: devel)\n", __func__); set_audio_registers(core, am_l); break; default: - dprintk("%s Warning: wrong value\n", __FUNCTION__); + dprintk("%s Warning: wrong value\n", __func__); return; break; }; @@ -637,7 +637,7 @@ static void set_audio_standard_EIAJ(struct cx88_core *core) { /* end of list */ }, }; - dprintk("%s (status: unknown)\n", __FUNCTION__); + dprintk("%s (status: unknown)\n", __func__); set_audio_start(core, SEL_EIAJ); set_audio_registers(core, eiaj); @@ -691,7 +691,7 @@ static void set_audio_standard_FM(struct cx88_core *core, { /* end of list */ }, }; - dprintk("%s (status: unknown)\n", __FUNCTION__); + dprintk("%s (status: unknown)\n", __func__); set_audio_start(core, SEL_FMRADIO); switch (deemph) { From d80e134dc8e7e078248f7966a6884858f7ab185f Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 264/452] V4L/DVB (7522): media/video/em28xx replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 2 +- drivers/media/video/em28xx/em28xx-core.c | 6 +++--- drivers/media/video/em28xx/em28xx-i2c.c | 2 +- drivers/media/video/em28xx/em28xx-video.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 8c67f678266a..92b2a6db4fdc 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -51,7 +51,7 @@ MODULE_PARM_DESC(debug, "activates debug info"); #define dprintk(fmt, arg...) do { \ if (debug) \ printk(KERN_INFO "em28xx-audio %s: " fmt, \ - __FUNCTION__, ##arg); \ + __func__, ##arg); \ } while (0) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 4ebef10b5722..9aa96f1713a1 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -38,7 +38,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); #define em28xx_coredbg(fmt, arg...) do {\ if (core_debug) \ printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + dev->name, __func__ , ##arg); } while (0) static unsigned int reg_debug; module_param(reg_debug,int,0644); @@ -47,7 +47,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); #define em28xx_regdbg(fmt, arg...) do {\ if (reg_debug) \ printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + dev->name, __func__ , ##arg); } while (0) static unsigned int isoc_debug; module_param(isoc_debug,int,0644); @@ -56,7 +56,7 @@ MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); #define em28xx_isocdbg(fmt, arg...) do {\ if (isoc_debug) \ printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + dev->name, __func__ , ##arg); } while (0) static int alt = EM28XX_PINOUT; module_param(alt, int, 0644); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index c3d98d81c335..6e1b7b4e7668 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -45,7 +45,7 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); printk(fmt, ##args); } while (0) #define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \ printk(KERN_DEBUG "%s at %s: " fmt, \ - dev->name, __FUNCTION__ , ##args); } while (0) + dev->name, __func__ , ##args); } while (0) /* * em2800_i2c_send_max4() diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index c8264f40aa0d..c7f074c6f226 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -52,7 +52,7 @@ #define em28xx_videodbg(fmt, arg...) do {\ if (video_debug) \ printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + dev->name, __func__ , ##arg); } while (0) MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From 22cc065bad19b0a19adecdc753ded7a7b0c752fa Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 265/452] V4L/DVB (7523): media/video/et61x251 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/et61x251/et61x251.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h index 02c741d8f85a..cc77d144df3c 100644 --- a/drivers/media/video/et61x251/et61x251.h +++ b/drivers/media/video/et61x251/et61x251.h @@ -199,7 +199,7 @@ do { \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \ - __FILE__, __FUNCTION__, __LINE__ , ## args); \ + __FILE__, __func__, __LINE__ , ## args); \ } \ } while (0) # define KDBG(level, fmt, args...) \ @@ -209,7 +209,7 @@ do { \ pr_info("et61x251: " fmt "\n", ## args); \ else if ((level) == 3) \ pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \ - __FUNCTION__, __LINE__ , ## args); \ + __func__, __LINE__ , ## args); \ } \ } while (0) # define V4LDBG(level, name, cmd) \ @@ -225,7 +225,7 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ +dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \ __LINE__ , ## args) #undef PDBGG From 12aa67a63d2bf4e6500af6b2de40d18fa0bc1360 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 266/452] V4L/DVB (7524): media/video/ovcamchip replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ovcamchip/ovcamchip_priv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h index 50c7763d44b3..9afa4fe47726 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h @@ -24,11 +24,11 @@ extern int ovcamchip_debug; #define PDEBUG(level, fmt, args...) \ if (ovcamchip_debug >= (level)) pr_debug("[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) + __func__, __LINE__ , ## args) #define DDEBUG(level, dev, fmt, args...) \ if (ovcamchip_debug >= (level)) dev_dbg(dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) + __func__, __LINE__ , ## args) /* Number of times to retry chip detection. Increase this if you are getting * "Failed to init camera chip" */ From 645635b002311fafffd1b8f4e2e8200639fb7629 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 267/452] V4L/DVB (7525): media/video/pwc replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/pwc-if.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index d2941c5656ca..423fa7c2d0c9 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -489,7 +489,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev) int i; unsigned long flags; - PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__); + PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__); spin_lock_irqsave(&pdev->ptrlock, flags); pdev->full_frames = NULL; @@ -511,7 +511,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev) pdev->fill_image = 0; spin_unlock_irqrestore(&pdev->ptrlock, flags); - PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__); + PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__); } @@ -1428,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) unsigned long page, pos = 0; int index; - PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__); + PWC_DEBUG_MEMORY(">> %s\n", __func__); pdev = vdev->priv; size = vma->vm_end - vma->vm_start; start = vma->vm_start; From 5016381c33d63f23c43416b9c8421b1eeaa1b515 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 268/452] V4L/DVB (7526): media/video/saa7134 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-empress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index e002be568c21..1314522a8130 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -402,7 +402,7 @@ static int empress_init(struct saa7134_dev *dev) { int err; - dprintk("%s: %s\n",dev->name,__FUNCTION__); + dprintk("%s: %s\n",dev->name,__func__); dev->empress_dev = video_device_alloc(); if (NULL == dev->empress_dev) return -ENOMEM; @@ -440,7 +440,7 @@ static int empress_init(struct saa7134_dev *dev) static int empress_fini(struct saa7134_dev *dev) { - dprintk("%s: %s\n",dev->name,__FUNCTION__); + dprintk("%s: %s\n",dev->name,__func__); if (NULL == dev->empress_dev) return 0; From a79d13b3aa0226630ee639e6a2e98a4bda1afd4d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 269/452] V4L/DVB (7527): media/video/sn9c102 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sn9c102/sn9c102.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h index 2e3c3de793a7..0c8d87d8d18d 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/video/sn9c102/sn9c102.h @@ -176,7 +176,7 @@ do { \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + __func__, __LINE__ , ## args); \ } \ } while (0) # define V4LDBG(level, name, cmd) \ @@ -191,7 +191,7 @@ do { \ pr_info("sn9c102: " fmt "\n", ## args); \ else if ((level) == 3) \ pr_debug("sn9c102: [%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + __func__, __LINE__ , ## args); \ } \ } while (0) #else @@ -202,7 +202,7 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ +dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \ __LINE__ , ## args) #undef PDBGG From 4126a8f5c209ba8138619311c1c8e73d361d9700 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 270/452] V4L/DVB (7528): media/video/usbvideo replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvideo/konicawc.c | 2 +- .../media/video/usbvideo/quickcam_messenger.c | 2 +- drivers/media/video/usbvideo/usbvideo.c | 140 +++++++++--------- drivers/media/video/usbvideo/vicam.c | 2 +- 4 files changed, 73 insertions(+), 73 deletions(-) diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 97479609f97d..1c180284ec6c 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -57,7 +57,7 @@ static struct usbvideo *cams; static int debug; #define DEBUG(n, format, arg...) \ if (n <= debug) { \ - printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ + printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \ } #else #define DEBUG(n, arg...) diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index e0ee6d8f2565..32e536edf09d 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -46,7 +46,7 @@ static int debug; #define DEBUG(n, format, arg...) \ if (n <= debug) { \ - printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ + printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \ } #else #define DEBUG(n, arg...) diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index 300188097de6..4128ee20b64e 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -525,11 +525,11 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) static int num_pass; if (uvd == NULL) { - err("%s: uvd == NULL", __FUNCTION__); + err("%s: uvd == NULL", __func__); return; } if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { - err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe); + err("%s: uvd->curframe=%d.", __func__, uvd->curframe); return; } @@ -630,15 +630,15 @@ EXPORT_SYMBOL(usbvideo_HexDump); static int usbvideo_ClientIncModCount(struct uvd *uvd) { if (uvd == NULL) { - err("%s: uvd == NULL", __FUNCTION__); + err("%s: uvd == NULL", __func__); return -EINVAL; } if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", __FUNCTION__); + err("%s: uvd->handle == NULL", __func__); return -EINVAL; } if (!try_module_get(uvd->handle->md_module)) { - err("%s: try_module_get() == 0", __FUNCTION__); + err("%s: try_module_get() == 0", __func__); return -ENODEV; } return 0; @@ -647,15 +647,15 @@ static int usbvideo_ClientIncModCount(struct uvd *uvd) static void usbvideo_ClientDecModCount(struct uvd *uvd) { if (uvd == NULL) { - err("%s: uvd == NULL", __FUNCTION__); + err("%s: uvd == NULL", __func__); return; } if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", __FUNCTION__); + err("%s: uvd->handle == NULL", __func__); return; } if (uvd->handle->md_module == NULL) { - err("%s: uvd->handle->md_module == NULL", __FUNCTION__); + err("%s: uvd->handle->md_module == NULL", __func__); return; } module_put(uvd->handle->md_module); @@ -675,13 +675,13 @@ int usbvideo_register( /* Check parameters for sanity */ if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { - err("%s: Illegal call", __FUNCTION__); + err("%s: Illegal call", __func__); return -EINVAL; } /* Check registration callback - must be set! */ if (cbTbl->probe == NULL) { - err("%s: probe() is required!", __FUNCTION__); + err("%s: probe() is required!", __func__); return -EINVAL; } @@ -692,7 +692,7 @@ int usbvideo_register( return -ENOMEM; } dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", - __FUNCTION__, cams, base_size, num_cams); + __func__, cams, base_size, num_cams); /* Copy callbacks, apply defaults for those that are not set */ memmove(&cams->cb, cbTbl, sizeof(cams->cb)); @@ -721,7 +721,7 @@ int usbvideo_register( up->user_data = kmalloc(up->user_size, GFP_KERNEL); if (up->user_data == NULL) { err("%s: Failed to allocate user_data (%d. bytes)", - __FUNCTION__, up->user_size); + __func__, up->user_size); while (i) { up = &cams->cam[--i]; kfree(up->user_data); @@ -730,7 +730,7 @@ int usbvideo_register( return -ENOMEM; } dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", - __FUNCTION__, i, up->user_data, up->user_size); + __func__, i, up->user_data, up->user_size); } } @@ -776,19 +776,19 @@ void usbvideo_Deregister(struct usbvideo **pCams) int i; if (pCams == NULL) { - err("%s: pCams == NULL", __FUNCTION__); + err("%s: pCams == NULL", __func__); return; } cams = *pCams; if (cams == NULL) { - err("%s: cams == NULL", __FUNCTION__); + err("%s: cams == NULL", __func__); return; } - dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName); + dbg("%s: Deregistering %s driver.", __func__, cams->drvName); usb_deregister(&cams->usbdrv); - dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras); + dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras); for (i=0; i < cams->num_cameras; i++) { struct uvd *up = &cams->cam[i]; int warning = 0; @@ -802,16 +802,16 @@ void usbvideo_Deregister(struct usbvideo **pCams) } if (warning) { err("%s: Warning: user_data=$%p user_size=%d.", - __FUNCTION__, up->user_data, up->user_size); + __func__, up->user_data, up->user_size); } else { dbg("%s: Freeing %d. $%p->user_data=$%p", - __FUNCTION__, i, up, up->user_data); + __func__, i, up, up->user_data); kfree(up->user_data); } } /* Whole array was allocated in one chunk */ dbg("%s: Freed %d uvd structures", - __FUNCTION__, cams->num_cameras); + __func__, cams->num_cameras); kfree(cams); *pCams = NULL; } @@ -846,7 +846,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf) int i; if (uvd == NULL) { - err("%s($%p): Illegal call.", __FUNCTION__, intf); + err("%s($%p): Illegal call.", __func__, intf); return; } @@ -854,7 +854,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf) usbvideo_ClientIncModCount(uvd); if (uvd->debug > 0) - info("%s(%p.)", __FUNCTION__, intf); + info("%s(%p.)", __func__, intf); mutex_lock(&uvd->lock); uvd->remove_pending = 1; /* Now all ISO data will be ignored */ @@ -870,10 +870,10 @@ static void usbvideo_Disconnect(struct usb_interface *intf) video_unregister_device(&uvd->vdev); if (uvd->debug > 0) - info("%s: Video unregistered.", __FUNCTION__); + info("%s: Video unregistered.", __func__); if (uvd->user) - info("%s: In use, disconnect pending.", __FUNCTION__); + info("%s: In use, disconnect pending.", __func__); else usbvideo_CameraRelease(uvd); mutex_unlock(&uvd->lock); @@ -895,7 +895,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf) static void usbvideo_CameraRelease(struct uvd *uvd) { if (uvd == NULL) { - err("%s: Illegal call", __FUNCTION__); + err("%s: Illegal call", __func__); return; } @@ -1013,18 +1013,18 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) char tmp1[20], tmp2[20]; /* Buffers for printing */ if (uvd == NULL) { - err("%s: Illegal call.", __FUNCTION__); + err("%s: Illegal call.", __func__); return -EINVAL; } if (uvd->video_endp == 0) { - info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__); + info("%s: No video endpoint specified; data pump disabled.", __func__); } if (uvd->paletteBits == 0) { - err("%s: No palettes specified!", __FUNCTION__); + err("%s: No palettes specified!", __func__); return -EINVAL; } if (uvd->defaultPalette == 0) { - info("%s: No default palette!", __FUNCTION__); + info("%s: No default palette!", __func__); } uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * @@ -1034,7 +1034,7 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) if (uvd->debug > 0) { info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", - __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits); + __func__, uvd->iface, uvd->video_endp, uvd->paletteBits); } if (uvd->dev == NULL) { err("%s: uvd->dev == NULL", __func__); @@ -1042,11 +1042,11 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) } 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__); + err("%s: video_register_device failed", __func__); return -EPIPE; } if (uvd->debug > 1) { - info("%s: video_register_device() successful", __FUNCTION__); + info("%s: video_register_device() successful", __func__); } info("%s on /dev/video%d: canvas=%s videosize=%s", @@ -1113,14 +1113,14 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) int i, errCode = 0; if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, dev); + info("%s($%p)", __func__, dev); if (0 < usbvideo_ClientIncModCount(uvd)) return -ENODEV; mutex_lock(&uvd->lock); if (uvd->user) { - err("%s: Someone tried to open an already opened device!", __FUNCTION__); + err("%s: Someone tried to open an already opened device!", __func__); errCode = -EBUSY; } else { /* Clear statistics */ @@ -1136,7 +1136,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE); if ((uvd->fbuf == NULL) || (!RingQueue_IsAllocated(&uvd->dp))) { - err("%s: Failed to allocate fbuf or dp", __FUNCTION__); + err("%s: Failed to allocate fbuf or dp", __func__); errCode = -ENOMEM; } else { /* Allocate all buffers */ @@ -1180,19 +1180,19 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) if (errCode == 0) { if (VALID_CALLBACK(uvd, setupOnOpen)) { if (uvd->debug > 1) - info("%s: setupOnOpen callback", __FUNCTION__); + info("%s: setupOnOpen callback", __func__); errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); if (errCode < 0) { err("%s: setupOnOpen callback failed (%d.).", - __FUNCTION__, errCode); + __func__, errCode); } else if (uvd->debug > 1) { - info("%s: setupOnOpen callback successful", __FUNCTION__); + info("%s: setupOnOpen callback successful", __func__); } } if (errCode == 0) { uvd->settingsAdjusted = 0; if (uvd->debug > 1) - info("%s: Open succeeded.", __FUNCTION__); + info("%s: Open succeeded.", __func__); uvd->user++; file->private_data = uvd; } @@ -1202,7 +1202,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) if (errCode != 0) usbvideo_ClientDecModCount(uvd); if (uvd->debug > 0) - info("%s: Returning %d.", __FUNCTION__, errCode); + info("%s: Returning %d.", __func__, errCode); return errCode; } @@ -1225,7 +1225,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) int i; if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, dev); + info("%s($%p)", __func__, dev); mutex_lock(&uvd->lock); GET_CALLBACK(uvd, stopDataPump)(uvd); @@ -1252,7 +1252,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) usbvideo_ClientDecModCount(uvd); if (uvd->debug > 1) - info("%s: Completed.", __FUNCTION__); + info("%s: Completed.", __func__); file->private_data = NULL; return 0; } @@ -1506,7 +1506,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, return -EFAULT; if (uvd->debug >= 1) - info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock); + info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock); mutex_lock(&uvd->lock); @@ -1553,7 +1553,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, */ if (frmx == -1) { if (uvd->defaultPalette == 0) { - err("%s: No default palette; don't know what to do!", __FUNCTION__); + err("%s: No default palette; don't know what to do!", __func__); count = -EFAULT; goto read_done; } @@ -1625,7 +1625,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, frame->seqRead_Index += count; if (uvd->debug >= 1) { err("%s: {copy} count used=%Zd, new seqRead_Index=%ld", - __FUNCTION__, count, frame->seqRead_Index); + __func__, count, frame->seqRead_Index); } /* Finally check if the frame is done with and "release" it */ @@ -1636,7 +1636,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, /* Mark it as available to be used again. */ uvd->frame[frmx].frameState = FrameState_Unused; if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) { - err("%s: usbvideo_NewFrame failed.", __FUNCTION__); + err("%s: usbvideo_NewFrame failed.", __func__); } } read_done: @@ -1743,10 +1743,10 @@ static int usbvideo_StartDataPump(struct uvd *uvd) int i, errFlag; if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, uvd); + info("%s($%p)", __func__, uvd); if (!CAMERA_IS_OPERATIONAL(uvd)) { - err("%s: Camera is not operational", __FUNCTION__); + err("%s: Camera is not operational", __func__); return -EFAULT; } uvd->curframe = -1; @@ -1754,14 +1754,14 @@ static int usbvideo_StartDataPump(struct uvd *uvd) /* Alternate interface 1 is is the biggest frame size */ i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); if (i < 0) { - err("%s: usb_set_interface error", __FUNCTION__); + err("%s: usb_set_interface error", __func__); uvd->last_error = i; return -EBUSY; } if (VALID_CALLBACK(uvd, videoStart)) GET_CALLBACK(uvd, videoStart)(uvd); else - err("%s: videoStart not set", __FUNCTION__); + err("%s: videoStart not set", __func__); /* We double buffer the Iso lists */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { @@ -1786,12 +1786,12 @@ static int usbvideo_StartDataPump(struct uvd *uvd) for (i=0; i < USBVIDEO_NUMSBUF; i++) { errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); if (errFlag) - err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag); + err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag); } uvd->streaming = 1; if (uvd->debug > 1) - info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp); + info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp); return 0; } @@ -1813,14 +1813,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd) return; if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, uvd); + info("%s($%p)", __func__, uvd); /* Unschedule all of the iso td's */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { usb_kill_urb(uvd->sbuf[i].urb); } if (uvd->debug > 1) - info("%s: streaming=0", __FUNCTION__); + info("%s: streaming=0", __func__); uvd->streaming = 0; if (!uvd->remove_pending) { @@ -1828,12 +1828,12 @@ static void usbvideo_StopDataPump(struct uvd *uvd) if (VALID_CALLBACK(uvd, videoStop)) GET_CALLBACK(uvd, videoStop)(uvd); else - err("%s: videoStop not set", __FUNCTION__); + err("%s: videoStop not set", __func__); /* Set packet size to 0 */ j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); if (j < 0) { - err("%s: usb_set_interface() error %d.", __FUNCTION__, j); + err("%s: usb_set_interface() error %d.", __func__, j); uvd->last_error = j; } } @@ -1957,12 +1957,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) struct usbvideo_frame *frame = &uvd->frame[frameNum]; if (uvd->debug >= 2) - info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum); + info("%s($%p,%d.)", __func__, uvd, frameNum); switch (frame->frameState) { case FrameState_Unused: if (uvd->debug >= 2) - info("%s: FrameState_Unused", __FUNCTION__); + info("%s: FrameState_Unused", __func__); return -EINVAL; case FrameState_Ready: case FrameState_Grabbing: @@ -1972,7 +1972,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) redo: if (!CAMERA_IS_OPERATIONAL(uvd)) { if (uvd->debug >= 2) - info("%s: Camera is not operational (1)", __FUNCTION__); + info("%s: Camera is not operational (1)", __func__); return -EIO; } ntries = 0; @@ -1981,24 +1981,24 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) signalPending = signal_pending(current); if (!CAMERA_IS_OPERATIONAL(uvd)) { if (uvd->debug >= 2) - info("%s: Camera is not operational (2)", __FUNCTION__); + info("%s: Camera is not operational (2)", __func__); return -EIO; } assert(uvd->fbuf != NULL); if (signalPending) { if (uvd->debug >= 2) - info("%s: Signal=$%08x", __FUNCTION__, signalPending); + info("%s: Signal=$%08x", __func__, signalPending); if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { usbvideo_TestPattern(uvd, 1, 0); uvd->curframe = -1; uvd->stats.frame_num++; if (uvd->debug >= 2) - info("%s: Forced test pattern screen", __FUNCTION__); + info("%s: Forced test pattern screen", __func__); return 0; } else { /* Standard answer: Interrupted! */ if (uvd->debug >= 2) - info("%s: Interrupted!", __FUNCTION__); + info("%s: Interrupted!", __func__); return -EINTR; } } else { @@ -2008,17 +2008,17 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) else if (VALID_CALLBACK(uvd, processData)) GET_CALLBACK(uvd, processData)(uvd, frame); else - err("%s: processData not set", __FUNCTION__); + err("%s: processData not set", __func__); } } while (frame->frameState == FrameState_Grabbing); if (uvd->debug >= 2) { info("%s: Grabbing done; state=%d. (%lu. bytes)", - __FUNCTION__, frame->frameState, frame->seqRead_Length); + __func__, frame->frameState, frame->seqRead_Length); } if (frame->frameState == FrameState_Error) { int ret = usbvideo_NewFrame(uvd, frameNum); if (ret < 0) { - err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret); + err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret); return ret; } goto redo; @@ -2050,7 +2050,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) } frame->frameState = FrameState_Done_Hold; if (uvd->debug >= 2) - info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__); + info("%s: Entered FrameState_Done_Hold state.", __func__); return 0; case FrameState_Done_Hold: @@ -2061,12 +2061,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) * it will be released back into the wild to roam freely. */ if (uvd->debug >= 2) - info("%s: FrameState_Done_Hold state.", __FUNCTION__); + info("%s: FrameState_Done_Hold state.", __func__); return 0; } /* Catch-all for other cases. We shall not be here. */ - err("%s: Invalid state %d.", __FUNCTION__, frame->frameState); + err("%s: Invalid state %d.", __func__, frame->frameState); frame->frameState = FrameState_Unused; return 0; } @@ -2162,7 +2162,7 @@ static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, const int ccm = 128; /* Color correction median - see below */ if ((uvd == NULL) || (frame == NULL)) { - err("%s: Illegal call.", __FUNCTION__); + err("%s: Illegal call.", __func__); return; } adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 4d4795ae3bc7..64819353276a 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -48,7 +48,7 @@ // #define VICAM_DEBUG #ifdef VICAM_DEBUG -#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args) +#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args) #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args) #else #define DBG(fmn,args...) do {} while(0) From d5a50e498603f5fa78e0373c389e2d2c3c13d709 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 8 Apr 2008 23:20:00 -0300 Subject: [PATCH 271/452] V4L/DVB (7529): media/video/zc0301 replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zc0301/zc0301.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h index a2de50efa31a..7bbab541a309 100644 --- a/drivers/media/video/zc0301/zc0301.h +++ b/drivers/media/video/zc0301/zc0301.h @@ -160,7 +160,7 @@ do { \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \ - __FILE__, __FUNCTION__, __LINE__ , ## args); \ + __FILE__, __func__, __LINE__ , ## args); \ } \ } while (0) # define KDBG(level, fmt, args...) \ @@ -170,7 +170,7 @@ do { \ pr_info("zc0301: " fmt "\n", ## args); \ else if ((level) == 3) \ pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \ - __FUNCTION__, __LINE__ , ## args); \ + __func__, __LINE__ , ## args); \ } \ } while (0) # define V4LDBG(level, name, cmd) \ @@ -186,7 +186,7 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ +dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \ __LINE__ , ## args) #undef PDBGG From 8727073beff795ec0c9cb18833431d0b606f8264 Mon Sep 17 00:00:00 2001 From: Christoph Pfister Date: Wed, 9 Apr 2008 17:34:09 -0300 Subject: [PATCH 272/452] V4L/DVB (7530): budget-av: Fix support for certain cams The current ci implementation doesn't accept 0xff when reading data bytes (address == 0), thus breaks cams which report a buffer size of 0x--ff like my orion one. Remove the 0xff check altogether, because validation is really the job of a higher layer. Signed-off-by: Christoph Pfister Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 2d64d557b977..f0689e064f06 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -178,7 +178,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre udelay(1); result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0); - if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) { + if (result == -ETIMEDOUT) { ciintf_slot_shutdown(ca, slot); printk(KERN_INFO "budget-av: cam ejected 3\n"); return -ETIMEDOUT; From c4e3bcb688dd561ae219a957e0d924f718335cab Mon Sep 17 00:00:00 2001 From: Christoph Pfister Date: Wed, 9 Apr 2008 17:37:36 -0300 Subject: [PATCH 273/452] V4L/DVB (7531): budget-av: Fix CI interface on (some) KNC1 DVBS cards Quoting the commit introducing reinitialise_demod (3984 / by adq): "These cards [KNC1 DVBT and DVBC] need special handling for CI - reinitialising the frontend device when the CI module is reset." Apparently my 1894:0010 also needs that fix, because once you initialise CI/CAM you lose lock. Signed-off-by: Christoph Pfister Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index f0689e064f06..ed7fb1df554d 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -941,6 +941,12 @@ static void frontend_init(struct budget_av *budget_av) switch (saa->pci->subsystem_device) { case SUBID_DVBS_KNC1: + /* + * maybe that setting is needed for other dvb-s cards as well, + * but so far it has been only confirmed for this type + */ + budget_av->reinitialise_demod = 1; + /* fall through */ case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBS_EASYWATCH_1: if (saa->pci->subsystem_vendor == 0x1894) { From faea4d2ab2d4710f87739fd53b5c13ca7a7d34aa Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 9 Apr 2008 17:49:55 -0300 Subject: [PATCH 274/452] V4L/DVB (7532): budget: Add support for Fujitsu Siemens DVB-T Activy Budget Implement support for Fujitsu Siemens DVB-T Activy Budget, sub-system id 0x1131:0x5f61. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 6cbb52d64244..829576dc2799 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -257,11 +257,17 @@ static struct ves1820_config alps_tdbe2_config = { static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct budget* budget = (struct budget*) fe->dvb->priv; + struct budget *budget = fe->dvb->priv; + u8 *tuner_addr = fe->tuner_priv; u32 div; u8 cfg, cpump, band_select; u8 data[4]; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) }; + + if (tuner_addr) + msg.addr = *tuner_addr; + else + msg.addr = 0x61; div = (36125000 + params->frequency) / 166666; @@ -292,6 +298,12 @@ static struct l64781_config grundig_29504_401_config = { .demod_address = 0x55, }; +static struct l64781_config grundig_29504_401_config_activy = { + .demod_address = 0x54, +}; + +static u8 tuner_address_grundig_29504_401_activy = 0x60; + static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; @@ -433,6 +445,14 @@ static void frontend_init(struct budget *budget) } break; + case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */ + budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy; + budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; + } + break; + case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260)) budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap); if (budget->dvb_frontend) { @@ -537,6 +557,7 @@ MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT); MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); +MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), @@ -547,6 +568,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), + MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61), { .vendor = 0, } From b38bf410fed223a48482e499150d4b554526a13a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 7 Apr 2008 08:32:14 -0300 Subject: [PATCH 275/452] V4L/DVB (7534): ivtv: the upd* modules have to be probed to properly autodetect some cards Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-i2c.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index fa5ab1eb1800..9824eafee021 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -177,10 +177,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) } if (id != I2C_DRIVERID_TUNER) { - c = i2c_new_device(&itv->i2c_adap, &info); - if (c->driver == NULL) + if (id == I2C_DRIVERID_UPD64031A || + id == I2C_DRIVERID_UPD64083) { + unsigned short addrs[2] = { info.addr, I2C_CLIENT_END }; + + c = i2c_new_probed_device(&itv->i2c_adap, &info, addrs); + } else + c = i2c_new_device(&itv->i2c_adap, &info); + if (c && c->driver == NULL) i2c_unregister_device(c); - else + else if (c) itv->i2c_clients[i] = c; return itv->i2c_clients[i] ? 0 : -ENODEV; } From fb7b37cf913c19dbdbb9bf3e653924e126b4007e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 9 Apr 2008 06:26:17 -0300 Subject: [PATCH 276/452] V4L/DVB (7535): saa717x: add new audio/video decoder i2c driver Added the last remaining out-of-tree kernel driver from the ivtv project. The saa717x is used in several Japanese cards and a Russian card. The driver is not complete in that only NTSC is supported and no PAL/SECAM. Hopefully this will be added in the future. Signed-off-by: Takahiro Adachi Signed-off-by: Kyuma Ohta Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 9 + drivers/media/video/Makefile | 1 + drivers/media/video/ivtv/Kconfig | 1 + drivers/media/video/ivtv/ivtv-driver.c | 2 + drivers/media/video/saa717x.c | 1516 ++++++++++++++++++++++++ 5 files changed, 1529 insertions(+) create mode 100644 drivers/media/video/saa717x.c diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index de6a6208e344..54b9f84e9a3e 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -270,6 +270,15 @@ config VIDEO_SAA711X To compile this driver as a module, choose M here: the module will be called saa7115. +config VIDEO_SAA717X + tristate "Philips SAA7171/3/4 audio/video decoders" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Philips SAA7171/3/4 audio/video decoders. + + To compile this driver as a module, choose M here: the + module will be called saa717x. + config VIDEO_SAA7191 tristate "Philips SAA7191 video decoder" depends on VIDEO_V4L1 && I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 8b1e97a7caa3..fe3be94afd10 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o +obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index 270906fc3146..b6171702c4d0 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -10,6 +10,7 @@ config VIDEO_IVTV select VIDEO_CX25840 select VIDEO_MSP3400 select VIDEO_SAA711X + select VIDEO_SAA717X select VIDEO_SAA7127 select VIDEO_TVAUDIO select VIDEO_CS53L32A diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 1ed77167b125..065df53f80fd 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -883,7 +883,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) #ifndef CONFIG_VIDEO_SAA7127 hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127); #endif +#ifndef CONFIG_VIDEO_SAA717X hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X); +#endif #ifndef CONFIG_VIDEO_UPD64031A hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A); #endif diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c new file mode 100644 index 000000000000..53c5edbcf7ea --- /dev/null +++ b/drivers/media/video/saa717x.c @@ -0,0 +1,1516 @@ +/* + * saa717x - Philips SAA717xHL video decoder driver + * + * Based on the saa7115 driver + * + * Changes by Ohta Kyuma + * - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004) + * + * Changes by T.Adachi (tadachi@tadachi-net.com) + * - support audio, video scaler etc, and checked the initialize sequence. + * + * Cleaned up by Hans Verkuil + * + * Note: this is a reversed engineered driver based on captures from + * the I2C bus under Windows. This chip is very similar to the saa7134, + * though. Unfortunately, this driver is currently only working for NTSC. + * + * 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 +#include +#include + +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver"); +MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil"); +MODULE_LICENSE("GPL"); + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +/* + * Generic i2c probe + * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' + */ + +struct saa717x_state { + v4l2_std_id std; + int input; + int enable; + int radio; + int bright; + int contrast; + int hue; + int sat; + int playback; + int audio; + int tuner_audio_mode; + int audio_main_mute; + int audio_main_vol_r; + int audio_main_vol_l; + u16 audio_main_bass; + u16 audio_main_treble; + u16 audio_main_volume; + u16 audio_main_balance; + int audio_input; +}; + +/* ----------------------------------------------------------------------- */ + +/* for audio mode */ +#define TUNER_AUDIO_MONO 0 /* LL */ +#define TUNER_AUDIO_STEREO 1 /* LR */ +#define TUNER_AUDIO_LANG1 2 /* LL */ +#define TUNER_AUDIO_LANG2 3 /* RR */ + +#define SAA717X_NTSC_WIDTH (704) +#define SAA717X_NTSC_HEIGHT (480) + +/* ----------------------------------------------------------------------- */ + +static int saa717x_write(struct i2c_client *client, u32 reg, u32 value) +{ + struct i2c_adapter *adap = client->adapter; + int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488; + unsigned char mm1[6]; + struct i2c_msg msg; + + msg.flags = 0; + msg.addr = client->addr; + mm1[0] = (reg >> 8) & 0xff; + mm1[1] = reg & 0xff; + + if (fw_addr) { + mm1[4] = (value >> 16) & 0xff; + mm1[3] = (value >> 8) & 0xff; + mm1[2] = value & 0xff; + } else { + mm1[2] = value & 0xff; + } + msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */ + msg.buf = mm1; + v4l_dbg(2, debug, client, "wrote: reg 0x%03x=%08x\n", reg, value); + return i2c_transfer(adap, &msg, 1) == 1; +} + +static void saa717x_write_regs(struct i2c_client *client, u32 *data) +{ + while (data[0] || data[1]) { + saa717x_write(client, data[0], data[1]); + data += 2; + } +} + +static u32 saa717x_read(struct i2c_client *client, u32 reg) +{ + struct i2c_adapter *adap = client->adapter; + int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528; + unsigned char mm1[2]; + unsigned char mm2[4] = { 0, 0, 0, 0 }; + struct i2c_msg msgs[2]; + u32 value; + + msgs[0].flags = 0; + msgs[1].flags = I2C_M_RD; + msgs[0].addr = msgs[1].addr = client->addr; + mm1[0] = (reg >> 8) & 0xff; + mm1[1] = reg & 0xff; + msgs[0].len = 2; + msgs[0].buf = mm1; + msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */ + msgs[1].buf = mm2; + i2c_transfer(adap, msgs, 2); + + if (fw_addr) + value = (mm2[2] & 0xff) | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16); + else + value = mm2[0] & 0xff; + + v4l_dbg(2, debug, client, "read: reg 0x%03x=0x%08x\n", reg, value); + return value; +} + +/* ----------------------------------------------------------------------- */ + +static u32 reg_init_initialize[] = +{ + /* from linux driver */ + 0x101, 0x008, /* Increment delay */ + + 0x103, 0x000, /* Analog input control 2 */ + 0x104, 0x090, /* Analog input control 3 */ + 0x105, 0x090, /* Analog input control 4 */ + 0x106, 0x0eb, /* Horizontal sync start */ + 0x107, 0x0e0, /* Horizontal sync stop */ + 0x109, 0x055, /* Luminance control */ + + 0x10f, 0x02a, /* Chroma gain control */ + 0x110, 0x000, /* Chroma control 2 */ + + 0x114, 0x045, /* analog/ADC */ + + 0x118, 0x040, /* RAW data gain */ + 0x119, 0x080, /* RAW data offset */ + + 0x044, 0x000, /* VBI horizontal input window start (L) TASK A */ + 0x045, 0x000, /* VBI horizontal input window start (H) TASK A */ + 0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */ + 0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */ + + 0x049, 0x000, /* VBI vertical input window start (H) TASK A */ + + 0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */ + 0x04d, 0x002, /* VBI horizontal output length (H) TASK A */ + + 0x064, 0x080, /* Lumina brightness TASK A */ + 0x065, 0x040, /* Luminance contrast TASK A */ + 0x066, 0x040, /* Chroma saturation TASK A */ + /* 067H: Reserved */ + 0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */ + 0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */ + 0x06a, 0x000, /* VBI phase offset TASK A */ + + 0x06e, 0x000, /* Horizontal phase offset Luma TASK A */ + 0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */ + + 0x072, 0x000, /* Vertical filter mode TASK A */ + + 0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */ + 0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */ + 0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */ + 0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */ + + 0x089, 0x000, /* VBI vertical input window start (H) TAKS B */ + + 0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */ + 0x08d, 0x002, /* VBI horizontal output length (H) TASK B */ + + 0x0a4, 0x080, /* Lumina brightness TASK B */ + 0x0a5, 0x040, /* Luminance contrast TASK B */ + 0x0a6, 0x040, /* Chroma saturation TASK B */ + /* 0A7H reserved */ + 0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */ + 0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */ + 0x0aa, 0x000, /* VBI phase offset TASK B */ + + 0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */ + 0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */ + + 0x0b2, 0x000, /* Vertical filter mode TASK B */ + + 0x00c, 0x000, /* Start point GREEN path */ + 0x00d, 0x000, /* Start point BLUE path */ + 0x00e, 0x000, /* Start point RED path */ + + 0x010, 0x010, /* GREEN path gamma curve --- */ + 0x011, 0x020, + 0x012, 0x030, + 0x013, 0x040, + 0x014, 0x050, + 0x015, 0x060, + 0x016, 0x070, + 0x017, 0x080, + 0x018, 0x090, + 0x019, 0x0a0, + 0x01a, 0x0b0, + 0x01b, 0x0c0, + 0x01c, 0x0d0, + 0x01d, 0x0e0, + 0x01e, 0x0f0, + 0x01f, 0x0ff, /* --- GREEN path gamma curve */ + + 0x020, 0x010, /* BLUE path gamma curve --- */ + 0x021, 0x020, + 0x022, 0x030, + 0x023, 0x040, + 0x024, 0x050, + 0x025, 0x060, + 0x026, 0x070, + 0x027, 0x080, + 0x028, 0x090, + 0x029, 0x0a0, + 0x02a, 0x0b0, + 0x02b, 0x0c0, + 0x02c, 0x0d0, + 0x02d, 0x0e0, + 0x02e, 0x0f0, + 0x02f, 0x0ff, /* --- BLUE path gamma curve */ + + 0x030, 0x010, /* RED path gamma curve --- */ + 0x031, 0x020, + 0x032, 0x030, + 0x033, 0x040, + 0x034, 0x050, + 0x035, 0x060, + 0x036, 0x070, + 0x037, 0x080, + 0x038, 0x090, + 0x039, 0x0a0, + 0x03a, 0x0b0, + 0x03b, 0x0c0, + 0x03c, 0x0d0, + 0x03d, 0x0e0, + 0x03e, 0x0f0, + 0x03f, 0x0ff, /* --- RED path gamma curve */ + + 0x109, 0x085, /* Luminance control */ + + /**** from app start ****/ + 0x584, 0x000, /* AGC gain control */ + 0x585, 0x000, /* Program count */ + 0x586, 0x003, /* Status reset */ + 0x588, 0x0ff, /* Number of audio samples (L) */ + 0x589, 0x00f, /* Number of audio samples (M) */ + 0x58a, 0x000, /* Number of audio samples (H) */ + 0x58b, 0x000, /* Audio select */ + 0x58c, 0x010, /* Audio channel assign1 */ + 0x58d, 0x032, /* Audio channel assign2 */ + 0x58e, 0x054, /* Audio channel assign3 */ + 0x58f, 0x023, /* Audio format */ + 0x590, 0x000, /* SIF control */ + + 0x595, 0x000, /* ?? */ + 0x596, 0x000, /* ?? */ + 0x597, 0x000, /* ?? */ + + 0x464, 0x00, /* Digital input crossbar1 */ + + 0x46c, 0xbbbb10, /* Digital output selection1-3 */ + 0x470, 0x101010, /* Digital output selection4-6 */ + + 0x478, 0x00, /* Sound feature control */ + + 0x474, 0x18, /* Softmute control */ + + 0x454, 0x0425b9, /* Sound Easy programming(reset) */ + 0x454, 0x042539, /* Sound Easy programming(reset) */ + + + /**** common setting( of DVD play, including scaler commands) ****/ + 0x042, 0x003, /* Data path configuration for VBI (TASK A) */ + + 0x082, 0x003, /* Data path configuration for VBI (TASK B) */ + + 0x108, 0x0f8, /* Sync control */ + 0x2a9, 0x0fd, /* ??? */ + 0x102, 0x089, /* select video input "mode 9" */ + 0x111, 0x000, /* Mode/delay control */ + + 0x10e, 0x00a, /* Chroma control 1 */ + + 0x594, 0x002, /* SIF, analog I/O select */ + + 0x454, 0x0425b9, /* Sound */ + 0x454, 0x042539, + + 0x111, 0x000, + 0x10e, 0x00a, + 0x464, 0x000, + 0x300, 0x000, + 0x301, 0x006, + 0x302, 0x000, + 0x303, 0x006, + 0x308, 0x040, + 0x309, 0x000, + 0x30a, 0x000, + 0x30b, 0x000, + 0x000, 0x002, + 0x001, 0x000, + 0x002, 0x000, + 0x003, 0x000, + 0x004, 0x033, + 0x040, 0x01d, + 0x041, 0x001, + 0x042, 0x004, + 0x043, 0x000, + 0x080, 0x01e, + 0x081, 0x001, + 0x082, 0x004, + 0x083, 0x000, + 0x190, 0x018, + 0x115, 0x000, + 0x116, 0x012, + 0x117, 0x018, + 0x04a, 0x011, + 0x08a, 0x011, + 0x04b, 0x000, + 0x08b, 0x000, + 0x048, 0x000, + 0x088, 0x000, + 0x04e, 0x012, + 0x08e, 0x012, + 0x058, 0x012, + 0x098, 0x012, + 0x059, 0x000, + 0x099, 0x000, + 0x05a, 0x003, + 0x09a, 0x003, + 0x05b, 0x001, + 0x09b, 0x001, + 0x054, 0x008, + 0x094, 0x008, + 0x055, 0x000, + 0x095, 0x000, + 0x056, 0x0c7, + 0x096, 0x0c7, + 0x057, 0x002, + 0x097, 0x002, + 0x0ff, 0x0ff, + 0x060, 0x001, + 0x0a0, 0x001, + 0x061, 0x000, + 0x0a1, 0x000, + 0x062, 0x000, + 0x0a2, 0x000, + 0x063, 0x000, + 0x0a3, 0x000, + 0x070, 0x000, + 0x0b0, 0x000, + 0x071, 0x004, + 0x0b1, 0x004, + 0x06c, 0x0e9, + 0x0ac, 0x0e9, + 0x06d, 0x003, + 0x0ad, 0x003, + 0x05c, 0x0d0, + 0x09c, 0x0d0, + 0x05d, 0x002, + 0x09d, 0x002, + 0x05e, 0x0f2, + 0x09e, 0x0f2, + 0x05f, 0x000, + 0x09f, 0x000, + 0x074, 0x000, + 0x0b4, 0x000, + 0x075, 0x000, + 0x0b5, 0x000, + 0x076, 0x000, + 0x0b6, 0x000, + 0x077, 0x000, + 0x0b7, 0x000, + 0x195, 0x008, + 0x0ff, 0x0ff, + 0x108, 0x0f8, + 0x111, 0x000, + 0x10e, 0x00a, + 0x2a9, 0x0fd, + 0x464, 0x001, + 0x454, 0x042135, + 0x598, 0x0e7, + 0x599, 0x07d, + 0x59a, 0x018, + 0x59c, 0x066, + 0x59d, 0x090, + 0x59e, 0x001, + 0x584, 0x000, + 0x585, 0x000, + 0x586, 0x003, + 0x588, 0x0ff, + 0x589, 0x00f, + 0x58a, 0x000, + 0x58b, 0x000, + 0x58c, 0x010, + 0x58d, 0x032, + 0x58e, 0x054, + 0x58f, 0x023, + 0x590, 0x000, + 0x595, 0x000, + 0x596, 0x000, + 0x597, 0x000, + 0x464, 0x000, + 0x46c, 0xbbbb10, + 0x470, 0x101010, + + + 0x478, 0x000, + 0x474, 0x018, + 0x454, 0x042135, + 0x598, 0x0e7, + 0x599, 0x07d, + 0x59a, 0x018, + 0x59c, 0x066, + 0x59d, 0x090, + 0x59e, 0x001, + 0x584, 0x000, + 0x585, 0x000, + 0x586, 0x003, + 0x588, 0x0ff, + 0x589, 0x00f, + 0x58a, 0x000, + 0x58b, 0x000, + 0x58c, 0x010, + 0x58d, 0x032, + 0x58e, 0x054, + 0x58f, 0x023, + 0x590, 0x000, + 0x595, 0x000, + 0x596, 0x000, + 0x597, 0x000, + 0x464, 0x000, + 0x46c, 0xbbbb10, + 0x470, 0x101010, + + 0x478, 0x000, + 0x474, 0x018, + 0x454, 0x042135, + 0x598, 0x0e7, + 0x599, 0x07d, + 0x59a, 0x018, + 0x59c, 0x066, + 0x59d, 0x090, + 0x59e, 0x001, + 0x584, 0x000, + 0x585, 0x000, + 0x586, 0x003, + 0x588, 0x0ff, + 0x589, 0x00f, + 0x58a, 0x000, + 0x58b, 0x000, + 0x58c, 0x010, + 0x58d, 0x032, + 0x58e, 0x054, + 0x58f, 0x023, + 0x590, 0x000, + 0x595, 0x000, + 0x596, 0x000, + 0x597, 0x000, + 0x464, 0x000, + 0x46c, 0xbbbb10, + 0x470, 0x101010, + 0x478, 0x000, + 0x474, 0x018, + 0x454, 0x042135, + 0x193, 0x000, + 0x300, 0x000, + 0x301, 0x006, + 0x302, 0x000, + 0x303, 0x006, + 0x308, 0x040, + 0x309, 0x000, + 0x30a, 0x000, + 0x30b, 0x000, + 0x000, 0x002, + 0x001, 0x000, + 0x002, 0x000, + 0x003, 0x000, + 0x004, 0x033, + 0x040, 0x01d, + 0x041, 0x001, + 0x042, 0x004, + 0x043, 0x000, + 0x080, 0x01e, + 0x081, 0x001, + 0x082, 0x004, + 0x083, 0x000, + 0x190, 0x018, + 0x115, 0x000, + 0x116, 0x012, + 0x117, 0x018, + 0x04a, 0x011, + 0x08a, 0x011, + 0x04b, 0x000, + 0x08b, 0x000, + 0x048, 0x000, + 0x088, 0x000, + 0x04e, 0x012, + 0x08e, 0x012, + 0x058, 0x012, + 0x098, 0x012, + 0x059, 0x000, + 0x099, 0x000, + 0x05a, 0x003, + 0x09a, 0x003, + 0x05b, 0x001, + 0x09b, 0x001, + 0x054, 0x008, + 0x094, 0x008, + 0x055, 0x000, + 0x095, 0x000, + 0x056, 0x0c7, + 0x096, 0x0c7, + 0x057, 0x002, + 0x097, 0x002, + 0x060, 0x001, + 0x0a0, 0x001, + 0x061, 0x000, + 0x0a1, 0x000, + 0x062, 0x000, + 0x0a2, 0x000, + 0x063, 0x000, + 0x0a3, 0x000, + 0x070, 0x000, + 0x0b0, 0x000, + 0x071, 0x004, + 0x0b1, 0x004, + 0x06c, 0x0e9, + 0x0ac, 0x0e9, + 0x06d, 0x003, + 0x0ad, 0x003, + 0x05c, 0x0d0, + 0x09c, 0x0d0, + 0x05d, 0x002, + 0x09d, 0x002, + 0x05e, 0x0f2, + 0x09e, 0x0f2, + 0x05f, 0x000, + 0x09f, 0x000, + 0x074, 0x000, + 0x0b4, 0x000, + 0x075, 0x000, + 0x0b5, 0x000, + 0x076, 0x000, + 0x0b6, 0x000, + 0x077, 0x000, + 0x0b7, 0x000, + 0x195, 0x008, + 0x598, 0x0e7, + 0x599, 0x07d, + 0x59a, 0x018, + 0x59c, 0x066, + 0x59d, 0x090, + 0x59e, 0x001, + 0x584, 0x000, + 0x585, 0x000, + 0x586, 0x003, + 0x588, 0x0ff, + 0x589, 0x00f, + 0x58a, 0x000, + 0x58b, 0x000, + 0x58c, 0x010, + 0x58d, 0x032, + 0x58e, 0x054, + 0x58f, 0x023, + 0x590, 0x000, + 0x595, 0x000, + 0x596, 0x000, + 0x597, 0x000, + 0x464, 0x000, + 0x46c, 0xbbbb10, + 0x470, 0x101010, + 0x478, 0x000, + 0x474, 0x018, + 0x454, 0x042135, + 0x193, 0x0a6, + 0x108, 0x0f8, + 0x042, 0x003, + 0x082, 0x003, + 0x454, 0x0425b9, + 0x454, 0x042539, + 0x193, 0x000, + 0x193, 0x0a6, + 0x464, 0x000, + + 0, 0 +}; + +/* Tuner */ +static u32 reg_init_tuner_input[] = { + 0x108, 0x0f8, /* Sync control */ + 0x111, 0x000, /* Mode/delay control */ + 0x10e, 0x00a, /* Chroma control 1 */ + 0, 0 +}; + +/* Composite */ +static u32 reg_init_composite_input[] = { + 0x108, 0x0e8, /* Sync control */ + 0x111, 0x000, /* Mode/delay control */ + 0x10e, 0x04a, /* Chroma control 1 */ + 0, 0 +}; + +/* S-Video */ +static u32 reg_init_svideo_input[] = { + 0x108, 0x0e8, /* Sync control */ + 0x111, 0x000, /* Mode/delay control */ + 0x10e, 0x04a, /* Chroma control 1 */ + 0, 0 +}; + +static u32 reg_set_audio_template[4][2] = +{ + { /* for MONO + tadachi 6/29 DMA audio output select? + Register 0x46c + 7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1 + 0: MAIN left, 1: MAIN right + 2: AUX1 left, 3: AUX1 right + 4: AUX2 left, 5: AUX2 right + 6: DPL left, 7: DPL right + 8: DPL center, 9: DPL surround + A: monitor output, B: digital sense */ + 0xbbbb00, + + /* tadachi 6/29 DAC and I2S output select? + Register 0x470 + 7-4:DAC right ch. 3-0:DAC left ch. + I2S1 right,left I2S2 right,left */ + 0x00, + }, + { /* for STEREO */ + 0xbbbb10, 0x101010, + }, + { /* for LANG1 */ + 0xbbbb00, 0x00, + }, + { /* for LANG2/SAP */ + 0xbbbb11, 0x111111, + } +}; + + +/* Get detected audio flags (from saa7134 driver) */ +static void get_inf_dev_status(struct i2c_client *client, + int *dual_flag, int *stereo_flag) +{ + u32 reg_data3; + + static char *stdres[0x20] = { + [0x00] = "no standard detected", + [0x01] = "B/G (in progress)", + [0x02] = "D/K (in progress)", + [0x03] = "M (in progress)", + + [0x04] = "B/G A2", + [0x05] = "B/G NICAM", + [0x06] = "D/K A2 (1)", + [0x07] = "D/K A2 (2)", + [0x08] = "D/K A2 (3)", + [0x09] = "D/K NICAM", + [0x0a] = "L NICAM", + [0x0b] = "I NICAM", + + [0x0c] = "M Korea", + [0x0d] = "M BTSC ", + [0x0e] = "M EIAJ", + + [0x0f] = "FM radio / IF 10.7 / 50 deemp", + [0x10] = "FM radio / IF 10.7 / 75 deemp", + [0x11] = "FM radio / IF sel / 50 deemp", + [0x12] = "FM radio / IF sel / 75 deemp", + + [0x13 ... 0x1e] = "unknown", + [0x1f] = "??? [in progress]", + }; + + + *dual_flag = *stereo_flag = 0; + + /* (demdec status: 0x528) */ + + /* read current status */ + reg_data3 = saa717x_read(client, 0x0528); + + v4l_dbg(1, debug, client, "tvaudio thread status: 0x%x [%s%s%s]\n", + reg_data3, stdres[reg_data3 & 0x1f], + (reg_data3 & 0x000020) ? ",stereo" : "", + (reg_data3 & 0x000040) ? ",dual" : ""); + v4l_dbg(1, debug, client, "detailed status: " + "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n", + (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone " : "", + (reg_data3 & 0x000100) ? " A2/EIAJ dual " : "", + (reg_data3 & 0x000200) ? " A2/EIAJ stereo " : "", + (reg_data3 & 0x000400) ? " A2/EIAJ noise mute " : "", + + (reg_data3 & 0x000800) ? " BTSC/FM radio pilot " : "", + (reg_data3 & 0x001000) ? " SAP carrier " : "", + (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "", + (reg_data3 & 0x004000) ? " SAP noise mute " : "", + (reg_data3 & 0x008000) ? " VDSP " : "", + + (reg_data3 & 0x010000) ? " NICST " : "", + (reg_data3 & 0x020000) ? " NICDU " : "", + (reg_data3 & 0x040000) ? " NICAM muted " : "", + (reg_data3 & 0x080000) ? " NICAM reserve sound " : "", + + (reg_data3 & 0x100000) ? " init done " : ""); + + if (reg_data3 & 0x000220) { + v4l_dbg(1, debug, client, "ST!!!\n"); + *stereo_flag = 1; + } + + if (reg_data3 & 0x000140) { + v4l_dbg(1, debug, client, "DUAL!!!\n"); + *dual_flag = 1; + } +} + +/* regs write to set audio mode */ +static void set_audio_mode(struct i2c_client *client, int audio_mode) +{ + v4l_dbg(1, debug, client, "writing registers to set audio mode by set %d\n", + audio_mode); + + saa717x_write(client, 0x46c, reg_set_audio_template[audio_mode][0]); + saa717x_write(client, 0x470, reg_set_audio_template[audio_mode][1]); +} + +/* write regs to video output level (bright,contrast,hue,sat) */ +static void set_video_output_level_regs(struct i2c_client *client, + struct saa717x_state *decoder) +{ + /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */ + saa717x_write(client, 0x10a, decoder->bright); + + /* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) - + 0h (luminance off) 40: i2c dump + c0h (-1.0 inverse chrominance) + 80h (-2.0 inverse chrominance) */ + saa717x_write(client, 0x10b, decoder->contrast); + + /* saturation? 7fh(max)-40h(ITU)-0h(color off) + c0h (-1.0 inverse chrominance) + 80h (-2.0 inverse chrominance) */ + saa717x_write(client, 0x10c, decoder->sat); + + /* color hue (phase) control + 7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */ + saa717x_write(client, 0x10d, decoder->hue); +} + +/* write regs to set audio volume, bass and treble */ +static int set_audio_regs(struct i2c_client *client, + struct saa717x_state *decoder) +{ + u8 mute = 0xac; /* -84 dB */ + u32 val; + unsigned int work_l, work_r; + + /* set SIF analog I/O select */ + saa717x_write(client, 0x0594, decoder->audio_input); + v4l_dbg(1, debug, client, "set audio input %d\n", + decoder->audio_input); + + /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */ + work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768; + work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768; + decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40; + decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40; + + /* set main volume */ + /* main volume L[7-0],R[7-0],0x00 24=24dB,-83dB, -84(mute) */ + /* def:0dB->6dB(MPG600GR) */ + /* if mute is on, set mute */ + if (decoder->audio_main_mute) { + val = mute | (mute << 8); + } else { + val = (u8)decoder->audio_main_vol_l | + ((u8)decoder->audio_main_vol_r << 8); + } + + saa717x_write(client, 0x480, val); + + /* bass and treble; go to another function */ + /* set bass and treble */ + val = decoder->audio_main_bass | (decoder->audio_main_treble << 8); + saa717x_write(client, 0x488, val); + return 0; +} + +/********** scaling staff ***********/ +static void set_h_prescale(struct i2c_client *client, + int task, int prescale) +{ + static const struct { + int xpsc; + int xacl; + int xc2_1; + int xdcg; + int vpfy; + } vals[] = { + /* XPSC XACL XC2_1 XDCG VPFY */ + { 1, 0, 0, 0, 0 }, + { 2, 2, 1, 2, 2 }, + { 3, 4, 1, 3, 2 }, + { 4, 8, 1, 4, 2 }, + { 5, 8, 1, 4, 2 }, + { 6, 8, 1, 4, 3 }, + { 7, 8, 1, 4, 3 }, + { 8, 15, 0, 4, 3 }, + { 9, 15, 0, 4, 3 }, + { 10, 16, 1, 5, 3 }, + }; + static const int count = ARRAY_SIZE(vals); + int i, task_shift; + + task_shift = task * 0x40; + for (i = 0; i < count; i++) + if (vals[i].xpsc == prescale) + break; + if (i == count) + return; + + /* horizonal prescaling */ + saa717x_write(client, 0x60 + task_shift, vals[i].xpsc); + /* accumulation length */ + saa717x_write(client, 0x61 + task_shift, vals[i].xacl); + /* level control */ + saa717x_write(client, 0x62 + task_shift, + (vals[i].xc2_1 << 3) | vals[i].xdcg); + /*FIR prefilter control */ + saa717x_write(client, 0x63 + task_shift, + (vals[i].vpfy << 2) | vals[i].vpfy); +} + +/********** scaling staff ***********/ +static void set_v_scale(struct i2c_client *client, int task, int yscale) +{ + int task_shift; + + task_shift = task * 0x40; + /* Vertical scaling ratio (LOW) */ + saa717x_write(client, 0x70 + task_shift, yscale & 0xff); + /* Vertical scaling ratio (HI) */ + saa717x_write(client, 0x71 + task_shift, yscale >> 8); +} + +static int saa717x_set_audio_clock_freq(struct i2c_client *client, u32 freq) +{ + /* not yet implament, so saa717x_cfg_??hz_??_audio is not defined. */ + return 0; +} + +static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) +{ + struct saa717x_state *state = i2c_get_clientdata(client); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value < 0 || ctrl->value > 255) { + v4l_err(client, "invalid brightness setting %d\n", ctrl->value); + return -ERANGE; + } + + state->bright = ctrl->value; + v4l_dbg(1, debug, client, "bright:%d\n", state->bright); + saa717x_write(client, 0x10a, state->bright); + break; + + case V4L2_CID_CONTRAST: + if (ctrl->value < 0 || ctrl->value > 127) { + v4l_err(client, "invalid contrast setting %d\n", ctrl->value); + return -ERANGE; + } + + state->contrast = ctrl->value; + v4l_dbg(1, debug, client, "contrast:%d\n", state->contrast); + saa717x_write(client, 0x10b, state->contrast); + break; + + case V4L2_CID_SATURATION: + if (ctrl->value < 0 || ctrl->value > 127) { + v4l_err(client, "invalid saturation setting %d\n", ctrl->value); + return -ERANGE; + } + + state->sat = ctrl->value; + v4l_dbg(1, debug, client, "sat:%d\n", state->sat); + saa717x_write(client, 0x10c, state->sat); + break; + + case V4L2_CID_HUE: + if (ctrl->value < -127 || ctrl->value > 127) { + v4l_err(client, "invalid hue setting %d\n", ctrl->value); + return -ERANGE; + } + + state->hue = ctrl->value; + v4l_dbg(1, debug, client, "hue:%d\n", state->hue); + saa717x_write(client, 0x10d, state->hue); + break; + + case V4L2_CID_AUDIO_MUTE: + state->audio_main_mute = ctrl->value; + set_audio_regs(client, state); + break; + + case V4L2_CID_AUDIO_VOLUME: + state->audio_main_volume = ctrl->value; + set_audio_regs(client, state); + break; + + case V4L2_CID_AUDIO_BALANCE: + state->audio_main_balance = ctrl->value; + set_audio_regs(client, state); + break; + + case V4L2_CID_AUDIO_TREBLE: + state->audio_main_treble = ctrl->value; + set_audio_regs(client, state); + break; + + case V4L2_CID_AUDIO_BASS: + state->audio_main_bass = ctrl->value; + set_audio_regs(client, state); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int saa717x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) +{ + struct saa717x_state *state = i2c_get_clientdata(client); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = state->bright; + break; + + case V4L2_CID_CONTRAST: + ctrl->value = state->contrast; + break; + + case V4L2_CID_SATURATION: + ctrl->value = state->sat; + break; + + case V4L2_CID_HUE: + ctrl->value = state->hue; + break; + + case V4L2_CID_AUDIO_MUTE: + ctrl->value = state->audio_main_mute; + break; + + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = state->audio_main_volume; + break; + + case V4L2_CID_AUDIO_BALANCE: + ctrl->value = state->audio_main_balance; + break; + + case V4L2_CID_AUDIO_TREBLE: + ctrl->value = state->audio_main_treble; + break; + + case V4L2_CID_AUDIO_BASS: + ctrl->value = state->audio_main_bass; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static struct v4l2_queryctrl saa717x_qctrl[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 128, + .flags = 0, + }, { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 64, + .flags = 0, + }, { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 64, + .flags = 0, + }, { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = -128, + .maximum = 127, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_AUDIO_VOLUME, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Volume", + .minimum = 0, + .maximum = 65535, + .step = 65535 / 100, + .default_value = 58880, + .flags = 0, + }, { + .id = V4L2_CID_AUDIO_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Balance", + .minimum = 0, + .maximum = 65535, + .step = 65535 / 100, + .default_value = 32768, + .flags = 0, + }, { + .id = V4L2_CID_AUDIO_MUTE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = 0, + }, { + .id = V4L2_CID_AUDIO_BASS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Bass", + .minimum = 0, + .maximum = 65535, + .step = 65535 / 100, + .default_value = 32768, + }, { + .id = V4L2_CID_AUDIO_TREBLE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Treble", + .minimum = 0, + .maximum = 65535, + .step = 65535 / 100, + .default_value = 32768, + }, +}; + +static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_state *decoder, int inp) +{ + int is_tuner = inp & 0x80; /* tuner input flag */ + + inp &= 0x7f; + + v4l_dbg(1, debug, client, "decoder set input (%d)\n", inp); + /* inputs from 0-9 are available*/ + /* saa717x have mode0-mode9 but mode5 is reserved. */ + if (inp < 0 || inp > 9 || inp == 5) + return -EINVAL; + + if (decoder->input != inp) { + int input_line = inp; + + decoder->input = input_line; + v4l_dbg(1, debug, client, "now setting %s input %d\n", + input_line >= 6 ? "S-Video" : "Composite", + input_line); + + /* select mode */ + saa717x_write(client, 0x102, + (saa717x_read(client, 0x102) & 0xf0) | + input_line); + + /* bypass chrominance trap for modes 6..9 */ + saa717x_write(client, 0x109, + (saa717x_read(client, 0x109) & 0x7f) | + (input_line < 6 ? 0x0 : 0x80)); + + /* change audio_mode */ + if (is_tuner) { + /* tuner */ + set_audio_mode(client, decoder->tuner_audio_mode); + } else { + /* Force to STEREO mode if Composite or + * S-Video were chosen */ + set_audio_mode(client, TUNER_AUDIO_STEREO); + } + /* change initialize procedure (Composite/S-Video) */ + if (is_tuner) + saa717x_write_regs(client, reg_init_tuner_input); + else if (input_line >= 6) + saa717x_write_regs(client, reg_init_svideo_input); + else + saa717x_write_regs(client, reg_init_composite_input); + } + + return 0; +} + +static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + struct saa717x_state *decoder = i2c_get_clientdata(client); + + v4l_dbg(1, debug, client, "IOCTL: %08x\n", cmd); + + switch (cmd) { + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + return saa717x_set_audio_clock_freq(client, *(u32 *)arg); + + case VIDIOC_G_CTRL: + return saa717x_get_v4lctrl(client, (struct v4l2_control *)arg); + + case VIDIOC_S_CTRL: + return saa717x_set_v4lctrl(client, (struct v4l2_control *)arg); + + case VIDIOC_QUERYCTRL: { + struct v4l2_queryctrl *qc = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++) + if (qc->id && qc->id == saa717x_qctrl[i].id) { + memcpy(qc, &saa717x_qctrl[i], sizeof(*qc)); + return 0; + } + return -EINVAL; + } + +#ifdef CONFIG_VIDEO_ADV_DEBUG + case VIDIOC_DBG_G_REGISTER: { + struct v4l2_register *reg = arg; + + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = saa717x_read(client, reg->reg); + break; + } + + case VIDIOC_DBG_S_REGISTER: { + struct v4l2_register *reg = arg; + u16 addr = reg->reg & 0xffff; + u8 val = reg->val & 0xff; + + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + saa717x_write(client, addr, val); + break; + } +#endif + + case VIDIOC_S_FMT: { + struct v4l2_format *fmt = (struct v4l2_format *)arg; + struct v4l2_pix_format *pix; + int prescale, h_scale, v_scale; + + pix = &fmt->fmt.pix; + v4l_dbg(1, debug, client, "decoder set size\n"); + + /* FIXME need better bounds checking here */ + if (pix->width < 1 || pix->width > 1440) + return -EINVAL; + if (pix->height < 1 || pix->height > 960) + return -EINVAL; + + /* scaling setting */ + /* NTSC and interlace only */ + prescale = SAA717X_NTSC_WIDTH / pix->width; + if (prescale == 0) + prescale = 1; + h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width; + /* interlace */ + v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height; + + /* Horizontal prescaling etc */ + set_h_prescale(client, 0, prescale); + set_h_prescale(client, 1, prescale); + + /* Horizontal scaling increment */ + /* TASK A */ + saa717x_write(client, 0x6C, (u8)(h_scale & 0xFF)); + saa717x_write(client, 0x6D, (u8)((h_scale >> 8) & 0xFF)); + /* TASK B */ + saa717x_write(client, 0xAC, (u8)(h_scale & 0xFF)); + saa717x_write(client, 0xAD, (u8)((h_scale >> 8) & 0xFF)); + + /* Vertical prescaling etc */ + set_v_scale(client, 0, v_scale); + set_v_scale(client, 1, v_scale); + + /* set video output size */ + /* video number of pixels at output */ + /* TASK A */ + saa717x_write(client, 0x5C, (u8)(pix->width & 0xFF)); + saa717x_write(client, 0x5D, (u8)((pix->width >> 8) & 0xFF)); + /* TASK B */ + saa717x_write(client, 0x9C, (u8)(pix->width & 0xFF)); + saa717x_write(client, 0x9D, (u8)((pix->width >> 8) & 0xFF)); + + /* video number of lines at output */ + /* TASK A */ + saa717x_write(client, 0x5E, (u8)(pix->height & 0xFF)); + saa717x_write(client, 0x5F, (u8)((pix->height >> 8) & 0xFF)); + /* TASK B */ + saa717x_write(client, 0x9E, (u8)(pix->height & 0xFF)); + saa717x_write(client, 0x9F, (u8)((pix->height >> 8) & 0xFF)); + break; + } + + case AUDC_SET_RADIO: + decoder->radio = 1; + break; + + case VIDIOC_S_STD: { + v4l2_std_id std = *(v4l2_std_id *) arg; + + v4l_dbg(1, debug, client, "decoder set norm "); + v4l_dbg(1, debug, client, "(not yet implementd)\n"); + + decoder->radio = 0; + decoder->std = std; + break; + } + + case VIDIOC_INT_G_AUDIO_ROUTING: { + struct v4l2_routing *route = arg; + + route->input = decoder->audio_input; + route->output = 0; + break; + } + + case VIDIOC_INT_S_AUDIO_ROUTING: { + struct v4l2_routing *route = arg; + + if (route->input < 3) { /* FIXME! --tadachi */ + decoder->audio_input = route->input; + v4l_dbg(1, debug, client, + "set decoder audio input to %d\n", + decoder->audio_input); + set_audio_regs(client, decoder); + break; + } + return -ERANGE; + } + + case VIDIOC_INT_S_VIDEO_ROUTING: { + struct v4l2_routing *route = arg; + int inp = route->input; + + return saa717x_set_video_input(client, decoder, inp); + } + + case VIDIOC_STREAMON: { + v4l_dbg(1, debug, client, "decoder enable output\n"); + decoder->enable = 1; + saa717x_write(client, 0x193, 0xa6); + break; + } + + case VIDIOC_STREAMOFF: { + v4l_dbg(1, debug, client, "decoder disable output\n"); + decoder->enable = 0; + saa717x_write(client, 0x193, 0x26); /* right? FIXME!--tadachi */ + break; + } + + /* change audio mode */ + case VIDIOC_S_TUNER: { + struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; + int audio_mode; + char *mes[4] = { + "MONO", "STEREO", "LANG1", "LANG2/SAP" + }; + + audio_mode = V4L2_TUNER_MODE_STEREO; + + switch (vt->audmode) { + case V4L2_TUNER_MODE_MONO: + audio_mode = TUNER_AUDIO_MONO; + break; + case V4L2_TUNER_MODE_STEREO: + audio_mode = TUNER_AUDIO_STEREO; + break; + case V4L2_TUNER_MODE_LANG2: + audio_mode = TUNER_AUDIO_LANG2; + break; + case V4L2_TUNER_MODE_LANG1: + audio_mode = TUNER_AUDIO_LANG1; + break; + } + + v4l_dbg(1, debug, client, "change audio mode to %s\n", + mes[audio_mode]); + decoder->tuner_audio_mode = audio_mode; + /* The registers are not changed here. */ + /* See DECODER_ENABLE_OUTPUT section. */ + set_audio_mode(client, decoder->tuner_audio_mode); + break; + } + + case VIDIOC_G_TUNER: { + struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; + int dual_f, stereo_f; + + if (decoder->radio) + break; + get_inf_dev_status(client, &dual_f, &stereo_f); + + v4l_dbg(1, debug, client, "DETECT==st:%d dual:%d\n", + stereo_f, dual_f); + + /* mono */ + if ((dual_f == 0) && (stereo_f == 0)) { + vt->rxsubchans = V4L2_TUNER_SUB_MONO; + v4l_dbg(1, debug, client, "DETECT==MONO\n"); + } + + /* stereo */ + if (stereo_f == 1) { + if (vt->audmode == V4L2_TUNER_MODE_STEREO || + vt->audmode == V4L2_TUNER_MODE_LANG1) { + vt->rxsubchans = V4L2_TUNER_SUB_STEREO; + v4l_dbg(1, debug, client, "DETECT==ST(ST)\n"); + } else { + vt->rxsubchans = V4L2_TUNER_SUB_MONO; + v4l_dbg(1, debug, client, "DETECT==ST(MONO)\n"); + } + } + + /* dual */ + if (dual_f == 1) { + if (vt->audmode == V4L2_TUNER_MODE_LANG2) { + vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO; + v4l_dbg(1, debug, client, "DETECT==DUAL1\n"); + } else { + vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO; + v4l_dbg(1, debug, client, "DETECT==DUAL2\n"); + } + } + break; + } + + case VIDIOC_LOG_STATUS: + /* not yet implemented */ + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + + +/* i2c implementation */ + +/* ----------------------------------------------------------------------- */ +static int saa717x_probe(struct i2c_client *client) +{ + struct saa717x_state *decoder; + u8 id = 0; + char *p = ""; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + snprintf(client->name, sizeof(client->name) - 1, "saa717x"); + + if (saa717x_write(client, 0x5a4, 0xfe) && + saa717x_write(client, 0x5a5, 0x0f) && + saa717x_write(client, 0x5a6, 0x00) && + saa717x_write(client, 0x5a7, 0x01)) + id = saa717x_read(client, 0x5a0); + if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) { + v4l_dbg(1, debug, client, "saa717x not found (id=%02x)\n", id); + return -ENODEV; + } + if (id == 0xc2) + p = "saa7173"; + else if (id == 0x32) + p = "saa7174A"; + else if (id == 0x6c) + p = "saa7174HL"; + else + p = "saa7171"; + v4l_info(client, "%s found @ 0x%x (%s)\n", p, + client->addr << 1, client->adapter->name); + + decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL); + i2c_set_clientdata(client, decoder); + + if (decoder == NULL) + return -ENOMEM; + decoder->std = V4L2_STD_NTSC; + decoder->input = -1; + decoder->enable = 1; + + /* tune these parameters */ + decoder->bright = 0x80; + decoder->contrast = 0x44; + decoder->sat = 0x40; + decoder->hue = 0x00; + + /* FIXME!! */ + decoder->playback = 0; /* initially capture mode used */ + decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */ + + decoder->audio_input = 2; /* FIXME!! */ + + decoder->tuner_audio_mode = TUNER_AUDIO_STEREO; + /* set volume, bass and treble */ + decoder->audio_main_vol_l = 6; + decoder->audio_main_vol_r = 6; + decoder->audio_main_bass = 0; + decoder->audio_main_treble = 0; + decoder->audio_main_mute = 0; + decoder->audio_main_balance = 32768; + /* normalize (24 to -40 (not -84) -> 65535 to 0) */ + decoder->audio_main_volume = + (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40)); + + v4l_dbg(1, debug, client, "writing init values\n"); + + /* FIXME!! */ + saa717x_write_regs(client, reg_init_initialize); + set_video_output_level_regs(client, decoder); + /* set bass,treble to 0db 20041101 K.Ohta */ + decoder->audio_main_bass = 0; + decoder->audio_main_treble = 0; + set_audio_regs(client, decoder); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(2*HZ); + return 0; +} + +static int saa717x_remove(struct i2c_client *client) +{ + kfree(i2c_get_clientdata(client)); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa717x", + .driverid = I2C_DRIVERID_SAA717X, + .command = saa717x_command, + .probe = saa717x_probe, + .remove = saa717x_remove, + .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, +}; From 9950c1b5b4b86d4aae12853c2f0a0ef11d976764 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Apr 2008 11:29:44 -0300 Subject: [PATCH 277/452] V4L/DVB (7537): cx88/saa7134: Fix: avoid OOPS on module unload If frontend is not attached, both cx88-dvb and saa7134-dvb don't register DVB. However, dvb unregister were inconditionally called. Due to that, an OOPS is generated. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 3 ++- drivers/media/video/saa7134/saa7134-dvb.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 8fc929eb47ba..e83d9869e68b 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -951,7 +951,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) struct cx8802_dev *dev = drv->core->dvbdev; /* dvb */ - videobuf_dvb_unregister(&dev->dvb); + if (dev->dvb.frontend) + videobuf_dvb_unregister(&dev->dvb); vp3054_i2c_remove(dev); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 5c84f45ecbe2..e5c3569dd2c8 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1302,7 +1302,8 @@ static int dvb_fini(struct saa7134_dev *dev) } } } - videobuf_dvb_unregister(&dev->dvb); + if (dev->dvb.frontend) + videobuf_dvb_unregister(&dev->dvb); return 0; } From 78e92006f410a4044f8c1760c25ac9d11d259aa2 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 9 Apr 2008 19:13:13 -0300 Subject: [PATCH 278/452] V4L/DVB (7538): Adds selectable adapter numbers as per module option The adapter_nr module options can be used to allocate static adapter numbers on a driver level. It avoids problems with changing DVB apapter numbers after warm/cold boot or device unplugging and repluging. Each driver holds DVB_MAX_ADAPTER long array of the preferred order of adapter numbers. options dvb-usb-dib0700 adapter_nr=7,6,5,4,3,2,1,0 would result in a reversed allocation of adapter numbers. With adapter_nr=2,5 it tries first to get adapter number 2 and 5. If both are already in use it will allocate the lowest free adapter number. Signed-off-by: Janne Grunau Acked-by: Hermann Pitton Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop.c | 8 +++- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 7 +++- drivers/media/dvb/cinergyT2/cinergyT2.c | 7 +++- drivers/media/dvb/dvb-core/dvbdev.c | 41 ++++++++++++++----- drivers/media/dvb/dvb-core/dvbdev.h | 13 +++++- drivers/media/dvb/dvb-usb/a800.c | 6 ++- drivers/media/dvb/dvb-usb/af9005.c | 5 ++- drivers/media/dvb/dvb-usb/au6610.c | 6 ++- drivers/media/dvb/dvb-usb/cxusb.c | 29 +++++++++---- drivers/media/dvb/dvb-usb/dib0700_core.c | 5 ++- drivers/media/dvb/dvb-usb/dibusb-mb.c | 14 +++++-- drivers/media/dvb/dvb-usb/dibusb-mc.c | 5 ++- drivers/media/dvb/dvb-usb/digitv.c | 8 +++- drivers/media/dvb/dvb-usb/dtt200u.c | 17 +++++--- drivers/media/dvb/dvb-usb/dvb-usb-common.h | 3 +- drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | 9 ++-- drivers/media/dvb/dvb-usb/dvb-usb-init.c | 16 ++++---- drivers/media/dvb/dvb-usb/dvb-usb.h | 5 ++- drivers/media/dvb/dvb-usb/gl861.c | 6 ++- drivers/media/dvb/dvb-usb/gp8psk.c | 5 ++- drivers/media/dvb/dvb-usb/m920x.c | 22 ++++++---- drivers/media/dvb/dvb-usb/nova-t-usb2.c | 5 ++- drivers/media/dvb/dvb-usb/opera1.c | 6 ++- drivers/media/dvb/dvb-usb/ttusb2.c | 8 +++- drivers/media/dvb/dvb-usb/umt-010.c | 5 ++- drivers/media/dvb/dvb-usb/vp702x.c | 5 ++- drivers/media/dvb/dvb-usb/vp7045.c | 6 ++- drivers/media/dvb/pluto2/pluto2.c | 5 ++- drivers/media/dvb/ttpci/av7110.c | 4 +- drivers/media/dvb/ttpci/budget-core.c | 7 +++- .../media/dvb/ttusb-budget/dvb-ttusb-budget.c | 8 +++- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 6 ++- drivers/media/video/cx23885/cx23885-dvb.c | 4 +- drivers/media/video/cx88/cx88-dvb.c | 5 ++- drivers/media/video/saa7134/saa7134-dvb.c | 5 ++- drivers/media/video/videobuf-dvb.c | 6 ++- include/media/videobuf-dvb.h | 3 +- 37 files changed, 242 insertions(+), 83 deletions(-) diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index 205146c24129..5f79c8dc3836 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c @@ -49,6 +49,8 @@ module_param_named(debug, b2c2_flexcop_debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS); #undef DEBSTATUS +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* global zero for ibi values */ flexcop_ibi_value ibi_zero; @@ -66,8 +68,10 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) static int flexcop_dvb_init(struct flexcop_device *fc) { - int ret; - if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) { + int ret = dvb_register_adapter(&fc->dvb_adapter, + "FlexCop Digital TV device", fc->owner, + fc->dev, adapter_nr); + if (ret < 0) { err("error registering DVB adapter"); return ret; } diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index a39439b5f04c..6afbfbbef0ce 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -40,6 +40,8 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk( args... ) \ do { \ if (debug) printk(KERN_DEBUG args); \ @@ -717,7 +719,10 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) { int result; - if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) { + result = dvb_register_adapter(&card->dvb_adapter, card->card_name, + THIS_MODULE, &card->bt->dev->dev, + adapter_nr); + if (result < 0) { printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result); return result; } diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 29b2459e0b21..f5010e8671b8 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -58,6 +58,8 @@ static int debug; module_param_named(debug, debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk(level, args...) \ do { \ if ((debug & level)) { \ @@ -938,7 +940,10 @@ static int cinergyt2_probe (struct usb_interface *intf, return -ENOMEM; } - if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) { + err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, + THIS_MODULE, &cinergyt2->udev->dev, + adapter_nr); + if (err < 0) { kfree(cinergyt2); return err; } diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 0a2897bc9873..8b56d929f7fd 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -49,7 +49,6 @@ static const char * const dnames[] = { "net", "osd" }; -#define DVB_MAX_ADAPTERS 8 #define DVB_MAX_IDS 4 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) @@ -262,18 +261,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev) } EXPORT_SYMBOL(dvb_unregister_device); +static int dvbdev_check_free_adapter_num(int num) +{ + struct list_head *entry; + list_for_each(entry, &dvb_adapter_list) { + struct dvb_adapter *adap; + adap = list_entry(entry, struct dvb_adapter, list_head); + if (adap->num == num) + return 0; + } + return 1; +} static int dvbdev_get_free_adapter_num (void) { int num = 0; while (num < DVB_MAX_ADAPTERS) { - struct dvb_adapter *adap; - list_for_each_entry(adap, &dvb_adapter_list, list_head) - if (adap->num == num) - goto skip; - return num; -skip: + if (dvbdev_check_free_adapter_num(num)) + return num; num++; } @@ -281,13 +287,28 @@ skip: } -int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device) +int dvb_register_adapter(struct dvb_adapter *adap, const char *name, + struct module *module, struct device *device, + short *adapter_nums) { - int num; + int i, num; mutex_lock(&dvbdev_register_lock); - if ((num = dvbdev_get_free_adapter_num ()) < 0) { + for (i = 0; i < DVB_MAX_ADAPTERS; ++i) { + num = adapter_nums[i]; + if (num >= 0 && num < DVB_MAX_ADAPTERS) { + /* use the one the driver asked for */ + if (dvbdev_check_free_adapter_num(num)) + break; + } else { + num = dvbdev_get_free_adapter_num(); + break; + } + num = -1; + } + + if (num < 0) { mutex_unlock(&dvbdev_register_lock); return -ENFILE; } diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index 6dff10ebf470..5f9a737c6de1 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h @@ -31,6 +31,10 @@ #define DVB_MAJOR 212 +#define DVB_MAX_ADAPTERS 8 + +#define DVB_UNSET (-1) + #define DVB_DEVICE_VIDEO 0 #define DVB_DEVICE_AUDIO 1 #define DVB_DEVICE_SEC 2 @@ -41,6 +45,11 @@ #define DVB_DEVICE_NET 7 #define DVB_DEVICE_OSD 8 +#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ + static short adapter_nr[] = \ + {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \ + module_param_array(adapter_nr, short, NULL, 0444); \ + MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers") struct dvb_adapter { int num; @@ -78,7 +87,9 @@ struct dvb_device { }; -extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device); +extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name, + struct module *module, struct device *device, + short *adapter_nums); extern int dvb_unregister_adapter (struct dvb_adapter *adap); extern int dvb_register_device (struct dvb_adapter *adap, diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index a6c5f19f680d..dc8c8784caa8 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c @@ -18,6 +18,9 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_rc(args...) dprintk(debug,0x01,args) static int a800_power_ctrl(struct dvb_usb_device *d, int onoff) @@ -94,7 +97,8 @@ static struct dvb_usb_device_properties a800_properties; static int a800_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &a800_properties, + THIS_MODULE, NULL, adapter_nr); } /* do not change the order of the ID table */ diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c index e7f76f515b4f..cfe71feefcad 100644 --- a/drivers/media/dvb/dvb-usb/af9005.c +++ b/drivers/media/dvb/dvb-usb/af9005.c @@ -39,6 +39,8 @@ int dvb_usb_af9005_dump_eeprom = 0; module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0); MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* remote control decoder */ int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event, int *state); @@ -1020,7 +1022,8 @@ static struct dvb_usb_device_properties af9005_properties; static int af9005_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL); + return dvb_usb_device_init(intf, &af9005_properties, + THIS_MODULE, NULL, adapter_nr); } static struct usb_device_id af9005_usb_table[] = { diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c index f3ff81314696..2ccb90fa60c8 100644 --- a/drivers/media/dvb/dvb-usb/au6610.c +++ b/drivers/media/dvb/dvb-usb/au6610.c @@ -19,6 +19,8 @@ static int dvb_usb_au6610_debug; module_param_named(debug, dvb_usb_au6610_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { @@ -163,7 +165,9 @@ static int au6610_probe(struct usb_interface *intf, if (intf->num_altsetting < AU6610_ALTSETTING_COUNT) return -ENODEV; - if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d, + adapter_nr); + if (ret == 0) { alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING); if (alt == NULL) { diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 4e5118dfe2e0..c4b00660c65f 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -40,6 +40,9 @@ static int dvb_usb_cxusb_debug; module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args) #define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \ dprintk(dvb_usb_cxusb_debug,0x01,args) @@ -723,16 +726,24 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope static int cxusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) { + if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, + &cxusb_bluebird_nano2_needsfirmware_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; - } return -EINVAL; } diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 4b3836e63be9..595a04696c87 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -17,6 +17,8 @@ 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)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* expecting rx buffer: request data[0] data[1] ... data[2] */ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) { @@ -279,7 +281,8 @@ static int dib0700_probe(struct usb_interface *intf, struct dvb_usb_device *dev; for (i = 0; i < dib0700_device_count; i++) - if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0) + if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, + &dev, adapter_nr) == 0) { dib0700_rc_setup(dev); return 0; diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 043cadae0859..eeef50bff4f9 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -14,6 +14,8 @@ */ #include "dibusb.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) { struct dvb_usb_adapter *adap = fe->dvb->priv; @@ -107,10 +109,14 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties; static int dibusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0) + if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &dibusb2_0b_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; return -EINVAL; diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c index e7ea3e753d6d..059cec955318 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -14,13 +14,16 @@ */ #include "dibusb.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* USB Driver stuff */ static struct dvb_usb_device_properties dibusb_mc_properties; static int dibusb_mc_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE, + NULL, adapter_nr); } /* do not change the order of the ID table */ diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 3acbda4aa27e..b545cf3eab2e 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -20,6 +20,9 @@ static int dvb_usb_digitv_debug; module_param_named(debug,dvb_usb_digitv_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args) static int digitv_ctrl_msg(struct dvb_usb_device *d, @@ -256,8 +259,9 @@ static int digitv_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct dvb_usb_device *d; - int ret; - if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) { + int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d, + adapter_nr); + if (ret == 0) { u8 b[4] = { 0 }; if (d != NULL) { /* do that only when the firmware is loaded */ diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index d86cf9bee91c..81a6cbf60160 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c @@ -18,6 +18,8 @@ int dvb_usb_dtt200u_debug; module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) { u8 b = SET_INIT; @@ -101,11 +103,16 @@ static struct dvb_usb_device_properties wt220u_miglia_properties; static int dtt200u_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0) + if (0 == dvb_usb_device_init(intf, &dtt200u_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &wt220u_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &wt220u_fc_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; return -ENODEV; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h index 35ab68f6dcf6..6b7b2a89242e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h @@ -40,7 +40,8 @@ extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap); extern int dvb_usb_i2c_init(struct dvb_usb_device *); extern int dvb_usb_i2c_exit(struct dvb_usb_device *); -extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap); +extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, + short *adapter_nums); extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap); extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap); extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c index 4561a672da92..ce8cd0c5d831 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c @@ -77,12 +77,13 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) return dvb_usb_ctrl_feed(dvbdmxfeed,0); } -int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap) +int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums) { - int ret; + int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name, + adap->dev->owner, &adap->dev->udev->dev, + adapter_nums); - if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name, - adap->dev->owner, &adap->dev->udev->dev)) < 0) { + if (ret < 0) { deb_info("dvb_register_adapter failed: error %d", ret); goto err; } diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index cdd717c3fe45..e331db8c77b2 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -26,7 +26,7 @@ static int dvb_usb_force_pid_filter_usage; module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444); MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0)."); -static int dvb_usb_adapter_init(struct dvb_usb_device *d) +static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) { struct dvb_usb_adapter *adap; int ret,n; @@ -72,7 +72,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d) } if ((ret = dvb_usb_adapter_stream_init(adap)) || - (ret = dvb_usb_adapter_dvb_init(adap)) || + (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) || (ret = dvb_usb_adapter_frontend_init(adap))) { return ret; } @@ -122,7 +122,7 @@ static int dvb_usb_exit(struct dvb_usb_device *d) return 0; } -static int dvb_usb_init(struct dvb_usb_device *d) +static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums) { int ret = 0; @@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_device *d) dvb_usb_device_power_ctrl(d, 1); if ((ret = dvb_usb_i2c_init(d)) || - (ret = dvb_usb_adapter_init(d))) { + (ret = dvb_usb_adapter_init(d, adapter_nums))) { dvb_usb_exit(d); return ret; } @@ -213,8 +213,10 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff) /* * USB */ -int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_properties - *props, struct module *owner,struct dvb_usb_device **du) +int dvb_usb_device_init(struct usb_interface *intf, + struct dvb_usb_device_properties *props, + struct module *owner, struct dvb_usb_device **du, + short *adapter_nums) { struct usb_device *udev = interface_to_usbdev(intf); struct dvb_usb_device *d = NULL; @@ -254,7 +256,7 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_proper if (du != NULL) *du = d; - ret = dvb_usb_init(d); + ret = dvb_usb_init(d, adapter_nums); if (ret == 0) info("%s successfully initialized and connected.",desc->name); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index d1b3c7b81fff..b1de0f7e26e8 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -372,7 +372,10 @@ struct dvb_usb_device { void *priv; }; -extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_device_properties *, struct module *, struct dvb_usb_device **); +extern int dvb_usb_device_init(struct usb_interface *, + struct dvb_usb_device_properties *, + struct module *, struct dvb_usb_device **, + short *adapter_nums); extern void dvb_usb_device_exit(struct usb_interface *); /* the generic read/write method for device control */ diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c index 6b99d9f4d5b3..0a8ac64a4e33 100644 --- a/drivers/media/dvb/dvb-usb/gl861.c +++ b/drivers/media/dvb/dvb-usb/gl861.c @@ -16,6 +16,8 @@ static int dvb_usb_gl861_debug; module_param_named(debug,dvb_usb_gl861_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { @@ -140,7 +142,9 @@ static int gl861_probe(struct usb_interface *intf, if (intf->num_altsetting < 2) return -ENODEV; - if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d, + adapter_nr); + if (ret == 0) { alt = usb_altnum_to_altsetting(intf, 0); if (alt == NULL) { diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index 83e8535014c6..9a942afaf0af 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c @@ -22,6 +22,8 @@ int dvb_usb_gp8psk_debug; module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret = 0,try = 0; @@ -190,7 +192,8 @@ static int gp8psk_usb_probe(struct usb_interface *intf, { int ret; struct usb_device *udev = interface_to_usbdev(intf); - ret = dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL); + ret = dvb_usb_device_init(intf, &gp8psk_properties, + THIS_MODULE, NULL, adapter_nr); if (ret == 0) { info("found Genpix USB device pID = %x (hex)", le16_to_cpu(udev->descriptor.idProduct)); diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index 29ec2b967742..a12e6f784fda 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c @@ -22,6 +22,8 @@ static int dvb_usb_m920x_debug; module_param_named(debug,dvb_usb_m920x_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid); static inline int m920x_read(struct usb_device *udev, u8 request, u16 value, @@ -618,27 +620,31 @@ static int m920x_probe(struct usb_interface *intf, * multi-tuner device */ - if ((ret = dvb_usb_device_init(intf, &megasky_properties, - THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &megasky_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { rc_init_seq = megasky_rc_init; goto found; } - if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, - THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { /* No remote control, so no rc_init_seq */ goto found; } /* This configures both tuners on the TV Walker Twin */ - if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties, - THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &tvwalkertwin_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { rc_init_seq = tvwalkertwin_rc_init; goto found; } - if ((ret = dvb_usb_device_init(intf, &dposh_properties, - THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &dposh_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { /* Remote controller not supported yet. */ goto found; } diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index badc468170ea..07fb843c7c2b 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -15,6 +15,8 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_rc(args...) dprintk(debug,0x01,args) #define deb_ee(args...) dprintk(debug,0x02,args) @@ -142,7 +144,8 @@ static struct dvb_usb_device_properties nova_t_properties; static int nova_t_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &nova_t_properties, + THIS_MODULE, NULL, adapter_nr); } /* do not change the order of the ID table */ diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index 302cc67407c3..0eef5fe094e1 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -46,6 +46,9 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + + static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value, u8 * data, u16 len, int flags) { @@ -548,7 +551,8 @@ static int opera1_probe(struct usb_interface *intf, return -EINVAL; } - if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, NULL) != 0) + if (0 != dvb_usb_device_init(intf, &opera1_properties, + THIS_MODULE, NULL, adapter_nr)) return -EINVAL; return 0; } diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c index 0eb33378254b..706687c78506 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -37,6 +37,8 @@ static int dvb_usb_ttusb2_debug; module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + struct ttusb2_state { u8 id; }; @@ -181,8 +183,10 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400; static int ttusb2_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf, &ttusb2_properties, THIS_MODULE, NULL) == 0 || - dvb_usb_device_init(intf, &ttusb2_properties_s2400, THIS_MODULE, NULL) == 0) + if (0 == dvb_usb_device_init(intf, &ttusb2_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400, + THIS_MODULE, NULL, adapter_nr)) return 0; return -ENODEV; } diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c index 0dcab3d4e236..9e7653bb3b66 100644 --- a/drivers/media/dvb/dvb-usb/umt-010.c +++ b/drivers/media/dvb/dvb-usb/umt-010.c @@ -13,6 +13,8 @@ #include "mt352.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int umt_mt352_demod_init(struct dvb_frontend *fe) { static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d }; @@ -75,7 +77,8 @@ static struct dvb_usb_device_properties umt_properties; static int umt_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0) + if (0 == dvb_usb_device_init(intf, &umt_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; return -EINVAL; } diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index e553c139ac44..986fff9a5ba8 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -21,6 +21,8 @@ int dvb_usb_vp702x_debug; module_param_named(debug,dvb_usb_vp702x_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + struct vp702x_state { int pid_filter_count; int pid_filter_can_bypass; @@ -238,7 +240,8 @@ static struct dvb_usb_device_properties vp702x_properties; static int vp702x_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &vp702x_properties, + THIS_MODULE, NULL, adapter_nr); } static struct usb_device_id vp702x_usb_table [] = { diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index c172babf59bb..acb345504e0d 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -18,6 +18,9 @@ static int dvb_usb_vp7045_debug; module_param_named(debug,dvb_usb_vp7045_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args) #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args) #define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args) @@ -219,7 +222,8 @@ static struct dvb_usb_device_properties vp7045_properties; static int vp7045_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &vp7045_properties, + THIS_MODULE, NULL, adapter_nr); } static struct usb_device_id vp7045_usb_table [] = { diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index 08a2599ed74a..960ed5763ae1 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -39,6 +39,8 @@ #include "dvbdev.h" #include "tda1004x.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define DRIVER_NAME "pluto2" #define REG_PIDn(n) ((n) << 2) /* PID n pattern registers */ @@ -662,7 +664,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, goto err_pluto_hw_exit; /* dvb */ - ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev); + ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, + THIS_MODULE, &pdev->dev, adapter_nr); if (ret < 0) goto err_i2c_del_adapter; diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 78919b9e14dc..747e7f1a6267 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -112,6 +112,8 @@ MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: module_param(tv_standard, int, 0444); MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static void restart_feeds(struct av7110 *av7110); static int av7110_num; @@ -2461,7 +2463,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev, goto err_kfree_0; ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name, - THIS_MODULE, &dev->pci->dev); + THIS_MODULE, &dev->pci->dev, adapter_nr); if (ret < 0) goto err_put_firmware_1; diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 06bbce42fcd7..18cac4b12ab2 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -57,6 +57,8 @@ module_param_named(bufsize, dma_buffer_size, int, 0444); MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off)."); MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /**************************************************************************** * TT budget / WinTV Nova ****************************************************************************/ @@ -471,9 +473,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, budget->buffer_width, budget->buffer_height); printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size); - if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) { + ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, + owner, &budget->dev->pci->dev, adapter_nr); + if (ret < 0) return ret; - } /* set dd1 stream a & b */ saa7146_write(dev, DD1_STREAM_B, 0x00000000); diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 317eccbe5c66..46dc4a3fcb6c 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -56,10 +56,11 @@ */ static int debug; - module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0) #define ISO_BUF_COUNT 4 @@ -1669,7 +1670,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i mutex_unlock(&ttusb->semi2c); - if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) { + result = dvb_register_adapter(&ttusb->adapter, + "Technotrend/Hauppauge Nova-USB", + THIS_MODULE, &udev->dev, adapter_nr); + if (result < 0) { ttusb_free_iso_urbs(ttusb); kfree(ttusb); return result; diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 95110c483312..42eee04daa5d 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -52,6 +52,8 @@ MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)"); module_param(enable_rc, int, 0644); MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk if (debug) printk #define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB" @@ -1437,7 +1439,9 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) dprintk("%s\n", __func__); if ((result = dvb_register_adapter(&dec->adapter, - dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) { + dec->model_name, THIS_MODULE, + &dec->udev->dev, + adapter_nr)) < 0) { printk("%s: dvb_register_adapter failed: error %d\n", __func__, result); diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 74baa28d16ab..1a720abbd066 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -54,6 +54,8 @@ static unsigned int alt_tuner; module_param(alt_tuner, int, 0644); MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* ------------------------------------------------------------------ */ static int dvb_buf_setup(struct videobuf_queue *q, @@ -333,7 +335,7 @@ static int dvb_register(struct cx23885_tsport *port) /* register everything */ return videobuf_dvb_register(&port->dvb, THIS_MODULE, port, - &dev->pci->dev); + &dev->pci->dev, adapter_nr); } int cx23885_dvb_register(struct cx23885_tsport *port) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index e83d9869e68b..fda7334d934b 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -58,6 +58,8 @@ static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk(level,fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) @@ -862,7 +864,8 @@ static int dvb_register(struct cx8802_dev *dev) cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); /* register everything */ - return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); + return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, + &dev->pci->dev, adapter_nr); } /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index e5c3569dd2c8..73154c1a0239 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -65,6 +65,8 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk(fmt, arg...) do { if (debug) \ printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0) @@ -1257,7 +1259,8 @@ static int dvb_init(struct saa7134_dev *dev) } /* register everything else */ - ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); + ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, + adapter_nr); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 4ba8b7db7fda..0f8542a4c71a 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -138,14 +138,16 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed) int videobuf_dvb_register(struct videobuf_dvb *dvb, struct module *module, void *adapter_priv, - struct device *device) + struct device *device, + short *adapter_nr) { int result; mutex_init(&dvb->lock); /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device); + result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device, + adapter_nr); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", dvb->name, result); diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h index 8233cafdeef6..b77748696329 100644 --- a/include/media/videobuf-dvb.h +++ b/include/media/videobuf-dvb.h @@ -27,7 +27,8 @@ struct videobuf_dvb { int videobuf_dvb_register(struct videobuf_dvb *dvb, struct module *module, void *adapter_priv, - struct device *device); + struct device *device, + short *adapter_nr); void videobuf_dvb_unregister(struct videobuf_dvb *dvb); /* From ad0ebb96c220c461386e9a765fca3daf5590d01e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:37:52 -0300 Subject: [PATCH 279/452] V4L/DVB (7540): em28xx: convert to use videobuf-vmalloc The usage of videobuf-vmalloc allows to cleanup em28xx logic. Also, it reduced its size by about 5.42% on i386 arch (and about 7.5% on x86_64): 39113 4876 40 44029 abfd old/em28xx.ko 36731 4868 40 41639 a2a7 /home/v4l/master/v4l/em28xx.ko Also, the preliminary tests, made on a single core 1.5 MHz Centrino showed that CPU usage reduced from 42%-75% to 28%-33% (reports from "top") command. A test with time command presented an even better result: This is the performance tests I did, running code_example to get 1,000 frames @29.995 Hz (about 35 seconds of stream), tested on a i386 machine, running at 1,5GHz: The old driver: $ time -f "%E: %Us User time, %Ss Kernel time, %P CPU used" ./capture_example 0:34.21: 8.22s User time, 25.16s Kernel time, 97% CPU used The videobuf-based driver: $ time -f "%E: %Us User time, %Ss Kernel time, %P CPU used" ./capture_example 0:35.36: 0.01s User time, 0.05s Kernel time, 0% CPU used Conclusion: The time consumption to receive the stream where reduced from about 33.38 seconds to 0.05 seconds. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 417 ------- drivers/media/video/em28xx/em28xx-video.c | 1202 +++++++++++++-------- drivers/media/video/em28xx/em28xx.h | 94 +- 3 files changed, 813 insertions(+), 900 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 9aa96f1713a1..95bc18d0e780 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -49,87 +49,10 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __func__ , ##arg); } while (0) -static unsigned int isoc_debug; -module_param(isoc_debug,int,0644); -MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); - -#define em28xx_isocdbg(fmt, arg...) do {\ - if (isoc_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - static int alt = EM28XX_PINOUT; module_param(alt, int, 0644); MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); - -/* - * em28xx_request_buffers() - * allocate a number of buffers - */ -u32 em28xx_request_buffers(struct em28xx *dev, u32 count) -{ - const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */ - void *buff = NULL; - u32 i; - em28xx_coredbg("requested %i buffers with size %zi\n", - count, imagesize); - if (count > EM28XX_NUM_FRAMES) - count = EM28XX_NUM_FRAMES; - - dev->num_frames = count; - while (dev->num_frames > 0) { - if ((buff = vmalloc_32(dev->num_frames * imagesize))) { - memset(buff, 0, dev->num_frames * imagesize); - break; - } - dev->num_frames--; - } - - for (i = 0; i < dev->num_frames; i++) { - dev->frame[i].bufmem = buff + i * imagesize; - dev->frame[i].buf.index = i; - dev->frame[i].buf.m.offset = i * imagesize; - dev->frame[i].buf.length = dev->frame_size; - dev->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dev->frame[i].buf.sequence = 0; - dev->frame[i].buf.field = V4L2_FIELD_NONE; - dev->frame[i].buf.memory = V4L2_MEMORY_MMAP; - dev->frame[i].buf.flags = 0; - } - return dev->num_frames; -} - -/* - * em28xx_queue_unusedframes() - * add all frames that are not currently in use to the inbuffer queue - */ -void em28xx_queue_unusedframes(struct em28xx *dev) -{ - unsigned long lock_flags; - u32 i; - - for (i = 0; i < dev->num_frames; i++) - if (dev->frame[i].state == F_UNUSED) { - dev->frame[i].state = F_QUEUED; - spin_lock_irqsave(&dev->queue_lock, lock_flags); - list_add_tail(&dev->frame[i].frame, &dev->inqueue); - spin_unlock_irqrestore(&dev->queue_lock, lock_flags); - } -} - -/* - * em28xx_release_buffers() - * free frame buffers - */ -void em28xx_release_buffers(struct em28xx *dev) -{ - if (dev->num_frames) { - vfree(dev->frame[0].bufmem); - dev->num_frames = 0; - } -} - /* * em28xx_read_reg_req() * reads data from the usb device specifying bRequest @@ -469,346 +392,6 @@ int em28xx_resolution_set(struct em28xx *dev) return em28xx_scaler_set(dev, dev->hscale, dev->vscale); } - -/******************* isoc transfer handling ****************************/ - -#ifdef ENABLE_DEBUG_ISOC_FRAMES -static void em28xx_isoc_dump(struct urb *urb) -{ - int len = 0; - int ntrans = 0; - int i; - - printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n", - urb->start_frame, urb->number_of_packets, - urb->error_count); - for (i = 0; i < urb->number_of_packets; i++) { - unsigned char *buf = - urb->transfer_buffer + - urb->iso_frame_desc[i].offset; - int alen = urb->iso_frame_desc[i].actual_length; - if (alen > 0) { - if (buf[0] == 0x88) { - ntrans++; - len += alen; - } else if (buf[0] == 0x22) { - printk(KERN_DEBUG - "= l=%d nt=%d bpp=%d\n", - len - 4 * ntrans, ntrans, - ntrans == 0 ? 0 : len / ntrans); - ntrans = 1; - len = alen; - } else - printk(KERN_DEBUG "!\n"); - } - printk(KERN_DEBUG " n=%d s=%d al=%d %x\n", i, - urb->iso_frame_desc[i].status, - urb->iso_frame_desc[i].actual_length, - (unsigned int) - *((unsigned char *)(urb->transfer_buffer + - urb->iso_frame_desc[i]. - offset))); - } -} -#endif - -static inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f, - unsigned long *lock_flags, unsigned char buf) -{ - if (!(buf & 0x01)) { - if ((*f)->state == F_GRABBING) { - /*previous frame is incomplete */ - if ((*f)->fieldbytesused < dev->field_size) { - (*f)->state = F_ERROR; - em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)", - dev->field_size-(*f)->fieldbytesused); - } else { - (*f)->state = F_DONE; - (*f)->buf.bytesused = dev->frame_size; - } - } - if ((*f)->state == F_DONE || (*f)->state == F_ERROR) { - /* move current frame to outqueue and get next free buffer from inqueue */ - spin_lock_irqsave(&dev-> queue_lock, *lock_flags); - list_move_tail(&(*f)->frame, &dev->outqueue); - if (!list_empty(&dev->inqueue)) - (*f) = list_entry(dev-> inqueue.next, - struct em28xx_frame_t,frame); - else - (*f) = NULL; - spin_unlock_irqrestore(&dev->queue_lock,*lock_flags); - } - if (!(*f)) { - em28xx_isocdbg ("new frame but no buffer is free"); - return -1; - } - do_gettimeofday(&(*f)->buf.timestamp); - (*f)->buf.sequence = ++dev->frame_count; - (*f)->buf.field = V4L2_FIELD_INTERLACED; - (*f)->state = F_GRABBING; - (*f)->buf.bytesused = 0; - (*f)->top_field = 1; - (*f)->fieldbytesused = 0; - } else { - /* acquiring bottom field */ - if ((*f)->state == F_GRABBING) { - if (!(*f)->top_field) { - (*f)->state = F_ERROR; - em28xx_isocdbg ("unexpected begin of bottom field; discarding it"); - } else if ((*f)-> fieldbytesused < dev->field_size - 172) { - (*f)->state = F_ERROR; - em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)", - dev->field_size-(*f)->fieldbytesused); - } else { - (*f)->top_field = 0; - (*f)->fieldbytesused = 0; - } - } - } - return (0); -} - -static inline void em28xx_isoc_video_copy(struct em28xx *dev, - struct em28xx_frame_t **f, unsigned char *buf, int len) -{ - void *fieldstart, *startwrite, *startread; - int linesdone, currlinedone, offset, lencopy,remain; - - if(dev->frame_size != (*f)->buf.length){ - em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length); - return; - } - - if ((*f)->fieldbytesused + len > dev->field_size) - len =dev->field_size - (*f)->fieldbytesused; - - if (buf[0] != 0x88 && buf[0] != 0x22) { - em28xx_isocdbg("frame is not complete\n"); - startread = buf; - len+=4; - } else - startread = buf + 4; - - remain = len; - - if ((*f)->top_field) - fieldstart = (*f)->bufmem; - else - fieldstart = (*f)->bufmem + dev->bytesperline; - - linesdone = (*f)->fieldbytesused / dev->bytesperline; - currlinedone = (*f)->fieldbytesused % dev->bytesperline; - offset = linesdone * dev->bytesperline * 2 + currlinedone; - startwrite = fieldstart + offset; - lencopy = dev->bytesperline - currlinedone; - lencopy = lencopy > remain ? remain : lencopy; - - memcpy(startwrite, startread, lencopy); - remain -= lencopy; - - while (remain > 0) { - startwrite += lencopy + dev->bytesperline; - startread += lencopy; - if (dev->bytesperline > remain) - lencopy = remain; - else - lencopy = dev->bytesperline; - - memcpy(startwrite, startread, lencopy); - remain -= lencopy; - } - - (*f)->fieldbytesused += len; -} - -/* - * em28xx_isoIrq() - * handles the incoming isoc urbs and fills the frames from our inqueue - */ -static void em28xx_isocIrq(struct urb *urb) -{ - struct em28xx *dev = urb->context; - int i, status; - struct em28xx_frame_t **f; - unsigned long lock_flags; - - if (!dev) - return; -#ifdef ENABLE_DEBUG_ISOC_FRAMES - if (isoc_debug>1) - em28xx_isoc_dump(urb); -#endif - - if (urb->status == -ENOENT) - return; - - f = &dev->frame_current; - - if (dev->stream == STREAM_INTERRUPT) { - dev->stream = STREAM_OFF; - if ((*f)) - (*f)->state = F_QUEUED; - em28xx_isocdbg("stream interrupted"); - wake_up_interruptible(&dev->wait_stream); - } - - if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) - return; - - if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) { - if (!(*f)) - (*f) = list_entry(dev->inqueue.next, - struct em28xx_frame_t, frame); - - for (i = 0; i < urb->number_of_packets; i++) { - unsigned char *buf = urb->transfer_buffer + - urb->iso_frame_desc[i].offset; - int len = urb->iso_frame_desc[i].actual_length - 4; - - if (urb->iso_frame_desc[i].status) { - em28xx_isocdbg("data error: [%d] len=%d, status=%d", i, - urb->iso_frame_desc[i].actual_length, - urb->iso_frame_desc[i].status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - if (urb->iso_frame_desc[i].actual_length <= 0) { - em28xx_isocdbg("packet %d is empty",i); - continue; - } - if (urb->iso_frame_desc[i].actual_length > - urb->iso_frame_desc[i].length) { - em28xx_isocdbg("packet bigger than packet size"); - continue; - } - /*new frame */ - if (buf[0] == 0x22 && buf[1] == 0x5a) { - em28xx_isocdbg("Video frame, length=%i!",len); - - if (em28xx_isoc_video(dev,f,&lock_flags,buf[2])) - break; - } else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) { - em28xx_isocdbg("VBI HEADER!!!"); - } - - /* actual copying */ - if ((*f)->state == F_GRABBING) { - em28xx_isoc_video_copy(dev,f,buf, len); - } - } - } - - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - - urb->status = 0; - if ((status = usb_submit_urb(urb, GFP_ATOMIC))) { - em28xx_errdev("resubmit of urb failed (error=%i)\n", status); - dev->state |= DEV_MISCONFIGURED; - } - wake_up_interruptible(&dev->wait_frame); - return; -} - -/* - * em28xx_uninit_isoc() - * deallocates the buffers and urbs allocated during em28xx_init_iosc() - */ -void em28xx_uninit_isoc(struct em28xx *dev) -{ - int i; - - for (i = 0; i < EM28XX_NUM_BUFS; i++) { - if (dev->urb[i]) { - usb_kill_urb(dev->urb[i]); - if (dev->transfer_buffer[i]) { - usb_buffer_free(dev->udev, - dev->urb[i]->transfer_buffer_length, - dev->transfer_buffer[i], - dev->urb[i]->transfer_dma); - } - usb_free_urb(dev->urb[i]); - } - dev->urb[i] = NULL; - dev->transfer_buffer[i] = NULL; - } - em28xx_capture_start(dev, 0); -} - -/* - * em28xx_init_isoc() - * allocates transfer buffers and submits the urbs for isoc transfer - */ -int em28xx_init_isoc(struct em28xx *dev) -{ - /* change interface to 3 which allows the biggest packet sizes */ - int i, errCode; - int sb_size; - - em28xx_set_alternate(dev); - sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size; - - /* reset streaming vars */ - dev->frame_current = NULL; - dev->frame_count = 0; - - /* allocate urbs */ - for (i = 0; i < EM28XX_NUM_BUFS; i++) { - struct urb *urb; - int j; - /* allocate transfer buffer */ - urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL); - if (!urb){ - em28xx_errdev("cannot alloc urb %i\n", i); - em28xx_uninit_isoc(dev); - return -ENOMEM; - } - dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, - GFP_KERNEL, - &urb->transfer_dma); - if (!dev->transfer_buffer[i]) { - em28xx_errdev - ("unable to allocate %i bytes for transfer buffer %i\n", - sb_size, i); - em28xx_uninit_isoc(dev); - usb_free_urb(urb); - return -ENOMEM; - } - memset(dev->transfer_buffer[i], 0, sb_size); - urb->dev = dev->udev; - urb->context = dev; - urb->pipe = usb_rcvisocpipe(dev->udev, 0x82); - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - urb->interval = 1; - urb->transfer_buffer = dev->transfer_buffer[i]; - urb->complete = em28xx_isocIrq; - urb->number_of_packets = EM28XX_NUM_PACKETS; - urb->transfer_buffer_length = sb_size; - for (j = 0; j < EM28XX_NUM_PACKETS; j++) { - urb->iso_frame_desc[j].offset = j * dev->max_pkt_size; - urb->iso_frame_desc[j].length = dev->max_pkt_size; - } - dev->urb[i] = urb; - } - - /* submit urbs */ - em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n", - EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size); - for (i = 0; i < EM28XX_NUM_BUFS; i++) { - errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL); - if (errCode) { - em28xx_errdev("submit of urb %i failed (error=%i)\n", i, - errCode); - em28xx_uninit_isoc(dev); - return errCode; - } - } - - return 0; -} - int em28xx_set_alternate(struct em28xx *dev) { int errCode, prev_alt = dev->alt; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index c7f074c6f226..182058ac8432 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -54,6 +54,21 @@ printk(KERN_INFO "%s %s :"fmt, \ dev->name, __func__ , ##arg); } while (0) +static unsigned int isoc_debug; +module_param(isoc_debug,int,0644); +MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); + +#define em28xx_isocdbg(fmt, arg...) do {\ + if (isoc_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) + +#define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ + +/* Limits minimum and default number of buffers */ +#define EM28XX_MIN_BUF 4 +#define EM28XX_DEF_BUF 8 + MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); @@ -107,6 +122,665 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { static struct usb_driver em28xx_usb_driver; +/* ------------------------------------------------------------------ + DMA and thread functions + ------------------------------------------------------------------*/ + +/* + * Announces that a buffer were filled and request the next + */ +static void inline buffer_filled (struct em28xx *dev, + struct em28xx_dmaqueue *dma_q, + struct em28xx_buffer *buf) +{ + /* Nobody is waiting something to be done, just return */ + if (!waitqueue_active(&buf->vb.done)) { + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + + printk(KERN_ERR "em28xx: buffer underrun at %ld\n", + jiffies); + + return; + } + + /* Advice that buffer was filled */ + em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); + buf->vb.state = VIDEOBUF_DONE; + buf->vb.field_count++; + do_gettimeofday(&buf->vb.ts); + + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); +} + +/* + * Identify the buffer header type and properly handles + */ +static void em28xx_copy_video(struct em28xx *dev, + struct em28xx_dmaqueue *dma_q, + struct em28xx_buffer *buf, + unsigned char *p, + unsigned char *outp, unsigned long len) +{ + void *fieldstart, *startwrite, *startread; + int linesdone, currlinedone, offset, lencopy,remain; + + if(dev->frame_size != buf->vb.size){ + em28xx_errdev("size %i and buf.length %lu are different!\n", + dev->frame_size, buf->vb.size); + return; + } + + if (dma_q->pos + len > buf->vb.size) + len = buf->vb.size - dma_q->pos; + + if (outp[0] != 0x88 && outp[0] != 0x22) { + em28xx_isocdbg("frame is not complete\n"); + len += 4; + } else + p +=4; + + startread = p; + remain = len; + + /* Interlaces frame */ + if (buf->top_field) + fieldstart = outp; + else + fieldstart = outp + dev->bytesperline; + + linesdone = dma_q->pos / dev->bytesperline; + currlinedone = dma_q->pos % dev->bytesperline; + offset = linesdone * dev->bytesperline * 2 + currlinedone; + startwrite = fieldstart + offset; + lencopy = dev->bytesperline - currlinedone; + lencopy = lencopy > remain ? remain : lencopy; + + if (__copy_to_user(startwrite, startread, lencopy) != 0) + em28xx_errdev("copy_to_user failed.\n"); + + remain -= lencopy; + + while (remain > 0) { + startwrite += lencopy + dev->bytesperline; + startread += lencopy; + if (dev->bytesperline > remain) + lencopy = remain; + else + lencopy = dev->bytesperline; + + if (__copy_to_user(startwrite, startread, lencopy) != 0) + em28xx_errdev("copy_to_user failed.\n"); + + remain -= lencopy; + } + + dma_q->pos += len; +} + +static void inline print_err_status (struct em28xx *dev, + int packet, int status) +{ + char *errmsg = "Unknown"; + + switch(status) { + case -ENOENT: + errmsg = "unlinked synchronuously"; + break; + case -ECONNRESET: + errmsg = "unlinked asynchronuously"; + break; + case -ENOSR: + errmsg = "Buffer error (overrun)"; + break; + case -EPIPE: + errmsg = "Stalled (device not responding)"; + break; + case -EOVERFLOW: + errmsg = "Babble (bad cable?)"; + break; + case -EPROTO: + errmsg = "Bit-stuff error (bad cable?)"; + break; + case -EILSEQ: + errmsg = "CRC/Timeout (could be anything)"; + break; + case -ETIME: + errmsg = "Device does not respond"; + break; + } + if (packet<0) { + em28xx_isocdbg("URB status %d [%s].\n", status, errmsg); + } else { + em28xx_isocdbg("URB packet %d, status %d [%s].\n", + packet, status, errmsg); + } +} + +/* + * video-buf generic routine to get the next available buffer + */ +static int inline get_next_buf (struct em28xx_dmaqueue *dma_q, + struct em28xx_buffer **buf) +{ + struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); + + if (list_empty(&dma_q->active)) { + em28xx_isocdbg("No active queue to serve\n"); + return 0; + } + + *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); + + return 1; +} + +/* + * Controls the isoc copy of each urb packet + */ +static inline int em28xx_isoc_copy(struct urb *urb, struct em28xx_buffer **buf) +{ + struct em28xx_dmaqueue *dma_q = urb->context; + struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); + unsigned char *outp = videobuf_to_vmalloc (&(*buf)->vb); + int i, len = 0, rc = 1; + char *p; + + if (!dev) + return 0; + + if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) + return 0; + + if (urb->status<0) { + print_err_status (dev,-1,urb->status); + if (urb->status == -ENOENT) + return 0; + } + + for (i = 0; i < urb->number_of_packets; i++) { + int status = urb->iso_frame_desc[i].status; + + if (status<0) { + print_err_status (dev,i,status); + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + } + + len=urb->iso_frame_desc[i].actual_length - 4; + + if (urb->iso_frame_desc[i].actual_length <= 0) { + em28xx_isocdbg("packet %d is empty",i); + continue; + } + if (urb->iso_frame_desc[i].actual_length > + dev->max_pkt_size) { + em28xx_isocdbg("packet bigger than packet size"); + continue; + } + + p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + + /* FIXME: incomplete buffer checks where removed to make + logic simpler. Impacts of those changes should be evaluated + */ + if (outp[0] == 0x22 && outp[1] == 0x5a) { + em28xx_isocdbg("Video frame, length=%i, %s", len, + (outp[2] == 1)? "top" : "botton"); + + if (outp[2] == 1) { + if ((*buf)->receiving) + buffer_filled (dev, dma_q, *buf); + + (*buf)->top_field = 1; + } else { + (*buf)->top_field = 0; + } + (*buf)->receiving = 1; + dma_q->pos = 0; + } else if (outp[0]==0x33 && outp[1]==0x95 && outp[2]==0x00) { + em28xx_isocdbg("VBI HEADER!!!"); + } + + em28xx_copy_video(dev, dma_q, *buf, p, outp, len); + + /* FIXME: Should add vbi copy */ + } + return rc; +} + +/* ------------------------------------------------------------------ + URB control + ------------------------------------------------------------------*/ + +/* + * IRQ callback, called by URB callback + */ +static void em28xx_irq_callback(struct urb *urb) +{ + struct em28xx_buffer *buf; + struct em28xx_dmaqueue *dma_q = urb->context; + struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); + int rc,i; + unsigned long flags; + + spin_lock_irqsave(&dev->slock,flags); + + buf=dev->isoc_ctl.buf; + + if (!buf) { + rc=get_next_buf (dma_q, &buf); + if (rc<=0) + goto ret; + } + + /* Copy data from URB */ + rc=em28xx_isoc_copy(urb, &buf); + + dev->isoc_ctl.buf=buf; +ret: + /* Reset urb buffers */ + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + urb->status = 0; + + if ((urb->status = usb_submit_urb(urb, GFP_ATOMIC))) { + em28xx_err("urb resubmit failed (error=%i)\n", + urb->status); + } + + if (rc >= 0) + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + spin_unlock_irqrestore(&dev->slock,flags); +} + +/* + * Stop and Deallocate URBs + */ +static void em28xx_uninit_isoc(struct em28xx *dev) +{ + struct urb *urb; + int i; + + dev->isoc_ctl.nfields=-1; + dev->isoc_ctl.buf=NULL; + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb=dev->isoc_ctl.urb[i]; + if (urb) { + usb_kill_urb(urb); + usb_unlink_urb(urb); + if (dev->isoc_ctl.transfer_buffer[i]) { + usb_buffer_free(dev->udev, + urb->transfer_buffer_length, + dev->isoc_ctl.transfer_buffer[i], + urb->transfer_dma); + } + usb_free_urb(urb); + dev->isoc_ctl.urb[i] = NULL; + } + dev->isoc_ctl.transfer_buffer[i] = NULL; + } + + kfree (dev->isoc_ctl.urb); + kfree (dev->isoc_ctl.transfer_buffer); + dev->isoc_ctl.urb=NULL; + dev->isoc_ctl.transfer_buffer=NULL; + + dev->isoc_ctl.num_bufs=0; + + em28xx_capture_start(dev, 0); +} + +/* + * Stop video thread - FIXME: Can be easily removed + */ +static void em28xx_stop_thread(struct em28xx_dmaqueue *dma_q) +{ + struct em28xx *dev= container_of(dma_q, struct em28xx, vidq); + + em28xx_uninit_isoc(dev); +} + +/* + * Allocate URBs and start IRQ + */ +static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, + int num_bufs) +{ + struct em28xx_dmaqueue *dma_q = &dev->vidq; + int i; + int sb_size, pipe; + struct urb *urb; + int j, k; + + /* De-allocates all pending stuff */ + em28xx_uninit_isoc(dev); + + dev->isoc_ctl.num_bufs = num_bufs; + + dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + if (!dev->isoc_ctl.urb) { + em28xx_errdev("cannot alloc memory for usb buffers\n"); + return -ENOMEM; + } + + dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs, + GFP_KERNEL); + if (!dev->isoc_ctl.urb) { + em28xx_errdev("cannot allocate memory for usbtransfer\n"); + kfree(dev->isoc_ctl.urb); + return -ENOMEM; + } + + dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; + + sb_size = max_packets * dev->isoc_ctl.max_pkt_size; + + /* allocate urbs and transfer buffers */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb = usb_alloc_urb(max_packets, GFP_KERNEL); + if (!urb) { + em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); + em28xx_uninit_isoc(dev); + usb_free_urb(urb); + return -ENOMEM; + } + dev->isoc_ctl.urb[i] = urb; + + dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev, + sb_size, GFP_KERNEL, &urb->transfer_dma); + if (!dev->isoc_ctl.transfer_buffer[i]) { + em28xx_err ("unable to allocate %i bytes for transfer" + " buffer %i%s\n", + sb_size, i, + in_interrupt()?" while in int":""); + em28xx_uninit_isoc(dev); + return -ENOMEM; + } + memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); + + /* FIXME: this is a hack - should be + 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' + should also be using 'desc.bInterval' + */ + pipe=usb_rcvisocpipe(dev->udev, 0x82); + usb_fill_int_urb(urb, dev->udev, pipe, + dev->isoc_ctl.transfer_buffer[i], sb_size, + em28xx_irq_callback, dma_q, 1); + + urb->number_of_packets = max_packets; + urb->transfer_flags = URB_ISO_ASAP; + + k = 0; + for (j = 0; j < max_packets; j++) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->isoc_ctl.max_pkt_size; + k += dev->isoc_ctl.max_pkt_size; + } + } + + return 0; +} + +static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q, + struct em28xx_buffer *buf) +{ + struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); + int i,rc; + + init_waitqueue_head(&dma_q->wq); + + em28xx_capture_start(dev, 1); + + /* submit urbs and enables IRQ */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); + if (rc) { + em28xx_err("submit of urb %i failed (error=%i)\n", i, + rc); + em28xx_uninit_isoc(dev); + return rc; + } + } + + if (rc<0) + return rc; + + return 0; +} + +static int restart_video_queue(struct em28xx_dmaqueue *dma_q) +{ + struct em28xx *dev= container_of(dma_q,struct em28xx,vidq); + + struct em28xx_buffer *buf, *prev; + struct list_head *item; + + em28xx_videodbg("%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 em28xx_buffer, vb.queue); + em28xx_videodbg("restart_queue [%p/%d]: restart dma\n", + buf, buf->vb.i); + em28xx_stop_thread(dma_q); + em28xx_start_thread(dma_q, buf); + + /* cancel all outstanding capture / vbi requests */ + list_for_each(item,&dma_q->active) { + buf = list_entry(item, struct em28xx_buffer, 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 em28xx_buffer, vb.queue); + if (NULL == prev) { + list_del(&buf->vb.queue); + list_add_tail(&buf->vb.queue,&dma_q->active); + + em28xx_videodbg("Restarting video dma\n"); + em28xx_stop_thread(dma_q); + em28xx_start_thread(dma_q, buf); + + buf->vb.state = VIDEOBUF_ACTIVE; + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + em28xx_videodbg("[%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; + em28xx_videodbg("[%p/%d] restart_queue -" + " move to active\n",buf,buf->vb.i); + } else { + return 0; + } + prev = buf; + } +} + +static void em28xx_vid_timeout(unsigned long data) +{ + struct em28xx *dev = (struct em28xx*)data; + struct em28xx_dmaqueue *vidq = &dev->vidq; + struct em28xx_buffer *buf; + unsigned long flags; + + spin_lock_irqsave(&dev->slock,flags); + while (!list_empty(&vidq->active)) { + buf = list_entry(vidq->active.next, struct em28xx_buffer, + vb.queue); + list_del(&buf->vb.queue); + buf->vb.state = VIDEOBUF_ERROR; + wake_up(&buf->vb.done); + em28xx_videodbg("em28xx/0: [%p/%d] timeout\n", + buf, buf->vb.i); + } + + restart_video_queue(vidq); + spin_unlock_irqrestore(&dev->slock,flags); +} + +/* ------------------------------------------------------------------ + Videobuf operations + ------------------------------------------------------------------*/ + +static int +buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +{ + struct em28xx_fh *fh = vq->priv_data; + + *size = 16 * fh->width * fh->height >> 3; + if (0 == *count) + *count = EM28XX_DEF_BUF; + + if (*count < EM28XX_MIN_BUF) { + *count=EM28XX_MIN_BUF; + } + + return 0; +} + +static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) +{ + if (in_interrupt()) + BUG(); + + videobuf_waiton(&buf->vb, 0, 0); + videobuf_vmalloc_free(&buf->vb); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int +buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct em28xx_fh *fh = vq->priv_data; + struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb); + struct em28xx *dev = fh->dev; + int rc = 0, urb_init = 0; + const int urbsize = EM28XX_NUM_PACKETS * dev->max_pkt_size; + + BUG_ON(NULL == fh->fmt); + + /* FIXME: It assumes depth = 16 */ + /* The only currently supported format is 16 bits/pixel */ + buf->vb.size = 16 * fh->width * fh->height >> 3; + + 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; + buf->vb.state = VIDEOBUF_NEEDS_INIT; + } + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + if (0 != (rc = videobuf_iolock(vq,&buf->vb,NULL))) + goto fail; + urb_init=1; + } + + + if (!dev->isoc_ctl.num_bufs) + urb_init=1; + + if (urb_init) { + rc = em28xx_prepare_isoc(dev, urbsize, EM28XX_NUM_BUFS); + if (rc<0) + goto fail; + } + + buf->vb.state = VIDEOBUF_PREPARED; + return 0; + +fail: + free_buffer(vq,buf); + return rc; +} + +static void +buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + struct em28xx_fh *fh = vq->priv_data; + struct em28xx *dev = fh->dev; + struct em28xx_dmaqueue *vidq = &dev->vidq; + struct em28xx_buffer *prev; + + if (!list_empty(&vidq->queued)) { + list_add_tail(&buf->vb.queue,&vidq->queued); + buf->vb.state = VIDEOBUF_QUEUED; + em28xx_videodbg("[%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); + em28xx_videodbg("[%p/%d] buffer_queue - first active\n", + buf, buf->vb.i); + em28xx_start_thread(vidq, buf); + } else { + prev = list_entry(vidq->active.prev, struct em28xx_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; + em28xx_videodbg("[%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; + em28xx_videodbg("[%p/%d] buffer_queue - first queued\n", + buf, buf->vb.i); + } + } +} + +static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb); + struct em28xx_fh *fh = vq->priv_data; + struct em28xx *dev = (struct em28xx*)fh->dev; + struct em28xx_dmaqueue *vidq = &dev->vidq; + + em28xx_stop_thread(vidq); + + free_buffer(vq,buf); +} + +static struct videobuf_queue_ops em28xx_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; /********************* v4l2 interface ******************************************/ @@ -152,23 +826,6 @@ static void em28xx_config_i2c(struct em28xx *dev) em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); } -/* - * em28xx_empty_framequeues() - * prepare queues for incoming and outgoing frames - */ -static void em28xx_empty_framequeues(struct em28xx *dev) -{ - u32 i; - - INIT_LIST_HEAD(&dev->inqueue); - INIT_LIST_HEAD(&dev->outqueue); - - for (i = 0; i < EM28XX_NUM_FRAMES; i++) { - dev->frame[i].state = F_UNUSED; - dev->frame[i].buf.bytesused = 0; - } -} - static void video_mux(struct em28xx *dev, int index) { struct v4l2_routing route; @@ -230,33 +887,6 @@ static void res_free(struct em28xx_fh *fh) mutex_unlock(&dev->lock); } -/* - * em28xx_vm_open() - */ -static void em28xx_vm_open(struct vm_area_struct *vma) -{ - struct em28xx_frame_t *f = vma->vm_private_data; - f->vma_use_count++; -} - -/* - * em28xx_vm_close() - */ -static void em28xx_vm_close(struct vm_area_struct *vma) -{ - /* NOTE: buffers are not freed here */ - struct em28xx_frame_t *f = vma->vm_private_data; - - if (f->vma_use_count) - f->vma_use_count--; -} - -static struct vm_operations_struct em28xx_vm_ops = { - .open = em28xx_vm_open, - .close = em28xx_vm_close, -}; - - /* * em28xx_get_ctrl() * return the current saturation, brightness or contrast, mute state @@ -296,34 +926,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) } } -/* - * em28xx_stream_interrupt() - * stops streaming - */ -static int em28xx_stream_interrupt(struct em28xx *dev) -{ - int rc = 0; - - /* stop reading from the device */ - - dev->stream = STREAM_INTERRUPT; - rc = wait_event_timeout(dev->wait_stream, - (dev->stream == STREAM_OFF) || - (dev->state & DEV_DISCONNECTED), - EM28XX_URB_TIMEOUT); - - if (rc) { - dev->state |= DEV_MISCONFIGURED; - em28xx_videodbg("device is misconfigured; close and " - "open /dev/video%d again\n", - dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); - return rc; - } - - return 0; -} - - static int check_dev(struct em28xx *dev) { if (dev->state & DEV_DISCONNECTED) { @@ -447,7 +1049,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - int rc, i; + int rc; rc = check_dev(dev); if (rc < 0) @@ -457,25 +1059,6 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, mutex_lock(&dev->lock); - for (i = 0; i < dev->num_frames; i++) - if (dev->frame[i].vma_use_count) { - em28xx_videodbg("VIDIOC_S_FMT failed. " - "Unmap the buffers first.\n"); - rc = -EINVAL; - goto err; - } - - /* stop io in case it is already in progress */ - if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n"); - rc = em28xx_stream_interrupt(dev); - if (rc < 0) - goto err; - } - - em28xx_release_buffers(dev); - dev->io = IO_NONE; - /* set new image size */ dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; @@ -484,19 +1067,11 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, dev->bytesperline = dev->width * 2; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - /* FIXME: This is really weird! Why capture is starting with - this ioctl ??? - */ - em28xx_uninit_isoc(dev); em28xx_set_alternate(dev); - em28xx_capture_start(dev, 1); em28xx_resolution_set(dev); - em28xx_init_isoc(dev); - rc = 0; -err: mutex_unlock(&dev->lock); - return rc; + return 0; } static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) @@ -918,23 +1493,11 @@ static int vidioc_streamon(struct file *file, void *priv, if (rc < 0) return rc; - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP) - return -EINVAL; - if (list_empty(&dev->inqueue)) - return -EINVAL; - - mutex_lock(&dev->lock); - - if (unlikely(res_get(fh) < 0)) { - mutex_unlock(&dev->lock); + if (unlikely(res_get(fh) < 0)) return -EBUSY; - } - dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ - - mutex_unlock(&dev->lock); - return 0; + return (videobuf_streamon(&fh->vb_vidq)); } static int vidioc_streamoff(struct file *file, void *priv, @@ -948,23 +1511,14 @@ static int vidioc_streamoff(struct file *file, void *priv, if (rc < 0) return rc; - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP) + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (type != fh->type) return -EINVAL; - mutex_lock(&dev->lock); + videobuf_streamoff(&fh->vb_vidq); + res_free(fh); - if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_STREAMOFF: interrupting stream\n"); - rc = em28xx_stream_interrupt(dev); - if (rc < 0) { - mutex_unlock(&dev->lock); - return rc; - } - } - - em28xx_empty_framequeues(dev); - - mutex_unlock(&dev->lock); return 0; } @@ -1058,53 +1612,13 @@ static int vidioc_reqbufs(struct file *file, void *priv, { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - u32 i; int rc; rc = check_dev(dev); if (rc < 0) return rc; - if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - rb->memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - if (dev->io == IO_READ) { - em28xx_videodbg("method is set to read;" - " close and open the device again to" - " choose the mmap I/O method\n"); - return -EINVAL; - } - - for (i = 0; i < dev->num_frames; i++) - if (dev->frame[i].vma_use_count) { - em28xx_videodbg("VIDIOC_REQBUFS failed; " - "previous buffers are still mapped\n"); - return -EINVAL; - } - - mutex_lock(&dev->lock); - - if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); - rc = em28xx_stream_interrupt(dev); - if (rc < 0) { - mutex_unlock(&dev->lock); - return rc; - } - } - - em28xx_empty_framequeues(dev); - - em28xx_release_buffers(dev); - if (rb->count) - rb->count = em28xx_request_buffers(dev, rb->count); - - dev->frame_current = NULL; - dev->io = rb->count ? IO_MMAP : IO_NONE; - - mutex_unlock(&dev->lock); - return 0; + return (videobuf_reqbufs(&fh->vb_vidq, rb)); } static int vidioc_querybuf(struct file *file, void *priv, @@ -1118,52 +1632,20 @@ static int vidioc_querybuf(struct file *file, void *priv, if (rc < 0) return rc; - if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b->index >= dev->num_frames || dev->io != IO_MMAP) - return -EINVAL; - - mutex_lock(&dev->lock); - - memcpy(b, &dev->frame[b->index].buf, sizeof(*b)); - - if (dev->frame[b->index].vma_use_count) - b->flags |= V4L2_BUF_FLAG_MAPPED; - - if (dev->frame[b->index].state == F_DONE) - b->flags |= V4L2_BUF_FLAG_DONE; - else if (dev->frame[b->index].state != F_UNUSED) - b->flags |= V4L2_BUF_FLAG_QUEUED; - - mutex_unlock(&dev->lock); - return 0; + return (videobuf_querybuf(&fh->vb_vidq, b)); } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - unsigned long lock_flags; int rc; rc = check_dev(dev); if (rc < 0) return rc; - if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP || - b->index >= dev->num_frames) - return -EINVAL; - - if (dev->frame[b->index].state != F_UNUSED) - return -EAGAIN; - - dev->frame[b->index].state = F_QUEUED; - - /* add frame to fifo */ - spin_lock_irqsave(&dev->queue_lock, lock_flags); - list_add_tail(&dev->frame[b->index].frame, &dev->inqueue); - spin_unlock_irqrestore(&dev->queue_lock, lock_flags); - - return 0; + return (videobuf_qbuf(&fh->vb_vidq, b)); } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1171,47 +1653,25 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int rc; - struct em28xx_frame_t *f; - unsigned long lock_flags; rc = check_dev(dev); if (rc < 0) return rc; - if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP) - return -EINVAL; - - if (list_empty(&dev->outqueue)) { - if (dev->stream == STREAM_OFF) - return -EINVAL; - - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - rc = wait_event_interruptible(dev->wait_frame, - (!list_empty(&dev->outqueue)) || - (dev->state & DEV_DISCONNECTED)); - if (rc) - return rc; - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - } - - spin_lock_irqsave(&dev->queue_lock, lock_flags); - f = list_entry(dev->outqueue.next, struct em28xx_frame_t, frame); - list_del(dev->outqueue.next); - spin_unlock_irqrestore(&dev->queue_lock, lock_flags); - - f->state = F_UNUSED; - memcpy(b, &f->buf, sizeof(*b)); - - if (f->vma_use_count) - b->flags |= V4L2_BUF_FLAG_MAPPED; - - return 0; + return (videobuf_dqbuf(&fh->vb_vidq, b, + file->f_flags & O_NONBLOCK)); } +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) +{ + struct em28xx_fh *fh=priv; + + return videobuf_cgmbuf (&fh->vb_vidq, mbuf, 8); +} +#endif + + /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ @@ -1361,16 +1821,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->vscale = 0; em28xx_set_alternate(dev); - em28xx_capture_start(dev, 1); em28xx_resolution_set(dev); - - /* start the transfer */ - errCode = em28xx_init_isoc(dev); - if (errCode) - goto err; - - em28xx_empty_framequeues(dev); } if (fh->radio) { em28xx_videodbg("video_open: setting radio device\n"); @@ -1379,7 +1831,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->users++; -err: + videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, + NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, + sizeof(struct em28xx_buffer), fh); + mutex_unlock(&dev->lock); return errCode; } @@ -1445,9 +1900,8 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) mutex_lock(&dev->lock); if (dev->users == 1) { - em28xx_uninit_isoc(dev); - em28xx_release_buffers(dev); - dev->io = IO_NONE; + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); /* the device is already disconnect, free the remaining resources */ @@ -1480,134 +1934,28 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) */ static ssize_t em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, - loff_t * f_pos) + loff_t * pos) { - struct em28xx_frame_t *f, *i; - unsigned long lock_flags; - int ret = 0; struct em28xx_fh *fh = filp->private_data; struct em28xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; /* FIXME: read() is not prepared to allow changing the video resolution while streaming. Seems a bug at em28xx_set_fmt */ - if (unlikely(res_get(fh) < 0)) - return -EBUSY; + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (unlikely(res_get(fh))) + return -EBUSY; - mutex_lock(&dev->lock); - - if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - em28xx_videodbg("V4l2_Buf_type_videocapture is set\n"); - - if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n"); - em28xx_videodbg("not supported yet! ...\n"); - if (copy_to_user(buf, "", 1)) { - mutex_unlock(&dev->lock); - return -EFAULT; - } - mutex_unlock(&dev->lock); - return (1); + return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, + filp->f_flags & O_NONBLOCK); } - if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { - em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n"); - em28xx_videodbg("not supported yet! ...\n"); - if (copy_to_user(buf, "", 1)) { - mutex_unlock(&dev->lock); - return -EFAULT; - } - mutex_unlock(&dev->lock); - return (1); - } - - if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("device not present\n"); - mutex_unlock(&dev->lock); - return -ENODEV; - } - - if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg("device misconfigured; close and open it again\n"); - mutex_unlock(&dev->lock); - return -EIO; - } - - if (dev->io == IO_MMAP) { - em28xx_videodbg ("IO method is set to mmap; close and open" - " the device again to choose the read method\n"); - mutex_unlock(&dev->lock); - return -EINVAL; - } - - if (dev->io == IO_NONE) { - if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) { - em28xx_errdev("read failed, not enough memory\n"); - mutex_unlock(&dev->lock); - return -ENOMEM; - } - dev->io = IO_READ; - dev->stream = STREAM_ON; - em28xx_queue_unusedframes(dev); - } - - if (!count) { - mutex_unlock(&dev->lock); - return 0; - } - - if (list_empty(&dev->outqueue)) { - if (filp->f_flags & O_NONBLOCK) { - mutex_unlock(&dev->lock); - return -EAGAIN; - } - ret = wait_event_interruptible - (dev->wait_frame, - (!list_empty(&dev->outqueue)) || - (dev->state & DEV_DISCONNECTED)); - if (ret) { - mutex_unlock(&dev->lock); - return ret; - } - if (dev->state & DEV_DISCONNECTED) { - mutex_unlock(&dev->lock); - return -ENODEV; - } - dev->video_bytesread = 0; - } - - f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame); - - em28xx_queue_unusedframes(dev); - - if (count > f->buf.length) - count = f->buf.length; - - if ((dev->video_bytesread + count) > dev->frame_size) - count = dev->frame_size - dev->video_bytesread; - - if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) { - em28xx_err("Error while copying to user\n"); - return -EFAULT; - } - dev->video_bytesread += count; - - if (dev->video_bytesread == dev->frame_size) { - spin_lock_irqsave(&dev->queue_lock, lock_flags); - list_for_each_entry(i, &dev->outqueue, frame) - i->state = F_UNUSED; - INIT_LIST_HEAD(&dev->outqueue); - spin_unlock_irqrestore(&dev->queue_lock, lock_flags); - - em28xx_queue_unusedframes(dev); - dev->video_bytesread = 0; - } - - *f_pos += count; - - mutex_unlock(&dev->lock); - - return count; + return 0; } /* @@ -1616,46 +1964,21 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, */ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) { - unsigned int mask = 0; struct em28xx_fh *fh = filp->private_data; struct em28xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; if (unlikely(res_get(fh) < 0)) return POLLERR; - mutex_lock(&dev->lock); + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) + return POLLERR; - if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("device not present\n"); - } else if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg("device is misconfigured; close and open it again\n"); - } else { - if (dev->io == IO_NONE) { - if (!em28xx_request_buffers - (dev, EM28XX_NUM_READ_FRAMES)) { - em28xx_warn - ("poll() failed, not enough memory\n"); - } else { - dev->io = IO_READ; - dev->stream = STREAM_ON; - } - } - - if (dev->io == IO_READ) { - em28xx_queue_unusedframes(dev); - poll_wait(filp, &dev->wait_frame, wait); - - if (!list_empty(&dev->outqueue)) - mask |= POLLIN | POLLRDNORM; - - mutex_unlock(&dev->lock); - - return mask; - } - } - - mutex_unlock(&dev->lock); - return POLLERR; + return videobuf_poll_stream(filp, &fh->vb_vidq, wait); } /* @@ -1665,69 +1988,23 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) { struct em28xx_fh *fh = filp->private_data; struct em28xx *dev = fh->dev; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long start = vma->vm_start; - void *pos; - u32 i; + int rc; if (unlikely(res_get(fh) < 0)) return -EBUSY; - mutex_lock(&dev->lock); + rc = check_dev(dev); + if (rc < 0) + return rc; - if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("mmap: device not present\n"); - mutex_unlock(&dev->lock); - return -ENODEV; - } + rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg ("mmap: Device is misconfigured; close and " - "open it again\n"); - mutex_unlock(&dev->lock); - return -EIO; - } + em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, + rc); - if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE)) { - mutex_unlock(&dev->lock); - return -EINVAL; - } - - if (size > PAGE_ALIGN(dev->frame[0].buf.length)) - size = PAGE_ALIGN(dev->frame[0].buf.length); - - for (i = 0; i < dev->num_frames; i++) { - if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) - break; - } - if (i == dev->num_frames) { - em28xx_videodbg("mmap: user supplied mapping address is out of range\n"); - mutex_unlock(&dev->lock); - return -EINVAL; - } - - /* VM_IO is eventually going to replace PageReserved altogether */ - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ - - pos = dev->frame[i].bufmem; - while (size > 0) { /* size is page-aligned */ - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - em28xx_videodbg("mmap: vm_insert_page failed\n"); - mutex_unlock(&dev->lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &em28xx_vm_ops; - vma->vm_private_data = &dev->frame[i]; - - em28xx_vm_open(vma); - mutex_unlock(&dev->lock); - return 0; + return rc; } static const struct file_operations em28xx_v4l_fops = { @@ -1790,6 +2067,9 @@ static const struct video_device em28xx_video_template = { .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, #endif +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif .tvnorms = V4L2_STD_ALL, .current_norm = V4L2_STD_PAL, @@ -2005,6 +2285,14 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->radio_dev->minor & 0x1f); } + /* init video dma queues */ + INIT_LIST_HEAD(&dev->vidq.active); + INIT_LIST_HEAD(&dev->vidq.queued); + + dev->vidq.timeout.function = em28xx_vid_timeout; + dev->vidq.timeout.data = (unsigned long)dev; + init_timer(&dev->vidq.timeout); + if (dev->has_msp34xx) { /* Send a reset to other chips via gpio */ diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 04e0e48ecabe..dd18ceb30a43 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -26,12 +26,12 @@ #define _EM28XX_H #include +#include + #include #include #include -#define UNSET -1 - /* maximum number of em28xx boards */ #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ @@ -81,31 +81,69 @@ /* time in msecs to wait for i2c writes to finish */ #define EM2800_I2C_WRITE_TIMEOUT 20 -/* the various frame states */ -enum em28xx_frame_state { - F_UNUSED = 0, - F_QUEUED, - F_GRABBING, - F_DONE, - F_ERROR, -}; - -/* stream states */ enum em28xx_stream_state { STREAM_OFF, STREAM_INTERRUPT, STREAM_ON, }; -/* frames */ -struct em28xx_frame_t { - void *bufmem; - struct v4l2_buffer buf; - enum em28xx_frame_state state; +struct em28xx_usb_isoc_ctl { + /* max packet size of isoc transaction */ + int max_pkt_size; + + /* number of allocated urbs */ + int num_bufs; + + /* urb for isoc transfers */ + struct urb **urb; + + /* transfer buffers for isoc transfer */ + char **transfer_buffer; + + /* Last buffer command and region */ + u8 cmd; + int pos, size, pktsize; + + /* Last field: ODD or EVEN? */ + int field; + + /* Stores incomplete commands */ + u32 tmp_buf; + int tmp_buf_len; + + /* Stores already requested buffers */ + struct em28xx_buffer *buf; + + /* Stores the number of received fields */ + int nfields; +}; + +struct em28xx_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ +}; + +/* buffer for one video frame */ +struct em28xx_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + struct em28xx_fmt *fmt; + struct list_head frame; - unsigned long vma_use_count; int top_field; - int fieldbytesused; + int receiving; +}; + +struct em28xx_dmaqueue { + struct list_head active; + struct list_head queued; + struct timer_list timeout; + + wait_queue_head_t wq; + + /* Counters to control buffer fill */ + int pos; }; /* io methods */ @@ -255,10 +293,6 @@ struct em28xx { int mute; int volume; /* frame properties */ - struct em28xx_frame_t frame[EM28XX_NUM_FRAMES]; /* list of frames */ - int num_frames; /* number of frames currently in use */ - unsigned int frame_count; /* total number of transfered frames */ - struct em28xx_frame_t *frame_current; /* the frame that is being filled */ int width; /* current frame width */ int height; /* current frame height */ int frame_size; /* current frame size */ @@ -277,7 +311,6 @@ struct em28xx { /* states */ enum em28xx_dev_state state; - enum em28xx_stream_state stream; enum em28xx_io_method io; struct work_struct request_module_wk; @@ -292,6 +325,11 @@ struct em28xx { unsigned char eedata[256]; + /* Isoc control struct */ + struct em28xx_dmaqueue vidq; + struct em28xx_usb_isoc_ctl isoc_ctl; + spinlock_t slock; + /* usb transfer */ struct usb_device *udev; /* the usb device */ int alt; /* alternate */ @@ -315,6 +353,12 @@ struct em28xx_fh { struct em28xx *dev; unsigned int stream_on:1; /* Locks streams */ int radio; + + unsigned int width, height; + struct videobuf_queue vb_vidq; + struct em28xx_fmt *fmt; + + enum v4l2_buf_type type; }; struct em28xx_ops { @@ -351,8 +395,6 @@ int em28xx_colorlevels_set_default(struct em28xx *dev); int em28xx_capture_start(struct em28xx *dev, int start); int em28xx_outfmt_set_yuv422(struct em28xx *dev); int em28xx_resolution_set(struct em28xx *dev); -int em28xx_init_isoc(struct em28xx *dev); -void em28xx_uninit_isoc(struct em28xx *dev); int em28xx_set_alternate(struct em28xx *dev); /* Provided by em28xx-video.c */ From d7aa80207babe694b316a48200b096cf0336ecb3 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Sun, 13 Apr 2008 14:38:47 -0300 Subject: [PATCH 280/452] V4L/DVB (7541): em28xx: Some fixes to videobuf It fixes a couple of minor bugs, comments out a bogus BUG_ON, sets fh->type correctly, uses dev->width and dev->height for now, and adds a missing spinlock init (nasty - caused a system lockup). It also adds some debug code which probably isn't all that useful. I haven't tested this version of the patch yet, though, so I'm not sure what you can expect if you try it. Signed-off-by: Aidan Thornton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 279 +++++++++------------- drivers/media/video/em28xx/em28xx.h | 3 +- 2 files changed, 113 insertions(+), 169 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 182058ac8432..4e6cc612a994 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -133,10 +133,10 @@ static void inline buffer_filled (struct em28xx *dev, struct em28xx_dmaqueue *dma_q, struct em28xx_buffer *buf) { + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + /* Nobody is waiting something to be done, just return */ if (!waitqueue_active(&buf->vb.done)) { - mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); - printk(KERN_ERR "em28xx: buffer underrun at %ld\n", jiffies); @@ -174,7 +174,7 @@ static void em28xx_copy_video(struct em28xx *dev, if (dma_q->pos + len > buf->vb.size) len = buf->vb.size - dma_q->pos; - if (outp[0] != 0x88 && outp[0] != 0x22) { + if (p[0] != 0x88 && p[0] != 0x22) { em28xx_isocdbg("frame is not complete\n"); len += 4; } else @@ -196,8 +196,13 @@ static void em28xx_copy_video(struct em28xx *dev, lencopy = dev->bytesperline - currlinedone; lencopy = lencopy > remain ? remain : lencopy; - if (__copy_to_user(startwrite, startread, lencopy) != 0) - em28xx_errdev("copy_to_user failed.\n"); + if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) { + em28xx_isocdbg("Overflow of %i bytes past buffer end (1)\n", + ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size)); + lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite; + } + BUG_ON(lencopy <= 0); + memcpy(startwrite, startread, lencopy); remain -= lencopy; @@ -209,8 +214,16 @@ static void em28xx_copy_video(struct em28xx *dev, else lencopy = dev->bytesperline; - if (__copy_to_user(startwrite, startread, lencopy) != 0) - em28xx_errdev("copy_to_user failed.\n"); + BUG_ON(lencopy <= 0); + + if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) { + em28xx_isocdbg("Overflow of %i bytes past buffer end (2)\n", + ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size)); + lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite; + } + if(lencopy <= 0) break; + + memcpy(startwrite, startread, lencopy); remain -= lencopy; } @@ -278,13 +291,14 @@ static int inline get_next_buf (struct em28xx_dmaqueue *dma_q, /* * Controls the isoc copy of each urb packet */ -static inline int em28xx_isoc_copy(struct urb *urb, struct em28xx_buffer **buf) +static inline int em28xx_isoc_copy(struct urb *urb) { + struct em28xx_buffer *buf; struct em28xx_dmaqueue *dma_q = urb->context; struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - unsigned char *outp = videobuf_to_vmalloc (&(*buf)->vb); + unsigned char *outp; int i, len = 0, rc = 1; - char *p; + unsigned char *p; if (!dev) return 0; @@ -298,6 +312,17 @@ static inline int em28xx_isoc_copy(struct urb *urb, struct em28xx_buffer **buf) return 0; } + buf=dev->isoc_ctl.buf; + + if (!buf) { + rc=get_next_buf (dma_q, &buf); + if (rc<=0) + return rc; + } + + outp = videobuf_to_vmalloc (&buf->vb); + + for (i = 0; i < urb->number_of_packets; i++) { int status = urb->iso_frame_desc[i].status; @@ -310,7 +335,7 @@ static inline int em28xx_isoc_copy(struct urb *urb, struct em28xx_buffer **buf) len=urb->iso_frame_desc[i].actual_length - 4; if (urb->iso_frame_desc[i].actual_length <= 0) { - em28xx_isocdbg("packet %d is empty",i); + /* em28xx_isocdbg("packet %d is empty",i); - spammy */ continue; } if (urb->iso_frame_desc[i].actual_length > @@ -320,31 +345,37 @@ static inline int em28xx_isoc_copy(struct urb *urb, struct em28xx_buffer **buf) } p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; /* FIXME: incomplete buffer checks where removed to make logic simpler. Impacts of those changes should be evaluated */ - if (outp[0] == 0x22 && outp[1] == 0x5a) { - em28xx_isocdbg("Video frame, length=%i, %s", len, - (outp[2] == 1)? "top" : "botton"); + if (p[0] == 0x22 && p[1] == 0x5a) { + /* FIXME - are the fields the right way around? */ + em28xx_isocdbg("Video frame, length=%i, %s\n", len, + (p[2] & 1)? "top" : "bottom"); + em28xx_isocdbg("Current buffer is: outp = 0x%p, len = %i\n", outp, (int)buf->vb.size); - if (outp[2] == 1) { - if ((*buf)->receiving) - buffer_filled (dev, dma_q, *buf); + if (p[2] & 1) { + if (buf->receiving) { + buffer_filled (dev, dma_q, buf); + rc=get_next_buf (dma_q, &buf); + if (rc<=0) + return rc; - (*buf)->top_field = 1; + outp = videobuf_to_vmalloc (&buf->vb); + } + + buf->top_field = 1; } else { - (*buf)->top_field = 0; + buf->top_field = 0; } - (*buf)->receiving = 1; + buf->receiving = 1; dma_q->pos = 0; - } else if (outp[0]==0x33 && outp[1]==0x95 && outp[2]==0x00) { - em28xx_isocdbg("VBI HEADER!!!"); + } else if (p[0]==0x33 && p[1]==0x95 && p[2]==0x00) { + em28xx_isocdbg("VBI HEADER!!!\n"); } - em28xx_copy_video(dev, dma_q, *buf, p, outp, len); + em28xx_copy_video(dev, dma_q, buf, p, outp, len); /* FIXME: Should add vbi copy */ } @@ -360,7 +391,6 @@ static inline int em28xx_isoc_copy(struct urb *urb, struct em28xx_buffer **buf) */ static void em28xx_irq_callback(struct urb *urb) { - struct em28xx_buffer *buf; struct em28xx_dmaqueue *dma_q = urb->context; struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); int rc,i; @@ -368,19 +398,9 @@ static void em28xx_irq_callback(struct urb *urb) spin_lock_irqsave(&dev->slock,flags); - buf=dev->isoc_ctl.buf; - - if (!buf) { - rc=get_next_buf (dma_q, &buf); - if (rc<=0) - goto ret; - } - /* Copy data from URB */ - rc=em28xx_isoc_copy(urb, &buf); + rc=em28xx_isoc_copy(urb); - dev->isoc_ctl.buf=buf; -ret: /* Reset urb buffers */ for (i = 0; i < urb->number_of_packets; i++) { urb->iso_frame_desc[i].status = 0; @@ -393,8 +413,12 @@ ret: urb->status); } +#if 0 /* Bad idea. There are problems that cause a load of valid, but + empty, data packets. Don't reset the timeout unless we've actually + got a frame. I've had xawtv hang in free_buffer due to this! */ if (rc >= 0) mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); +#endif spin_unlock_irqrestore(&dev->slock,flags); } @@ -406,6 +430,8 @@ static void em28xx_uninit_isoc(struct em28xx *dev) struct urb *urb; int i; + em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); + dev->isoc_ctl.nfields=-1; dev->isoc_ctl.buf=NULL; for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { @@ -432,18 +458,9 @@ static void em28xx_uninit_isoc(struct em28xx *dev) dev->isoc_ctl.num_bufs=0; - em28xx_capture_start(dev, 0); + // em28xx_capture_start(dev, 0); - FIXME - how could I restart it? } -/* - * Stop video thread - FIXME: Can be easily removed - */ -static void em28xx_stop_thread(struct em28xx_dmaqueue *dma_q) -{ - struct em28xx *dev= container_of(dma_q, struct em28xx, vidq); - - em28xx_uninit_isoc(dev); -} /* * Allocate URBs and start IRQ @@ -457,18 +474,20 @@ static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, struct urb *urb; int j, k; + em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n"); + /* De-allocates all pending stuff */ em28xx_uninit_isoc(dev); dev->isoc_ctl.num_bufs = num_bufs; - dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); if (!dev->isoc_ctl.urb) { em28xx_errdev("cannot alloc memory for usb buffers\n"); return -ENOMEM; } - dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs, + dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); if (!dev->isoc_ctl.urb) { em28xx_errdev("cannot allocate memory for usbtransfer\n"); @@ -486,7 +505,6 @@ static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, if (!urb) { em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); em28xx_uninit_isoc(dev); - usb_free_urb(urb); return -ENOMEM; } dev->isoc_ctl.urb[i] = urb; @@ -527,16 +545,15 @@ static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, return 0; } -static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf) +static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q) { struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - int i,rc; + int i,rc = 0; + + em28xx_videodbg("Called em28xx_start_thread\n"); init_waitqueue_head(&dma_q->wq); - em28xx_capture_start(dev, 1); - /* submit urbs and enables IRQ */ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); @@ -554,68 +571,6 @@ static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q, return 0; } -static int restart_video_queue(struct em28xx_dmaqueue *dma_q) -{ - struct em28xx *dev= container_of(dma_q,struct em28xx,vidq); - - struct em28xx_buffer *buf, *prev; - struct list_head *item; - - em28xx_videodbg("%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 em28xx_buffer, vb.queue); - em28xx_videodbg("restart_queue [%p/%d]: restart dma\n", - buf, buf->vb.i); - em28xx_stop_thread(dma_q); - em28xx_start_thread(dma_q, buf); - - /* cancel all outstanding capture / vbi requests */ - list_for_each(item,&dma_q->active) { - buf = list_entry(item, struct em28xx_buffer, 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 em28xx_buffer, vb.queue); - if (NULL == prev) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue,&dma_q->active); - - em28xx_videodbg("Restarting video dma\n"); - em28xx_stop_thread(dma_q); - em28xx_start_thread(dma_q, buf); - - buf->vb.state = VIDEOBUF_ACTIVE; - mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); - em28xx_videodbg("[%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; - em28xx_videodbg("[%p/%d] restart_queue -" - " move to active\n",buf,buf->vb.i); - } else { - return 0; - } - prev = buf; - } -} static void em28xx_vid_timeout(unsigned long data) { @@ -635,7 +590,7 @@ static void em28xx_vid_timeout(unsigned long data) buf, buf->vb.i); } - restart_video_queue(vidq); + /* restart_video_queue(vidq); */ spin_unlock_irqrestore(&dev->slock,flags); } @@ -648,7 +603,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct em28xx_fh *fh = vq->priv_data; - *size = 16 * fh->width * fh->height >> 3; + *size = 16 * fh->dev->width * fh->dev->height >> 3; if (0 == *count) *count = EM28XX_DEF_BUF; @@ -676,41 +631,45 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, struct em28xx_fh *fh = vq->priv_data; struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb); struct em28xx *dev = fh->dev; + struct em28xx_dmaqueue *vidq = &dev->vidq; int rc = 0, urb_init = 0; - const int urbsize = EM28XX_NUM_PACKETS * dev->max_pkt_size; - BUG_ON(NULL == fh->fmt); + /* BUG_ON(NULL == fh->fmt); */ /* FIXME: It assumes depth = 16 */ /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = 16 * fh->width * fh->height >> 3; + buf->vb.size = 16 * dev->width * dev->height >> 3; 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.width != dev->width || + buf->vb.height != dev->height || buf->vb.field != field) { buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; + buf->vb.width = dev->width; + buf->vb.height = dev->height; buf->vb.field = field; buf->vb.state = VIDEOBUF_NEEDS_INIT; } if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - if (0 != (rc = videobuf_iolock(vq,&buf->vb,NULL))) + rc = videobuf_iolock(vq, &buf->vb, NULL); + if (rc < 0) goto fail; - urb_init=1; } - if (!dev->isoc_ctl.num_bufs) urb_init=1; if (urb_init) { - rc = em28xx_prepare_isoc(dev, urbsize, EM28XX_NUM_BUFS); + rc = em28xx_prepare_isoc(dev, EM28XX_NUM_PACKETS, EM28XX_NUM_BUFS); + if (rc<0) + goto fail; + + /* FIXME - should probably be done in response to STREAMON */ + rc = em28xx_start_thread(vidq); if (rc<0) goto fail; } @@ -730,37 +689,10 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) struct em28xx_fh *fh = vq->priv_data; struct em28xx *dev = fh->dev; struct em28xx_dmaqueue *vidq = &dev->vidq; - struct em28xx_buffer *prev; - if (!list_empty(&vidq->queued)) { - list_add_tail(&buf->vb.queue,&vidq->queued); - buf->vb.state = VIDEOBUF_QUEUED; - em28xx_videodbg("[%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); - em28xx_videodbg("[%p/%d] buffer_queue - first active\n", - buf, buf->vb.i); - em28xx_start_thread(vidq, buf); - } else { - prev = list_entry(vidq->active.prev, struct em28xx_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; - em28xx_videodbg("[%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; - em28xx_videodbg("[%p/%d] buffer_queue - first queued\n", - buf, buf->vb.i); - } - } + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vidq->active); + } static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) @@ -768,9 +700,8 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb); struct em28xx_fh *fh = vq->priv_data; struct em28xx *dev = (struct em28xx*)fh->dev; - struct em28xx_dmaqueue *vidq = &dev->vidq; - em28xx_stop_thread(vidq); + em28xx_isocdbg("em28xx: called buffer_release\n"); free_buffer(vq,buf); } @@ -1068,6 +999,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); em28xx_set_alternate(dev); + em28xx_capture_start(dev, 1); /* ??? */ em28xx_resolution_set(dev); mutex_unlock(&dev->lock); @@ -1497,6 +1429,14 @@ static int vidioc_streamon(struct file *file, void *priv, if (unlikely(res_get(fh) < 0)) return -EBUSY; + /* We can't do this from buffer_queue or anything called from + there, since it's called with IRQs disabled and the spinlock held, + and this uses USB functions that may sleep + + FIXME FIXME FIXME - putting this here means it may not always + be called when it needs to be */ + em28xx_capture_start(dev, 1); + return (videobuf_streamon(&fh->vb_vidq)); } @@ -1778,15 +1718,16 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) int errCode = 0, radio = 0; struct em28xx *h,*dev = NULL; struct em28xx_fh *fh; + enum v4l2_buf_type fh_type = 0; list_for_each_entry(h, &em28xx_devlist, devlist) { if (h->vdev->minor == minor) { dev = h; - dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } if (h->vbi_dev->minor == minor) { dev = h; - dev->type = V4L2_BUF_TYPE_VBI_CAPTURE; + fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; } if (h->radio_dev && h->radio_dev->minor == minor) { @@ -1798,7 +1739,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) return -ENODEV; em28xx_videodbg("open minor=%d type=%s users=%d\n", - minor,v4l2_type_names[dev->type],dev->users); + minor, v4l2_type_names[fh_type], dev->users); fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); @@ -1809,9 +1750,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) mutex_lock(&dev->lock); fh->dev = dev; fh->radio = radio; + fh->type = fh_type; filp->private_data = fh; - if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { dev->width = norm_maxw(dev); dev->height = norm_maxh(dev); dev->frame_size = dev->width * dev->height * 2; @@ -1912,6 +1854,9 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) return 0; } + /* do this before setting alternate! */ + em28xx_uninit_isoc(dev); + /* set alternate 0 */ dev->alt = 0; em28xx_videodbg("setting alternate 0\n"); @@ -2178,7 +2123,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->udev = udev; mutex_init(&dev->lock); - spin_lock_init(&dev->queue_lock); + spin_lock_init(&dev->slock); init_waitqueue_head(&dev->open); init_waitqueue_head(&dev->wait_frame); init_waitqueue_head(&dev->wait_stream); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index dd18ceb30a43..af15fd3f4f81 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -301,7 +301,6 @@ struct em28xx { int hscale; /* horizontal scale factor (see datasheet) */ int vscale; /* vertical scale factor (see datasheet) */ int interlaced; /* 1=interlace fileds, 0=just top fileds */ - int type; unsigned int video_bytesread; /* Number of bytes read */ unsigned long hash; /* eeprom hash - for boards with generic ID */ @@ -317,7 +316,7 @@ struct em28xx { /* locks */ struct mutex lock; - spinlock_t queue_lock; + /* spinlock_t queue_lock; */ struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; struct video_device *vbi_dev; From ea8df7e09d2226c321c234a8f736fdb167a046cb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:39:29 -0300 Subject: [PATCH 281/452] V4L/DVB (7542): em28xx: Fix some warnings Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 4e6cc612a994..6049a2278190 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -197,7 +197,7 @@ static void em28xx_copy_video(struct em28xx *dev, lencopy = lencopy > remain ? remain : lencopy; if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) { - em28xx_isocdbg("Overflow of %i bytes past buffer end (1)\n", + em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n", ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size)); lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite; } @@ -217,7 +217,7 @@ static void em28xx_copy_video(struct em28xx *dev, BUG_ON(lencopy <= 0); if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) { - em28xx_isocdbg("Overflow of %i bytes past buffer end (2)\n", + em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n", ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size)); lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite; } From 47625da2ab5e98728cdefbd344fb1493c26769ad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:40:10 -0300 Subject: [PATCH 282/452] V4L/DVB (7543): Fix capture start/stop and timeout Also removes the dead restart_video_queue() function Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 24 +++++------------------ 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 6049a2278190..ecc146bfc022 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -413,12 +413,6 @@ static void em28xx_irq_callback(struct urb *urb) urb->status); } -#if 0 /* Bad idea. There are problems that cause a load of valid, but - empty, data packets. Don't reset the timeout unless we've actually - got a frame. I've had xawtv hang in free_buffer due to this! */ - if (rc >= 0) - mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); -#endif spin_unlock_irqrestore(&dev->slock,flags); } @@ -458,7 +452,7 @@ static void em28xx_uninit_isoc(struct em28xx *dev) dev->isoc_ctl.num_bufs=0; - // em28xx_capture_start(dev, 0); - FIXME - how could I restart it? + em28xx_capture_start(dev, 0); } @@ -554,6 +548,8 @@ static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q) init_waitqueue_head(&dma_q->wq); + em28xx_capture_start(dev, 1); + /* submit urbs and enables IRQ */ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); @@ -571,7 +567,6 @@ static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q) return 0; } - static void em28xx_vid_timeout(unsigned long data) { struct em28xx *dev = (struct em28xx*)data; @@ -589,8 +584,9 @@ static void em28xx_vid_timeout(unsigned long data) em28xx_videodbg("em28xx/0: [%p/%d] timeout\n", buf, buf->vb.i); } + /* Instead of trying to restart, just sets timeout again */ + mod_timer(&vidq->timeout, jiffies + BUFFER_TIMEOUT); - /* restart_video_queue(vidq); */ spin_unlock_irqrestore(&dev->slock,flags); } @@ -668,7 +664,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (rc<0) goto fail; - /* FIXME - should probably be done in response to STREAMON */ rc = em28xx_start_thread(vidq); if (rc<0) goto fail; @@ -999,7 +994,6 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); em28xx_set_alternate(dev); - em28xx_capture_start(dev, 1); /* ??? */ em28xx_resolution_set(dev); mutex_unlock(&dev->lock); @@ -1429,14 +1423,6 @@ static int vidioc_streamon(struct file *file, void *priv, if (unlikely(res_get(fh) < 0)) return -EBUSY; - /* We can't do this from buffer_queue or anything called from - there, since it's called with IRQs disabled and the spinlock held, - and this uses USB functions that may sleep - - FIXME FIXME FIXME - putting this here means it may not always - be called when it needs to be */ - em28xx_capture_start(dev, 1); - return (videobuf_streamon(&fh->vb_vidq)); } From ca21d2dc945c224c3f121f6b5f2436877f029eed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:40:36 -0300 Subject: [PATCH 283/452] V4L/DVB (7544): em28xx: Fix timeout code Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index ecc146bfc022..229d154424ff 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -452,6 +452,7 @@ static void em28xx_uninit_isoc(struct em28xx *dev) dev->isoc_ctl.num_bufs=0; + del_timer(&dev->vidq.timeout); em28xx_capture_start(dev, 0); } @@ -575,9 +576,8 @@ static void em28xx_vid_timeout(unsigned long data) unsigned long flags; spin_lock_irqsave(&dev->slock,flags); - while (!list_empty(&vidq->active)) { - buf = list_entry(vidq->active.next, struct em28xx_buffer, - vb.queue); + + list_for_each_entry(buf, vidq->active.next, vb.queue) { list_del(&buf->vb.queue); buf->vb.state = VIDEOBUF_ERROR; wake_up(&buf->vb.done); From f245e549f0d1fb43fd6d7759d31cd763e6d914b6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:41:23 -0300 Subject: [PATCH 284/452] V4L/DVB (7545): em28xx: Fix CodingStyle errors and most warnings introduced by videobuf The last videobuf changes introduced several CodingStyle errors. Fixes all those errors, as reported by checkpatch.pl Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 151 +++++++++++----------- 1 file changed, 78 insertions(+), 73 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 229d154424ff..c5593526a6e7 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -55,13 +55,13 @@ dev->name, __func__ , ##arg); } while (0) static unsigned int isoc_debug; -module_param(isoc_debug,int,0644); -MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); +module_param(isoc_debug, int, 0644); +MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); #define em28xx_isocdbg(fmt, arg...) do {\ if (isoc_debug) \ printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + dev->name, __func__ , ##arg); } while (0) #define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ @@ -129,7 +129,7 @@ static struct usb_driver em28xx_usb_driver; /* * Announces that a buffer were filled and request the next */ -static void inline buffer_filled (struct em28xx *dev, +static inline void buffer_filled(struct em28xx *dev, struct em28xx_dmaqueue *dma_q, struct em28xx_buffer *buf) { @@ -163,9 +163,9 @@ static void em28xx_copy_video(struct em28xx *dev, unsigned char *outp, unsigned long len) { void *fieldstart, *startwrite, *startread; - int linesdone, currlinedone, offset, lencopy,remain; + int linesdone, currlinedone, offset, lencopy, remain; - if(dev->frame_size != buf->vb.size){ + if (dev->frame_size != buf->vb.size) { em28xx_errdev("size %i and buf.length %lu are different!\n", dev->frame_size, buf->vb.size); return; @@ -178,7 +178,7 @@ static void em28xx_copy_video(struct em28xx *dev, em28xx_isocdbg("frame is not complete\n"); len += 4; } else - p +=4; + p += 4; startread = p; remain = len; @@ -196,10 +196,11 @@ static void em28xx_copy_video(struct em28xx *dev, lencopy = dev->bytesperline - currlinedone; lencopy = lencopy > remain ? remain : lencopy; - if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) { + if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n", - ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size)); - lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite; + ((char *)startwrite + lencopy) - + ((char *)outp + buf->vb.size)); + lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite; } BUG_ON(lencopy <= 0); memcpy(startwrite, startread, lencopy); @@ -216,12 +217,15 @@ static void em28xx_copy_video(struct em28xx *dev, BUG_ON(lencopy <= 0); - if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) { + if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n", - ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size)); - lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite; + ((char *)startwrite + lencopy) - + ((char *)outp + buf->vb.size)); + lencopy = remain = (char *)outp + buf->vb.size - + (char *)startwrite; } - if(lencopy <= 0) break; + if (lencopy <= 0) + break; memcpy(startwrite, startread, lencopy); @@ -231,12 +235,12 @@ static void em28xx_copy_video(struct em28xx *dev, dma_q->pos += len; } -static void inline print_err_status (struct em28xx *dev, +static inline void print_err_status(struct em28xx *dev, int packet, int status) { char *errmsg = "Unknown"; - switch(status) { + switch (status) { case -ENOENT: errmsg = "unlinked synchronuously"; break; @@ -262,7 +266,7 @@ static void inline print_err_status (struct em28xx *dev, errmsg = "Device does not respond"; break; } - if (packet<0) { + if (packet < 0) { em28xx_isocdbg("URB status %d [%s].\n", status, errmsg); } else { em28xx_isocdbg("URB packet %d, status %d [%s].\n", @@ -273,7 +277,7 @@ static void inline print_err_status (struct em28xx *dev, /* * video-buf generic routine to get the next available buffer */ -static int inline get_next_buf (struct em28xx_dmaqueue *dma_q, +static inline int get_next_buf(struct em28xx_dmaqueue *dma_q, struct em28xx_buffer **buf) { struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); @@ -306,33 +310,33 @@ static inline int em28xx_isoc_copy(struct urb *urb) if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) return 0; - if (urb->status<0) { - print_err_status (dev,-1,urb->status); + if (urb->status < 0) { + print_err_status(dev, -1, urb->status); if (urb->status == -ENOENT) return 0; } - buf=dev->isoc_ctl.buf; + buf = dev->isoc_ctl.buf; if (!buf) { - rc=get_next_buf (dma_q, &buf); - if (rc<=0) + rc = get_next_buf(dma_q, &buf); + if (rc <= 0) return rc; } - outp = videobuf_to_vmalloc (&buf->vb); + outp = videobuf_to_vmalloc(&buf->vb); for (i = 0; i < urb->number_of_packets; i++) { int status = urb->iso_frame_desc[i].status; - if (status<0) { - print_err_status (dev,i,status); + if (status < 0) { + print_err_status(dev, i, status); if (urb->iso_frame_desc[i].status != -EPROTO) continue; } - len=urb->iso_frame_desc[i].actual_length - 4; + len = urb->iso_frame_desc[i].actual_length - 4; if (urb->iso_frame_desc[i].actual_length <= 0) { /* em28xx_isocdbg("packet %d is empty",i); - spammy */ @@ -353,25 +357,25 @@ static inline int em28xx_isoc_copy(struct urb *urb) /* FIXME - are the fields the right way around? */ em28xx_isocdbg("Video frame, length=%i, %s\n", len, (p[2] & 1)? "top" : "bottom"); - em28xx_isocdbg("Current buffer is: outp = 0x%p, len = %i\n", outp, (int)buf->vb.size); + em28xx_isocdbg("Current buffer is: outp = 0x%p," + " len = %i\n", outp, (int)buf->vb.size); if (p[2] & 1) { if (buf->receiving) { - buffer_filled (dev, dma_q, buf); - rc=get_next_buf (dma_q, &buf); - if (rc<=0) + buffer_filled(dev, dma_q, buf); + rc = get_next_buf(dma_q, &buf); + if (rc <= 0) return rc; - outp = videobuf_to_vmalloc (&buf->vb); + outp = videobuf_to_vmalloc(&buf->vb); } buf->top_field = 1; - } else { + } else buf->top_field = 0; - } buf->receiving = 1; dma_q->pos = 0; - } else if (p[0]==0x33 && p[1]==0x95 && p[2]==0x00) { + } else if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) { em28xx_isocdbg("VBI HEADER!!!\n"); } @@ -393,13 +397,13 @@ static void em28xx_irq_callback(struct urb *urb) { struct em28xx_dmaqueue *dma_q = urb->context; struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - int rc,i; + int rc, i; unsigned long flags; - spin_lock_irqsave(&dev->slock,flags); + spin_lock_irqsave(&dev->slock, flags); /* Copy data from URB */ - rc=em28xx_isoc_copy(urb); + rc = em28xx_isoc_copy(urb); /* Reset urb buffers */ for (i = 0; i < urb->number_of_packets; i++) { @@ -408,12 +412,13 @@ static void em28xx_irq_callback(struct urb *urb) } urb->status = 0; - if ((urb->status = usb_submit_urb(urb, GFP_ATOMIC))) { + urb->status = usb_submit_urb(urb, GFP_ATOMIC); + if (urb->status) { em28xx_err("urb resubmit failed (error=%i)\n", urb->status); } - spin_unlock_irqrestore(&dev->slock,flags); + spin_unlock_irqrestore(&dev->slock, flags); } /* @@ -426,10 +431,10 @@ static void em28xx_uninit_isoc(struct em28xx *dev) em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); - dev->isoc_ctl.nfields=-1; - dev->isoc_ctl.buf=NULL; + dev->isoc_ctl.nfields = -1; + dev->isoc_ctl.buf = NULL; for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb=dev->isoc_ctl.urb[i]; + urb = dev->isoc_ctl.urb[i]; if (urb) { usb_kill_urb(urb); usb_unlink_urb(urb); @@ -445,12 +450,12 @@ static void em28xx_uninit_isoc(struct em28xx *dev) dev->isoc_ctl.transfer_buffer[i] = NULL; } - kfree (dev->isoc_ctl.urb); - kfree (dev->isoc_ctl.transfer_buffer); - dev->isoc_ctl.urb=NULL; - dev->isoc_ctl.transfer_buffer=NULL; + kfree(dev->isoc_ctl.urb); + kfree(dev->isoc_ctl.transfer_buffer); + dev->isoc_ctl.urb = NULL; + dev->isoc_ctl.transfer_buffer = NULL; - dev->isoc_ctl.num_bufs=0; + dev->isoc_ctl.num_bufs = 0; del_timer(&dev->vidq.timeout); em28xx_capture_start(dev, 0); @@ -507,7 +512,7 @@ static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL, &urb->transfer_dma); if (!dev->isoc_ctl.transfer_buffer[i]) { - em28xx_err ("unable to allocate %i bytes for transfer" + em28xx_err("unable to allocate %i bytes for transfer" " buffer %i%s\n", sb_size, i, in_interrupt()?" while in int":""); @@ -520,7 +525,7 @@ static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' should also be using 'desc.bInterval' */ - pipe=usb_rcvisocpipe(dev->udev, 0x82); + pipe = usb_rcvisocpipe(dev->udev, 0x82); usb_fill_int_urb(urb, dev->udev, pipe, dev->isoc_ctl.transfer_buffer[i], sb_size, em28xx_irq_callback, dma_q, 1); @@ -540,10 +545,10 @@ static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, return 0; } -static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q) +static int em28xx_start_thread(struct em28xx_dmaqueue *dma_q) { struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - int i,rc = 0; + int i, rc = 0; em28xx_videodbg("Called em28xx_start_thread\n"); @@ -562,7 +567,7 @@ static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q) } } - if (rc<0) + if (rc < 0) return rc; return 0; @@ -570,12 +575,12 @@ static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q) static void em28xx_vid_timeout(unsigned long data) { - struct em28xx *dev = (struct em28xx*)data; + struct em28xx *dev = (struct em28xx *)data; struct em28xx_dmaqueue *vidq = &dev->vidq; struct em28xx_buffer *buf; unsigned long flags; - spin_lock_irqsave(&dev->slock,flags); + spin_lock_irqsave(&dev->slock, flags); list_for_each_entry(buf, vidq->active.next, vb.queue) { list_del(&buf->vb.queue); @@ -587,7 +592,7 @@ static void em28xx_vid_timeout(unsigned long data) /* Instead of trying to restart, just sets timeout again */ mod_timer(&vidq->timeout, jiffies + BUFFER_TIMEOUT); - spin_unlock_irqrestore(&dev->slock,flags); + spin_unlock_irqrestore(&dev->slock, flags); } /* ------------------------------------------------------------------ @@ -603,9 +608,8 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) if (0 == *count) *count = EM28XX_DEF_BUF; - if (*count < EM28XX_MIN_BUF) { - *count=EM28XX_MIN_BUF; - } + if (*count < EM28XX_MIN_BUF) + *count = EM28XX_MIN_BUF; return 0; } @@ -625,7 +629,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) { struct em28xx_fh *fh = vq->priv_data; - struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb); + struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); struct em28xx *dev = fh->dev; struct em28xx_dmaqueue *vidq = &dev->vidq; int rc = 0, urb_init = 0; @@ -657,15 +661,16 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, } if (!dev->isoc_ctl.num_bufs) - urb_init=1; + urb_init = 1; if (urb_init) { - rc = em28xx_prepare_isoc(dev, EM28XX_NUM_PACKETS, EM28XX_NUM_BUFS); - if (rc<0) + rc = em28xx_prepare_isoc(dev, EM28XX_NUM_PACKETS, + EM28XX_NUM_BUFS); + if (rc < 0) goto fail; rc = em28xx_start_thread(vidq); - if (rc<0) + if (rc < 0) goto fail; } @@ -673,7 +678,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, return 0; fail: - free_buffer(vq,buf); + free_buffer(vq, buf); return rc; } @@ -682,7 +687,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; + struct em28xx *dev = fh->dev; struct em28xx_dmaqueue *vidq = &dev->vidq; buf->vb.state = VIDEOBUF_QUEUED; @@ -692,13 +697,13 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb); + struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = (struct em28xx*)fh->dev; + struct em28xx *dev = (struct em28xx *)fh->dev; em28xx_isocdbg("em28xx: called buffer_release\n"); - free_buffer(vq,buf); + free_buffer(vq, buf); } static struct videobuf_queue_ops em28xx_video_qops = { @@ -1589,11 +1594,11 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) } #ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) +static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) { - struct em28xx_fh *fh=priv; + struct em28xx_fh *fh = priv; - return videobuf_cgmbuf (&fh->vb_vidq, mbuf, 8); + return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); } #endif @@ -1865,7 +1870,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) */ static ssize_t em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, - loff_t * pos) + loff_t *pos) { struct em28xx_fh *fh = filp->private_data; struct em28xx *dev = fh->dev; From e74153d44a57d9445fb1dfad7c3accbec6d4a873 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:55:38 -0300 Subject: [PATCH 285/452] V4L/DVB (7547): em28xx: Fix a broken lock Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index c5593526a6e7..033ecb45256b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -790,15 +790,12 @@ static int res_get(struct em28xx_fh *fh) if (fh->stream_on) return rc; - mutex_lock(&dev->lock); - if (dev->stream_on) - rc = -EINVAL; - else { - dev->stream_on = 1; - fh->stream_on = 1; - } + return -EINVAL; + mutex_lock(&dev->lock); + dev->stream_on = 1; + fh->stream_on = 1; mutex_unlock(&dev->lock); return rc; } From e0fadfd34dda2205b296b8826acfaaf4df2e022f Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Sun, 13 Apr 2008 14:56:02 -0300 Subject: [PATCH 286/452] V4L/DVB (7548): Various fixes for the em28xx videobuf code - Aborting buffer_filled if no-one's waiting on the waitqueue probably isn't what we want, since just because no-one's waiting for it now doesn't mean they wouldn't dequeue it in time. (vivi gets away with this, possibly because it can fill each buffer much faster.) - The first BUG_ON(lencopy <= 0); really isn't worth causing a kernel panic over, especially since there are some reasons why it could trigger in normal use. - The top and botom frames are actually the wrong way around. Signed-off-by: Aidan Thornton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 033ecb45256b..e2d04cf4ba9d 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -135,14 +135,6 @@ static inline void buffer_filled(struct em28xx *dev, { mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); - /* Nobody is waiting something to be done, just return */ - if (!waitqueue_active(&buf->vb.done)) { - printk(KERN_ERR "em28xx: buffer underrun at %ld\n", - jiffies); - - return; - } - /* Advice that buffer was filled */ em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); buf->vb.state = VIDEOBUF_DONE; @@ -202,7 +194,8 @@ static void em28xx_copy_video(struct em28xx *dev, ((char *)outp + buf->vb.size)); lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite; } - BUG_ON(lencopy <= 0); + if (lencopy <= 0) + return; memcpy(startwrite, startread, lencopy); remain -= lencopy; @@ -356,11 +349,13 @@ static inline int em28xx_isoc_copy(struct urb *urb) if (p[0] == 0x22 && p[1] == 0x5a) { /* FIXME - are the fields the right way around? */ em28xx_isocdbg("Video frame, length=%i, %s\n", len, - (p[2] & 1)? "top" : "bottom"); + (p[2] & 1)? "odd" : "even"); em28xx_isocdbg("Current buffer is: outp = 0x%p," " len = %i\n", outp, (int)buf->vb.size); - if (p[2] & 1) { + if (p[2] & 1) + buf->top_field = 0; + else { if (buf->receiving) { buffer_filled(dev, dma_q, buf); rc = get_next_buf(dma_q, &buf); @@ -371,8 +366,7 @@ static inline int em28xx_isoc_copy(struct urb *urb) } buf->top_field = 1; - } else - buf->top_field = 0; + } buf->receiving = 1; dma_q->pos = 0; } else if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) { From 78bb3949a965e8a28e20988e28868429606b3639 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:56:25 -0300 Subject: [PATCH 287/452] V4L/DVB (7549): em28xx: some small cleanups - Remove dead code; - Fix a few CodingStyle issues; - Prints frame number, if debug is enabled. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index e2d04cf4ba9d..0a2ff4afe416 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -133,7 +133,7 @@ static inline void buffer_filled(struct em28xx *dev, struct em28xx_dmaqueue *dma_q, struct em28xx_buffer *buf) { - mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT); /* Advice that buffer was filled */ em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); @@ -159,7 +159,7 @@ static void em28xx_copy_video(struct em28xx *dev, if (dev->frame_size != buf->vb.size) { em28xx_errdev("size %i and buf.length %lu are different!\n", - dev->frame_size, buf->vb.size); + dev->frame_size, buf->vb.size); return; } @@ -208,8 +208,6 @@ static void em28xx_copy_video(struct em28xx *dev, else lencopy = dev->bytesperline; - BUG_ON(lencopy <= 0); - if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n", ((char *)startwrite + lencopy) - @@ -319,7 +317,6 @@ static inline int em28xx_isoc_copy(struct urb *urb) outp = videobuf_to_vmalloc(&buf->vb); - for (i = 0; i < urb->number_of_packets; i++) { int status = urb->iso_frame_desc[i].status; @@ -347,11 +344,8 @@ static inline int em28xx_isoc_copy(struct urb *urb) logic simpler. Impacts of those changes should be evaluated */ if (p[0] == 0x22 && p[1] == 0x5a) { - /* FIXME - are the fields the right way around? */ - em28xx_isocdbg("Video frame, length=%i, %s\n", len, - (p[2] & 1)? "odd" : "even"); - em28xx_isocdbg("Current buffer is: outp = 0x%p," - " len = %i\n", outp, (int)buf->vb.size); + em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], + len, (p[2] & 1)? "odd" : "even"); if (p[2] & 1) buf->top_field = 0; @@ -455,7 +449,6 @@ static void em28xx_uninit_isoc(struct em28xx *dev) em28xx_capture_start(dev, 0); } - /* * Allocate URBs and start IRQ */ From 0561297501842b5d7e0ca8805084f4d3f97c1078 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Sun, 13 Apr 2008 14:57:01 -0300 Subject: [PATCH 288/452] V4L/DVB (7550): em28xx: Fix a possible memory leak I did notice a possible memory leak since iolock is could possibly be called before a buffer has been freed. This ensure s_fmt isn't called while the queue is busy thereby avoiding iolock on already allocated buffers. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 25 +++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 0a2ff4afe416..0aaf4e767e0d 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -630,16 +630,10 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; - if (buf->fmt != fh->fmt || - buf->vb.width != dev->width || - buf->vb.height != dev->height || - buf->vb.field != field) { - buf->fmt = fh->fmt; - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - buf->vb.state = VIDEOBUF_NEEDS_INIT; - } + buf->fmt = fh->fmt; + buf->vb.width = dev->width; + buf->vb.height = dev->height; + buf->vb.field = field; if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); @@ -974,6 +968,12 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, mutex_lock(&dev->lock); + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + em28xx_errdev("%s queue busy\n", __func__); + rc = -EBUSY; + goto out; + } + /* set new image size */ dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; @@ -985,8 +985,11 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, em28xx_set_alternate(dev); em28xx_resolution_set(dev); + rc = 0; + +out: mutex_unlock(&dev->lock); - return 0; + return rc; } static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) From fbde31d54b729e4aac1d06375d4365318fd88675 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:57:44 -0300 Subject: [PATCH 289/452] V4L/DVB (7551): vivi: Add a missing \n Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 17eb3ec5d704..b1e9592acb90 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -533,7 +533,7 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) BUG(); videobuf_vmalloc_free(&buf->vb); - dprintk(dev, 1, "free_buffer: freed"); + dprintk(dev, 1, "free_buffer: freed\n"); buf->vb.state = VIDEOBUF_NEEDS_INIT; } @@ -1052,7 +1052,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, + .compat_ioctl = v4l_compat_ioctl32, .mmap = vivi_mmap, .llseek = no_llseek, }; From 968ced78a53509a996708a14e8b9269d1dc6a61c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:58:21 -0300 Subject: [PATCH 290/452] V4L/DVB (7552): videbuf-vmalloc: Corrects mmap code There were some bugs on videobuf-vmalloc. Basically, remap were called with a wrong parameter. Due to that, a later remap were needed, generating the need of some hacks on videobuf-vmalloc and videobuf-core. This patch fixes the remap and removes the hacks. TODO: - V4L2_MEMORY_USERPTR is not implemented yet. This method should be properly implemented, in order to work with a few userspace applications. - The driver also doesn't implement V4L2_MEMORY_OVERLAY. This method is used only by a few applications, and are becaming obsolete, due to the increment of cpu performance. So, most apps prefer to retrieve data to an internal buffer, doing some processing like de-interlacing. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 14 -- drivers/media/video/videobuf-vmalloc.c | 169 ++++++++++++++++--------- 2 files changed, 108 insertions(+), 75 deletions(-) diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 37ddbed8e167..5613e0882b5c 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -91,20 +91,6 @@ 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); } diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 9eb7982988a6..075acdf6b7c7 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -124,45 +124,75 @@ static int __videobuf_iolock (struct videobuf_queue* q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) { - int pages; - struct videobuf_vmalloc_memory *mem=vb->priv; + struct videobuf_vmalloc_memory *mem = vb->priv; BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); + MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; + switch (vb->memory) { + case V4L2_MEMORY_MMAP: + dprintk(1, "%s memory method MMAP\n", __func__); - /* Currently, doesn't support V4L2_MEMORY_OVERLAY */ - if ((vb->memory != V4L2_MEMORY_MMAP) && - (vb->memory != V4L2_MEMORY_USERPTR) ) { - printk(KERN_ERR "Method currently unsupported.\n"); - return -EINVAL; - } - - /* FIXME: should be tested with kernel mmap mem */ - mem->vmalloc=vmalloc_user (PAGE_ALIGN(vb->size)); - if (NULL == mem->vmalloc) { - printk(KERN_ERR "vmalloc (%d pages) failed\n",pages); - return -ENOMEM; - } - - dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", - (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; + /* All handling should be done by __videobuf_mmap_mapper() */ + if (!mem->vmalloc) { + printk(KERN_ERR "memory is not alloced/mmapped.\n"); + return -EINVAL; } + break; + case V4L2_MEMORY_USERPTR: + { + int pages = PAGE_ALIGN(vb->size); + + dprintk(1, "%s memory method USERPTR\n", __func__); + +#if 1 + if (vb->baddr) { + printk(KERN_ERR "USERPTR is currently not supported\n"); + return -EINVAL; + } +#endif + + /* The only USERPTR currently supported is the one needed for + read() method. + */ + + mem->vmalloc = vmalloc_user(pages); + if (!mem->vmalloc) { + printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); + return -ENOMEM; + } + dprintk(1, "vmalloc is at addr %p (%d pages)\n", + mem->vmalloc, pages); + +#if 0 + int rc; + /* Kernel userptr is used also by read() method. In this case, + there's no need to remap, since data will be copied to user + */ + if (!vb->baddr) + return 0; + + /* FIXME: to properly support USERPTR, remap should occur. + The code bellow won't work, since mem->vma = NULL + */ + /* Try to remap memory */ + rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0); + if (rc < 0) { + printk(KERN_ERR "mmap: remap failed with error %d. ", rc); + return -ENOMEM; + } +#endif + + break; + } + case V4L2_MEMORY_OVERLAY: + default: + dprintk(1, "%s memory method OVERLAY/unknown\n", __func__); + + /* Currently, doesn't support V4L2_MEMORY_OVERLAY */ + printk(KERN_ERR "Memory method currently unsupported.\n"); + return -EINVAL; } return 0; @@ -178,6 +208,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) { unsigned int i; + dprintk(1, "%s\n", __func__); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (q->bufs[i]) { if (q->bufs[i]->map) @@ -194,10 +225,11 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct videobuf_vmalloc_memory *mem; struct videobuf_mapping *map; unsigned int first; - int retval; + int retval, pages; unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED)) + dprintk(1, "%s\n", __func__); + if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) return -EINVAL; /* look for first buffer to map */ @@ -217,46 +249,55 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, } /* create mapping + update buffer list */ - map = q->bufs[first]->map = kzalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); + map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); if (NULL == map) return -ENOMEM; + q->bufs[first]->map = map; map->start = vma->vm_start; map->end = vma->vm_end; map->q = q; q->bufs[first]->baddr = vma->vm_start; + mem = q->bufs[first]->priv; + BUG_ON(!mem); + MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); + + pages = PAGE_ALIGN(vma->vm_end - vma->vm_start); + mem->vmalloc = vmalloc_user(pages); + if (!mem->vmalloc) { + printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); + goto error; + } + dprintk(1, "vmalloc is at addr %p (%d pages)\n", + mem->vmalloc, pages); + + /* Try to remap memory */ + retval = remap_vmalloc_range(vma, mem->vmalloc, 0); + if (retval < 0) { + printk(KERN_ERR "mmap: remap failed with error %d. ", retval); + vfree(mem->vmalloc); + goto error; + } + vma->vm_ops = &videobuf_vm_ops; vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; vma->vm_private_data = map; - mem=q->bufs[first]->priv; - BUG_ON (!mem); - MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); - - /* 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 %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", - map,q,vma->vm_start,vma->vm_end, + map, q, vma->vm_start, vma->vm_end, (long int) q->bufs[first]->bsize, - vma->vm_pgoff,first); + vma->vm_pgoff, first); videobuf_vm_open(vma); - return (0); + return 0; + +error: + mem = NULL; + kfree(map); + return -ENOMEM; } static int __videobuf_copy_to_user ( struct videobuf_queue *q, @@ -347,13 +388,19 @@ EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); void videobuf_vmalloc_free (struct videobuf_buffer *buf) { - struct videobuf_vmalloc_memory *mem=buf->priv; - BUG_ON (!mem); + struct videobuf_vmalloc_memory *mem = buf->priv; - MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); + if (!mem) + return; + + MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); vfree(mem->vmalloc); - mem->vmalloc=NULL; + mem->vmalloc = NULL; + + + + /* FIXME: need to do buf->priv = NULL? */ return; } From aaea56afc31345e7b0456ebb01586ba627ecd0f8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:58:43 -0300 Subject: [PATCH 291/452] V4L/DVB (7553): videobuf-vmalloc: fix STREAMOFF/STREAMON There were a small bug on videobuf-vmalloc that were preventing STREAMOFF to work. The issue is that vmalloc'ed mmaped memory should only be freed after being sure that there aren't any mmap usage. Otherwise, the memory remap will stop working, and the userspace won't receive any frames. This bug were affecting some userspace applications, like tvtime. After this patch, tvtime started to work again with the drivers that use videobuf-vmalloc. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-vmalloc.c | 36 +++++++++++++++++++------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 075acdf6b7c7..73627d380f07 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -57,19 +57,20 @@ videobuf_vm_open(struct vm_area_struct *vma) map->count++; } -static void -videobuf_vm_close(struct vm_area_struct *vma) +static void videobuf_vm_close(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; struct videobuf_queue *q = map->q; int i; - dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map, - map->count,vma->vm_start,vma->vm_end); + dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, + map->count, vma->vm_start, vma->vm_end); map->count--; if (0 == map->count) { - dprintk(1,"munmap %p q=%p\n",map,q); + struct videobuf_vmalloc_memory *mem; + + dprintk(1, "munmap %p q=%p\n", map, q); mutex_lock(&q->vb_lock); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) @@ -78,6 +79,18 @@ videobuf_vm_close(struct vm_area_struct *vma) if (q->bufs[i]->map != map) continue; + mem = q->bufs[i]->priv; + if (mem) { + /* This callback is called only if kernel has + allocated memory and this memory is mmapped. + In this case, memory should be freed, + in order to do memory unmap. + */ + MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); + vfree(mem->vmalloc); + mem->vmalloc = NULL; + } + q->bufs[i]->map = NULL; q->bufs[i]->baddr = 0; } @@ -390,6 +403,15 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf) { struct videobuf_vmalloc_memory *mem = buf->priv; + /* mmapped memory can't be freed here, otherwise mmapped region + would be released, while still needed. In this case, the memory + release should happen inside videobuf_vm_close(). + So, it should free memory only if the memory were allocated for + read() operation. + */ + if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0)) + return; + if (!mem) return; @@ -398,10 +420,6 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf) vfree(mem->vmalloc); mem->vmalloc = NULL; - - - /* FIXME: need to do buf->priv = NULL? */ - return; } EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); From a9dbbeb7d615761a82fcd4f00ec290a07be7d8a2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:59:29 -0300 Subject: [PATCH 292/452] V4L/DVB (7554): videobuf-dma-sg: Remove unused flag Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-sg.c | 4 ---- include/media/videobuf-dma-sg.h | 3 --- 2 files changed, 7 deletions(-) diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 440c1a8e9c1f..c0b7902862e4 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -162,9 +162,6 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n", data,size,dma->nr_pages); - dma->varea = (void *) data; - - err = get_user_pages(current,current->mm, data & PAGE_MASK, dma->nr_pages, rw == READ, 1, /* force */ @@ -300,7 +297,6 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) vfree(dma->vmalloc); dma->vmalloc = NULL; - dma->varea = NULL; if (dma->bus_addr) { dma->bus_addr = 0; diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index b6ab08045de6..be8da269ee33 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -68,9 +68,6 @@ struct videobuf_dmabuf { /* for kernel buffers */ void *vmalloc; - /* Stores the userspace pointer to vmalloc area */ - void *varea; - /* for overlay buffers (pci-pci dma) */ dma_addr_t bus_addr; From b957dfdc3161d00b01b52154eb2d53580c8911e5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:01:12 -0300 Subject: [PATCH 293/452] V4L/DVB (7555): em28xx: remove timeout It seems that we don't need a timeout for em28xx. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 31 ----------------------- drivers/media/video/em28xx/em28xx.h | 1 - 2 files changed, 32 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 0aaf4e767e0d..d6ada6226b54 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -63,8 +63,6 @@ MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __func__ , ##arg); } while (0) -#define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ - /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 #define EM28XX_DEF_BUF 8 @@ -133,8 +131,6 @@ static inline void buffer_filled(struct em28xx *dev, struct em28xx_dmaqueue *dma_q, struct em28xx_buffer *buf) { - mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT); - /* Advice that buffer was filled */ em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); buf->vb.state = VIDEOBUF_DONE; @@ -445,7 +441,6 @@ static void em28xx_uninit_isoc(struct em28xx *dev) dev->isoc_ctl.num_bufs = 0; - del_timer(&dev->vidq.timeout); em28xx_capture_start(dev, 0); } @@ -560,28 +555,6 @@ static int em28xx_start_thread(struct em28xx_dmaqueue *dma_q) return 0; } -static void em28xx_vid_timeout(unsigned long data) -{ - struct em28xx *dev = (struct em28xx *)data; - struct em28xx_dmaqueue *vidq = &dev->vidq; - struct em28xx_buffer *buf; - unsigned long flags; - - spin_lock_irqsave(&dev->slock, flags); - - list_for_each_entry(buf, vidq->active.next, vb.queue) { - list_del(&buf->vb.queue); - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - em28xx_videodbg("em28xx/0: [%p/%d] timeout\n", - buf, buf->vb.i); - } - /* Instead of trying to restart, just sets timeout again */ - mod_timer(&vidq->timeout, jiffies + BUFFER_TIMEOUT); - - spin_unlock_irqrestore(&dev->slock, flags); -} - /* ------------------------------------------------------------------ Videobuf operations ------------------------------------------------------------------*/ @@ -2212,10 +2185,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.queued); - dev->vidq.timeout.function = em28xx_vid_timeout; - dev->vidq.timeout.data = (unsigned long)dev; - init_timer(&dev->vidq.timeout); - if (dev->has_msp34xx) { /* Send a reset to other chips via gpio */ diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index af15fd3f4f81..6d62357a038f 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -138,7 +138,6 @@ struct em28xx_buffer { struct em28xx_dmaqueue { struct list_head active; struct list_head queued; - struct timer_list timeout; wait_queue_head_t wq; From 0ea13e6e59853cab9e8ed3ac231ec5d44d8386a6 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Sun, 13 Apr 2008 15:02:24 -0300 Subject: [PATCH 294/452] V4L/DVB (7556): em28xx: fix locking on vidioc_s_fmt_cap Currently, vidioc_s_fmt_cap is allowed even if streaming is running on some other fh. This is likely to cause issues. Block use of vidioc_s_fmt_cap if someone else has claimed access to the device. Signed-off-by: Aidan Thornton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index d6ada6226b54..d3485f500c5e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -947,6 +947,12 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, goto out; } + if (dev->stream_on && !fh->stream_on) { + em28xx_errdev("%s device in use by another fh\n", __func__); + rc = -EBUSY; + goto out; + } + /* set new image size */ dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; From e9e6040df6c96678d7b776b3902e3b2c6bbfc5a3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:05:47 -0300 Subject: [PATCH 295/452] V4L/DVB (7557): em28xx: honour video_debug modprobe parameter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index d3485f500c5e..064728f67740 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2057,6 +2057,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, vfd->dev = &dev->udev->dev; vfd->release = video_device_release; vfd->type = type; + vfd->debug = video_debug; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); From 5e28e00964cdc90dec5ebb4c00dfa2fc1ecf36fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:06:24 -0300 Subject: [PATCH 296/452] V4L/DVB (7558): videobuf: Improve command output for debug purposes Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-ioctl.c | 3 ++ drivers/media/video/pwc/pwc-v4l.c | 4 +- drivers/media/video/videodev.c | 59 +++++++++++++++------------ 3 files changed, 39 insertions(+), 27 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 1beb296a1763..90f59c4155ae 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1632,6 +1632,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, if (ivtv_debug & IVTV_DBGFLG_IOCTL) { printk(KERN_INFO "ivtv%d ioctl: ", itv->num); v4l_printk_ioctl(cmd); + printk("\n"); } return ivtv_debug_ioctls(filp, cmd, arg); @@ -1675,6 +1676,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, if (ivtv_debug & IVTV_DBGFLG_IOCTL) { printk(KERN_INFO "ivtv%d ioctl: ", itv->num); v4l_printk_ioctl(cmd); + printk("\n"); } return ivtv_v4l2_ioctls(itv, filp, cmd, arg); @@ -1688,6 +1690,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, if (ivtv_debug & IVTV_DBGFLG_IOCTL) { printk(KERN_INFO "ivtv%d ioctl: ", itv->num); v4l_printk_ioctl(cmd); + printk("\n"); } return ivtv_control_ioctls(itv, cmd, arg); diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 32fbe1ae6251..1742889874df 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -351,8 +351,10 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file, return -EFAULT; #ifdef CONFIG_USB_PWC_DEBUG - if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) + if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) { v4l_printk_ioctl(cmd); + printk("\n"); + } #endif diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 0bf056622d6a..4c4ee566d257 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -18,9 +18,9 @@ #define dbgarg(cmd, fmt, arg...) \ if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \ - printk (KERN_DEBUG "%s: ", vfd->name); \ + printk(KERN_DEBUG "%s: ", vfd->name); \ v4l_printk_ioctl(cmd); \ - printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); \ + printk(" " fmt, ## arg); \ } #define dbgarg2(fmt, arg...) \ @@ -378,7 +378,35 @@ static const char *v4l2_int_ioctls[] = { external ioctl messages as well as internal V4L ioctl */ void v4l_printk_ioctl(unsigned int cmd) { - char *dir; + char *dir, *type; + + switch (_IOC_TYPE(cmd)) { + case 'd': + if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) { + type = "v4l2_int"; + break; + } + printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]); + return; +#ifdef CONFIG_VIDEO_V4L1_COMPAT + case 'v': + if (_IOC_NR(cmd) >= V4L1_IOCTLS) { + type = "v4l1"; + break; + } + printk("%s", v4l1_ioctls[_IOC_NR(cmd)]); + return; +#endif + case 'V': + if (_IOC_NR(cmd) >= V4L2_IOCTLS) { + type = "v4l2"; + break; + } + printk("%s", v4l2_ioctls[_IOC_NR(cmd)]); + return; + default: + type = "unknown"; + } switch (_IOC_DIR(cmd)) { case _IOC_NONE: dir = "--"; break; @@ -387,29 +415,8 @@ void v4l_printk_ioctl(unsigned int cmd) case _IOC_READ | _IOC_WRITE: dir = "rw"; break; default: dir = "*ERR*"; break; } - switch (_IOC_TYPE(cmd)) { - case 'd': - printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n", - (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ? - v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); - break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case 'v': - printk("v4l1 ioctl %s, dir=%s (0x%08x)\n", - (_IOC_NR(cmd) < V4L1_IOCTLS) ? - v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); - break; -#endif - case 'V': - printk("v4l2 ioctl %s, dir=%s (0x%08x)\n", - (_IOC_NR(cmd) < V4L2_IOCTLS) ? - v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); - break; - - default: - printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n", - _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); - } + printk("%s ioctl '%c', dir=%s, #%d (0x%08x)", + type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); } EXPORT_SYMBOL(v4l_printk_ioctl); From cb7847249f1b2bad201e38c770ef4401c61c022a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:06:52 -0300 Subject: [PATCH 297/452] V4L/DVB (7559): em28xx: Fills the entire buffer, before getting another one Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 064728f67740..db3bbacb3a77 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -137,6 +137,8 @@ static inline void buffer_filled(struct em28xx *dev, buf->vb.field_count++; do_gettimeofday(&buf->vb.ts); + dev->isoc_ctl.buf = NULL; + list_del(&buf->vb.queue); wake_up(&buf->vb.done); } @@ -269,6 +271,11 @@ static inline int get_next_buf(struct em28xx_dmaqueue *dma_q, { struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); + /* If the previous buffer were not filled yet, continue */ + *buf = dev->isoc_ctl.buf; + if (*buf) + return 1; + if (list_empty(&dma_q->active)) { em28xx_isocdbg("No active queue to serve\n"); return 0; @@ -276,6 +283,9 @@ static inline int get_next_buf(struct em28xx_dmaqueue *dma_q, *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); + + dev->isoc_ctl.buf = *buf; + return 1; } @@ -303,13 +313,9 @@ static inline int em28xx_isoc_copy(struct urb *urb) return 0; } - buf = dev->isoc_ctl.buf; - - if (!buf) { - rc = get_next_buf(dma_q, &buf); - if (rc <= 0) - return rc; - } + rc = get_next_buf(dma_q, &buf); + if (rc <= 0) + return rc; outp = videobuf_to_vmalloc(&buf->vb); @@ -351,7 +357,6 @@ static inline int em28xx_isoc_copy(struct urb *urb) rc = get_next_buf(dma_q, &buf); if (rc <= 0) return rc; - outp = videobuf_to_vmalloc(&buf->vb); } @@ -416,7 +421,6 @@ static void em28xx_uninit_isoc(struct em28xx *dev) em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); dev->isoc_ctl.nfields = -1; - dev->isoc_ctl.buf = NULL; for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { urb = dev->isoc_ctl.urb[i]; if (urb) { @@ -478,6 +482,7 @@ static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, } dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; + dev->isoc_ctl.buf = NULL; sb_size = max_packets * dev->isoc_ctl.max_pkt_size; From d6849652628d3479859ca10bdd4b21024466df5f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:07:16 -0300 Subject: [PATCH 298/452] V4L/DVB (7560): videodev: Some printk fixes Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videodev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 4c4ee566d257..effcd2ae4152 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -25,7 +25,7 @@ #define dbgarg2(fmt, arg...) \ if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ - printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); + printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg); #include #include @@ -781,6 +781,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, if ( (vfd->debug & V4L2_DEBUG_IOCTL) && !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { v4l_print_ioctl(vfd->name, cmd); + printk("\n"); } #ifdef CONFIG_VIDEO_V4L1_COMPAT @@ -1864,8 +1865,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { if (ret<0) { - printk ("%s: err:\n", vfd->name); + printk("%s: err: on ", vfd->name); v4l_print_ioctl(vfd->name, cmd); + printk("\n"); } } From aa9479ed508d78dcd06479dc6274c9b02d1398df Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:07:56 -0300 Subject: [PATCH 299/452] V4L/DVB (7561): videobuf-vmalloc: stop streaming before unmap Before the patch, there were a risk of freeing and unmapping userspace memory, while there were pending requests. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 1 - drivers/media/video/videobuf-vmalloc.c | 23 +++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 5613e0882b5c..45a8cbdf417d 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -901,7 +901,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q) { int i; - videobuf_queue_cancel(q); __videobuf_mmap_free(q); INIT_LIST_HEAD(&q->stream); diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 73627d380f07..d68d0273807b 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -72,6 +72,11 @@ static void videobuf_vm_close(struct vm_area_struct *vma) dprintk(1, "munmap %p q=%p\n", map, q); mutex_lock(&q->vb_lock); + + /* We need first to cancel streams, before unmapping */ + if (q->streaming) + videobuf_queue_cancel(q); + for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -86,7 +91,15 @@ static void videobuf_vm_close(struct vm_area_struct *vma) In this case, memory should be freed, in order to do memory unmap. */ + MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); + + /* vfree is not atomic - can't be + called with IRQ's disabled + */ + dprintk(1, "%s: buf[%d] freeing (%p)\n", + __func__, i, mem->vmalloc); + vfree(mem->vmalloc); mem->vmalloc = NULL; } @@ -94,9 +107,12 @@ static void videobuf_vm_close(struct vm_area_struct *vma) q->bufs[i]->map = NULL; q->bufs[i]->baddr = 0; } - mutex_unlock(&q->vb_lock); + kfree(map); + + mutex_unlock(&q->vb_lock); } + return; } @@ -138,6 +154,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, struct v4l2_framebuffer *fbuf) { struct videobuf_vmalloc_memory *mem = vb->priv; + int pages; BUG_ON(!mem); @@ -154,8 +171,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, } break; case V4L2_MEMORY_USERPTR: - { - int pages = PAGE_ALIGN(vb->size); + pages = PAGE_ALIGN(vb->size); dprintk(1, "%s memory method USERPTR\n", __func__); @@ -198,7 +214,6 @@ static int __videobuf_iolock (struct videobuf_queue* q, #endif break; - } case V4L2_MEMORY_OVERLAY: default: dprintk(1, "%s memory method OVERLAY/unknown\n", __func__); From 0cf4daee31d88086cf3508d1d8d1f4e451c27906 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Fri, 28 Mar 2008 10:18:33 -0700 Subject: [PATCH 300/452] V4L/DVB (7562): videobuf: Require spinlocks for all videobuf users A spinlock is necessary for queue_cancel to work with every driver in the tree. Otherwise a race exists between IRQ handlers removing buffers from the queue and queue_cancel invalidating the queue. Signed-off-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 46 +++++++++++------------------ 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 45a8cbdf417d..848a2d0e1233 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -123,6 +123,9 @@ void videobuf_queue_core_init(struct videobuf_queue *q, BUG_ON(!q->ops->buf_queue); BUG_ON(!q->ops->buf_release); + /* Lock is mandatory for queue_cancel to work */ + BUG_ON(!irqlock); + /* Having implementations for abstract methods are mandatory */ BUG_ON(!q->int_ops); @@ -180,8 +183,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q) wake_up_interruptible_sync(&q->wait); /* remove queued buffers from list */ - if (q->irqlock) - spin_lock_irqsave(q->irqlock, flags); + spin_lock_irqsave(q->irqlock, flags); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -191,8 +193,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q) wake_up_all(&q->bufs[i]->done); } } - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock, flags); + spin_unlock_irqrestore(q->irqlock, flags); /* free all buffers + clear queue */ for (i = 0; i < VIDEO_MAX_FRAME; i++) { @@ -548,11 +549,9 @@ int videobuf_qbuf(struct videobuf_queue *q, list_add_tail(&buf->stream, &q->stream); if (q->streaming) { - if (q->irqlock) - spin_lock_irqsave(q->irqlock, flags); + spin_lock_irqsave(q->irqlock, flags); q->ops->buf_queue(q, buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock, flags); + spin_unlock_irqrestore(q->irqlock, flags); } dprintk(1, "qbuf: succeded\n"); retval = 0; @@ -689,13 +688,11 @@ int videobuf_streamon(struct videobuf_queue *q) if (q->streaming) goto done; q->streaming = 1; - if (q->irqlock) - spin_lock_irqsave(q->irqlock, flags); + spin_lock_irqsave(q->irqlock, flags); list_for_each_entry(buf, &q->stream, stream) if (buf->state == VIDEOBUF_PREPARED) q->ops->buf_queue(q, buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock, flags); + spin_unlock_irqrestore(q->irqlock, flags); wake_up_interruptible_sync(&q->wait); done: @@ -751,11 +748,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, goto done; /* start capture & wait */ - if (q->irqlock) - spin_lock_irqsave(q->irqlock, flags); + spin_lock_irqsave(q->irqlock, flags); q->ops->buf_queue(q, q->read_buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock, flags); + spin_unlock_irqrestore(q->irqlock, flags); retval = videobuf_waiton(q->read_buf, 0, 0); if (0 == retval) { CALL(q, sync, q, q->read_buf); @@ -816,12 +811,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, q->read_buf = NULL; goto done; } - if (q->irqlock) - spin_lock_irqsave(q->irqlock, flags); + spin_lock_irqsave(q->irqlock, flags); q->ops->buf_queue(q, q->read_buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock, flags); + spin_unlock_irqrestore(q->irqlock, flags); + q->read_off = 0; } @@ -887,12 +881,10 @@ static int __videobuf_read_start(struct videobuf_queue *q) return err; list_add_tail(&q->bufs[i]->stream, &q->stream); } - if (q->irqlock) - spin_lock_irqsave(q->irqlock, flags); + spin_lock_irqsave(q->irqlock, flags); for (i = 0; i < count; i++) q->ops->buf_queue(q, q->bufs[i]); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock, flags); + spin_unlock_irqrestore(q->irqlock, flags); q->reading = 1; return 0; } @@ -1004,11 +996,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, if (q->read_off == q->read_buf->size) { list_add_tail(&q->read_buf->stream, &q->stream); - if (q->irqlock) - spin_lock_irqsave(q->irqlock, flags); + spin_lock_irqsave(q->irqlock, flags); q->ops->buf_queue(q, q->read_buf); - if (q->irqlock) - spin_unlock_irqrestore(q->irqlock, flags); + spin_unlock_irqrestore(q->irqlock, flags); q->read_buf = NULL; } if (retval < 0) From dbecb44c11d9517d604240b53581951ac4e3b5e6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:08:55 -0300 Subject: [PATCH 301/452] V4L/DVB (7563): em28xx: Add missing checks There are some cases where nobody is waiting for a buffer. Due to the lack of check, if you try to abort the userspace app, machine were hanging, since IRQ were trying to use a buffer that were disallocated. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 35 +++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index db3bbacb3a77..10928dccaecc 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -270,19 +270,39 @@ static inline int get_next_buf(struct em28xx_dmaqueue *dma_q, struct em28xx_buffer **buf) { struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); + char *outp; - /* If the previous buffer were not filled yet, continue */ + if (list_empty(&dma_q->active)) { + em28xx_isocdbg("No active queue to serve\n"); + dev->isoc_ctl.buf = NULL; + return 0; + } + + /* Check if the last buffer were fully filled */ *buf = dev->isoc_ctl.buf; + + /* Nobody is waiting on this buffer - discards */ + if (*buf && !waitqueue_active(&(*buf)->vb.done)) { + dev->isoc_ctl.buf = NULL; + *buf = NULL; + } + + /* Returns the last buffer, to be filled with remaining data */ if (*buf) return 1; - if (list_empty(&dma_q->active)) { + /* Get the next buffer */ + *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); + + /* Nobody is waiting on the next buffer. returns */ + if (!*buf || !waitqueue_active(&(*buf)->vb.done)) { em28xx_isocdbg("No active queue to serve\n"); return 0; } - *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); - + /* Cleans up buffer - Usefull for testing for frame/URB loss */ + outp = videobuf_to_vmalloc(&(*buf)->vb); + memset(outp, 0, (*buf)->vb.size); dev->isoc_ctl.buf = *buf; @@ -387,12 +407,11 @@ static void em28xx_irq_callback(struct urb *urb) struct em28xx_dmaqueue *dma_q = urb->context; struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); int rc, i; - unsigned long flags; - - spin_lock_irqsave(&dev->slock, flags); /* Copy data from URB */ + spin_lock(&dev->slock); rc = em28xx_isoc_copy(urb); + spin_unlock(&dev->slock); /* Reset urb buffers */ for (i = 0; i < urb->number_of_packets; i++) { @@ -406,8 +425,6 @@ static void em28xx_irq_callback(struct urb *urb) em28xx_err("urb resubmit failed (error=%i)\n", urb->status); } - - spin_unlock_irqrestore(&dev->slock, flags); } /* From b4916f8ca1da71bb97fb6dcf1e8da3f9c64cf80e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:09:14 -0300 Subject: [PATCH 302/452] V4L/DVB (7564): em28xx: Some fixes to display logic Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 31 ++++++++++++----------- drivers/media/video/em28xx/em28xx.h | 3 +++ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 10928dccaecc..d5728c2cd360 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -365,32 +365,33 @@ static inline int em28xx_isoc_copy(struct urb *urb) /* FIXME: incomplete buffer checks where removed to make logic simpler. Impacts of those changes should be evaluated */ + if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) { + em28xx_isocdbg("VBI HEADER!!!\n"); + /* FIXME: Should add vbi copy */ + continue; + } if (p[0] == 0x22 && p[1] == 0x5a) { em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], len, (p[2] & 1)? "odd" : "even"); if (p[2] & 1) buf->top_field = 0; - else { - if (buf->receiving) { - buffer_filled(dev, dma_q, buf); - rc = get_next_buf(dma_q, &buf); - if (rc <= 0) - return rc; - outp = videobuf_to_vmalloc(&buf->vb); - } - + else buf->top_field = 1; + +// if (dev->isoc_ctl.last_field && !buf->top_field) { + if (dev->isoc_ctl.last_field != buf->top_field) { + buffer_filled(dev, dma_q, buf); + rc = get_next_buf(dma_q, &buf); + if (rc <= 0) + return rc; + outp = videobuf_to_vmalloc(&buf->vb); } - buf->receiving = 1; + dev->isoc_ctl.last_field = buf->top_field; + dma_q->pos = 0; - } else if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) { - em28xx_isocdbg("VBI HEADER!!!\n"); } - em28xx_copy_video(dev, dma_q, buf, p, outp, len); - - /* FIXME: Should add vbi copy */ } return rc; } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6d62357a038f..993c1ed05cc3 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -114,6 +114,9 @@ struct em28xx_usb_isoc_ctl { /* Stores already requested buffers */ struct em28xx_buffer *buf; + /* Store last filled frame */ + int last_field; + /* Stores the number of received fields */ int nfields; }; From 3b5fa928a6b2971ec65571745defc5d9758b4bc1 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Sun, 13 Apr 2008 15:09:36 -0300 Subject: [PATCH 303/452] V4L/DVB (7565): em28xx: fix buffer underrun handling This patch fixes three related issues and a fourth trivial one: - Use buffers even if no-one's currently waiting for them (fixes underrun issues); - Don't return incomplete/mangled frames at the start of streaming and in the case of buffer underruns; - Fix an issue which could cause the driver to write to a buffer that's been freed after videobuf_queue_cancel is called (exposed by the previous two fixes - for some reason, ignoring buffers that weren't being waited on worked around the issue); - Fix a bug which could cause only one field to be filled in the first buffer (or first few buffers) after streaming is started. Signed-off-by: Aidan Thornton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 84 +++++++++++------------ drivers/media/video/em28xx/em28xx.h | 3 - 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index d5728c2cd360..f8bbf397d3a7 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -266,7 +266,7 @@ static inline void print_err_status(struct em28xx *dev, /* * video-buf generic routine to get the next available buffer */ -static inline int get_next_buf(struct em28xx_dmaqueue *dma_q, +static inline void get_next_buf(struct em28xx_dmaqueue *dma_q, struct em28xx_buffer **buf) { struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); @@ -274,39 +274,21 @@ static inline int get_next_buf(struct em28xx_dmaqueue *dma_q, if (list_empty(&dma_q->active)) { em28xx_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.buf = NULL; - return 0; - } - - /* Check if the last buffer were fully filled */ - *buf = dev->isoc_ctl.buf; - - /* Nobody is waiting on this buffer - discards */ - if (*buf && !waitqueue_active(&(*buf)->vb.done)) { dev->isoc_ctl.buf = NULL; *buf = NULL; + return; } - /* Returns the last buffer, to be filled with remaining data */ - if (*buf) - return 1; - /* Get the next buffer */ *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); - /* Nobody is waiting on the next buffer. returns */ - if (!*buf || !waitqueue_active(&(*buf)->vb.done)) { - em28xx_isocdbg("No active queue to serve\n"); - return 0; - } - /* Cleans up buffer - Usefull for testing for frame/URB loss */ outp = videobuf_to_vmalloc(&(*buf)->vb); memset(outp, 0, (*buf)->vb.size); dev->isoc_ctl.buf = *buf; - return 1; + return; } /* @@ -317,7 +299,7 @@ static inline int em28xx_isoc_copy(struct urb *urb) struct em28xx_buffer *buf; struct em28xx_dmaqueue *dma_q = urb->context; struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - unsigned char *outp; + unsigned char *outp = NULL; int i, len = 0, rc = 1; unsigned char *p; @@ -333,11 +315,9 @@ static inline int em28xx_isoc_copy(struct urb *urb) return 0; } - rc = get_next_buf(dma_q, &buf); - if (rc <= 0) - return rc; - - outp = videobuf_to_vmalloc(&buf->vb); + buf = dev->isoc_ctl.buf; + if (buf != NULL) + outp = videobuf_to_vmalloc(&buf->vb); for (i = 0; i < urb->number_of_packets; i++) { int status = urb->iso_frame_desc[i].status; @@ -374,24 +354,27 @@ static inline int em28xx_isoc_copy(struct urb *urb) em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], len, (p[2] & 1)? "odd" : "even"); - if (p[2] & 1) - buf->top_field = 0; - else - buf->top_field = 1; - -// if (dev->isoc_ctl.last_field && !buf->top_field) { - if (dev->isoc_ctl.last_field != buf->top_field) { - buffer_filled(dev, dma_q, buf); - rc = get_next_buf(dma_q, &buf); - if (rc <= 0) - return rc; - outp = videobuf_to_vmalloc(&buf->vb); + if (!(p[2] & 1)) { + if (buf != NULL) + buffer_filled(dev, dma_q, buf); + get_next_buf(dma_q, &buf); + if (buf == NULL) + outp = NULL; + else + outp = videobuf_to_vmalloc(&buf->vb); + } + + if (buf != NULL) { + if (p[2] & 1) + buf->top_field = 0; + else + buf->top_field = 1; } - dev->isoc_ctl.last_field = buf->top_field; dma_q->pos = 0; } - em28xx_copy_video(dev, dma_q, buf, p, outp, len); + if (buf != NULL) + em28xx_copy_video(dev, dma_q, buf, p, outp, len); } return rc; } @@ -597,12 +580,29 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) return 0; } +/* This is called *without* dev->slock held; please keep it that way */ static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) { + struct em28xx_fh *fh = vq->priv_data; + struct em28xx *dev = fh->dev; + unsigned long flags = 0; if (in_interrupt()) BUG(); - videobuf_waiton(&buf->vb, 0, 0); + /* We used to wait for the buffer to finish here, but this didn't work + because, as we were keeping the state as VIDEOBUF_QUEUED, + videobuf_queue_cancel marked it as finished for us. + (Also, it could wedge forever if the hardware was misconfigured.) + + This should be safe; by the time we get here, the buffer isn't + queued anymore. If we ever start marking the buffers as + VIDEOBUF_ACTIVE, it won't be, though. + */ + spin_lock_irqsave(&dev->slock, flags); + if (dev->isoc_ctl.buf == buf) + dev->isoc_ctl.buf = NULL; + spin_unlock_irqrestore(&dev->slock, flags); + videobuf_vmalloc_free(&buf->vb); buf->vb.state = VIDEOBUF_NEEDS_INIT; } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 993c1ed05cc3..6d62357a038f 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -114,9 +114,6 @@ struct em28xx_usb_isoc_ctl { /* Stores already requested buffers */ struct em28xx_buffer *buf; - /* Store last filled frame */ - int last_field; - /* Stores the number of received fields */ int nfields; }; From 59d3448995a4c0ca98cbe82f6dac9460323377c1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:10:00 -0300 Subject: [PATCH 304/452] V4L/DVB (7566): videobuf-dvb: allow its usage with videobuf-vmalloc videobuf-dvb were still using a function that were videobuf-dma-sg dependent. This patch creates a generic handler for this function. This way, videobuf-dvb can now work with all videobuf implementations. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 7 +++++++ drivers/media/video/videobuf-dma-sg.c | 11 +++++++++++ drivers/media/video/videobuf-dvb.c | 10 ++++++---- drivers/media/video/videobuf-vmalloc.c | 1 + include/media/videobuf-core.h | 18 ++++++++++-------- include/media/videobuf-vmalloc.h | 4 ++++ 6 files changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 848a2d0e1233..fc51e4918bbf 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -94,6 +94,13 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, return CALL(q, iolock, q, vb, fbuf); } +void *videobuf_queue_to_vmalloc (struct videobuf_queue *q, + struct videobuf_buffer *buf) +{ + return CALL(q, vmalloc, buf); +} +EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc); + /* --------------------------------------------------------------------- */ diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index c0b7902862e4..03a7b946bd54 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -432,6 +432,16 @@ static void *__videobuf_alloc(size_t size) return vb; } +static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf) +{ + struct videobuf_dma_sg_memory *mem = buf->priv; + BUG_ON(!mem); + + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); + + return mem->dma.vmalloc; +} + static int __videobuf_iolock (struct videobuf_queue* q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) @@ -677,6 +687,7 @@ static struct videobuf_qtype_ops sg_ops = { .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, + .vmalloc = __videobuf_to_vmalloc, }; void *videobuf_sg_alloc(size_t size) diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 0f8542a4c71a..6e4d73ec6855 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -20,9 +20,10 @@ #include #include #include + #include -#include +#include #include /* ------------------------------------------------------------------ */ @@ -45,7 +46,7 @@ static int videobuf_dvb_thread(void *data) struct videobuf_buffer *buf; unsigned long flags; int err; - struct videobuf_dmabuf *dma; + void *outp; dprintk("dvb thread started\n"); set_freezable(); @@ -66,9 +67,10 @@ static int videobuf_dvb_thread(void *data) try_to_freeze(); /* feed buffer data to demux */ - dma=videobuf_to_dma(buf); + outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf); + if (buf->state == VIDEOBUF_DONE) - dvb_dmx_swfilter(&dvb->demux, dma->vmalloc, + dvb_dmx_swfilter(&dvb->demux, outp, buf->size); /* requeue buffer */ diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index d68d0273807b..c91e1d8e3802 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -387,6 +387,7 @@ static struct videobuf_qtype_ops qops = { .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, + .vmalloc = videobuf_to_vmalloc, }; void videobuf_queue_vmalloc_init(struct videobuf_queue* q, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 377a6c6e931b..5b39a22533fe 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -13,6 +13,9 @@ * the Free Software Foundation; either version 2 */ +#ifndef _VIDEOBUF_CORE_H +#define _VIDEOBUF_CORE_H + #include #ifdef CONFIG_VIDEO_V4L1_COMPAT #include @@ -123,7 +126,8 @@ struct videobuf_queue_ops { struct videobuf_qtype_ops { u32 magic; - void* (*alloc) (size_t size); + void *(*alloc) (size_t size); + void *(*vmalloc) (struct videobuf_buffer *buf); int (*iolock) (struct videobuf_queue* q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf); @@ -185,6 +189,10 @@ int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, void *videobuf_alloc(struct videobuf_queue* q); +/* Used on videobuf-dvb */ +void *videobuf_queue_to_vmalloc (struct videobuf_queue* q, + struct videobuf_buffer *buf); + void videobuf_queue_core_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, struct device *dev, @@ -233,10 +241,4 @@ int videobuf_mmap_free(struct videobuf_queue *q); int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma); -/* --------------------------------------------------------------------- */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ +#endif diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h index ec63ab0fab93..aed39460c154 100644 --- a/include/media/videobuf-vmalloc.h +++ b/include/media/videobuf-vmalloc.h @@ -12,6 +12,8 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 */ +#ifndef _VIDEOBUF_VMALLOC_H +#define _VIDEOBUF_VMALLOC_H #include @@ -39,3 +41,5 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q, void *videobuf_to_vmalloc (struct videobuf_buffer *buf); void videobuf_vmalloc_free (struct videobuf_buffer *buf); + +#endif From 44dc733cd9edac53402d705cd2f720accd0b3e2c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:11:08 -0300 Subject: [PATCH 305/452] V4L/DVB (7567): em28xx: Some cleanups Removes some fields from data structs. There are some fields that are just caching some calculus for buffer size. The calculus were moved to the places it were needed and the now unused fields were removed. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 4 +-- drivers/media/video/em28xx/em28xx-video.c | 43 ++++++----------------- drivers/media/video/em28xx/em28xx.h | 7 ---- 3 files changed, 13 insertions(+), 41 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 95bc18d0e780..97635abb916e 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -396,13 +396,13 @@ 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->width * 2 + 4; /* 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) + if (dev->width * 2 * dev->height > 720 * 240 * 2) min_pkt_size *= 2; for (i = 0; i < dev->num_alt; i++) { diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index f8bbf397d3a7..6084f8452b2b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -154,12 +154,7 @@ static void em28xx_copy_video(struct em28xx *dev, { void *fieldstart, *startwrite, *startread; int linesdone, currlinedone, offset, lencopy, remain; - - if (dev->frame_size != buf->vb.size) { - em28xx_errdev("size %i and buf.length %lu are different!\n", - dev->frame_size, buf->vb.size); - return; - } + int bytesperline = dev->width << 1; if (dma_q->pos + len > buf->vb.size) len = buf->vb.size - dma_q->pos; @@ -177,13 +172,13 @@ static void em28xx_copy_video(struct em28xx *dev, if (buf->top_field) fieldstart = outp; else - fieldstart = outp + dev->bytesperline; + fieldstart = outp + bytesperline; - linesdone = dma_q->pos / dev->bytesperline; - currlinedone = dma_q->pos % dev->bytesperline; - offset = linesdone * dev->bytesperline * 2 + currlinedone; + linesdone = dma_q->pos / bytesperline; + currlinedone = dma_q->pos % bytesperline; + offset = linesdone * bytesperline * 2 + currlinedone; startwrite = fieldstart + offset; - lencopy = dev->bytesperline - currlinedone; + lencopy = bytesperline - currlinedone; lencopy = lencopy > remain ? remain : lencopy; if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { @@ -199,12 +194,12 @@ static void em28xx_copy_video(struct em28xx *dev, remain -= lencopy; while (remain > 0) { - startwrite += lencopy + dev->bytesperline; + startwrite += lencopy + bytesperline; startread += lencopy; - if (dev->bytesperline > remain) + if (bytesperline > remain) lencopy = remain; else - lencopy = dev->bytesperline; + lencopy = bytesperline; if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n", @@ -617,8 +612,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, struct em28xx_dmaqueue *vidq = &dev->vidq; int rc = 0, urb_init = 0; - /* BUG_ON(NULL == fh->fmt); */ - /* FIXME: It assumes depth = 16 */ /* The only currently supported format is 16 bits/pixel */ buf->vb.size = 16 * dev->width * dev->height >> 3; @@ -626,7 +619,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; - buf->fmt = fh->fmt; buf->vb.width = dev->width; buf->vb.height = dev->height; buf->vb.field = field; @@ -877,8 +869,8 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv, f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - f->fmt.pix.bytesperline = dev->bytesperline; - f->fmt.pix.sizeimage = dev->frame_size; + f->fmt.pix.bytesperline = dev->width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ @@ -979,9 +971,6 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, /* set new image size */ dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; - dev->frame_size = dev->width * dev->height * 2; - dev->field_size = dev->frame_size >> 1; - dev->bytesperline = dev->width * 2; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); em28xx_set_alternate(dev); @@ -1019,9 +1008,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) /* set new image size */ dev->width = f.fmt.pix.width; dev->height = f.fmt.pix.height; - dev->frame_size = dev->width * dev->height * 2; - dev->field_size = dev->frame_size >> 1; - dev->bytesperline = dev->width * 2; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); em28xx_resolution_set(dev); @@ -1736,9 +1722,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { dev->width = norm_maxw(dev); dev->height = norm_maxh(dev); - dev->frame_size = dev->width * dev->height * 2; - dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ - dev->bytesperline = dev->width * 2; dev->hscale = 0; dev->vscale = 0; @@ -2152,10 +2135,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->width = maxw; dev->height = maxh; dev->interlaced = EM28XX_INTERLACED_DEFAULT; - dev->field_size = dev->width * dev->height; - dev->frame_size = - dev->interlaced ? dev->field_size << 1 : dev->field_size; - dev->bytesperline = dev->width * 2; dev->hscale = 0; dev->vscale = 0; dev->ctl_input = 2; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6d62357a038f..0080a09860d9 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -128,8 +128,6 @@ struct em28xx_buffer { /* common v4l buffer stuff -- must be first */ struct videobuf_buffer vb; - struct em28xx_fmt *fmt; - struct list_head frame; int top_field; int receiving; @@ -294,9 +292,6 @@ struct em28xx { /* frame properties */ int width; /* current frame width */ int height; /* current frame height */ - int frame_size; /* current frame size */ - int field_size; /* current field size */ - int bytesperline; int hscale; /* horizontal scale factor (see datasheet) */ int vscale; /* vertical scale factor (see datasheet) */ int interlaced; /* 1=interlace fileds, 0=just top fileds */ @@ -352,9 +347,7 @@ struct em28xx_fh { unsigned int stream_on:1; /* Locks streams */ int radio; - unsigned int width, height; struct videobuf_queue vb_vidq; - struct em28xx_fmt *fmt; enum v4l2_buf_type type; }; From dbad108bdcb30629c850f5606949510da010a686 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 13 Apr 2008 15:47:53 -0300 Subject: [PATCH 306/452] V4L/DVB (7568): Support for DVB-S demod PN1010 (clone of S5H1420) added This device is a clone of the PN1010 used by SkyStar2 rev2.7 . This patch adds support for the flexcop-device and makes the driver look a little bit nicer. It needs to be checked whether the driver is still ok for the budget-cards. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/s5h1420.c | 519 +++++++++++++-------- drivers/media/dvb/frontends/s5h1420.h | 62 +-- drivers/media/dvb/frontends/s5h1420_priv.h | 102 ++++ drivers/media/dvb/ttpci/budget.c | 1 + 4 files changed, 470 insertions(+), 214 deletions(-) create mode 100644 drivers/media/dvb/frontends/s5h1420_priv.h diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 1e2d602d371a..281e1cb2edc6 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -1,24 +1,26 @@ /* -Driver for Samsung S5H1420 QPSK Demodulator - -Copyright (C) 2005 Andrew de Quincey - -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. - -*/ + * Driver for + * Samsung S5H1420 and + * PnpNetwork PN1010 QPSK Demodulator + * + * Copyright (C) 2005 Andrew de Quincey + * Copyright (C) 2005-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. + */ #include #include @@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include +#include + + #include "dvb_frontend.h" #include "s5h1420.h" - - +#include "s5h1420_priv.h" #define TONE_FREQ 22000 struct s5h1420_state { struct i2c_adapter* i2c; const struct s5h1420_config* config; + struct dvb_frontend frontend; + struct i2c_adapter tuner_i2c_adapter; + + u8 CON_1_val; u8 postlocked:1; u32 fclk; u32 tunedfreq; fe_code_rate_t fec_inner; u32 symbol_rate; + + /* FIXME: ugly workaround for flexcop's incapable i2c-controller + * it does not support repeated-start, workaround: write addr-1 + * and then read + */ + u8 shadow[255]; }; static u32 s5h1420_getsymbolrate(struct s5h1420_state* state); @@ -54,43 +68,65 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe, static int debug; -#define dprintk if (debug) printk +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debugging"); + +#define dprintk(x...) do { \ + if (debug) \ + printk(KERN_DEBUG "S5H1420: " x); \ +} while (0) + +static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg) +{ + int ret; + u8 b[2]; + struct i2c_msg msg[] = { + { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 }, + { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 }, + }; + + b[0] = (reg - 1) & 0xff; + b[1] = state->shadow[(reg - 1) & 0xff]; + + if (state->config->repeated_start_workaround) { + ret = i2c_transfer(state->i2c, msg, 3); + if (ret != 3) + return ret; + } else { + ret = i2c_transfer(state->i2c, &msg[1], 2); + if (ret != 2) + return ret; + } + + /* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */ + + return b[0]; +} static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data) { - u8 buf [] = { reg, data }; + u8 buf[] = { reg, data }; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; int err; - if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data); + /* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */ + err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) { + dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data); return -EREMOTEIO; } + state->shadow[reg] = data; return 0; } -static u8 s5h1420_readreg (struct s5h1420_state* state, u8 reg) -{ - int ret; - u8 b0 [] = { reg }; - u8 b1 [] = { 0 }; - struct i2c_msg msg1 = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }; - struct i2c_msg msg2 = { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }; - - if ((ret = i2c_transfer (state->i2c, &msg1, 1)) != 1) - return ret; - - if ((ret = i2c_transfer (state->i2c, &msg2, 1)) != 1) - return ret; - - return b1[0]; -} - static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) { struct s5h1420_state* state = fe->demodulator_priv; + dprintk("enter %s\n", __func__); + switch(voltage) { case SEC_VOLTAGE_13: s5h1420_writereg(state, 0x3c, @@ -106,6 +142,7 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag break; } + dprintk("leave %s\n", __func__); return 0; } @@ -113,6 +150,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { struct s5h1420_state* state = fe->demodulator_priv; + dprintk("enter %s\n", __func__); switch(tone) { case SEC_TONE_ON: s5h1420_writereg(state, 0x3b, @@ -124,6 +162,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01); break; } + dprintk("leave %s\n", __func__); return 0; } @@ -137,6 +176,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, unsigned long timeout; int result = 0; + dprintk("enter %s\n", __func__); if (cmd->msg_len > 8) return -EINVAL; @@ -168,6 +208,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, /* restore original settings */ s5h1420_writereg(state, 0x3b, val); msleep(15); + dprintk("leave %s\n", __func__); return result; } @@ -289,6 +330,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status) struct s5h1420_state* state = fe->demodulator_priv; u8 val; + dprintk("enter %s\n", __func__); + if (status == NULL) return -EINVAL; @@ -297,13 +340,13 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status) /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert the inversion, wait a bit and check again */ - if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) { - val = s5h1420_readreg(state, 0x32); + if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) { + val = s5h1420_readreg(state, Vit10); if ((val & 0x07) == 0x03) { if (val & 0x08) - s5h1420_writereg(state, 0x31, 0x13); + s5h1420_writereg(state, Vit09, 0x13); else - s5h1420_writereg(state, 0x31, 0x1b); + s5h1420_writereg(state, Vit09, 0x1b); /* wait a bit then update lock status */ mdelay(200); @@ -312,68 +355,73 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status) } /* perform post lock setup */ - if ((*status & FE_HAS_LOCK) && (!state->postlocked)) { + if ((*status & FE_HAS_LOCK) && !state->postlocked) { /* calculate the data rate */ u32 tmp = s5h1420_getsymbolrate(state); - switch(s5h1420_readreg(state, 0x32) & 0x07) { - case 0: - tmp = (tmp * 2 * 1) / 2; - break; - - case 1: - tmp = (tmp * 2 * 2) / 3; - break; - - case 2: - tmp = (tmp * 2 * 3) / 4; - break; - - case 3: - tmp = (tmp * 2 * 5) / 6; - break; - - case 4: - tmp = (tmp * 2 * 6) / 7; - break; - - case 5: - tmp = (tmp * 2 * 7) / 8; - break; + switch (s5h1420_readreg(state, Vit10) & 0x07) { + case 0: tmp = (tmp * 2 * 1) / 2; break; + case 1: tmp = (tmp * 2 * 2) / 3; break; + case 2: tmp = (tmp * 2 * 3) / 4; break; + case 3: tmp = (tmp * 2 * 5) / 6; break; + case 4: tmp = (tmp * 2 * 6) / 7; break; + case 5: tmp = (tmp * 2 * 7) / 8; break; } + if (tmp == 0) { - printk("s5h1420: avoided division by 0\n"); + printk(KERN_ERR "s5h1420: avoided division by 0\n"); tmp = 1; } tmp = state->fclk / tmp; + /* set the MPEG_CLK_INTL for the calculated data rate */ - if (tmp < 4) + if (tmp < 2) val = 0x00; - else if (tmp < 8) + else if (tmp < 5) val = 0x01; - else if (tmp < 12) + else if (tmp < 9) val = 0x02; - else if (tmp < 16) + else if (tmp < 13) val = 0x03; - else if (tmp < 24) + else if (tmp < 17) val = 0x04; - else if (tmp < 32) + else if (tmp < 25) val = 0x05; - else + else if (tmp < 33) val = 0x06; - s5h1420_writereg(state, 0x22, val); + else + val = 0x07; + dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val); - /* DC freeze */ - s5h1420_writereg(state, 0x1f, s5h1420_readreg(state, 0x1f) | 0x01); + s5h1420_writereg(state, FEC01, 0x18); + s5h1420_writereg(state, FEC01, 0x10); + s5h1420_writereg(state, FEC01, val); - /* kicker disable + remove DC offset */ - s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) & 0x6f); + /* Enable "MPEG_Out" */ + val = s5h1420_readreg(state, Mpeg02); + s5h1420_writereg(state, Mpeg02, val | (1 << 6)); + + /* kicker disable */ + val = s5h1420_readreg(state, QPSK01) & 0x7f; + s5h1420_writereg(state, QPSK01, val); + + /* DC freeze TODO it was never activated by default or it can stay activated */ + + if (s5h1420_getsymbolrate(state) >= 20000000) { + s5h1420_writereg(state, Loop04, 0x8a); + s5h1420_writereg(state, Loop05, 0x6a); + } else { + s5h1420_writereg(state, Loop04, 0x58); + s5h1420_writereg(state, Loop05, 0x27); + } /* post-lock processing has been done! */ state->postlocked = 1; } + dprintk("leave %s\n", __func__); + return 0; } @@ -414,6 +462,7 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) static void s5h1420_reset(struct s5h1420_state* state) { + dprintk("%s\n", __func__); s5h1420_writereg (state, 0x01, 0x08); s5h1420_writereg (state, 0x01, 0x00); udelay(10); @@ -422,54 +471,52 @@ static void s5h1420_reset(struct s5h1420_state* state) static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_frontend_parameters *p) { + u8 v; u64 val; + dprintk("enter %s\n", __func__); + val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24); - if (p->u.qpsk.symbol_rate <= 21000000) { + if (p->u.qpsk.symbol_rate < 29000000) val *= 2; - } do_div(val, (state->fclk / 1000)); - s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0x7f); - s5h1420_writereg(state, 0x11, val >> 16); - s5h1420_writereg(state, 0x12, val >> 8); - s5h1420_writereg(state, 0x13, val & 0xff); - s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80); + dprintk("symbol rate register: %06llx\n", val); + + v = s5h1420_readreg(state, Loop01); + s5h1420_writereg(state, Loop01, v & 0x7f); + s5h1420_writereg(state, Tnco01, val >> 16); + s5h1420_writereg(state, Tnco02, val >> 8); + s5h1420_writereg(state, Tnco03, val & 0xff); + s5h1420_writereg(state, Loop01, v | 0x80); + dprintk("leave %s\n", __func__); } static u32 s5h1420_getsymbolrate(struct s5h1420_state* state) { - u64 val = 0; - int sampling = 2; - - if (s5h1420_readreg(state, 0x05) & 0x2) - sampling = 1; - - s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08); - val = s5h1420_readreg(state, 0x11) << 16; - val |= s5h1420_readreg(state, 0x12) << 8; - val |= s5h1420_readreg(state, 0x13); - s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7); - - val *= (state->fclk / 1000ULL); - do_div(val, ((1<<24) * sampling)); - - return (u32) (val * 1000ULL); + return state->symbol_rate; } static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset) { int val; + u8 v; + + dprintk("enter %s\n", __func__); /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so * divide fclk by 1000000 to get the correct value. */ val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000)); - s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0xbf); - s5h1420_writereg(state, 0x0e, val >> 16); - s5h1420_writereg(state, 0x0f, val >> 8); - s5h1420_writereg(state, 0x10, val & 0xff); - s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x40); + dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val); + + v = s5h1420_readreg(state, Loop01); + s5h1420_writereg(state, Loop01, v & 0xbf); + s5h1420_writereg(state, Pnco01, val >> 16); + s5h1420_writereg(state, Pnco02, val >> 8); + s5h1420_writereg(state, Pnco03, val & 0xff); + s5h1420_writereg(state, Loop01, v | 0x40); + dprintk("leave %s\n", __func__); } static int s5h1420_getfreqoffset(struct s5h1420_state* state) @@ -496,52 +543,53 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state, struct dvb_frontend_parameters *p) { u8 inversion = 0; + u8 vit08, vit09; - if (p->inversion == INVERSION_OFF) { + dprintk("enter %s\n", __func__); + + if (p->inversion == INVERSION_OFF) inversion = state->config->invert ? 0x08 : 0; - } else if (p->inversion == INVERSION_ON) { + else if (p->inversion == INVERSION_ON) inversion = state->config->invert ? 0 : 0x08; - } if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) { - s5h1420_writereg(state, 0x30, 0x3f); - s5h1420_writereg(state, 0x31, 0x00 | inversion); + vit08 = 0x3f; + vit09 = 0; } else { switch(p->u.qpsk.fec_inner) { case FEC_1_2: - s5h1420_writereg(state, 0x30, 0x01); - s5h1420_writereg(state, 0x31, 0x10 | inversion); + vit08 = 0x01; vit09 = 0x10; break; case FEC_2_3: - s5h1420_writereg(state, 0x30, 0x02); - s5h1420_writereg(state, 0x31, 0x11 | inversion); + vit08 = 0x02; vit09 = 0x11; break; case FEC_3_4: - s5h1420_writereg(state, 0x30, 0x04); - s5h1420_writereg(state, 0x31, 0x12 | inversion); + vit08 = 0x04; vit09 = 0x12; break; case FEC_5_6: - s5h1420_writereg(state, 0x30, 0x08); - s5h1420_writereg(state, 0x31, 0x13 | inversion); + vit08 = 0x08; vit09 = 0x13; break; case FEC_6_7: - s5h1420_writereg(state, 0x30, 0x10); - s5h1420_writereg(state, 0x31, 0x14 | inversion); + vit08 = 0x10; vit09 = 0x14; break; case FEC_7_8: - s5h1420_writereg(state, 0x30, 0x20); - s5h1420_writereg(state, 0x31, 0x15 | inversion); + vit08 = 0x20; vit09 = 0x15; break; default: return; } } + vit09 |= inversion; + dprintk("fec: %02x %02x\n", vit08, vit09); + s5h1420_writereg(state, Vit08, vit08); + s5h1420_writereg(state, Vit09, vit09); + dprintk("leave %s\n", __func__); } static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state) @@ -583,16 +631,19 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct s5h1420_state* state = fe->demodulator_priv; int frequency_delta; struct dvb_frontend_tune_settings fesettings; + uint8_t clock_settting; + + dprintk("enter %s\n", __func__); /* check if we should do a fast-tune */ memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters)); s5h1420_get_tune_settings(fe, &fesettings); frequency_delta = p->frequency - state->tunedfreq; if ((frequency_delta > -fesettings.max_drift) && - (frequency_delta < fesettings.max_drift) && - (frequency_delta != 0) && - (state->fec_inner == p->u.qpsk.fec_inner) && - (state->symbol_rate == p->u.qpsk.symbol_rate)) { + (frequency_delta < fesettings.max_drift) && + (frequency_delta != 0) && + (state->fec_inner == p->u.qpsk.fec_inner) && + (state->symbol_rate == p->u.qpsk.symbol_rate)) { if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, p); @@ -606,54 +657,93 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, } else { s5h1420_setfreqoffset(state, 0); } + dprintk("simple tune\n"); return 0; } + dprintk("tuning demod\n"); /* first of all, software reset */ s5h1420_reset(state); /* set s5h1420 fclk PLL according to desired symbol rate */ - if (p->u.qpsk.symbol_rate > 28000000) { - state->fclk = 88000000; - s5h1420_writereg(state, 0x03, 0x50); - s5h1420_writereg(state, 0x04, 0x40); - s5h1420_writereg(state, 0x05, 0xae); - } else if (p->u.qpsk.symbol_rate > 21000000) { + if (p->u.qpsk.symbol_rate > 33000000) + state->fclk = 80000000; + else if (p->u.qpsk.symbol_rate > 28500000) state->fclk = 59000000; - s5h1420_writereg(state, 0x03, 0x33); - s5h1420_writereg(state, 0x04, 0x40); - s5h1420_writereg(state, 0x05, 0xae); - } else { + else if (p->u.qpsk.symbol_rate > 25000000) + state->fclk = 86000000; + else if (p->u.qpsk.symbol_rate > 1900000) state->fclk = 88000000; - s5h1420_writereg(state, 0x03, 0x50); - s5h1420_writereg(state, 0x04, 0x40); - s5h1420_writereg(state, 0x05, 0xac); + else + state->fclk = 44000000; + + /* Clock */ + switch (state->fclk) { + default: + case 88000000: + clock_settting = 80; + break; + case 86000000: + clock_settting = 78; + break; + case 80000000: + clock_settting = 72; + break; + case 59000000: + clock_settting = 51; + break; + case 44000000: + clock_settting = 36; + break; } + dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32)); + s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8); + s5h1420_writereg(state, PLL02, 0x40); + s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32)); + + /* TODO DC offset removal, config parameter ? */ + if (p->u.qpsk.symbol_rate > 29000000) + s5h1420_writereg(state, QPSK01, 0xae | 0x10); + else + s5h1420_writereg(state, QPSK01, 0xac | 0x10); /* set misc registers */ - s5h1420_writereg(state, 0x02, 0x00); - s5h1420_writereg(state, 0x06, 0x00); - s5h1420_writereg(state, 0x07, 0xb0); - s5h1420_writereg(state, 0x0a, 0xe7); - s5h1420_writereg(state, 0x0b, 0x78); - s5h1420_writereg(state, 0x0c, 0x48); - s5h1420_writereg(state, 0x0d, 0x6b); - s5h1420_writereg(state, 0x2e, 0x8e); - s5h1420_writereg(state, 0x35, 0x33); - s5h1420_writereg(state, 0x38, 0x01); - s5h1420_writereg(state, 0x39, 0x7d); - s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32)); - s5h1420_writereg(state, 0x3c, 0x00); - s5h1420_writereg(state, 0x45, 0x61); - s5h1420_writereg(state, 0x46, 0x1d); + s5h1420_writereg(state, CON_1, 0x00); + s5h1420_writereg(state, QPSK02, 0x00); + s5h1420_writereg(state, Pre01, 0xb0); - /* start QPSK */ - s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1); + s5h1420_writereg(state, Loop01, 0xF0); + s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */ + s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */ + if (p->u.qpsk.symbol_rate > 20000000) + s5h1420_writereg(state, Loop04, 0x79); + else + s5h1420_writereg(state, Loop04, 0x58); + s5h1420_writereg(state, Loop05, 0x6b); + + if (p->u.qpsk.symbol_rate >= 8000000) + s5h1420_writereg(state, Post01, (0 << 6) | 0x10); + else if (p->u.qpsk.symbol_rate >= 4000000) + s5h1420_writereg(state, Post01, (1 << 6) | 0x10); + else + s5h1420_writereg(state, Post01, (3 << 6) | 0x10); + + s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */ + + s5h1420_writereg(state, Sync01, 0x33); + s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity); + s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */ + s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */ + + s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */ + s5h1420_writereg(state, DiS03, 0x00); + s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */ /* set tuner PLL */ if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, p); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); s5h1420_setfreqoffset(state, 0); } @@ -661,10 +751,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, s5h1420_setsymbolrate(state, p); s5h1420_setfec_inversion(state, p); + /* start QPSK */ + s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1); + state->fec_inner = p->u.qpsk.fec_inner; state->symbol_rate = p->u.qpsk.symbol_rate; state->postlocked = 0; state->tunedfreq = p->frequency; + + dprintk("leave %s\n", __func__); return 0; } @@ -717,11 +812,10 @@ static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) { struct s5h1420_state* state = fe->demodulator_priv; - if (enable) { - return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1); - } else { - return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe); - } + if (enable) + return s5h1420_writereg(state, 0x02, state->CON_1_val | 1); + else + return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe); } static int s5h1420_init (struct dvb_frontend* fe) @@ -729,7 +823,8 @@ static int s5h1420_init (struct dvb_frontend* fe) struct s5h1420_state* state = fe->demodulator_priv; /* disable power down and do reset */ - s5h1420_writereg(state, 0x02, 0x10); + state->CON_1_val = 0x10; + s5h1420_writereg(state, 0x02, state->CON_1_val); msleep(10); s5h1420_reset(state); @@ -739,26 +834,60 @@ static int s5h1420_init (struct dvb_frontend* fe) static int s5h1420_sleep(struct dvb_frontend* fe) { struct s5h1420_state* state = fe->demodulator_priv; - - return s5h1420_writereg(state, 0x02, 0x12); + state->CON_1_val = 0x12; + return s5h1420_writereg(state, 0x02, state->CON_1_val); } static void s5h1420_release(struct dvb_frontend* fe) { struct s5h1420_state* state = fe->demodulator_priv; + i2c_del_adapter(&state->tuner_i2c_adapter); kfree(state); } +static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) +{ + struct s5h1420_state *state = i2c_get_adapdata(i2c_adap); + struct i2c_msg m[1 + num]; + u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */ + + memset(m, 0, sizeof(struct i2c_msg) * (1 + num)); + + m[0].addr = state->config->demod_address; + m[0].buf = tx_open; + m[0].len = 2; + + memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); + + return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO; +} + +static struct i2c_algorithm s5h1420_tuner_i2c_algo = { + .master_xfer = s5h1420_tuner_i2c_tuner_xfer, + .functionality = s5h1420_tuner_i2c_func, +}; + +struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe) +{ + struct s5h1420_state *state = fe->demodulator_priv; + return &state->tuner_i2c_adapter; +} +EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter); + static struct dvb_frontend_ops s5h1420_ops; -struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, - struct i2c_adapter* i2c) +struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config, + struct i2c_adapter *i2c) { - struct s5h1420_state* state = NULL; - u8 identity; - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct s5h1420_state), GFP_KERNEL); + struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL); + u8 i; + if (state == NULL) goto error; @@ -772,24 +901,42 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, state->symbol_rate = 0; /* check if the demod is there + identify it */ - identity = s5h1420_readreg(state, 0x00); - if (identity != 0x03) + i = s5h1420_readreg(state, ID01); + if (i != 0x03) goto error; + memset(state->shadow, 0xff, sizeof(state->shadow)); + + for (i = 0; i < 0x50; i++) + state->shadow[i] = s5h1420_readreg(state, i); + /* create dvb_frontend */ memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; + + /* create tuner i2c adapter */ + strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE); + state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL, + state->tuner_i2c_adapter.algo = &s5h1420_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) { + printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n"); + goto error; + } + return &state->frontend; error: kfree(state); return NULL; } +EXPORT_SYMBOL(s5h1420_attach); static struct dvb_frontend_ops s5h1420_ops = { .info = { - .name = "Samsung S5H1420 DVB-S", + .name = "Samsung S5H1420/PnpNetwork PN1010 DVB-S", .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, @@ -826,10 +973,6 @@ static struct dvb_frontend_ops s5h1420_ops = { .set_voltage = s5h1420_set_voltage, }; -module_param(debug, int, 0644); - -MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver"); -MODULE_AUTHOR("Andrew de Quincey"); +MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver"); +MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher"); MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(s5h1420_attach); diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h index 2cc785012b23..4c913f142bc4 100644 --- a/drivers/media/dvb/frontends/s5h1420.h +++ b/drivers/media/dvb/frontends/s5h1420.h @@ -1,25 +1,26 @@ /* - Driver for S5H1420 QPSK Demodulators - - Copyright (C) 2005 Andrew de Quincey - - 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. - -*/ - + * Driver for + * Samsung S5H1420 and + * PnpNetwork PN1010 QPSK Demodulator + * + * Copyright (C) 2005 Andrew de Quincey + * Copyright (C) 2005-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 S5H1420_H #define S5H1420_H @@ -31,19 +32,28 @@ struct s5h1420_config u8 demod_address; /* does the inversion require inversion? */ - u8 invert:1; + u8 invert : 1; + + u8 repeated_start_workaround : 1; + u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */ }; #if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE)) -extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, - struct i2c_adapter* i2c); +extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config, + struct i2c_adapter *i2c); +extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe); #else -static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, - struct i2c_adapter* i2c) +static inline struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config, + struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } + +static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe) +{ + return NULL; +} #endif // CONFIG_DVB_S5H1420 #endif // S5H1420_H diff --git a/drivers/media/dvb/frontends/s5h1420_priv.h b/drivers/media/dvb/frontends/s5h1420_priv.h new file mode 100644 index 000000000000..d9c58d281816 --- /dev/null +++ b/drivers/media/dvb/frontends/s5h1420_priv.h @@ -0,0 +1,102 @@ +/* + * Driver for + * Samsung S5H1420 and + * PnpNetwork PN1010 QPSK Demodulator + * + * Copyright (C) 2005 Andrew de Quincey + * Copyright (C) 2005 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 S5H1420_PRIV +#define S5H1420_PRIV + +#include + +enum s5h1420_register { + ID01 = 0x00, + CON_0 = 0x01, + CON_1 = 0x02, + PLL01 = 0x03, + PLL02 = 0x04, + QPSK01 = 0x05, + QPSK02 = 0x06, + Pre01 = 0x07, + Post01 = 0x08, + Loop01 = 0x09, + Loop02 = 0x0a, + Loop03 = 0x0b, + Loop04 = 0x0c, + Loop05 = 0x0d, + Pnco01 = 0x0e, + Pnco02 = 0x0f, + Pnco03 = 0x10, + Tnco01 = 0x11, + Tnco02 = 0x12, + Tnco03 = 0x13, + Monitor01 = 0x14, + Monitor02 = 0x15, + Monitor03 = 0x16, + Monitor04 = 0x17, + Monitor05 = 0x18, + Monitor06 = 0x19, + Monitor07 = 0x1a, + Monitor12 = 0x1f, + + FEC01 = 0x22, + Soft01 = 0x23, + Soft02 = 0x24, + Soft03 = 0x25, + Soft04 = 0x26, + Soft05 = 0x27, + Soft06 = 0x28, + Vit01 = 0x29, + Vit02 = 0x2a, + Vit03 = 0x2b, + Vit04 = 0x2c, + Vit05 = 0x2d, + Vit06 = 0x2e, + Vit07 = 0x2f, + Vit08 = 0x30, + Vit09 = 0x31, + Vit10 = 0x32, + Vit11 = 0x33, + Vit12 = 0x34, + Sync01 = 0x35, + Sync02 = 0x36, + Rs01 = 0x37, + Mpeg01 = 0x38, + Mpeg02 = 0x39, + DiS01 = 0x3a, + DiS02 = 0x3b, + DiS03 = 0x3c, + DiS04 = 0x3d, + DiS05 = 0x3e, + DiS06 = 0x3f, + DiS07 = 0x40, + DiS08 = 0x41, + DiS09 = 0x42, + DiS10 = 0x43, + DiS11 = 0x44, + Rf01 = 0x45, + Err01 = 0x46, + Err02 = 0x47, + Err03 = 0x48, + Err04 = 0x49, +}; + + +#endif diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 829576dc2799..e36c32528e5c 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -358,6 +358,7 @@ static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend static struct s5h1420_config s5h1420_config = { .demod_address = 0x53, .invert = 1, + .cdclk_polarity = 1, }; static struct tda10086_config tda10086_config = { From 1881ee89e0fe03ac5bba9045acb3bea1818f9466 Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Sat, 12 Apr 2008 15:04:46 -0300 Subject: [PATCH 307/452] V4L/DVB (7571): mt312: Cleanup buffer variables of read/write functions Change type of buffer variables from void* to u8* to save some casts. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 5 +++++ drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/mt312.c | 12 ++++++------ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 0209644f222a..4284a3092c14 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -369,6 +369,11 @@ config DVB_TUNER_XC5000 This device is only used inside a SiP called togther with a demodulator for now. +config DVB_TUNER_ITD1000 + tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + comment "Miscellaneous devices" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 23304b3774b5..129367886bcc 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -52,3 +52,4 @@ obj-$(CONFIG_DVB_TUA6100) += tua6100.o obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o obj-$(CONFIG_DVB_S5H1409) += s5h1409.o obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o +obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index daca855c804a..b03a959ef2e8 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -58,7 +58,7 @@ static int debug; #define MT312_PLL_CLK 10000000UL /* 10 MHz */ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, - void *buf, const size_t count) + u8 *buf, const size_t count) { int ret; struct i2c_msg msg[2]; @@ -84,7 +84,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, int i; dprintk("R(%d):", reg & 0x7f); for (i = 0; i < count; i++) - printk(" %02x", ((const u8 *) buf)[i]); + printk(" %02x", buf[i]); printk("\n"); } @@ -92,7 +92,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, } static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, - const void *src, const size_t count) + const u8 *src, const size_t count) { int ret; u8 buf[count + 1]; @@ -102,7 +102,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, int i; dprintk("W(%d):", reg & 0x7f); for (i = 0; i < count; i++) - printk(" %02x", ((const u8 *) src)[i]); + printk(" %02x", src[i]); printk("\n"); } @@ -463,7 +463,7 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr) int ret; u8 buf[2]; - ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf)); + ret = mt312_read(state, M_SNR_H, buf, sizeof(buf)); if (ret < 0) return ret; @@ -478,7 +478,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc) int ret; u8 buf[2]; - ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf)); + ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf)); if (ret < 0) return ret; From 82cd2dff4a5562a081c8bbf449a1ae7b9ecb5b1b Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Sat, 12 Apr 2008 15:04:47 -0300 Subject: [PATCH 308/452] V4L/DVB (7572): mt312: Fix diseqc Correct the frequency of the emitted diseqc signal to 22kHz. Adds sleep(100) to wait for message to be transmitted. For now the only user of mt312 is b2c2-flexcop, and it does overwrite all diseqc related functions with own code. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mt312.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index b03a959ef2e8..32b419477887 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -270,7 +270,7 @@ static int mt312_initfe(struct dvb_frontend *fe) MT312_SYS_CLK) * 2, 1000000); /* DISEQC_RATIO */ - buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4); + buf[1] = mt312_div(MT312_PLL_CLK, 22000 * 4); ret = mt312_write(state, SYS_CLK, buf, sizeof(buf)); if (ret < 0) @@ -323,6 +323,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe, if (ret < 0) return ret; + /* is there a better way to wait for message to be transmitted */ + msleep(100); + /* set DISEQC_MODE[2:0] to zero if a return message is expected */ if (c->msg[0] & 0x02) { ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40)); From 111221fb676176dc90638d6004f1c26164ddd5ae Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Sat, 12 Apr 2008 15:04:48 -0300 Subject: [PATCH 309/452] V4L/DVB (7573): mt312: Supports different xtal frequencies Do not hardcode xtal frequency but allow different values for future zl10313 support. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mt312.c | 33 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index 32b419477887..1f478c8c0d4a 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -43,7 +43,8 @@ struct mt312_state { struct dvb_frontend frontend; u8 id; - u8 frequency; + unsigned long xtal; + u8 freq_mult; }; static int debug; @@ -53,8 +54,6 @@ static int debug; printk(KERN_DEBUG "mt312: " args); \ } while (0) -#define MT312_SYS_CLK 90000000UL /* 90 MHz */ -#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */ #define MT312_PLL_CLK 10000000UL /* 10 MHz */ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, @@ -209,7 +208,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr) dprintk("sym_rat_op=%d dec_ratio=%d\n", sym_rat_op, dec_ratio); dprintk("*sr(manual) = %lu\n", - (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) * + (((state->xtal * 8192) / (sym_rat_op + 8192)) * 2) - dec_ratio); } @@ -242,7 +241,7 @@ static int mt312_initfe(struct dvb_frontend *fe) /* wake up */ ret = mt312_writereg(state, CONFIG, - (state->frequency == 60 ? 0x88 : 0x8c)); + (state->freq_mult == 6 ? 0x88 : 0x8c)); if (ret < 0) return ret; @@ -266,11 +265,10 @@ static int mt312_initfe(struct dvb_frontend *fe) } /* SYS_CLK */ - buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK : - MT312_SYS_CLK) * 2, 1000000); + buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000); /* DISEQC_RATIO */ - buf[1] = mt312_div(MT312_PLL_CLK, 22000 * 4); + buf[1] = mt312_div(state->xtal, 22000 * 4); ret = mt312_write(state, SYS_CLK, buf, sizeof(buf)); if (ret < 0) @@ -535,17 +533,17 @@ static int mt312_set_frontend(struct dvb_frontend *fe, return ret; if (p->u.qpsk.symbol_rate >= 30000000) { /* Note that 30MS/s should use 90MHz */ - if ((config_val & 0x0c) == 0x08) { + if (state->freq_mult == 6) { /* We are running 60MHz */ - state->frequency = 90; + state->freq_mult = 9; ret = mt312_initfe(fe); if (ret < 0) return ret; } } else { - if ((config_val & 0x0c) == 0x0C) { + if (state->freq_mult == 9) { /* We are running 90MHz */ - state->frequency = 60; + state->freq_mult = 6; ret = mt312_initfe(fe); if (ret < 0) return ret; @@ -664,6 +662,7 @@ static void mt312_release(struct dvb_frontend *fe) kfree(state); } +#define MT312_SYS_CLK 90000000UL /* 90 MHz */ static struct dvb_frontend_ops vp310_mt312_ops = { .info = { @@ -671,8 +670,8 @@ static struct dvb_frontend_ops vp310_mt312_ops = { .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, - .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, - .symbol_rate_min = MT312_SYS_CLK / 128, + .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */ + .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */ .symbol_rate_max = MT312_SYS_CLK / 2, .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | @@ -729,11 +728,13 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config, switch (state->id) { case ID_VP310: strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S"); - state->frequency = 90; + state->xtal = MT312_PLL_CLK; + state->freq_mult = 9; break; case ID_MT312: strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S"); - state->frequency = 60; + state->xtal = MT312_PLL_CLK; + state->freq_mult = 6; break; default: printk(KERN_WARNING "Only Zarlink VP310/MT312" From 6a5cbd591c703491b62892682adc124ece67f3a9 Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Sat, 12 Apr 2008 15:04:49 -0300 Subject: [PATCH 310/452] V4L/DVB (7574): mt312: Add support for zl10313 demod Add zl10313 support to mt312 driver. zl10313 uses 10.111MHz xtal. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mt312.c | 90 +++++++++++++++++++++--- drivers/media/dvb/frontends/mt312_priv.h | 5 +- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index 1f478c8c0d4a..e17a36180f9c 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -1,7 +1,8 @@ /* - Driver for Zarlink VP310/MT312 Satellite Channel Decoder + Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder Copyright (C) 2003 Andreas Oberritter + Copyright (C) 2008 Matthias Schwarzott 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 @@ -55,6 +56,7 @@ static int debug; } while (0) #define MT312_PLL_CLK 10000000UL /* 10 MHz */ +#define MT312_PLL_CLK_10_111 10111000UL /* 10.111 MHz */ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, u8 *buf, const size_t count) @@ -264,6 +266,32 @@ static int mt312_initfe(struct dvb_frontend *fe) return ret; } + switch (state->id) { + case ID_ZL10313: + /* enable ADC */ + ret = mt312_writereg(state, GPP_CTRL, 0x80); + if (ret < 0) + return ret; + + /* configure ZL10313 for optimal ADC performance */ + buf[0] = 0x80; + buf[1] = 0xB0; + ret = mt312_write(state, HW_CTRL, buf, 2); + if (ret < 0) + return ret; + + /* enable MPEG output and ADCs */ + ret = mt312_writereg(state, HW_CTRL, 0x00); + if (ret < 0) + return ret; + + ret = mt312_writereg(state, MPEG_CTRL, 0x00); + if (ret < 0) + return ret; + + break; + } + /* SYS_CLK */ buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000); @@ -278,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe) if (ret < 0) return ret; - ret = mt312_writereg(state, OP_CTRL, 0x53); + /* different MOCLK polarity */ + switch (state->id) { + case ID_ZL10313: + buf[0] = 0x33; + break; + default: + buf[0] = 0x53; + break; + } + + ret = mt312_writereg(state, OP_CTRL, buf[0]); if (ret < 0) return ret; @@ -552,6 +590,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe, break; case ID_MT312: + case ID_ZL10313: break; default: @@ -617,11 +656,29 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct mt312_state *state = fe->demodulator_priv; - if (enable) { - return mt312_writereg(state, GPP_CTRL, 0x40); - } else { - return mt312_writereg(state, GPP_CTRL, 0x00); + u8 val = 0x00; + int ret; + + switch (state->id) { + case ID_ZL10313: + ret = mt312_readreg(state, GPP_CTRL, &val); + if (ret < 0) + goto error; + + /* preserve this bit to not accidently shutdown ADC */ + val &= 0x80; + break; } + + if (enable) + val |= 0x40; + else + val &= ~0x40; + + ret = mt312_writereg(state, GPP_CTRL, val); + +error: + return ret; } static int mt312_sleep(struct dvb_frontend *fe) @@ -635,6 +692,18 @@ static int mt312_sleep(struct dvb_frontend *fe) if (ret < 0) return ret; + if (state->id == ID_ZL10313) { + /* reset ADC */ + ret = mt312_writereg(state, GPP_CTRL, 0x00); + if (ret < 0) + return ret; + + /* full shutdown of ADCs, mpeg bus tristated */ + ret = mt312_writereg(state, HW_CTRL, 0x0d); + if (ret < 0) + return ret; + } + ret = mt312_readreg(state, CONFIG, &config); if (ret < 0) return ret; @@ -736,8 +805,13 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config, state->xtal = MT312_PLL_CLK; state->freq_mult = 6; break; + case ID_ZL10313: + strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S"); + state->xtal = MT312_PLL_CLK_10_111; + state->freq_mult = 9; + break; default: - printk(KERN_WARNING "Only Zarlink VP310/MT312" + printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313" " are supported chips.\n"); goto error; } @@ -753,7 +827,7 @@ EXPORT_SYMBOL(vp310_mt312_attach); module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver"); +MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver"); MODULE_AUTHOR("Andreas Oberritter "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/mt312_priv.h b/drivers/media/dvb/frontends/mt312_priv.h index 5e0b95b5337b..a3959f94d639 100644 --- a/drivers/media/dvb/frontends/mt312_priv.h +++ b/drivers/media/dvb/frontends/mt312_priv.h @@ -110,6 +110,8 @@ enum mt312_reg_addr { VIT_ERRPER_H = 83, VIT_ERRPER_M = 84, VIT_ERRPER_L = 85, + HW_CTRL = 84, /* ZL10313 only */ + MPEG_CTRL = 85, /* ZL10313 only */ VIT_SETUP = 86, VIT_REF0 = 87, VIT_REF1 = 88, @@ -156,7 +158,8 @@ enum mt312_reg_addr { enum mt312_model_id { ID_VP310 = 1, - ID_MT312 = 3 + ID_MT312 = 3, + ID_ZL10313 = 5, }; #endif /* DVB_FRONTENDS_MT312_PRIV */ From 11d3f323930ef625c1018ed13adeb04127c356e0 Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Sat, 12 Apr 2008 15:04:50 -0300 Subject: [PATCH 311/452] V4L/DVB (7575): mt312: add attach-time setting to invert lnb-voltage Add a setting to config struct for inversion of lnb-voltage. Needed for support of Avermedia A700 cards. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mt312.c | 7 ++++++- drivers/media/dvb/frontends/mt312.h | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index e17a36180f9c..081ca3398c76 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -422,11 +422,16 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v) { struct mt312_state *state = fe->demodulator_priv; const u8 volt_tab[3] = { 0x00, 0x40, 0x00 }; + u8 val; if (v > SEC_VOLTAGE_OFF) return -EINVAL; - return mt312_writereg(state, DISEQC_MODE, volt_tab[v]); + val = volt_tab[v]; + if (state->config->voltage_inverted) + val ^= 0x40; + + return mt312_writereg(state, DISEQC_MODE, val); } static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s) diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h index afe24fd822bd..96338f0c4dd4 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb/frontends/mt312.h @@ -31,6 +31,9 @@ struct mt312_config { /* the demodulator's i2c address */ u8 demod_address; + + /* inverted voltage setting */ + int voltage_inverted:1; }; #if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE)) From c9dd82c2f978e4ebac1cbb7cee8d379d1090154b Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 29 Mar 2008 21:28:07 -0300 Subject: [PATCH 312/452] 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 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 */ From ca19aaa510b150ca358166b29eb2bb62ad971f76 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 13 Apr 2008 15:49:22 -0300 Subject: [PATCH 313/452] V4L/DVB (7569): Added support for SkyStar2 rev2.7 and ITD1000 DVB-S tuner This patches adds support for the SkyStar2 rev2.7 with the PN1010/ITD1000 Frontend. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/Kconfig | 2 + drivers/media/dvb/b2c2/Makefile | 1 + drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 48 +++ drivers/media/dvb/frontends/itd1000.c | 400 +++++++++++++++++++++ drivers/media/dvb/frontends/itd1000.h | 42 +++ drivers/media/dvb/frontends/itd1000_priv.h | 88 +++++ 6 files changed, 581 insertions(+) create mode 100644 drivers/media/dvb/frontends/itd1000.c create mode 100644 drivers/media/dvb/frontends/itd1000.h create mode 100644 drivers/media/dvb/frontends/itd1000_priv.h diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 8193d88d171c..6ec5afba1ca7 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_S5H1420 if !DVB_FE_CUSTOMISE + select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE help diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile index 7d5334106d5a..870e2848c296 100644 --- a/drivers/media/dvb/b2c2/Makefile +++ b/drivers/media/dvb/b2c2/Makefile @@ -2,6 +2,7 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \ flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o + ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),) b2c2-flexcop-objs += flexcop-dma.o endif diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 6759c3ad234a..04989b7a165c 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -19,6 +19,9 @@ #include "dvb-pll.h" #include "tuner-simple.h" +#include "s5h1420.h" +#include "itd1000.h" + #include "cx24123.h" #include "cx24113.h" @@ -482,6 +485,18 @@ static struct stv0297_config alps_tdee4_stv0297_config = { }; +/* SkyStar2 rev2.7 (a/u) */ +static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { + .demod_address = 0x53, + .invert = 1, + .repeated_start_workaround = 1, +}; + +static struct itd1000_config skystar2_rev2_7_itd1000_config = { + .i2c_address = 0x61, +}; + +/* SkyStar2 rev2.8 */ static struct cx24123_config skystar2_rev2_8_cx24123_config = { .demod_address = 0x55, .dont_use_pll = 1, @@ -500,6 +515,39 @@ int flexcop_frontend_init(struct flexcop_device *fc) struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap; struct i2c_adapter *i2c_tuner; + /* enable no_base_addr - no repeated start when reading */ + fc->fc_i2c_adap[0].no_base_addr = 1; + fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c); + if (fc->fe != NULL) { + flexcop_ibi_value r108; + i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe); + ops = &fc->fe->ops; + + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; + + fc->dev_type = FC_SKY_REV27; + + /* enable no_base_addr - no repeated start when reading */ + fc->fc_i2c_adap[2].no_base_addr = 1; + if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL) + err("ISL6421 could NOT be attached"); + else + info("ISL6421 successfully attached"); + + /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */ + r108.raw = 0x00000506; + fc->write_ibi_reg(fc, tw_sm_c_108, r108); + if (i2c_tuner) { + if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL) + err("ITD1000 could NOT be attached"); + else + info("ITD1000 successfully attached"); + } + goto fe_found; + } + fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */ + /* try the sky v2.8 (cx24123, isl6421) */ fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config, i2c); diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c new file mode 100644 index 000000000000..04c562ccf990 --- /dev/null +++ b/drivers/media/dvb/frontends/itd1000.c @@ -0,0 +1,400 @@ +/* + * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite" + * + * 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.= + */ + +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" + +#include "itd1000.h" +#include "itd1000_priv.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); + +#define deb(args...) do { \ + if (debug) { \ + printk(KERN_DEBUG "ITD1000: " args);\ + printk("\n"); \ + } \ +} while (0) + +#define warn(args...) do { \ + printk(KERN_WARNING "ITD1000: " args); \ + printk("\n"); \ +} while (0) + +#define info(args...) do { \ + printk(KERN_INFO "ITD1000: " args); \ + printk("\n"); \ +} while (0) + +/* don't write more than one byte with flexcop behind */ +static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len) +{ + u8 buf[1+len]; + struct i2c_msg msg = { + .addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1 + }; + buf[0] = reg; + memcpy(&buf[1], v, len); + + /* deb("wr %02x: %02x", reg, v[0]); */ + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "itd1000 I2C write failed\n"); + return -EREMOTEIO; + } + return 0; +} + +static int itd1000_read_reg(struct itd1000_state *state, u8 reg) +{ + u8 val; + struct i2c_msg msg[2] = { + { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, + { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = &val, .len = 1 }, + }; + + /* ugly flexcop workaround */ + itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1); + + if (i2c_transfer(state->i2c, msg, 2) != 2) { + warn("itd1000 I2C read failed"); + return -EREMOTEIO; + } + return val; +} + +static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v) +{ + int ret = itd1000_write_regs(state, r, &v, 1); + state->shadow[r] = v; + return ret; +} + + +static struct { + u32 symbol_rate; + u8 pgaext : 4; /* PLLFH */ + u8 bbgvmin : 4; /* BBGVMIN */ +} itd1000_lpf_pga[] = { + { 0, 0x8, 0x3 }, + { 5200000, 0x8, 0x3 }, + { 12200000, 0x4, 0x3 }, + { 15400000, 0x2, 0x3 }, + { 19800000, 0x2, 0x3 }, + { 21500000, 0x2, 0x3 }, + { 24500000, 0x2, 0x3 }, + { 28400000, 0x2, 0x3 }, + { 33400000, 0x2, 0x3 }, + { 34400000, 0x1, 0x4 }, + { 34400000, 0x1, 0x4 }, + { 38400000, 0x1, 0x4 }, + { 38400000, 0x1, 0x4 }, + { 40400000, 0x1, 0x4 }, + { 45400000, 0x1, 0x4 }, +}; + +static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate) +{ + u8 i; + u8 con1 = itd1000_read_reg(state, CON1) & 0xfd; + u8 pllfh = itd1000_read_reg(state, PLLFH) & 0x0f; + u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0; + u8 bw = itd1000_read_reg(state, BW) & 0xf0; + + deb("symbol_rate = %d", symbol_rate); + + /* not sure what is that ? - starting to download the table */ + itd1000_write_reg(state, CON1, con1 | (1 << 1)); + + for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++) + if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) { + deb("symrate: index: %d pgaext: %x, bbgvmin: %x", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin); + itd1000_write_reg(state, PLLFH, pllfh | (itd1000_lpf_pga[i].pgaext << 4)); + itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin)); + itd1000_write_reg(state, BW, bw | (i & 0x0f)); + break; + } + + itd1000_write_reg(state, CON1, con1 | (0 << 1)); +} + +static struct { + u8 vcorg; + u32 fmax_rg; +} itd1000_vcorg[] = { + { 1, 920000 }, + { 2, 971000 }, + { 3, 1031000 }, + { 4, 1091000 }, + { 5, 1171000 }, + { 6, 1281000 }, + { 7, 1381000 }, + { 8, 500000 }, /* this is intentional. */ + { 9, 1451000 }, + { 10, 1531000 }, + { 11, 1631000 }, + { 12, 1741000 }, + { 13, 1891000 }, + { 14, 2071000 }, + { 15, 2250000 }, +}; + +static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz) +{ + u8 i; + u8 gvbb_i2c = itd1000_read_reg(state, GVBB_I2C) & 0xbf; + u8 vco_chp1_i2c = itd1000_read_reg(state, VCO_CHP1_I2C) & 0x0f; + u8 adcout; + + /* reserved bit again (reset ?) */ + itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6)); + + for (i = 0; i < ARRAY_SIZE(itd1000_vcorg); i++) { + if (freq_khz < itd1000_vcorg[i].fmax_rg) { + itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | (itd1000_vcorg[i].vcorg << 4)); + msleep(1); + + adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f; + + deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c); + + if (adcout > 13) { + if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15)) + itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg + 1) << 4)); + } else if (adcout < 2) { + if (!(itd1000_vcorg[i].vcorg == 1 || itd1000_vcorg[i].vcorg == 9)) + itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg - 1) << 4)); + } + break; + } + } +} + +struct { + u32 freq; + u8 values[10]; /* RFTR, RFST1 - RFST9 */ +} itd1000_fre_values[] = { + { 1075000, { 0x59, 0x1d, 0x1c, 0x17, 0x16, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } }, + { 1250000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } }, + { 1450000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } }, + { 1650000, { 0x69, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } }, + { 1750000, { 0x69, 0x1e, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } }, + { 1850000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } }, + { 1900000, { 0x69, 0x1d, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } }, + { 1950000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0d, 0x0b, 0x0a } }, + { 2050000, { 0x69, 0x1e, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0b, 0x0a } }, + { 2150000, { 0x69, 0x1d, 0x1c, 0x17, 0x15, 0x14, 0x13, 0x0f, 0x0e, 0x0b } } +}; + + +#define FREF 16 + +static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz) +{ + int i, j; + u32 plln, pllf; + u64 tmp; + + plln = (freq_khz * 1000) / 2 / FREF; + + /* Compute the factional part times 1000 */ + tmp = plln % 1000000; + plln /= 1000000; + + tmp *= 1048576; + do_div(tmp, 1000000); + pllf = (u32) tmp; + + state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF; + deb("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d", freq_khz, state->frequency, pllf, plln); + + itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */; + itd1000_write_reg(state, PLLNL, plln & 0xff); + itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f)); + itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff); + itd1000_write_reg(state, PLLFL, (pllf >> 0) & 0xff); + + for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) { + if (freq_khz <= itd1000_fre_values[i].freq) { + deb("fre_values: %d", i); + itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]); + for (j = 0; j < 9; j++) + itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]); + break; + } + } + + itd1000_set_vco(state, freq_khz); +} + +static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +{ + struct itd1000_state *state = fe->tuner_priv; + u8 pllcon1; + + itd1000_set_lo(state, p->frequency); + itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate); + + pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f; + itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7)); + itd1000_write_reg(state, PLLCON1, pllcon1); + + return 0; +} + +static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct itd1000_state *state = fe->tuner_priv; + *frequency = state->frequency; + return 0; +} + +static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + return 0; +} + +static u8 itd1000_init_tab[][2] = { + { PLLCON1, 0x65 }, /* Register does not change */ + { PLLNH, 0x80 }, /* Bits [7:6] do not change */ + { RESERVED_0X6D, 0x3b }, + { VCO_CHP2_I2C, 0x12 }, + { 0x72, 0xf9 }, /* No such regsister defined */ + { RESERVED_0X73, 0xff }, + { RESERVED_0X74, 0xb2 }, + { RESERVED_0X75, 0xc7 }, + { EXTGVBBRF, 0xf0 }, + { DIVAGCCK, 0x80 }, + { BBTR, 0xa0 }, + { RESERVED_0X7E, 0x4f }, + { 0x82, 0x88 }, /* No such regsister defined */ + { 0x83, 0x80 }, /* No such regsister defined */ + { 0x84, 0x80 }, /* No such regsister defined */ + { RESERVED_0X85, 0x74 }, + { RESERVED_0X86, 0xff }, + { RESERVED_0X88, 0x02 }, + { RESERVED_0X89, 0x16 }, + { RFST0, 0x1f }, + { RESERVED_0X94, 0x66 }, + { RESERVED_0X95, 0x66 }, + { RESERVED_0X96, 0x77 }, + { RESERVED_0X97, 0x99 }, + { RESERVED_0X98, 0xff }, + { RESERVED_0X99, 0xfc }, + { RESERVED_0X9A, 0xba }, + { RESERVED_0X9B, 0xaa }, +}; + +static u8 itd1000_reinit_tab[][2] = { + { VCO_CHP1_I2C, 0x8a }, + { BW, 0x87 }, + { GVBB_I2C, 0x03 }, + { BBGVMIN, 0x03 }, + { CON1, 0x2e }, +}; + + +static int itd1000_init(struct dvb_frontend *fe) +{ + struct itd1000_state *state = fe->tuner_priv; + int i; + + for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++) + itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]); + + for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++) + itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]); + + return 0; +} + +static int itd1000_sleep(struct dvb_frontend *fe) +{ + return 0; +} + +static int itd1000_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static const struct dvb_tuner_ops itd1000_tuner_ops = { + .info = { + .name = "Integrant ITD1000", + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = 125, /* kHz for QPSK frontends */ + }, + + .release = itd1000_release, + + .init = itd1000_init, + .sleep = itd1000_sleep, + + .set_params = itd1000_set_parameters, + .get_frequency = itd1000_get_frequency, + .get_bandwidth = itd1000_get_bandwidth +}; + + +struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg) +{ + struct itd1000_state *state = NULL; + u8 i = 0; + + state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL); + if (state == NULL) + return NULL; + + state->cfg = cfg; + state->i2c = i2c; + + i = itd1000_read_reg(state, 0); + if (i != 0) { + kfree(state); + return NULL; + } + info("successfully identified (ID: %d)", i); + + memset(state->shadow, 0xff, sizeof(state->shadow)); + for (i = 0x65; i < 0x9c; i++) + state->shadow[i] = itd1000_read_reg(state, i); + + memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = state; + + return fe; +} +EXPORT_SYMBOL(itd1000_attach); + +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_DESCRIPTION("Integrant ITD1000 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb/frontends/itd1000.h new file mode 100644 index 000000000000..5e18df071b88 --- /dev/null +++ b/drivers/media/dvb/frontends/itd1000.h @@ -0,0 +1,42 @@ +/* + * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite" + * + * Copyright (c) 2007 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 ITD1000_H +#define ITD1000_H + +struct dvb_frontend; +struct i2c_adapter; + +struct itd1000_config { + u8 i2c_address; +}; + +#if defined(CONFIG_DVB_TUNER_ITD1000) || (defined(CONFIG_DVB_TUNER_ITD1000_MODULE) && defined(MODULE)) +extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg); +#else +static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h new file mode 100644 index 000000000000..8cdc54e57903 --- /dev/null +++ b/drivers/media/dvb/frontends/itd1000_priv.h @@ -0,0 +1,88 @@ +/* + * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite" + * + * Copyright (c) 2007 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 ITD1000_PRIV_H +#define ITD1000_PRIV_H + +struct itd1000_state { + struct itd1000_config *cfg; + struct i2c_adapter *i2c; + + u32 frequency; /* contains the value resulting from the LO-setting */ + + /* ugly workaround for flexcop's incapable i2c-controller + * FIXME, if possible + */ + u8 shadow[255]; +}; + +enum itd1000_register { + VCO_CHP1 = 0x65, + VCO_CHP2, + PLLCON1, + PLLNH, + PLLNL, + PLLFH, + PLLFM, + PLLFL, + RESERVED_0X6D, + PLLLOCK, + VCO_CHP2_I2C, + VCO_CHP1_I2C, + BW, + RESERVED_0X73 = 0x73, + RESERVED_0X74, + RESERVED_0X75, + GVBB, + GVRF, + GVBB_I2C, + EXTGVBBRF, + DIVAGCCK, + BBTR, + RFTR, + BBGVMIN, + RESERVED_0X7E, + RESERVED_0X85 = 0x85, + RESERVED_0X86, + CON1, + RESERVED_0X88, + RESERVED_0X89, + RFST0, + RFST1, + RFST2, + RFST3, + RFST4, + RFST5, + RFST6, + RFST7, + RFST8, + RFST9, + RESERVED_0X94, + RESERVED_0X95, + RESERVED_0X96, + RESERVED_0X97, + RESERVED_0X98, + RESERVED_0X99, + RESERVED_0X9A, + RESERVED_0X9B, +}; + +#endif From a53a45567cb4879c46bb019757cdeb1b1ecabbd5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:47:03 -0300 Subject: [PATCH 314/452] V4L/DVB (7575a): Revert changeset 4c3b01f71181a52ab7735a7c52b1aa2232826075 Due to the patch order change, pvrusb2 were broken. So, changeset 4c3b01f71181a52ab7735a7c52b1aa2232826075 were applied at mainstream to fix. After the pvrusb2 changes, this patch is no longer required and should be reverted. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index c33ba35a4ddf..3434b0e6d675 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -218,16 +218,12 @@ static const struct pvr2_device_desc pvr2_device_73xxx = { .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx), .flag_has_cx25840 = !0, .flag_has_hauppauge_rom = !0, -#if 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, .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, -#else - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, -#endif }; From b9bc07a006ae94d7b3dd5db873bcf10ceb749253 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Thu, 10 Apr 2008 09:40:31 -0300 Subject: [PATCH 315/452] V4L/DVB (7579): bttv: Fix memory leak in radio_release Fix the leak of the bttv_fh structure allocated in radio_open which was introduced by commit 5cd3955cb8adfc1edf481e9e1cb2289db50ccacb. Signed-off-by: Robert Fitzsimons Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 79da9d01d715..2ca3e9cfb2bb 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3463,6 +3463,9 @@ static int radio_release(struct inode *inode, struct file *file) struct bttv *btv = fh->btv; struct rds_command cmd; + file->private_data = NULL; + kfree(fh); + btv->radio_user--; bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd); From 9faa2d75822e1950b3aacc8ccbdf0cdb595e47de Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 13 Apr 2008 08:48:43 -0300 Subject: [PATCH 316/452] V4L/DVB (7580): Fix concurrent read from /proc/videocodecs Observation one: ->write_proc and ->data assignments aren't needed. Removed. Observation two: codecs lists are unprotected. Patch doesn't fix this. Observation three: /proc/videocodecs printout is done to temporary _global_ buffer which is freed in between. Consequently, two users hitting this file can screwup each other. Steps to reproduce: modprobe videocodec while true; do cat /proc/videocodecs &>/dev/null; done & while true; do cat /proc/videocodecs &>/dev/null; done & The fix is switching to seq_files, this removes code, especially some line-length "logic". Signed-off-by: Alexey Dobriyan Acked-by: Jan Kara Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videocodec.c | 113 ++++++------------------------- 1 file changed, 19 insertions(+), 94 deletions(-) diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c index b30b6b2a9a85..cf24956f3204 100644 --- a/drivers/media/video/videocodec.c +++ b/drivers/media/video/videocodec.c @@ -39,6 +39,7 @@ #ifdef CONFIG_PROC_FS #include +#include #include #endif @@ -320,56 +321,22 @@ videocodec_unregister (const struct videocodec *codec) } #ifdef CONFIG_PROC_FS -/* ============ */ -/* procfs stuff */ -/* ============ */ - -static char *videocodec_buf = NULL; -static int videocodec_bufsize; - -static int -videocodec_build_table (void) +static int proc_videocodecs_show(struct seq_file *m, void *v) { struct codec_list *h = codeclist_top; struct attached_list *a; - int i = 0, size; - // sum up amount of slaves plus their attached masters - while (h) { - i += h->attached + 1; - h = h->next; - } -#define LINESIZE 100 - size = LINESIZE * (i + 1); - - dprintk(3, "videocodec_build table: %d entries, %d bytes\n", i, - size); - - kfree(videocodec_buf); - videocodec_buf = kmalloc(size, GFP_KERNEL); - - if (!videocodec_buf) - return 0; - - i = 0; - i += scnprintf(videocodec_buf + i, size - 1, - "lave or attached aster name type flags magic "); - i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n"); + seq_printf(m, "lave or attached aster name type flags magic "); + seq_printf(m, "(connected as)\n"); h = codeclist_top; while (h) { - if (i > (size - LINESIZE)) - break; // security check - i += scnprintf(videocodec_buf + i, size -i -1, - "S %32s %04x %08lx %08lx (TEMPLATE)\n", + seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n", h->codec->name, h->codec->type, h->codec->flags, h->codec->magic); a = h->list; while (a) { - if (i > (size - LINESIZE)) - break; // security check - i += scnprintf(videocodec_buf + i, size -i -1, - "M %32s %04x %08lx %08lx (%s)\n", + seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n", a->codec->master_data->name, a->codec->master_data->type, a->codec->master_data->flags, @@ -380,54 +347,21 @@ videocodec_build_table (void) h = h->next; } - return i; + return 0; } -//The definition: -//typedef int (read_proc_t)(char *page, char **start, off_t off, -// int count, int *eof, void *data); - -static int -videocodec_info (char *buffer, - char **buffer_location, - off_t offset, - int buffer_length, - int *eof, - void *data) +static int proc_videocodecs_open(struct inode *inode, struct file *file) { - int size; - - dprintk(3, "videocodec_info: offset: %ld, len %d / size %d\n", - offset, buffer_length, videocodec_bufsize); - - if (offset == 0) { - videocodec_bufsize = videocodec_build_table(); - } - if ((offset < 0) || (offset >= videocodec_bufsize)) { - dprintk(4, - "videocodec_info: call delivers no result, return 0\n"); - *eof = 1; - return 0; - } - - if (buffer_length < (videocodec_bufsize - offset)) { - dprintk(4, "videocodec_info: %ld needed, %d got\n", - videocodec_bufsize - offset, buffer_length); - size = buffer_length; - } else { - dprintk(4, "videocodec_info: last reading of %ld bytes\n", - videocodec_bufsize - offset); - size = videocodec_bufsize - offset; - *eof = 1; - } - - memcpy(buffer, videocodec_buf + offset, size); - /* doesn't work... */ - /* copy_to_user(buffer, videocodec_buf+offset, size); */ - /* *buffer_location = videocodec_buf+offset; */ - - return size; + return single_open(file, proc_videocodecs_show, NULL); } + +static const struct file_operations videocodecs_proc_fops = { + .owner = THIS_MODULE, + .open = proc_videocodecs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif /* ===================== */ @@ -444,16 +378,8 @@ videocodec_init (void) VIDEOCODEC_VERSION); #ifdef CONFIG_PROC_FS - videocodec_buf = NULL; - videocodec_bufsize = 0; - - videocodec_proc_entry = create_proc_entry("videocodecs", 0, NULL); - if (videocodec_proc_entry) { - videocodec_proc_entry->read_proc = videocodec_info; - videocodec_proc_entry->write_proc = NULL; - videocodec_proc_entry->data = NULL; - videocodec_proc_entry->owner = THIS_MODULE; - } else { + videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops); + if (!videocodec_proc_entry) { dprintk(1, KERN_ERR "videocodec: can't init procfs.\n"); } #endif @@ -465,7 +391,6 @@ videocodec_exit (void) { #ifdef CONFIG_PROC_FS remove_proc_entry("videocodecs", NULL); - kfree(videocodec_buf); #endif } From 0b9c2b7a413c0e79254f17bbe095cee24885cd4b Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 10 Apr 2008 21:34:39 -0300 Subject: [PATCH 317/452] V4L/DVB (7582): proc: switch /proc/driver/radio-typhoon to seq_file interface Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-typhoon.c | 40 +++++++++++++++++------------ 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 8b9888337bd1..18f2abd7e255 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -35,6 +35,7 @@ #include /* Initdata */ #include /* request_region */ #include /* radio card status report */ +#include #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ @@ -93,9 +94,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency); static void typhoon_mute(struct typhoon_device *dev); static void typhoon_unmute(struct typhoon_device *dev); static int typhoon_setvol(struct typhoon_device *dev, int vol); -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS -static int typhoon_get_info(char *buf, char **start, off_t offset, int len); -#endif static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) { @@ -368,30 +366,39 @@ static struct video_device typhoon_radio = #ifdef CONFIG_RADIO_TYPHOON_PROC_FS -static int typhoon_get_info(char *buf, char **start, off_t offset, int len) +static int typhoon_proc_show(struct seq_file *m, void *v) { - char *out = buf; - #ifdef MODULE #define MODULEPROCSTRING "Driver loaded as a module" #else #define MODULEPROCSTRING "Driver compiled into kernel" #endif - /* output must be kept under PAGE_SIZE */ - out += sprintf(out, BANNER); - out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n"); - out += sprintf(out, "frequency = %lu kHz\n", + seq_puts(m, BANNER); + seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n"); + seq_printf(m, "frequency = %lu kHz\n", typhoon_unit.curfreq >> 4); - out += sprintf(out, "volume = %d\n", typhoon_unit.curvol); - out += sprintf(out, "mute = %s\n", typhoon_unit.muted ? + seq_printf(m, "volume = %d\n", typhoon_unit.curvol); + seq_printf(m, "mute = %s\n", typhoon_unit.muted ? "on" : "off"); - out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase); - out += sprintf(out, "mute frequency = %lu kHz\n", + seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase); + seq_printf(m, "mute frequency = %lu kHz\n", typhoon_unit.mutefreq >> 4); - return out - buf; + return 0; } +static int typhoon_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, typhoon_proc_show, NULL); +} + +static const struct file_operations typhoon_proc_fops = { + .owner = THIS_MODULE, + .open = typhoon_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */ MODULE_AUTHOR("Dr. Henrik Seidel"); @@ -452,8 +459,7 @@ static int __init typhoon_init(void) typhoon_mute(&typhoon_unit); #ifdef CONFIG_RADIO_TYPHOON_PROC_FS - if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL, - typhoon_get_info)) + if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops)) printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n"); #endif From 17de9a4e53567912735105e189535f5d83e74a81 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 15 Apr 2008 18:11:50 -0300 Subject: [PATCH 318/452] V4L/DVB (7584): Fix build that occurs when CONFIG_VIDEO_PMS=y and VIDEO_V4L2_COMMON=m This patch removes zoran checks for VIDEO_V4L2, since this API is always present, when V4L is selected. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 9 +++++++-- drivers/media/video/msp3400-driver.c | 4 ++-- drivers/media/video/tuner-core.c | 2 +- drivers/media/video/zoran.h | 16 ---------------- drivers/media/video/zoran_driver.c | 18 ++---------------- 5 files changed, 12 insertions(+), 37 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 1f7244cffe2f..128bb9cd5755 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -30,7 +30,7 @@ config VIDEO_V4L2_COMMON depends on (I2C || I2C=n) && VIDEO_DEV default (I2C || I2C=n) && VIDEO_DEV -config VIDEO_V4L1 +config VIDEO_ALLOW_V4L1 bool "Enable Video For Linux API 1 (DEPRECATED)" depends on VIDEO_DEV && VIDEO_V4L2_COMMON default VIDEO_DEV && VIDEO_V4L2_COMMON @@ -59,10 +59,15 @@ config VIDEO_V4L1_COMPAT If you are unsure as to whether this is required, answer Y. config VIDEO_V4L2 - bool + tristate depends on VIDEO_DEV && VIDEO_V4L2_COMMON default VIDEO_DEV && VIDEO_V4L2_COMMON +config VIDEO_V4L1 + tristate + depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1 + default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1 + source "drivers/media/video/Kconfig" source "drivers/media/radio/Kconfig" diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 7a11f3159e32..b73c740f7fb2 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -366,7 +366,7 @@ int msp_sleep(struct msp_state *state, int timeout) } /* ------------------------------------------------------------------------ */ -#ifdef CONFIG_VIDEO_V4L1 +#ifdef CONFIG_VIDEO_ALLOW_V4L1 static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode) { if (rxsubchans == V4L2_TUNER_SUB_MONO) @@ -514,7 +514,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ -#ifdef CONFIG_VIDEO_V4L1 +#ifdef CONFIG_VIDEO_ALLOW_V4L1 case VIDIOCGAUDIO: { struct video_audio *va = arg; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 225e8f8df1a5..e886f48a2909 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -758,7 +758,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (analog_ops->standby) analog_ops->standby(&t->fe); break; -#ifdef CONFIG_VIDEO_V4L1 +#ifdef CONFIG_VIDEO_ALLOW_V4L1 case VIDIOCSAUDIO: if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) return 0; diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 498a43c1f2b1..81cc3b00a079 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -243,10 +243,8 @@ struct zoran_format { #ifdef CONFIG_VIDEO_V4L1_COMPAT int palette; #endif -#ifdef CONFIG_VIDEO_V4L2 __u32 fourcc; int colorspace; -#endif int depth; __u32 flags; __u32 vfespfr; @@ -271,20 +269,6 @@ struct zoran_v4l_settings { const struct zoran_format *format; /* capture format */ }; -/* whoops, this one is undeclared if !v4l2 */ -#ifndef CONFIG_VIDEO_V4L2 -struct v4l2_jpegcompression { - int quality; - int APPn; - int APP_len; - char APP_data[60]; - int COM_len; - char COM_data[60]; - __u32 jpeg_markers; - __u8 reserved[116]; -}; -#endif - /* jpg-capture/-playback settings */ struct zoran_jpg_settings { int decimation; /* this bit is used to set everything to default */ diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 1a002eaeb06c..0134bec1e399 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -85,7 +85,6 @@ #include "zoran_device.h" #include "zoran_card.h" -#ifdef CONFIG_VIDEO_V4L2 /* we declare some card type definitions here, they mean * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */ #define ZORAN_V4L2_VID_FLAGS ( \ @@ -94,19 +93,15 @@ V4L2_CAP_VIDEO_OUTPUT |\ V4L2_CAP_VIDEO_OVERLAY \ ) -#endif #include -#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT) +#if defined(CONFIG_VIDEO_V4L1_COMPAT) #define ZFMT(pal, fcc, cs) \ .palette = (pal), .fourcc = (fcc), .colorspace = (cs) -#elif defined(CONFIG_VIDEO_V4L2) -#define ZFMT(pal, fcc, cs) \ - .fourcc = (fcc), .colorspace = (cs) #else #define ZFMT(pal, fcc, cs) \ - .palette = (pal) + .fourcc = (fcc), .colorspace = (cs) #endif const struct zoran_format zoran_formats[] = { @@ -209,7 +204,6 @@ 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)"); -#ifdef CONFIG_VIDEO_V4L2 /* small helper function for calculating buffersizes for v4l2 * we calculate the nearest higher power-of-two, which * will be the recommended buffersize */ @@ -232,7 +226,6 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings) return 8192; return result; } -#endif /* forward references */ static void v4l_fbuffer_free(struct file *file); @@ -1709,7 +1702,6 @@ setup_overlay (struct file *file, return wait_grab_pending(zr); } -#ifdef CONFIG_VIDEO_V4L2 /* get the status of a buffer in the clients buffer queue */ static int zoran_v4l2_buffer_status (struct file *file, @@ -1815,7 +1807,6 @@ zoran_v4l2_buffer_status (struct file *file, return 0; } -#endif static int zoran_set_norm (struct zoran *zr, @@ -2624,8 +2615,6 @@ zoran_do_ioctl (struct inode *inode, } break; -#ifdef CONFIG_VIDEO_V4L2 - /* The new video4linux2 capture interface - much nicer than video4linux1, since * it allows for integrating the JPEG capturing calls inside standard v4l2 */ @@ -4197,7 +4186,6 @@ zoran_do_ioctl (struct inode *inode, return 0; } break; -#endif default: dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n", @@ -4657,9 +4645,7 @@ static const struct file_operations zoran_fops = { struct video_device zoran_template __devinitdata = { .name = ZORAN_NAME, .type = ZORAN_VID_TYPE, -#ifdef CONFIG_VIDEO_V4L2 .type2 = ZORAN_V4L2_VID_FLAGS, -#endif .fops = &zoran_fops, .release = &zoran_vdev_release, .minor = -1 From 1d3104b819979784df1da6ad76acef33cd9736e4 Mon Sep 17 00:00:00 2001 From: David Hilvert Date: Wed, 16 Apr 2008 04:27:09 -0300 Subject: [PATCH 319/452] V4L/DVB (7589): ibmcam: improve support for the IBM PC Camera Pro This patch modifies Dmitri's original ibmcam driver for Linux to improve support for the IBM PC Camera Pro. It may also offer improved support for other models classified by the driver as 'Model 3', such as the IBM PC Camera Pro Max. See http://auricle.dyndns.org/xvp610/ Signed-off-by: David Hilvert Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvideo/ibmcam.c | 62 ++++++++++++++++++++------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index 84ee6b1d9fd2..59166b760104 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -802,6 +802,21 @@ static enum ParseState ibmcam_model2_320x240_parse_lines( return scan_Continue; } +/* + * ibmcam_model3_parse_lines() + * + * | Even lines | Odd Lines | + * -----------------------------------| + * |YYY........Y|UYVYUYVY.........UYVY| + * |YYY........Y|UYVYUYVY.........UYVY| + * |............|.....................| + * |YYY........Y|UYVYUYVY.........UYVY| + * |------------+---------------------| + * + * There is one (U, V) chroma pair for every four luma (Y) values. This + * function reads a pair of lines at a time and obtains missing chroma values + * from adjacent pixels. + */ static enum ParseState ibmcam_model3_parse_lines( struct uvd *uvd, struct usbvideo_frame *frame, @@ -816,6 +831,7 @@ static enum ParseState ibmcam_model3_parse_lines( const int ccm = 128; /* Color correction median - see below */ int i, u, v, rw, data_w=0, data_h=0, color_corr; static unsigned char lineBuffer[640*3]; + int line; color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); @@ -869,15 +885,15 @@ static enum ParseState ibmcam_model3_parse_lines( return scan_NextFrame; } - /* Make sure there's enough data for the entire line */ - len = 3 * data_w; /* */ + /* Make sure that lineBuffer can store two lines of data */ + len = 3 * data_w; /* */ assert(len <= sizeof(lineBuffer)); - /* Make sure there's enough data for the entire line */ + /* Make sure there's enough data for two lines */ if (RingQueue_GetLength(&uvd->dp) < len) return scan_Out; - /* Suck one line out of the ring queue */ + /* Suck two lines of data out of the ring queue */ RingQueue_Dequeue(&uvd->dp, lineBuffer, len); data = lineBuffer; @@ -887,15 +903,23 @@ static enum ParseState ibmcam_model3_parse_lines( rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1; RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1); - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int y, rv, gv, bv; /* RGB components */ + /* Iterate over two lines. */ + for (line = 0; line < 2; line++) { + for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { + int y; + int rv, gv, bv; /* RGB components */ - if (i < data_w) { - y = data[i]; /* Luminosity is the first line */ + if (i >= data_w) { + RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0); + continue; + } + + /* first line is YYY...Y; second is UYVY...UYVY */ + y = data[(line == 0) ? i : (i*2 + 1)]; /* Apply static color correction */ - u = color[i*2] + hue_corr; - v = color[i*2 + 1] + hue2_corr; + u = color[(i/2)*4] + hue_corr; + v = color[(i/2)*4 + 2] + hue2_corr; /* Apply color correction */ if (color_corr != 0) { @@ -903,13 +927,21 @@ static enum ParseState ibmcam_model3_parse_lines( u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; } - } else - y = 0, u = v = 128; - YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); - RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */ + + YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); + RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* No deinterlacing */ + } + + /* Check for the end of requested data */ + if (rw == 0) + break; + + /* Prepare for the second line */ + rw--; + data = lineBuffer + data_w; } - frame->deinterlace = Deinterlace_FillEvenLines; + frame->deinterlace = Deinterlace_None; /* * Account for number of bytes that we wrote into output V4L frame. From 9e05c0f0d84c25f7f576ebc22a9a3a2cf962cc58 Mon Sep 17 00:00:00 2001 From: Ivan Bobyr Date: Wed, 16 Apr 2008 16:01:55 -0300 Subject: [PATCH 320/452] V4L/DVB (7590): ir-common: Adds 3 missing IR keys for FlyVIdeo2000 The patch extends the default keymap of FlyVIdeo2000 IR remote control so that this remote may also serve movie & music players in a better way. I bought a SAA7130 TV tuner with a remote control having 3 additional button as the default layout, exactly as: 1) labeled "<<<" : key code 0x19, may be used as "backward"in MPlayer,XMMS etc 2) labeled ">>>" : key code 0x1f, may be used as "forward"... 3) not labeled : key code 0x0a, may be used as "pause"... Once have added these code definitions to the kernel, me got all these operations available for viewing movies & listening music. Signed-off-by : Ivan Bobyr Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index c5d10bdf4286..65f810cde605 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -771,7 +771,11 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { [ 0x12 ] = KEY_CHANNELUP, // Channel + [ 0x13 ] = KEY_CHANNELDOWN, // Channel - [ 0x06 ] = KEY_AGAIN, // Recall - [ 0x10 ] = KEY_ENTER, // Enter + [ 0x10 ] = KEY_ENTER, // Enter + + [ 0x19 ] = KEY_BACK, // Rewind ( <<< ) + [ 0x1f ] = KEY_FORWARD, // Forward ( >>> ) + [ 0x0a ] = KEY_ANGLE, // (no label, may be used as the PAUSE button) }; EXPORT_SYMBOL_GPL(ir_codes_flyvideo); From 168c626cb8f85df17585af99e14403904641c7ac Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 16 Apr 2008 16:13:15 -0300 Subject: [PATCH 321/452] V4L/DVB (7591): drivers/media/video: use time_before, time_before_eq, etc The functions time_before, time_before_eq, time_after, and time_after_eq are more robust for comparing jiffies against other values. A simplified version of the semantic patch making this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @ change_compare_np @ expression E; @@ ( - jiffies <= E + time_before_eq(jiffies,E) | - jiffies >= E + time_after_eq(jiffies,E) | - jiffies < E + time_before(jiffies,E) | - jiffies > E + time_after(jiffies,E) ) @ include depends on change_compare_np @ @@ @ no_include depends on !include && change_compare_np @ @@ #include + #include // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/c-qcam.c | 7 +++++-- drivers/media/video/ivtv/ivtv-fileops.c | 4 +++- drivers/media/video/ivtv/ivtv-mailbox.c | 11 +++++++---- drivers/media/video/ivtv/ivtv-streams.c | 3 ++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 2c85ced61150..fe1e67bb1ca8 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -95,7 +96,8 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam, unsigned long oldjiffies = jiffies; unsigned int i; - for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); ) + for (oldjiffies = jiffies; + time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); ) if (qcam_ready1(qcam) == value) return 0; @@ -120,7 +122,8 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) unsigned long oldjiffies = jiffies; unsigned int i; - for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); ) + for (oldjiffies = jiffies; + time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); ) if (qcam_ready2(qcam) == value) return 0; diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index d949a81339d5..a7640c49f1d8 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -219,7 +219,9 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, /* Process pending program info updates and pending VBI data */ ivtv_update_pgm_info(itv); - if (jiffies - itv->dualwatch_jiffies > msecs_to_jiffies(1000)) { + if (time_after(jiffies, + itv->dualwatch_jiffies + + msecs_to_jiffies(1000))) { itv->dualwatch_jiffies = jiffies; ivtv_dualwatch(itv); } diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c index 13a6c374d2db..1b5c0ac09a85 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/video/ivtv/ivtv-mailbox.c @@ -177,7 +177,8 @@ static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int f /* Sleep before a retry, if not atomic */ if (!(flags & API_NO_WAIT_MB)) { - if (jiffies - then > msecs_to_jiffies(10*retries)) + if (time_after(jiffies, + then + msecs_to_jiffies(10*retries))) break; ivtv_msleep_timeout(10, 0); } @@ -244,7 +245,9 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) data, then just return 0 as there is no need to issue this command again. Just an optimization to prevent unnecessary use of mailboxes. */ if (itv->api_cache[cmd].last_jiffies && - jiffies - itv->api_cache[cmd].last_jiffies < msecs_to_jiffies(1800000) && + time_before(jiffies, + itv->api_cache[cmd].last_jiffies + + msecs_to_jiffies(1800000)) && !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) { itv->api_cache[cmd].last_jiffies = jiffies; return 0; @@ -299,7 +302,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) } } while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) { - if (jiffies - then > api_timeout) { + if (time_after(jiffies, then + api_timeout)) { IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name); /* reset the mailbox, but it is likely too late already */ write_sync(0, &mbox->flags); @@ -311,7 +314,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) else ivtv_msleep_timeout(1, 0); } - if (jiffies - then > msecs_to_jiffies(100)) + if (time_after(jiffies, then + msecs_to_jiffies(100))) IVTV_DEBUG_WARN("%s took %u jiffies\n", api_info[cmd].name, jiffies_to_msecs(jiffies - then)); diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 24d98ecf35ad..4ab8d36831ba 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -768,7 +768,8 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) /* wait 2s for EOS interrupt */ while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) && - jiffies < then + msecs_to_jiffies (2000)) { + time_before(jiffies, + then + msecs_to_jiffies(2000))) { schedule_timeout(msecs_to_jiffies(10)); } From 3aefb79af8d41c85e11da7109d62038849421bb6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:36:41 -0300 Subject: [PATCH 322/452] V4L/DVB (7593): em28xx: add a module to handle dvb This patch adds em28xx-dvb. This driver is highly based on cx88-dvb and saa7134-dvb. This code currently loads and unloads successfully. However, some changes are needed to properly support the mpeg streams and to setup em28xx to work on DVB mode. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/Kconfig | 8 ++ drivers/media/video/em28xx/Makefile | 1 + drivers/media/video/em28xx/em28xx-cards.c | 21 +-- drivers/media/video/em28xx/em28xx-dvb.c | 157 ++++++++++++++++++++++ drivers/media/video/em28xx/em28xx-video.c | 12 +- drivers/media/video/em28xx/em28xx.h | 43 ++++++ 6 files changed, 218 insertions(+), 24 deletions(-) create mode 100644 drivers/media/video/em28xx/em28xx-dvb.c diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 0f7a0bd86ff4..11a2759ecbc9 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -27,3 +27,11 @@ config VIDEO_EM28XX_ALSA To compile this driver as a module, choose M here: the module will be called em28xx-alsa +config VIDEO_EM28XX_DVB + tristate "DVB/ATSC Support for em28xx based TV cards" + depends on VIDEO_EM28XX && DVB_CORE + select VIDEOBUF_DVB + select FW_LOADER + ---help--- + This adds support for DVB cards based on the + Empiatech em28xx chips. diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile index 0924550992d0..3d1c3cc337fe 100644 --- a/drivers/media/video/em28xx/Makefile +++ b/drivers/media/video/em28xx/Makefile @@ -5,6 +5,7 @@ em28xx-alsa-objs := em28xx-audio.o obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o +obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o EXTRA_CFLAGS += -Idrivers/media/video EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 94aed008f83b..bbd75bd3ff1a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -52,26 +52,6 @@ struct em28xx_hash_table { unsigned int tuner; }; -/* Boards supported by driver */ - -#define EM2800_BOARD_UNKNOWN 0 -#define EM2820_BOARD_UNKNOWN 1 -#define EM2820_BOARD_TERRATEC_CINERGY_250 2 -#define EM2820_BOARD_PINNACLE_USB_2 3 -#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4 -#define EM2820_BOARD_MSI_VOX_USB_2 5 -#define EM2800_BOARD_TERRATEC_CINERGY_200 6 -#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 -#define EM2800_BOARD_KWORLD_USB2800 8 -#define EM2820_BOARD_PINNACLE_DVC_90 9 -#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10 -#define EM2880_BOARD_TERRATEC_HYBRID_XS 11 -#define EM2820_BOARD_KWORLD_PVRTV2800RF 12 -#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13 -#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14 -#define EM2800_BOARD_VGEAR_POCKETTV 15 -#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16 - struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_UNKNOWN] = { .name = "Unknown EM2800 video grabber", @@ -665,6 +645,7 @@ static void em28xx_set_model(struct em28xx *dev) dev->analog_gpio = em28xx_boards[dev->model].analog_gpio; dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; + dev->has_dvb = em28xx_boards[dev->model].has_dvb; } /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c new file mode 100644 index 000000000000..1ffe64f62095 --- /dev/null +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -0,0 +1,157 @@ +/* + DVB device driver for em28xx + + (c) 2008 Mauro Carvalho Chehab + + Based on cx88-dvb and saa7134-dvb originally written by: + (c) 2004, 2005 Chris Pascoe + (c) 2004 Gerd Knorr [SuSE Labs] + + 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. + */ + +#include +#include + +#include "em28xx.h" +#include +#include + +#include "lgdt330x.h" +#include "tuner-xc2028.h" +#include "tuner-xc2028-types.h" + +MODULE_DESCRIPTION("driver for em28xx based DVB cards"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_LICENSE("GPL"); + +static unsigned int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debug messages [dvb]"); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +#define dprintk(level, fmt, arg...) do { \ +if (debug >= level) \ + printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg) \ +} while (0) + +static int +buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +{ + struct em28xx_fh *fh = vq->priv_data; + struct em28xx *dev = fh->dev; + + *size = 16 * fh->dev->width * fh->dev->height >> 3; + if (0 == *count) + *count = EM28XX_DEF_BUF; + + if (*count < EM28XX_MIN_BUF) + *count = EM28XX_MIN_BUF; + + dev->mode = EM28XX_DIGITAL_MODE; + + return 0; +} + +/* ------------------------------------------------------------------ */ + +/* Add demods here */ + +/* ------------------------------------------------------------------ */ + +static int attach_xc3028(u8 addr, struct em28xx *dev) +{ + struct dvb_frontend *fe; + struct xc2028_ctrl ctl; + struct xc2028_config cfg = { + .i2c_adap = &dev->i2c_adap, + .i2c_addr = addr, + .ctrl = &ctl, + }; + + if (!dev->dvb.frontend) { + printk(KERN_ERR "%s/2: dvb frontend not attached. " + "Can't attach xc3028\n", + dev->name); + return -EINVAL; + } + + 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 -EINVAL; + } + + printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name); + + return 0; +} + +static int dvb_init(struct em28xx *dev) +{ + /* init struct videobuf_dvb */ + dev->dvb.name = dev->name; + + dev->qops->buf_setup = buffer_setup; + + videobuf_queue_vmalloc_init(&dev->dvb.dvbq, dev->qops, + &dev->udev->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_ALTERNATE, + sizeof(struct em28xx_buffer), dev); + + /* init frontend */ + switch (dev->model) { + default: + printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" + " isn't supported yet\n", + dev->name); + break; + } + if (NULL == dev->dvb.frontend) { + printk(KERN_ERR + "%s/2: frontend initialization failed\n", + dev->name); + return -EINVAL; + } + + /* register everything */ + return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, + &dev->udev->dev, + adapter_nr); +} + +static int dvb_fini(struct em28xx *dev) +{ + if (dev->dvb.frontend) + videobuf_dvb_unregister(&dev->dvb); + + return 0; +} + +static struct em28xx_ops dvb_ops = { + .id = EM28XX_DVB, + .name = "Em28xx dvb Extension", + .init = dvb_init, + .fini = dvb_fini, +}; + +static int __init em28xx_dvb_register(void) +{ + return em28xx_register_extension(&dvb_ops); +} + +static void __exit em28xx_dvb_unregister(void) +{ + em28xx_unregister_extension(&dvb_ops); +} + +module_init(em28xx_dvb_register); +module_exit(em28xx_dvb_unregister); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 6084f8452b2b..362251838d4b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -63,10 +63,6 @@ MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __func__ , ##arg); } while (0) -/* Limits minimum and default number of buffers */ -#define EM28XX_MIN_BUF 4 -#define EM28XX_DEF_BUF 8 - MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); @@ -2237,6 +2233,9 @@ static void request_module_async(struct work_struct *work) request_module("snd-usb-audio"); else request_module("em28xx-alsa"); + + if (dev->has_dvb) + request_module("em28xx-dvb"); } static void request_modules(struct em28xx *dev) @@ -2368,6 +2367,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); +#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) + dev->qops = kmalloc(sizeof(em28xx_video_qops), GFP_KERNEL); + memcpy(dev->qops, &em28xx_video_qops, sizeof(em28xx_video_qops)); +#endif + request_modules(dev); return 0; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 0080a09860d9..96a56faeb77b 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -31,6 +31,32 @@ #include #include #include +#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) +#include +#endif + +/* Boards supported by driver */ +#define EM2800_BOARD_UNKNOWN 0 +#define EM2820_BOARD_UNKNOWN 1 +#define EM2820_BOARD_TERRATEC_CINERGY_250 2 +#define EM2820_BOARD_PINNACLE_USB_2 3 +#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4 +#define EM2820_BOARD_MSI_VOX_USB_2 5 +#define EM2800_BOARD_TERRATEC_CINERGY_200 6 +#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 +#define EM2800_BOARD_KWORLD_USB2800 8 +#define EM2820_BOARD_PINNACLE_DVC_90 9 +#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10 +#define EM2880_BOARD_TERRATEC_HYBRID_XS 11 +#define EM2820_BOARD_KWORLD_PVRTV2800RF 12 +#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13 +#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14 +#define EM2800_BOARD_VGEAR_POCKETTV 15 +#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16 + +/* Limits minimum and default number of buffers */ +#define EM28XX_MIN_BUF 4 +#define EM28XX_DEF_BUF 8 /* maximum number of em28xx boards */ #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ @@ -81,6 +107,11 @@ /* time in msecs to wait for i2c writes to finish */ #define EM2800_I2C_WRITE_TIMEOUT 20 +enum em28xx_mode { + EM28XX_ANALOG_MODE, + EM28XX_DIGITAL_MODE, +}; + enum em28xx_stream_state { STREAM_OFF, STREAM_INTERRUPT, @@ -200,6 +231,7 @@ struct em28xx_board { unsigned int mts_firmware:1; unsigned int has_12mhz_i2s:1; unsigned int max_range_640_480:1; + unsigned int has_dvb:1; unsigned int analog_gpio; @@ -234,7 +266,10 @@ enum em28xx_dev_state { #define EM28XX_NUM_AUDIO_PACKETS 64 #define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */ #define EM28XX_CAPTURE_STREAM_EN 1 + +/* em28xx extensions */ #define EM28XX_AUDIO 0x10 +#define EM28XX_DVB 0x20 struct em28xx_audio { char name[50]; @@ -266,6 +301,7 @@ struct em28xx { unsigned int has_audio_class:1; unsigned int has_12mhz_i2s:1; unsigned int max_range_640_480:1; + unsigned int has_dvb:1; int video_inputs; /* number of video inputs */ struct list_head devlist; @@ -340,6 +376,13 @@ struct em28xx { int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg, char *buf, int len); int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg); + + enum em28xx_mode mode; + +#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) + struct videobuf_dvb dvb; + struct videobuf_queue_ops *qops; +#endif }; struct em28xx_fh { From acaa4b609fbab25e09459cd8e842e292b27f5ecb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:37:18 -0300 Subject: [PATCH 323/452] V4L/DVB (7594): em28xx: Fix Kconfig Some devices have msp3400 audio decoder chip. Selects it, if em28xx. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 11a2759ecbc9..2b47a9bd0b65 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,11 +1,12 @@ config VIDEO_EM28XX - tristate "Empia EM2800/2820/2840 USB video capture support" + tristate "Empia EM28xx USB video capture support" depends on VIDEO_DEV && I2C && INPUT select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO ---help--- This is a video4linux driver for Empia 28xx based TV cards. From ee6e3a865a469c78daa93a1e6cdbaca3a102f9c8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:37:31 -0300 Subject: [PATCH 324/452] V4L/DVB (7595): Improve generic support for setting gpio values em28xx based devices with xc3028 may require some specific gpio values. This patch adds a generic handling for such values. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 138 +++++++++++----------- drivers/media/video/em28xx/em28xx-core.c | 32 ++++- drivers/media/video/em28xx/em28xx.h | 23 +++- 3 files changed, 116 insertions(+), 77 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index bbd75bd3ff1a..c907d6a5a056 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -194,9 +194,6 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_SVIDEO, .amux = 1, } }, - - /* gpio's 4, 1, 0 */ - .analog_gpio = 0x003d2d, }, [EM2880_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Hybrid XS", @@ -445,73 +442,88 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, }; +int em28xx_tuner_callback(void *ptr, int command, int arg) +{ + int rc = 0, i; + struct em28xx *dev = ptr; + struct gpio_ctl (*gpio_ctl)[MAX_GPIO]; + + if (dev->tuner_type != TUNER_XC2028) + return 0; + + if (command != XC2028_TUNER_RESET) + return 0; + + if (dev->mode == EM28XX_ANALOG_MODE) + gpio_ctl = dev->analog_gpio; + else + gpio_ctl = dev->digital_gpio; + + /* Send GPIO reset sequences specified at board entry */ + for (i = 0; i < MAX_GPIO; i++) { + if (!gpio_ctl[i]->val) + break; + + dev->em28xx_write_regs(dev, + gpio_ctl[i]->reg, + &gpio_ctl[i]->val, 1); + if (gpio_ctl[i]->t1) + msleep(gpio_ctl[i]->t1); + + if (!gpio_ctl[i]->rst) + continue; + dev->em28xx_write_regs(dev, + gpio_ctl[i]->reg, + &gpio_ctl[i]->rst, 1); + if (gpio_ctl[i]->t2) + msleep(gpio_ctl[i]->t2); + + dev->em28xx_write_regs(dev, + gpio_ctl[i]->reg, + &gpio_ctl[i]->val, 1); + if (gpio_ctl[i]->t3) + msleep(gpio_ctl[i]->t3); + } + return rc; +} +EXPORT_SYMBOL_GPL(em28xx_tuner_callback); + +static void em28xx_set_model(struct em28xx *dev) +{ + dev->is_em2800 = em28xx_boards[dev->model].is_em2800; + dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx; + dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; + dev->decoder = em28xx_boards[dev->model].decoder; + dev->video_inputs = em28xx_boards[dev->model].vchannels; + dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; + dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; + dev->has_dvb = em28xx_boards[dev->model].has_dvb; + dev->analog_gpio = &em28xx_boards[dev->model].analog_gpio; + dev->digital_gpio = &em28xx_boards[dev->model].digital_gpio; +} + /* Since em28xx_pre_card_setup() requires a proper dev->model, * this won't work for boards with generic PCI IDs */ void em28xx_pre_card_setup(struct em28xx *dev) { + em28xx_set_model(dev); + /* request some modules */ switch (dev->model) { case EM2880_BOARD_TERRATEC_PRODIGY_XS: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_TERRATEC_HYBRID_XS: + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: em28xx_write_regs(dev, XCLK_REG, "\x27", 1); em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1); - em28xx_write_regs(dev, 0x08, "\xff", 1); - em28xx_write_regs(dev, 0x04, "\x00", 1); - msleep(100); - em28xx_write_regs(dev, 0x04, "\x08", 1); - msleep(100); - em28xx_write_regs(dev, 0x08, "\xff", 1); - msleep(50); - em28xx_write_regs(dev, 0x08, "\x2d", 1); - msleep(50); - em28xx_write_regs(dev, 0x08, "\x3d", 1); - break; } -} -static int em28xx_tuner_callback(void *ptr, int command, int arg) -{ - int rc = 0; - struct em28xx *dev = ptr; - - if (dev->tuner_type != TUNER_XC2028) - return 0; - - switch (command) { - case XC2028_TUNER_RESET: - { - /* GPIO and initialization codes for analog TV and radio - This code should be complemented for DTV, since reset - codes are different. - */ - - dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); - dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); - - if (dev->analog_gpio) { - char gpio0 = dev->analog_gpio & 0xff; - char gpio1 = (dev->analog_gpio >> 8) & 0xff; - char gpio4 = dev->analog_gpio >> 24; - - if (gpio4) { - dev->em28xx_write_regs(dev, 0x04, &gpio4, 1); - msleep(140); - } - - msleep(6); - dev->em28xx_write_regs(dev, 0x08, &gpio0, 1); - msleep(10); - dev->em28xx_write_regs(dev, 0x08, &gpio1, 1); - msleep(5); - } - - break; - } - } - return rc; + /* Put xc2028 tuners and demods into a sane state */ + if (dev->tuner_type == TUNER_XC2028) { + dev->mode = EM28XX_DIGITAL_MODE; + em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); + }; } static void em28xx_config_tuner(struct em28xx *dev) @@ -634,20 +646,6 @@ static int em28xx_hint_board(struct em28xx *dev) return -1; } - -static void em28xx_set_model(struct em28xx *dev) -{ - dev->is_em2800 = em28xx_boards[dev->model].is_em2800; - dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx; - dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; - dev->decoder = em28xx_boards[dev->model].decoder; - dev->video_inputs = em28xx_boards[dev->model].vchannels; - dev->analog_gpio = em28xx_boards[dev->model].analog_gpio; - dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; - dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; - dev->has_dvb = em28xx_boards[dev->model].has_dvb; -} - /* ----------------------------------------------------------------------- */ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) { diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 97635abb916e..841c7c2c91b3 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -314,14 +314,36 @@ int em28xx_colorlevels_set_default(struct em28xx *dev) int em28xx_capture_start(struct em28xx *dev, int start) { - int ret; + int rc; /* FIXME: which is the best order? */ /* video registers are sampled by VREF */ - if ((ret = em28xx_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00, - 0x10)) < 0) - return ret; + rc = em28xx_write_reg_bits(dev, USBSUSP_REG, + start ? 0x10 : 0x00, 0x10); + if (rc < 0) + return rc; + + if (!start) { + /* disable video capture */ + rc = em28xx_write_regs(dev, VINENABLE_REG, "\x27", 1); + if (rc < 0) + return rc; + } + /* enable video capture */ - return em28xx_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1); + rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + if (rc < 0) + return rc; + if (dev->mode == EM28XX_ANALOG_MODE) + rc = em28xx_write_regs(dev, VINENABLE_REG,"\x67", 1); + else + rc = em28xx_write_regs(dev, VINENABLE_REG,"\x37", 1); + + if (rc < 0) + return rc; + + msleep (6); + + return rc; } int em28xx_outfmt_set_yuv422(struct em28xx *dev) diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 96a56faeb77b..00d2f62142e3 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -218,6 +218,21 @@ enum em28xx_decoder { EM28XX_SAA7114 }; +#define MAX_GPIO 2 +struct gpio_ctl { + /* Register to be set */ + unsigned char reg; + /* Initial/final value */ + unsigned char val; + /* reset value - if set, it will do: + val1 - val2 - val1 + */ + unsigned char rst; + /* Sleep times + */ + unsigned int t1, t2, t3; +}; + struct em28xx_board { char *name; int vchannels; @@ -233,7 +248,8 @@ struct em28xx_board { unsigned int max_range_640_480:1; unsigned int has_dvb:1; - unsigned int analog_gpio; + struct gpio_ctl analog_gpio[MAX_GPIO]; + struct gpio_ctl digital_gpio[MAX_GPIO]; enum em28xx_decoder decoder; @@ -293,7 +309,6 @@ struct em28xx { char name[30]; /* name (including minor) of the device */ int model; /* index in the device_data struct */ int devno; /* marks the number of this device */ - unsigned int analog_gpio; unsigned int is_em2800:1; unsigned int has_msp34xx:1; unsigned int has_tda9887:1; @@ -303,6 +318,9 @@ struct em28xx { unsigned int max_range_640_480:1; unsigned int has_dvb:1; + struct gpio_ctl (*analog_gpio)[MAX_GPIO]; + struct gpio_ctl (*digital_gpio)[MAX_GPIO]; + int video_inputs; /* number of video inputs */ struct list_head devlist; @@ -443,6 +461,7 @@ extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); +int em28xx_tuner_callback(void *ptr, int command, int arg); /* Provided by em28xx-input.c */ /* TODO: Check if the standard get_key handlers on ir-common can be used */ From 227ad4ab9058ef2624934183e8083886cf64bf56 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:37:40 -0300 Subject: [PATCH 325/452] V4L/DVB (7596): em28xx-dvb: Add support for HVR950 This patch adds DVB support for Hauppauge HVR950. Thanks to Michael Krufky for getting those values. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/Kconfig | 1 + drivers/media/video/em28xx/em28xx-cards.c | 29 ++++++++++++++++++++++- drivers/media/video/em28xx/em28xx-dvb.c | 17 ++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 2b47a9bd0b65..4818cda38913 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -31,6 +31,7 @@ config VIDEO_EM28XX_ALSA config VIDEO_EM28XX_DVB tristate "DVB/ATSC Support for em28xx based TV cards" depends on VIDEO_EM28XX && DVB_CORE + select DVB_LGDT330X if !DVB_FE_CUSTOMISE select VIDEOBUF_DVB select FW_LOADER ---help--- diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c907d6a5a056..710f110b6e8a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -180,6 +180,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_12mhz_i2s = 1, + .has_dvb = 1, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -194,6 +195,32 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_SVIDEO, .amux = 1, } }, + .analog_gpio = { + { /* xc3028 reset seq */ + .reg = 0x08, + .val = 0x3d, + .rst = 0x2d, + .t1 = 5, + .t2 = 10, + .t3 = 5, + }, + }, + .digital_gpio = { + { /* xc3028 reset seq */ + .reg = 0x08, + .val = 0x3e, + .rst = 0x2e, + .t1 = 6, + .t2 = 6, + .t3 = 6, + }, { /* demod reset seq */ + .reg = 0x04, + .val = 0x0c, + .rst = 0x04, + .t2 = 10, + .t3 = 10, + } + }, }, [EM2880_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Hybrid XS", @@ -521,7 +548,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* Put xc2028 tuners and demods into a sane state */ if (dev->tuner_type == TUNER_XC2028) { - dev->mode = EM28XX_DIGITAL_MODE; + dev->mode = EM28XX_ANALOG_MODE; em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); }; } diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 1ffe64f62095..1645021191a8 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -58,7 +58,10 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) /* ------------------------------------------------------------------ */ -/* Add demods here */ +static struct lgdt330x_config em2880_lgdt3303_dev = { + .demod_address = 0x0e, + .demod_chip = LGDT3303, +}; /* ------------------------------------------------------------------ */ @@ -70,6 +73,7 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) .i2c_adap = &dev->i2c_adap, .i2c_addr = addr, .ctrl = &ctl, + .callback = em28xx_tuner_callback, }; if (!dev->dvb.frontend) { @@ -109,6 +113,17 @@ static int dvb_init(struct em28xx *dev) /* init frontend */ switch (dev->model) { + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: + /* Enable lgdt330x */ + dev->mode = EM28XX_ANALOG_MODE; + em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); + + dev->dvb.frontend = dvb_attach(lgdt330x_attach, + &em2880_lgdt3303_dev, + &dev->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", From 3ca9c09379e8f3be0744c47f72769457fa46e9f3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:37:53 -0300 Subject: [PATCH 326/452] V4L/DVB (7597): em28xx: share the same xc3028 setup for analog and digital modes Thanks to Devin Heitmueller and Aidan Thornton" for pointing some errors with the previous scenario. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 24 +++++++++++++++++------ drivers/media/video/em28xx/em28xx-dvb.c | 17 ++++++++-------- drivers/media/video/em28xx/em28xx.h | 2 ++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 710f110b6e8a..f4883b4a6b7a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -36,7 +36,6 @@ #include #include "em28xx.h" -#include "tuner-xc2028.h" static int tuner = -1; module_param(tuner, int, 0444); @@ -553,10 +552,25 @@ void em28xx_pre_card_setup(struct em28xx *dev) }; } +void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) +{ + memset(ctl, 0, sizeof(*ctl)); + + ctl->fname = XC2028_DEFAULT_FIRMWARE; + ctl->max_len = 64; + ctl->mts = em28xx_boards[dev->model].mts_firmware; + + switch (dev->model) { + /* Add card-specific parameters for xc3028 here */ + default: + ctl->demod = XC3028_FE_OREN538; + } +} +EXPORT_SYMBOL_GPL(em28xx_setup_xc3028); + static void em28xx_config_tuner(struct em28xx *dev) { struct v4l2_priv_tun_config xc2028_cfg; - struct xc2028_ctrl ctl; struct tuner_setup tun_setup; struct v4l2_frequency f; @@ -571,11 +585,9 @@ static void em28xx_config_tuner(struct em28xx *dev) em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); if (dev->tuner_type == TUNER_XC2028) { - memset(&ctl, 0, sizeof(ctl)); + struct xc2028_ctrl ctl; - ctl.fname = XC2028_DEFAULT_FIRMWARE; - ctl.max_len = 64; - ctl.mts = em28xx_boards[dev->model].mts_firmware; + em28xx_setup_xc3028(dev, &ctl); xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 1645021191a8..1ceabeac4f7b 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -20,8 +20,6 @@ #include #include "lgdt330x.h" -#include "tuner-xc2028.h" -#include "tuner-xc2028-types.h" MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab "); @@ -69,12 +67,15 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) { struct dvb_frontend *fe; struct xc2028_ctrl ctl; - struct xc2028_config cfg = { - .i2c_adap = &dev->i2c_adap, - .i2c_addr = addr, - .ctrl = &ctl, - .callback = em28xx_tuner_callback, - }; + struct xc2028_config cfg; + + memset (&cfg, 0, sizeof(cfg)); + cfg.i2c_adap = &dev->i2c_adap; + cfg.i2c_addr = addr; + cfg.ctrl = &ctl; + cfg.callback = em28xx_tuner_callback; + + em28xx_setup_xc3028(dev, &ctl); if (!dev->dvb.frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 00d2f62142e3..fa1c74217a52 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -34,6 +34,7 @@ #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) #include #endif +#include "tuner-xc2028.h" /* Boards supported by driver */ #define EM2800_BOARD_UNKNOWN 0 @@ -462,6 +463,7 @@ extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); int em28xx_tuner_callback(void *ptr, int command, int arg); +void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl); /* Provided by em28xx-input.c */ /* TODO: Check if the standard get_key handlers on ir-common can be used */ From bdfbf9520372daf2b4d6941474c92310848ccb27 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 17 Apr 2008 21:38:27 -0300 Subject: [PATCH 327/452] V4L/DVB (7598): em28xx: several fixes on gpio programming em28xx-cards.c: - Fix reversed val/rst values in both analog_gpio and digital_gpio vectors - Fix crash that would was occurring during every analog startup while looping over gpio_ctl - Remove what appears to be a redundant setting of gpio_ctl->val - Don't use OREN538 demodulation for the HVR-950 (prevents ATSC scanning from working) em28xx-dvb.c: - Tuner should be in digital mode when issuing the reset - Add copyright - Change struct definition (corresponds to fix in em28xx-cards.c for gpio_ctl looping) Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 61 ++++++++++++++--------- drivers/media/video/em28xx/em28xx-dvb.c | 5 +- drivers/media/video/em28xx/em28xx.h | 4 +- 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index f4883b4a6b7a..2e7fd1911154 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -197,8 +197,8 @@ struct em28xx_board em28xx_boards[] = { .analog_gpio = { { /* xc3028 reset seq */ .reg = 0x08, - .val = 0x3d, - .rst = 0x2d, + .val = 0x2d, + .rst = 0x3d, .t1 = 5, .t2 = 10, .t3 = 5, @@ -207,15 +207,15 @@ struct em28xx_board em28xx_boards[] = { .digital_gpio = { { /* xc3028 reset seq */ .reg = 0x08, - .val = 0x3e, - .rst = 0x2e, + .val = 0x2e, + .rst = 0x3e, .t1 = 6, .t2 = 6, .t3 = 6, }, { /* demod reset seq */ .reg = 0x04, - .val = 0x0c, - .rst = 0x04, + .val = 0x04, + .rst = 0x0c, .t2 = 10, .t3 = 10, } @@ -472,7 +472,7 @@ int em28xx_tuner_callback(void *ptr, int command, int arg) { int rc = 0, i; struct em28xx *dev = ptr; - struct gpio_ctl (*gpio_ctl)[MAX_GPIO]; + struct gpio_ctl *gpio_ctl; if (dev->tuner_type != TUNER_XC2028) return 0; @@ -485,30 +485,40 @@ int em28xx_tuner_callback(void *ptr, int command, int arg) else gpio_ctl = dev->digital_gpio; + /* djh - Not sure if these are still required */ + if (dev->mode == EM28XX_ANALOG_MODE) { + dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); + msleep(6); + } else { + dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1); + msleep(6); + } + /* Send GPIO reset sequences specified at board entry */ for (i = 0; i < MAX_GPIO; i++) { - if (!gpio_ctl[i]->val) + if (!gpio_ctl->val) break; dev->em28xx_write_regs(dev, - gpio_ctl[i]->reg, - &gpio_ctl[i]->val, 1); - if (gpio_ctl[i]->t1) - msleep(gpio_ctl[i]->t1); + gpio_ctl->reg, + &gpio_ctl->val, 1); + if (gpio_ctl->t1) + msleep(gpio_ctl->t1); - if (!gpio_ctl[i]->rst) + if (!gpio_ctl->rst) { + gpio_ctl++; continue; - dev->em28xx_write_regs(dev, - gpio_ctl[i]->reg, - &gpio_ctl[i]->rst, 1); - if (gpio_ctl[i]->t2) - msleep(gpio_ctl[i]->t2); + } dev->em28xx_write_regs(dev, - gpio_ctl[i]->reg, - &gpio_ctl[i]->val, 1); - if (gpio_ctl[i]->t3) - msleep(gpio_ctl[i]->t3); + gpio_ctl->reg, + &gpio_ctl->rst, 1); + if (gpio_ctl->t2) + msleep(gpio_ctl->t2); + + gpio_ctl++; } return rc; } @@ -524,8 +534,8 @@ static void em28xx_set_model(struct em28xx *dev) dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; dev->has_dvb = em28xx_boards[dev->model].has_dvb; - dev->analog_gpio = &em28xx_boards[dev->model].analog_gpio; - dev->digital_gpio = &em28xx_boards[dev->model].digital_gpio; + dev->analog_gpio = em28xx_boards[dev->model].analog_gpio; + dev->digital_gpio = em28xx_boards[dev->model].digital_gpio; } /* Since em28xx_pre_card_setup() requires a proper dev->model, @@ -562,6 +572,9 @@ void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) switch (dev->model) { /* Add card-specific parameters for xc3028 here */ + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: + ctl->demod = XC3028_FE_DEFAULT; + break; default: ctl->demod = XC3028_FE_OREN538; } diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 1ceabeac4f7b..cbc155d302c8 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -3,6 +3,9 @@ (c) 2008 Mauro Carvalho Chehab + (c) 2008 Devin Heitmueller + - Fixes for the driver to properly work with HVR-950 + Based on cx88-dvb and saa7134-dvb originally written by: (c) 2004, 2005 Chris Pascoe (c) 2004 Gerd Knorr [SuSE Labs] @@ -116,7 +119,7 @@ static int dvb_init(struct em28xx *dev) switch (dev->model) { case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: /* Enable lgdt330x */ - dev->mode = EM28XX_ANALOG_MODE; + dev->mode = EM28XX_DIGITAL_MODE; em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); dev->dvb.frontend = dvb_attach(lgdt330x_attach, diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index fa1c74217a52..10f64652c04f 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -319,8 +319,8 @@ struct em28xx { unsigned int max_range_640_480:1; unsigned int has_dvb:1; - struct gpio_ctl (*analog_gpio)[MAX_GPIO]; - struct gpio_ctl (*digital_gpio)[MAX_GPIO]; + struct gpio_ctl *analog_gpio; + struct gpio_ctl *digital_gpio; int video_inputs; /* number of video inputs */ struct list_head devlist; From 52284c3e47bf502aaff72ab2ede509193b628b1b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:38:38 -0300 Subject: [PATCH 328/452] V4L/DVB (7599): em28xx-dvb: videobuf callbacks are waiting for em28xx_fh Thanks to Devin Heitmueller for pointing this issue. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-dvb.c | 8 +++++++- drivers/media/video/em28xx/em28xx.h | 23 +++++++++++++---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index cbc155d302c8..d3d52972cd84 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -45,6 +45,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) struct em28xx_fh *fh = vq->priv_data; struct em28xx *dev = fh->dev; + /* FIXME: The better would be to allocate a smaller buffer */ *size = 16 * fh->dev->width * fh->dev->height >> 3; if (0 == *count) *count = EM28XX_DEF_BUF; @@ -109,11 +110,16 @@ static int dvb_init(struct em28xx *dev) dev->qops->buf_setup = buffer_setup; + /* FIXME: Do we need more initialization here? */ + memset(&dev->dvb_fh, 0, sizeof (dev->dvb_fh)); + dev->dvb_fh.dev = dev; + dev->dvb_fh.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + videobuf_queue_vmalloc_init(&dev->dvb.dvbq, dev->qops, &dev->udev->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, - sizeof(struct em28xx_buffer), dev); + sizeof(struct em28xx_buffer), &dev->dvb_fh); /* init frontend */ switch (dev->model) { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 10f64652c04f..3786dd819bbd 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -304,6 +304,18 @@ struct em28xx_audio { spinlock_t slock; }; +struct em28xx; + +struct em28xx_fh { + struct em28xx *dev; + unsigned int stream_on:1; /* Locks streams */ + int radio; + + struct videobuf_queue vb_vidq; + + enum v4l2_buf_type type; +}; + /* main device struct */ struct em28xx { /* generic device properties */ @@ -401,19 +413,10 @@ struct em28xx { #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) struct videobuf_dvb dvb; struct videobuf_queue_ops *qops; + struct em28xx_fh dvb_fh; #endif }; -struct em28xx_fh { - struct em28xx *dev; - unsigned int stream_on:1; /* Locks streams */ - int radio; - - struct videobuf_queue vb_vidq; - - enum v4l2_buf_type type; -}; - struct em28xx_ops { struct list_head next; char *name; From d2d9fbfd732f49999a2a94f2479934488fe3ea9d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:38:53 -0300 Subject: [PATCH 329/452] V4L/DVB (7600): em28xx: Sets frequency when changing to analog mode This will make tuner-xc2028 to change to analog, if needed. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 362251838d4b..72a7633b6452 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -560,6 +560,8 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct em28xx_fh *fh = vq->priv_data; + struct em28xx *dev = fh->dev; + struct v4l2_frequency f; *size = 16 * fh->dev->width * fh->dev->height >> 3; if (0 == *count) @@ -568,6 +570,14 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) if (*count < EM28XX_MIN_BUF) *count = EM28XX_MIN_BUF; + dev->mode = EM28XX_ANALOG_MODE; + + /* Ask tuner to go to analog mode */ + memset (&f, 0, sizeof(f)); + f.frequency = dev->ctl_freq; + + em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); + return 0; } From 7e6388a1b97cca57a1906df6104feb4001721576 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Thu, 17 Apr 2008 21:40:03 -0300 Subject: [PATCH 330/452] V4L/DVB (7601): em28xx-dvb: add support for the HVR-900 Adds the correct GPIOs and demod attach code for the HVR-900 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/Kconfig | 1 + drivers/media/video/em28xx/em28xx-cards.c | 20 ++++++++++++++++++++ drivers/media/video/em28xx/em28xx-dvb.c | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 4818cda38913..c57420e263ff 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -32,6 +32,7 @@ config VIDEO_EM28XX_DVB tristate "DVB/ATSC Support for em28xx based TV cards" depends on VIDEO_EM28XX && DVB_CORE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_ZL10353 if !DVB_FE_CUSTOMISE select VIDEOBUF_DVB select FW_LOADER ---help--- diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 2e7fd1911154..2a44d2adeb09 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -171,6 +171,26 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_SVIDEO, .amux = 1, } }, + .analog_gpio = { + { /* xc3028 reset seq */ + .reg = 0x08, + .val = 0x2d, + .rst = 0x3d, + .t1 = 5, + .t2 = 10, + .t3 = 5, + }, + }, + .digital_gpio = { + { /* xc3028 reset seq */ + .reg = 0x08, + .val = 0x2e, + .rst = 0x3e, + .t1 = 6, + .t2 = 6, + .t3 = 6, + } + }, }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = { .name = "Hauppauge WinTV HVR 950", diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index d3d52972cd84..65e0ab65fbe1 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -23,6 +23,7 @@ #include #include "lgdt330x.h" +#include "zl10353.h" MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab "); @@ -65,6 +66,13 @@ static struct lgdt330x_config em2880_lgdt3303_dev = { .demod_chip = LGDT3303, }; +static struct zl10353_config em28xx_zl10353_with_xc3028 = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .parallel_ts = 1, + .if2 = 45600, +}; + /* ------------------------------------------------------------------ */ static int attach_xc3028(u8 addr, struct em28xx *dev) @@ -134,6 +142,16 @@ static int dvb_init(struct em28xx *dev) if (attach_xc3028(0x61, dev) < 0) return -EINVAL; break; + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + /* Enable zl10353 */ + dev->mode = EM28XX_DIGITAL_MODE; + em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); + dev->dvb.frontend = dvb_attach(zl10353_attach, + &em28xx_zl10353_with_xc3028, + &dev->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", From 579f72e44fb1c991352f44c20b471c3001357f68 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Thu, 17 Apr 2008 21:40:16 -0300 Subject: [PATCH 331/452] V4L/DVB (7602): em28xx: generalise URB setup code Move the URB setup and management code to em28xx-core.c and generalise it slighlty so that the DVB code can use it. Signed-off-by: Aidan Thornton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 181 ++++++++++++++++++++ drivers/media/video/em28xx/em28xx-video.c | 195 +--------------------- drivers/media/video/em28xx/em28xx.h | 17 ++ 3 files changed, 202 insertions(+), 191 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 841c7c2c91b3..cb9f721ca280 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -53,6 +53,12 @@ static int alt = EM28XX_PINOUT; module_param(alt, int, 0644); MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); +/* FIXME */ +#define em28xx_isocdbg(fmt, arg...) do {\ + if (core_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __func__ , ##arg); } while (0) + /* * em28xx_read_reg_req() * reads data from the usb device specifying bRequest @@ -455,3 +461,178 @@ int em28xx_set_alternate(struct em28xx *dev) } return 0; } + +/* ------------------------------------------------------------------ + URB control + ------------------------------------------------------------------*/ + +/* + * IRQ callback, called by URB callback + */ +static void em28xx_irq_callback(struct urb *urb) +{ + struct em28xx_dmaqueue *dma_q = urb->context; + struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); + int rc, i; + + /* Copy data from URB */ + spin_lock(&dev->slock); + rc = dev->isoc_ctl.isoc_copy(dev, urb); + spin_unlock(&dev->slock); + + /* Reset urb buffers */ + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + urb->status = 0; + + urb->status = usb_submit_urb(urb, GFP_ATOMIC); + if (urb->status) { + em28xx_err("urb resubmit failed (error=%i)\n", + urb->status); + } +} + +/* + * Stop and Deallocate URBs + */ +void em28xx_uninit_isoc(struct em28xx *dev) +{ + struct urb *urb; + int i; + + em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); + + dev->isoc_ctl.nfields = -1; + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb = dev->isoc_ctl.urb[i]; + if (urb) { + usb_kill_urb(urb); + usb_unlink_urb(urb); + if (dev->isoc_ctl.transfer_buffer[i]) { + usb_buffer_free(dev->udev, + urb->transfer_buffer_length, + dev->isoc_ctl.transfer_buffer[i], + urb->transfer_dma); + } + usb_free_urb(urb); + dev->isoc_ctl.urb[i] = NULL; + } + dev->isoc_ctl.transfer_buffer[i] = NULL; + } + + kfree(dev->isoc_ctl.urb); + kfree(dev->isoc_ctl.transfer_buffer); + + dev->isoc_ctl.urb = NULL; + dev->isoc_ctl.transfer_buffer = NULL; + dev->isoc_ctl.num_bufs = 0; + + em28xx_capture_start(dev, 0); +} +EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); + +/* + * Allocate URBs and start IRQ + */ +int em28xx_init_isoc(struct em28xx *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct em28xx *dev, struct urb *urb), + int cap_type) +{ + struct em28xx_dmaqueue *dma_q = &dev->vidq; + int i; + int sb_size, pipe; + struct urb *urb; + int j, k; + int rc; + + em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n"); + + /* De-allocates all pending stuff */ + em28xx_uninit_isoc(dev); + + dev->isoc_ctl.isoc_copy = isoc_copy; + dev->isoc_ctl.num_bufs = num_bufs; + + dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + if (!dev->isoc_ctl.urb) { + em28xx_errdev("cannot alloc memory for usb buffers\n"); + return -ENOMEM; + } + + dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, + GFP_KERNEL); + if (!dev->isoc_ctl.urb) { + em28xx_errdev("cannot allocate memory for usbtransfer\n"); + kfree(dev->isoc_ctl.urb); + return -ENOMEM; + } + + dev->isoc_ctl.max_pkt_size = max_pkt_size; + dev->isoc_ctl.buf = NULL; + + sb_size = max_packets * dev->isoc_ctl.max_pkt_size; + + /* allocate urbs and transfer buffers */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb = usb_alloc_urb(max_packets, GFP_KERNEL); + if (!urb) { + em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); + em28xx_uninit_isoc(dev); + return -ENOMEM; + } + dev->isoc_ctl.urb[i] = urb; + + dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev, + sb_size, GFP_KERNEL, &urb->transfer_dma); + if (!dev->isoc_ctl.transfer_buffer[i]) { + em28xx_err("unable to allocate %i bytes for transfer" + " buffer %i%s\n", + sb_size, i, + in_interrupt()?" while in int":""); + em28xx_uninit_isoc(dev); + return -ENOMEM; + } + memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); + + /* FIXME: this is a hack - should be + 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' + should also be using 'desc.bInterval' + */ + pipe = usb_rcvisocpipe(dev->udev, cap_type == EM28XX_ANALOG_CAPTURE ? 0x82 : 0x84); + usb_fill_int_urb(urb, dev->udev, pipe, + dev->isoc_ctl.transfer_buffer[i], sb_size, + em28xx_irq_callback, dma_q, 1); + + urb->number_of_packets = max_packets; + urb->transfer_flags = URB_ISO_ASAP; + + k = 0; + for (j = 0; j < max_packets; j++) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->isoc_ctl.max_pkt_size; + k += dev->isoc_ctl.max_pkt_size; + } + } + + init_waitqueue_head(&dma_q->wq); + + em28xx_capture_start(dev, cap_type); + + /* submit urbs and enables IRQ */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); + if (rc) { + em28xx_err("submit of urb %i failed (error=%i)\n", i, + rc); + em28xx_uninit_isoc(dev); + return rc; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(em28xx_init_isoc); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 72a7633b6452..1a0b09714af5 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -285,11 +285,10 @@ static inline void get_next_buf(struct em28xx_dmaqueue *dma_q, /* * Controls the isoc copy of each urb packet */ -static inline int em28xx_isoc_copy(struct urb *urb) +static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) { struct em28xx_buffer *buf; struct em28xx_dmaqueue *dma_q = urb->context; - struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); unsigned char *outp = NULL; int i, len = 0, rc = 1; unsigned char *p; @@ -370,188 +369,6 @@ static inline int em28xx_isoc_copy(struct urb *urb) return rc; } -/* ------------------------------------------------------------------ - URB control - ------------------------------------------------------------------*/ - -/* - * IRQ callback, called by URB callback - */ -static void em28xx_irq_callback(struct urb *urb) -{ - struct em28xx_dmaqueue *dma_q = urb->context; - struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - int rc, i; - - /* Copy data from URB */ - spin_lock(&dev->slock); - rc = em28xx_isoc_copy(urb); - spin_unlock(&dev->slock); - - /* Reset urb buffers */ - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - urb->status = 0; - - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) { - em28xx_err("urb resubmit failed (error=%i)\n", - urb->status); - } -} - -/* - * Stop and Deallocate URBs - */ -static void em28xx_uninit_isoc(struct em28xx *dev) -{ - struct urb *urb; - int i; - - em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); - - dev->isoc_ctl.nfields = -1; - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = dev->isoc_ctl.urb[i]; - if (urb) { - usb_kill_urb(urb); - usb_unlink_urb(urb); - if (dev->isoc_ctl.transfer_buffer[i]) { - usb_buffer_free(dev->udev, - urb->transfer_buffer_length, - dev->isoc_ctl.transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - dev->isoc_ctl.urb[i] = NULL; - } - dev->isoc_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->isoc_ctl.urb); - kfree(dev->isoc_ctl.transfer_buffer); - dev->isoc_ctl.urb = NULL; - dev->isoc_ctl.transfer_buffer = NULL; - - dev->isoc_ctl.num_bufs = 0; - - em28xx_capture_start(dev, 0); -} - -/* - * Allocate URBs and start IRQ - */ -static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets, - int num_bufs) -{ - struct em28xx_dmaqueue *dma_q = &dev->vidq; - int i; - int sb_size, pipe; - struct urb *urb; - int j, k; - - em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n"); - - /* De-allocates all pending stuff */ - em28xx_uninit_isoc(dev); - - dev->isoc_ctl.num_bufs = num_bufs; - - dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - em28xx_errdev("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - em28xx_errdev("cannot allocate memory for usbtransfer\n"); - kfree(dev->isoc_ctl.urb); - return -ENOMEM; - } - - dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; - dev->isoc_ctl.buf = NULL; - - sb_size = max_packets * dev->isoc_ctl.max_pkt_size; - - /* allocate urbs and transfer buffers */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = usb_alloc_urb(max_packets, GFP_KERNEL); - if (!urb) { - em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); - em28xx_uninit_isoc(dev); - return -ENOMEM; - } - dev->isoc_ctl.urb[i] = urb; - - dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); - if (!dev->isoc_ctl.transfer_buffer[i]) { - em28xx_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt()?" while in int":""); - em28xx_uninit_isoc(dev); - return -ENOMEM; - } - memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); - - /* FIXME: this is a hack - should be - 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' - should also be using 'desc.bInterval' - */ - pipe = usb_rcvisocpipe(dev->udev, 0x82); - usb_fill_int_urb(urb, dev->udev, pipe, - dev->isoc_ctl.transfer_buffer[i], sb_size, - em28xx_irq_callback, dma_q, 1); - - urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP; - - k = 0; - for (j = 0; j < max_packets; j++) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->isoc_ctl.max_pkt_size; - k += dev->isoc_ctl.max_pkt_size; - } - } - - return 0; -} - -static int em28xx_start_thread(struct em28xx_dmaqueue *dma_q) -{ - struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - int i, rc = 0; - - em28xx_videodbg("Called em28xx_start_thread\n"); - - init_waitqueue_head(&dma_q->wq); - - em28xx_capture_start(dev, 1); - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); - if (rc) { - em28xx_err("submit of urb %i failed (error=%i)\n", i, - rc); - em28xx_uninit_isoc(dev); - return rc; - } - } - - if (rc < 0) - return rc; - - return 0; -} - /* ------------------------------------------------------------------ Videobuf operations ------------------------------------------------------------------*/ @@ -615,7 +432,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, struct em28xx_fh *fh = vq->priv_data; struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); struct em28xx *dev = fh->dev; - struct em28xx_dmaqueue *vidq = &dev->vidq; int rc = 0, urb_init = 0; /* FIXME: It assumes depth = 16 */ @@ -639,12 +455,9 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, urb_init = 1; if (urb_init) { - rc = em28xx_prepare_isoc(dev, EM28XX_NUM_PACKETS, - EM28XX_NUM_BUFS); - if (rc < 0) - goto fail; - - rc = em28xx_start_thread(vidq); + rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, + EM28XX_NUM_BUFS, dev->max_pkt_size, + em28xx_isoc_copy, EM28XX_ANALOG_CAPTURE); if (rc < 0) goto fail; } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 3786dd819bbd..151bc57bd08b 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -119,6 +119,8 @@ enum em28xx_stream_state { STREAM_ON, }; +struct em28xx; + struct em28xx_usb_isoc_ctl { /* max packet size of isoc transaction */ int max_pkt_size; @@ -148,6 +150,10 @@ struct em28xx_usb_isoc_ctl { /* Stores the number of received fields */ int nfields; + + /* isoc urb callback */ + int (*isoc_copy) (struct em28xx *dev, struct urb *urb); + }; struct em28xx_fmt { @@ -279,6 +285,12 @@ enum em28xx_dev_state { DEV_MISCONFIGURED = 0x04, }; +enum em28xx_capture_mode { + EM28XX_CAPTURE_OFF = 0, + EM28XX_ANALOG_CAPTURE, + EM28XX_DIGITAL_CAPTURE, +}; + #define EM28XX_AUDIO_BUFS 5 #define EM28XX_NUM_AUDIO_PACKETS 64 #define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */ @@ -452,6 +464,11 @@ int em28xx_capture_start(struct em28xx *dev, int start); int em28xx_outfmt_set_yuv422(struct em28xx *dev); int em28xx_resolution_set(struct em28xx *dev); int em28xx_set_alternate(struct em28xx *dev); +int em28xx_init_isoc(struct em28xx *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct em28xx *dev, struct urb *urb), + int cap_type); +void em28xx_uninit_isoc(struct em28xx *dev); /* Provided by em28xx-video.c */ int em28xx_register_extension(struct em28xx_ops *dev); From 3421b7787a2cf41ac5edce9b5766bddd1e1d9986 Mon Sep 17 00:00:00 2001 From: Aidan Thornton Date: Thu, 17 Apr 2008 21:40:36 -0300 Subject: [PATCH 332/452] V4L/DVB (7603): em28xx-dvb: don't use videobuf-dvb Modifies em28xx-dvb not to use videobuf-dvb, but instead to include the code for registering dvb devices locally and use the URB management code in the em28xx driver directly. DVB data streaming should now work. Signed-off-by: Aidan Thornton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-dvb.c | 351 +++++++++++++++++++--- drivers/media/video/em28xx/em28xx-video.c | 5 - drivers/media/video/em28xx/em28xx.h | 6 +- 3 files changed, 303 insertions(+), 59 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 65e0ab65fbe1..fd8f44cb6cbc 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -6,7 +6,9 @@ (c) 2008 Devin Heitmueller - Fixes for the driver to properly work with HVR-950 - Based on cx88-dvb and saa7134-dvb originally written by: + (c) 2008 Aidan Thornton + + Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by: (c) 2004, 2005 Chris Pascoe (c) 2004 Gerd Knorr [SuSE Labs] @@ -37,28 +39,157 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define dprintk(level, fmt, arg...) do { \ if (debug >= level) \ - printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg) \ + printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ } while (0) -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +#define EM28XX_DVB_NUM_BUFS 5 +#define EM28XX_DVB_MAX_PACKETSIZE 564 +#define EM28XX_DVB_MAX_PACKETS 64 + +struct em28xx_dvb { + struct dvb_frontend *frontend; + + /* feed count management */ + struct mutex lock; + int nfeeds; + + /* general boilerplate stuff */ + struct dvb_adapter adapter; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dmx_frontend fe_hw; + struct dmx_frontend fe_mem; + struct dvb_net net; +}; + + +static inline void print_err_status(struct em28xx *dev, + int packet, int status) { - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; + char *errmsg = "Unknown"; - /* FIXME: The better would be to allocate a smaller buffer */ - *size = 16 * fh->dev->width * fh->dev->height >> 3; - if (0 == *count) - *count = EM28XX_DEF_BUF; + switch (status) { + case -ENOENT: + errmsg = "unlinked synchronuously"; + break; + case -ECONNRESET: + errmsg = "unlinked asynchronuously"; + break; + case -ENOSR: + errmsg = "Buffer error (overrun)"; + break; + case -EPIPE: + errmsg = "Stalled (device not responding)"; + break; + case -EOVERFLOW: + errmsg = "Babble (bad cable?)"; + break; + case -EPROTO: + errmsg = "Bit-stuff error (bad cable?)"; + break; + case -EILSEQ: + errmsg = "CRC/Timeout (could be anything)"; + break; + case -ETIME: + errmsg = "Device does not respond"; + break; + } + if (packet < 0) { + dprintk(1, "URB status %d [%s].\n", status, errmsg); + } else { + dprintk(1, "URB packet %d, status %d [%s].\n", packet, status, errmsg); + } +} - if (*count < EM28XX_MIN_BUF) - *count = EM28XX_MIN_BUF; +static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb) +{ + int i; - dev->mode = EM28XX_DIGITAL_MODE; + if (!dev) + return 0; + + if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) + return 0; + + if (urb->status < 0) { + print_err_status(dev, -1, urb->status); + if (urb->status == -ENOENT) + return 0; + } + + for (i = 0; i < urb->number_of_packets; i++) { + int status = urb->iso_frame_desc[i].status; + + if (status < 0) { + print_err_status(dev, i, status); + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + } + + dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + + urb->iso_frame_desc[i].offset, + urb->iso_frame_desc[i].actual_length); + } return 0; } +static int start_streaming(struct em28xx_dvb* dvb) { + struct em28xx *dev = dvb->adapter.priv; + + usb_set_interface(dev->udev, 0, 1); + dev->em28xx_write_regs_req(dev,0x00,0x48,"\x00",1); + + return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, + EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE, + dvb_isoc_copy, EM28XX_DIGITAL_CAPTURE); +} + +static int stop_streaming(struct em28xx_dvb* dvb) { + struct em28xx *dev = dvb->adapter.priv; + + em28xx_uninit_isoc(dev); + return 0; +} + +static int start_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + struct em28xx_dvb *dvb = demux->priv; + int rc, ret; + + if (!demux->dmx.frontend) + return -EINVAL; + + mutex_lock(&dvb->lock); + dvb->nfeeds++; + rc = dvb->nfeeds; + + if (dvb->nfeeds == 1) { + ret = start_streaming(dvb); + if(ret < 0) rc = ret; + } + + mutex_unlock(&dvb->lock); + return rc; +} + +static int stop_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + struct em28xx_dvb *dvb = demux->priv; + int err = 0; + + mutex_lock(&dvb->lock); + dvb->nfeeds--; + if (0 == dvb->nfeeds) { + err = stop_streaming(dvb); + } + mutex_unlock(&dvb->lock); + return err; +} + + /* ------------------------------------------------------------------ */ static struct lgdt330x_config em2880_lgdt3303_dev = { @@ -89,20 +220,20 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) em28xx_setup_xc3028(dev, &ctl); - if (!dev->dvb.frontend) { + if (!dev->dvb->frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " "Can't attach xc3028\n", dev->name); return -EINVAL; } - fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + 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; + dvb_frontend_detach(dev->dvb->frontend); + dvb_unregister_frontend(dev->dvb->frontend); + dev->dvb->frontend = NULL; return -EINVAL; } @@ -111,23 +242,129 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) return 0; } +/* ------------------------------------------------------------------ */ + +int register_dvb(struct em28xx_dvb *dvb, + struct module *module, + struct em28xx *dev, + struct device *device) +{ + int result; + + mutex_init(&dvb->lock); + + /* register adapter */ + result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, + adapter_nr); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", + dev->name, result); + goto fail_adapter; + } + dvb->adapter.priv = dev; + + /* register frontend */ + result = dvb_register_frontend(&dvb->adapter, dvb->frontend); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", + dev->name, result); + goto fail_frontend; + } + + /* register demux stuff */ + dvb->demux.dmx.capabilities = + DMX_TS_FILTERING | DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + dvb->demux.priv = dvb; + dvb->demux.filternum = 256; + dvb->demux.feednum = 256; + dvb->demux.start_feed = start_feed; + dvb->demux.stop_feed = stop_feed; + result = dvb_dmx_init(&dvb->demux); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", + dev->name, result); + goto fail_dmx; + } + + dvb->dmxdev.filternum = 256; + dvb->dmxdev.demux = &dvb->demux.dmx; + dvb->dmxdev.capabilities = 0; + result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", + dev->name, result); + goto fail_dmxdev; + } + + dvb->fe_hw.source = DMX_FRONTEND_0; + result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); + if (result < 0) { + printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", + dev->name, result); + goto fail_fe_hw; + } + + dvb->fe_mem.source = DMX_MEMORY_FE; + result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); + if (result < 0) { + printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", + dev->name, result); + goto fail_fe_mem; + } + + result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); + if (result < 0) { + printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", + dev->name, result); + goto fail_fe_conn; + } + + /* register network adapter */ + dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + return 0; + +fail_fe_conn: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); +fail_fe_mem: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); +fail_fe_hw: + dvb_dmxdev_release(&dvb->dmxdev); +fail_dmxdev: + dvb_dmx_release(&dvb->demux); +fail_dmx: + dvb_unregister_frontend(dvb->frontend); +fail_frontend: + dvb_frontend_detach(dvb->frontend); + dvb_unregister_adapter(&dvb->adapter); +fail_adapter: + return result; +} + +static void unregister_dvb(struct em28xx_dvb *dvb) +{ + dvb_net_release(&dvb->net); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); + dvb_dmxdev_release(&dvb->dmxdev); + dvb_dmx_release(&dvb->demux); + dvb_unregister_frontend(dvb->frontend); + dvb_frontend_detach(dvb->frontend); + dvb_unregister_adapter(&dvb->adapter); +} + + static int dvb_init(struct em28xx *dev) { - /* init struct videobuf_dvb */ - dev->dvb.name = dev->name; + int result = 0; + struct em28xx_dvb *dvb; - dev->qops->buf_setup = buffer_setup; - - /* FIXME: Do we need more initialization here? */ - memset(&dev->dvb_fh, 0, sizeof (dev->dvb_fh)); - dev->dvb_fh.dev = dev; - dev->dvb_fh.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - videobuf_queue_vmalloc_init(&dev->dvb.dvbq, dev->qops, - &dev->udev->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_ALTERNATE, - sizeof(struct em28xx_buffer), &dev->dvb_fh); + dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); + if(dvb == NULL) { + printk("em28xx_dvb: memory allocation failed\n"); + return -ENOMEM; + } + dev->dvb = dvb; /* init frontend */ switch (dev->model) { @@ -136,21 +373,25 @@ static int dvb_init(struct em28xx *dev) dev->mode = EM28XX_DIGITAL_MODE; em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); - dev->dvb.frontend = dvb_attach(lgdt330x_attach, - &em2880_lgdt3303_dev, - &dev->i2c_adap); - if (attach_xc3028(0x61, dev) < 0) - return -EINVAL; + dvb->frontend = dvb_attach(lgdt330x_attach, + &em2880_lgdt3303_dev, + &dev->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) { + result = -EINVAL; + goto out_free; + } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: /* Enable zl10353 */ dev->mode = EM28XX_DIGITAL_MODE; em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); - dev->dvb.frontend = dvb_attach(zl10353_attach, - &em28xx_zl10353_with_xc3028, - &dev->i2c_adap); - if (attach_xc3028(0x61, dev) < 0) - return -EINVAL; + dvb->frontend = dvb_attach(zl10353_attach, + &em28xx_zl10353_with_xc3028, + &dev->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) { + result = -EINVAL; + goto out_free; + } break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" @@ -158,23 +399,35 @@ static int dvb_init(struct em28xx *dev) dev->name); break; } - if (NULL == dev->dvb.frontend) { + if (NULL == dvb->frontend) { printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->name); - return -EINVAL; + result = -EINVAL; + goto out_free; } /* register everything */ - return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, - &dev->udev->dev, - adapter_nr); + result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); + + if (result < 0) { + goto out_free; + } + + return 0; + +out_free: + kfree(dvb); + dev->dvb = NULL; + return result; } static int dvb_fini(struct em28xx *dev) { - if (dev->dvb.frontend) - videobuf_dvb_unregister(&dev->dvb); + if (dev->dvb) { + unregister_dvb(dev->dvb); + dev->dvb = NULL; + } return 0; } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 1a0b09714af5..ffbc91f2ecbd 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2190,11 +2190,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); -#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) - dev->qops = kmalloc(sizeof(em28xx_video_qops), GFP_KERNEL); - memcpy(dev->qops, &em28xx_video_qops, sizeof(em28xx_video_qops)); -#endif - request_modules(dev); return 0; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 151bc57bd08b..e5fd2dc77355 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -422,11 +422,7 @@ struct em28xx { enum em28xx_mode mode; -#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) - struct videobuf_dvb dvb; - struct videobuf_queue_ops *qops; - struct em28xx_fh dvb_fh; -#endif + struct em28xx_dvb *dvb; }; struct em28xx_ops { From 102a0b0879a01a413ed5f667f7db9c2085ca8474 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:40:45 -0300 Subject: [PATCH 333/452] V4L/DVB (7604): em28xx-dvb: Fix analog mode The analog entries are wrong. Fix it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 147 +++++++++------------- drivers/media/video/em28xx/em28xx-core.c | 9 +- drivers/media/video/em28xx/em28xx-dvb.c | 1 + drivers/media/video/em28xx/em28xx.h | 22 +--- 4 files changed, 66 insertions(+), 113 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 2a44d2adeb09..0859a84e7433 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -171,26 +171,6 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_SVIDEO, .amux = 1, } }, - .analog_gpio = { - { /* xc3028 reset seq */ - .reg = 0x08, - .val = 0x2d, - .rst = 0x3d, - .t1 = 5, - .t2 = 10, - .t3 = 5, - }, - }, - .digital_gpio = { - { /* xc3028 reset seq */ - .reg = 0x08, - .val = 0x2e, - .rst = 0x3e, - .t1 = 6, - .t2 = 6, - .t3 = 6, - } - }, }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = { .name = "Hauppauge WinTV HVR 950", @@ -214,32 +194,6 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_SVIDEO, .amux = 1, } }, - .analog_gpio = { - { /* xc3028 reset seq */ - .reg = 0x08, - .val = 0x2d, - .rst = 0x3d, - .t1 = 5, - .t2 = 10, - .t3 = 5, - }, - }, - .digital_gpio = { - { /* xc3028 reset seq */ - .reg = 0x08, - .val = 0x2e, - .rst = 0x3e, - .t1 = 6, - .t2 = 6, - .t3 = 6, - }, { /* demod reset seq */ - .reg = 0x04, - .val = 0x04, - .rst = 0x0c, - .t2 = 10, - .t3 = 10, - } - }, }, [EM2880_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Hybrid XS", @@ -476,7 +430,28 @@ struct usb_device_id em28xx_id_table [] = { }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); -/* EEPROM hash table for devices with generic USB IDs */ +/* + * Reset sequences for analog/digital modes + */ + +/* Board Hauppauge WinTV HVR 900 analog */ +struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { + { -1, -1, 6}, + {0x08, 0x2d, 10}, + {0x08, 0x3d, 5}, + { -1, -1, -1}, +}; +/* Board Hauppauge WinTV HVR 900 digital */ +struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { + { -1, -1, 6}, + {0x08, 0x2e, 6}, + {0x08, 0x3e, 6}, + { -1, -1, -1}, +}; + +/* + * EEPROM hash table for devices with generic USB IDs + */ static struct em28xx_hash_table em28xx_eeprom_hash [] = { /* P/N: SA 60002070465 Tuner: TVF7533-MF */ {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, @@ -490,9 +465,9 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { int em28xx_tuner_callback(void *ptr, int command, int arg) { - int rc = 0, i; + int rc = 0; struct em28xx *dev = ptr; - struct gpio_ctl *gpio_ctl; + struct em28xx_reg_seq *gpio; if (dev->tuner_type != TUNER_XC2028) return 0; @@ -501,44 +476,31 @@ int em28xx_tuner_callback(void *ptr, int command, int arg) return 0; if (dev->mode == EM28XX_ANALOG_MODE) - gpio_ctl = dev->analog_gpio; + gpio = dev->analog_gpio; else - gpio_ctl = dev->digital_gpio; + gpio = dev->digital_gpio; /* djh - Not sure if these are still required */ - if (dev->mode == EM28XX_ANALOG_MODE) { - dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); - dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); - msleep(6); - } else { - dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); - dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1); - msleep(6); - } + dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + if (dev->mode == EM28XX_ANALOG_MODE) + dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); + else + dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1); + msleep(6); + + if (!gpio) + return rc; /* Send GPIO reset sequences specified at board entry */ - for (i = 0; i < MAX_GPIO; i++) { - if (!gpio_ctl->val) - break; + while (gpio->sleep >= 0) { + if (gpio->reg >= 0) + rc = dev->em28xx_write_regs(dev, + gpio->reg, + &gpio->val, 1); + if (gpio->sleep > 0) + msleep(gpio->sleep); - dev->em28xx_write_regs(dev, - gpio_ctl->reg, - &gpio_ctl->val, 1); - if (gpio_ctl->t1) - msleep(gpio_ctl->t1); - - if (!gpio_ctl->rst) { - gpio_ctl++; - continue; - } - - dev->em28xx_write_regs(dev, - gpio_ctl->reg, - &gpio_ctl->rst, 1); - if (gpio_ctl->t2) - msleep(gpio_ctl->t2); - - gpio_ctl++; + gpio++; } return rc; } @@ -554,8 +516,6 @@ static void em28xx_set_model(struct em28xx *dev) dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; dev->has_dvb = em28xx_boards[dev->model].has_dvb; - dev->analog_gpio = em28xx_boards[dev->model].analog_gpio; - dev->digital_gpio = em28xx_boards[dev->model].digital_gpio; } /* Since em28xx_pre_card_setup() requires a proper dev->model, @@ -573,13 +533,22 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: em28xx_write_regs(dev, XCLK_REG, "\x27", 1); em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1); - } + em28xx_write_regs(dev, 0x08, "\xff", 1); + em28xx_write_regs(dev, 0x04, "\x00", 1); + msleep(100); + em28xx_write_regs(dev, 0x04, "\x08", 1); + msleep(100); + em28xx_write_regs(dev, 0x08, "\xff", 1); + msleep(50); + em28xx_write_regs(dev, 0x08, "\x2d", 1); + msleep(50); + em28xx_write_regs(dev, 0x08, "\x3d", 1); - /* Put xc2028 tuners and demods into a sane state */ - if (dev->tuner_type == TUNER_XC2028) { - dev->mode = EM28XX_ANALOG_MODE; - em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); - }; + dev->analog_gpio = hauppauge_wintv_hvr_900_analog; + dev->digital_gpio = hauppauge_wintv_hvr_900_digital; + + break; + } } void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index cb9f721ca280..77f64900717d 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -331,22 +331,17 @@ int em28xx_capture_start(struct em28xx *dev, int start) if (!start) { /* disable video capture */ rc = em28xx_write_regs(dev, VINENABLE_REG, "\x27", 1); - if (rc < 0) - return rc; + return rc; } /* enable video capture */ rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); - if (rc < 0) - return rc; + if (dev->mode == EM28XX_ANALOG_MODE) rc = em28xx_write_regs(dev, VINENABLE_REG,"\x67", 1); else rc = em28xx_write_regs(dev, VINENABLE_REG,"\x37", 1); - if (rc < 0) - return rc; - msleep (6); return rc; diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index fd8f44cb6cbc..64816ae106e3 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -414,6 +414,7 @@ static int dvb_init(struct em28xx *dev) goto out_free; } + printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); return 0; out_free: diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index e5fd2dc77355..91dce95cd19c 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -225,19 +225,10 @@ enum em28xx_decoder { EM28XX_SAA7114 }; -#define MAX_GPIO 2 -struct gpio_ctl { - /* Register to be set */ - unsigned char reg; - /* Initial/final value */ +struct em28xx_reg_seq { + int reg; unsigned char val; - /* reset value - if set, it will do: - val1 - val2 - val1 - */ - unsigned char rst; - /* Sleep times - */ - unsigned int t1, t2, t3; + int sleep; }; struct em28xx_board { @@ -255,9 +246,6 @@ struct em28xx_board { unsigned int max_range_640_480:1; unsigned int has_dvb:1; - struct gpio_ctl analog_gpio[MAX_GPIO]; - struct gpio_ctl digital_gpio[MAX_GPIO]; - enum em28xx_decoder decoder; struct em28xx_input input[MAX_EM28XX_INPUT]; @@ -343,8 +331,8 @@ struct em28xx { unsigned int max_range_640_480:1; unsigned int has_dvb:1; - struct gpio_ctl *analog_gpio; - struct gpio_ctl *digital_gpio; + /* GPIO sequences for tuner callback */ + struct em28xx_reg_seq *analog_gpio, *digital_gpio; int video_inputs; /* number of video inputs */ struct list_head devlist; From 92b75ab0752636802da9a63093dcbbe296ec1fef Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:40:53 -0300 Subject: [PATCH 334/452] V4L/DVB (7605): tuner-xc3028: Avoids too much firmware reloads xc3028_sleep function is being used with a different meaning. This should be called only before doing S1/S3 sleep. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-xc2028.c | 38 +++++++----------------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 62b5de231e0d..95d5922eac95 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -235,6 +235,7 @@ static v4l2_std_id parse_audio_std_option(void) static void free_firmware(struct xc2028_data *priv) { int i; + tuner_dbg("%s called\n", __func__); if (!priv->firm) return; @@ -1050,27 +1051,6 @@ static int xc2028_set_params(struct dvb_frontend *fe, T_DIGITAL_TV, type, 0, demod); } -static int xc2028_sleep(struct dvb_frontend *fe) -{ - struct xc2028_data *priv = fe->tuner_priv; - int rc = 0; - - tuner_dbg("%s called\n", __func__); - - mutex_lock(&priv->lock); - - if (priv->firm_version < 0x0202) - rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00}); - else - rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00}); - - priv->cur_fw.type = 0; /* need firmware reload */ - - mutex_unlock(&priv->lock); - - return rc; -} - static int xc2028_dvb_release(struct dvb_frontend *fe) { @@ -1118,21 +1098,21 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) mutex_lock(&priv->lock); - kfree(priv->ctrl.fname); - free_firmware(priv); - memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); - priv->ctrl.fname = NULL; + if (priv->ctrl.max_len < 9) + priv->ctrl.max_len = 13; if (p->fname) { + if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) { + kfree(priv->ctrl.fname); + free_firmware(priv); + } + priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); if (priv->ctrl.fname == NULL) rc = -ENOMEM; } - if (priv->ctrl.max_len < 9) - priv->ctrl.max_len = 13; - mutex_unlock(&priv->lock); return rc; @@ -1152,8 +1132,6 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = { .get_frequency = xc2028_get_frequency, .get_rf_strength = xc2028_signal, .set_params = xc2028_set_params, - .sleep = xc2028_sleep, - }; struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, From e6a353b0dc2686ae04805919e7a22430d2f1e29e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:41:00 -0300 Subject: [PATCH 335/452] V4L/DVB (7606): em28xx-dvb: Program GPO as well Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 0859a84e7433..fed2dc4473df 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -446,6 +446,8 @@ struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { { -1, -1, 6}, {0x08, 0x2e, 6}, {0x08, 0x3e, 6}, + {0x04, 0x04, 10}, + {0x04, 0x0c, 10}, { -1, -1, -1}, }; From 6ea54d938b6f81baa0952a8b15d3e67e6c268b8f Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 17 Apr 2008 21:41:10 -0300 Subject: [PATCH 336/452] V4L/DVB (7607): CodingStyle fixes Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 4 +- drivers/media/video/em28xx/em28xx-core.c | 63 ++++++---- drivers/media/video/em28xx/em28xx-dvb.c | 29 +++-- drivers/media/video/em28xx/em28xx-i2c.c | 144 ++++++++++++---------- drivers/media/video/em28xx/em28xx-input.c | 26 ++-- drivers/media/video/em28xx/em28xx-video.c | 103 +++++++++------- drivers/media/video/em28xx/em28xx.h | 47 +++---- 7 files changed, 234 insertions(+), 182 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index fed2dc4473df..7dfea3ac9b2f 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -436,10 +436,10 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); /* Board Hauppauge WinTV HVR 900 analog */ struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { - { -1, -1, 6}, + { -1, -1, 6}, {0x08, 0x2d, 10}, {0x08, 0x3d, 5}, - { -1, -1, -1}, + { -1, -1, -1}, }; /* Board Hauppauge WinTV HVR 900 digital */ struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 77f64900717d..a742a57d3979 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -77,12 +77,12 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, buf, len, HZ); - if (reg_debug){ + if (reg_debug) { printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); - for (byte = 0; byte < len; byte++) { - printk(" %02x", (unsigned char)buf[byte]); - } - printk("\n"); + for (byte = 0; byte < len; byte++) + printk(KERN_INFO " %02x", (unsigned char)buf[byte]); + + printk(KERN_INFO "\n"); } return ret; @@ -143,8 +143,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, if (reg_debug) { int i; for (i = 0; i < len; ++i) - printk (" %02x", (unsigned char)buf[i]); - printk ("\n"); + printk(KERN_INFO " %02x", (unsigned char)buf[i]); + printk(KERN_INFO "\n"); } if (!bufs) @@ -173,8 +173,12 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, { int oldval; u8 newval; - if ((oldval = em28xx_read_reg(dev, reg)) < 0) + + oldval = em28xx_read_reg(dev, reg); + + if (oldval < 0) return oldval; + newval = (((u8) oldval) & ~bitmask) | (val & bitmask); return em28xx_write_regs(dev, reg, &newval, 1); } @@ -187,20 +191,26 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) { int ret, i; u8 addr = reg & 0x7f; - if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0) + + ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2); + if (ret < 0) return ret; - if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) + + ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1); + if (ret < 0) return ret; /* Wait up to 50 ms for AC97 command to complete */ for (i = 0; i < 10; i++) { - if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) + ret = em28xx_read_reg(dev, AC97BUSY_REG); + if (ret < 0) return ret; + if (!(ret & 0x01)) return 0; msleep(5); } - em28xx_warn ("AC97 command still being executed: not handled properly!\n"); + em28xx_warn("AC97 command still being executed: not handled properly!\n"); return 0; } @@ -338,11 +348,11 @@ int em28xx_capture_start(struct em28xx *dev, int start) rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); if (dev->mode == EM28XX_ANALOG_MODE) - rc = em28xx_write_regs(dev, VINENABLE_REG,"\x67", 1); + rc = em28xx_write_regs(dev, VINENABLE_REG, "\x67", 1); else - rc = em28xx_write_regs(dev, VINENABLE_REG,"\x37", 1); + rc = em28xx_write_regs(dev, VINENABLE_REG, "\x37", 1); - msleep (6); + msleep(6); return rc; } @@ -357,7 +367,8 @@ int em28xx_outfmt_set_yuv422(struct em28xx *dev) static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, u8 ymax) { - em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax); + em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", + xmin, ymin, xmax, ymax); em28xx_write_regs(dev, XMIN_REG, &xmin, 1); em28xx_write_regs(dev, XMAX_REG, &xmax, 1); @@ -372,7 +383,8 @@ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, u8 cheight = height; u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01); - em28xx_coredbg("em28xx Area Set: (%d,%d)\n", (width | (overflow & 2) << 7), + em28xx_coredbg("em28xx Area Set: (%d,%d)\n", + (width | (overflow & 2) << 7), (height | (overflow & 1) << 8)); em28xx_write_regs(dev, HSTART_REG, &hstart, 1); @@ -386,7 +398,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) { u8 mode; /* the em2800 scaler only supports scaling down to 50% */ - if(dev->is_em2800) + if (dev->is_em2800) mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); else { u8 buf[2]; @@ -396,7 +408,8 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) buf[0] = v; buf[1] = v >> 8; em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2); - /* it seems that both H and V scalers must be active to work correctly */ + /* it seems that both H and V scalers must be active + to work correctly */ mode = (h || v)? 0x30: 0x00; } return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30); @@ -449,7 +462,7 @@ int em28xx_set_alternate(struct em28xx *dev) dev->alt, dev->max_pkt_size); errCode = usb_set_interface(dev->udev, 0, dev->alt); if (errCode < 0) { - em28xx_errdev ("cannot change alternate number to %d (error=%i)\n", + em28xx_errdev("cannot change alternate number to %d (error=%i)\n", dev->alt, errCode); return errCode; } @@ -507,9 +520,9 @@ void em28xx_uninit_isoc(struct em28xx *dev) usb_unlink_urb(urb); if (dev->isoc_ctl.transfer_buffer[i]) { usb_buffer_free(dev->udev, - urb->transfer_buffer_length, - dev->isoc_ctl.transfer_buffer[i], - urb->transfer_dma); + urb->transfer_buffer_length, + dev->isoc_ctl.transfer_buffer[i], + urb->transfer_dma); } usb_free_urb(urb); dev->isoc_ctl.urb[i] = NULL; @@ -596,7 +609,9 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' should also be using 'desc.bInterval' */ - pipe = usb_rcvisocpipe(dev->udev, cap_type == EM28XX_ANALOG_CAPTURE ? 0x82 : 0x84); + pipe = usb_rcvisocpipe(dev->udev, + cap_type == EM28XX_ANALOG_CAPTURE ? 0x82 : 0x84); + usb_fill_int_urb(urb, dev->udev, pipe, dev->isoc_ctl.transfer_buffer[i], sb_size, em28xx_irq_callback, dma_q, 1); diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 64816ae106e3..21b8f1d48024 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -97,7 +97,8 @@ static inline void print_err_status(struct em28xx *dev, if (packet < 0) { dprintk(1, "URB status %d [%s].\n", status, errmsg); } else { - dprintk(1, "URB packet %d, status %d [%s].\n", packet, status, errmsg); + dprintk(1, "URB packet %d, status %d [%s].\n", + packet, status, errmsg); } } @@ -134,18 +135,20 @@ static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb) return 0; } -static int start_streaming(struct em28xx_dvb* dvb) { +static int start_streaming(struct em28xx_dvb *dvb) +{ struct em28xx *dev = dvb->adapter.priv; usb_set_interface(dev->udev, 0, 1); - dev->em28xx_write_regs_req(dev,0x00,0x48,"\x00",1); + dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE, dvb_isoc_copy, EM28XX_DIGITAL_CAPTURE); } -static int stop_streaming(struct em28xx_dvb* dvb) { +static int stop_streaming(struct em28xx_dvb *dvb) +{ struct em28xx *dev = dvb->adapter.priv; em28xx_uninit_isoc(dev); @@ -167,7 +170,8 @@ static int start_feed(struct dvb_demux_feed *feed) if (dvb->nfeeds == 1) { ret = start_streaming(dvb); - if(ret < 0) rc = ret; + if (ret < 0) + rc = ret; } mutex_unlock(&dvb->lock); @@ -182,9 +186,10 @@ static int stop_feed(struct dvb_demux_feed *feed) mutex_lock(&dvb->lock); dvb->nfeeds--; - if (0 == dvb->nfeeds) { + + if (0 == dvb->nfeeds) err = stop_streaming(dvb); - } + mutex_unlock(&dvb->lock); return err; } @@ -212,7 +217,7 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) struct xc2028_ctrl ctl; struct xc2028_config cfg; - memset (&cfg, 0, sizeof(cfg)); + memset(&cfg, 0, sizeof(cfg)); cfg.i2c_adap = &dev->i2c_adap; cfg.i2c_addr = addr; cfg.ctrl = &ctl; @@ -360,8 +365,9 @@ static int dvb_init(struct em28xx *dev) struct em28xx_dvb *dvb; dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); - if(dvb == NULL) { - printk("em28xx_dvb: memory allocation failed\n"); + + if (dvb == NULL) { + printk(KERN_INFO "em28xx_dvb: memory allocation failed\n"); return -ENOMEM; } dev->dvb = dvb; @@ -410,9 +416,8 @@ static int dvb_init(struct em28xx *dev) /* register everything */ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); - if (result < 0) { + if (result < 0) goto out_free; - } printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); return 0; diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 6e1b7b4e7668..6a78fd294cab 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -41,11 +41,21 @@ static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\ - printk(fmt, ##args); } while (0) -#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \ - printk(KERN_DEBUG "%s at %s: " fmt, \ - dev->name, __func__ , ##args); } while (0) + +#define dprintk1(lvl, fmt, args...) \ +do { \ + if (i2c_debug >= lvl) { \ + printk(fmt, ##args); \ + } \ +} while (0) + +#define dprintk2(lvl, fmt, args...) \ +do { \ + if (i2c_debug >= lvl) { \ + printk(KERN_DEBUG "%s at %s: " fmt, \ + dev->name, __func__ , ##args); \ + } \ +} while (0) /* * em2800_i2c_send_max4() @@ -235,16 +245,16 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, return 0; for (i = 0; i < num; i++) { addr = msgs[i].addr << 1; - dprintk2(2,"%s %s addr=%x len=%d:", + dprintk2(2, "%s %s addr=%x len=%d:", (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (!msgs[i].len) { /* no len: check only for device presence */ + if (!msgs[i].len) { /* no len: check only for device presence */ if (dev->is_em2800) rc = em2800_i2c_check_for_device(dev, addr); else rc = em28xx_i2c_check_for_device(dev, addr); if (rc < 0) { - dprintk2(2," no device\n"); + dprintk2(2, " no device\n"); return rc; } @@ -258,14 +268,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, rc = em28xx_i2c_recv_bytes(dev, addr, msgs[i].buf, msgs[i].len); - if (i2c_debug>=2) { - for (byte = 0; byte < msgs[i].len; byte++) { + if (i2c_debug >= 2) { + for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); - } } } else { /* write bytes */ - if (i2c_debug>=2) { + if (i2c_debug >= 2) { for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } @@ -281,13 +290,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, } if (rc < 0) goto err; - if (i2c_debug>=2) + if (i2c_debug >= 2) printk("\n"); } return num; - err: - dprintk2(2," ERROR: %i\n", rc); +err: + dprintk2(2, " ERROR: %i\n", rc); return rc; } @@ -330,7 +339,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) return -1; buf = 0; - if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) { + + err = i2c_master_send(&dev->i2c_client, &buf, 1); + if (err != 1) { printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", dev->name, err); return -1; @@ -403,8 +414,10 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) break; } printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", - em_eeprom->string_idx_table,em_eeprom->string1, - em_eeprom->string2,em_eeprom->string3); + em_eeprom->string_idx_table, + em_eeprom->string1, + em_eeprom->string2, + em_eeprom->string3); return 0; } @@ -430,58 +443,61 @@ static int attach_inform(struct i2c_client *client) struct em28xx *dev = client->adapter->algo_data; switch (client->addr << 1) { - case 0x86: - case 0x84: - case 0x96: - case 0x94: - { - struct v4l2_priv_tun_config tda9887_cfg; + case 0x86: + case 0x84: + case 0x96: + case 0x94: + { + struct v4l2_priv_tun_config tda9887_cfg; - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = TUNER_TDA9887; - tun_setup.addr = client->addr; + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; + tun_setup.type = TUNER_TDA9887; + tun_setup.addr = client->addr; - em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, + &tun_setup); - tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &dev->tda9887_conf; - em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, - &tda9887_cfg); - break; - } - case 0x42: - dprintk1(1,"attach_inform: saa7114 detected.\n"); - break; - case 0x4a: - dprintk1(1,"attach_inform: saa7113 detected.\n"); - break; - case 0xa0: - dprintk1(1,"attach_inform: eeprom detected.\n"); - break; - case 0x60: - case 0x8e: - { - struct IR_i2c *ir = i2c_get_clientdata(client); - dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys); - em28xx_set_ir(dev,ir); - break; - } - case 0x80: - case 0x88: - dprintk1(1,"attach_inform: msp34xx detected.\n"); - break; - case 0xb8: - case 0xba: - dprintk1(1,"attach_inform: tvp5150 detected.\n"); - break; + tda9887_cfg.tuner = TUNER_TDA9887; + tda9887_cfg.priv = &dev->tda9887_conf; + em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, + &tda9887_cfg); + break; + } + case 0x42: + dprintk1(1, "attach_inform: saa7114 detected.\n"); + break; + case 0x4a: + dprintk1(1, "attach_inform: saa7113 detected.\n"); + break; + case 0xa0: + dprintk1(1, "attach_inform: eeprom detected.\n"); + break; + case 0x60: + case 0x8e: + { + struct IR_i2c *ir = i2c_get_clientdata(client); + dprintk1(1, "attach_inform: IR detected (%s).\n", + ir->phys); + em28xx_set_ir(dev, ir); + break; + } + case 0x80: + case 0x88: + dprintk1(1, "attach_inform: msp34xx detected.\n"); + break; + case 0xb8: + case 0xba: + dprintk1(1, "attach_inform: tvp5150 detected.\n"); + break; - default: - if (!dev->tuner_addr) - dev->tuner_addr = client->addr; + default: + if (!dev->tuner_addr) + dev->tuner_addr = client->addr; - dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1); + dprintk1(1, "attach inform: detected I2C address %x\n", + client->addr << 1); } diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 10da2fd8d987..bb5807159b8d 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -32,10 +32,12 @@ static unsigned int ir_debug; module_param(ir_debug, int, 0644); -MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); +MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); -#define dprintk(fmt, arg...) if (ir_debug) \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) +#define dprintk(fmt, arg...) \ + if (ir_debug) { \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \ + } /* ----------------------------------------------------------------------- */ @@ -44,7 +46,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c,&b,1)) { + if (1 != i2c_master_recv(&ir->c, &b, 1)) { dprintk("read error\n"); return -EIO; } @@ -74,24 +76,25 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char code; /* poll IR chip */ - if (2 != i2c_master_recv(&ir->c,buf,2)) + if (2 != i2c_master_recv(&ir->c, buf, 2)) return -EIO; /* Does eliminate repeated parity code */ - if (buf[1]==0xff) + if (buf[1] == 0xff) return 0; - ir->old=buf[1]; + ir->old = buf[1]; /* Rearranges bits to the right order */ - code= ((buf[0]&0x01)<<5) | /* 0010 0000 */ + code = ((buf[0]&0x01)<<5) | /* 0010 0000 */ ((buf[0]&0x02)<<3) | /* 0001 0000 */ ((buf[0]&0x04)<<1) | /* 0000 1000 */ ((buf[0]&0x08)>>1) | /* 0000 0100 */ ((buf[0]&0x10)>>3) | /* 0000 0010 */ ((buf[0]&0x20)>>5); /* 0000 0001 */ - dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",code,buf[0]); + dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n", + code, buf[0]); /* return key */ *ir_key = code; @@ -106,15 +109,14 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, /* poll IR chip */ - if (3 != i2c_master_recv(&ir->c,buf,3)) { + if (3 != i2c_master_recv(&ir->c, buf, 3)) { dprintk("read error\n"); return -EIO; } dprintk("key %02x\n", buf[2]&0x3f); - if (buf[0]!=0x00){ + if (buf[0] != 0x00) return 0; - } *ir_key = buf[2]&0x3f; *ir_raw = buf[2]&0x3f; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index ffbc91f2ecbd..1ac90322d681 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1,5 +1,6 @@ /* - em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices + em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB + video capture devices Copyright (C) 2005 Ludovico Cavedon Markus Rechberger @@ -58,10 +59,13 @@ static unsigned int isoc_debug; module_param(isoc_debug, int, 0644); MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); -#define em28xx_isocdbg(fmt, arg...) do {\ - if (isoc_debug) \ +#define em28xx_isocdbg(fmt, arg...) \ +do {\ + if (isoc_debug) { \ printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) + dev->name, __func__ , ##arg); \ + } \ + } while (0) MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -84,8 +88,8 @@ MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); static unsigned int video_debug; -module_param(video_debug,int,0644); -MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); +module_param(video_debug, int, 0644); +MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ static unsigned long em28xx_devused; @@ -102,7 +106,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { .step = 0x1, .default_value = 0x1f, .flags = 0, - },{ + }, { .id = V4L2_CID_AUDIO_MUTE, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Mute", @@ -390,7 +394,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) dev->mode = EM28XX_ANALOG_MODE; /* Ask tuner to go to analog mode */ - memset (&f, 0, sizeof(f)); + memset(&f, 0, sizeof(f)); f.frequency = dev->ctl_freq; em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); @@ -483,7 +487,8 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) } -static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) +static void buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) { struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); struct em28xx_fh *fh = vq->priv_data; @@ -501,7 +506,7 @@ static struct videobuf_queue_ops em28xx_video_qops = { .buf_release = buffer_release, }; -/********************* v4l2 interface ******************************************/ +/********************* v4l2 interface **************************************/ /* * em28xx_config() @@ -516,9 +521,9 @@ static int em28xx_config(struct em28xx *dev) /* enable vbi capturing */ -/* em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */ -/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */ - em28xx_write_regs_req(dev,0x00,0x11,"\x51",1); +/* em28xx_write_regs_req(dev, 0x00, 0x0e, "\xC0", 1); audio register */ +/* em28xx_write_regs_req(dev, 0x00, 0x0f, "\x80", 1); clk register */ + em28xx_write_regs_req(dev, 0x00, 0x11, "\x51", 1); dev->mute = 1; /* maybe not the right place... */ dev->volume = 0x1f; @@ -557,12 +562,15 @@ static void video_mux(struct em28xx *dev, int index) em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); if (dev->has_msp34xx) { - if (dev->i2s_speed) - em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); + if (dev->i2s_speed) { + em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, + &dev->i2s_speed); + } route.input = dev->ctl_ainput; route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); /* Note: this is msp3400 specific */ - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); + em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, + &route); } em28xx_audio_analog_set(dev); @@ -802,7 +810,7 @@ out: return rc; } -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; @@ -919,11 +927,11 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) index = dev->ctl_ainput; - if (index == 0) { + if (index == 0) strcpy(a->name, "Television"); - } else { + else strcpy(a->name, "Line In"); - } + a->capability = V4L2_AUDCAP_STEREO; a->index = index; @@ -1501,7 +1509,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) { int minor = iminor(inode); int errCode = 0, radio = 0; - struct em28xx *h,*dev = NULL; + struct em28xx *h, *dev = NULL; struct em28xx_fh *fh; enum v4l2_buf_type fh_type = 0; @@ -1602,12 +1610,13 @@ static void em28xx_release_resources(struct em28xx *dev) usb_put_dev(dev->udev); /* Mark device as unused */ - em28xx_devused&=~(1<devno); + em28xx_devused &= ~(1<devno); } /* * em28xx_v4l2_close() - * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls + * stops streaming and deallocates all resources allocated by the v4l2 + * calls and ioctls */ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) { @@ -1660,7 +1669,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) * will allocate buffers when called for the first time */ static ssize_t -em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, +em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, loff_t *pos) { struct em28xx_fh *fh = filp->private_data; @@ -1825,7 +1834,7 @@ static struct video_device em28xx_radio_template = { #endif }; -/******************************** usb interface *****************************************/ +/******************************** usb interface ******************************/ static LIST_HEAD(em28xx_extension_devlist); @@ -2088,22 +2097,24 @@ static int em28xx_usb_probe(struct usb_interface *interface, ifnum = interface->altsetting[0].desc.bInterfaceNumber; /* Check to see next free device and mark as used */ - nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS); - em28xx_devused|=1<altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n", - udev->descriptor.idVendor,udev->descriptor.idProduct, + udev->descriptor.idVendor, + udev->descriptor.idProduct, ifnum, interface->altsetting[0].desc.bInterfaceClass); - em28xx_devused&=~(1<descriptor.idVendor,udev->descriptor.idProduct, + udev->descriptor.idVendor, + udev->descriptor.idProduct, ifnum, interface->altsetting[0].desc.bInterfaceClass); @@ -2113,18 +2124,19 @@ static int em28xx_usb_probe(struct usb_interface *interface, if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); - em28xx_devused&=~(1<bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); - em28xx_devused&=~(1<= EM28XX_MAXBOARDS) { - printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); - em28xx_devused&=~(1<actconfig->interface[0]; - dev->num_alt=uif->num_altsetting; - em28xx_info("Alternate settings: %i\n",dev->num_alt); -// dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* - dev->alt_max_pkt_size = kmalloc(32* - dev->num_alt,GFP_KERNEL); + dev->num_alt = uif->num_altsetting; + em28xx_info("Alternate settings: %i\n", dev->num_alt); +/* dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */ + dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); + if (dev->alt_max_pkt_size == NULL) { em28xx_errdev("out of memory!\n"); - em28xx_devused&=~(1<alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - em28xx_info("Alternate setting %i, max size= %i\n",i, - dev->alt_max_pkt_size[i]); + em28xx_info("Alternate setting %i, max size= %i\n", i, + dev->alt_max_pkt_size[i]); } - if ((card[nr]>=0)&&(card[nr]= 0) && (card[nr] < em28xx_bcount)) dev->model = card[nr]; /* allocate device struct */ @@ -2213,7 +2225,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) em28xx_info("disconnecting %s\n", dev->vdev->name); - /* wait until all current v4l2 io is finished then deallocate resources */ + /* wait until all current v4l2 io is finished then deallocate + resources */ mutex_lock(&dev->lock); wake_up_interruptible_all(&dev->open); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 91dce95cd19c..5b21efaf7844 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -365,7 +365,8 @@ struct em28xx { unsigned int video_bytesread; /* Number of bytes read */ unsigned long hash; /* eeprom hash - for boards with generic ID */ - unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */ + unsigned long i2c_hash; /* i2c devicelist hash - + for boards with generic ID */ struct em28xx_audio *adev; @@ -399,14 +400,14 @@ struct em28xx { struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ /* helper funcs that call usb_control_msg */ - int (*em28xx_write_regs) (struct em28xx * dev, u16 reg, char *buf, - int len); - int (*em28xx_read_reg) (struct em28xx * dev, u16 reg); - int (*em28xx_read_reg_req_len) (struct em28xx * dev, u8 req, u16 reg, + int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, char *buf, int len); - int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg, + int (*em28xx_read_reg) (struct em28xx *dev, u16 reg); + int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg, + char *buf, int len); + int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg, char *buf, int len); - int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg); + int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg); enum em28xx_mode mode; @@ -459,7 +460,7 @@ int em28xx_register_extension(struct em28xx_ops *dev); void em28xx_unregister_extension(struct em28xx_ops *dev); /* Provided by em28xx-cards.c */ -extern int em2800_variant_detect(struct usb_device* udev,int model); +extern int em2800_variant_detect(struct usb_device *udev, int model); extern void em28xx_pre_card_setup(struct em28xx *dev); extern void em28xx_card_setup(struct em28xx *dev); extern struct em28xx_board em28xx_boards[]; @@ -557,80 +558,80 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, printk(KERN_WARNING "%s: "fmt,\ dev->name , ##arg); } while (0) -inline static int em28xx_compression_disable(struct em28xx *dev) +static inline int em28xx_compression_disable(struct em28xx *dev) { /* side effect of disabling scaler and mixer */ return em28xx_write_regs(dev, COMPR_REG, "\x00", 1); } -inline static int em28xx_contrast_get(struct em28xx *dev) +static inline int em28xx_contrast_get(struct em28xx *dev) { return em28xx_read_reg(dev, YGAIN_REG) & 0x1f; } -inline static int em28xx_brightness_get(struct em28xx *dev) +static inline int em28xx_brightness_get(struct em28xx *dev) { return em28xx_read_reg(dev, YOFFSET_REG); } -inline static int em28xx_saturation_get(struct em28xx *dev) +static inline int em28xx_saturation_get(struct em28xx *dev) { return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f; } -inline static int em28xx_u_balance_get(struct em28xx *dev) +static inline int em28xx_u_balance_get(struct em28xx *dev) { return em28xx_read_reg(dev, UOFFSET_REG); } -inline static int em28xx_v_balance_get(struct em28xx *dev) +static inline int em28xx_v_balance_get(struct em28xx *dev) { return em28xx_read_reg(dev, VOFFSET_REG); } -inline static int em28xx_gamma_get(struct em28xx *dev) +static inline int em28xx_gamma_get(struct em28xx *dev) { return em28xx_read_reg(dev, GAMMA_REG) & 0x3f; } -inline static int em28xx_contrast_set(struct em28xx *dev, s32 val) +static inline int em28xx_contrast_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1); } -inline static int em28xx_brightness_set(struct em28xx *dev, s32 val) +static inline int em28xx_brightness_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1); } -inline static int em28xx_saturation_set(struct em28xx *dev, s32 val) +static inline int em28xx_saturation_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1); } -inline static int em28xx_u_balance_set(struct em28xx *dev, s32 val) +static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1); } -inline static int em28xx_v_balance_set(struct em28xx *dev, s32 val) +static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1); } -inline static int em28xx_gamma_set(struct em28xx *dev, s32 val) +static inline int em28xx_gamma_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1); } /*FIXME: maxw should be dependent of alt mode */ -inline static unsigned int norm_maxw(struct em28xx *dev) +static inline unsigned int norm_maxw(struct em28xx *dev) { if (dev->max_range_640_480) return 640; @@ -638,7 +639,7 @@ inline static unsigned int norm_maxw(struct em28xx *dev) return 720; } -inline static unsigned int norm_maxh(struct em28xx *dev) +static inline unsigned int norm_maxh(struct em28xx *dev) { if (dev->max_range_640_480) return 480; From 83244025e70aadd7e8baad520decf5d53d534d8f Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 17 Apr 2008 21:41:16 -0300 Subject: [PATCH 337/452] V4L/DVB (7608): em28xx-dvb: Some cleanups and fixes em28xx-dvb.c: - Remove unneeded xc3028_ctrl structure. The driver automatically preserves the previous value tuner-xc2028.c: - Make the return type for xc2028_get_reg signed, since all of the callers are looking for "< 0" to detect errors. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-dvb.c | 4 ---- drivers/media/video/tuner-xc2028.c | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 21b8f1d48024..39581d976e01 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -214,17 +214,13 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = { static int attach_xc3028(u8 addr, struct em28xx *dev) { struct dvb_frontend *fe; - struct xc2028_ctrl ctl; struct xc2028_config cfg; memset(&cfg, 0, sizeof(cfg)); cfg.i2c_adap = &dev->i2c_adap; cfg.i2c_addr = addr; - cfg.ctrl = &ctl; cfg.callback = em28xx_tuner_callback; - em28xx_setup_xc3028(dev, &ctl); - if (!dev->dvb->frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " "Can't attach xc3028\n", diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 95d5922eac95..9dd688ec3cff 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -130,7 +130,7 @@ struct xc2028_data { _rc; \ }) -static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) +static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) { unsigned char buf[2]; unsigned char ibuf[2]; From 7640ea99339c687864f6131598e2eee2ca73cb9c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 17 Apr 2008 21:41:23 -0300 Subject: [PATCH 338/452] V4L/DVB (7609): em28xx-core: speed-up firmware load em28xx-core.c: - Remove sleep in i2c message routine which slows down i2c by a factor 10x. Load time for BASE firmware went from 13s to .973s Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index a742a57d3979..9cbc4788090c 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -153,7 +153,6 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, bufs, len, HZ); - msleep(5); /* FIXME: magic number */ kfree(bufs); return ret; } From 89b329ef9d7cc16ed46fc991b21b2d45e7bf452c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:42:14 -0300 Subject: [PATCH 339/452] V4L/DVB (7610): em28xx: Select reg wait time based on chip ID This is more conservative than just removing the msleep() from em28xx_write_regs_req(), since some old hardware may still need it. So, it will remove the sleep time only for those chips where this removal were tested. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 14 ++++++++++++++ drivers/media/video/em28xx/em28xx-core.c | 3 +++ drivers/media/video/em28xx/em28xx-video.c | 4 ---- drivers/media/video/em28xx/em28xx.h | 3 +++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 7dfea3ac9b2f..0c71e599c140 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -525,6 +525,20 @@ static void em28xx_set_model(struct em28xx *dev) */ void em28xx_pre_card_setup(struct em28xx *dev) { + int rc; + + dev->wait_after_write = 5; + rc = em28xx_read_reg(dev, CHIPID_REG); + if (rc > 0) { + switch (rc) { + case 36: + em28xx_info("chip ID is em2882/em2883\n"); + dev->wait_after_write = 0; + break; + default: + em28xx_info("em28xx chip ID = %d\n", rc); + } + } em28xx_set_model(dev); /* request some modules */ diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 9cbc4788090c..e47b206187b5 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -153,6 +153,9 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, bufs, len, HZ); + if (dev->wait_after_write) + msleep(dev->wait_after_write); + kfree(bufs); return ret; } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 1ac90322d681..a8aa09c5bc5f 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1927,10 +1927,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->em28xx_read_reg_req = em28xx_read_reg_req; dev->is_em2800 = em28xx_boards[dev->model].is_em2800; - errCode = em28xx_read_reg(dev, CHIPID_REG); - if (errCode >= 0) - em28xx_info("em28xx chip ID = %d\n", errCode); - em28xx_pre_card_setup(dev); errCode = em28xx_config(dev); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 5b21efaf7844..8f12b848b1d1 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -331,6 +331,9 @@ struct em28xx { unsigned int max_range_640_480:1; unsigned int has_dvb:1; + /* Some older em28xx chips needs a waiting time after writing */ + unsigned int wait_after_write; + /* GPIO sequences for tuner callback */ struct em28xx_reg_seq *analog_gpio, *digital_gpio; From 2ba890ec0849b222a6dabb5192ccd8fd1696d6d3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:42:58 -0300 Subject: [PATCH 340/452] V4L/DVB (7611): em28xx: Move registers to a separate file em28xx.h contains lots of different stuff inside. The better is to break it on some files. This patch removes the register names, moving them to a separate file. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/em28xx/em28xx-reg.h | 88 +++++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 66 +---------------- 3 files changed, 90 insertions(+), 66 deletions(-) create mode 100644 drivers/media/video/em28xx/em28xx-reg.h diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 0c71e599c140..0cf61a502203 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -531,7 +531,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) rc = em28xx_read_reg(dev, CHIPID_REG); if (rc > 0) { switch (rc) { - case 36: + case CHIP_ID_EM2883: em28xx_info("chip ID is em2882/em2883\n"); dev->wait_after_write = 0; break; diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h new file mode 100644 index 000000000000..02eb2b171ba6 --- /dev/null +++ b/drivers/media/video/em28xx/em28xx-reg.h @@ -0,0 +1,88 @@ +#define EM_GPIO_0 (1 << 0) +#define EM_GPIO_1 (1 << 1) +#define EM_GPIO_2 (1 << 2) +#define EM_GPIO_3 (1 << 3) +#define EM_GPIO_4 (1 << 4) +#define EM_GPIO_5 (1 << 5) +#define EM_GPIO_6 (1 << 6) +#define EM_GPIO_7 (1 << 7) + +#define EM_GPO_0 (1 << 0) +#define EM_GPO_1 (1 << 1) +#define EM_GPO_2 (1 << 2) +#define EM_GPO_3 (1 << 3) + +/* em2800 registers */ +#define EM2800_AUDIOSRC_REG 0x08 + +/* em28xx registers */ + + /* GPIO/GPO registers */ +#define EM_R04_GPO 0x04 /* em2880-em2883 only */ +#define EM_R08_GPIO 0x08 /* em2820 or upper */ + +#define I2C_CLK_REG 0x06 +#define CHIPID_REG 0x0a +#define USBSUSP_REG 0x0c /* */ + +#define AUDIOSRC_REG 0x0e +#define XCLK_REG 0x0f + +#define VINMODE_REG 0x10 +#define VINCTRL_REG 0x11 +#define VINENABLE_REG 0x12 /* */ + +#define GAMMA_REG 0x14 +#define RGAIN_REG 0x15 +#define GGAIN_REG 0x16 +#define BGAIN_REG 0x17 +#define ROFFSET_REG 0x18 +#define GOFFSET_REG 0x19 +#define BOFFSET_REG 0x1a + +#define OFLOW_REG 0x1b +#define HSTART_REG 0x1c +#define VSTART_REG 0x1d +#define CWIDTH_REG 0x1e +#define CHEIGHT_REG 0x1f + +#define YGAIN_REG 0x20 +#define YOFFSET_REG 0x21 +#define UVGAIN_REG 0x22 +#define UOFFSET_REG 0x23 +#define VOFFSET_REG 0x24 +#define SHARPNESS_REG 0x25 + +#define COMPR_REG 0x26 +#define OUTFMT_REG 0x27 + +#define XMIN_REG 0x28 +#define XMAX_REG 0x29 +#define YMIN_REG 0x2a +#define YMAX_REG 0x2b + +#define HSCALELOW_REG 0x30 +#define HSCALEHIGH_REG 0x31 +#define VSCALELOW_REG 0x32 +#define VSCALEHIGH_REG 0x33 + +#define AC97LSB_REG 0x40 +#define AC97MSB_REG 0x41 +#define AC97ADDR_REG 0x42 +#define AC97BUSY_REG 0x43 + +/* em202 registers */ +#define MASTER_AC97 0x02 +#define LINE_IN_AC97 0x10 +#define VIDEO_AC97 0x14 + +/* register settings */ +#define EM2800_AUDIO_SRC_TUNER 0x0d +#define EM2800_AUDIO_SRC_LINE 0x0c +#define EM28XX_AUDIO_SRC_TUNER 0xc0 +#define EM28XX_AUDIO_SRC_LINE 0x80 + +/* FIXME: Need to be populated with the other chip ID's */ +enum em28xx_chip_id { + CHIP_ID_EM2883 = 36, +}; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 8f12b848b1d1..2188bc44c465 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -35,6 +35,7 @@ #include #endif #include "tuner-xc2028.h" +#include "em28xx-reg.h" /* Boards supported by driver */ #define EM2800_BOARD_UNKNOWN 0 @@ -480,71 +481,6 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); -/* em2800 registers */ -#define EM2800_AUDIOSRC_REG 0x08 - -/* em28xx registers */ -#define I2C_CLK_REG 0x06 -#define CHIPID_REG 0x0a -#define USBSUSP_REG 0x0c /* */ - -#define AUDIOSRC_REG 0x0e -#define XCLK_REG 0x0f - -#define VINMODE_REG 0x10 -#define VINCTRL_REG 0x11 -#define VINENABLE_REG 0x12 /* */ - -#define GAMMA_REG 0x14 -#define RGAIN_REG 0x15 -#define GGAIN_REG 0x16 -#define BGAIN_REG 0x17 -#define ROFFSET_REG 0x18 -#define GOFFSET_REG 0x19 -#define BOFFSET_REG 0x1a - -#define OFLOW_REG 0x1b -#define HSTART_REG 0x1c -#define VSTART_REG 0x1d -#define CWIDTH_REG 0x1e -#define CHEIGHT_REG 0x1f - -#define YGAIN_REG 0x20 -#define YOFFSET_REG 0x21 -#define UVGAIN_REG 0x22 -#define UOFFSET_REG 0x23 -#define VOFFSET_REG 0x24 -#define SHARPNESS_REG 0x25 - -#define COMPR_REG 0x26 -#define OUTFMT_REG 0x27 - -#define XMIN_REG 0x28 -#define XMAX_REG 0x29 -#define YMIN_REG 0x2a -#define YMAX_REG 0x2b - -#define HSCALELOW_REG 0x30 -#define HSCALEHIGH_REG 0x31 -#define VSCALELOW_REG 0x32 -#define VSCALEHIGH_REG 0x33 - -#define AC97LSB_REG 0x40 -#define AC97MSB_REG 0x41 -#define AC97ADDR_REG 0x42 -#define AC97BUSY_REG 0x43 - -/* em202 registers */ -#define MASTER_AC97 0x02 -#define LINE_IN_AC97 0x10 -#define VIDEO_AC97 0x14 - -/* register settings */ -#define EM2800_AUDIO_SRC_TUNER 0x0d -#define EM2800_AUDIO_SRC_LINE 0x0c -#define EM28XX_AUDIO_SRC_TUNER 0xc0 -#define EM28XX_AUDIO_SRC_LINE 0x80 - /* printk macros */ #define em28xx_err(fmt, arg...) do {\ From 7e26ca8012a8392c5e53055b8ff3d9512faee6c6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:43:38 -0300 Subject: [PATCH 341/452] V4L/DVB (7612): em28xx-cards: use register names for GPIO/GPO Before this patch, registers 0x04 and 0x08 were referenced by its value. This is bad, since makes harder for someone to understand what this is doing. This patch renames those two registers into an appropriate name. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 0cf61a502203..cbf6e179acb4 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -436,18 +436,18 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); /* Board Hauppauge WinTV HVR 900 analog */ struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { - { -1, -1, 6}, - {0x08, 0x2d, 10}, - {0x08, 0x3d, 5}, - { -1, -1, -1}, + { -1, -1, 6}, + {EM_R08_GPIO, 0x2d, 10}, + {EM_R08_GPIO, 0x3d, 5}, + { -1, -1, -1}, }; /* Board Hauppauge WinTV HVR 900 digital */ struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { - { -1, -1, 6}, - {0x08, 0x2e, 6}, - {0x08, 0x3e, 6}, - {0x04, 0x04, 10}, - {0x04, 0x0c, 10}, + { -1, -1, 6}, + {EM_R08_GPIO, 0x2e, 6}, + {EM_R08_GPIO, 0x3e, 6}, + {EM_R04_GPO, 0x04, 10}, + {EM_R04_GPO, 0x0c, 10}, { -1, -1, -1}, }; From 41facaa4b63cc1a0ff5a900149a29942d47e1491 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:44:58 -0300 Subject: [PATCH 342/452] V4L/DVB (7613): em28xx: rename registers Now, all registers will follow the same convension: EM28XX_R_ This allows to associate a register with its value, and also with a canonical name. Also, registers that are specific to a given chip were renamed accordingly, as EM2800_foo (for 2800 only registers) or EM2880_foo (for registers that started to appear on em2880). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 18 ++--- drivers/media/video/em28xx/em28xx-core.c | 84 ++++++++++----------- drivers/media/video/em28xx/em28xx-reg.h | 92 +++++++++++------------ drivers/media/video/em28xx/em28xx-video.c | 6 +- drivers/media/video/em28xx/em28xx.h | 26 +++---- 5 files changed, 113 insertions(+), 113 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index cbf6e179acb4..ed50b4e55264 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -437,17 +437,17 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); /* Board Hauppauge WinTV HVR 900 analog */ struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { { -1, -1, 6}, - {EM_R08_GPIO, 0x2d, 10}, - {EM_R08_GPIO, 0x3d, 5}, + {EM28XX_R08_GPIO, 0x2d, 10}, + {EM28XX_R08_GPIO, 0x3d, 5}, { -1, -1, -1}, }; /* Board Hauppauge WinTV HVR 900 digital */ struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { { -1, -1, 6}, - {EM_R08_GPIO, 0x2e, 6}, - {EM_R08_GPIO, 0x3e, 6}, - {EM_R04_GPO, 0x04, 10}, - {EM_R04_GPO, 0x0c, 10}, + {EM28XX_R08_GPIO, 0x2e, 6}, + {EM28XX_R08_GPIO, 0x3e, 6}, + {EM2880_R04_GPO, 0x04, 10}, + {EM2880_R04_GPO, 0x0c, 10}, { -1, -1, -1}, }; @@ -528,7 +528,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) int rc; dev->wait_after_write = 5; - rc = em28xx_read_reg(dev, CHIPID_REG); + rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); if (rc > 0) { switch (rc) { case CHIP_ID_EM2883: @@ -547,8 +547,8 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: - em28xx_write_regs(dev, XCLK_REG, "\x27", 1); - em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1); + em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); em28xx_write_regs(dev, 0x08, "\xff", 1); em28xx_write_regs(dev, 0x04, "\x00", 1); msleep(100); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index e47b206187b5..01d5f44268ff 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -194,17 +194,17 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) int ret, i; u8 addr = reg & 0x7f; - ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2); + ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, val, 2); if (ret < 0) return ret; - ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1); + ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1); if (ret < 0) return ret; /* Wait up to 50 ms for AC97 command to complete */ for (i = 0; i < 10; i++) { - ret = em28xx_read_reg(dev, AC97BUSY_REG); + ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY); if (ret < 0) return ret; @@ -230,7 +230,7 @@ static int em28xx_set_audio_source(struct em28xx *dev) else input = EM2800_AUDIO_SRC_TUNER; - ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1); + ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1); if (ret < 0) return ret; } @@ -256,7 +256,7 @@ static int em28xx_set_audio_source(struct em28xx *dev) } } - ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); + ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0); if (ret < 0) return ret; msleep(5); @@ -264,11 +264,11 @@ static int em28xx_set_audio_source(struct em28xx *dev) /* Sets AC97 mixer registers This is seems to be needed, even for non-ac97 configs */ - ret = em28xx_write_ac97(dev, VIDEO_AC97, video); + ret = em28xx_write_ac97(dev, EM28XX_R14_VIDEO_AC97, video); if (ret < 0) return ret; - ret = em28xx_write_ac97(dev, LINE_IN_AC97, line); + ret = em28xx_write_ac97(dev, EM28XX_R10_LINE_IN_AC97, line); return ret; } @@ -284,7 +284,7 @@ int em28xx_audio_analog_set(struct em28xx *dev) /* Mute */ s[1] |= 0x80; - ret = em28xx_write_ac97(dev, MASTER_AC97, s); + ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s); if (ret < 0) return ret; @@ -295,7 +295,7 @@ int em28xx_audio_analog_set(struct em28xx *dev) if (!dev->mute) xclk |= 0x80; - ret = em28xx_write_reg_bits(dev, XCLK_REG, xclk, 0xa7); + ret = em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, xclk, 0xa7); if (ret < 0) return ret; msleep(10); @@ -306,7 +306,7 @@ int em28xx_audio_analog_set(struct em28xx *dev) /* Unmute device */ if (!dev->mute) s[1] &= ~0x80; - ret = em28xx_write_ac97(dev, MASTER_AC97, s); + ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s); return ret; } @@ -314,20 +314,20 @@ EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); int em28xx_colorlevels_set_default(struct em28xx *dev) { - em28xx_write_regs(dev, YGAIN_REG, "\x10", 1); /* contrast */ - em28xx_write_regs(dev, YOFFSET_REG, "\x00", 1); /* brightness */ - em28xx_write_regs(dev, UVGAIN_REG, "\x10", 1); /* saturation */ - em28xx_write_regs(dev, UOFFSET_REG, "\x00", 1); - em28xx_write_regs(dev, VOFFSET_REG, "\x00", 1); - em28xx_write_regs(dev, SHARPNESS_REG, "\x00", 1); + em28xx_write_regs(dev, EM28XX_R20_YGAIN, "\x10", 1); /* contrast */ + em28xx_write_regs(dev, EM28XX_R21_YOFFSET, "\x00", 1); /* brightness */ + em28xx_write_regs(dev, EM28XX_R22_UVGAIN, "\x10", 1); /* saturation */ + em28xx_write_regs(dev, EM28XX_R23_UOFFSET, "\x00", 1); + em28xx_write_regs(dev, EM28XX_R24_VOFFSET, "\x00", 1); + em28xx_write_regs(dev, EM28XX_R25_SHARPNESS, "\x00", 1); - em28xx_write_regs(dev, GAMMA_REG, "\x20", 1); - em28xx_write_regs(dev, RGAIN_REG, "\x20", 1); - em28xx_write_regs(dev, GGAIN_REG, "\x20", 1); - em28xx_write_regs(dev, BGAIN_REG, "\x20", 1); - em28xx_write_regs(dev, ROFFSET_REG, "\x00", 1); - em28xx_write_regs(dev, GOFFSET_REG, "\x00", 1); - return em28xx_write_regs(dev, BOFFSET_REG, "\x00", 1); + em28xx_write_regs(dev, EM28XX_R14_GAMMA, "\x20", 1); + em28xx_write_regs(dev, EM28XX_R15_RGAIN, "\x20", 1); + em28xx_write_regs(dev, EM28XX_R16_GGAIN, "\x20", 1); + em28xx_write_regs(dev, EM28XX_R17_BGAIN, "\x20", 1); + em28xx_write_regs(dev, EM28XX_R18_ROFFSET, "\x00", 1); + em28xx_write_regs(dev, EM28XX_R19_GOFFSET, "\x00", 1); + return em28xx_write_regs(dev, EM28XX_R1A_BOFFSET, "\x00", 1); } int em28xx_capture_start(struct em28xx *dev, int start) @@ -335,14 +335,14 @@ int em28xx_capture_start(struct em28xx *dev, int start) int rc; /* FIXME: which is the best order? */ /* video registers are sampled by VREF */ - rc = em28xx_write_reg_bits(dev, USBSUSP_REG, + rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP, start ? 0x10 : 0x00, 0x10); if (rc < 0) return rc; if (!start) { /* disable video capture */ - rc = em28xx_write_regs(dev, VINENABLE_REG, "\x27", 1); + rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x27", 1); return rc; } @@ -350,9 +350,9 @@ int em28xx_capture_start(struct em28xx *dev, int start) rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); if (dev->mode == EM28XX_ANALOG_MODE) - rc = em28xx_write_regs(dev, VINENABLE_REG, "\x67", 1); + rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x67", 1); else - rc = em28xx_write_regs(dev, VINENABLE_REG, "\x37", 1); + rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x37", 1); msleep(6); @@ -361,9 +361,9 @@ int em28xx_capture_start(struct em28xx *dev, int start) int em28xx_outfmt_set_yuv422(struct em28xx *dev) { - em28xx_write_regs(dev, OUTFMT_REG, "\x34", 1); - em28xx_write_regs(dev, VINMODE_REG, "\x10", 1); - return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1); + em28xx_write_regs(dev, EM28XX_R27_OUTFMT, "\x34", 1); + em28xx_write_regs(dev, EM28XX_R10_VINMODE, "\x10", 1); + return em28xx_write_regs(dev, EM28XX_R11_VINCTRL, "\x11", 1); } static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, @@ -372,10 +372,10 @@ static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax); - em28xx_write_regs(dev, XMIN_REG, &xmin, 1); - em28xx_write_regs(dev, XMAX_REG, &xmax, 1); - em28xx_write_regs(dev, YMIN_REG, &ymin, 1); - return em28xx_write_regs(dev, YMAX_REG, &ymax, 1); + em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1); + em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1); + em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1); + return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1); } static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, @@ -389,11 +389,11 @@ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, (width | (overflow & 2) << 7), (height | (overflow & 1) << 8)); - em28xx_write_regs(dev, HSTART_REG, &hstart, 1); - em28xx_write_regs(dev, VSTART_REG, &vstart, 1); - em28xx_write_regs(dev, CWIDTH_REG, &cwidth, 1); - em28xx_write_regs(dev, CHEIGHT_REG, &cheight, 1); - return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1); + em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1); + em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1); + em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1); + em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1); + return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1); } static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) @@ -406,15 +406,15 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) u8 buf[2]; buf[0] = h; buf[1] = h >> 8; - em28xx_write_regs(dev, HSCALELOW_REG, (char *)buf, 2); + em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); buf[0] = v; buf[1] = v >> 8; - em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2); + em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); /* it seems that both H and V scalers must be active to work correctly */ mode = (h || v)? 0x30: 0x00; } - return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30); + return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30); } /* FIXME: this only function read values from dev */ diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 02eb2b171ba6..9058bed07953 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h @@ -13,68 +13,68 @@ #define EM_GPO_3 (1 << 3) /* em2800 registers */ -#define EM2800_AUDIOSRC_REG 0x08 +#define EM2800_R08_AUDIOSRC 0x08 /* em28xx registers */ /* GPIO/GPO registers */ -#define EM_R04_GPO 0x04 /* em2880-em2883 only */ -#define EM_R08_GPIO 0x08 /* em2820 or upper */ +#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ +#define EM28XX_R08_GPIO 0x08 /* em2820 or upper */ -#define I2C_CLK_REG 0x06 -#define CHIPID_REG 0x0a -#define USBSUSP_REG 0x0c /* */ +#define EM28XX_R06_I2C_CLK 0x06 +#define EM28XX_R0A_CHIPID 0x0a +#define EM28XX_R0C_USBSUSP 0x0c /* */ -#define AUDIOSRC_REG 0x0e -#define XCLK_REG 0x0f +#define EM28XX_R0E_AUDIOSRC 0x0e +#define EM28XX_R0F_XCLK 0x0f -#define VINMODE_REG 0x10 -#define VINCTRL_REG 0x11 -#define VINENABLE_REG 0x12 /* */ +#define EM28XX_R10_VINMODE 0x10 +#define EM28XX_R11_VINCTRL 0x11 +#define EM28XX_R12_VINENABLE 0x12 /* */ -#define GAMMA_REG 0x14 -#define RGAIN_REG 0x15 -#define GGAIN_REG 0x16 -#define BGAIN_REG 0x17 -#define ROFFSET_REG 0x18 -#define GOFFSET_REG 0x19 -#define BOFFSET_REG 0x1a +#define EM28XX_R14_GAMMA 0x14 +#define EM28XX_R15_RGAIN 0x15 +#define EM28XX_R16_GGAIN 0x16 +#define EM28XX_R17_BGAIN 0x17 +#define EM28XX_R18_ROFFSET 0x18 +#define EM28XX_R19_GOFFSET 0x19 +#define EM28XX_R1A_BOFFSET 0x1a -#define OFLOW_REG 0x1b -#define HSTART_REG 0x1c -#define VSTART_REG 0x1d -#define CWIDTH_REG 0x1e -#define CHEIGHT_REG 0x1f +#define EM28XX_R1B_OFLOW 0x1b +#define EM28XX_R1C_HSTART 0x1c +#define EM28XX_R1D_VSTART 0x1d +#define EM28XX_R1E_CWIDTH 0x1e +#define EM28XX_R1F_CHEIGHT 0x1f -#define YGAIN_REG 0x20 -#define YOFFSET_REG 0x21 -#define UVGAIN_REG 0x22 -#define UOFFSET_REG 0x23 -#define VOFFSET_REG 0x24 -#define SHARPNESS_REG 0x25 +#define EM28XX_R20_YGAIN 0x20 +#define EM28XX_R21_YOFFSET 0x21 +#define EM28XX_R22_UVGAIN 0x22 +#define EM28XX_R23_UOFFSET 0x23 +#define EM28XX_R24_VOFFSET 0x24 +#define EM28XX_R25_SHARPNESS 0x25 -#define COMPR_REG 0x26 -#define OUTFMT_REG 0x27 +#define EM28XX_R26_COMPR 0x26 +#define EM28XX_R27_OUTFMT 0x27 -#define XMIN_REG 0x28 -#define XMAX_REG 0x29 -#define YMIN_REG 0x2a -#define YMAX_REG 0x2b +#define EM28XX_R28_XMIN 0x28 +#define EM28XX_R29_XMAX 0x29 +#define EM28XX_R2A_YMIN 0x2a +#define EM28XX_R2B_YMAX 0x2b -#define HSCALELOW_REG 0x30 -#define HSCALEHIGH_REG 0x31 -#define VSCALELOW_REG 0x32 -#define VSCALEHIGH_REG 0x33 +#define EM28XX_R30_HSCALELOW 0x30 +#define EM28XX_R31_HSCALEHIGH 0x31 +#define EM28XX_R32_VSCALELOW 0x32 +#define EM28XX_R33_VSCALEHIGH 0x33 -#define AC97LSB_REG 0x40 -#define AC97MSB_REG 0x41 -#define AC97ADDR_REG 0x42 -#define AC97BUSY_REG 0x43 +#define EM28XX_R40_AC97LSB 0x40 +#define EM28XX_R41_AC97MSB 0x41 +#define EM28XX_R42_AC97ADDR 0x42 +#define EM28XX_R43_AC97BUSY 0x43 /* em202 registers */ -#define MASTER_AC97 0x02 -#define LINE_IN_AC97 0x10 -#define VIDEO_AC97 0x14 +#define EM28XX_R02_MASTER_AC97 0x02 +#define EM28XX_R10_LINE_IN_AC97 0x10 +#define EM28XX_R14_VIDEO_AC97 0x14 /* register settings */ #define EM2800_AUDIO_SRC_TUNER 0x0d diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index a8aa09c5bc5f..fb533fda2198 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1142,9 +1142,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int em28xx_reg_len(int reg) { switch (reg) { - case AC97LSB_REG: - case HSCALELOW_REG: - case VSCALELOW_REG: + case EM28XX_R40_AC97LSB: + case EM28XX_R30_HSCALELOW: + case EM28XX_R32_VSCALELOW: return 2; default: return 1; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 2188bc44c465..e4a56d8dfcf4 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -500,73 +500,73 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, static inline int em28xx_compression_disable(struct em28xx *dev) { /* side effect of disabling scaler and mixer */ - return em28xx_write_regs(dev, COMPR_REG, "\x00", 1); + return em28xx_write_regs(dev, EM28XX_R26_COMPR, "\x00", 1); } static inline int em28xx_contrast_get(struct em28xx *dev) { - return em28xx_read_reg(dev, YGAIN_REG) & 0x1f; + return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f; } static inline int em28xx_brightness_get(struct em28xx *dev) { - return em28xx_read_reg(dev, YOFFSET_REG); + return em28xx_read_reg(dev, EM28XX_R21_YOFFSET); } static inline int em28xx_saturation_get(struct em28xx *dev) { - return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f; + return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f; } static inline int em28xx_u_balance_get(struct em28xx *dev) { - return em28xx_read_reg(dev, UOFFSET_REG); + return em28xx_read_reg(dev, EM28XX_R23_UOFFSET); } static inline int em28xx_v_balance_get(struct em28xx *dev) { - return em28xx_read_reg(dev, VOFFSET_REG); + return em28xx_read_reg(dev, EM28XX_R24_VOFFSET); } static inline int em28xx_gamma_get(struct em28xx *dev) { - return em28xx_read_reg(dev, GAMMA_REG) & 0x3f; + return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f; } static inline int em28xx_contrast_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1); + return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1); } static inline int em28xx_brightness_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1); + return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1); } static inline int em28xx_saturation_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1); + return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1); } static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1); + return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1); } static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1); + return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1); } static inline int em28xx_gamma_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1); + return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1); } /*FIXME: maxw should be dependent of alt mode */ From 82ac4f876505615ba9dc6a73cd9a584bad8fe23f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:46:14 -0300 Subject: [PATCH 343/452] V4L/DVB (7614): em28xx-core: fix some debug printk's that wrongly received KERN_INFO Those printk's were adding more info to a line that were already being printed. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 01d5f44268ff..bd7794f4fd74 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -80,9 +80,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, if (reg_debug) { printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); for (byte = 0; byte < len; byte++) - printk(KERN_INFO " %02x", (unsigned char)buf[byte]); + printk(" %02x", (unsigned char)buf[byte]); - printk(KERN_INFO "\n"); + printk("\n"); } return ret; @@ -143,8 +143,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, if (reg_debug) { int i; for (i = 0; i < len; ++i) - printk(KERN_INFO " %02x", (unsigned char)buf[i]); - printk(KERN_INFO "\n"); + printk(" %02x", (unsigned char)buf[i]); + printk("\n"); } if (!bufs) From c67ec53f8f4e90ebd482789e2f6d121f41a0bd90 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:48:00 -0300 Subject: [PATCH 344/452] V4L/DVB (7615): em28xx: Provide the proper support for switching between analog/digital Before this patch, HVR900/HVR950 were incorreclty going back to analog. The result is that only digital were working. This patch provides the proper setup for analog/digital and tuner callback. It also properly resets analog into a sane state at open(). Thanks to Steven Toth and Michael Krufky for helping to set the proper parameters to GPO/GPIO em2883 ports. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 81 +++++++++----------- drivers/media/video/em28xx/em28xx-core.c | 90 +++++++++++++++++++++-- drivers/media/video/em28xx/em28xx-dvb.c | 20 ++--- drivers/media/video/em28xx/em28xx-video.c | 12 ++- drivers/media/video/em28xx/em28xx.h | 22 +++--- 5 files changed, 150 insertions(+), 75 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ed50b4e55264..13ffde281067 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -436,19 +436,25 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); /* Board Hauppauge WinTV HVR 900 analog */ struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { - { -1, -1, 6}, - {EM28XX_R08_GPIO, 0x2d, 10}, - {EM28XX_R08_GPIO, 0x3d, 5}, - { -1, -1, -1}, + {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, + {0x05, 0xff, 0x10, 10}, + { -1, -1, -1, -1}, }; + /* Board Hauppauge WinTV HVR 900 digital */ struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { - { -1, -1, 6}, - {EM28XX_R08_GPIO, 0x2e, 6}, - {EM28XX_R08_GPIO, 0x3e, 6}, - {EM2880_R04_GPO, 0x04, 10}, - {EM2880_R04_GPO, 0x0c, 10}, - { -1, -1, -1}, + {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, + {EM2880_R04_GPO, 0x04, 0x0f, 10}, + {EM2880_R04_GPO, 0x0c, 0x0f, 10}, + { -1, -1, -1, -1}, +}; + +/* Board Hauppauge WinTV HVR 900 tuner_callback */ +struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = { + {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, + {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, + {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, + { -1, -1, -1, -1}, }; /* @@ -469,7 +475,6 @@ int em28xx_tuner_callback(void *ptr, int command, int arg) { int rc = 0; struct em28xx *dev = ptr; - struct em28xx_reg_seq *gpio; if (dev->tuner_type != TUNER_XC2028) return 0; @@ -478,32 +483,10 @@ int em28xx_tuner_callback(void *ptr, int command, int arg) return 0; if (dev->mode == EM28XX_ANALOG_MODE) - gpio = dev->analog_gpio; + rc = em28xx_gpio_set(dev, dev->tun_analog_gpio); else - gpio = dev->digital_gpio; + rc = em28xx_gpio_set(dev, dev->tun_digital_gpio); - /* djh - Not sure if these are still required */ - dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); - if (dev->mode == EM28XX_ANALOG_MODE) - dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); - else - dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1); - msleep(6); - - if (!gpio) - return rc; - - /* Send GPIO reset sequences specified at board entry */ - while (gpio->sleep >= 0) { - if (gpio->reg >= 0) - rc = dev->em28xx_write_regs(dev, - gpio->reg, - &gpio->val, 1); - if (gpio->sleep > 0) - msleep(gpio->sleep); - - gpio++; - } return rc; } EXPORT_SYMBOL_GPL(em28xx_tuner_callback); @@ -527,6 +510,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) { int rc; + rc = em28xx_read_reg(dev, EM2880_R04_GPO); + if (rc >= 0) + dev->reg_gpo = rc; + dev->wait_after_write = 5; rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); if (rc > 0) { @@ -547,24 +534,24 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); - em28xx_write_regs(dev, 0x08, "\xff", 1); - em28xx_write_regs(dev, 0x04, "\x00", 1); - msleep(100); - em28xx_write_regs(dev, 0x04, "\x08", 1); - msleep(100); - em28xx_write_regs(dev, 0x08, "\xff", 1); msleep(50); - em28xx_write_regs(dev, 0x08, "\x2d", 1); - msleep(50); - em28xx_write_regs(dev, 0x08, "\x3d", 1); - dev->analog_gpio = hauppauge_wintv_hvr_900_analog; - dev->digital_gpio = hauppauge_wintv_hvr_900_digital; + /* Sets GPO/GPIO sequences for this device */ + dev->analog_gpio = hauppauge_wintv_hvr_900_analog; + dev->digital_gpio = hauppauge_wintv_hvr_900_digital; + dev->tun_analog_gpio = hauppauge_wintv_hvr_900_tuner_callback; + dev->tun_digital_gpio = hauppauge_wintv_hvr_900_tuner_callback; break; } + + em28xx_gpio_set(dev, dev->tun_analog_gpio); + em28xx_set_mode(dev, EM28XX_ANALOG_MODE); + + /* Unlock device */ + em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); } void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index bd7794f4fd74..db40358c773b 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -134,7 +134,10 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, unsigned char *bufs; if (dev->state & DEV_DISCONNECTED) - return(-ENODEV); + return -ENODEV; + + if (len < 1) + return -EINVAL; bufs = kmalloc(len, GFP_KERNEL); @@ -162,7 +165,23 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) { - return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); + int rc; + + rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); + + /* Stores GPO/GPIO values at the cache, if changed + Only write values should be stored, since input on a GPIO + register will return the input bits. + Not sure what happens on reading GPO register. + */ + if (rc >= 0) { + if (reg == EM2880_R04_GPO) + dev->reg_gpo = buf[0]; + else if (reg == EM28XX_R08_GPIO) + dev->reg_gpio = buf[0]; + } + + return rc; } /* @@ -176,12 +195,19 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, int oldval; u8 newval; - oldval = em28xx_read_reg(dev, reg); + /* Uses cache for gpo/gpio registers */ + if (reg == EM2880_R04_GPO) + oldval = dev->reg_gpo; + else if (reg == EM28XX_R08_GPIO) + oldval = dev->reg_gpio; + else + oldval = em28xx_read_reg(dev, reg); if (oldval < 0) return oldval; newval = (((u8) oldval) & ~bitmask) | (val & bitmask); + return em28xx_write_regs(dev, reg, &newval, 1); } @@ -472,6 +498,57 @@ int em28xx_set_alternate(struct em28xx *dev) return 0; } +int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio) +{ + int rc = 0; + + if (!gpio) + return rc; + + dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + if (dev->mode == EM28XX_ANALOG_MODE) + dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); + else + dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1); + msleep(6); + + /* Send GPIO reset sequences specified at board entry */ + while (gpio->sleep >= 0) { + if (gpio->reg >= 0) { + rc = em28xx_write_reg_bits(dev, + gpio->reg, + gpio->val, + gpio->mask); + if (rc < 0) + return rc; + } + if (gpio->sleep > 0) + msleep(gpio->sleep); + + gpio++; + } + return rc; +} + +int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode) +{ + if (dev->mode == set_mode) + return 0; + + if (set_mode == EM28XX_MODE_UNDEFINED) { + dev->mode = set_mode; + return 0; + } + + dev->mode = set_mode; + + if (dev->mode == EM28XX_DIGITAL_MODE) + return em28xx_gpio_set(dev, dev->digital_gpio); + else + return em28xx_gpio_set(dev, dev->analog_gpio); +} +EXPORT_SYMBOL_GPL(em28xx_set_mode); + /* ------------------------------------------------------------------ URB control ------------------------------------------------------------------*/ @@ -548,8 +625,7 @@ EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); */ int em28xx_init_isoc(struct em28xx *dev, int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct em28xx *dev, struct urb *urb), - int cap_type) + int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) { struct em28xx_dmaqueue *dma_q = &dev->vidq; int i; @@ -612,7 +688,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, should also be using 'desc.bInterval' */ pipe = usb_rcvisocpipe(dev->udev, - cap_type == EM28XX_ANALOG_CAPTURE ? 0x82 : 0x84); + dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84); usb_fill_int_urb(urb, dev->udev, pipe, dev->isoc_ctl.transfer_buffer[i], sb_size, @@ -632,7 +708,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, init_waitqueue_head(&dma_q->wq); - em28xx_capture_start(dev, cap_type); + em28xx_capture_start(dev, 1); /* submit urbs and enables IRQ */ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 39581d976e01..2e9ec626b609 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -137,14 +137,17 @@ static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb) static int start_streaming(struct em28xx_dvb *dvb) { + int rc; struct em28xx *dev = dvb->adapter.priv; usb_set_interface(dev->udev, 0, 1); - dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); + if (rc < 0) + return rc; return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE, - dvb_isoc_copy, EM28XX_DIGITAL_CAPTURE); + dvb_isoc_copy); } static int stop_streaming(struct em28xx_dvb *dvb) @@ -152,6 +155,9 @@ static int stop_streaming(struct em28xx_dvb *dvb) struct em28xx *dev = dvb->adapter.priv; em28xx_uninit_isoc(dev); + + em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); + return 0; } @@ -368,13 +374,10 @@ static int dvb_init(struct em28xx *dev) } dev->dvb = dvb; + em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: - /* Enable lgdt330x */ - dev->mode = EM28XX_DIGITAL_MODE; - em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); - dvb->frontend = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap); @@ -384,9 +387,6 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - /* Enable zl10353 */ - dev->mode = EM28XX_DIGITAL_MODE; - em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0); dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap); @@ -415,10 +415,12 @@ static int dvb_init(struct em28xx *dev) if (result < 0) goto out_free; + em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); return 0; out_free: + em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); kfree(dvb); dev->dvb = NULL; return result; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index fb533fda2198..4ffd064c402a 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -461,7 +461,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (urb_init) { rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, EM28XX_NUM_BUFS, dev->max_pkt_size, - em28xx_isoc_copy, EM28XX_ANALOG_CAPTURE); + em28xx_isoc_copy); if (rc < 0) goto fail; } @@ -1534,8 +1534,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) em28xx_videodbg("open minor=%d type=%s users=%d\n", minor, v4l2_type_names[fh_type], dev->users); - fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); + fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); if (!fh) { em28xx_errdev("em28xx-video.c: Out of memory?!\n"); return -ENOMEM; @@ -1552,9 +1552,15 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->hscale = 0; dev->vscale = 0; + em28xx_set_mode(dev, EM28XX_ANALOG_MODE); em28xx_set_alternate(dev); em28xx_resolution_set(dev); + /* Needed, since GPIO might have disabled power of + some i2c device + */ + em28xx_config_i2c(dev); + } if (fh->radio) { em28xx_videodbg("video_open: setting radio device\n"); @@ -1568,6 +1574,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) sizeof(struct em28xx_buffer), fh); mutex_unlock(&dev->lock); + return errCode; } @@ -1647,6 +1654,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) /* do this before setting alternate! */ em28xx_uninit_isoc(dev); + em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); /* set alternate 0 */ dev->alt = 0; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index e4a56d8dfcf4..e0d119c22810 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -110,6 +110,7 @@ #define EM2800_I2C_WRITE_TIMEOUT 20 enum em28xx_mode { + EM28XX_MODE_UNDEFINED, EM28XX_ANALOG_MODE, EM28XX_DIGITAL_MODE, }; @@ -228,7 +229,7 @@ enum em28xx_decoder { struct em28xx_reg_seq { int reg; - unsigned char val; + unsigned char val, mask; int sleep; }; @@ -274,12 +275,6 @@ enum em28xx_dev_state { DEV_MISCONFIGURED = 0x04, }; -enum em28xx_capture_mode { - EM28XX_CAPTURE_OFF = 0, - EM28XX_ANALOG_CAPTURE, - EM28XX_DIGITAL_CAPTURE, -}; - #define EM28XX_AUDIO_BUFS 5 #define EM28XX_NUM_AUDIO_PACKETS 64 #define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */ @@ -335,9 +330,12 @@ struct em28xx { /* Some older em28xx chips needs a waiting time after writing */ unsigned int wait_after_write; - /* GPIO sequences for tuner callback */ + /* GPIO sequences for analog and digital mode */ struct em28xx_reg_seq *analog_gpio, *digital_gpio; + /* GPIO sequences for tuner callbacks */ + struct em28xx_reg_seq *tun_analog_gpio, *tun_digital_gpio; + int video_inputs; /* number of video inputs */ struct list_head devlist; @@ -415,6 +413,9 @@ struct em28xx { enum em28xx_mode mode; + /* Caches GPO and GPIO registers */ + unsigned char reg_gpo, reg_gpio; + struct em28xx_dvb *dvb; }; @@ -455,9 +456,10 @@ int em28xx_resolution_set(struct em28xx *dev); int em28xx_set_alternate(struct em28xx *dev); int em28xx_init_isoc(struct em28xx *dev, int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct em28xx *dev, struct urb *urb), - int cap_type); + int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); void em28xx_uninit_isoc(struct em28xx *dev); +int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); +int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); /* Provided by em28xx-video.c */ int em28xx_register_extension(struct em28xx_ops *dev); From e3569abc1c51d24f9c64b214f85477e490b156e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:49:20 -0300 Subject: [PATCH 345/452] V4L/DVB (7616): em28xx-dvb: Properly selects digital mode at the right place The driver should be switched to digital mode, when trying to access the frontend or when streaming. This patch provides the correct code to support this feature. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-dvb.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 2e9ec626b609..7df81575b7f2 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -201,6 +201,18 @@ static int stop_feed(struct dvb_demux_feed *feed) } + +/* ------------------------------------------------------------------ */ +static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) +{ + struct em28xx *dev = fe->dvb->priv; + + if (acquire) + return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); + else + return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); +} + /* ------------------------------------------------------------------ */ static struct lgdt330x_config em2880_lgdt3303_dev = { @@ -268,6 +280,10 @@ int register_dvb(struct em28xx_dvb *dvb, dev->name, result); goto fail_adapter; } + + /* Ensure all frontends negotiate bus access */ + dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; + dvb->adapter.priv = dev; /* register frontend */ @@ -287,6 +303,7 @@ int register_dvb(struct em28xx_dvb *dvb, dvb->demux.feednum = 256; dvb->demux.start_feed = start_feed; dvb->demux.stop_feed = stop_feed; + result = dvb_dmx_init(&dvb->demux); if (result < 0) { printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", From e9888a1330402050e596b2553e7009fe371c42be Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Apr 2008 21:49:59 -0300 Subject: [PATCH 346/452] V4L/DVB (7617): Removes a manual mode setup The setup is already done at open(). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 4ffd064c402a..8996175cc950 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -391,8 +391,6 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) if (*count < EM28XX_MIN_BUF) *count = EM28XX_MIN_BUF; - dev->mode = EM28XX_ANALOG_MODE; - /* Ask tuner to go to analog mode */ memset(&f, 0, sizeof(f)); f.frequency = dev->ctl_freq; From e54318e5a41cfe10325ae2f817d337beb84e79aa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 18 Apr 2008 18:34:31 -0300 Subject: [PATCH 347/452] V4L/DVB (7618): em28xx: make some symbols static Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 9 ++++----- drivers/media/video/em28xx/em28xx.h | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 13ffde281067..93a7176f9cd1 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -435,14 +435,14 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); */ /* Board Hauppauge WinTV HVR 900 analog */ -struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { +static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, {0x05, 0xff, 0x10, 10}, { -1, -1, -1, -1}, }; /* Board Hauppauge WinTV HVR 900 digital */ -struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { +static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x04, 0x0f, 10}, {EM2880_R04_GPO, 0x0c, 0x0f, 10}, @@ -450,7 +450,7 @@ struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { }; /* Board Hauppauge WinTV HVR 900 tuner_callback */ -struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = { +static struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = { {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, @@ -554,7 +554,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); } -void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) +static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) { memset(ctl, 0, sizeof(*ctl)); @@ -571,7 +571,6 @@ void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ctl->demod = XC3028_FE_OREN538; } } -EXPORT_SYMBOL_GPL(em28xx_setup_xc3028); static void em28xx_config_tuner(struct em28xx *dev) { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index e0d119c22810..002f170b211a 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -474,7 +474,6 @@ extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); int em28xx_tuner_callback(void *ptr, int command, int arg); -void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl); /* Provided by em28xx-input.c */ /* TODO: Check if the standard get_key handlers on ir-common can be used */ From e77ebdaa927a9e1b6a2e46086f6ca9a445cd0b88 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 18 Apr 2008 18:37:25 -0300 Subject: [PATCH 348/452] V4L/DVB (7619): em28xx: adds proper demod IF for HVR-900 Thanks to Aidan Thornton for helping to test this firmware Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 93a7176f9cd1..50ccf3771204 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -563,8 +563,11 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ctl->mts = em28xx_boards[dev->model].mts_firmware; switch (dev->model) { - /* Add card-specific parameters for xc3028 here */ + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + ctl->demod = XC3028_FE_ZARLINK456; + break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: + /* FIXME: Better to specify the needed IF */ ctl->demod = XC3028_FE_DEFAULT; break; default: From c8234ea37fb8b7a904223672edf36d269ea569a2 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 29 Mar 2008 18:15:33 -0300 Subject: [PATCH 349/452] V4L/DVB (7620): Adding support for a new i2c bridge type Adding support for a new i2c bridge type Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- include/linux/i2c-id.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index b979112f74e0..32eb8bbe4831 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -125,6 +125,7 @@ #define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */ #define I2C_HW_B_INTELFB 0x010021 /* intel framebuffer driver */ #define I2C_HW_B_CX23885 0x010022 /* conexant 23885 based tv cards (bus1) */ +#define I2C_HW_B_AU0828 0x010023 /* auvitek au0828 usb bridge */ /* --- PCF 8584 based algorithms */ #define I2C_HW_P_ELEK 0x020002 /* Elektor ISA Bus inteface card */ From 265a6510629ab39f33ece43a857089dd37978184 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 18 Apr 2008 21:34:00 -0300 Subject: [PATCH 350/452] V4L/DVB (7621): Add support for Hauppauge HVR950Q/HVR850/FusioHDTV7-USB Including support for the AU0828 USB Bridge. Including support for the AU8522 ATSC/QAM Demodulator. Including support for the AU8522 ATSC/QAM Demodulator. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 8 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/au8522.c | 448 ++++++++++++++++++++++ drivers/media/dvb/frontends/au8522.h | 55 +++ drivers/media/video/Kconfig | 2 + drivers/media/video/Makefile | 2 + drivers/media/video/au0828/Kconfig | 10 + drivers/media/video/au0828/Makefile | 9 + drivers/media/video/au0828/au0828-cards.c | 144 +++++++ drivers/media/video/au0828/au0828-cards.h | 25 ++ drivers/media/video/au0828/au0828-core.c | 252 ++++++++++++ drivers/media/video/au0828/au0828-dvb.c | 371 ++++++++++++++++++ drivers/media/video/au0828/au0828-i2c.c | 402 +++++++++++++++++++ drivers/media/video/au0828/au0828-reg.h | 35 ++ drivers/media/video/au0828/au0828.h | 117 ++++++ 15 files changed, 1881 insertions(+) create mode 100644 drivers/media/dvb/frontends/au8522.c create mode 100644 drivers/media/dvb/frontends/au8522.h create mode 100644 drivers/media/video/au0828/Kconfig create mode 100644 drivers/media/video/au0828/Makefile create mode 100644 drivers/media/video/au0828/au0828-cards.c create mode 100644 drivers/media/video/au0828/au0828-cards.h create mode 100644 drivers/media/video/au0828/au0828-core.c create mode 100644 drivers/media/video/au0828/au0828-dvb.c create mode 100644 drivers/media/video/au0828/au0828-i2c.c create mode 100644 drivers/media/video/au0828/au0828-reg.h create mode 100644 drivers/media/video/au0828/au0828.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 4284a3092c14..ae3659be323f 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -291,6 +291,14 @@ config DVB_S5H1409 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. +config DVB_AU8522 + tristate "Auvitek AU8522 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want + to support this frontend. + comment "Tuners/PLL support" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 129367886bcc..8e23a30ed3be 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -53,3 +53,4 @@ obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o obj-$(CONFIG_DVB_S5H1409) += s5h1409.o obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o +obj-$(CONFIG_DVB_AU8522) += au8522.o diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c new file mode 100644 index 000000000000..d3c44b95e240 --- /dev/null +++ b/drivers/media/dvb/frontends/au8522.c @@ -0,0 +1,448 @@ +/* + Auvitek AU8522 QAM/8VSB demodulator driver + + Copyright (C) 2008 Steven Toth + + 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 +#include +#include +#include +#include +#include "dvb_frontend.h" +#include "dvb-pll.h" +#include "au8522.h" + +struct au8522_state { + + struct i2c_adapter* i2c; + + /* configuration settings */ + const struct au8522_config* config; + + struct dvb_frontend frontend; + + u32 current_frequency; + fe_modulation_t current_modulation; + +}; + +static int debug = 0; +#define dprintk if (debug) printk + +/* 16 bit registers, 8 bit values */ +static int au8522_writereg(struct au8522_state* state, u16 reg, u8 data) +{ + int ret; + u8 buf [] = { reg >> 8, reg & 0xff, data }; + + struct i2c_msg msg = { .addr = state->config->demod_address, + .flags = 0, .buf = buf, .len = 3 }; + + ret = i2c_transfer(state->i2c, &msg, 1); + + if (ret != 1) + printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, " + "ret == %i)\n", __FUNCTION__, reg, data, ret); + + return (ret != 1) ? -1 : 0; +} + +static u8 au8522_readreg(struct au8522_state* state, u16 reg) +{ + int ret; + u8 b0 [] = { reg >> 8, reg & 0xff }; + u8 b1 [] = { 0 }; + + struct i2c_msg msg [] = { + { .addr = state->config->demod_address, .flags = 0, + .buf = b0, .len = 2 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, + .buf = b1, .len = 1 } }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) + printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + return b1[0]; +} + +static int au8522_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct au8522_state* state = fe->demodulator_priv; + + dprintk("%s(%d)\n", __FUNCTION__, enable); + + if (enable) + return au8522_writereg(state, 0x106, 1); + else + return au8522_writereg(state, 0x106, 0); +} + +static int au8522_enable_modulation(struct dvb_frontend* fe, + fe_modulation_t m) +{ + struct au8522_state* state = fe->demodulator_priv; + + dprintk("%s(0x%08x)\n", __FUNCTION__, m); + + switch(m) { + case VSB_8: + dprintk("%s() VSB_8\n", __FUNCTION__); + + //au8522_writereg(state, 0x410b, 0x84); // Serial + + //au8522_writereg(state, 0x8090, 0x82); + au8522_writereg(state, 0x8090, 0x84); + au8522_writereg(state, 0x4092, 0x11); + au8522_writereg(state, 0x2005, 0x00); + au8522_writereg(state, 0x8091, 0x80); + + au8522_writereg(state, 0x80a3, 0x0c); + au8522_writereg(state, 0x80a4, 0xe8); + au8522_writereg(state, 0x8081, 0xc4); + au8522_writereg(state, 0x80a5, 0x40); + au8522_writereg(state, 0x80a7, 0x40); + au8522_writereg(state, 0x80a6, 0x67); + au8522_writereg(state, 0x8262, 0x20); + au8522_writereg(state, 0x821c, 0x30); + au8522_writereg(state, 0x80d8, 0x1a); + au8522_writereg(state, 0x8227, 0xa0); + au8522_writereg(state, 0x8121, 0xff); + au8522_writereg(state, 0x80a8, 0xf0); + au8522_writereg(state, 0x80a9, 0x05); + au8522_writereg(state, 0x80aa, 0x77); + au8522_writereg(state, 0x80ab, 0xf0); + au8522_writereg(state, 0x80ac, 0x05); + au8522_writereg(state, 0x80ad, 0x77); + au8522_writereg(state, 0x80ae, 0x41); + au8522_writereg(state, 0x80af, 0x66); + au8522_writereg(state, 0x821b, 0xcc); + au8522_writereg(state, 0x821d, 0x80); + au8522_writereg(state, 0x80b5, 0xfb); + au8522_writereg(state, 0x80b6, 0x8e); + au8522_writereg(state, 0x80b7, 0x39); + au8522_writereg(state, 0x80a4, 0xe8); + au8522_writereg(state, 0x8231, 0x13); + break; + case QAM_64: + case QAM_256: + au8522_writereg(state, 0x80a3, 0x09); + au8522_writereg(state, 0x80a4, 0x00); + au8522_writereg(state, 0x8081, 0xc4); + au8522_writereg(state, 0x80a5, 0x40); + au8522_writereg(state, 0x80b5, 0xfb); + au8522_writereg(state, 0x80b6, 0x8e); + au8522_writereg(state, 0x80b7, 0x39); + au8522_writereg(state, 0x80aa, 0x77); + au8522_writereg(state, 0x80ad, 0x77); + au8522_writereg(state, 0x80a6, 0x67); + au8522_writereg(state, 0x8262, 0x20); + au8522_writereg(state, 0x821c, 0x30); + au8522_writereg(state, 0x80b8, 0x3e); + au8522_writereg(state, 0x80b9, 0xf0); + au8522_writereg(state, 0x80ba, 0x01); + au8522_writereg(state, 0x80bb, 0x18); + au8522_writereg(state, 0x80bc, 0x50); + au8522_writereg(state, 0x80bd, 0x00); + au8522_writereg(state, 0x80be, 0xea); + au8522_writereg(state, 0x80bf, 0xef); + au8522_writereg(state, 0x80c0, 0xfc); + au8522_writereg(state, 0x80c1, 0xbd); + au8522_writereg(state, 0x80c2, 0x1f); + au8522_writereg(state, 0x80c3, 0xfc); + au8522_writereg(state, 0x80c4, 0xdd); + au8522_writereg(state, 0x80c5, 0xaf); + au8522_writereg(state, 0x80c6, 0x00); + au8522_writereg(state, 0x80c7, 0x38); + au8522_writereg(state, 0x80c8, 0x30); + au8522_writereg(state, 0x80c9, 0x05); + au8522_writereg(state, 0x80ca, 0x4a); + au8522_writereg(state, 0x80cb, 0xd0); + au8522_writereg(state, 0x80cc, 0x01); + au8522_writereg(state, 0x80cd, 0xd9); + au8522_writereg(state, 0x80ce, 0x6f); + au8522_writereg(state, 0x80cf, 0xf9); + au8522_writereg(state, 0x80d0, 0x70); + au8522_writereg(state, 0x80d1, 0xdf); + au8522_writereg(state, 0x80d2, 0xf7); + au8522_writereg(state, 0x80d3, 0xc2); + au8522_writereg(state, 0x80d4, 0xdf); + au8522_writereg(state, 0x80d5, 0x02); + au8522_writereg(state, 0x80d6, 0x9a); + au8522_writereg(state, 0x80d7, 0xd0); + au8522_writereg(state, 0x8250, 0x0d); + au8522_writereg(state, 0x8251, 0xcd); + au8522_writereg(state, 0x8252, 0xe0); + au8522_writereg(state, 0x8253, 0x05); + au8522_writereg(state, 0x8254, 0xa7); + au8522_writereg(state, 0x8255, 0xff); + au8522_writereg(state, 0x8256, 0xed); + au8522_writereg(state, 0x8257, 0x5b); + au8522_writereg(state, 0x8258, 0xae); + au8522_writereg(state, 0x8259, 0xe6); + au8522_writereg(state, 0x825a, 0x3d); + au8522_writereg(state, 0x825b, 0x0f); + au8522_writereg(state, 0x825c, 0x0d); + au8522_writereg(state, 0x825d, 0xea); + au8522_writereg(state, 0x825e, 0xf2); + au8522_writereg(state, 0x825f, 0x51); + au8522_writereg(state, 0x8260, 0xf5); + au8522_writereg(state, 0x8261, 0x06); + au8522_writereg(state, 0x821a, 0x00); + au8522_writereg(state, 0x8546, 0x40); + au8522_writereg(state, 0x8210, 0x26); + au8522_writereg(state, 0x8211, 0xf6); + au8522_writereg(state, 0x8212, 0x84); + au8522_writereg(state, 0x8213, 0x02); + au8522_writereg(state, 0x8502, 0x01); + au8522_writereg(state, 0x8121, 0x04); + au8522_writereg(state, 0x8122, 0x04); + au8522_writereg(state, 0x852e, 0x10); + au8522_writereg(state, 0x80a4, 0xca); + au8522_writereg(state, 0x80a7, 0x40); + au8522_writereg(state, 0x8526, 0x01); + break; + default: + dprintk("%s() Invalid modulation\n", __FUNCTION__); + return -EINVAL; + } + + state->current_modulation = m; + + return 0; +} + +/* Talk to the demod, set the FEC, GUARD, QAM settings etc */ +static int au8522_set_frontend (struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) +{ + struct au8522_state* state = fe->demodulator_priv; + + dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency); + + state->current_frequency = p->frequency; + + au8522_enable_modulation(fe, p->u.vsb.modulation); + + /* Allow the demod to settle */ + msleep(100); + + if (fe->ops.tuner_ops.set_params) { + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + + return 0; +} + +/* Reset the demod hardware and reset all of the configuration registers + to a default state. */ +static int au8522_init(struct dvb_frontend* fe) +{ + struct au8522_state* state = fe->demodulator_priv; + dprintk("%s()\n", __FUNCTION__); + + au8522_writereg(state, 0xa4, 1 << 5); + + au8522_i2c_gate_ctrl(fe, 1); + + return 0; +} + +static int au8522_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct au8522_state* state = fe->demodulator_priv; + u8 reg; + u32 tuner_status = 0; + + *status = 0; + + if (state->current_modulation == VSB_8) { + dprintk("%s() Checking VSB_8\n", __FUNCTION__); + //au8522_writereg(state, 0x80a4, 0x20); + reg = au8522_readreg(state, 0x4088); + if(reg & 0x01) + *status |= FE_HAS_VITERBI; + if(reg & 0x02) + *status |= FE_HAS_LOCK | FE_HAS_SYNC; + } else { + dprintk("%s() Checking QAM\n", __FUNCTION__); + reg = au8522_readreg(state, 0x4541); + if(reg & 0x80) + *status |= FE_HAS_VITERBI; + if(reg & 0x20) + *status |= FE_HAS_LOCK | FE_HAS_SYNC; + } + + switch(state->config->status_mode) { + case AU8522_DEMODLOCKING: + dprintk("%s() DEMODLOCKING\n", __FUNCTION__); + if (*status & FE_HAS_VITERBI) + *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; + break; + case AU8522_TUNERLOCKING: + /* Get the tuner status */ + dprintk("%s() TUNERLOCKING\n", __FUNCTION__); + if (fe->ops.tuner_ops.get_status) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + fe->ops.tuner_ops.get_status(fe, &tuner_status); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + if (tuner_status) + *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; + break; + } + + dprintk("%s() status 0x%08x\n", __FUNCTION__, *status); + + return 0; +} + +static int au8522_read_snr(struct dvb_frontend* fe, u16* snr) +{ + dprintk("%s()\n", __FUNCTION__); + + *snr = 0; + + return 0; +} + +static int au8522_read_signal_strength(struct dvb_frontend* fe, + u16* signal_strength) +{ + return au8522_read_snr(fe, signal_strength); +} + +static int au8522_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct au8522_state* state = fe->demodulator_priv; + + *ucblocks = au8522_readreg(state, 0x4087); + + return 0; +} + +static int au8522_read_ber(struct dvb_frontend* fe, u32* ber) +{ + return au8522_read_ucblocks(fe, ber); +} + +static int au8522_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) +{ + struct au8522_state* state = fe->demodulator_priv; + + p->frequency = state->current_frequency; + p->u.vsb.modulation = state->current_modulation; + + return 0; +} + +static int au8522_get_tune_settings(struct dvb_frontend* fe, + struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 1000; + return 0; +} + +static void au8522_release(struct dvb_frontend* fe) +{ + struct au8522_state* state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops au8522_ops; + +struct dvb_frontend* au8522_attach(const struct au8522_config* config, + struct i2c_adapter* i2c) +{ + struct au8522_state* state = NULL; + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &au8522_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + if (au8522_init(&state->frontend) != 0) { + printk(KERN_ERR "%s: Failed to initialize correctly\n", + __FUNCTION__); + goto error; + } + + /* Note: Leaving the I2C gate open here. */ + au8522_i2c_gate_ctrl(&state->frontend, 1); + + return &state->frontend; + +error: + kfree(state); + return NULL; +} + +static struct dvb_frontend_ops au8522_ops = { + + .info = { + .name = "Auvitek AU8522 QAM/8VSB Frontend", + .type = FE_ATSC, + .frequency_min = 54000000, + .frequency_max = 858000000, + .frequency_stepsize = 62500, + .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + + .init = au8522_init, + .i2c_gate_ctrl = au8522_i2c_gate_ctrl, + .set_frontend = au8522_set_frontend, + .get_frontend = au8522_get_frontend, + .get_tune_settings = au8522_get_tune_settings, + .read_status = au8522_read_status, + .read_ber = au8522_read_ber, + .read_signal_strength = au8522_read_signal_strength, + .read_snr = au8522_read_snr, + .read_ucblocks = au8522_read_ucblocks, + .release = au8522_release, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Enable verbose debug messages"); + +MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver"); +MODULE_AUTHOR("Steven Toth"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(au8522_attach); + +/* + * Local variables: + * c-basic-offset: 8 + */ diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h new file mode 100644 index 000000000000..a75627155fed --- /dev/null +++ b/drivers/media/dvb/frontends/au8522.h @@ -0,0 +1,55 @@ +/* + Auvitek AU8522 QAM/8VSB demodulator driver + + Copyright (C) 2008 Steven Toth + + 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 __AU8522_H__ +#define __AU8522_H__ + +#include + +struct au8522_config +{ + /* the demodulator's i2c address */ + u8 demod_address; + + /* Return lock status based on tuner lock, or demod lock */ +#define AU8522_TUNERLOCKING 0 +#define AU8522_DEMODLOCKING 1 + u8 status_mode; +}; + +#if defined(CONFIG_DVB_AU8522) || (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE)) +extern struct dvb_frontend* au8522_attach(const struct au8522_config* config, + struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* au8522_attach(const struct au8522_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif /* CONFIG_DVB_AU8522 */ + +#endif /* __AU8522_H__ */ + +/* + * Local variables: + * c-basic-offset: 8 + */ diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 54b9f84e9a3e..fe9a4cc14141 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -698,6 +698,8 @@ source "drivers/media/video/cx88/Kconfig" source "drivers/media/video/cx23885/Kconfig" +source "drivers/media/video/au0828/Kconfig" + source "drivers/media/video/ivtv/Kconfig" config VIDEO_M32R_AR diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index fe3be94afd10..be14227f3726 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -143,5 +143,7 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o +obj-$(CONFIG_VIDEO_AU0828) += au0828/ + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig new file mode 100644 index 000000000000..38d68ee8026a --- /dev/null +++ b/drivers/media/video/au0828/Kconfig @@ -0,0 +1,10 @@ + +config VIDEO_AU0828 + tristate "Auvitek AU0828 support" + depends on VIDEO_DEV && I2C && INPUT + select I2C_ALGOBIT + ---help--- + This is a video4linux driver for Auvitek's USB device. + + To compile this driver as a module, choose M here: the + module will be called ambarella diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile new file mode 100644 index 000000000000..9f4f572c89c5 --- /dev/null +++ b/drivers/media/video/au0828/Makefile @@ -0,0 +1,9 @@ +au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o + +obj-$(CONFIG_VIDEO_AU0828) += au0828.o + +EXTRA_CFLAGS += -Idrivers/media/video +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends + +EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c new file mode 100644 index 000000000000..c4cb11e9d6fc --- /dev/null +++ b/drivers/media/video/au0828/au0828-cards.c @@ -0,0 +1,144 @@ +/* + * Driver for the Auvitek USB bridge + * + * Copyright (c) 2008 Steven Toth + * + * 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 "au0828.h" +#include "au0828-cards.h" + +#define _dbg(level, fmt, arg...)\ + do {\ + if (debug >= level) \ + printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ + } while (0) + +struct au0828_board au0828_boards[] = { + [AU0828_BOARD_UNKNOWN] = { + .name = "Unknown board", + }, + [AU0828_BOARD_HAUPPAUGE_HVR850] = { + .name = "Hauppauge HVR850", + }, + [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { + .name = "Hauppauge HVR950Q", + }, + [AU0828_BOARD_DVICO_FUSIONHDTV7] = { + .name = "DViCO FusionHDTV USB", + }, +}; +const unsigned int au0828_bcount = ARRAY_SIZE(au0828_boards); + +/* Tuner callback function for au0828 boards. Currently only needed + * for HVR1500Q, which has an xc5000 tuner. + */ +int au0828_tuner_callback(void *priv, int command, int arg) +{ + struct au0828_dev *dev = priv; + + switch(dev->board) { + case AU0828_BOARD_HAUPPAUGE_HVR850: + case AU0828_BOARD_HAUPPAUGE_HVR950Q: + case AU0828_BOARD_DVICO_FUSIONHDTV7: + if(command == 0) { + /* Tuner Reset Command from xc5000 */ + /* Drive the tuner into reset and out */ + au0828_clear(dev, REG_001, 2); + mdelay(200); + au0828_set(dev, REG_001, 2); + mdelay(50); + return 0; + } + else { + printk(KERN_ERR + "%s(): Unknown command.\n", __FUNCTION__); + return -EINVAL; + } + break; + } + + return 0; /* Should never be here */ +} + +/* + * The bridge has between 8 and 12 gpios. + * Regs 1 and 0 deal with output enables. + * Regs 3 and 2 * deal with direction. + */ +void au0828_gpio_setup(struct au0828_dev *dev) +{ + switch(dev->board) { + case AU0828_BOARD_HAUPPAUGE_HVR850: + case AU0828_BOARD_HAUPPAUGE_HVR950Q: + /* GPIO's + * 4 - CS5340 + * 5 - AU8522 Demodulator + * 6 - eeprom W/P + * 9 - XC5000 Tuner + */ + + /* Into reset */ + au0828_write(dev, REG_003, 0x02); + au0828_write(dev, REG_002, 0x88 | 0x20); + au0828_write(dev, REG_001, 0x0); + au0828_write(dev, REG_000, 0x0); + msleep(100); + + /* Out of reset */ + au0828_write(dev, REG_003, 0x02); + au0828_write(dev, REG_001, 0x02); + au0828_write(dev, REG_002, 0x88 | 0x20); + au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40); + msleep(250); + break; + case AU0828_BOARD_DVICO_FUSIONHDTV7: + /* GPIO's + * 6 - ? + * 8 - AU8522 Demodulator + * 9 - XC5000 Tuner + */ + + /* Into reset */ + au0828_write(dev, REG_003, 0x02); + au0828_write(dev, REG_002, 0xa0); + au0828_write(dev, REG_001, 0x0); + au0828_write(dev, REG_000, 0x0); + msleep(100); + + /* Out of reset */ + au0828_write(dev, REG_003, 0x02); + au0828_write(dev, REG_002, 0xa0); + au0828_write(dev, REG_001, 0x02); + au0828_write(dev, REG_000, 0xa0); + msleep(250); + break; + } +} + +/* table of devices that work with this driver */ +struct usb_device_id au0828_usb_id_table [] = { + { USB_DEVICE(0x2040, 0x7200), + .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, + { USB_DEVICE(0x2040, 0x7240), + .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 }, + { USB_DEVICE(0x0fe9, 0xd620), + .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 }, + { }, +}; + +MODULE_DEVICE_TABLE(usb, au0828_usb_id_table); diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h new file mode 100644 index 000000000000..e26f54a961d0 --- /dev/null +++ b/drivers/media/video/au0828/au0828-cards.h @@ -0,0 +1,25 @@ +/* + * Driver for the Auvitek USB bridge + * + * Copyright (c) 2008 Steven Toth + * + * 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. + */ + +#define AU0828_BOARD_UNKNOWN 0 +#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1 +#define AU0828_BOARD_HAUPPAUGE_HVR850 2 +#define AU0828_BOARD_DVICO_FUSIONHDTV7 3 diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c new file mode 100644 index 000000000000..8d0b8a8b06bd --- /dev/null +++ b/drivers/media/video/au0828/au0828-core.c @@ -0,0 +1,252 @@ +/* + * Driver for the Auvitek USB bridge + * + * Copyright (c) 2008 Steven Toth + * + * 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 +#include +#include + +#include "au0828.h" + +static unsigned int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debug messages"); + +#define _err(fmt, arg...)\ + do {\ + printk(KERN_ERR DRIVER_NAME "/0: " fmt, ## arg);\ + } while (0) + +#define _info(fmt, arg...)\ + do {\ + printk(KERN_INFO DRIVER_NAME "/0: " fmt, ## arg);\ + } while (0) + +#define _dbg(level, fmt, arg...)\ + do {\ + if (debug >= level) \ + printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ + } while (0) + +#define _AU0828_BULKPIPE 0x03 +#define _BULKPIPESIZE 0xffff + +static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, + u16 index, unsigned char *cp, u16 size); +static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, + u16 index, unsigned char *cp, u16 size); + +/* USB Direction */ +#define CMD_REQUEST_IN 0x00 +#define CMD_REQUEST_OUT 0x01 + +u32 au0828_readreg(struct au0828_dev *dev, u16 reg) +{ + recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1); + _dbg(3,"%s(0x%x) = 0x%x\n", __FUNCTION__, reg, dev->ctrlmsg[0]); + return dev->ctrlmsg[0]; +} + +u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) +{ + _dbg(3,"%s(0x%x, 0x%x)\n", __FUNCTION__, reg, val); + return send_control_msg(dev, CMD_REQUEST_OUT, val, reg, dev->ctrlmsg, 0); +} + +static void cmd_msg_dump(struct au0828_dev *dev) +{ + int i; + + for (i = 0;i < sizeof(dev->ctrlmsg); i+=16) + _dbg(1,"%s() %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x\n", + __FUNCTION__, + dev->ctrlmsg[i+0], dev->ctrlmsg[i+1], + dev->ctrlmsg[i+2], dev->ctrlmsg[i+3], + dev->ctrlmsg[i+4], dev->ctrlmsg[i+5], + dev->ctrlmsg[i+6], dev->ctrlmsg[i+7], + dev->ctrlmsg[i+8], dev->ctrlmsg[i+9], + dev->ctrlmsg[i+10], dev->ctrlmsg[i+11], + dev->ctrlmsg[i+12], dev->ctrlmsg[i+13], + dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]); +} + +static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, + u16 index, unsigned char *cp, u16 size) +{ + int status = -ENODEV; + mutex_lock(&dev->mutex); + if (dev->usbdev) { + + /* cp must be memory that has been allocated by kmalloc */ + status = usb_control_msg(dev->usbdev, + usb_sndctrlpipe(dev->usbdev, 0), + request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, + cp, size, 1000); + + status = min(status, 0); + + if (status < 0) { + _err("%s() Failed sending control message, error %d.\n", + __FUNCTION__, + status); + } + + } + mutex_unlock(&dev->mutex); + return status; +} + +static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, + u16 index, unsigned char *cp, u16 size) +{ + int status = -ENODEV; + mutex_lock(&dev->mutex); + if (dev->usbdev) { + + memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg)); + + /* cp must be memory that has been allocated by kmalloc */ + status = usb_control_msg(dev->usbdev, + usb_rcvctrlpipe(dev->usbdev, 0), + request, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, + cp, size, 1000); + + status = min(status, 0); + + if (status < 0) { + _err("%s() Failed receiving ctrl msg, error %d.\n", + __FUNCTION__, + status); + } + else + if (debug > 4) + cmd_msg_dump(dev); + } + mutex_unlock(&dev->mutex); + return status; +} +static void au0828_usb_disconnect(struct usb_interface *interface) +{ + struct au0828_dev *dev = usb_get_intfdata(interface); + + _dbg(1,"%s()\n", __FUNCTION__); + + /* Digital TV */ + au0828_dvb_unregister(dev); + + /* I2C */ + au0828_i2c_unregister(dev); + + usb_set_intfdata(interface, NULL); + + mutex_lock(&dev->mutex); + dev->usbdev = NULL; + mutex_unlock(&dev->mutex); + + kfree(dev); + +} + +static int au0828_usb_probe (struct usb_interface *interface, + const struct usb_device_id *id) +{ + int ifnum; + struct au0828_dev *dev; + struct usb_device *usbdev = interface_to_usbdev(interface); + + ifnum = interface->altsetting->desc.bInterfaceNumber; + + if (ifnum != 0) + return -ENODEV; + + _dbg(1,"%s() vendor id 0x%x device id 0x%x ifnum:%d\n", + __FUNCTION__, + le16_to_cpu(usbdev->descriptor.idVendor), + le16_to_cpu(usbdev->descriptor.idProduct), + ifnum); + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + _err("Unable to allocate memory\n"); + return -ENOMEM; + } + + mutex_init(&dev->mutex); + mutex_init(&dev->dvb.lock); + dev->usbdev = usbdev; + dev->board = id->driver_info; + + usb_set_intfdata(interface, dev); + + /* Power Up the bridge */ + au0828_write(dev, REG_600, 1 << 4); + + /* Bring up the GPIO's and supporting devices */ + au0828_gpio_setup(dev); + + /* I2C */ + au0828_i2c_register(dev); + + /* Digital TV */ + au0828_dvb_register(dev); + + _info("Registered device AU0828 [%s]\n", + au0828_boards[dev->board].name); + + return 0; +} + +static struct usb_driver au0828_usb_driver = { + .name = DRIVER_NAME, + .probe = au0828_usb_probe, + .disconnect = au0828_usb_disconnect, + .id_table = au0828_usb_id_table, +}; + +static int __init au0828_init(void) +{ + int ret; + + _info("au0828 driver loaded\n"); + + ret = usb_register(&au0828_usb_driver); + if (ret) + _err("usb_register failed, error = %d\n", ret); + + return ret; +} + +static void __exit au0828_exit(void) +{ + usb_deregister(&au0828_usb_driver); +} + +module_init(au0828_init); +module_exit(au0828_exit); + +MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); +MODULE_AUTHOR("Steven Toth "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c new file mode 100644 index 000000000000..3c8a29eafc2d --- /dev/null +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -0,0 +1,371 @@ +/* + * Driver for the Auvitek USB bridge + * + * Copyright (c) 2008 Steven Toth + * + * 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 +#include +#include +#include + +#include "au0828.h" + +#include "au8522.h" +#include "xc5000.h" + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +unsigned int dvb_debug = 1; + +#define _dbg(level, fmt, arg...)\ + do { if (dvb_debug >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, DRIVER_NAME, ## arg);\ + } while (0) + +static struct au8522_config hauppauge_hvr950q_config = { + .demod_address = 0x8e >> 1, + .status_mode = AU8522_DEMODLOCKING, +}; + +static struct xc5000_config hauppauge_hvr950q_tunerconfig = { + .i2c_address = 0x61, + .if_khz = 6000, + .tuner_callback = au0828_tuner_callback +}; + +/*-------------------------------------------------------------------*/ +static void urb_completion(struct urb *purb) +{ + u8 *ptr; + struct au0828_dev *dev = purb->context; + int ptype = usb_pipetype(purb->pipe); + + if (dev->urb_streaming == 0) + return; + + if (ptype != PIPE_BULK) { + printk(KERN_ERR "%s() Unsupported URB type %d\n", __FUNCTION__, ptype); + return; + } + + ptr = (u8 *)purb->transfer_buffer; + + /* Feed the transport payload into the kernel demux */ + dvb_dmx_swfilter_packets(&dev->dvb.demux, purb->transfer_buffer, purb->actual_length / 188); + + /* Clean the buffer before we requeue */ + memset(purb->transfer_buffer, 0, URB_BUFSIZE); + + /* Requeue URB */ + usb_submit_urb(purb, GFP_ATOMIC); +} + +static int stop_urb_transfer(struct au0828_dev *dev) +{ + int i; + + printk(KERN_INFO "%s()\n", __FUNCTION__); + + /* FIXME: Do we need to free the transfer_buffers? */ + for (i = 0; i < URB_COUNT; i++) { + usb_kill_urb(dev->urbs[i]); + kfree(dev->urbs[i]->transfer_buffer); + usb_free_urb(dev->urbs[i]); + } + + dev->urb_streaming = 0; + + return 0; +} + +#define _AU0828_BULKPIPE 0x83 +#define _BULKPIPESIZE 0xe522 + +static int start_urb_transfer(struct au0828_dev *dev) +{ + struct urb *purb; + int i, ret = -ENOMEM; + unsigned int pipe = usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE); + int pipesize = usb_maxpacket(dev->usbdev, pipe, usb_pipeout(pipe)); + int packets = _BULKPIPESIZE / pipesize; + int transfer_buflen = packets * pipesize; + + printk(KERN_INFO "%s() transfer_buflen = %d\n", __FUNCTION__, transfer_buflen); + + if (dev->urb_streaming) { + printk("%s: iso xfer already running!\n", __FUNCTION__); + return 0; + } + + for (i = 0; i < URB_COUNT; i++) { + + dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->urbs[i]) { + goto err; + } + + purb = dev->urbs[i]; + + purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL); + if (!purb->transfer_buffer) { + usb_free_urb(purb); + dev->urbs[i] = 0; + goto err; + } + + purb->status = -EINPROGRESS; + usb_fill_bulk_urb(purb, + dev->usbdev, + usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE), + purb->transfer_buffer, + URB_BUFSIZE, + urb_completion, + dev); + + } + + for (i = 0; i < URB_COUNT; i++) { + ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC); + if (ret != 0) { + stop_urb_transfer(dev); + printk("%s: failed urb submission, err = %d\n", __FUNCTION__, ret); + return ret; + } + } + + dev->urb_streaming = 1; + ret = 0; + +err: + return ret; +} + +static int au0828_dvb_start_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + struct au0828_dev *dev = (struct au0828_dev *) demux->priv; + struct au0828_dvb *dvb = &dev->dvb; + int ret = 0; + + printk(KERN_INFO "%s() pid = 0x%x index = %d\n", __FUNCTION__, feed->pid, feed->index); + + if (!demux->dmx.frontend) + return -EINVAL; + + printk(KERN_INFO "%s() Preparing, feeding = %d\n", __FUNCTION__, dvb->feeding); + if (dvb) { + mutex_lock(&dvb->lock); + if (dvb->feeding++ == 0) { + printk(KERN_INFO "%s() Starting Transport DMA\n", + __FUNCTION__); + au0828_write(dev, 0x608, 0x90); + au0828_write(dev, 0x609, 0x72); + au0828_write(dev, 0x60a, 0x71); + au0828_write(dev, 0x60b, 0x01); + ret = start_urb_transfer(dev); + } + mutex_unlock(&dvb->lock); + } + + return ret; +} + +static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + struct au0828_dev *dev = (struct au0828_dev *) demux->priv; + struct au0828_dvb *dvb = &dev->dvb; + int ret = 0; + + printk(KERN_INFO "%s() pid = 0x%x index = %d\n", __FUNCTION__, feed->pid, feed->index); + + if (dvb) { + mutex_lock(&dvb->lock); + if (--dvb->feeding == 0) { + printk(KERN_INFO "%s() Stopping Transport DMA\n", + __FUNCTION__); + au0828_write(dev, 0x608, 0x00); + au0828_write(dev, 0x609, 0x00); + au0828_write(dev, 0x60a, 0x00); + au0828_write(dev, 0x60b, 0x00); + ret = stop_urb_transfer(dev); + } + mutex_unlock(&dvb->lock); + } + + return ret; +} + +int dvb_register(struct au0828_dev *dev) +{ + struct au0828_dvb *dvb = &dev->dvb; + int result; + + /* register adapter */ + result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE, + &dev->usbdev->dev, adapter_nr); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", + DRIVER_NAME, result); + goto fail_adapter; + } + dvb->adapter.priv = dev; + + /* register frontend */ + result = dvb_register_frontend(&dvb->adapter, dvb->frontend); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", + DRIVER_NAME, result); + goto fail_frontend; + } + + /* register demux stuff */ + dvb->demux.dmx.capabilities = + DMX_TS_FILTERING | DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + dvb->demux.priv = dev; + dvb->demux.filternum = 256; + dvb->demux.feednum = 256; + dvb->demux.start_feed = au0828_dvb_start_feed; + dvb->demux.stop_feed = au0828_dvb_stop_feed; + result = dvb_dmx_init(&dvb->demux); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", + DRIVER_NAME, result); + goto fail_dmx; + } + + dvb->dmxdev.filternum = 256; + dvb->dmxdev.demux = &dvb->demux.dmx; + dvb->dmxdev.capabilities = 0; + result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", + DRIVER_NAME, result); + goto fail_dmxdev; + } + + dvb->fe_hw.source = DMX_FRONTEND_0; + result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); + if (result < 0) { + printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", + DRIVER_NAME, result); + goto fail_fe_hw; + } + + dvb->fe_mem.source = DMX_MEMORY_FE; + result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); + if (result < 0) { + printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", + DRIVER_NAME, result); + goto fail_fe_mem; + } + + result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); + if (result < 0) { + printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", + DRIVER_NAME, result); + goto fail_fe_conn; + } + + /* register network adapter */ + dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + return 0; + +fail_fe_conn: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); +fail_fe_mem: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); +fail_fe_hw: + dvb_dmxdev_release(&dvb->dmxdev); +fail_dmxdev: + dvb_dmx_release(&dvb->demux); +fail_dmx: + dvb_unregister_frontend(dvb->frontend); +fail_frontend: + dvb_frontend_detach(dvb->frontend); + dvb_unregister_adapter(&dvb->adapter); +fail_adapter: + return result; +} + +void au0828_dvb_unregister(struct au0828_dev *dev) +{ + struct au0828_dvb *dvb = &dev->dvb; + + dvb_net_release(&dvb->net); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); + dvb_dmxdev_release(&dvb->dmxdev); + dvb_dmx_release(&dvb->demux); + dvb_unregister_frontend(dvb->frontend); + dvb_frontend_detach(dvb->frontend); + dvb_unregister_adapter(&dvb->adapter); +} + +/* All the DVB attach calls go here, this function get's modified + * for each new card. No other function in this file needs + * to change. + */ +int au0828_dvb_register(struct au0828_dev *dev) +{ + struct au0828_dvb *dvb = &dev->dvb; + int ret; + + /* init frontend */ + switch (dev->board) { + case AU0828_BOARD_HAUPPAUGE_HVR850: + case AU0828_BOARD_HAUPPAUGE_HVR950Q: + case AU0828_BOARD_DVICO_FUSIONHDTV7: + dvb->frontend = dvb_attach(au8522_attach, + &hauppauge_hvr950q_config, + &dev->i2c_adap); + if (dvb->frontend != NULL) { + hauppauge_hvr950q_tunerconfig.priv = dev; + dvb_attach(xc5000_attach, dvb->frontend, + &dev->i2c_adap, + &hauppauge_hvr950q_tunerconfig); + } + break; + default: + printk("The frontend of your DVB/ATSC card isn't supported yet\n"); + break; + } + if (NULL == dvb->frontend) { + printk("Frontend initialization failed\n"); + return -1; + } + + /* Put the analog decoder in standby to keep it quiet */ + au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL); + + if (dvb->frontend->ops.analog_ops.standby) + dvb->frontend->ops.analog_ops.standby(dvb->frontend); + + /* register everything */ + ret = dvb_register(dev); + if (ret < 0) { + if (dvb->frontend->ops.release) + dvb->frontend->ops.release(dvb->frontend); + return ret; + } + + return 0; +} diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c new file mode 100644 index 000000000000..3e7482481152 --- /dev/null +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -0,0 +1,402 @@ +/* + * Driver for the Auvitek AU0828 USB bridge + * + * Copyright (c) 2008 Steven Toth + * + * 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 +#include +#include +#include + +#include "au0828.h" + +#include + +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; +module_param(i2c_scan, int, 0444); +MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); + +#define dprintk(level, fmt, arg...)\ + do { if (i2c_debug >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, DRIVER_NAME, ## arg);\ + } while (0) + +#define I2C_WAIT_DELAY 512 +#define I2C_WAIT_RETRY 64 + +static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap) +{ + struct au0828_dev *dev = i2c_adap->algo_data; + return au0828_read(dev, REG_201) & 0x08 ? 0 : 1; +} + +static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap) +{ + struct au0828_dev *dev = i2c_adap->algo_data; + return au0828_read(dev, REG_201) & 0x02 ? 0 : 1; +} + +static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap) +{ + int count; + + for (count = 0; count < I2C_WAIT_RETRY; count++) { + if (!i2c_slave_did_read_ack(i2c_adap)) + break; + udelay(I2C_WAIT_DELAY); + } + + if (I2C_WAIT_RETRY == count) + return 0; + + return 1; +} + +static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap) +{ + struct au0828_dev *dev = i2c_adap->algo_data; + return au0828_read(dev, REG_201) & 0x01 ? 0 : 1; +} + +static int i2c_wait_read_done(struct i2c_adapter *i2c_adap) +{ + int count; + + for (count = 0; count < I2C_WAIT_RETRY; count++) { + if (!i2c_is_read_busy(i2c_adap)) + break; + udelay(I2C_WAIT_DELAY); + } + + if (I2C_WAIT_RETRY == count) + return 0; + + return 1; +} + +static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap) +{ + struct au0828_dev *dev = i2c_adap->algo_data; + return au0828_read(dev, REG_201) & 0x04 ? 1 : 0; +} + +static int i2c_wait_write_done(struct i2c_adapter *i2c_adap) +{ + int count; + + for (count = 0; count < I2C_WAIT_RETRY; count++) { + if (i2c_is_write_done(i2c_adap)) + break; + udelay(I2C_WAIT_DELAY); + } + + if (I2C_WAIT_RETRY == count) + return 0; + + return 1; +} + +static inline int i2c_is_busy(struct i2c_adapter *i2c_adap) +{ + struct au0828_dev *dev = i2c_adap->algo_data; + return au0828_read(dev, REG_201) & 0x10 ? 1 : 0; +} + +static int i2c_wait_done(struct i2c_adapter *i2c_adap) +{ + int count; + + for (count = 0; count < I2C_WAIT_RETRY; count++) { + if (!i2c_is_busy(i2c_adap)) + break; + udelay(I2C_WAIT_DELAY); + } + + if (I2C_WAIT_RETRY == count) + return 0; + + return 1; +} + +/* FIXME: Implement join handling correctly */ +static int i2c_sendbytes(struct i2c_adapter *i2c_adap, + const struct i2c_msg *msg, int joined_rlen) +{ + int i, strobe = 0; + struct au0828_dev *dev = i2c_adap->algo_data; + + dprintk(1, "%s()\n", __FUNCTION__); + + au0828_write(dev, REG_2FF, 0x01); + au0828_write(dev, REG_202, 0x07); + + /* Hardware needs 8 bit addresses */ + au0828_write(dev, REG_203, msg->addr << 1); + + if (i2c_debug) + dprintk(1, "SEND: %02x\n", msg->addr); + + for (i=0; i < msg->len;) { + + if (i2c_debug) + dprintk(1, " %02x\n", msg->buf[i]); + + au0828_write(dev, REG_205, msg->buf[i]); + + strobe++; + i++; + + if ((strobe >= 4) || (i >= msg->len)) { + + /* Strobe the byte into the bus */ + if (i < msg->len) + au0828_write(dev, REG_200, 0x41); + else + au0828_write(dev, REG_200, 0x01); + + /* Reset strobe trigger */ + strobe = 0; + + if (!i2c_wait_write_done(i2c_adap)) + return -EIO; + + } + + } + if (!i2c_wait_done(i2c_adap)) + return -EIO; + + if (i2c_debug) + dprintk(1, "\n"); + + return msg->len; +} + +/* FIXME: Implement join handling correctly */ +static int i2c_readbytes(struct i2c_adapter *i2c_adap, + const struct i2c_msg *msg, int joined) +{ + struct au0828_dev *dev = i2c_adap->algo_data; + int i; + + dprintk(1, "%s()\n", __FUNCTION__); + + au0828_write(dev, REG_2FF, 0x01); + au0828_write(dev, REG_202, 0x07); + + /* Hardware needs 8 bit addresses */ + au0828_write(dev, REG_203, msg->addr << 1); + + if (i2c_debug) + dprintk(1, " RECV:\n"); + + /* Deal with i2c_scan */ + if (msg->len == 0) { + au0828_write(dev, REG_200, 0x20); + if (i2c_wait_read_ack(i2c_adap)) + return -EIO; + return 0; + } + + for (i=0; i < msg->len;) { + + i++; + + if (i < msg->len) + au0828_write(dev, REG_200, 0x60); + else + au0828_write(dev, REG_200, 0x20); + + if (!i2c_wait_read_done(i2c_adap)) + return -EIO; + + msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff; + + if (i2c_debug) + dprintk(1, " %02x\n", msg->buf[i-1]); + } + if (!i2c_wait_done(i2c_adap)) + return -EIO; + + if (i2c_debug) + dprintk(1, "\n"); + + return msg->len; +} + +static int i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + int i, retval = 0; + + dprintk(1, "%s(num = %d)\n", __FUNCTION__, num); + + for (i = 0 ; i < num; i++) { + dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", + __FUNCTION__, num, msgs[i].addr, msgs[i].len); + if (msgs[i].flags & I2C_M_RD) { + /* read */ + retval = i2c_readbytes(i2c_adap, &msgs[i], 0); + } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && + msgs[i].addr == msgs[i + 1].addr) { + /* write then read from same address */ + retval = i2c_sendbytes(i2c_adap, &msgs[i], + msgs[i + 1].len); + if (retval < 0) + goto err; + i++; + retval = i2c_readbytes(i2c_adap, &msgs[i], 1); + } else { + /* write */ + retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); + } + if (retval < 0) + goto err; + } + return num; + +err: + return retval; +} + +static int attach_inform(struct i2c_client *client) +{ + dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", + client->driver->driver.name, client->addr, client->name); + + if (!client->driver->command) + return 0; + + return 0; +} + +static int detach_inform(struct i2c_client *client) +{ + dprintk(1, "i2c detach [client=%s]\n", client->name); + + return 0; +} + +void au0828_call_i2c_clients(struct au0828_dev *dev, + unsigned int cmd, void *arg) +{ + if (dev->i2c_rc != 0) + return; + + i2c_clients_command(&dev->i2c_adap, cmd, arg); +} + +static u32 au0828_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; +} + +static struct i2c_algorithm au0828_i2c_algo_template = { + .master_xfer = i2c_xfer, + .functionality = au0828_functionality, +}; + +/* ----------------------------------------------------------------------- */ + +static struct i2c_adapter au0828_i2c_adap_template = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .id = I2C_HW_B_AU0828, + .algo = &au0828_i2c_algo_template, + .class = I2C_CLASS_TV_ANALOG, + .client_register = attach_inform, + .client_unregister = detach_inform, +}; + +static struct i2c_client au0828_i2c_client_template = { + .name = "au0828 internal", +}; + +static char *i2c_devs[128] = { + [ 0x8e >> 1 ] = "au8522", + [ 0xa0 >> 1 ] = "eeprom", + [ 0xc2 >> 1 ] = "tuner/xc5000", +}; + +static void do_i2c_scan(char *name, struct i2c_client *c) +{ + unsigned char buf; + int i, rc; + + for (i = 0; i < 128; i++) { + c->addr = i; + rc = i2c_master_recv(c, &buf, 0); + if (rc < 0) + continue; + printk("%s: i2c scan: found device @ 0x%x [%s]\n", + name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); + } +} + +/* init + register i2c algo-bit adapter */ +int au0828_i2c_register(struct au0828_dev *dev) +{ + dprintk(1, "%s()\n", __FUNCTION__); + + memcpy(&dev->i2c_adap, &au0828_i2c_adap_template, + sizeof(dev->i2c_adap)); + memcpy(&dev->i2c_algo, &au0828_i2c_algo_template, + sizeof(dev->i2c_algo)); + memcpy(&dev->i2c_client, &au0828_i2c_client_template, + sizeof(dev->i2c_client)); + + dev->i2c_adap.dev.parent = &dev->usbdev->dev; + + strlcpy(dev->i2c_adap.name, DRIVER_NAME, + sizeof(dev->i2c_adap.name)); + + dev->i2c_algo.data = dev; + dev->i2c_adap.algo_data = dev; + i2c_set_adapdata(&dev->i2c_adap, dev); + i2c_add_adapter(&dev->i2c_adap); + + dev->i2c_client.adapter = &dev->i2c_adap; + + if (0 == dev->i2c_rc) { + printk("%s: i2c bus registered\n", DRIVER_NAME); + if (i2c_scan) + do_i2c_scan(DRIVER_NAME, &dev->i2c_client); + } else + printk("%s: i2c bus register FAILED\n", DRIVER_NAME); + return dev->i2c_rc; +} + +int au0828_i2c_unregister(struct au0828_dev *dev) +{ + i2c_del_adapter(&dev->i2c_adap); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h new file mode 100644 index 000000000000..c501f6a52af3 --- /dev/null +++ b/drivers/media/video/au0828/au0828-reg.h @@ -0,0 +1,35 @@ +/* + * Driver for the Auvitek USB bridge + * + * Copyright (c) 2008 Steven Toth + * + * 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. + */ + +#define REG_000 0x000 +#define REG_001 0x001 +#define REG_002 0x002 +#define REG_003 0x003 + +#define REG_200 0x200 +#define REG_201 0x201 +#define REG_202 0x202 +#define REG_203 0x203 +#define REG_205 0x205 +#define REG_209 0x209 +#define REG_2FF 0x2ff + +#define REG_600 0x600 diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h new file mode 100644 index 000000000000..517227667040 --- /dev/null +++ b/drivers/media/video/au0828/au0828.h @@ -0,0 +1,117 @@ +/* + * Driver for the Auvitek AU0828 USB bridge + * + * Copyright (c) 2008 Steven Toth + * + * 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 +#include + +/* DVB */ +#include "demux.h" +#include "dmxdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" +#include "dvbdev.h" + +#include "au0828-reg.h" +#include "au0828-cards.h" + +#define DRIVER_NAME "au0828" +#define URB_COUNT 16 +//#define URB_BUFSIZE (312 * 188) +#define URB_BUFSIZE (0xe522) + +struct au0828_board { + char *name; +}; + +struct au0828_dvb { + struct mutex lock; + struct dvb_adapter adapter; + struct dvb_frontend *frontend; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dmx_frontend fe_hw; + struct dmx_frontend fe_mem; + struct dvb_net net; + int feeding; +}; + +struct au0828_dev { + struct mutex mutex; + struct usb_device *usbdev; + int board; + u8 ctrlmsg[64]; + + /* I2C */ + struct i2c_adapter i2c_adap; + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + u32 i2c_rc; + + /* Digital */ + struct au0828_dvb dvb; + + /* USB / URB Related */ + int urb_streaming; + struct urb *urbs[URB_COUNT]; + +}; + +struct au0828_buff { + struct au0828_dev *dev; + struct urb *purb; + struct list_head buff_list; +}; + +/* ----------------------------------------------------------- */ +#define au0828_read(dev,reg) au0828_readreg(dev,reg) +#define au0828_write(dev,reg,value) au0828_writereg(dev,reg,value) +#define au0828_andor(dev,reg,mask,value) \ + au0828_writereg(dev,reg,(au0828_readreg(dev,reg)&~(mask))|((value)&(mask))) + +#define au0828_set(dev,reg,bit) au0828_andor(dev,(reg),(bit),(bit)) +#define au0828_clear(dev,reg,bit) au0828_andor(dev,(reg),(bit),0) + +/* ----------------------------------------------------------- */ +/* au0828-core.c */ +extern u32 au0828_read(struct au0828_dev *dev, u16 reg); +extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val); + +/* ----------------------------------------------------------- */ +/* au0828-cards.c */ +extern struct au0828_board au0828_boards[]; +extern struct usb_device_id au0828_usb_id_table[]; +extern const unsigned int au0828_bcount; +extern void au0828_gpio_setup(struct au0828_dev *dev); +extern int au0828_tuner_callback(void *priv, int command, int arg); + +/* ----------------------------------------------------------- */ +/* au0828-i2c.c */ +extern int au0828_i2c_register(struct au0828_dev *dev); +extern int au0828_i2c_unregister(struct au0828_dev *dev); +extern void au0828_call_i2c_clients(struct au0828_dev *dev, + unsigned int cmd, void *arg); + +/* ----------------------------------------------------------- */ +/* au0828-dvb.c */ +extern int au0828_dvb_register(struct au0828_dev *dev); +extern void au0828_dvb_unregister(struct au0828_dev *dev); From 28930fa9af9be77abe3d8bce3193908bf266efc6 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 29 Mar 2008 19:53:07 -0300 Subject: [PATCH 351/452] V4L/DVB (7622): HVR950Q Hauppauge eeprom support HVR950Q Hauppauge eeprom support. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 39 +++++++++++++++++++++++ drivers/media/video/au0828/au0828-core.c | 3 ++ drivers/media/video/au0828/au0828.h | 2 ++ 3 files changed, 44 insertions(+) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index c4cb11e9d6fc..cbcc6f81f460 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -75,6 +75,45 @@ int au0828_tuner_callback(void *priv, int command, int arg) return 0; /* Should never be here */ } +static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) +{ + struct tveeprom tv; + + tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); + + /* Make sure we support the board model */ + switch (tv.model) + { + case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ + break; + default: + printk("%s: warning: unknown hauppauge model #%d\n", __FUNCTION__, tv.model); + break; + } + + printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", __FUNCTION__, tv.model); +} + + +void au0828_card_setup(struct au0828_dev *dev) +{ + + static u8 eeprom[256]; + + if (dev->i2c_rc == 0) { + dev->i2c_client.addr = 0xa0 >> 1; + tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); + } + + switch(dev->board) { + case AU0828_BOARD_HAUPPAUGE_HVR850: + case AU0828_BOARD_HAUPPAUGE_HVR950Q: + if (dev->i2c_rc == 0) + hauppauge_eeprom(dev, eeprom+0xa0); + break; + } +} + /* * The bridge has between 8 and 12 gpios. * Regs 1 and 0 deal with output enables. diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 8d0b8a8b06bd..f5df99ea3b9f 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -210,6 +210,9 @@ static int au0828_usb_probe (struct usb_interface *interface, /* I2C */ au0828_i2c_register(dev); + /* Setup */ + au0828_card_setup(dev); + /* Digital TV */ au0828_dvb_register(dev); diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 517227667040..3dc09f8ffef7 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -22,6 +22,7 @@ #include #include #include +#include /* DVB */ #include "demux.h" @@ -103,6 +104,7 @@ extern struct usb_device_id au0828_usb_id_table[]; extern const unsigned int au0828_bcount; extern void au0828_gpio_setup(struct au0828_dev *dev); extern int au0828_tuner_callback(void *priv, int command, int arg); +extern void au0828_card_setup(struct au0828_dev *dev); /* ----------------------------------------------------------- */ /* au0828-i2c.c */ From c32d4d7510ae4da4e83bbd6e6471b04e9c9108ea Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 1 Apr 2008 01:27:41 -0300 Subject: [PATCH 352/452] V4L/DVB (7623): Scripts to maintain the CARDLIST file Scripts to maintain the CARDLIST file. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.au0828 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Documentation/video4linux/CARDLIST.au0828 diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828 new file mode 100644 index 000000000000..aaae360312e4 --- /dev/null +++ b/Documentation/video4linux/CARDLIST.au0828 @@ -0,0 +1,4 @@ + 0 -> Unknown board (au0828) + 1 -> Hauppauge HVR950Q (au0828) [2040:7200] + 2 -> Hauppauge HVR850 (au0828) [2040:7240] + 3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620] From 9c26de555dd3c2cb9833b4d324150aa6b5547b91 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Wed, 2 Apr 2008 01:10:40 -0300 Subject: [PATCH 353/452] V4L/DVB (7624): Avoid an oops if the board is not fully defined Avoid an oops if the board is not fully defined. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-core.c | 1 + drivers/media/video/au0828/au0828-dvb.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index f5df99ea3b9f..a3410fc8f5f9 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -217,6 +217,7 @@ static int au0828_usb_probe (struct usb_interface *interface, au0828_dvb_register(dev); _info("Registered device AU0828 [%s]\n", + au0828_boards[dev->board].name == NULL ? "Unset" : au0828_boards[dev->board].name); return 0; diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 3c8a29eafc2d..ecc08a8e31ca 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -57,6 +57,9 @@ static void urb_completion(struct urb *purb) struct au0828_dev *dev = purb->context; int ptype = usb_pipetype(purb->pipe); + if (!dev) + return; + if (dev->urb_streaming == 0) return; @@ -310,6 +313,9 @@ void au0828_dvb_unregister(struct au0828_dev *dev) { struct au0828_dvb *dvb = &dev->dvb; + if(dvb->frontend == NULL) + return; + dvb_net_release(&dvb->net); dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); From bc3c613cef903e73e7365986a1943b0124350018 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 18 Apr 2008 21:39:11 -0300 Subject: [PATCH 354/452] V4L/DVB (7625): au0828: Cleanup Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 13 ++--- drivers/media/video/au0828/au0828-core.c | 71 ++++++++++++++--------- drivers/media/video/au0828/au0828-dvb.c | 53 ++++++++--------- drivers/media/video/au0828/au0828-i2c.c | 45 +++++--------- drivers/media/video/au0828/au0828.h | 9 +++ 5 files changed, 95 insertions(+), 96 deletions(-) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index cbcc6f81f460..eafdc552a9fa 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -22,12 +22,6 @@ #include "au0828.h" #include "au0828-cards.h" -#define _dbg(level, fmt, arg...)\ - do {\ - if (debug >= level) \ - printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ - } while (0) - struct au0828_board au0828_boards[] = { [AU0828_BOARD_UNKNOWN] = { .name = "Unknown board", @@ -51,6 +45,8 @@ int au0828_tuner_callback(void *priv, int command, int arg) { struct au0828_dev *dev = priv; + dprintk(1, "%s()\n", __FUNCTION__); + switch(dev->board) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: @@ -97,9 +93,10 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) void au0828_card_setup(struct au0828_dev *dev) { - static u8 eeprom[256]; + dprintk(1, "%s()\n", __FUNCTION__); + if (dev->i2c_rc == 0) { dev->i2c_client.addr = 0xa0 >> 1; tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); @@ -121,6 +118,8 @@ void au0828_card_setup(struct au0828_dev *dev) */ void au0828_gpio_setup(struct au0828_dev *dev) { + dprintk(1, "%s()\n", __FUNCTION__); + switch(dev->board) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index a3410fc8f5f9..76801d135f2a 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -26,25 +26,23 @@ #include "au0828.h" -static unsigned int debug; +/* + * 1 = General debug messages + * 2 = USB handling + * 4 = I2C related + * 8 = Bridge related + */ +unsigned int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); -#define _err(fmt, arg...)\ - do {\ - printk(KERN_ERR DRIVER_NAME "/0: " fmt, ## arg);\ - } while (0) +unsigned int usb_debug = 0; +module_param(usb_debug, int, 0644); +MODULE_PARM_DESC(usb_debug, "enable usb debug messages"); -#define _info(fmt, arg...)\ - do {\ - printk(KERN_INFO DRIVER_NAME "/0: " fmt, ## arg);\ - } while (0) - -#define _dbg(level, fmt, arg...)\ - do {\ - if (debug >= level) \ - printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ - } while (0) +unsigned int bridge_debug = 0; +module_param(bridge_debug, int, 0644); +MODULE_PARM_DESC(bridge_debug, "enable bridge debug messages"); #define _AU0828_BULKPIPE 0x03 #define _BULKPIPESIZE 0xffff @@ -61,13 +59,13 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, u32 au0828_readreg(struct au0828_dev *dev, u16 reg) { recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1); - _dbg(3,"%s(0x%x) = 0x%x\n", __FUNCTION__, reg, dev->ctrlmsg[0]); + dprintk(8, "%s(0x%x) = 0x%x\n", __FUNCTION__, reg, dev->ctrlmsg[0]); return dev->ctrlmsg[0]; } u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) { - _dbg(3,"%s(0x%x, 0x%x)\n", __FUNCTION__, reg, val); + dprintk(8, "%s(0x%x, 0x%x)\n", __FUNCTION__, reg, val); return send_control_msg(dev, CMD_REQUEST_OUT, val, reg, dev->ctrlmsg, 0); } @@ -76,7 +74,7 @@ static void cmd_msg_dump(struct au0828_dev *dev) int i; for (i = 0;i < sizeof(dev->ctrlmsg); i+=16) - _dbg(1,"%s() %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " + dprintk(2,"%s() %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x\n", __FUNCTION__, dev->ctrlmsg[i+0], dev->ctrlmsg[i+1], @@ -107,7 +105,7 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, status = min(status, 0); if (status < 0) { - _err("%s() Failed sending control message, error %d.\n", + printk(KERN_ERR "%s() Failed sending control message, error %d.\n", __FUNCTION__, status); } @@ -137,13 +135,12 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, status = min(status, 0); if (status < 0) { - _err("%s() Failed receiving ctrl msg, error %d.\n", + printk(KERN_ERR "%s() Failed receiving control message, error %d.\n", __FUNCTION__, status); } else - if (debug > 4) - cmd_msg_dump(dev); + cmd_msg_dump(dev); } mutex_unlock(&dev->mutex); return status; @@ -152,7 +149,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) { struct au0828_dev *dev = usb_get_intfdata(interface); - _dbg(1,"%s()\n", __FUNCTION__); + dprintk(1,"%s()\n", __FUNCTION__); /* Digital TV */ au0828_dvb_unregister(dev); @@ -182,7 +179,7 @@ static int au0828_usb_probe (struct usb_interface *interface, if (ifnum != 0) return -ENODEV; - _dbg(1,"%s() vendor id 0x%x device id 0x%x ifnum:%d\n", + dprintk(1,"%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __FUNCTION__, le16_to_cpu(usbdev->descriptor.idVendor), le16_to_cpu(usbdev->descriptor.idProduct), @@ -190,7 +187,7 @@ static int au0828_usb_probe (struct usb_interface *interface, dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - _err("Unable to allocate memory\n"); + printk(KERN_ERR "%s() Unable to allocate memory\n", __FUNCTION__); return -ENOMEM; } @@ -216,7 +213,7 @@ static int au0828_usb_probe (struct usb_interface *interface, /* Digital TV */ au0828_dvb_register(dev); - _info("Registered device AU0828 [%s]\n", + printk(KERN_INFO "Registered device AU0828 [%s]\n", au0828_boards[dev->board].name == NULL ? "Unset" : au0828_boards[dev->board].name); @@ -234,11 +231,29 @@ static int __init au0828_init(void) { int ret; - _info("au0828 driver loaded\n"); + if(debug) + printk(KERN_INFO "%s() Debugging is enabled\n", __FUNCTION__); + + if(usb_debug) { + printk(KERN_INFO "%s() USB Debugging is enabled\n", __FUNCTION__); + debug |= 2; + } + + if(i2c_debug) { + printk(KERN_INFO "%s() I2C Debugging is enabled\n", __FUNCTION__); + debug |= 4; + } + + if(bridge_debug) { + printk(KERN_INFO "%s() Bridge Debugging is enabled\n", __FUNCTION__); + debug |= 8; + } + + printk(KERN_INFO "au0828 driver loaded\n"); ret = usb_register(&au0828_usb_driver); if (ret) - _err("usb_register failed, error = %d\n", ret); + printk(KERN_ERR "usb_register failed, error = %d\n", ret); return ret; } diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index ecc08a8e31ca..453fb3efa3e0 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -26,19 +26,11 @@ #include #include "au0828.h" - #include "au8522.h" #include "xc5000.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -unsigned int dvb_debug = 1; - -#define _dbg(level, fmt, arg...)\ - do { if (dvb_debug >= level)\ - printk(KERN_DEBUG "%s/0: " fmt, DRIVER_NAME, ## arg);\ - } while (0) - static struct au8522_config hauppauge_hvr950q_config = { .demod_address = 0x8e >> 1, .status_mode = AU8522_DEMODLOCKING, @@ -57,6 +49,8 @@ static void urb_completion(struct urb *purb) struct au0828_dev *dev = purb->context; int ptype = usb_pipetype(purb->pipe); + dprintk(2, "%s()\n", __FUNCTION__); + if (!dev) return; @@ -84,7 +78,7 @@ static int stop_urb_transfer(struct au0828_dev *dev) { int i; - printk(KERN_INFO "%s()\n", __FUNCTION__); + dprintk(2, "%s()\n", __FUNCTION__); /* FIXME: Do we need to free the transfer_buffers? */ for (i = 0; i < URB_COUNT; i++) { @@ -105,15 +99,11 @@ static int start_urb_transfer(struct au0828_dev *dev) { struct urb *purb; int i, ret = -ENOMEM; - unsigned int pipe = usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE); - int pipesize = usb_maxpacket(dev->usbdev, pipe, usb_pipeout(pipe)); - int packets = _BULKPIPESIZE / pipesize; - int transfer_buflen = packets * pipesize; - printk(KERN_INFO "%s() transfer_buflen = %d\n", __FUNCTION__, transfer_buflen); + dprintk(2, "%s()\n", __FUNCTION__); if (dev->urb_streaming) { - printk("%s: iso xfer already running!\n", __FUNCTION__); + dprintk(2, "%s: iso xfer already running!\n", __FUNCTION__); return 0; } @@ -167,17 +157,15 @@ static int au0828_dvb_start_feed(struct dvb_demux_feed *feed) struct au0828_dvb *dvb = &dev->dvb; int ret = 0; - printk(KERN_INFO "%s() pid = 0x%x index = %d\n", __FUNCTION__, feed->pid, feed->index); + dprintk(1, "%s()\n", __FUNCTION__); if (!demux->dmx.frontend) return -EINVAL; - printk(KERN_INFO "%s() Preparing, feeding = %d\n", __FUNCTION__, dvb->feeding); if (dvb) { mutex_lock(&dvb->lock); if (dvb->feeding++ == 0) { - printk(KERN_INFO "%s() Starting Transport DMA\n", - __FUNCTION__); + /* Start transport */ au0828_write(dev, 0x608, 0x90); au0828_write(dev, 0x609, 0x72); au0828_write(dev, 0x60a, 0x71); @@ -197,13 +185,12 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) struct au0828_dvb *dvb = &dev->dvb; int ret = 0; - printk(KERN_INFO "%s() pid = 0x%x index = %d\n", __FUNCTION__, feed->pid, feed->index); + dprintk(1, "%s()\n", __FUNCTION__); if (dvb) { mutex_lock(&dvb->lock); if (--dvb->feeding == 0) { - printk(KERN_INFO "%s() Stopping Transport DMA\n", - __FUNCTION__); + /* Stop transport */ au0828_write(dev, 0x608, 0x00); au0828_write(dev, 0x609, 0x00); au0828_write(dev, 0x60a, 0x00); @@ -221,11 +208,13 @@ int dvb_register(struct au0828_dev *dev) struct au0828_dvb *dvb = &dev->dvb; int result; + dprintk(1, "%s()\n", __FUNCTION__); + /* register adapter */ result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE, &dev->usbdev->dev, adapter_nr); if (result < 0) { - printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", + printk(KERN_ERROR "%s: dvb_register_adapter failed (errno = %d)\n", DRIVER_NAME, result); goto fail_adapter; } @@ -234,7 +223,7 @@ int dvb_register(struct au0828_dev *dev) /* register frontend */ result = dvb_register_frontend(&dvb->adapter, dvb->frontend); if (result < 0) { - printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", + printk(KERN_ERR "%s: dvb_register_frontend failed (errno = %d)\n", DRIVER_NAME, result); goto fail_frontend; } @@ -250,7 +239,7 @@ int dvb_register(struct au0828_dev *dev) dvb->demux.stop_feed = au0828_dvb_stop_feed; result = dvb_dmx_init(&dvb->demux); if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", + printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n", DRIVER_NAME, result); goto fail_dmx; } @@ -260,7 +249,7 @@ int dvb_register(struct au0828_dev *dev) dvb->dmxdev.capabilities = 0; result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", + printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n", DRIVER_NAME, result); goto fail_dmxdev; } @@ -268,7 +257,7 @@ int dvb_register(struct au0828_dev *dev) dvb->fe_hw.source = DMX_FRONTEND_0; result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", + printk(KERN_ERR "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result); goto fail_fe_hw; } @@ -276,14 +265,14 @@ int dvb_register(struct au0828_dev *dev) dvb->fe_mem.source = DMX_MEMORY_FE; result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", + printk(KERN_ERR "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result); goto fail_fe_mem; } result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); if (result < 0) { - printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", + printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n", DRIVER_NAME, result); goto fail_fe_conn; } @@ -313,6 +302,8 @@ void au0828_dvb_unregister(struct au0828_dev *dev) { struct au0828_dvb *dvb = &dev->dvb; + dprintk(1, "%s()\n", __FUNCTION__); + if(dvb->frontend == NULL) return; @@ -335,6 +326,8 @@ int au0828_dvb_register(struct au0828_dev *dev) struct au0828_dvb *dvb = &dev->dvb; int ret; + dprintk(1, "%s()\n", __FUNCTION__); + /* init frontend */ switch (dev->board) { case AU0828_BOARD_HAUPPAUGE_HVR850: @@ -355,7 +348,7 @@ int au0828_dvb_register(struct au0828_dev *dev) break; } if (NULL == dvb->frontend) { - printk("Frontend initialization failed\n"); + printk(KERN_ERR "%s() Frontend initialization failed\n", __FUNCTION__); return -1; } diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index 3e7482481152..4545a9cbaa6d 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -29,19 +29,14 @@ #include -static unsigned int i2c_debug; -module_param(i2c_debug, int, 0644); +unsigned int i2c_debug = 0; +module_param(i2c_debug, int, 0444); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +unsigned int i2c_scan = 0; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -#define dprintk(level, fmt, arg...)\ - do { if (i2c_debug >= level)\ - printk(KERN_DEBUG "%s/0: " fmt, DRIVER_NAME, ## arg);\ - } while (0) - #define I2C_WAIT_DELAY 512 #define I2C_WAIT_RETRY 64 @@ -146,7 +141,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, int i, strobe = 0; struct au0828_dev *dev = i2c_adap->algo_data; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(4, "%s()\n", __FUNCTION__); au0828_write(dev, REG_2FF, 0x01); au0828_write(dev, REG_202, 0x07); @@ -154,13 +149,11 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); - if (i2c_debug) - dprintk(1, "SEND: %02x\n", msg->addr); + dprintk(4, "SEND: %02x\n", msg->addr); for (i=0; i < msg->len;) { - if (i2c_debug) - dprintk(1, " %02x\n", msg->buf[i]); + dprintk(4, " %02x\n", msg->buf[i]); au0828_write(dev, REG_205, msg->buf[i]); @@ -187,8 +180,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (!i2c_wait_done(i2c_adap)) return -EIO; - if (i2c_debug) - dprintk(1, "\n"); + dprintk(4, "\n"); return msg->len; } @@ -200,7 +192,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, struct au0828_dev *dev = i2c_adap->algo_data; int i; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(4, "%s()\n", __FUNCTION__); au0828_write(dev, REG_2FF, 0x01); au0828_write(dev, REG_202, 0x07); @@ -208,8 +200,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); - if (i2c_debug) - dprintk(1, " RECV:\n"); + dprintk(4, " RECV:\n"); /* Deal with i2c_scan */ if (msg->len == 0) { @@ -233,14 +224,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff; - if (i2c_debug) - dprintk(1, " %02x\n", msg->buf[i-1]); + dprintk(4, " %02x\n", msg->buf[i-1]); } if (!i2c_wait_done(i2c_adap)) return -EIO; - if (i2c_debug) - dprintk(1, "\n"); + dprintk(4, "\n"); return msg->len; } @@ -250,10 +239,10 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, { int i, retval = 0; - dprintk(1, "%s(num = %d)\n", __FUNCTION__, num); + dprintk(4, "%s(num = %d)\n", __FUNCTION__, num); for (i = 0 ; i < num; i++) { - dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", + dprintk(4, "%s(num = %d) addr = 0x%02x len = 0x%x\n", __FUNCTION__, num, msgs[i].addr, msgs[i].len); if (msgs[i].flags & I2C_M_RD) { /* read */ @@ -384,6 +373,7 @@ int au0828_i2c_register(struct au0828_dev *dev) do_i2c_scan(DRIVER_NAME, &dev->i2c_client); } else printk("%s: i2c bus register FAILED\n", DRIVER_NAME); + return dev->i2c_rc; } @@ -393,10 +383,3 @@ int au0828_i2c_unregister(struct au0828_dev *dev) return 0; } -/* ----------------------------------------------------------------------- */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 3dc09f8ffef7..94426770a6df 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -96,6 +96,9 @@ struct au0828_buff { /* au0828-core.c */ extern u32 au0828_read(struct au0828_dev *dev, u16 reg); extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val); +extern unsigned int debug; +extern unsigned int usb_debug; +extern unsigned int bridge_debug; /* ----------------------------------------------------------- */ /* au0828-cards.c */ @@ -112,8 +115,14 @@ extern int au0828_i2c_register(struct au0828_dev *dev); extern int au0828_i2c_unregister(struct au0828_dev *dev); extern void au0828_call_i2c_clients(struct au0828_dev *dev, unsigned int cmd, void *arg); +extern unsigned int i2c_debug; /* ----------------------------------------------------------- */ /* au0828-dvb.c */ extern int au0828_dvb_register(struct au0828_dev *dev); extern void au0828_dvb_unregister(struct au0828_dev *dev); + +#define dprintk(level, fmt, arg...)\ + do { if (debug & level)\ + printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ + } while (0) From fdfc7452f17eb65eb29a143cf992ea2b8d262c7a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 18:59:48 -0300 Subject: [PATCH 355/452] V4L/DVB (7626): Kconfig: VIDEO_AU0828 should select DVB_AU8522 and DVB_TUNER_XC5000 VIDEO_AU0828 should select DVB_AU8522 and DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index 38d68ee8026a..1a7c8f77f1ce 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -3,6 +3,8 @@ config VIDEO_AU0828 tristate "Auvitek AU0828 support" depends on VIDEO_DEV && I2C && INPUT select I2C_ALGOBIT + select DVB_AU8522 if !DVB_FE_CUSTOMIZE + select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE ---help--- This is a video4linux driver for Auvitek's USB device. From f07e8e4bb790f6cb462d5d5425193cad874ac0de Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 18 Apr 2008 21:42:30 -0300 Subject: [PATCH 356/452] V4L/DVB (7627): au0828: replace __FUNCTION__ with __func__ replace __FUNCTION__ with __func__ and clean associated checkpatch.pl warnings. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 14 ++++--- drivers/media/video/au0828/au0828-core.c | 28 +++++++------- drivers/media/video/au0828/au0828-dvb.c | 46 ++++++++++++----------- drivers/media/video/au0828/au0828-i2c.c | 10 ++--- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index eafdc552a9fa..5c9c3aea99d4 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -45,7 +45,7 @@ int au0828_tuner_callback(void *priv, int command, int arg) { struct au0828_dev *dev = priv; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); switch(dev->board) { case AU0828_BOARD_HAUPPAUGE_HVR850: @@ -62,7 +62,7 @@ int au0828_tuner_callback(void *priv, int command, int arg) } else { printk(KERN_ERR - "%s(): Unknown command.\n", __FUNCTION__); + "%s(): Unknown command.\n", __func__); return -EINVAL; } break; @@ -83,11 +83,13 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ break; default: - printk("%s: warning: unknown hauppauge model #%d\n", __FUNCTION__, tv.model); + printk(KERN_WARNING "%s: warning: " + "unknown hauppauge model #%d\n", __func__, tv.model); break; } - printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", __FUNCTION__, tv.model); + printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", + __func__, tv.model); } @@ -95,7 +97,7 @@ void au0828_card_setup(struct au0828_dev *dev) { static u8 eeprom[256]; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (dev->i2c_rc == 0) { dev->i2c_client.addr = 0xa0 >> 1; @@ -118,7 +120,7 @@ void au0828_card_setup(struct au0828_dev *dev) */ void au0828_gpio_setup(struct au0828_dev *dev) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); switch(dev->board) { case AU0828_BOARD_HAUPPAUGE_HVR850: diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 76801d135f2a..efecac3979ae 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -59,13 +59,13 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, u32 au0828_readreg(struct au0828_dev *dev, u16 reg) { recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1); - dprintk(8, "%s(0x%x) = 0x%x\n", __FUNCTION__, reg, dev->ctrlmsg[0]); + dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]); return dev->ctrlmsg[0]; } u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) { - dprintk(8, "%s(0x%x, 0x%x)\n", __FUNCTION__, reg, val); + dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val); return send_control_msg(dev, CMD_REQUEST_OUT, val, reg, dev->ctrlmsg, 0); } @@ -76,7 +76,7 @@ static void cmd_msg_dump(struct au0828_dev *dev) for (i = 0;i < sizeof(dev->ctrlmsg); i+=16) dprintk(2,"%s() %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x\n", - __FUNCTION__, + __func__, dev->ctrlmsg[i+0], dev->ctrlmsg[i+1], dev->ctrlmsg[i+2], dev->ctrlmsg[i+3], dev->ctrlmsg[i+4], dev->ctrlmsg[i+5], @@ -106,8 +106,7 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, if (status < 0) { printk(KERN_ERR "%s() Failed sending control message, error %d.\n", - __FUNCTION__, - status); + __func__, status); } } @@ -136,8 +135,7 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, if (status < 0) { printk(KERN_ERR "%s() Failed receiving control message, error %d.\n", - __FUNCTION__, - status); + __func__, status); } else cmd_msg_dump(dev); @@ -149,7 +147,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) { struct au0828_dev *dev = usb_get_intfdata(interface); - dprintk(1,"%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); /* Digital TV */ au0828_dvb_unregister(dev); @@ -179,15 +177,14 @@ static int au0828_usb_probe (struct usb_interface *interface, if (ifnum != 0) return -ENODEV; - dprintk(1,"%s() vendor id 0x%x device id 0x%x ifnum:%d\n", - __FUNCTION__, + dprintk(1,"%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, le16_to_cpu(usbdev->descriptor.idVendor), le16_to_cpu(usbdev->descriptor.idProduct), ifnum); dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - printk(KERN_ERR "%s() Unable to allocate memory\n", __FUNCTION__); + printk(KERN_ERR "%s() Unable to allocate memory\n", __func__); return -ENOMEM; } @@ -232,20 +229,21 @@ static int __init au0828_init(void) int ret; if(debug) - printk(KERN_INFO "%s() Debugging is enabled\n", __FUNCTION__); + printk(KERN_INFO "%s() Debugging is enabled\n", __func__); if(usb_debug) { - printk(KERN_INFO "%s() USB Debugging is enabled\n", __FUNCTION__); + printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__); debug |= 2; } if(i2c_debug) { - printk(KERN_INFO "%s() I2C Debugging is enabled\n", __FUNCTION__); + printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__); debug |= 4; } if(bridge_debug) { - printk(KERN_INFO "%s() Bridge Debugging is enabled\n", __FUNCTION__); + printk(KERN_INFO "%s() Bridge Debugging is enabled\n", + __func__); debug |= 8; } diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 453fb3efa3e0..8853f4e26092 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -49,7 +49,7 @@ static void urb_completion(struct urb *purb) struct au0828_dev *dev = purb->context; int ptype = usb_pipetype(purb->pipe); - dprintk(2, "%s()\n", __FUNCTION__); + dprintk(2, "%s()\n", __func__); if (!dev) return; @@ -58,7 +58,8 @@ static void urb_completion(struct urb *purb) return; if (ptype != PIPE_BULK) { - printk(KERN_ERR "%s() Unsupported URB type %d\n", __FUNCTION__, ptype); + printk(KERN_ERR "%s() Unsupported URB type %d\n", + __func__, ptype); return; } @@ -78,7 +79,7 @@ static int stop_urb_transfer(struct au0828_dev *dev) { int i; - dprintk(2, "%s()\n", __FUNCTION__); + dprintk(2, "%s()\n", __func__); /* FIXME: Do we need to free the transfer_buffers? */ for (i = 0; i < URB_COUNT; i++) { @@ -100,10 +101,10 @@ static int start_urb_transfer(struct au0828_dev *dev) struct urb *purb; int i, ret = -ENOMEM; - dprintk(2, "%s()\n", __FUNCTION__); + dprintk(2, "%s()\n", __func__); if (dev->urb_streaming) { - dprintk(2, "%s: iso xfer already running!\n", __FUNCTION__); + dprintk(2, "%s: iso xfer already running!\n", __func__); return 0; } @@ -138,7 +139,8 @@ static int start_urb_transfer(struct au0828_dev *dev) ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC); if (ret != 0) { stop_urb_transfer(dev); - printk("%s: failed urb submission, err = %d\n", __FUNCTION__, ret); + printk(KERN_ERR "%s: failed urb submission, " + "err = %d\n", __func__, ret); return ret; } } @@ -157,7 +159,7 @@ static int au0828_dvb_start_feed(struct dvb_demux_feed *feed) struct au0828_dvb *dvb = &dev->dvb; int ret = 0; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (!demux->dmx.frontend) return -EINVAL; @@ -185,7 +187,7 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) struct au0828_dvb *dvb = &dev->dvb; int ret = 0; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if (dvb) { mutex_lock(&dvb->lock); @@ -208,14 +210,14 @@ int dvb_register(struct au0828_dev *dev) struct au0828_dvb *dvb = &dev->dvb; int result; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); /* register adapter */ result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE, &dev->usbdev->dev, adapter_nr); if (result < 0) { - printk(KERN_ERROR "%s: dvb_register_adapter failed (errno = %d)\n", - DRIVER_NAME, result); + printk(KERN_ERR "%s: dvb_register_adapter failed " + "(errno = %d)\n", DRIVER_NAME, result); goto fail_adapter; } dvb->adapter.priv = dev; @@ -223,8 +225,8 @@ int dvb_register(struct au0828_dev *dev) /* register frontend */ result = dvb_register_frontend(&dvb->adapter, dvb->frontend); if (result < 0) { - printk(KERN_ERR "%s: dvb_register_frontend failed (errno = %d)\n", - DRIVER_NAME, result); + printk(KERN_ERR "%s: dvb_register_frontend failed " + "(errno = %d)\n", DRIVER_NAME, result); goto fail_frontend; } @@ -257,16 +259,16 @@ int dvb_register(struct au0828_dev *dev) dvb->fe_hw.source = DMX_FRONTEND_0; result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); if (result < 0) { - printk(KERN_ERR "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", - DRIVER_NAME, result); + printk(KERN_ERR "%s: add_frontend failed " + "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result); goto fail_fe_hw; } dvb->fe_mem.source = DMX_MEMORY_FE; result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); if (result < 0) { - printk(KERN_ERR "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", - DRIVER_NAME, result); + printk(KERN_ERR "%s: add_frontend failed " + "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result); goto fail_fe_mem; } @@ -302,7 +304,7 @@ void au0828_dvb_unregister(struct au0828_dev *dev) { struct au0828_dvb *dvb = &dev->dvb; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); if(dvb->frontend == NULL) return; @@ -326,7 +328,7 @@ int au0828_dvb_register(struct au0828_dev *dev) struct au0828_dvb *dvb = &dev->dvb; int ret; - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); /* init frontend */ switch (dev->board) { @@ -344,11 +346,13 @@ int au0828_dvb_register(struct au0828_dev *dev) } break; default: - printk("The frontend of your DVB/ATSC card isn't supported yet\n"); + printk(KERN_WARNING "The frontend of your DVB/ATSC card " + "isn't supported yet\n"); break; } if (NULL == dvb->frontend) { - printk(KERN_ERR "%s() Frontend initialization failed\n", __FUNCTION__); + printk(KERN_ERR "%s() Frontend initialization failed\n", + __func__); return -1; } diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index 4545a9cbaa6d..c1e1cf6ed95a 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -141,7 +141,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, int i, strobe = 0; struct au0828_dev *dev = i2c_adap->algo_data; - dprintk(4, "%s()\n", __FUNCTION__); + dprintk(4, "%s()\n", __func__); au0828_write(dev, REG_2FF, 0x01); au0828_write(dev, REG_202, 0x07); @@ -192,7 +192,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, struct au0828_dev *dev = i2c_adap->algo_data; int i; - dprintk(4, "%s()\n", __FUNCTION__); + dprintk(4, "%s()\n", __func__); au0828_write(dev, REG_2FF, 0x01); au0828_write(dev, REG_202, 0x07); @@ -239,11 +239,11 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, { int i, retval = 0; - dprintk(4, "%s(num = %d)\n", __FUNCTION__, num); + dprintk(4, "%s(num = %d)\n", __func__, num); for (i = 0 ; i < num; i++) { dprintk(4, "%s(num = %d) addr = 0x%02x len = 0x%x\n", - __FUNCTION__, num, msgs[i].addr, msgs[i].len); + __func__, num, msgs[i].addr, msgs[i].len); if (msgs[i].flags & I2C_M_RD) { /* read */ retval = i2c_readbytes(i2c_adap, &msgs[i], 0); @@ -346,7 +346,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) /* init + register i2c algo-bit adapter */ int au0828_i2c_register(struct au0828_dev *dev) { - dprintk(1, "%s()\n", __FUNCTION__); + dprintk(1, "%s()\n", __func__); memcpy(&dev->i2c_adap, &au0828_i2c_adap_template, sizeof(dev->i2c_adap)); From e059b0fac7d9df8bf759d7092a16221f0fd250e8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 18:59:48 -0300 Subject: [PATCH 357/452] V4L/DVB (7628): au8522: codingstyle cleanups Fixed some checkpatch.pl warnings Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 70 ++++++++++++++-------------- drivers/media/dvb/frontends/au8522.h | 9 ++-- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index d3c44b95e240..caef885a122f 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -31,10 +31,10 @@ struct au8522_state { - struct i2c_adapter* i2c; + struct i2c_adapter *i2c; /* configuration settings */ - const struct au8522_config* config; + const struct au8522_config *config; struct dvb_frontend frontend; @@ -47,7 +47,7 @@ static int debug = 0; #define dprintk if (debug) printk /* 16 bit registers, 8 bit values */ -static int au8522_writereg(struct au8522_state* state, u16 reg, u8 data) +static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) { int ret; u8 buf [] = { reg >> 8, reg & 0xff, data }; @@ -64,7 +64,7 @@ static int au8522_writereg(struct au8522_state* state, u16 reg, u8 data) return (ret != 1) ? -1 : 0; } -static u8 au8522_readreg(struct au8522_state* state, u16 reg) +static u8 au8522_readreg(struct au8522_state *state, u16 reg) { int ret; u8 b0 [] = { reg >> 8, reg & 0xff }; @@ -83,9 +83,9 @@ static u8 au8522_readreg(struct au8522_state* state, u16 reg) return b1[0]; } -static int au8522_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { - struct au8522_state* state = fe->demodulator_priv; + struct au8522_state *state = fe->demodulator_priv; dprintk("%s(%d)\n", __FUNCTION__, enable); @@ -95,10 +95,10 @@ static int au8522_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) return au8522_writereg(state, 0x106, 0); } -static int au8522_enable_modulation(struct dvb_frontend* fe, - fe_modulation_t m) +static int au8522_enable_modulation(struct dvb_frontend *fe, + fe_modulation_t m) { - struct au8522_state* state = fe->demodulator_priv; + struct au8522_state *state = fe->demodulator_priv; dprintk("%s(0x%08x)\n", __FUNCTION__, m); @@ -230,10 +230,10 @@ static int au8522_enable_modulation(struct dvb_frontend* fe, } /* Talk to the demod, set the FEC, GUARD, QAM settings etc */ -static int au8522_set_frontend (struct dvb_frontend* fe, - struct dvb_frontend_parameters *p) +static int au8522_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) { - struct au8522_state* state = fe->demodulator_priv; + struct au8522_state *state = fe->demodulator_priv; dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency); @@ -255,9 +255,9 @@ static int au8522_set_frontend (struct dvb_frontend* fe, /* Reset the demod hardware and reset all of the configuration registers to a default state. */ -static int au8522_init(struct dvb_frontend* fe) +static int au8522_init(struct dvb_frontend *fe) { - struct au8522_state* state = fe->demodulator_priv; + struct au8522_state *state = fe->demodulator_priv; dprintk("%s()\n", __FUNCTION__); au8522_writereg(state, 0xa4, 1 << 5); @@ -267,9 +267,9 @@ static int au8522_init(struct dvb_frontend* fe) return 0; } -static int au8522_read_status(struct dvb_frontend* fe, fe_status_t* status) +static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) { - struct au8522_state* state = fe->demodulator_priv; + struct au8522_state *state = fe->demodulator_priv; u8 reg; u32 tuner_status = 0; @@ -279,16 +279,16 @@ static int au8522_read_status(struct dvb_frontend* fe, fe_status_t* status) dprintk("%s() Checking VSB_8\n", __FUNCTION__); //au8522_writereg(state, 0x80a4, 0x20); reg = au8522_readreg(state, 0x4088); - if(reg & 0x01) + if (reg & 0x01) *status |= FE_HAS_VITERBI; - if(reg & 0x02) + if (reg & 0x02) *status |= FE_HAS_LOCK | FE_HAS_SYNC; } else { dprintk("%s() Checking QAM\n", __FUNCTION__); reg = au8522_readreg(state, 0x4541); - if(reg & 0x80) + if (reg & 0x80) *status |= FE_HAS_VITERBI; - if(reg & 0x20) + if (reg & 0x20) *status |= FE_HAS_LOCK | FE_HAS_SYNC; } @@ -320,7 +320,7 @@ static int au8522_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } -static int au8522_read_snr(struct dvb_frontend* fe, u16* snr) +static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) { dprintk("%s()\n", __FUNCTION__); @@ -329,30 +329,30 @@ static int au8522_read_snr(struct dvb_frontend* fe, u16* snr) return 0; } -static int au8522_read_signal_strength(struct dvb_frontend* fe, - u16* signal_strength) +static int au8522_read_signal_strength(struct dvb_frontend *fe, + u16 *signal_strength) { return au8522_read_snr(fe, signal_strength); } -static int au8522_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { - struct au8522_state* state = fe->demodulator_priv; + struct au8522_state *state = fe->demodulator_priv; *ucblocks = au8522_readreg(state, 0x4087); return 0; } -static int au8522_read_ber(struct dvb_frontend* fe, u32* ber) +static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber) { return au8522_read_ucblocks(fe, ber); } -static int au8522_get_frontend(struct dvb_frontend* fe, +static int au8522_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { - struct au8522_state* state = fe->demodulator_priv; + struct au8522_state *state = fe->demodulator_priv; p->frequency = state->current_frequency; p->u.vsb.modulation = state->current_modulation; @@ -360,25 +360,25 @@ static int au8522_get_frontend(struct dvb_frontend* fe, return 0; } -static int au8522_get_tune_settings(struct dvb_frontend* fe, - struct dvb_frontend_tune_settings *tune) +static int au8522_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *tune) { tune->min_delay_ms = 1000; return 0; } -static void au8522_release(struct dvb_frontend* fe) +static void au8522_release(struct dvb_frontend *fe) { - struct au8522_state* state = fe->demodulator_priv; + struct au8522_state *state = fe->demodulator_priv; kfree(state); } static struct dvb_frontend_ops au8522_ops; -struct dvb_frontend* au8522_attach(const struct au8522_config* config, - struct i2c_adapter* i2c) +struct dvb_frontend *au8522_attach(const struct au8522_config *config, + struct i2c_adapter *i2c) { - struct au8522_state* state = NULL; + struct au8522_state *state = NULL; /* allocate memory for the internal state */ state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL); diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h index a75627155fed..9952957ab7b0 100644 --- a/drivers/media/dvb/frontends/au8522.h +++ b/drivers/media/dvb/frontends/au8522.h @@ -36,11 +36,12 @@ struct au8522_config }; #if defined(CONFIG_DVB_AU8522) || (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE)) -extern struct dvb_frontend* au8522_attach(const struct au8522_config* config, - struct i2c_adapter* i2c); +extern struct dvb_frontend *au8522_attach(const struct au8522_config *config, + struct i2c_adapter *i2c); #else -static inline struct dvb_frontend* au8522_attach(const struct au8522_config* config, - struct i2c_adapter* i2c) +static inline +struct dvb_frontend *au8522_attach(const struct au8522_config *config, + struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return NULL; From ce1719a61c7c0ac40c6244e6b354181dde27062d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Apr 2008 18:59:48 -0300 Subject: [PATCH 358/452] V4L/DVB (7629): au8522: replace __FUNCTION__ with __func__ replace __FUNCTION__ with __func__ and clean associated checkpatch.pl warnings. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 31 ++++++++++++++-------------- drivers/media/dvb/frontends/au8522.h | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index caef885a122f..dc01e75cdc60 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -59,7 +59,7 @@ static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) if (ret != 1) printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, " - "ret == %i)\n", __FUNCTION__, reg, data, ret); + "ret == %i)\n", __func__, reg, data, ret); return (ret != 1) ? -1 : 0; } @@ -79,7 +79,8 @@ static u8 au8522_readreg(struct au8522_state *state, u16 reg) ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) - printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + printk(KERN_ERR "%s: readreg error (ret == %i)\n", + __func__, ret); return b1[0]; } @@ -87,7 +88,7 @@ static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct au8522_state *state = fe->demodulator_priv; - dprintk("%s(%d)\n", __FUNCTION__, enable); + dprintk("%s(%d)\n", __func__, enable); if (enable) return au8522_writereg(state, 0x106, 1); @@ -100,11 +101,11 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, { struct au8522_state *state = fe->demodulator_priv; - dprintk("%s(0x%08x)\n", __FUNCTION__, m); + dprintk("%s(0x%08x)\n", __func__, m); switch(m) { case VSB_8: - dprintk("%s() VSB_8\n", __FUNCTION__); + dprintk("%s() VSB_8\n", __func__); //au8522_writereg(state, 0x410b, 0x84); // Serial @@ -220,7 +221,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, au8522_writereg(state, 0x8526, 0x01); break; default: - dprintk("%s() Invalid modulation\n", __FUNCTION__); + dprintk("%s() Invalid modulation\n", __func__); return -EINVAL; } @@ -235,7 +236,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe, { struct au8522_state *state = fe->demodulator_priv; - dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency); + dprintk("%s(frequency=%d)\n", __func__, p->frequency); state->current_frequency = p->frequency; @@ -258,7 +259,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe, static int au8522_init(struct dvb_frontend *fe) { struct au8522_state *state = fe->demodulator_priv; - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); au8522_writereg(state, 0xa4, 1 << 5); @@ -276,7 +277,7 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) *status = 0; if (state->current_modulation == VSB_8) { - dprintk("%s() Checking VSB_8\n", __FUNCTION__); + dprintk("%s() Checking VSB_8\n", __func__); //au8522_writereg(state, 0x80a4, 0x20); reg = au8522_readreg(state, 0x4088); if (reg & 0x01) @@ -284,7 +285,7 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) if (reg & 0x02) *status |= FE_HAS_LOCK | FE_HAS_SYNC; } else { - dprintk("%s() Checking QAM\n", __FUNCTION__); + dprintk("%s() Checking QAM\n", __func__); reg = au8522_readreg(state, 0x4541); if (reg & 0x80) *status |= FE_HAS_VITERBI; @@ -294,13 +295,13 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) switch(state->config->status_mode) { case AU8522_DEMODLOCKING: - dprintk("%s() DEMODLOCKING\n", __FUNCTION__); + dprintk("%s() DEMODLOCKING\n", __func__); if (*status & FE_HAS_VITERBI) *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; break; case AU8522_TUNERLOCKING: /* Get the tuner status */ - dprintk("%s() TUNERLOCKING\n", __FUNCTION__); + dprintk("%s() TUNERLOCKING\n", __func__); if (fe->ops.tuner_ops.get_status) { if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -315,14 +316,14 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) break; } - dprintk("%s() status 0x%08x\n", __FUNCTION__, *status); + dprintk("%s() status 0x%08x\n", __func__, *status); return 0; } static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) { - dprintk("%s()\n", __FUNCTION__); + dprintk("%s()\n", __func__); *snr = 0; @@ -395,7 +396,7 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config, if (au8522_init(&state->frontend) != 0) { printk(KERN_ERR "%s: Failed to initialize correctly\n", - __FUNCTION__); + __func__); goto error; } diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h index 9952957ab7b0..19d5d1ef9842 100644 --- a/drivers/media/dvb/frontends/au8522.h +++ b/drivers/media/dvb/frontends/au8522.h @@ -43,7 +43,7 @@ static inline struct dvb_frontend *au8522_attach(const struct au8522_config *config, struct i2c_adapter *i2c) { - 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_AU8522 */ From 8973dc4b70c5506596207da3fddab03002357178 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 5 Apr 2008 23:08:08 -0300 Subject: [PATCH 359/452] V4L/DVB (7630): au8522: fix au8522_read_ucblocks for qam ucblocks are reported in separate registers for vsb & qam Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index dc01e75cdc60..9fb61e6ed679 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -340,7 +340,10 @@ static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { struct au8522_state *state = fe->demodulator_priv; - *ucblocks = au8522_readreg(state, 0x4087); + if (state->current_modulation == VSB_8) + *ucblocks = au8522_readreg(state, 0x4087); + else + *ucblocks = au8522_readreg(state, 0x4543); return 0; } From fb8152cb01dc2bca04a6ee561920d0a02af6c73b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 5 Apr 2008 23:13:05 -0300 Subject: [PATCH 360/452] V4L/DVB (7631): au8522: add function au8522_read_mse add function au8522_read_mse, which will be used to compute snr TO DO: mse2snr Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index 9fb61e6ed679..d445cf1e02be 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -321,11 +321,28 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) return 0; } +static int au8522_read_mse(struct dvb_frontend *fe) +{ + struct au8522_state *state = fe->demodulator_priv; + int mse = 0; + + if (state->current_modulation == VSB_8) + mse = au8522_readreg(state, 0x4311); + else + mse = au8522_readreg(state, 0x4522); + + dprintk("%s: %d\n", __func__, mse); + + return mse; +} + static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) { dprintk("%s()\n", __func__); - *snr = 0; + /* FIXME: This is mse, not snr + * TODO: mse2snr */ + *snr = au8522_read_mse(fe); return 0; } From f01699b482875bf224a907a45d58e8e3739d554b Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 10 Apr 2008 02:01:48 -0300 Subject: [PATCH 361/452] V4L/DVB (7632): au8522: Added SNR support and basic cleanup au8522: Added SNR support and basic cleanup Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 511 ++++++++++++++++++++------- 1 file changed, 382 insertions(+), 129 deletions(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index d445cf1e02be..fa3e6abdfa6e 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -96,129 +96,388 @@ static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) return au8522_writereg(state, 0x106, 0); } +/* VSB SNR lookup table */ +static struct { + u16 val; + u16 data; +} vsb_mse2snr_tab[] = { + { 0, 270 }, + { 2, 250 }, + { 3, 240 }, + { 5, 230 }, + { 7, 220 }, + { 9, 210 }, + { 12, 200 }, + { 13, 195 }, + { 15, 190 }, + { 17, 185 }, + { 19, 180 }, + { 21, 175 }, + { 24, 170 }, + { 27, 165 }, + { 31, 160 }, + { 32, 158 }, + { 33, 156 }, + { 36, 152 }, + { 37, 150 }, + { 39, 148 }, + { 40, 146 }, + { 41, 144 }, + { 43, 142 }, + { 44, 140 }, + { 48, 135 }, + { 50, 130 }, + { 43, 142 }, + { 53, 125 }, + { 56, 120 }, + { 256, 115 }, +}; + +/* QAM64 SNR lookup table */ +static struct { + u16 val; + u16 data; +} qam64_mse2snr_tab[] = { + { 15, 0 }, + { 16, 290 }, + { 17, 288 }, + { 18, 286 }, + { 19, 284 }, + { 20, 282 }, + { 21, 281 }, + { 22, 279 }, + { 23, 277 }, + { 24, 275 }, + { 25, 273 }, + { 26, 271 }, + { 27, 269 }, + { 28, 268 }, + { 29, 266 }, + { 30, 264 }, + { 31, 262 }, + { 32, 260 }, + { 33, 259 }, + { 34, 258 }, + { 35, 256 }, + { 36, 255 }, + { 37, 254 }, + { 38, 252 }, + { 39, 251 }, + { 40, 250 }, + { 41, 249 }, + { 42, 248 }, + { 43, 246 }, + { 44, 245 }, + { 45, 244 }, + { 46, 242 }, + { 47, 241 }, + { 48, 240 }, + { 50, 239 }, + { 51, 238 }, + { 53, 237 }, + { 54, 236 }, + { 56, 235 }, + { 57, 234 }, + { 59, 233 }, + { 60, 232 }, + { 62, 231 }, + { 63, 230 }, + { 65, 229 }, + { 67, 228 }, + { 68, 227 }, + { 70, 226 }, + { 71, 225 }, + { 73, 224 }, + { 74, 223 }, + { 76, 222 }, + { 78, 221 }, + { 80, 220 }, + { 82, 219 }, + { 85, 218 }, + { 88, 217 }, + { 90, 216 }, + { 92, 215 }, + { 93, 214 }, + { 94, 212 }, + { 95, 211 }, + { 97, 210 }, + { 99, 209 }, + { 101, 208 }, + { 102, 207 }, + { 104, 206 }, + { 107, 205 }, + { 111, 204 }, + { 114, 203 }, + { 118, 202 }, + { 122, 201 }, + { 125, 200 }, + { 128, 199 }, + { 130, 198 }, + { 132, 197 }, + { 256, 190 }, +}; + +/* QAM256 SNR lookup table */ +static struct { + u16 val; + u16 data; +} qam256_mse2snr_tab[] = { + { 16, 0 }, + { 17, 400 }, + { 18, 398 }, + { 19, 396 }, + { 20, 394 }, + { 21, 392 }, + { 22, 390 }, + { 23, 388 }, + { 24, 386 }, + { 25, 384 }, + { 26, 382 }, + { 27, 380 }, + { 28, 379 }, + { 29, 378 }, + { 30, 377 }, + { 31, 376 }, + { 32, 375 }, + { 33, 374 }, + { 34, 373 }, + { 35, 372 }, + { 36, 371 }, + { 37, 370 }, + { 38, 362 }, + { 39, 354 }, + { 40, 346 }, + { 41, 338 }, + { 42, 330 }, + { 43, 328 }, + { 44, 326 }, + { 45, 324 }, + { 46, 322 }, + { 47, 320 }, + { 48, 319 }, + { 49, 318 }, + { 50, 317 }, + { 51, 316 }, + { 52, 315 }, + { 53, 314 }, + { 54, 313 }, + { 55, 312 }, + { 56, 311 }, + { 57, 310 }, + { 58, 308 }, + { 59, 306 }, + { 60, 304 }, + { 61, 302 }, + { 62, 300 }, + { 63, 298 }, + { 65, 295 }, + { 68, 294 }, + { 70, 293 }, + { 73, 292 }, + { 76, 291 }, + { 78, 290 }, + { 79, 289 }, + { 81, 288 }, + { 82, 287 }, + { 83, 286 }, + { 84, 285 }, + { 85, 284 }, + { 86, 283 }, + { 88, 282 }, + { 89, 281 }, + { 256, 280 }, +}; + +static int au8522_vsb_mse2snr_lookup(int mse, u16 *snr) +{ + int i, ret = -EINVAL; + dprintk("%s()\n", __func__); + + for (i = 0; i < ARRAY_SIZE(vsb_mse2snr_tab); i++) { + if (mse < vsb_mse2snr_tab[i].val) { + *snr = vsb_mse2snr_tab[i].data; + ret = 0; + break; + } + } + dprintk("%s() snr=%d\n", __func__, *snr); + return ret; +} + +static int au8522_qam64_mse2snr_lookup(int mse, u16 *snr) +{ + int i, ret = -EINVAL; + dprintk("%s()\n", __func__); + + for (i = 0; i < ARRAY_SIZE(qam64_mse2snr_tab); i++) { + if (mse < qam64_mse2snr_tab[i].val) { + *snr = qam64_mse2snr_tab[i].data; + ret = 0; + break; + } + } + dprintk("%s() snr=%d\n", __func__, *snr); + return ret; +} + +static int au8522_qam256_mse2snr_lookup(int mse, u16 *snr) +{ + int i, ret = -EINVAL; + dprintk("%s()\n", __func__); + + for (i = 0; i < ARRAY_SIZE(qam256_mse2snr_tab); i++) { + if (mse < qam256_mse2snr_tab[i].val) { + *snr = qam256_mse2snr_tab[i].data; + ret = 0; + break; + } + } + dprintk("%s() snr=%d\n", __func__, *snr); + return ret; +} + +/* VSB Modulation table */ +static struct { + u16 reg; + u16 data; +} VSB_mod_tab[] = { + { 0x8090, 0x84 }, + { 0x4092, 0x11 }, + { 0x2005, 0x00 }, + { 0x8091, 0x80 }, + { 0x80a3, 0x0c }, + { 0x80a4, 0xe8 }, + { 0x8081, 0xc4 }, + { 0x80a5, 0x40 }, + { 0x80a7, 0x40 }, + { 0x80a6, 0x67 }, + { 0x8262, 0x20 }, + { 0x821c, 0x30 }, + { 0x80d8, 0x1a }, + { 0x8227, 0xa0 }, + { 0x8121, 0xff }, + { 0x80a8, 0xf0 }, + { 0x80a9, 0x05 }, + { 0x80aa, 0x77 }, + { 0x80ab, 0xf0 }, + { 0x80ac, 0x05 }, + { 0x80ad, 0x77 }, + { 0x80ae, 0x41 }, + { 0x80af, 0x66 }, + { 0x821b, 0xcc }, + { 0x821d, 0x80 }, + { 0x80b5, 0xfb }, + { 0x80b6, 0x8e }, + { 0x80b7, 0x39 }, + { 0x80a4, 0xe8 }, + { 0x8231, 0x13 }, +}; + +/* QAM Modulation table */ +static struct { + u16 reg; + u16 data; +} QAM_mod_tab[] = { + { 0x80a3, 0x09 }, + { 0x80a4, 0x00 }, + { 0x8081, 0xc4 }, + { 0x80a5, 0x40 }, + { 0x80b5, 0xfb }, + { 0x80b6, 0x8e }, + { 0x80b7, 0x39 }, + { 0x80aa, 0x77 }, + { 0x80ad, 0x77 }, + { 0x80a6, 0x67 }, + { 0x8262, 0x20 }, + { 0x821c, 0x30 }, + { 0x80b8, 0x3e }, + { 0x80b9, 0xf0 }, + { 0x80ba, 0x01 }, + { 0x80bb, 0x18 }, + { 0x80bc, 0x50 }, + { 0x80bd, 0x00 }, + { 0x80be, 0xea }, + { 0x80bf, 0xef }, + { 0x80c0, 0xfc }, + { 0x80c1, 0xbd }, + { 0x80c2, 0x1f }, + { 0x80c3, 0xfc }, + { 0x80c4, 0xdd }, + { 0x80c5, 0xaf }, + { 0x80c6, 0x00 }, + { 0x80c7, 0x38 }, + { 0x80c8, 0x30 }, + { 0x80c9, 0x05 }, + { 0x80ca, 0x4a }, + { 0x80cb, 0xd0 }, + { 0x80cc, 0x01 }, + { 0x80cd, 0xd9 }, + { 0x80ce, 0x6f }, + { 0x80cf, 0xf9 }, + { 0x80d0, 0x70 }, + { 0x80d1, 0xdf }, + { 0x80d2, 0xf7 }, + { 0x80d3, 0xc2 }, + { 0x80d4, 0xdf }, + { 0x80d5, 0x02 }, + { 0x80d6, 0x9a }, + { 0x80d7, 0xd0 }, + { 0x8250, 0x0d }, + { 0x8251, 0xcd }, + { 0x8252, 0xe0 }, + { 0x8253, 0x05 }, + { 0x8254, 0xa7 }, + { 0x8255, 0xff }, + { 0x8256, 0xed }, + { 0x8257, 0x5b }, + { 0x8258, 0xae }, + { 0x8259, 0xe6 }, + { 0x825a, 0x3d }, + { 0x825b, 0x0f }, + { 0x825c, 0x0d }, + { 0x825d, 0xea }, + { 0x825e, 0xf2 }, + { 0x825f, 0x51 }, + { 0x8260, 0xf5 }, + { 0x8261, 0x06 }, + { 0x821a, 0x00 }, + { 0x8546, 0x40 }, + { 0x8210, 0x26 }, + { 0x8211, 0xf6 }, + { 0x8212, 0x84 }, + { 0x8213, 0x02 }, + { 0x8502, 0x01 }, + { 0x8121, 0x04 }, + { 0x8122, 0x04 }, + { 0x852e, 0x10 }, + { 0x80a4, 0xca }, + { 0x80a7, 0x40 }, + { 0x8526, 0x01 }, +}; + static int au8522_enable_modulation(struct dvb_frontend *fe, fe_modulation_t m) { struct au8522_state *state = fe->demodulator_priv; + int i; dprintk("%s(0x%08x)\n", __func__, m); switch(m) { case VSB_8: dprintk("%s() VSB_8\n", __func__); - - //au8522_writereg(state, 0x410b, 0x84); // Serial - - //au8522_writereg(state, 0x8090, 0x82); - au8522_writereg(state, 0x8090, 0x84); - au8522_writereg(state, 0x4092, 0x11); - au8522_writereg(state, 0x2005, 0x00); - au8522_writereg(state, 0x8091, 0x80); - - au8522_writereg(state, 0x80a3, 0x0c); - au8522_writereg(state, 0x80a4, 0xe8); - au8522_writereg(state, 0x8081, 0xc4); - au8522_writereg(state, 0x80a5, 0x40); - au8522_writereg(state, 0x80a7, 0x40); - au8522_writereg(state, 0x80a6, 0x67); - au8522_writereg(state, 0x8262, 0x20); - au8522_writereg(state, 0x821c, 0x30); - au8522_writereg(state, 0x80d8, 0x1a); - au8522_writereg(state, 0x8227, 0xa0); - au8522_writereg(state, 0x8121, 0xff); - au8522_writereg(state, 0x80a8, 0xf0); - au8522_writereg(state, 0x80a9, 0x05); - au8522_writereg(state, 0x80aa, 0x77); - au8522_writereg(state, 0x80ab, 0xf0); - au8522_writereg(state, 0x80ac, 0x05); - au8522_writereg(state, 0x80ad, 0x77); - au8522_writereg(state, 0x80ae, 0x41); - au8522_writereg(state, 0x80af, 0x66); - au8522_writereg(state, 0x821b, 0xcc); - au8522_writereg(state, 0x821d, 0x80); - au8522_writereg(state, 0x80b5, 0xfb); - au8522_writereg(state, 0x80b6, 0x8e); - au8522_writereg(state, 0x80b7, 0x39); - au8522_writereg(state, 0x80a4, 0xe8); - au8522_writereg(state, 0x8231, 0x13); + for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++) + au8522_writereg(state, + VSB_mod_tab[i].reg, + VSB_mod_tab[i].data); break; case QAM_64: case QAM_256: - au8522_writereg(state, 0x80a3, 0x09); - au8522_writereg(state, 0x80a4, 0x00); - au8522_writereg(state, 0x8081, 0xc4); - au8522_writereg(state, 0x80a5, 0x40); - au8522_writereg(state, 0x80b5, 0xfb); - au8522_writereg(state, 0x80b6, 0x8e); - au8522_writereg(state, 0x80b7, 0x39); - au8522_writereg(state, 0x80aa, 0x77); - au8522_writereg(state, 0x80ad, 0x77); - au8522_writereg(state, 0x80a6, 0x67); - au8522_writereg(state, 0x8262, 0x20); - au8522_writereg(state, 0x821c, 0x30); - au8522_writereg(state, 0x80b8, 0x3e); - au8522_writereg(state, 0x80b9, 0xf0); - au8522_writereg(state, 0x80ba, 0x01); - au8522_writereg(state, 0x80bb, 0x18); - au8522_writereg(state, 0x80bc, 0x50); - au8522_writereg(state, 0x80bd, 0x00); - au8522_writereg(state, 0x80be, 0xea); - au8522_writereg(state, 0x80bf, 0xef); - au8522_writereg(state, 0x80c0, 0xfc); - au8522_writereg(state, 0x80c1, 0xbd); - au8522_writereg(state, 0x80c2, 0x1f); - au8522_writereg(state, 0x80c3, 0xfc); - au8522_writereg(state, 0x80c4, 0xdd); - au8522_writereg(state, 0x80c5, 0xaf); - au8522_writereg(state, 0x80c6, 0x00); - au8522_writereg(state, 0x80c7, 0x38); - au8522_writereg(state, 0x80c8, 0x30); - au8522_writereg(state, 0x80c9, 0x05); - au8522_writereg(state, 0x80ca, 0x4a); - au8522_writereg(state, 0x80cb, 0xd0); - au8522_writereg(state, 0x80cc, 0x01); - au8522_writereg(state, 0x80cd, 0xd9); - au8522_writereg(state, 0x80ce, 0x6f); - au8522_writereg(state, 0x80cf, 0xf9); - au8522_writereg(state, 0x80d0, 0x70); - au8522_writereg(state, 0x80d1, 0xdf); - au8522_writereg(state, 0x80d2, 0xf7); - au8522_writereg(state, 0x80d3, 0xc2); - au8522_writereg(state, 0x80d4, 0xdf); - au8522_writereg(state, 0x80d5, 0x02); - au8522_writereg(state, 0x80d6, 0x9a); - au8522_writereg(state, 0x80d7, 0xd0); - au8522_writereg(state, 0x8250, 0x0d); - au8522_writereg(state, 0x8251, 0xcd); - au8522_writereg(state, 0x8252, 0xe0); - au8522_writereg(state, 0x8253, 0x05); - au8522_writereg(state, 0x8254, 0xa7); - au8522_writereg(state, 0x8255, 0xff); - au8522_writereg(state, 0x8256, 0xed); - au8522_writereg(state, 0x8257, 0x5b); - au8522_writereg(state, 0x8258, 0xae); - au8522_writereg(state, 0x8259, 0xe6); - au8522_writereg(state, 0x825a, 0x3d); - au8522_writereg(state, 0x825b, 0x0f); - au8522_writereg(state, 0x825c, 0x0d); - au8522_writereg(state, 0x825d, 0xea); - au8522_writereg(state, 0x825e, 0xf2); - au8522_writereg(state, 0x825f, 0x51); - au8522_writereg(state, 0x8260, 0xf5); - au8522_writereg(state, 0x8261, 0x06); - au8522_writereg(state, 0x821a, 0x00); - au8522_writereg(state, 0x8546, 0x40); - au8522_writereg(state, 0x8210, 0x26); - au8522_writereg(state, 0x8211, 0xf6); - au8522_writereg(state, 0x8212, 0x84); - au8522_writereg(state, 0x8213, 0x02); - au8522_writereg(state, 0x8502, 0x01); - au8522_writereg(state, 0x8121, 0x04); - au8522_writereg(state, 0x8122, 0x04); - au8522_writereg(state, 0x852e, 0x10); - au8522_writereg(state, 0x80a4, 0xca); - au8522_writereg(state, 0x80a7, 0x40); - au8522_writereg(state, 0x8526, 0x01); + dprintk("%s() QAM 64/256\n", __func__); + for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++) + au8522_writereg(state, + QAM_mod_tab[i].reg, + QAM_mod_tab[i].data); break; default: dprintk("%s() Invalid modulation\n", __func__); @@ -321,30 +580,24 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) return 0; } -static int au8522_read_mse(struct dvb_frontend *fe) -{ - struct au8522_state *state = fe->demodulator_priv; - int mse = 0; - - if (state->current_modulation == VSB_8) - mse = au8522_readreg(state, 0x4311); - else - mse = au8522_readreg(state, 0x4522); - - dprintk("%s: %d\n", __func__, mse); - - return mse; -} - static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) { + struct au8522_state *state = fe->demodulator_priv; + int ret = -EINVAL; + dprintk("%s()\n", __func__); - /* FIXME: This is mse, not snr - * TODO: mse2snr */ - *snr = au8522_read_mse(fe); + if (state->current_modulation == QAM_256) + ret = au8522_qam256_mse2snr_lookup( + au8522_readreg(state, 0x4522), snr); + else if (state->current_modulation == QAM_64) + ret = au8522_qam64_mse2snr_lookup( + au8522_readreg(state, 0x4522), snr); + else /* VSB_8 */ + ret = au8522_vsb_mse2snr_lookup( + au8522_readreg(state, 0x4311), snr); - return 0; + return ret; } static int au8522_read_signal_strength(struct dvb_frontend *fe, From 0daa5de740c65de7c9554071eec84c6731370065 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 10 Apr 2008 04:24:56 -0300 Subject: [PATCH 362/452] V4L/DVB (7633): au8522: consolidate mse2snr_lookup functions consolidate au8522_qam256_mse2snr_lookup, au8522_qam64_mse2snr_lookup and au8522_vsb_mse2snr_lookup into a single function, au8522_mse2snr_lookup. Pass the mse2snr table into au8522_mse2snr_lookup depending on the modulation type. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 76 +++++++++------------------- 1 file changed, 23 insertions(+), 53 deletions(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index fa3e6abdfa6e..394fb90bdcb0 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -96,11 +96,13 @@ static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) return au8522_writereg(state, 0x106, 0); } -/* VSB SNR lookup table */ -static struct { +struct mse2snr_tab { u16 val; u16 data; -} vsb_mse2snr_tab[] = { +}; + +/* VSB SNR lookup table */ +static struct mse2snr_tab vsb_mse2snr_tab[] = { { 0, 270 }, { 2, 250 }, { 3, 240 }, @@ -134,10 +136,7 @@ static struct { }; /* QAM64 SNR lookup table */ -static struct { - u16 val; - u16 data; -} qam64_mse2snr_tab[] = { +static struct mse2snr_tab qam64_mse2snr_tab[] = { { 15, 0 }, { 16, 290 }, { 17, 288 }, @@ -218,10 +217,7 @@ static struct { }; /* QAM256 SNR lookup table */ -static struct { - u16 val; - u16 data; -} qam256_mse2snr_tab[] = { +static struct mse2snr_tab qam256_mse2snr_tab[] = { { 16, 0 }, { 17, 400 }, { 18, 398 }, @@ -288,46 +284,14 @@ static struct { { 256, 280 }, }; -static int au8522_vsb_mse2snr_lookup(int mse, u16 *snr) +static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse, u16 *snr) { int i, ret = -EINVAL; dprintk("%s()\n", __func__); - for (i = 0; i < ARRAY_SIZE(vsb_mse2snr_tab); i++) { - if (mse < vsb_mse2snr_tab[i].val) { - *snr = vsb_mse2snr_tab[i].data; - ret = 0; - break; - } - } - dprintk("%s() snr=%d\n", __func__, *snr); - return ret; -} - -static int au8522_qam64_mse2snr_lookup(int mse, u16 *snr) -{ - int i, ret = -EINVAL; - dprintk("%s()\n", __func__); - - for (i = 0; i < ARRAY_SIZE(qam64_mse2snr_tab); i++) { - if (mse < qam64_mse2snr_tab[i].val) { - *snr = qam64_mse2snr_tab[i].data; - ret = 0; - break; - } - } - dprintk("%s() snr=%d\n", __func__, *snr); - return ret; -} - -static int au8522_qam256_mse2snr_lookup(int mse, u16 *snr) -{ - int i, ret = -EINVAL; - dprintk("%s()\n", __func__); - - for (i = 0; i < ARRAY_SIZE(qam256_mse2snr_tab); i++) { - if (mse < qam256_mse2snr_tab[i].val) { - *snr = qam256_mse2snr_tab[i].data; + for (i = 0; i < sz; i++) { + if (mse < tab[i].val) { + *snr = tab[i].data; ret = 0; break; } @@ -588,14 +552,20 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) dprintk("%s()\n", __func__); if (state->current_modulation == QAM_256) - ret = au8522_qam256_mse2snr_lookup( - au8522_readreg(state, 0x4522), snr); + ret = au8522_mse2snr_lookup(qam256_mse2snr_tab, + ARRAY_SIZE(qam256_mse2snr_tab), + au8522_readreg(state, 0x4522), + snr); else if (state->current_modulation == QAM_64) - ret = au8522_qam64_mse2snr_lookup( - au8522_readreg(state, 0x4522), snr); + ret = au8522_mse2snr_lookup(qam64_mse2snr_tab, + ARRAY_SIZE(qam64_mse2snr_tab), + au8522_readreg(state, 0x4522), + snr); else /* VSB_8 */ - ret = au8522_vsb_mse2snr_lookup( - au8522_readreg(state, 0x4311), snr); + ret = au8522_mse2snr_lookup(vsb_mse2snr_tab, + ARRAY_SIZE(vsb_mse2snr_tab), + au8522_readreg(state, 0x4311), + snr); return ret; } From a9c36aad59a06df199cdbb365d0b05663f8008f1 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 17 Apr 2008 21:41:28 -0300 Subject: [PATCH 363/452] V4L/DVB (7634): au0828: Cleanup au0828: Cleanup Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 8 +++----- drivers/media/video/au0828/au0828-core.c | 11 ++++++----- drivers/media/video/au0828/au0828-dvb.c | 12 ++++++------ drivers/media/video/au0828/au0828-i2c.c | 6 +++--- drivers/media/video/au0828/au0828-reg.h | 3 +++ drivers/media/video/au0828/au0828.h | 1 - 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 5c9c3aea99d4..f6c6228b6672 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -51,7 +51,7 @@ int au0828_tuner_callback(void *priv, int command, int arg) case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_DVICO_FUSIONHDTV7: - if(command == 0) { + if (command == 0) { /* Tuner Reset Command from xc5000 */ /* Drive the tuner into reset and out */ au0828_clear(dev, REG_001, 2); @@ -78,8 +78,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); /* Make sure we support the board model */ - switch (tv.model) - { + switch (tv.model) { case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ break; default: @@ -92,7 +91,6 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) __func__, tv.model); } - void au0828_card_setup(struct au0828_dev *dev) { static u8 eeprom[256]; @@ -116,7 +114,7 @@ void au0828_card_setup(struct au0828_dev *dev) /* * The bridge has between 8 and 12 gpios. * Regs 1 and 0 deal with output enables. - * Regs 3 and 2 * deal with direction. + * Regs 3 and 2 deal with direction. */ void au0828_gpio_setup(struct au0828_dev *dev) { diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index efecac3979ae..530c675e53a4 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -143,6 +143,7 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, mutex_unlock(&dev->mutex); return status; } + static void au0828_usb_disconnect(struct usb_interface *interface) { struct au0828_dev *dev = usb_get_intfdata(interface); @@ -177,7 +178,7 @@ static int au0828_usb_probe (struct usb_interface *interface, if (ifnum != 0) return -ENODEV; - dprintk(1,"%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, + dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, le16_to_cpu(usbdev->descriptor.idVendor), le16_to_cpu(usbdev->descriptor.idProduct), ifnum); @@ -228,20 +229,20 @@ static int __init au0828_init(void) { int ret; - if(debug) + if (debug) printk(KERN_INFO "%s() Debugging is enabled\n", __func__); - if(usb_debug) { + if (usb_debug) { printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__); debug |= 2; } - if(i2c_debug) { + if (i2c_debug) { printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__); debug |= 4; } - if(bridge_debug) { + if (bridge_debug) { printk(KERN_INFO "%s() Bridge Debugging is enabled\n", __func__); debug |= 8; diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 8853f4e26092..4a27e5b41f53 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -31,6 +31,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +#define _AU0828_BULKPIPE 0x83 +#define _BULKPIPESIZE 0xe522 + static struct au8522_config hauppauge_hvr950q_config = { .demod_address = 0x8e >> 1, .status_mode = AU8522_DEMODLOCKING, @@ -66,7 +69,8 @@ static void urb_completion(struct urb *purb) ptr = (u8 *)purb->transfer_buffer; /* Feed the transport payload into the kernel demux */ - dvb_dmx_swfilter_packets(&dev->dvb.demux, purb->transfer_buffer, purb->actual_length / 188); + dvb_dmx_swfilter_packets(&dev->dvb.demux, + purb->transfer_buffer, purb->actual_length / 188); /* Clean the buffer before we requeue */ memset(purb->transfer_buffer, 0, URB_BUFSIZE); @@ -81,7 +85,6 @@ static int stop_urb_transfer(struct au0828_dev *dev) dprintk(2, "%s()\n", __func__); - /* FIXME: Do we need to free the transfer_buffers? */ for (i = 0; i < URB_COUNT; i++) { usb_kill_urb(dev->urbs[i]); kfree(dev->urbs[i]->transfer_buffer); @@ -93,9 +96,6 @@ static int stop_urb_transfer(struct au0828_dev *dev) return 0; } -#define _AU0828_BULKPIPE 0x83 -#define _BULKPIPESIZE 0xe522 - static int start_urb_transfer(struct au0828_dev *dev) { struct urb *purb; @@ -306,7 +306,7 @@ void au0828_dvb_unregister(struct au0828_dev *dev) dprintk(1, "%s()\n", __func__); - if(dvb->frontend == NULL) + if (dvb->frontend == NULL) return; dvb_net_release(&dvb->net); diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index c1e1cf6ed95a..ae73a6769296 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -151,7 +151,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, dprintk(4, "SEND: %02x\n", msg->addr); - for (i=0; i < msg->len;) { + for (i = 0; i < msg->len;) { dprintk(4, " %02x\n", msg->buf[i]); @@ -210,7 +210,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, return 0; } - for (i=0; i < msg->len;) { + for (i = 0; i < msg->len;) { i++; @@ -241,7 +241,7 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, dprintk(4, "%s(num = %d)\n", __func__, num); - for (i = 0 ; i < num; i++) { + for (i = 0; i < num; i++) { dprintk(4, "%s(num = %d) addr = 0x%02x len = 0x%x\n", __func__, num, msgs[i].addr, msgs[i].len); if (msgs[i].flags & I2C_M_RD) { diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h index c501f6a52af3..39827550891c 100644 --- a/drivers/media/video/au0828/au0828-reg.h +++ b/drivers/media/video/au0828/au0828-reg.h @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* We'll start to rename these registers once we have a better + * understanding of their meaning. + */ #define REG_000 0x000 #define REG_001 0x001 #define REG_002 0x002 diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 94426770a6df..7e6aeb727baa 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -37,7 +37,6 @@ #define DRIVER_NAME "au0828" #define URB_COUNT 16 -//#define URB_BUFSIZE (312 * 188) #define URB_BUFSIZE (0xe522) struct au0828_board { From 37be1ea40e42c0de63cedbe65d35cbe6c2a81c0a Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 17 Apr 2008 21:45:08 -0300 Subject: [PATCH 364/452] V4L/DVB (7635): au8522: Cleanup au8522: Cleanup Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index 394fb90bdcb0..dbea1da79672 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -501,7 +501,6 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) if (state->current_modulation == VSB_8) { dprintk("%s() Checking VSB_8\n", __func__); - //au8522_writereg(state, 0x80a4, 0x20); reg = au8522_readreg(state, 0x4088); if (reg & 0x01) *status |= FE_HAS_VITERBI; From 805caff5a83679a6be6c90787462cb3e4b58e374 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 17 Apr 2008 21:47:11 -0300 Subject: [PATCH 365/452] V4L/DVB (7636): au0828: Add HVR850 model number au0828: Add HVR850 model number Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index f6c6228b6672..688cb8d26b30 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -80,6 +80,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) /* Make sure we support the board model */ switch (tv.model) { case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ + case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ break; default: printk(KERN_WARNING "%s: warning: " From bbdf855b0e98ba576b3577522af5e5c7503c4ed0 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 17 Apr 2008 22:30:22 -0300 Subject: [PATCH 366/452] V4L/DVB (7637): au0828: Typo au0828: Typo Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index 1a7c8f77f1ce..c97c4bd24841 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -9,4 +9,4 @@ config VIDEO_AU0828 This is a video4linux driver for Auvitek's USB device. To compile this driver as a module, choose M here: the - module will be called ambarella + module will be called au0828 From 18d73c58b5ea7425db05b666408f6f682d837b73 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 18 Apr 2008 22:12:52 -0300 Subject: [PATCH 367/452] V4L/DVB (7638): CodingStyle fixes for au8522 and au0828 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 29 ++++++++++++----------- drivers/media/dvb/frontends/au8522.h | 6 ++--- drivers/media/video/au0828/au0828-cards.c | 9 ++++--- drivers/media/video/au0828/au0828-core.c | 20 ++++++++-------- drivers/media/video/au0828/au0828-dvb.c | 3 +-- drivers/media/video/au0828/au0828-i2c.c | 18 +++++++------- drivers/media/video/au0828/au0828.h | 13 +++++----- 7 files changed, 49 insertions(+), 49 deletions(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index dbea1da79672..e340faacc78b 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -43,8 +43,12 @@ struct au8522_state { }; -static int debug = 0; -#define dprintk if (debug) printk +static int debug; + +#define dprintk(arg...) do { \ + if (debug) \ + printk(##arg); } \ + } while (0) /* 16 bit registers, 8 bit values */ static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) @@ -284,7 +288,8 @@ static struct mse2snr_tab qam256_mse2snr_tab[] = { { 256, 280 }, }; -static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse, u16 *snr) +static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse, + u16 *snr) { int i, ret = -EINVAL; dprintk("%s()\n", __func__); @@ -427,7 +432,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, dprintk("%s(0x%08x)\n", __func__, m); - switch(m) { + switch (m) { case VSB_8: dprintk("%s() VSB_8\n", __func__); for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++) @@ -469,9 +474,11 @@ static int au8522_set_frontend(struct dvb_frontend *fe, msleep(100); if (fe->ops.tuner_ops.set_params) { - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.tuner_ops.set_params(fe, p); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } return 0; @@ -515,7 +522,7 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) *status |= FE_HAS_LOCK | FE_HAS_SYNC; } - switch(state->config->status_mode) { + switch (state->config->status_mode) { case AU8522_DEMODLOCKING: dprintk("%s() DEMODLOCKING\n", __func__); if (*status & FE_HAS_VITERBI) @@ -651,6 +658,7 @@ error: kfree(state); return NULL; } +EXPORT_SYMBOL(au8522_attach); static struct dvb_frontend_ops au8522_ops = { @@ -682,10 +690,3 @@ MODULE_PARM_DESC(debug, "Enable verbose debug messages"); MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(au8522_attach); - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h index 19d5d1ef9842..d7affa3cdb27 100644 --- a/drivers/media/dvb/frontends/au8522.h +++ b/drivers/media/dvb/frontends/au8522.h @@ -24,8 +24,7 @@ #include -struct au8522_config -{ +struct au8522_config { /* the demodulator's i2c address */ u8 demod_address; @@ -35,7 +34,8 @@ struct au8522_config u8 status_mode; }; -#if defined(CONFIG_DVB_AU8522) || (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE)) +#if defined(CONFIG_DVB_AU8522) || \ + (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE)) extern struct dvb_frontend *au8522_attach(const struct au8522_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 688cb8d26b30..8ca91f814277 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -47,7 +47,7 @@ int au0828_tuner_callback(void *priv, int command, int arg) dprintk(1, "%s()\n", __func__); - switch(dev->board) { + switch (dev->board) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_DVICO_FUSIONHDTV7: @@ -59,8 +59,7 @@ int au0828_tuner_callback(void *priv, int command, int arg) au0828_set(dev, REG_001, 2); mdelay(50); return 0; - } - else { + } else { printk(KERN_ERR "%s(): Unknown command.\n", __func__); return -EINVAL; @@ -103,7 +102,7 @@ void au0828_card_setup(struct au0828_dev *dev) tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); } - switch(dev->board) { + switch (dev->board) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: if (dev->i2c_rc == 0) @@ -121,7 +120,7 @@ void au0828_gpio_setup(struct au0828_dev *dev) { dprintk(1, "%s()\n", __func__); - switch(dev->board) { + switch (dev->board) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: /* GPIO's diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 530c675e53a4..e65d5642cb1d 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -32,15 +32,15 @@ * 4 = I2C related * 8 = Bridge related */ -unsigned int debug = 0; +unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); -unsigned int usb_debug = 0; +unsigned int usb_debug; module_param(usb_debug, int, 0644); MODULE_PARM_DESC(usb_debug, "enable usb debug messages"); -unsigned int bridge_debug = 0; +unsigned int bridge_debug; module_param(bridge_debug, int, 0644); MODULE_PARM_DESC(bridge_debug, "enable bridge debug messages"); @@ -66,16 +66,17 @@ u32 au0828_readreg(struct au0828_dev *dev, u16 reg) u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) { dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val); - return send_control_msg(dev, CMD_REQUEST_OUT, val, reg, dev->ctrlmsg, 0); + return send_control_msg(dev, CMD_REQUEST_OUT, val, reg, + dev->ctrlmsg, 0); } static void cmd_msg_dump(struct au0828_dev *dev) { int i; - for (i = 0;i < sizeof(dev->ctrlmsg); i+=16) - dprintk(2,"%s() %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x\n", + for (i = 0; i < sizeof(dev->ctrlmsg); i += 16) + dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", __func__, dev->ctrlmsg[i+0], dev->ctrlmsg[i+1], dev->ctrlmsg[i+2], dev->ctrlmsg[i+3], @@ -136,8 +137,7 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, if (status < 0) { printk(KERN_ERR "%s() Failed receiving control message, error %d.\n", __func__, status); - } - else + } else cmd_msg_dump(dev); } mutex_unlock(&dev->mutex); @@ -166,7 +166,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) } -static int au0828_usb_probe (struct usb_interface *interface, +static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { int ifnum; diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 4a27e5b41f53..85d0ae9a322f 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -111,9 +111,8 @@ static int start_urb_transfer(struct au0828_dev *dev) for (i = 0; i < URB_COUNT; i++) { dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->urbs[i]) { + if (!dev->urbs[i]) goto err; - } purb = dev->urbs[i]; diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index ae73a6769296..94c8b74a6651 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -23,17 +23,17 @@ #include #include #include -#include +#include #include "au0828.h" #include -unsigned int i2c_debug = 0; +unsigned int i2c_debug; module_param(i2c_debug, int, 0444); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -unsigned int i2c_scan = 0; +unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); @@ -323,9 +323,9 @@ static struct i2c_client au0828_i2c_client_template = { }; static char *i2c_devs[128] = { - [ 0x8e >> 1 ] = "au8522", - [ 0xa0 >> 1 ] = "eeprom", - [ 0xc2 >> 1 ] = "tuner/xc5000", + [0x8e >> 1] = "au8522", + [0xa0 >> 1] = "eeprom", + [0xc2 >> 1] = "tuner/xc5000", }; static void do_i2c_scan(char *name, struct i2c_client *c) @@ -338,7 +338,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) rc = i2c_master_recv(c, &buf, 0); if (rc < 0) continue; - printk("%s: i2c scan: found device @ 0x%x [%s]\n", + printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n", name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); } } @@ -368,11 +368,11 @@ int au0828_i2c_register(struct au0828_dev *dev) dev->i2c_client.adapter = &dev->i2c_adap; if (0 == dev->i2c_rc) { - printk("%s: i2c bus registered\n", DRIVER_NAME); + printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME); if (i2c_scan) do_i2c_scan(DRIVER_NAME, &dev->i2c_client); } else - printk("%s: i2c bus register FAILED\n", DRIVER_NAME); + printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME); return dev->i2c_rc; } diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 7e6aeb727baa..0200b9fc5dc4 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -83,13 +83,14 @@ struct au0828_buff { }; /* ----------------------------------------------------------- */ -#define au0828_read(dev,reg) au0828_readreg(dev,reg) -#define au0828_write(dev,reg,value) au0828_writereg(dev,reg,value) -#define au0828_andor(dev,reg,mask,value) \ - au0828_writereg(dev,reg,(au0828_readreg(dev,reg)&~(mask))|((value)&(mask))) +#define au0828_read(dev, reg) au0828_readreg(dev, reg) +#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value) +#define au0828_andor(dev, reg, mask, value) \ + au0828_writereg(dev, reg, \ + (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask))) -#define au0828_set(dev,reg,bit) au0828_andor(dev,(reg),(bit),(bit)) -#define au0828_clear(dev,reg,bit) au0828_andor(dev,(reg),(bit),0) +#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit)) +#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0) /* ----------------------------------------------------------- */ /* au0828-core.c */ From 353a2761ffb3c4f43ec0c9c99bbe64629646b347 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 18 Apr 2008 22:24:01 -0300 Subject: [PATCH 368/452] V4L/DVB (7639): au8522: fix a small bug introduced by Checkpatch cleanup Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index e340faacc78b..084a280c2d7f 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -47,7 +47,7 @@ static int debug; #define dprintk(arg...) do { \ if (debug) \ - printk(##arg); } \ + printk(arg); \ } while (0) /* 16 bit registers, 8 bit values */ From ce96d0a44a4f8d1bb3dc12b5e98cb688c1bc730d Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 17 Apr 2008 22:55:29 -0300 Subject: [PATCH 369/452] V4L/DVB (7641): V4L: ov511 - use usb_interface as parent, not usb_device The current code creates a bogus DEVPATH: /devices/pci0000:00/0000:00:1d.0/usb1/1-2/video4linux/video0 while it should be: /devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.0/video4linux/video0 Signed-off-by: Kay Sievers Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov511.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 48ee2d892396..eafb0c7736e6 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -5833,7 +5833,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) goto error; memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev)); - ov->vdev->dev = &dev->dev; + ov->vdev->dev = &intf->dev; video_set_drvdata(ov->vdev, ov); for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) { From 6b92b3bd7ac91b7e255541f4be9bfd55b12dae41 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 5 Apr 2008 16:45:57 -0300 Subject: [PATCH 370/452] V4L/DVB (7642): cx88: enable radio GPIO correctly cx88: enable radio GPIO correctly. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 0534f589c725..620159d05506 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1364,6 +1364,10 @@ static const struct cx88_board cx88_boards[] = { }}, /* fixme: Add radio support */ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0xe780, + }, }, [CX88_BOARD_ADSTECH_PTV_390] = { .name = "ADS Tech Instant Video PCI", From 7bbb1ce4f3e517666ad27f3307d49bb2da69ffec Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 19 Apr 2008 01:06:25 -0300 Subject: [PATCH 371/452] V4L/DVB (7644): Adding support for the NXP TDA10048HN DVB OFDM demodulator Adding support for the NXP TDA10048HN DVB OFDM demodulator Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 8 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/tda10048.c | 704 +++++++++++++++++++++++++ drivers/media/dvb/frontends/tda10048.h | 63 +++ 4 files changed, 776 insertions(+) create mode 100644 drivers/media/dvb/frontends/tda10048.c create mode 100644 drivers/media/dvb/frontends/tda10048.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index ae3659be323f..68fab616f55d 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -188,6 +188,14 @@ config DVB_DIB7000P A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. +config DVB_TDA10048 + tristate "Philips TDA10048HN based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + select FW_LOADER + help + A DVB-T tuner module. Say Y when you want to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 8e23a30ed3be..2f873fc0f649 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -54,3 +54,4 @@ obj-$(CONFIG_DVB_S5H1409) += s5h1409.o obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o obj-$(CONFIG_DVB_AU8522) += au8522.o +obj-$(CONFIG_DVB_TDA10048) += tda10048.o diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c new file mode 100644 index 000000000000..701dd02b0d07 --- /dev/null +++ b/drivers/media/dvb/frontends/tda10048.c @@ -0,0 +1,704 @@ +/* + NXP TDA10048HN DVB OFDM demodulator driver + + Copyright (C) 2008 Steven Toth + + 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 +#include +#include +#include +#include +#include "dvb_frontend.h" +#include "tda10048.h" + +#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw" +#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878 + +/* Register name definitions */ +#define TDA10048_IDENTITY 0x00 +#define TDA10048_VERSION 0x01 +#define TDA10048_DSP_CODE_CPT 0x0C +#define TDA10048_DSP_CODE_IN 0x0E +#define TDA10048_IN_CONF1 0x10 +#define TDA10048_IN_CONF2 0x11 +#define TDA10048_IN_CONF3 0x12 +#define TDA10048_OUT_CONF1 0x14 +#define TDA10048_OUT_CONF2 0x15 +#define TDA10048_OUT_CONF3 0x16 +#define TDA10048_AUTO 0x18 +#define TDA10048_SYNC_STATUS 0x1A +#define TDA10048_CONF_C4_1 0x1E +#define TDA10048_CONF_C4_2 0x1F +#define TDA10048_CODE_IN_RAM 0x20 +#define TDA10048_CHANNEL_INFO_1_R 0x22 +#define TDA10048_CHANNEL_INFO_2_R 0x23 +#define TDA10048_CHANNEL_INFO1 0x24 +#define TDA10048_CHANNEL_INFO2 0x25 +#define TDA10048_TIME_ERROR_R 0x26 +#define TDA10048_TIME_ERROR 0x27 +#define TDA10048_FREQ_ERROR_LSB_R 0x28 +#define TDA10048_FREQ_ERROR_MSB_R 0x29 +#define TDA10048_FREQ_ERROR_LSB 0x2A +#define TDA10048_FREQ_ERROR_MSB 0x2B +#define TDA10048_IT_SEL 0x30 +#define TDA10048_IT_STAT 0x32 +#define TDA10048_DSP_AD_LSB 0x3C +#define TDA10048_DSP_AD_MSB 0x3D +#define TDA10048_DSP_REF_LSB 0x3E +#define TDA10048_DSP_REF_MSB 0x3F +#define TDA10048_CONF_TRISTATE1 0x44 +#define TDA10048_CONF_TRISTATE2 0x45 +#define TDA10048_CONF_POLARITY 0x46 +#define TDA10048_GPIO_SP_DS0 0x48 +#define TDA10048_GPIO_SP_DS1 0x49 +#define TDA10048_GPIO_SP_DS2 0x4A +#define TDA10048_GPIO_SP_DS3 0x4B +#define TDA10048_GPIO_OUT_SEL 0x4C +#define TDA10048_GPIO_SELECT 0x4D +#define TDA10048_IC_MODE 0x4E +#define TDA10048_CONF_XO 0x50 +#define TDA10048_CONF_PLL1 0x51 +#define TDA10048_CONF_PLL2 0x52 +#define TDA10048_CONF_PLL3 0x53 +#define TDA10048_CONF_ADC 0x54 +#define TDA10048_CONF_ADC_2 0x55 +#define TDA10048_CONF_C1_1 0x60 +#define TDA10048_CONF_C1_3 0x62 +#define TDA10048_AGC_CONF 0x70 +#define TDA10048_AGC_THRESHOLD_LSB 0x72 +#define TDA10048_AGC_THRESHOLD_MSB 0x73 +#define TDA10048_AGC_RENORM 0x74 +#define TDA10048_AGC_GAINS 0x76 +#define TDA10048_AGC_TUN_MIN 0x78 +#define TDA10048_AGC_TUN_MAX 0x79 +#define TDA10048_AGC_IF_MIN 0x7A +#define TDA10048_AGC_IF_MAX 0x7B +#define TDA10048_AGC_TUN_LEVEL 0x7E +#define TDA10048_AGC_IF_LEVEL 0x7F +#define TDA10048_DIG_AGC_LEVEL 0x81 +#define TDA10048_FREQ_PHY2_LSB 0x86 +#define TDA10048_FREQ_PHY2_MSB 0x87 +#define TDA10048_TIME_INVWREF_LSB 0x88 +#define TDA10048_TIME_INVWREF_MSB 0x89 +#define TDA10048_TIME_WREF_LSB 0x8A +#define TDA10048_TIME_WREF_MID1 0x8B +#define TDA10048_TIME_WREF_MID2 0x8C +#define TDA10048_TIME_WREF_MSB 0x8D +#define TDA10048_NP_OUT 0xA2 +#define TDA10048_CELL_ID_LSB 0xA4 +#define TDA10048_CELL_ID_MSB 0xA5 +#define TDA10048_EXTTPS_ODD 0xAA +#define TDA10048_EXTTPS_EVEN 0xAB +#define TDA10048_TPS_LENGTH 0xAC +#define TDA10048_FREE_REG_1 0xB2 +#define TDA10048_FREE_REG_2 0xB3 +#define TDA10048_CONF_C3_1 0xC0 +#define TDA10048_CYBER_CTRL 0xC2 +#define TDA10048_CBER_NMAX_LSB 0xC4 +#define TDA10048_CBER_NMAX_MSB 0xC5 +#define TDA10048_CBER_LSB 0xC6 +#define TDA10048_CBER_MSB 0xC7 +#define TDA10048_VBER_LSB 0xC8 +#define TDA10048_VBER_MID 0xC9 +#define TDA10048_VBER_MSB 0xCA +#define TDA10048_CYBER_LUT 0xCC +#define TDA10048_UNCOR_CTRL 0xCD +#define TDA10048_UNCOR_CPT_LSB 0xCE +#define TDA10048_UNCOR_CPT_MSB 0xCF +#define TDA10048_SOFT_IT_C3 0xD6 +#define TDA10048_CONF_TS2 0xE0 +#define TDA10048_CONF_TS1 0xE1 + +static unsigned int debug; + +#define dprintk(level, fmt, arg...)\ + do { if (debug >= level)\ + printk(KERN_DEBUG "tda10048: " fmt, ## arg);\ + } while (0) + +struct tda10048_state { + + struct i2c_adapter *i2c; + + /* configuration settings */ + const struct tda10048_config *config; + struct dvb_frontend frontend; + + int fwloaded; +}; + +static struct init_tab { + u8 reg; + u16 data; +} init_tab[] = { + { TDA10048_CONF_PLL1, 0x08 }, + { TDA10048_CONF_ADC_2, 0x00 }, + { TDA10048_CONF_C4_1, 0x00 }, + { TDA10048_CONF_PLL1, 0x0f }, + { TDA10048_CONF_PLL2, 0x0a }, + { TDA10048_CONF_PLL3, 0x43 }, + { TDA10048_FREQ_PHY2_LSB, 0x02 }, + { TDA10048_FREQ_PHY2_MSB, 0x0a }, + { TDA10048_TIME_WREF_LSB, 0xbd }, + { TDA10048_TIME_WREF_MID1, 0xe4 }, + { TDA10048_TIME_WREF_MID2, 0xa8 }, + { TDA10048_TIME_WREF_MSB, 0x02 }, + { TDA10048_TIME_INVWREF_LSB, 0x04 }, + { TDA10048_TIME_INVWREF_MSB, 0x06 }, + { TDA10048_CONF_C4_1, 0x00 }, + { TDA10048_CONF_C1_1, 0xa8 }, + { TDA10048_AGC_CONF, 0x16 }, + { TDA10048_CONF_C1_3, 0x0b }, + { TDA10048_AGC_TUN_MIN, 0x00 }, + { TDA10048_AGC_TUN_MAX, 0xff }, + { TDA10048_AGC_IF_MIN, 0x00 }, + { TDA10048_AGC_IF_MAX, 0xff }, + { TDA10048_AGC_THRESHOLD_MSB, 0x00 }, + { TDA10048_AGC_THRESHOLD_LSB, 0x70 }, + { TDA10048_CYBER_CTRL, 0x38 }, + { TDA10048_AGC_GAINS, 0x12 }, + { TDA10048_CONF_XO, 0x00 }, + { TDA10048_CONF_TS1, 0x07 }, + { TDA10048_IC_MODE, 0x00 }, + { TDA10048_CONF_TS2, 0xc0 }, + { TDA10048_CONF_TRISTATE1, 0x21 }, + { TDA10048_CONF_TRISTATE2, 0x00 }, + { TDA10048_CONF_POLARITY, 0x00 }, + { TDA10048_CONF_C4_2, 0x04 }, + { TDA10048_CONF_ADC, 0x60 }, + { TDA10048_CONF_ADC_2, 0x10 }, + { TDA10048_CONF_ADC, 0x60 }, + { TDA10048_CONF_ADC_2, 0x00 }, + { TDA10048_CONF_C1_1, 0xa8 }, + { TDA10048_UNCOR_CTRL, 0x00 }, + { TDA10048_CONF_C4_2, 0x04 }, +}; + +static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) +{ + int ret; + u8 buf [] = { reg, data }; + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, .buf = buf, .len = 2 }; + + dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data); + + ret = i2c_transfer(state->i2c, &msg, 1); + + if (ret != 1) + printk("%s: writereg error (ret == %i)\n", __func__, ret); + + return (ret != 1) ? -1 : 0; +} + +static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) +{ + int ret; + u8 b0 [] = { reg }; + u8 b1 [] = { 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 } }; + + dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg); + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) + printk(KERN_ERR "%s: readreg error (ret == %i)\n", + __func__, ret); + + return b1[0]; +} + +static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, + u8 *data, u16 len) +{ + int ret = -EREMOTEIO; + struct i2c_msg msg; + u8 *buf; + + dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len); + + buf = kmalloc(len + 1, GFP_KERNEL); + if (buf == NULL) { + ret = -ENOMEM; + goto error; + } + + *buf = reg; + memcpy(buf + 1, data, len); + + msg.addr = state->config->demod_address; + msg.flags = 0; + msg.buf = buf; + msg.len = len + 1; + + dprintk(2, "%s(): write len = %d\n", + __func__, msg.len); + + ret = i2c_transfer(state->i2c, &msg, 1); + if (ret != 1) { + printk(KERN_ERR "%s(): writereg error err %i\n", + __func__, ret); + ret = -EREMOTEIO; + } + +error: + kfree(buf); + + return ret; +} + +static int tda10048_firmware_upload(struct dvb_frontend *fe) +{ + struct tda10048_state *state = fe->demodulator_priv; + const struct firmware *fw; + int ret; + int pos = 0; + int cnt; + u8 wlen = state->config->fwbulkwritelen; + + if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50)) + wlen = TDA10048_BULKWRITE_200; + + /* request the firmware, this will block and timeout */ + printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n", + __func__, + TDA10048_DEFAULT_FIRMWARE); + + ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE, + &state->i2c->dev); + if (ret) { + printk(KERN_ERR "%s: Upload failed. (file not found?)\n", + __func__); + return -EIO; + } else { + printk(KERN_INFO "%s: firmware read %Zu bytes.\n", + __func__, + fw->size); + ret = 0; + } + + if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) { + printk(KERN_ERR "%s: firmware incorrect size\n", __func__); + return -EIO; + } else { + printk(KERN_INFO "%s: firmware uploading\n", __func__); + + /* Soft reset */ + tda10048_writereg(state, TDA10048_CONF_TRISTATE1, + tda10048_readreg(state, TDA10048_CONF_TRISTATE1) + & 0xfe); + tda10048_writereg(state, TDA10048_CONF_TRISTATE1, + tda10048_readreg(state, TDA10048_CONF_TRISTATE1) + | 0x01); + + /* Put the demod into host download mode */ + tda10048_writereg(state, TDA10048_CONF_C4_1, + tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9); + + /* Boot the DSP */ + tda10048_writereg(state, TDA10048_CONF_C4_1, + tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08); + + /* Prepare for download */ + tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0); + + /* Download the firmware payload */ + while (pos < fw->size) { + + if ((fw->size - pos) > wlen) + cnt = wlen; + else + cnt = fw->size - pos; + + tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN, + &fw->data[pos], cnt); + + pos += cnt; + } + + ret = -EIO; + /* Wait up to 250ms for the DSP to boot */ + for (cnt = 0; cnt < 250 ; cnt += 10) { + + msleep(10); + + if (tda10048_readreg(state, TDA10048_SYNC_STATUS) + & 0x40) { + ret = 0; + break; + } + } + } + + release_firmware(fw); + + if (ret == 0) { + printk(KERN_INFO "%s: firmware uploaded\n", __func__); + state->fwloaded = 1; + } else + printk(KERN_ERR "%s: firmware upload failed\n", __func__); + + return ret; +} + +static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion) +{ + struct tda10048_state *state = fe->demodulator_priv; + + dprintk(1, "%s(%d)\n", __func__, inversion); + + if (inversion == TDA10048_INVERSION_ON) + tda10048_writereg(state, TDA10048_CONF_C1_1, + tda10048_readreg(state, TDA10048_CONF_C1_1) | 0x20); + else + tda10048_writereg(state, TDA10048_CONF_C1_1, + tda10048_readreg(state, TDA10048_CONF_C1_1) & 0xdf); + + return 0; +} + +/* Retrieve the demod settings */ +static int tda10048_get_tps(struct tda10048_state *state, + struct dvb_ofdm_parameters *p) +{ + u8 val; + + /* Make sure the TPS regs are valid */ + if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01)) + return -EAGAIN; + + val = tda10048_readreg(state, TDA10048_OUT_CONF2); + switch ((val & 0x60) >> 5) { + case 0: p->constellation = QPSK; break; + case 1: p->constellation = QAM_16; break; + case 2: p->constellation = QAM_64; break; + } + switch ((val & 0x18) >> 3) { + case 0: p->hierarchy_information = HIERARCHY_NONE; break; + case 1: p->hierarchy_information = HIERARCHY_1; break; + case 2: p->hierarchy_information = HIERARCHY_2; break; + case 3: p->hierarchy_information = HIERARCHY_4; break; + } + switch (val & 0x07) { + case 0: p->code_rate_HP = FEC_1_2; break; + case 1: p->code_rate_HP = FEC_2_3; break; + case 2: p->code_rate_HP = FEC_3_4; break; + case 3: p->code_rate_HP = FEC_5_6; break; + case 4: p->code_rate_HP = FEC_7_8; break; + } + + val = tda10048_readreg(state, TDA10048_OUT_CONF3); + switch (val & 0x07) { + case 0: p->code_rate_LP = FEC_1_2; break; + case 1: p->code_rate_LP = FEC_2_3; break; + case 2: p->code_rate_LP = FEC_3_4; break; + case 3: p->code_rate_LP = FEC_5_6; break; + case 4: p->code_rate_LP = FEC_7_8; break; + } + + val = tda10048_readreg(state, TDA10048_OUT_CONF1); + switch ((val & 0x0c) >> 2) { + case 0: p->guard_interval = GUARD_INTERVAL_1_32; break; + case 1: p->guard_interval = GUARD_INTERVAL_1_16; break; + case 2: p->guard_interval = GUARD_INTERVAL_1_8; break; + case 3: p->guard_interval = GUARD_INTERVAL_1_4; break; + } + switch (val & 0x02) { + case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break; + case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break; + } + + return 0; +} + +static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct tda10048_state *state = fe->demodulator_priv; + dprintk(1, "%s(%d)\n", __func__, enable); + + if (enable) + return tda10048_writereg(state, TDA10048_CONF_C4_1, + tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02); + else + return tda10048_writereg(state, TDA10048_CONF_C4_1, + tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd); +} + +static int tda10048_output_mode(struct dvb_frontend *fe, int serial) +{ + struct tda10048_state *state = fe->demodulator_priv; + dprintk(1, "%s(%d)\n", __func__, serial); + + /* Ensure pins are out of tri-state */ + tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21); + tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00); + + if (serial) { + tda10048_writereg(state, TDA10048_IC_MODE, 0x80 | 0x20); + tda10048_writereg(state, TDA10048_CONF_TS2, 0xc0); + } else { + tda10048_writereg(state, TDA10048_IC_MODE, 0x00); + tda10048_writereg(state, TDA10048_CONF_TS2, 0x01); + } + + return 0; +} + +/* Talk to the demod, set the FEC, GUARD, QAM settings etc */ +/* TODO: Support manual tuning with specific params */ +static int tda10048_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct tda10048_state *state = fe->demodulator_priv; + + dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency); + + if (fe->ops.tuner_ops.set_params) { + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + fe->ops.tuner_ops.set_params(fe, p); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + /* Enable demod TPS auto detection and begin acquisition */ + tda10048_writereg(state, TDA10048_AUTO, 0x57); + + return 0; +} + +/* Establish sane defaults and load firmware. */ +static int tda10048_init(struct dvb_frontend *fe) +{ + struct tda10048_state *state = fe->demodulator_priv; + int ret = 0, i; + + dprintk(1, "%s()\n", __func__); + + /* Apply register defaults */ + for (i = 0; i < ARRAY_SIZE(init_tab); i++) + tda10048_writereg(state, init_tab[i].reg, init_tab[i].data); + + if (state->fwloaded == 0) + ret = tda10048_firmware_upload(fe); + + /* Set either serial or parallel */ + tda10048_output_mode(fe, state->config->output_mode); + + /* set inversion */ + tda10048_set_inversion(fe, state->config->inversion); + + /* Ensure we leave the gate closed */ + tda10048_i2c_gate_ctrl(fe, 0); + + return ret; +} + +static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct tda10048_state *state = fe->demodulator_priv; + u8 reg; + + *status = 0; + + reg = tda10048_readreg(state, TDA10048_SYNC_STATUS); + + dprintk(1, "%s() status =0x%02x\n", __func__, reg); + + if (reg & 0x02) + *status |= FE_HAS_CARRIER; + + if (reg & 0x04) + *status |= FE_HAS_SIGNAL; + + if (reg & 0x08) { + *status |= FE_HAS_LOCK; + *status |= FE_HAS_VITERBI; + *status |= FE_HAS_SYNC; + } + + return 0; +} + +static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct tda10048_state *state = fe->demodulator_priv; + + dprintk(1, "%s()\n", __func__); + + /* TODO: A reset may be required here */ + *ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 | + tda10048_readreg(state, TDA10048_CBER_LSB); + + return 0; +} + +static int tda10048_read_signal_strength(struct dvb_frontend *fe, + u16 *signal_strength) +{ + struct tda10048_state *state = fe->demodulator_priv; + u16 v; + + dprintk(1, "%s()\n", __func__); + + v = tda10048_readreg(state, TDA10048_NP_OUT); + if (v == 0) + *signal_strength = 100; + else { + /* TODO: Apply .db math for correct values */ + *signal_strength = v; + } + + return 0; +} + +static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct tda10048_state *state = fe->demodulator_priv; + + dprintk(1, "%s()\n", __func__); + + /* TODO: This result should be the same as signal strength */ + *snr = tda10048_readreg(state, TDA10048_NP_OUT); + + return 0; +} + +static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct tda10048_state *state = fe->demodulator_priv; + + dprintk(1, "%s()\n", __func__); + + *ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 | + tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB); + + return 0; +} + +static int tda10048_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct tda10048_state *state = fe->demodulator_priv; + + dprintk(1, "%s()\n", __func__); + + p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1) + & 0x20 ? INVERSION_ON : INVERSION_OFF; + + return tda10048_get_tps(state, &p->u.ofdm); +} + +static int tda10048_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 1000; + return 0; +} + +static void tda10048_release(struct dvb_frontend *fe) +{ + struct tda10048_state *state = fe->demodulator_priv; + dprintk(1, "%s()\n", __func__); + kfree(state); +} + +static struct dvb_frontend_ops tda10048_ops; + +struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, + struct i2c_adapter *i2c) +{ + struct tda10048_state *state = NULL; + + dprintk(1, "%s()\n", __func__); + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + state->fwloaded = 0; + + /* check if the demod is present */ + if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048) + goto error; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &tda10048_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + /* Leave the gate closed */ + tda10048_i2c_gate_ctrl(&state->frontend, 0); + + return &state->frontend; + +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(tda10048_attach); + +static struct dvb_frontend_ops tda10048_ops = { + + .info = { + .name = "NXP TDA10048HN DVB-T", + .type = FE_OFDM, + .frequency_min = 177000000, + .frequency_max = 858000000, + .frequency_stepsize = 166666, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER + }, + + .release = tda10048_release, + .init = tda10048_init, + .i2c_gate_ctrl = tda10048_i2c_gate_ctrl, + .set_frontend = tda10048_set_frontend, + .get_frontend = tda10048_get_frontend, + .get_tune_settings = tda10048_get_tune_settings, + .read_status = tda10048_read_status, + .read_ber = tda10048_read_ber, + .read_signal_strength = tda10048_read_signal_strength, + .read_snr = tda10048_read_snr, + .read_ucblocks = tda10048_read_ucblocks, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Enable verbose debug messages"); + +MODULE_DESCRIPTION("NXP TDA10048HN DVB-T Demodulator driver"); +MODULE_AUTHOR("Steven Toth"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h new file mode 100644 index 000000000000..2b5c78e62c86 --- /dev/null +++ b/drivers/media/dvb/frontends/tda10048.h @@ -0,0 +1,63 @@ +/* + NXP TDA10048HN DVB OFDM demodulator driver + + Copyright (C) 2008 Steven Toth + + 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 TDA10048_H +#define TDA10048_H + +#include +#include + +struct tda10048_config { + + /* the demodulator's i2c address */ + u8 demod_address; + + /* serial/parallel output */ +#define TDA10048_PARALLEL_OUTPUT 0 +#define TDA10048_SERIAL_OUTPUT 1 + u8 output_mode; + +#define TDA10048_BULKWRITE_200 200 +#define TDA10048_BULKWRITE_50 50 + u8 fwbulkwritelen; + + /* Spectral Inversion */ +#define TDA10048_INVERSION_OFF 0 +#define TDA10048_INVERSION_ON 1 + u8 inversion; +}; + +#if defined(CONFIG_DVB_TDA10048) || \ + (defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE)) +extern struct dvb_frontend *tda10048_attach( + const struct tda10048_config *config, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *tda10048_attach( + const struct tda10048_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_TDA10048 */ + +#endif /* TDA10048_H */ From b3ea01668907bdb32b0c690d28f9f2b1298bd258 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 19 Apr 2008 01:14:19 -0300 Subject: [PATCH 372/452] V4L/DVB (7645): Add support for the Hauppauge HVR-1200 This adds support for DVB-T mode only, analog mode is not supported. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/Kconfig | 2 ++ drivers/media/video/cx23885/cx23885-cards.c | 22 +++++++++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 26 +++++++++++++++++++++ drivers/media/video/cx23885/cx23885-i2c.c | 1 + drivers/media/video/cx23885/cx23885.h | 1 + 6 files changed, 53 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 0924e6e142c4..3e9e999e5895 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -5,3 +5,4 @@ 4 -> DViCO FusionHDTV5 Express [18ac:d500] 5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797] 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717] + 7 -> Hauppauge WinTV-HVR1200 [0070:71d1] diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 1fd326fe4113..ca5fbce3a909 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -8,6 +8,7 @@ config VIDEO_CX23885 select VIDEO_TVEEPROM select VIDEO_IR select VIDEOBUF_DVB + select VIDEO_CX25840 select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE @@ -16,6 +17,7 @@ config VIDEO_CX23885 select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE select DVB_TDA18271 if !DVB_FE_CUSTOMIZE select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE + select DVB_TDA10048 if !DVB_FE_CUSTOMIZE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 77cd452e6e5b..8cb32f307a5d 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -130,6 +130,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1500", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1200] = { + .name = "Hauppauge WinTV-HVR1200", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -181,6 +185,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x7717, .card = CX23885_BOARD_HAUPPAUGE_HVR1500, + }, { + .subvendor = 0x0070, + .subdevice = 0x71d1, + .card = CX23885_BOARD_HAUPPAUGE_HVR1200, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -314,6 +322,17 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00040004); mdelay(20); break; + case CX23885_BOARD_HAUPPAUGE_HVR1200: + /* GPIO-0 tda10048 demodulator reset */ + /* GPIO-2 tda18271 tuner reset */ + + /* Put the parts into reset and back */ + cx_set(GP0_IO, 0x00050000); + mdelay(20); + cx_clear(GP0_IO, 0x00000005); + mdelay(20); + cx_set(GP0_IO, 0x00050005); + break; } } @@ -324,6 +343,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1800: + case CX23885_BOARD_HAUPPAUGE_HVR1200: /* FIXME: Implement me */ break; } @@ -353,6 +373,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) break; case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: + case CX23885_BOARD_HAUPPAUGE_HVR1200: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -369,6 +390,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: + case CX23885_BOARD_HAUPPAUGE_HVR1200: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 1a720abbd066..18cd90c9c0f3 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -36,6 +36,7 @@ #include "tda18271.h" #include "lgdt330x.h" #include "xc5000.h" +#include "tda10048.h" #include "dvb-pll.h" #include "tuner-xc2028.h" #include "tuner-xc2028-types.h" @@ -107,6 +108,13 @@ static struct s5h1409_config hauppauge_generic_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, }; +static struct tda10048_config hauppauge_hvr1200_config = { + .demod_address = 0x10 >> 1, + .output_mode = TDA10048_SERIAL_OUTPUT, + .fwbulkwritelen = TDA10048_BULKWRITE_200, + .inversion = TDA10048_INVERSION_ON +}; + static struct s5h1409_config hauppauge_ezqam_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, @@ -178,6 +186,10 @@ static struct tda18271_config hauppauge_tda18271_config = { .gate = TDA18271_GATE_ANALOG, }; +static struct tda18271_config hauppauge_hvr1200_tuner_config = { + .gate = TDA18271_GATE_ANALOG, +}; + static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) { struct cx23885_tsport *port = ptr; @@ -317,6 +329,20 @@ static int dvb_register(struct cx23885_tsport *port) fe->ops.tuner_ops.set_config(fe, &ctl); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1200: + i2c_bus = &dev->i2c_bus[0]; + port->dvb.frontend = dvb_attach(tda10048_attach, + &hauppauge_hvr1200_config, + &i2c_bus->i2c_adap); + if (port->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, port->dvb.frontend, + &dev->i2c_bus[1].i2c_adap, 0x42, + &tda829x_no_probe); + dvb_attach(tda18271_attach, port->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + &hauppauge_hvr1200_tuner_config); + } + break; default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->name); diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 8773a1fd97cb..85f9d5ef17d0 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -353,6 +353,7 @@ static struct i2c_client cx23885_i2c_client_template = { }; static char *i2c_devs[128] = { + [0x10 >> 1] = "tda10048", [ 0x1c >> 1 ] = "lgdt3303", [ 0x86 >> 1 ] = "tda9887", [ 0x32 >> 1 ] = "cx24227", diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 7cb2179f2622..5bbfe6f50769 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -59,6 +59,7 @@ #define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP 4 #define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5 #define CX23885_BOARD_HAUPPAUGE_HVR1500 6 +#define CX23885_BOARD_HAUPPAUGE_HVR1200 7 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ From 2770b7d7136f9c6a51ae7fd1d29fa58caf2bcf1c Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 19 Apr 2008 01:18:47 -0300 Subject: [PATCH 373/452] V4L/DVB (7646): cx25840: Ensure GPIO2 is correctly set for cx23885/7/8 based products cx25840: Ensure GPIO2 is correctly set for cx23885/7/8 based products. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index ae395f8cf292..7fde678b2c4a 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1268,6 +1268,12 @@ static int cx25840_probe(struct i2c_client *client) state->id = id; state->rev = device_id; + if (state->is_cx23885) { + /* Drive GPIO2 direction and values */ + cx25840_write(client, 0x160, 0x1d); + cx25840_write(client, 0x164, 0x00); + } + return 0; } From a780a31cee55e01e7b479244e7907ba842c120a0 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 19 Apr 2008 01:25:52 -0300 Subject: [PATCH 374/452] V4L/DVB (7647): Add support for the Hauppauge HVR-1700 digital mode This adds support for DVB-T mode only, analog is not supported. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 34 +++++++++++++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 1 + drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 37 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 3e9e999e5895..b057a3c9f8ff 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -6,3 +6,4 @@ 5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797] 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717] 7 -> Hauppauge WinTV-HVR1200 [0070:71d1] + 8 -> Hauppauge WinTV-HVR1700 [0070:8101] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 8cb32f307a5d..84636ffc64dc 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -134,6 +134,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1200", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1700] = { + .name = "Hauppauge WinTV-HVR1700", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -189,6 +193,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x71d1, .card = CX23885_BOARD_HAUPPAUGE_HVR1200, + }, { + .subvendor = 0x0070, + .subdevice = 0x8101, + .card = CX23885_BOARD_HAUPPAUGE_HVR1700, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -243,6 +251,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */ case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ + case 81519: + /* WinTV-HVR1700 (PCIe, Retail, No IR, half height, + * DVB-T and MPEG2 HW Encoder */ break; default: printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model); @@ -326,6 +337,27 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* GPIO-0 tda10048 demodulator reset */ /* GPIO-2 tda18271 tuner reset */ + /* Put the parts into reset and back */ + cx_set(GP0_IO, 0x00050000); + mdelay(20); + cx_clear(GP0_IO, 0x00000005); + mdelay(20); + cx_set(GP0_IO, 0x00050005); + break; + case CX23885_BOARD_HAUPPAUGE_HVR1700: + /* GPIO-0 TDA10048 demodulator reset */ + /* GPIO-2 TDA8295A Reset */ + /* GPIO-3-10 cx23417 data0-7 */ + /* GPIO-11-14 cx23417 addr0-3 */ + /* GPIO-15-18 cx23417 READY, CS, RD, WR */ + + /* The following GPIO's are on the interna AVCore (cx25840) */ + /* GPIO-19 IR_RX */ + /* GPIO-20 IR_TX 416/DVBT Select */ + /* GPIO-21 IIS DAT */ + /* GPIO-22 IIS WCLK */ + /* GPIO-23 IIS BCLK */ + /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); @@ -374,6 +406,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: + case CX23885_BOARD_HAUPPAUGE_HVR1700: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -391,6 +424,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: + case CX23885_BOARD_HAUPPAUGE_HVR1700: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 18cd90c9c0f3..a1086c8b66ee 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -330,6 +330,7 @@ static int dvb_register(struct cx23885_tsport *port) } break; case CX23885_BOARD_HAUPPAUGE_HVR1200: + case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; port->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 5bbfe6f50769..c5496e08c949 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -60,6 +60,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5 #define CX23885_BOARD_HAUPPAUGE_HVR1500 6 #define CX23885_BOARD_HAUPPAUGE_HVR1200 7 +#define CX23885_BOARD_HAUPPAUGE_HVR1700 8 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ From ce89cfb4908bcebba3fb0cd2956d676e06043ef1 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 19 Apr 2008 01:36:06 -0300 Subject: [PATCH 375/452] V4L/DVB (7648): cx23885: Load any module dependencies accordingly For boards that require the avcore (cx25840) to be active, ensure it gets loaded. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 10 ++++++++++ drivers/media/video/cx23885/cx23885-core.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 84636ffc64dc..859510f7469c 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -431,6 +431,16 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; } + /* Certain boards support analog, or require the avcore to be + * loaded, ensure this happens. + */ + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1800: + case CX23885_BOARD_HAUPPAUGE_HVR1800lp: + case CX23885_BOARD_HAUPPAUGE_HVR1700: + request_module("cx25840"); + break; + } } /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 52942d102de4..b23d60801ed0 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -744,8 +744,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_i2c_register(&dev->i2c_bus[0]); cx23885_i2c_register(&dev->i2c_bus[1]); cx23885_i2c_register(&dev->i2c_bus[2]); - cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL); cx23885_card_setup(dev); + cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL); cx23885_ir_init(dev); if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { From d1e0b57162f45bb9c6bff25aa33b6e8424556422 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 17 Apr 2008 22:16:31 -0300 Subject: [PATCH 376/452] V4L/DVB (7650): git-dvb: Kconfig fix Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index c57420e263ff..9caffed2b6b8 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -4,6 +4,7 @@ config VIDEO_EM28XX select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR + select VIDEOBUF_VMALLOC select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO From 33e5316113b1a472f54579f014739e4a4a53d704 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 21 Apr 2008 06:58:48 -0300 Subject: [PATCH 377/452] V4L/DVB (7651): tuner-xc2028: Several fixes to SCODE This patch fixes several issues on SCODE: 1) The extracting tool weren't generating the proper tags for SCODE. This has almost no effect, since those tags shouldn't be used; 2) DIBCOM52 were using a wrong IF. It should be 5200, instead of 5700; 3) seek_firmware were wanting an exact match for firmware type. This is wrong. As result, no SCODE firmware were loaded; 4) A few files were including the wrong file for seeking demod firmwares; 5) XC3028_FE_DEFAULT can be used, if user doesn't want to load a firmware. However, this weren't documentated. This feature require more testing. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/extract_xc3028.pl | 46 ++++++++++----------- drivers/media/dvb/dvb-usb/cxusb.c | 3 +- drivers/media/video/cx23885/cx23885-dvb.c | 3 +- drivers/media/video/cx88/cx88-dvb.c | 3 +- drivers/media/video/tuner-xc2028-types.h | 18 +++++--- drivers/media/video/tuner-xc2028.c | 21 ++++++---- drivers/media/video/tuner-xc2028.h | 4 +- 7 files changed, 54 insertions(+), 44 deletions(-) diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl index cced8ac5c543..2cb816047fc1 100644 --- a/Documentation/video4linux/extract_xc3028.pl +++ b/Documentation/video4linux/extract_xc3028.pl @@ -686,11 +686,11 @@ sub main_firmware($$$$) write_hunk(812664, 192); # - # Firmware 58, type: SCODE FW HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192 + # Firmware 58, type: SCODE FW MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192 # - write_le32(0x60000000); # Type - write_le64(0x00000000, 0x00002000); # ID + write_le32(0x6002b004); # Type + write_le64(0x00000000, 0x0000b700); # ID write_le16(4500); # IF write_le32(192); # Size write_hunk(807672, 192); @@ -706,10 +706,10 @@ sub main_firmware($$$$) write_hunk(807864, 192); # - # Firmware 60, type: SCODE FW DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192 + # Firmware 60, type: SCODE FW DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192 # - write_le32(0x62000100); # Type + write_le32(0x620003e0); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(4760); # IF write_le32(192); # Size @@ -726,30 +726,30 @@ sub main_firmware($$$$) write_hunk(811512, 192); # - # Firmware 62, type: SCODE FW DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192 + # Firmware 62, type: SCODE FW HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192 # - write_le32(0x62000080); # Type + write_le32(0x60000000); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(5260); # IF write_le32(192); # Size write_hunk(810552, 192); # - # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192 + # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192 # write_le32(0x60008000); # Type - write_le64(0x00000008, 0x00000007); # ID + write_le64(0x0000000f, 0x00000007); # ID write_le16(5320); # IF write_le32(192); # Size write_hunk(810744, 192); # - # Firmware 64, type: SCODE FW DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192 + # Firmware 64, type: SCODE FW DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192 # - write_le32(0x64000200); # Type + write_le32(0x65000380); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(5400); # IF write_le32(192); # Size @@ -766,50 +766,50 @@ sub main_firmware($$$$) write_hunk(809592, 192); # - # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192 + # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192 # write_le32(0x60000000); # Type - write_le64(0x00000002, 0x00000007); # ID + write_le64(0x00000003, 0x00000007); # ID write_le16(5640); # IF write_le32(192); # Size write_hunk(808440, 192); # - # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192 + # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192 # write_le32(0x60000000); # Type - write_le64(0x00000008, 0x00000007); # ID + write_le64(0x0000000c, 0x00000007); # ID write_le16(5740); # IF write_le32(192); # Size write_hunk(808632, 192); # - # Firmware 68, type: SCODE FW DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192 + # Firmware 68, type: SCODE FW HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192 # - write_le32(0x61000080); # Type + write_le32(0x60000000); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(5900); # IF write_le32(192); # Size write_hunk(810360, 192); # - # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192 + # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192 # write_le32(0x60008000); # Type - write_le64(0x00000000, 0x00000010); # ID + write_le64(0x0000000c, 0x04c000f0); # ID write_le16(6000); # IF write_le32(192); # Size write_hunk(808824, 192); # - # Firmware 70, type: SCODE FW DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192 + # Firmware 70, type: SCODE FW DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192 # - write_le32(0x68000060); # Type + write_le32(0x68050060); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(6200); # IF write_le32(192); # Size @@ -846,11 +846,11 @@ sub main_firmware($$$$) write_hunk(809208, 192); # - # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192 + # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192 # write_le32(0x60008000); # Type - write_le64(0x00000000, 0x04000000); # ID + write_le64(0x0000000c, 0x044000e0); # ID write_le16(6500); # IF write_le32(192); # Size write_hunk(811128, 192); diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index c4b00660c65f..720fcd1c3c1d 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -33,7 +33,6 @@ #include "mt352_priv.h" #include "zl10353.h" #include "tuner-xc2028.h" -#include "tuner-xc2028-types.h" #include "tuner-simple.h" /* debug */ @@ -521,7 +520,7 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) static struct xc2028_ctrl ctl = { .fname = "xc3028-dvico-au-01.fw", .max_len = 64, - .scode_table = ZARLINK456, + .scode_table = XC3028_FE_ZARLINK456, }; fe = dvb_attach(xc2028_attach, adap->fe, &cfg); diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index a1086c8b66ee..1b9a85e43d44 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -39,7 +39,6 @@ #include "tda10048.h" #include "dvb-pll.h" #include "tuner-xc2028.h" -#include "tuner-xc2028-types.h" #include "tuner-simple.h" static unsigned int debug; @@ -320,7 +319,7 @@ static int dvb_register(struct cx23885_tsport *port) static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", .max_len = 64, - .scode_table = OREN538, + .scode_table = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index fda7334d934b..f1251b844e08 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-types.h" #include "tuner-simple.h" #include "tda9887.h" @@ -813,7 +812,7 @@ static int dvb_register(struct cx8802_dev *dev) static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", .max_len = 64, - .scode_table = OREN538, + .scode_table = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h index d0057fbf0ec7..17633c316c28 100644 --- a/drivers/media/video/tuner-xc2028-types.h +++ b/drivers/media/video/tuner-xc2028-types.h @@ -1,6 +1,9 @@ /* tuner-xc2028_types * - * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * This file includes internal tipes to be used inside tuner-xc2028. + * Shouldn't be included outside tuner-xc2028 + * + * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) * This code is placed under the terms of the GNU General Public License v2 */ @@ -85,11 +88,16 @@ /* This flag identifies that the scode table has a new format */ #define HAS_IF (1 << 30) -#define SCODE_TYPES (MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \ - LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794| \ - DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE) +#define SCODE_TYPES SCODE -/* Newer types to be moved to videodev2.h */ + +/* Newer types not defined on videodev2.h. + The original idea were to move all those types to videodev2.h, but + it seemed overkill, since, with the exception of SECAM/K3, the other + types seem to be autodetected. + It is not clear where secam/k3 is used, nor we have a feedback of this + working or being autodetected by the standard secam firmware. + */ #define V4L2_STD_SECAM_K3 (0x04000000) diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 9dd688ec3cff..0e580bcd0e09 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -1,6 +1,6 @@ /* tuner-xc2028 * - * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) * * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com) * - frontend interface @@ -404,7 +404,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, { struct xc2028_data *priv = fe->tuner_priv; int i, best_i = -1, best_nr_matches = 0; - unsigned int ign_firm_type_mask = 0; + unsigned int type_mask = 0; tuner_dbg("%s called, want type=", __func__); if (debug) { @@ -421,18 +421,23 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, *id = V4L2_STD_PAL; if (type & BASE) - type &= BASE_TYPES; + type_mask = BASE_TYPES; else if (type & SCODE) { type &= SCODE_TYPES; - ign_firm_type_mask = HAS_IF; + type_mask = SCODE_TYPES & ~HAS_IF; } else if (type & DTV_TYPES) - type &= DTV_TYPES; + type_mask = DTV_TYPES; else if (type & STD_SPECIFIC_TYPES) - type &= STD_SPECIFIC_TYPES; + type_mask = STD_SPECIFIC_TYPES; + + type &= type_mask; + + if (!type & SCODE) + type_mask = ~0; /* Seek for exact match */ for (i = 0; i < priv->firm_size; i++) { - if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) && + if ((type == (priv->firm[i].type & type_mask)) && (*id == priv->firm[i].id)) goto found; } @@ -442,7 +447,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, v4l2_std_id match_mask; int nr_matches; - if (type != (priv->firm[i].type & ~ign_firm_type_mask)) + if (type != (priv->firm[i].type & type_mask)) continue; match_mask = *id & priv->firm[i].id; diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h index 612e490634d0..fc2f132a5541 100644 --- a/drivers/media/video/tuner-xc2028.h +++ b/drivers/media/video/tuner-xc2028.h @@ -1,6 +1,6 @@ /* tuner-xc2028 * - * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) * This code is placed under the terms of the GNU General Public License v2 */ @@ -12,7 +12,7 @@ #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw" /* Dmoduler IF (kHz) */ -#define XC3028_FE_DEFAULT 0 +#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */ #define XC3028_FE_LG60 6000 #define XC3028_FE_ATI638 6380 #define XC3028_FE_OREN538 5380 From 4269a8eed210d143298baf80185317fc1dcb25ca Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 21 Apr 2008 07:01:09 -0300 Subject: [PATCH 378/452] V4L/DVB (7652): em28xx: Drop the severity level of the "urb resubmit failed" em28xx-core.c - Drop the severity level of the "urb resubmit failed" to debug, since it occurs every time a stream disconnects, which fills the dmesg log Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index db40358c773b..f8c41d8c74c4 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -576,8 +576,8 @@ static void em28xx_irq_callback(struct urb *urb) urb->status = usb_submit_urb(urb, GFP_ATOMIC); if (urb->status) { - em28xx_err("urb resubmit failed (error=%i)\n", - urb->status); + em28xx_isocdbg("urb resubmit failed (error=%i)\n", + urb->status); } } From b37f2d6a31fc8e80c79a0a214d83b128aa796543 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 21 Apr 2008 07:02:09 -0300 Subject: [PATCH 379/452] V4L/DVB (7653): tuner-xc2028: drop the severity of version reporting tuner-xc2028.c - Drop the severity level of the xc3028 version reporting, since it's only of interest to developers and user's don't need to have it show up in their dmesg output every time they change the channel. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-xc2028.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 0e580bcd0e09..a32094e545f7 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -784,10 +784,10 @@ check_device: goto fail; } - tuner_info("Device is Xceive %d version %d.%d, " - "firmware version %d.%d\n", - hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8, - (version & 0xf0) >> 4, version & 0xf); + tuner_dbg("Device is Xceive %d version %d.%d, " + "firmware version %d.%d\n", + hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8, + (version & 0xf0) >> 4, version & 0xf); /* Check firmware version against what we downloaded. */ if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) { From 9a1b04e461fc8127c902a988cd9a082ba0680b11 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 9 Apr 2008 23:07:11 -0300 Subject: [PATCH 380/452] V4L/DVB (7654): tda10086: make the xtal frequency a configuration option Some DVB-S boards, i.e. with the SD1878 tuner, use a 4 MHz reference frequency. This reqires a different setup of the clock PLL. This patch adds an enum to the tda10086_config struct and sets the proper values for the boards. This patch also fixes the DVB-S section of the MD7134_BRIDGE_2 Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/ttusb2.c | 1 + drivers/media/dvb/frontends/tda10086.c | 11 ++++++++--- drivers/media/dvb/frontends/tda10086.h | 8 ++++++++ drivers/media/dvb/ttpci/budget.c | 1 + drivers/media/video/saa7134/saa7134-dvb.c | 10 +++++++++- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c index 706687c78506..20ca9d9ee99b 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -147,6 +147,7 @@ static struct tda10086_config tda10086_config = { .demod_address = 0x0e, .invert = 0, .diseqc_tone = 1, + .xtal_freq = TDA10086_XTAL_16M, }; static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 5fc26757f393..acf1471373ca 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -128,10 +128,15 @@ static int tda10086_init(struct dvb_frontend* fe) tda10086_write_byte(state, 0x32, 0x00); // irq off tda10086_write_byte(state, 0x31, 0x56); // setup AFC - // setup PLL (assumes 16Mhz XIN) + // setup PLL (this assumes SACLK = 96MHz) tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup - tda10086_write_byte(state, 0x3a, 0x0b); // M=12 - tda10086_write_byte(state, 0x3b, 0x01); // P=2 + if (state->config->xtal_freq == TDA10086_XTAL_16M) { + tda10086_write_byte(state, 0x3a, 0x0b); // M=12 + tda10086_write_byte(state, 0x3b, 0x01); // P=2 + } else { + tda10086_write_byte(state, 0x3a, 0x17); // M=24 + tda10086_write_byte(state, 0x3b, 0x00); // P=1 + } tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL // setup TS interface diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h index 197c237e515f..f25d5ea381e5 100644 --- a/drivers/media/dvb/frontends/tda10086.h +++ b/drivers/media/dvb/frontends/tda10086.h @@ -26,6 +26,11 @@ #include #include +enum tda10086_xtal { + TDA10086_XTAL_16M, + TDA10086_XTAL_4M +}; + struct tda10086_config { /* the demodulator's i2c address */ @@ -36,6 +41,9 @@ struct tda10086_config /* do we need the diseqc signal with carrier? */ u8 diseqc_tone; + + /* frequency of the reference xtal */ + enum tda10086_xtal xtal_freq; }; #if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE)) diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index e36c32528e5c..7adfe17b0616 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -365,6 +365,7 @@ static struct tda10086_config tda10086_config = { .demod_address = 0x0e, .invert = 0, .diseqc_tone = 1, + .xtal_freq = TDA10086_XTAL_16M, }; static u8 read_pwm(struct budget* budget) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 73154c1a0239..2d16be2259db 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -851,6 +851,14 @@ static struct tda10086_config flydvbs = { .demod_address = 0x0e, .invert = 0, .diseqc_tone = 0, + .xtal_freq = TDA10086_XTAL_16M, +}; + +static struct tda10086_config sd1878_4m = { + .demod_address = 0x0e, + .invert = 0, + .diseqc_tone = 0, + .xtal_freq = TDA10086_XTAL_4M, }; /* ------------------------------------------------------------------ @@ -1206,7 +1214,7 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_MD7134_BRIDGE_2: dev->dvb.frontend = dvb_attach(tda10086_attach, - &flydvbs, &dev->i2c_adap); + &sd1878_4m, &dev->i2c_adap); if (dev->dvb.frontend) { struct dvb_frontend *fe; if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, From b1c54fe2aed3e2812f5b42916894f15e84b484b5 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Sun, 13 Apr 2008 21:09:11 -0300 Subject: [PATCH 381/452] V4L/DVB (7655): tda10086 coding stlye fixes This patch replaces the c++ style comments. No functional changes Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10086.c | 100 ++++++++++++------------- drivers/media/dvb/frontends/tda10086.h | 4 +- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index acf1471373ca..a17ce3c4ad86 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -90,16 +90,16 @@ static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask, { int val; - // read a byte and check + /* read a byte and check */ val = tda10086_read_byte(state, reg); if (val < 0) return val; - // mask if off + /* mask if off */ val = val & ~mask; val |= data & 0xff; - // write it out again + /* write it out again */ return tda10086_write_byte(state, reg, val); } @@ -112,63 +112,63 @@ static int tda10086_init(struct dvb_frontend* fe) if (state->config->diseqc_tone) t22k_off = 0; - // reset + /* reset */ tda10086_write_byte(state, 0x00, 0x00); msleep(10); - // misc setup + /* misc setup */ tda10086_write_byte(state, 0x01, 0x94); - tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP + tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */ tda10086_write_byte(state, 0x03, 0xe4); tda10086_write_byte(state, 0x04, 0x43); tda10086_write_byte(state, 0x0c, 0x0c); - tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold - tda10086_write_byte(state, 0x20, 0x89); // misc - tda10086_write_byte(state, 0x30, 0x04); // acquisition period length - tda10086_write_byte(state, 0x32, 0x00); // irq off - tda10086_write_byte(state, 0x31, 0x56); // setup AFC + tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */ + tda10086_write_byte(state, 0x20, 0x89); /* misc */ + tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */ + tda10086_write_byte(state, 0x32, 0x00); /* irq off */ + tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */ - // setup PLL (this assumes SACLK = 96MHz) - tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup + /* setup PLL (this assumes SACLK = 96MHz) */ + tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */ if (state->config->xtal_freq == TDA10086_XTAL_16M) { - tda10086_write_byte(state, 0x3a, 0x0b); // M=12 - tda10086_write_byte(state, 0x3b, 0x01); // P=2 + tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */ + tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */ } else { - tda10086_write_byte(state, 0x3a, 0x17); // M=24 - tda10086_write_byte(state, 0x3b, 0x00); // P=1 + tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */ + tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */ } - tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL + tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */ - // setup TS interface + /* setup TS interface */ tda10086_write_byte(state, 0x11, 0x81); tda10086_write_byte(state, 0x12, 0x81); - tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST - tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use - tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use + tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */ + tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */ + tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */ tda10086_write_byte(state, 0x10, 0x2a); - // setup ADC - tda10086_write_byte(state, 0x58, 0x61); // ADC setup - tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC + /* setup ADC */ + tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */ + tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */ - // setup AGC + /* setup AGC */ tda10086_write_byte(state, 0x05, 0x0B); tda10086_write_byte(state, 0x37, 0x63); - tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it + tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */ tda10086_write_byte(state, 0x40, 0x64); tda10086_write_byte(state, 0x41, 0x4f); tda10086_write_byte(state, 0x42, 0x43); - // setup viterbi - tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK + /* setup viterbi */ + tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */ - // setup carrier recovery + /* setup carrier recovery */ tda10086_write_byte(state, 0x3d, 0x80); - // setup SEC - tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone - tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency - tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // } + /* setup SEC */ + tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */ + tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); + tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); return 0; } @@ -307,7 +307,7 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state, dprintk ("%s %i\n", __func__, symbol_rate); - // setup the decimation and anti-aliasing filters.. + /* setup the decimation and anti-aliasing filters.. */ if (symbol_rate < (u32) (SACLK * 0.0137)) { dfn=4; afs=1; @@ -344,13 +344,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state, byp=1; } - // calculate BDR + /* calculate BDR */ big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<has_lock = false; - // set params + /* set params */ if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, fe_params); if (fe->ops.i2c_gate_ctrl) @@ -435,7 +435,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe, fe->ops.i2c_gate_ctrl(fe, 0); } - // calcluate the frequency offset (in *Hz* not kHz) + /* calcluate the frequency offset (in *Hz* not kHz) */ freqoff = fe_params->frequency - freq; freqoff = ((1<<16) * freqoff) / (SACLK/1000); tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f)); @@ -448,7 +448,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe, if ((ret = tda10086_set_fec(state, fe_params)) < 0) return ret; - // soft reset + disable TS output until lock + /* soft reset + disable TS output until lock */ tda10086_write_mask(state, 0x10, 0x40, 0x40); tda10086_write_mask(state, 0x00, 0x01, 0x00); @@ -466,11 +466,11 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa dprintk ("%s\n", __func__); - // check for invalid symbol rate + /* check for invalid symbol rate */ if (fe_params->u.qpsk.symbol_rate < 500000) return -EINVAL; - // calculate the updated frequency (note: we convert from Hz->kHz) + /* calculate the updated frequency (note: we convert from Hz->kHz) */ tmp64 = tda10086_read_byte(state, 0x52); tmp64 |= (tda10086_read_byte(state, 0x51) << 8); if (tmp64 & 0x8000) @@ -479,7 +479,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa do_div(tmp64, (1ULL<<15) * (1ULL<<1)); fe_params->frequency = (int) state->frequency + (int) tmp64; - // the inversion + /* the inversion */ val = tda10086_read_byte(state, 0x0c); if (val & 0x80) { switch(val & 0x40) { @@ -510,7 +510,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa } } - // calculate the updated symbol rate + /* calculate the updated symbol rate */ tmp = tda10086_read_byte(state, 0x1d); if (tmp & 0x80) tmp |= 0xffffff00; @@ -518,7 +518,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000); fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp; - // the FEC + /* the FEC */ val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4; switch(val) { case 0x00: @@ -571,7 +571,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status) *fe_status |= FE_HAS_LOCK; if (!state->has_lock) { state->has_lock = true; - // modify parameters for stable reception + /* modify parameters for stable reception */ tda10086_write_byte(state, 0x02, 0x00); } } @@ -611,10 +611,10 @@ static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) dprintk ("%s\n", __func__); - // read it + /* read it */ *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f; - // reset counter + /* reset counter */ tda10086_write_byte(state, 0x18, 0x00); tda10086_write_byte(state, 0x18, 0x80); @@ -627,7 +627,7 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber) dprintk ("%s\n", __func__); - // read it + /* read it */ *ber = 0; *ber |= tda10086_read_byte(state, 0x15); *ber |= tda10086_read_byte(state, 0x16) << 8; diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h index f25d5ea381e5..61148c558d8d 100644 --- a/drivers/media/dvb/frontends/tda10086.h +++ b/drivers/media/dvb/frontends/tda10086.h @@ -56,6 +56,6 @@ static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } -#endif // CONFIG_DVB_TDA10086 +#endif /* CONFIG_DVB_TDA10086 */ -#endif // TDA10086_H +#endif /* TDA10086_H */ From 3ff9a81b21c673fd91ad8456242ca68922f77ac4 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Sun, 13 Apr 2008 22:41:19 -0300 Subject: [PATCH 382/452] V4L/DVB (7656): tda826x: Calculate cut off fequency from symbol rate This patch makes the tuner work with transonders providing higher symbol rates. It was contributed by Oliver Endriss. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda826x.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index 5a15bb4263fb..a051554b5e25 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -75,6 +75,8 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param struct tda826x_priv *priv = fe->tuner_priv; int ret; u32 div; + u32 ksyms; + u32 bandwidth; u8 buf [11]; struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 }; @@ -82,6 +84,15 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param div = (params->frequency + (1000-1)) / 1000; + /* BW = ((1 + RO) * SR/2 + 5) * 1.3 [SR in MSPS, BW in MHz] */ + /* with R0 = 0.35 and some transformations: */ + ksyms = params->u.qpsk.symbol_rate / 1000; + bandwidth = (878 * ksyms + 6500000) / 1000000 + 1; + if (bandwidth < 5) + bandwidth = 5; + else if (bandwidth > 36) + bandwidth = 36; + buf[0] = 0x00; // subaddress buf[1] = 0x09; // powerdown RSSI + the magic value 1 if (!priv->has_loopthrough) @@ -89,7 +100,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO buf[3] = div >> 7; buf[4] = div << 1; - buf[5] = 0x77; // baseband cut-off 19 MHz + buf[5] = ((bandwidth - 5) << 3) | 7; /* baseband cut-off */ buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation buf[7] = 0x83; // charge pumps at high, tests off buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports. From 48c01a9c2d245b229f8b709040cb1776b00dc683 Mon Sep 17 00:00:00 2001 From: Andrea Odetti Date: Sun, 20 Apr 2008 18:37:45 -0300 Subject: [PATCH 383/452] V4L/DVB (7658): dvb-core: Fix DMX_SET_BUFFER_SIZE in case the buffer shrinks This patch fixes the bug in DMX_SET_BUFFER_SIZE for the demux. Basically it resets read and write pointers to 0 in case they are beyond the new size of the buffer. Signed-off-by: Andrea Odetti Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 4 +++- drivers/media/dvb/dvb-core/dvb_ringbuffer.c | 6 +++++- drivers/media/dvb/dvb-core/dvb_ringbuffer.h | 8 ++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 3415a3bb363c..bbd52be552db 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -281,7 +281,9 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, mem = buf->data; buf->data = NULL; buf->size = size; - dvb_ringbuffer_flush(buf); + + /* reset and not flush in case the buffer shrinks */ + dvb_ringbuffer_reset(buf); spin_unlock_irq(&dmxdevfilter->dev->lock); vfree(mem); diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c index ac9d93cf83c6..872985b7912d 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c @@ -90,7 +90,11 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) rbuf->error = 0; } - +void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) +{ + rbuf->pread = rbuf->pwrite = 0; + rbuf->error = 0; +} void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) { diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h index d97714e75736..890826262966 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h @@ -69,6 +69,7 @@ struct dvb_ringbuffer { ** to lock read or write operations. ** Two or more readers must be locked against each other. ** Flushing the buffer counts as a read operation. +** Resetting the buffer counts as a read and write operation. ** Two or more writers must be locked against each other. */ @@ -85,6 +86,13 @@ extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); +/* +** Reset the read and write pointers to zero and flush the buffer +** This counts as a read and write operation +*/ +extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); + + /* read routines & macros */ /* ---------------------- */ /* flush buffer */ From a095be4b030cd7eb5ac2a7dcb86e803db149a8db Mon Sep 17 00:00:00 2001 From: Andrea Odetti Date: Sun, 20 Apr 2008 19:14:51 -0300 Subject: [PATCH 384/452] V4L/DVB (7659): dvb-core: Implement DMX_SET_BUFFER_SIZE for dvr Implementation of DMX_SET_BUFFER_SIZE for dvr. Synchronization of the code of DMX_SET_BUFFER_SIZE for demux and dvr. Signed-off-by: Andrea Odetti Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 63 ++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index bbd52be552db..df5bef6a2517 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -259,6 +259,39 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, return ret; } +static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, + unsigned long size) +{ + struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer; + void *newmem; + void *oldmem; + + dprintk("function : %s\n", __func__); + + if (buf->size == size) + return 0; + if (!size) + return -EINVAL; + + newmem = vmalloc(size); + if (!newmem) + return -ENOMEM; + + oldmem = buf->data; + + spin_lock_irq(&dmxdev->lock); + buf->data = newmem; + buf->size = size; + + /* reset and not flush in case the buffer shrinks */ + dvb_ringbuffer_reset(buf); + spin_unlock_irq(&dmxdev->lock); + + vfree(oldmem); + + return 0; +} + static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter *dmxdevfilter, int state) { @@ -271,30 +304,32 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsigned long size) { struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; - void *mem; + void *newmem; + void *oldmem; if (buf->size == size) return 0; + if (!size) + return -EINVAL; if (dmxdevfilter->state >= DMXDEV_STATE_GO) return -EBUSY; + + newmem = vmalloc(size); + if (!newmem) + return -ENOMEM; + + oldmem = buf->data; + spin_lock_irq(&dmxdevfilter->dev->lock); - mem = buf->data; - buf->data = NULL; + buf->data = newmem; buf->size = size; /* reset and not flush in case the buffer shrinks */ dvb_ringbuffer_reset(buf); spin_unlock_irq(&dmxdevfilter->dev->lock); - vfree(mem); - if (buf->size) { - mem = vmalloc(dmxdevfilter->buffer.size); - if (!mem) - return -ENOMEM; - spin_lock_irq(&dmxdevfilter->dev->lock); - buf->data = mem; - spin_unlock_irq(&dmxdevfilter->dev->lock); - } + vfree(oldmem); + return 0; } @@ -1011,6 +1046,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, { struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; + unsigned long arg = (unsigned long)parg; int ret; if (mutex_lock_interruptible(&dmxdev->mutex)) @@ -1018,8 +1054,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, switch (cmd) { case DMX_SET_BUFFER_SIZE: - // FIXME: implement - ret = 0; + ret = dvb_dvr_set_buffer_size(dmxdev, arg); break; default: From 94ad6de7051a9eb6beda096144c5b409538eab86 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 20 Apr 2008 20:41:42 -0300 Subject: [PATCH 385/452] V4L/DVB (7660): bsbe1: Use settings recommended by the manufacturer Reworked the BSBE1 tuner support in bsbe1.h to follow the ALPS-recommended parameters more closely. Tested with BSBE1-based Activy cards and TT DVB-S rev 2.3. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/bsbe1.h | 58 ++++++++++------------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h index d8f65738e5d2..5e431ebd089b 100644 --- a/drivers/media/dvb/frontends/bsbe1.h +++ b/drivers/media/dvb/frontends/bsbe1.h @@ -1,5 +1,5 @@ /* - * bsbe1.h - ALPS BSBE1 tuner support (moved from av7110.c) + * bsbe1.h - ALPS BSBE1 tuner support * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,44 +26,24 @@ #define BSBE1_H static u8 alps_bsbe1_inittab[] = { - 0x01, 0x15, - 0x02, 0x30, - 0x03, 0x00, + 0x01, 0x15, /* XTAL = 4MHz, VCO = 352 MHz */ + 0x02, 0x30, /* MCLK = 88 MHz */ + 0x03, 0x00, /* ACR output 0 */ 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ + 0x05, 0x05, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x00, /* DAC output 0 */ 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ 0x09, 0x00, /* FIFO */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - 0x10, 0x3f, // AGC2 0x3d - 0x11, 0x84, - 0x12, 0xb9, - 0x15, 0xc9, // lock detector threshold - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - 0x31, 0x1f, // test all FECs - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control - 0x0f, 0x92, + 0x0c, 0x51, /* OP1/OP0 normal, val = 1 (LNB power on) */ + 0x0d, 0x82, /* DC offset compensation = on, beta_agc1 = 2 */ + 0x0f, 0x92, /* AGC1R */ + 0x10, 0x34, /* AGC2O */ + 0x11, 0x84, /* TLSR */ + 0x12, 0xb9, /* CFD */ + 0x15, 0xc9, /* lock detector threshold */ + 0x28, 0x00, /* out imp: normal, type: parallel, FEC mode: QPSK */ + 0x33, 0xfc, /* RS control */ + 0x34, 0x93, /* count viterbi bit errors per 2E18 bytes */ 0xff, 0xff }; @@ -100,11 +80,11 @@ static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_front if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; - div = (params->frequency + (125 - 1)) / 125; // round correctly + div = params->frequency / 1000; data[0] = (div >> 8) & 0x7f; data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1; + data[3] = 0xe0; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); From e84b133e329ddad725907844c285efcd35dae39d Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 20 Apr 2008 21:57:34 -0300 Subject: [PATCH 386/452] V4L/DVB (7661): stv0299: Add flag to turn off OP0 output Add flag to turn off OP0 output. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0299.c | 45 ++++++++++++++++++--------- drivers/media/dvb/frontends/stv0299.h | 3 ++ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index f7c36741537d..17556183e871 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -366,26 +366,32 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag * H/V switching over OP0, OP1 and OP2 are LNB power enable bits */ reg0x0c &= 0x0f; - - if (voltage == SEC_VOLTAGE_OFF) { - stv0299_writeregI (state, 0x0c, 0x00); /* LNB power off! */ - return stv0299_writeregI (state, 0x08, 0x00); /* LNB power off! */ - } - - stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6)); + reg0x08 = (reg0x08 & 0x3f) | (state->config->lock_output << 6); switch (voltage) { case SEC_VOLTAGE_13: - if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) reg0x0c |= 0x10; - else reg0x0c |= 0x40; - - return stv0299_writeregI(state, 0x0c, reg0x0c); - + if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) + reg0x0c |= 0x10; /* OP1 off, OP0 on */ + else + reg0x0c |= 0x40; /* OP1 on, OP0 off */ + break; case SEC_VOLTAGE_18: - return stv0299_writeregI(state, 0x0c, reg0x0c | 0x50); + reg0x0c |= 0x50; /* OP1 on, OP0 on */ + break; + case SEC_VOLTAGE_OFF: + /* LNB power off! */ + reg0x08 = 0x00; + reg0x0c = 0x00; + break; default: return -EINVAL; }; + + if (state->config->op0_off) + reg0x0c &= ~0x10; + + stv0299_writeregI(state, 0x08, reg0x08); + return stv0299_writeregI(state, 0x0c, reg0x0c); } static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd) @@ -445,11 +451,20 @@ static int stv0299_init (struct dvb_frontend* fe) { struct stv0299_state* state = fe->demodulator_priv; int i; + u8 reg; + u8 val; dprintk("stv0299: init chip\n"); - for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2) - stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]); + for (i = 0; ; i += 2) { + reg = state->config->inittab[i]; + val = state->config->inittab[i+1]; + if (reg == 0xff && val == 0xff) + break; + if (reg == 0x0c && state->config->op0_off) + val &= ~0x10; + stv0299_writeregI(state, reg, val); + } return 0; } diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index 84eaeb518540..abd9cf8153cf 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h @@ -82,6 +82,9 @@ struct stv0299_config /* Is 13v controlled by OP0 or OP1? */ u8 volt13_op0_op1:1; + /* Turn-off OP0? */ + u8 op0_off:1; + /* minimum delay before retuning */ int min_delay_ms; From da2c7f66174d082e6b8e1b0c9c0576833abfe866 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 20 Apr 2008 22:13:37 -0300 Subject: [PATCH 387/452] V4L/DVB (7662): stv0299: Fixed some typos Fixed some typos. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 2 +- drivers/media/dvb/dvb-usb/opera1.c | 2 +- drivers/media/dvb/frontends/bsru6.h | 2 +- drivers/media/dvb/frontends/stv0299.h | 8 ++++---- drivers/media/dvb/ttpci/budget-av.c | 8 ++++---- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 04989b7a165c..7b0ea3bdfafb 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -252,7 +252,7 @@ static struct stv0299_config samsung_tbmu24112_config = { .mclk = 88000000UL, .invert = 0, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_LK, + .lock_output = STV0299_LOCKOUTPUT_LK, .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index 0eef5fe094e1..7e32d11f32b0 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -246,7 +246,7 @@ static struct stv0299_config opera1_stv0299_config = { .mclk = 88000000UL, .invert = 1, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_0, + .lock_output = STV0299_LOCKOUTPUT_0, .volt13_op0_op1 = STV0299_VOLT13_OP0, .inittab = opera1_inittab, .set_symbol_rate = opera1_stv0299_set_symbol_rate, diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h index e231cd84b3a1..45a6dfd8ebb5 100644 --- a/drivers/media/dvb/frontends/bsru6.h +++ b/drivers/media/dvb/frontends/bsru6.h @@ -133,7 +133,7 @@ static struct stv0299_config alps_bsru6_config = { .mclk = 88000000UL, .invert = 1, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, + .lock_output = STV0299_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, .set_symbol_rate = alps_bsru6_set_symbol_rate, diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index abd9cf8153cf..3282f43022f5 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h @@ -48,10 +48,10 @@ #include #include "dvb_frontend.h" -#define STV0229_LOCKOUTPUT_0 0 -#define STV0229_LOCKOUTPUT_1 1 -#define STV0229_LOCKOUTPUT_CF 2 -#define STV0229_LOCKOUTPUT_LK 3 +#define STV0299_LOCKOUTPUT_0 0 +#define STV0299_LOCKOUTPUT_1 1 +#define STV0299_LOCKOUTPUT_CF 2 +#define STV0299_LOCKOUTPUT_LK 3 #define STV0299_VOLT13_OP0 0 #define STV0299_VOLT13_OP1 1 diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index ed7fb1df554d..b30a5288e484 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -577,7 +577,7 @@ static struct stv0299_config typhoon_config = { .mclk = 88000000UL, .invert = 0, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, + .lock_output = STV0299_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, @@ -590,7 +590,7 @@ static struct stv0299_config cinergy_1200s_config = { .mclk = 88000000UL, .invert = 0, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_0, + .lock_output = STV0299_LOCKOUTPUT_0, .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, @@ -602,7 +602,7 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = { .mclk = 88000000UL, .invert = 1, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, + .lock_output = STV0299_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, @@ -869,7 +869,7 @@ static struct stv0299_config philips_sd1878_config = { .mclk = 88000000UL, .invert = 0, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, + .lock_output = STV0299_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_sd1878_ci_set_symbol_rate, diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 0323515bfd2a..6530323d5406 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -728,7 +728,7 @@ static struct stv0299_config philips_su1278_tt_config = { .mclk = 64000000UL, .invert = 0, .skip_reinit = 1, - .lock_output = STV0229_LOCKOUTPUT_1, + .lock_output = STV0299_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 50, .set_symbol_rate = philips_su1278_tt_set_symbol_rate, diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 46dc4a3fcb6c..732ce4de512e 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1314,7 +1314,7 @@ static struct stv0299_config alps_stv0299_config = { .mclk = 88000000UL, .invert = 1, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, + .lock_output = STV0299_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, .set_symbol_rate = alps_stv0299_set_symbol_rate, From 87dd965f101bafea7c5e507f686814a0f0057417 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 20 Apr 2008 22:34:57 -0300 Subject: [PATCH 388/452] V4L/DVB (7663): budget: Support for Activy budget card with BSBE1 tuner Add support for Activy budget card with BSBE1 tuner, subsystem id 0x1131:0x4f60. Low band and DiSEqC support should work now (BSBE1 and BSRU6 tuner). Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget.c | 77 +++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 7adfe17b0616..2293d80c6e51 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -45,6 +45,7 @@ #include "tda826x.h" #include "lnbp21.h" #include "bsru6.h" +#include "bsbe1.h" static int diseqc_method; module_param(diseqc_method, int, 0444); @@ -368,6 +369,38 @@ static struct tda10086_config tda10086_config = { .xtal_freq = TDA10086_XTAL_16M, }; +static struct stv0299_config alps_bsru6_config_activy = { + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .op0_off = 1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, +}; + +static struct stv0299_config alps_bsbe1_config_activy = { + .demod_address = 0x68, + .inittab = alps_bsbe1_inittab, + .mclk = 88000000UL, + .invert = 1, + .op0_off = 1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsbe1_set_symbol_rate, +}; + + +static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg) +{ + u8 val; + struct i2c_msg msg[] = { + { .addr = adr, .flags = 0, .buf = ®, .len = 1 }, + { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 } + }; + + return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val; +} + static u8 read_pwm(struct budget* budget) { u8 b = 0xff; @@ -383,6 +416,8 @@ static u8 read_pwm(struct budget* budget) static void frontend_init(struct budget *budget) { + (void)alps_bsbe1_config; /* avoid warning */ + switch(budget->dev->pci->subsystem_device) { case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) case 0x1013: @@ -428,15 +463,43 @@ static void frontend_init(struct budget *budget) } break; - case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059)) - budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); - if (budget->dvb_frontend) { - budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; - budget->dvb_frontend->tuner_priv = &budget->i2c_adap; - budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; - budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; + case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */ + { + int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67); + + if (subtype < 0) + break; + /* fixme: find a better way to identify the card */ + if (subtype < 0x36) { + /* assume ALPS BSRU6 */ + budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap); + if (budget->dvb_frontend) { + printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n"); + budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; + budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; + break; + } + } else { + /* assume ALPS BSBE1 */ + /* reset tuner */ + saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO); + msleep(50); + saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI); + msleep(250); + budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap); + if (budget->dvb_frontend) { + printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n"); + budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; + budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; + break; + } } break; + } case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522)) budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap); From 130ca945d83637046bde4943629f011e22831fd3 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 10 Apr 2008 01:18:56 -0300 Subject: [PATCH 389/452] V4L/DVB (7665): videodev: Add default vidioc handler Added default vidioc handler for other private ioctls Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videodev.c | 7 +++++++ include/media/v4l2-dev.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index effcd2ae4152..31e8af0ba278 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1861,6 +1861,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); break; } + default: + { + if (!vfd->vidioc_default) + break; + ret = vfd->vidioc_default(file, fh, cmd, arg); + break; + } } /* switch */ if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index f2114459995d..a807d2f86ee8 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -318,6 +318,10 @@ struct video_device int (*vidioc_g_chip_ident) (struct file *file, void *fh, struct v4l2_chip_ident *chip); + /* For other private ioctls */ + int (*vidioc_default) (struct file *file, void *fh, + int cmd, void *arg); + #ifdef OBSOLETE_OWNER /* to be removed soon */ /* obsolete -- fops->owner is used instead */ From 6ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 10 Apr 2008 02:07:14 -0300 Subject: [PATCH 390/452] V4L/DVB (7666): meye: Replace meye_do_ioctl to use video_ioctl2 Convert meye to use video_ioctl2 Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/meye.c | 1499 +++++++++++++++++------------------- 1 file changed, 722 insertions(+), 777 deletions(-) diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 61c980193c10..e7ccbc895d7a 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -42,15 +42,10 @@ #include MODULE_AUTHOR("Stelian Pop "); -MODULE_DESCRIPTION("v4l/v4l2 driver for the MotionEye camera"); +MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera"); MODULE_LICENSE("GPL"); MODULE_VERSION(MEYE_DRIVER_VERSION); -/* force usage of V4L1 API */ -static int forcev4l1; /* = 0 */ -module_param(forcev4l1, int, 0644); -MODULE_PARM_DESC(forcev4l1, "force use of V4L1 instead of V4L2"); - /* number of grab buffers */ static unsigned int gbuffers = 2; module_param(gbuffers, int, 0444); @@ -876,803 +871,735 @@ static int meye_release(struct inode *inode, struct file *file) return 0; } -static int meye_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +static int meyeioc_g_params(struct meye_params *p) { - switch (cmd) { + *p = meye.params; + return 0; +} - case VIDIOCGCAP: { - struct video_capability *b = arg; - strcpy(b->name,meye.video_dev->name); - b->type = VID_TYPE_CAPTURE; - b->channels = 1; - b->audios = 0; - b->maxwidth = 640; - b->maxheight = 480; - b->minwidth = 320; - b->minheight = 240; - break; +static int meyeioc_s_params(struct meye_params *jp) +{ + if (jp->subsample > 1) + return -EINVAL; + + if (jp->quality > 10) + return -EINVAL; + + if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63) + return -EINVAL; + + if (jp->framerate > 31) + return -EINVAL; + + mutex_lock(&meye.lock); + + if (meye.params.subsample != jp->subsample || + meye.params.quality != jp->quality) + mchip_hic_stop(); /* need restart */ + + meye.params = *jp; + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, + meye.params.sharpness); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, + meye.params.agc); + sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, + meye.params.picture); + mutex_unlock(&meye.lock); + + return 0; +} + +static int meyeioc_qbuf_capt(int *nb) +{ + if (!meye.grab_fbuffer) + return -EINVAL; + + if (*nb >= gbuffers) + return -EINVAL; + + if (*nb < 0) { + /* stop capture */ + mchip_hic_stop(); + return 0; } - case VIDIOCGCHAN: { - struct video_channel *v = arg; - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - if (v->channel != 0) - return -EINVAL; - strcpy(v->name,"Camera"); - break; - } + if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED) + return -EBUSY; - case VIDIOCSCHAN: { - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - break; - } + mutex_lock(&meye.lock); - case VIDIOCGPICT: { - struct video_picture *p = arg; - *p = meye.picture; - break; - } + if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) + mchip_cont_compression_start(); - case VIDIOCSPICT: { - struct video_picture *p = arg; - if (p->depth != 16) - return -EINVAL; - if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV) - return -EINVAL; - mutex_lock(&meye.lock); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, - p->brightness >> 10); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, - p->hue >> 10); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, - p->colour >> 10); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, - p->contrast >> 10); - meye.picture = *p; + meye.grab_buffer[*nb].state = MEYE_BUF_USING; + kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); + mutex_unlock(&meye.lock); + + return 0; +} + +static int meyeioc_sync(struct file *file, void *fh, int *i) +{ + int unused; + + if (*i < 0 || *i >= gbuffers) + return -EINVAL; + + mutex_lock(&meye.lock); + switch (meye.grab_buffer[*i].state) { + + case MEYE_BUF_UNUSED: mutex_unlock(&meye.lock); - break; - } - - case VIDIOCSYNC: { - int *i = arg; - int unused; - - if (*i < 0 || *i >= gbuffers) - return -EINVAL; - - mutex_lock(&meye.lock); - - switch (meye.grab_buffer[*i].state) { - - case MEYE_BUF_UNUSED: - mutex_unlock(&meye.lock); - return -EINVAL; - case MEYE_BUF_USING: - if (file->f_flags & O_NONBLOCK) { - mutex_unlock(&meye.lock); - return -EAGAIN; - } - if (wait_event_interruptible(meye.proc_list, - (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { - mutex_unlock(&meye.lock); - return -EINTR; - } - /* fall through */ - case MEYE_BUF_DONE: - meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); - } - mutex_unlock(&meye.lock); - break; - } - - case VIDIOCMCAPTURE: { - struct video_mmap *vm = arg; - int restart = 0; - - if (vm->frame >= gbuffers || vm->frame < 0) - return -EINVAL; - if (vm->format != VIDEO_PALETTE_YUV422 && vm->format != VIDEO_PALETTE_YUYV) - return -EINVAL; - if (vm->height * vm->width * 2 > gbufsize) - return -EINVAL; - if (!meye.grab_fbuffer) - return -EINVAL; - if (meye.grab_buffer[vm->frame].state != MEYE_BUF_UNUSED) - return -EBUSY; - - mutex_lock(&meye.lock); - if (vm->width == 640 && vm->height == 480) { - if (meye.params.subsample) { - meye.params.subsample = 0; - restart = 1; - } - } else if (vm->width == 320 && vm->height == 240) { - if (!meye.params.subsample) { - meye.params.subsample = 1; - restart = 1; - } - } else { - mutex_unlock(&meye.lock); - return -EINVAL; - } - - if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT) - mchip_continuous_start(); - meye.grab_buffer[vm->frame].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int)); - mutex_unlock(&meye.lock); - break; - } - - case VIDIOCGMBUF: { - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0 , sizeof(*vm)); - vm->size = gbufsize * gbuffers; - vm->frames = gbuffers; - for (i = 0; i < gbuffers; i++) - vm->offsets[i] = i * gbufsize; - break; - } - - case MEYEIOC_G_PARAMS: { - struct meye_params *p = arg; - *p = meye.params; - break; - } - - case MEYEIOC_S_PARAMS: { - struct meye_params *jp = arg; - if (jp->subsample > 1) - return -EINVAL; - if (jp->quality > 10) - return -EINVAL; - if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63) - return -EINVAL; - if (jp->framerate > 31) - return -EINVAL; - mutex_lock(&meye.lock); - if (meye.params.subsample != jp->subsample || - meye.params.quality != jp->quality) - mchip_hic_stop(); /* need restart */ - meye.params = *jp; - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, - meye.params.sharpness); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, - meye.params.agc); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, - meye.params.picture); - mutex_unlock(&meye.lock); - break; - } - - case MEYEIOC_QBUF_CAPT: { - int *nb = arg; - - if (!meye.grab_fbuffer) - return -EINVAL; - if (*nb >= gbuffers) - return -EINVAL; - if (*nb < 0) { - /* stop capture */ - mchip_hic_stop(); - return 0; - } - if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED) - return -EBUSY; - mutex_lock(&meye.lock); - if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) - mchip_cont_compression_start(); - meye.grab_buffer[*nb].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); - mutex_unlock(&meye.lock); - break; - } - - case MEYEIOC_SYNC: { - int *i = arg; - int unused; - - if (*i < 0 || *i >= gbuffers) - return -EINVAL; - - mutex_lock(&meye.lock); - switch (meye.grab_buffer[*i].state) { - - case MEYE_BUF_UNUSED: - mutex_unlock(&meye.lock); - return -EINVAL; - case MEYE_BUF_USING: - if (file->f_flags & O_NONBLOCK) { - mutex_unlock(&meye.lock); - return -EAGAIN; - } - if (wait_event_interruptible(meye.proc_list, - (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { - mutex_unlock(&meye.lock); - return -EINTR; - } - /* fall through */ - case MEYE_BUF_DONE: - meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); - } - *i = meye.grab_buffer[*i].size; - mutex_unlock(&meye.lock); - break; - } - - case MEYEIOC_STILLCAPT: { - - if (!meye.grab_fbuffer) - return -EINVAL; - if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) - return -EBUSY; - mutex_lock(&meye.lock); - meye.grab_buffer[0].state = MEYE_BUF_USING; - mchip_take_picture(); - mchip_get_picture( - meye.grab_fbuffer, - mchip_hsize() * mchip_vsize() * 2); - meye.grab_buffer[0].state = MEYE_BUF_DONE; - mutex_unlock(&meye.lock); - break; - } - - case MEYEIOC_STILLJCAPT: { - int *len = arg; - - if (!meye.grab_fbuffer) - return -EINVAL; - if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) - return -EBUSY; - mutex_lock(&meye.lock); - meye.grab_buffer[0].state = MEYE_BUF_USING; - *len = -1; - while (*len == -1) { - mchip_take_picture(); - *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize); - } - meye.grab_buffer[0].state = MEYE_BUF_DONE; - mutex_unlock(&meye.lock); - break; - } - - case VIDIOC_QUERYCAP: { - struct v4l2_capability *cap = arg; - - if (forcev4l1) - return -EINVAL; - - memset(cap, 0, sizeof(*cap)); - strcpy(cap->driver, "meye"); - strcpy(cap->card, "meye"); - sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev)); - cap->version = (MEYE_DRIVER_MAJORVERSION << 8) + - MEYE_DRIVER_MINORVERSION; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING; - break; - } - - case VIDIOC_ENUMINPUT: { - struct v4l2_input *i = arg; - - if (i->index != 0) - return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = 0; - strcpy(i->name, "Camera"); - i->type = V4L2_INPUT_TYPE_CAMERA; - break; - } - - case VIDIOC_G_INPUT: { - int *i = arg; - - *i = 0; - break; - } - - case VIDIOC_S_INPUT: { - int *i = arg; - - if (*i != 0) - return -EINVAL; - break; - } - - case VIDIOC_QUERYCTRL: { - struct v4l2_queryctrl *c = arg; - - switch (c->id) { - - case V4L2_CID_BRIGHTNESS: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Brightness"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - c->flags = 0; - break; - case V4L2_CID_HUE: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Hue"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - c->flags = 0; - break; - case V4L2_CID_CONTRAST: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Contrast"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - c->flags = 0; - break; - case V4L2_CID_SATURATION: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Saturation"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - c->flags = 0; - break; - case V4L2_CID_AGC: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Agc"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 48; - c->flags = 0; - break; - case V4L2_CID_MEYE_SHARPNESS: - case V4L2_CID_SHARPNESS: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Sharpness"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - - /* Continue to report legacy private SHARPNESS ctrl but - * say it is disabled in preference to ctrl in the spec - */ - c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 : - V4L2_CTRL_FLAG_DISABLED; - break; - case V4L2_CID_PICTURE: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Picture"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 0; - c->flags = 0; - break; - case V4L2_CID_JPEGQUAL: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "JPEG quality"); - c->minimum = 0; - c->maximum = 10; - c->step = 1; - c->default_value = 8; - c->flags = 0; - break; - case V4L2_CID_FRAMERATE: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Framerate"); - c->minimum = 0; - c->maximum = 31; - c->step = 1; - c->default_value = 0; - c->flags = 0; - break; - default: - return -EINVAL; - } - break; - } - - case VIDIOC_S_CTRL: { - struct v4l2_control *c = arg; - - mutex_lock(&meye.lock); - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value); - meye.picture.brightness = c->value << 10; - break; - case V4L2_CID_HUE: - sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERAHUE, c->value); - meye.picture.hue = c->value << 10; - break; - case V4L2_CID_CONTRAST: - sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value); - meye.picture.contrast = c->value << 10; - break; - case V4L2_CID_SATURATION: - sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERACOLOR, c->value); - meye.picture.colour = c->value << 10; - break; - case V4L2_CID_AGC: - sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERAAGC, c->value); - 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; - break; - case V4L2_CID_PICTURE: - sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value); - meye.params.picture = c->value; - break; - case V4L2_CID_JPEGQUAL: - meye.params.quality = c->value; - break; - case V4L2_CID_FRAMERATE: - meye.params.framerate = c->value; - break; - default: - mutex_unlock(&meye.lock); - return -EINVAL; - } - mutex_unlock(&meye.lock); - break; - } - - case VIDIOC_G_CTRL: { - struct v4l2_control *c = arg; - - mutex_lock(&meye.lock); - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - c->value = meye.picture.brightness >> 10; - break; - case V4L2_CID_HUE: - c->value = meye.picture.hue >> 10; - break; - case V4L2_CID_CONTRAST: - c->value = meye.picture.contrast >> 10; - break; - case V4L2_CID_SATURATION: - c->value = meye.picture.colour >> 10; - break; - case V4L2_CID_AGC: - c->value = meye.params.agc; - break; - case V4L2_CID_SHARPNESS: - case V4L2_CID_MEYE_SHARPNESS: - c->value = meye.params.sharpness; - break; - case V4L2_CID_PICTURE: - c->value = meye.params.picture; - break; - case V4L2_CID_JPEGQUAL: - c->value = meye.params.quality; - break; - case V4L2_CID_FRAMERATE: - c->value = meye.params.framerate; - break; - default: - mutex_unlock(&meye.lock); - return -EINVAL; - } - mutex_unlock(&meye.lock); - break; - } - - case VIDIOC_ENUM_FMT: { - struct v4l2_fmtdesc *f = arg; - - if (f->index > 1) - return -EINVAL; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->index == 0) { - /* standard YUV 422 capture */ - memset(f, 0, sizeof(*f)); - f->index = 0; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->flags = 0; - strcpy(f->description, "YUV422"); - f->pixelformat = V4L2_PIX_FMT_YUYV; - } else { - /* compressed MJPEG capture */ - memset(f, 0, sizeof(*f)); - f->index = 1; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - strcpy(f->description, "MJPEG"); - f->pixelformat = V4L2_PIX_FMT_MJPEG; - } - break; - } - - case VIDIOC_TRY_FMT: { - struct v4l2_format *f = arg; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && - f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) - return -EINVAL; - if (f->fmt.pix.field != V4L2_FIELD_ANY && - f->fmt.pix.field != V4L2_FIELD_NONE) - return -EINVAL; - f->fmt.pix.field = V4L2_FIELD_NONE; - if (f->fmt.pix.width <= 320) { - f->fmt.pix.width = 320; - f->fmt.pix.height = 240; - } else { - f->fmt.pix.width = 640; - f->fmt.pix.height = 480; - } - f->fmt.pix.bytesperline = f->fmt.pix.width * 2; - f->fmt.pix.sizeimage = f->fmt.pix.height * - f->fmt.pix.bytesperline; - f->fmt.pix.colorspace = 0; - f->fmt.pix.priv = 0; - break; - } - - case VIDIOC_G_FMT: { - struct v4l2_format *f = arg; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - switch (meye.mchip_mode) { - case MCHIP_HIC_MODE_CONT_OUT: - default: - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - break; - case MCHIP_HIC_MODE_CONT_COMP: - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; - break; - } - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.width = mchip_hsize(); - f->fmt.pix.height = mchip_vsize(); - f->fmt.pix.bytesperline = f->fmt.pix.width * 2; - f->fmt.pix.sizeimage = f->fmt.pix.height * - f->fmt.pix.bytesperline; - f->fmt.pix.colorspace = 0; - f->fmt.pix.priv = 0; - break; - } - - case VIDIOC_S_FMT: { - struct v4l2_format *f = arg; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && - f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) - return -EINVAL; - if (f->fmt.pix.field != V4L2_FIELD_ANY && - f->fmt.pix.field != V4L2_FIELD_NONE) - return -EINVAL; - f->fmt.pix.field = V4L2_FIELD_NONE; - mutex_lock(&meye.lock); - if (f->fmt.pix.width <= 320) { - f->fmt.pix.width = 320; - f->fmt.pix.height = 240; - meye.params.subsample = 1; - } else { - f->fmt.pix.width = 640; - f->fmt.pix.height = 480; - meye.params.subsample = 0; - } - switch (f->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_YUYV: - meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT; - break; - case V4L2_PIX_FMT_MJPEG: - meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP; - break; - } - mutex_unlock(&meye.lock); - f->fmt.pix.bytesperline = f->fmt.pix.width * 2; - f->fmt.pix.sizeimage = f->fmt.pix.height * - f->fmt.pix.bytesperline; - f->fmt.pix.colorspace = 0; - f->fmt.pix.priv = 0; - - break; - } - - case VIDIOC_REQBUFS: { - struct v4l2_requestbuffers *req = arg; - int i; - - if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (req->memory != V4L2_MEMORY_MMAP) - return -EINVAL; - if (meye.grab_fbuffer && req->count == gbuffers) { - /* already allocated, no modifications */ - break; - } - mutex_lock(&meye.lock); - if (meye.grab_fbuffer) { - for (i = 0; i < gbuffers; i++) - if (meye.vma_use_count[i]) { - mutex_unlock(&meye.lock); - return -EINVAL; - } - rvfree(meye.grab_fbuffer, gbuffers * gbufsize); - meye.grab_fbuffer = NULL; - } - gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS)); - req->count = gbuffers; - meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize); - if (!meye.grab_fbuffer) { - printk(KERN_ERR "meye: v4l framebuffer allocation" - " failed\n"); - mutex_unlock(&meye.lock); - return -ENOMEM; - } - for (i = 0; i < gbuffers; i++) - meye.vma_use_count[i] = 0; - mutex_unlock(&meye.lock); - break; - } - - case VIDIOC_QUERYBUF: { - struct v4l2_buffer *buf = arg; - int index = buf->index; - - if (index < 0 || index >= gbuffers) - return -EINVAL; - memset(buf, 0, sizeof(*buf)); - buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf->index = index; - buf->bytesused = meye.grab_buffer[index].size; - buf->flags = V4L2_BUF_FLAG_MAPPED; - if (meye.grab_buffer[index].state == MEYE_BUF_USING) - buf->flags |= V4L2_BUF_FLAG_QUEUED; - if (meye.grab_buffer[index].state == MEYE_BUF_DONE) - buf->flags |= V4L2_BUF_FLAG_DONE; - buf->field = V4L2_FIELD_NONE; - buf->timestamp = meye.grab_buffer[index].timestamp; - buf->sequence = meye.grab_buffer[index].sequence; - buf->memory = V4L2_MEMORY_MMAP; - buf->m.offset = index * gbufsize; - buf->length = gbufsize; - break; - } - - case VIDIOC_QBUF: { - struct v4l2_buffer *buf = arg; - - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (buf->memory != V4L2_MEMORY_MMAP) - return -EINVAL; - if (buf->index < 0 || buf->index >= gbuffers) - return -EINVAL; - if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED) - return -EINVAL; - mutex_lock(&meye.lock); - buf->flags |= V4L2_BUF_FLAG_QUEUED; - buf->flags &= ~V4L2_BUF_FLAG_DONE; - meye.grab_buffer[buf->index].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); - mutex_unlock(&meye.lock); - break; - } - - case VIDIOC_DQBUF: { - struct v4l2_buffer *buf = arg; - int reqnr; - - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (buf->memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - mutex_lock(&meye.lock); - if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { + return -EINVAL; + case MEYE_BUF_USING: + if (file->f_flags & O_NONBLOCK) { mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, - kfifo_len(meye.doneq) != 0) < 0) { + (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { mutex_unlock(&meye.lock); return -EINTR; } - if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, - sizeof(int))) { - mutex_unlock(&meye.lock); - return -EBUSY; - } - if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) { - mutex_unlock(&meye.lock); - return -EINVAL; - } - buf->index = reqnr; - buf->bytesused = meye.grab_buffer[reqnr].size; - buf->flags = V4L2_BUF_FLAG_MAPPED; - buf->field = V4L2_FIELD_NONE; - buf->timestamp = meye.grab_buffer[reqnr].timestamp; - buf->sequence = meye.grab_buffer[reqnr].sequence; - buf->memory = V4L2_MEMORY_MMAP; - buf->m.offset = reqnr * gbufsize; - buf->length = gbufsize; - meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED; - mutex_unlock(&meye.lock); - break; + /* fall through */ + case MEYE_BUF_DONE: + meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; + kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); + } + *i = meye.grab_buffer[*i].size; + mutex_unlock(&meye.lock); + return 0; +} + +static int meyeioc_stillcapt(void) +{ + if (!meye.grab_fbuffer) + return -EINVAL; + + if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) + return -EBUSY; + + mutex_lock(&meye.lock); + meye.grab_buffer[0].state = MEYE_BUF_USING; + mchip_take_picture(); + + mchip_get_picture(meye.grab_fbuffer, + mchip_hsize() * mchip_vsize() * 2); + + meye.grab_buffer[0].state = MEYE_BUF_DONE; + mutex_unlock(&meye.lock); + + return 0; +} + +static int meyeioc_stilljcapt(int *len) +{ + if (!meye.grab_fbuffer) + return -EINVAL; + + if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) + return -EBUSY; + + mutex_lock(&meye.lock); + meye.grab_buffer[0].state = MEYE_BUF_USING; + *len = -1; + + while (*len == -1) { + mchip_take_picture(); + *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize); } - case VIDIOC_STREAMON: { - mutex_lock(&meye.lock); - switch (meye.mchip_mode) { - case MCHIP_HIC_MODE_CONT_OUT: - mchip_continuous_start(); - break; - case MCHIP_HIC_MODE_CONT_COMP: - mchip_cont_compression_start(); - break; - default: - mutex_unlock(&meye.lock); - return -EINVAL; - } - mutex_unlock(&meye.lock); + meye.grab_buffer[0].state = MEYE_BUF_DONE; + mutex_unlock(&meye.lock); + return 0; +} + +static int vidioc_querycap(struct file *file, void *fh, + struct v4l2_capability *cap) +{ + memset(cap, 0, sizeof(*cap)); + strcpy(cap->driver, "meye"); + strcpy(cap->card, "meye"); + sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev)); + + cap->version = (MEYE_DRIVER_MAJORVERSION << 8) + + MEYE_DRIVER_MINORVERSION; + + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING; + + return 0; +} + +static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) +{ + if (i->index != 0) + return -EINVAL; + + memset(i, 0, sizeof(*i)); + i->index = 0; + strcpy(i->name, "Camera"); + i->type = V4L2_INPUT_TYPE_CAMERA; + + return 0; +} + +static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *file, void *fh, unsigned int i) +{ + if (i != 0) + return -EINVAL; + + return 0; +} + +static int vidioc_queryctrl(struct file *file, void *fh, + struct v4l2_queryctrl *c) +{ + switch (c->id) { + + case V4L2_CID_BRIGHTNESS: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Brightness"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; break; - } - - case VIDIOC_STREAMOFF: { - int i; - - mutex_lock(&meye.lock); - mchip_hic_stop(); - kfifo_reset(meye.grabq); - kfifo_reset(meye.doneq); - for (i = 0; i < MEYE_MAX_BUFNBRS; i++) - meye.grab_buffer[i].state = MEYE_BUF_UNUSED; - mutex_unlock(&meye.lock); + case V4L2_CID_HUE: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Hue"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; break; - } - - /* - * XXX what about private snapshot ioctls ? - * Do they need to be converted to V4L2 ? - */ + case V4L2_CID_CONTRAST: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Contrast"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; + break; + case V4L2_CID_SATURATION: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Saturation"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; + break; + case V4L2_CID_AGC: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Agc"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 48; + c->flags = 0; + break; + case V4L2_CID_MEYE_SHARPNESS: + case V4L2_CID_SHARPNESS: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Sharpness"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + /* Continue to report legacy private SHARPNESS ctrl but + * say it is disabled in preference to ctrl in the spec + */ + c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 : + V4L2_CTRL_FLAG_DISABLED; + break; + case V4L2_CID_PICTURE: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Picture"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 0; + c->flags = 0; + break; + case V4L2_CID_JPEGQUAL: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "JPEG quality"); + c->minimum = 0; + c->maximum = 10; + c->step = 1; + c->default_value = 8; + c->flags = 0; + break; + case V4L2_CID_FRAMERATE: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Framerate"); + c->minimum = 0; + c->maximum = 31; + c->step = 1; + c->default_value = 0; + c->flags = 0; + break; default: - return -ENOIOCTLCMD; + return -EINVAL; } return 0; } -static int meye_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) { - return video_usercopy(inode, file, cmd, arg, meye_do_ioctl); + mutex_lock(&meye.lock); + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value); + meye.picture.brightness = c->value << 10; + break; + case V4L2_CID_HUE: + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERAHUE, c->value); + meye.picture.hue = c->value << 10; + break; + case V4L2_CID_CONTRAST: + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value); + meye.picture.contrast = c->value << 10; + break; + case V4L2_CID_SATURATION: + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERACOLOR, c->value); + meye.picture.colour = c->value << 10; + break; + case V4L2_CID_AGC: + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERAAGC, c->value); + 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; + break; + case V4L2_CID_PICTURE: + sony_pic_camera_command( + SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value); + meye.params.picture = c->value; + break; + case V4L2_CID_JPEGQUAL: + meye.params.quality = c->value; + break; + case V4L2_CID_FRAMERATE: + meye.params.framerate = c->value; + break; + default: + mutex_unlock(&meye.lock); + return -EINVAL; + } + mutex_unlock(&meye.lock); + + return 0; +} + +static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c) +{ + mutex_lock(&meye.lock); + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + c->value = meye.picture.brightness >> 10; + break; + case V4L2_CID_HUE: + c->value = meye.picture.hue >> 10; + break; + case V4L2_CID_CONTRAST: + c->value = meye.picture.contrast >> 10; + break; + case V4L2_CID_SATURATION: + c->value = meye.picture.colour >> 10; + break; + case V4L2_CID_AGC: + c->value = meye.params.agc; + break; + case V4L2_CID_SHARPNESS: + case V4L2_CID_MEYE_SHARPNESS: + c->value = meye.params.sharpness; + break; + case V4L2_CID_PICTURE: + c->value = meye.params.picture; + break; + case V4L2_CID_JPEGQUAL: + c->value = meye.params.quality; + break; + case V4L2_CID_FRAMERATE: + c->value = meye.params.framerate; + break; + default: + mutex_unlock(&meye.lock); + return -EINVAL; + } + mutex_unlock(&meye.lock); + + return 0; +} + +static int vidioc_enum_fmt_cap(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + if (f->index > 1) + return -EINVAL; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (f->index == 0) { + /* standard YUV 422 capture */ + memset(f, 0, sizeof(*f)); + f->index = 0; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->flags = 0; + strcpy(f->description, "YUV422"); + f->pixelformat = V4L2_PIX_FMT_YUYV; + } else { + /* compressed MJPEG capture */ + memset(f, 0, sizeof(*f)); + f->index = 1; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strcpy(f->description, "MJPEG"); + f->pixelformat = V4L2_PIX_FMT_MJPEG; + } + + return 0; +} + +static int vidioc_try_fmt_cap(struct file *file, void *fh, + struct v4l2_format *f) +{ + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && + f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) + return -EINVAL; + + if (f->fmt.pix.field != V4L2_FIELD_ANY && + f->fmt.pix.field != V4L2_FIELD_NONE) + return -EINVAL; + + f->fmt.pix.field = V4L2_FIELD_NONE; + + if (f->fmt.pix.width <= 320) { + f->fmt.pix.width = 320; + f->fmt.pix.height = 240; + } else { + f->fmt.pix.width = 640; + f->fmt.pix.height = 480; + } + + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + + return 0; +} + +static int vidioc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) +{ + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + switch (meye.mchip_mode) { + case MCHIP_HIC_MODE_CONT_OUT: + default: + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + break; + case MCHIP_HIC_MODE_CONT_COMP: + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; + break; + } + + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.width = mchip_hsize(); + f->fmt.pix.height = mchip_vsize(); + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + + return 0; +} + +static int vidioc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) +{ + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && + f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) + return -EINVAL; + + if (f->fmt.pix.field != V4L2_FIELD_ANY && + f->fmt.pix.field != V4L2_FIELD_NONE) + return -EINVAL; + + f->fmt.pix.field = V4L2_FIELD_NONE; + mutex_lock(&meye.lock); + + if (f->fmt.pix.width <= 320) { + f->fmt.pix.width = 320; + f->fmt.pix.height = 240; + meye.params.subsample = 1; + } else { + f->fmt.pix.width = 640; + f->fmt.pix.height = 480; + meye.params.subsample = 0; + } + + switch (f->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_YUYV: + meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT; + break; + case V4L2_PIX_FMT_MJPEG: + meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP; + break; + } + + mutex_unlock(&meye.lock); + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + + return 0; +} + +static int vidioc_reqbufs(struct file *file, void *fh, + struct v4l2_requestbuffers *req) +{ + int i; + + if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (req->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (meye.grab_fbuffer && req->count == gbuffers) { + /* already allocated, no modifications */ + return 0; + } + + mutex_lock(&meye.lock); + if (meye.grab_fbuffer) { + for (i = 0; i < gbuffers; i++) + if (meye.vma_use_count[i]) { + mutex_unlock(&meye.lock); + return -EINVAL; + } + rvfree(meye.grab_fbuffer, gbuffers * gbufsize); + meye.grab_fbuffer = NULL; + } + + gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS)); + req->count = gbuffers; + meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize); + + if (!meye.grab_fbuffer) { + printk(KERN_ERR "meye: v4l framebuffer allocation" + " failed\n"); + mutex_unlock(&meye.lock); + return -ENOMEM; + } + + for (i = 0; i < gbuffers; i++) + meye.vma_use_count[i] = 0; + + mutex_unlock(&meye.lock); + + return 0; +} + +static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) +{ + int index = buf->index; + + if (index < 0 || index >= gbuffers) + return -EINVAL; + + memset(buf, 0, sizeof(*buf)); + + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf->index = index; + buf->bytesused = meye.grab_buffer[index].size; + buf->flags = V4L2_BUF_FLAG_MAPPED; + + if (meye.grab_buffer[index].state == MEYE_BUF_USING) + buf->flags |= V4L2_BUF_FLAG_QUEUED; + + if (meye.grab_buffer[index].state == MEYE_BUF_DONE) + buf->flags |= V4L2_BUF_FLAG_DONE; + + buf->field = V4L2_FIELD_NONE; + buf->timestamp = meye.grab_buffer[index].timestamp; + buf->sequence = meye.grab_buffer[index].sequence; + buf->memory = V4L2_MEMORY_MMAP; + buf->m.offset = index * gbufsize; + buf->length = gbufsize; + + return 0; +} + +static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) +{ + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (buf->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (buf->index < 0 || buf->index >= gbuffers) + return -EINVAL; + + if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED) + return -EINVAL; + + mutex_lock(&meye.lock); + buf->flags |= V4L2_BUF_FLAG_QUEUED; + buf->flags &= ~V4L2_BUF_FLAG_DONE; + meye.grab_buffer[buf->index].state = MEYE_BUF_USING; + kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); + mutex_unlock(&meye.lock); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) +{ + int reqnr; + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (buf->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + mutex_lock(&meye.lock); + + if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { + mutex_unlock(&meye.lock); + return -EAGAIN; + } + + if (wait_event_interruptible(meye.proc_list, + kfifo_len(meye.doneq) != 0) < 0) { + mutex_unlock(&meye.lock); + return -EINTR; + } + + if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, + sizeof(int))) { + mutex_unlock(&meye.lock); + return -EBUSY; + } + + if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) { + mutex_unlock(&meye.lock); + return -EINVAL; + } + + buf->index = reqnr; + buf->bytesused = meye.grab_buffer[reqnr].size; + buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->field = V4L2_FIELD_NONE; + buf->timestamp = meye.grab_buffer[reqnr].timestamp; + buf->sequence = meye.grab_buffer[reqnr].sequence; + buf->memory = V4L2_MEMORY_MMAP; + buf->m.offset = reqnr * gbufsize; + buf->length = gbufsize; + meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED; + mutex_unlock(&meye.lock); + + return 0; +} + +static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) +{ + mutex_lock(&meye.lock); + + switch (meye.mchip_mode) { + case MCHIP_HIC_MODE_CONT_OUT: + mchip_continuous_start(); + break; + case MCHIP_HIC_MODE_CONT_COMP: + mchip_cont_compression_start(); + break; + default: + mutex_unlock(&meye.lock); + return -EINVAL; + } + + mutex_unlock(&meye.lock); + + return 0; +} + +static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) +{ + mutex_lock(&meye.lock); + mchip_hic_stop(); + kfifo_reset(meye.grabq); + kfifo_reset(meye.doneq); + + for (i = 0; i < MEYE_MAX_BUFNBRS; i++) + meye.grab_buffer[i].state = MEYE_BUF_UNUSED; + + mutex_unlock(&meye.lock); + return 0; +} + +static int vidioc_default(struct file *file, void *fh, int cmd, void *arg) +{ + switch (cmd) { + case MEYEIOC_G_PARAMS: + return meyeioc_g_params((struct meye_params *) arg); + + case MEYEIOC_S_PARAMS: + return meyeioc_s_params((struct meye_params *) arg); + + case MEYEIOC_QBUF_CAPT: + return meyeioc_qbuf_capt((int *) arg); + + case MEYEIOC_SYNC: + return meyeioc_sync(file, fh, (int *) arg); + + case MEYEIOC_STILLCAPT: + return meyeioc_stillcapt(); + + case MEYEIOC_STILLJCAPT: + return meyeioc_stilljcapt((int *) arg); + + default: + return -EINVAL; + } + } static unsigned int meye_poll(struct file *file, poll_table *wait) @@ -1760,7 +1687,7 @@ static const struct file_operations meye_fops = { .open = meye_open, .release = meye_release, .mmap = meye_mmap, - .ioctl = meye_ioctl, + .ioctl = video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, #endif @@ -1775,6 +1702,24 @@ static struct video_device meye_template = { .fops = &meye_fops, .release = video_device_release, .minor = -1, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, + .vidioc_try_fmt_cap = vidioc_try_fmt_cap, + .vidioc_g_fmt_cap = vidioc_g_fmt_cap, + .vidioc_s_fmt_cap = vidioc_s_fmt_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_default = vidioc_default, }; #ifdef CONFIG_PM From 587df9fca6496f4236c526b2c83f068a63cfd769 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 10:33:39 -0300 Subject: [PATCH 391/452] V4L/DVB (7668): soc-camera: Remove redundant return This obviously redundant return has been in the driver from the very first version. Remove it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 91a1251d904d..a1b92446c8b4 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -144,8 +144,6 @@ static int soc_camera_reqbufs(struct file *file, void *priv, return ret; return ici->ops->reqbufs(icf, p); - - return ret; } static int soc_camera_querybuf(struct file *file, void *priv, From a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 22 Apr 2008 10:36:32 -0300 Subject: [PATCH 392/452] V4L/DVB (7669): pxa_camera: Add support for YUV modes This patch adds support for YUV packed and planar capture for pxa_camera. Signed-off-by: Mike Rapoport Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 408 +++++++++++++++++++++++-------- 1 file changed, 300 insertions(+), 108 deletions(-) diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 936db67a5b0f..b999bda23c48 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -49,6 +49,9 @@ #define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */ #define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */ +#define CICR1_COLOR_SP_VAL(x) (((x) << 3) & CICR1_COLOR_SP) /* color space */ +#define CICR1_RGB_BPP_VAL(x) (((x) << 7) & CICR1_RGB_BPP) /* bpp for rgb */ +#define CICR1_RGBT_CONV_VAL(x) (((x) << 29) & CICR1_RGBT_CONV) /* rgbt conv */ #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 */ @@ -70,6 +73,19 @@ static DEFINE_MUTEX(camera_lock); /* * Structures */ +enum pxa_camera_active_dma { + DMA_Y = 0x1, + DMA_U = 0x2, + DMA_V = 0x4, +}; + +/* descriptor needed for the PXA DMA engine */ +struct pxa_cam_dma { + dma_addr_t sg_dma; + struct pxa_dma_desc *sg_cpu; + size_t sg_size; + int sglen; +}; /* buffer for one video frame */ struct pxa_buffer { @@ -78,11 +94,12 @@ struct pxa_buffer { 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; + /* our descriptor lists for Y, U and V channels */ + struct pxa_cam_dma dmas[3]; + int inwork; + + enum pxa_camera_active_dma active_dma; }; struct pxa_framebuffer_queue { @@ -100,7 +117,8 @@ struct pxa_camera_dev { unsigned int irq; void __iomem *base; - unsigned int dma_chan_y; + + unsigned int dma_chans[3]; struct pxacamera_platform_data *pdata; struct resource *res; @@ -128,7 +146,15 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); - *size = icd->width * icd->height * ((icd->current_fmt->depth + 7) >> 3); + /* planar capture requires Y, U and V buffers to be page aligned */ + if (icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P) { + *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */ + *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */ + *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */ + } else { + *size = icd->width * icd->height * + ((icd->current_fmt->depth + 7) >> 3); + } if (0 == *count) *count = 32; @@ -145,6 +171,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + int i; BUG_ON(in_interrupt()); @@ -157,14 +184,62 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) 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; + for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { + if (buf->dmas[i].sg_cpu) + dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size, + buf->dmas[i].sg_cpu, + buf->dmas[i].sg_dma); + buf->dmas[i].sg_cpu = NULL; + } buf->vb.state = VIDEOBUF_NEEDS_INIT; } +static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, + struct pxa_buffer *buf, + struct videobuf_dmabuf *dma, int channel, + int sglen, int sg_start, int cibr, + unsigned int size) +{ + struct pxa_cam_dma *pxa_dma = &buf->dmas[channel]; + int i; + + if (pxa_dma->sg_cpu) + dma_free_coherent(pcdev->dev, pxa_dma->sg_size, + pxa_dma->sg_cpu, pxa_dma->sg_dma); + + pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc); + pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size, + &pxa_dma->sg_dma, GFP_KERNEL); + if (!pxa_dma->sg_cpu) + return -ENOMEM; + + pxa_dma->sglen = sglen; + + for (i = 0; i < sglen; i++) { + int sg_i = sg_start + i; + struct scatterlist *sg = dma->sglist; + unsigned int dma_len = sg_dma_len(&sg[sg_i]), xfer_len; + + pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr; + pxa_dma->sg_cpu[i].dtadr = sg_dma_address(&sg[sg_i]); + + /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */ + xfer_len = (min(dma_len, size) + 7) & ~7; + + pxa_dma->sg_cpu[i].dcmd = + DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len; + size -= dma_len; + pxa_dma->sg_cpu[i].ddadr = + pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); + } + + pxa_dma->sg_cpu[sglen - 1].ddadr = DDADR_STOP; + pxa_dma->sg_cpu[sglen - 1].dcmd |= DCMD_ENDIRQEN; + + return 0; +} + static int pxa_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) { @@ -173,7 +248,9 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, 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; + int ret; + int sglen_y, sglen_yu = 0, sglen_u = 0, sglen_v = 0; + int size_y, size_u = 0, size_v = 0; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -218,49 +295,64 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, if (ret) goto fail; - if (buf->sg_cpu) - dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu, - buf->sg_dma); + if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) { + /* FIXME the calculations should be more precise */ + sglen_y = dma->sglen / 2; + sglen_u = sglen_v = dma->sglen / 4 + 1; + sglen_yu = sglen_y + sglen_u; + size_y = size / 2; + size_u = size_v = size / 4; + } else { + sglen_y = dma->sglen; + size_y = size; + } - 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; + /* init DMA for Y channel */ + ret = pxa_init_dma_channel(pcdev, buf, dma, 0, sglen_y, + 0, 0x28, size_y); + + if (ret) { + dev_err(pcdev->dev, + "DMA initialization for Y/RGB failed\n"); 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; + if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) { + /* init DMA for U channel */ + ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u, + sglen_y, 0x30, size_u); + if (ret) { + dev_err(pcdev->dev, + "DMA initialization for U failed\n"); + goto fail_u; + } - /* 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); + /* init DMA for V channel */ + ret = pxa_init_dma_channel(pcdev, buf, dma, 2, sglen_v, + sglen_yu, 0x38, size_v); + if (ret) { + dev_err(pcdev->dev, + "DMA initialization for V failed\n"); + goto fail_v; + } } - 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; + buf->active_dma = DMA_Y; + if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) + buf->active_dma |= DMA_U | DMA_V; return 0; +fail_v: + dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size, + buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma); +fail_u: + dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size, + buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma); fail: free_buffer(vq, buf); out: @@ -277,8 +369,6 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); struct pxa_buffer *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", __func__, @@ -292,59 +382,86 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, if (!active) { CIFR |= CIFR_RESET_F; - DDADR(pcdev->dma_chan_y) = buf->sg_dma; - DCSR(pcdev->dma_chan_y) = DCSR_RUN; + DDADR(pcdev->dma_chans[0]) = buf->dmas[0].sg_dma; + DCSR(pcdev->dma_chans[0]) = DCSR_RUN; + + if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) { + DDADR(pcdev->dma_chans[1]) = buf->dmas[1].sg_dma; + DCSR(pcdev->dma_chans[1]) = DCSR_RUN; + + DDADR(pcdev->dma_chans[2]) = buf->dmas[2].sg_dma; + DCSR(pcdev->dma_chans[2]) = 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; + struct pxa_cam_dma *buf_dma; + struct pxa_cam_dma *act_dma; + int channels = 1; + int nents; + int i; - /* Add the descriptors we just initialized to the currently - * running chain - */ - active->sg_cpu[active_dma->sglen - 1].ddadr = buf->sg_dma; + if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) + channels = 3; - /* 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); + for (i = 0; i < channels; i++) { + buf_dma = &buf->dmas[i]; + act_dma = &active->dmas[i]; + nents = buf_dma->sglen; - 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 + /* Stop DMA engine */ + DCSR(pcdev->dma_chans[i]) = 0; + + /* Add the descriptors we just initialized to + the currently running chain */ + act_dma->sg_cpu[act_dma->sglen - 1].ddadr = + buf_dma->sg_dma; + + /* Setup a dummy descriptor with the DMA engines current + * state */ - buf->sg_cpu[nents].ddadr = buf->sg_dma; - } else { - buf->sg_cpu[nents].ddadr = DDADR(pcdev->dma_chan_y); + buf_dma->sg_cpu[nents].dsadr = + pcdev->res->start + 0x28 + i*8; /* CIBRx */ + buf_dma->sg_cpu[nents].dtadr = + DTADR(pcdev->dma_chans[i]); + buf_dma->sg_cpu[nents].dcmd = + DCMD(pcdev->dma_chans[i]); + + if (DDADR(pcdev->dma_chans[i]) == DDADR_STOP) { + /* The DMA engine is on the last + descriptor, set the next descriptors + address to the descriptors we just + initialized */ + buf_dma->sg_cpu[nents].ddadr = buf_dma->sg_dma; + } else { + buf_dma->sg_cpu[nents].ddadr = + DDADR(pcdev->dma_chans[i]); + } + + /* The next descriptor is the dummy descriptor */ + DDADR(pcdev->dma_chans[i]) = buf_dma->sg_dma + nents * + sizeof(struct pxa_dma_desc); + + DCSR(pcdev->dma_chans[i]) = DCSR_RUN; } - - /* 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) { + if (CISR & (CISR_IFO_0 | CISR_IFO_1 | CISR_IFO_2)) { dev_warn(pcdev->dev, "FIFO overrun\n"); - DDADR(pcdev->dma_chan_y) = pcdev->active->sg_dma; + for (i = 0; i < channels; i++) + DDADR(pcdev->dma_chans[i]) = + pcdev->active->dmas[i].sg_dma; CICR0 &= ~CICR0_ENB; CIFR |= CIFR_RESET_F; - DCSR(pcdev->dma_chan_y) = DCSR_RUN; + for (i = 0; i < channels; i++) + DCSR(pcdev->dma_chans[i]) = 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, @@ -376,9 +493,33 @@ static void pxa_videobuf_release(struct videobuf_queue *vq, free_buffer(vq, buf); } -static void pxa_camera_dma_irq_y(int channel, void *data) +static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, + struct videobuf_buffer *vb, + struct pxa_buffer *buf) +{ + /* _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); + vb->field_count++; + wake_up(&vb->done); + + if (list_empty(&pcdev->capture)) { + pcdev->active = NULL; + DCSR(pcdev->dma_chans[0]) = 0; + DCSR(pcdev->dma_chans[1]) = 0; + DCSR(pcdev->dma_chans[2]) = 0; + CICR0 &= ~CICR0_ENB; + return; + } + + pcdev->active = list_entry(pcdev->capture.next, + struct pxa_buffer, vb.queue); +} + +static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, + enum pxa_camera_active_dma act_dma) { - struct pxa_camera_dev *pcdev = data; struct pxa_buffer *buf; unsigned long flags; unsigned int status; @@ -386,8 +527,8 @@ 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; + status = DCSR(channel); + DCSR(channel) = status | DCSR_ENDINTR; if (status & DCSR_BUSERR) { dev_err(pcdev->dev, "DMA Bus Error IRQ!\n"); @@ -411,27 +552,32 @@ static void pxa_camera_dma_irq_y(int channel, void *data) dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); - /* _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); - 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); + buf->active_dma &= ~act_dma; + if (!buf->active_dma) + pxa_camera_wakeup(pcdev, vb, buf); out: spin_unlock_irqrestore(&pcdev->lock, flags); } +static void pxa_camera_dma_irq_y(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + pxa_camera_dma_irq(channel, pcdev, DMA_Y); +} + +static void pxa_camera_dma_irq_u(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + pxa_camera_dma_irq(channel, pcdev, DMA_U); +} + +static void pxa_camera_dma_irq_v(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + pxa_camera_dma_irq(channel, pcdev, DMA_V); +} + static struct videobuf_queue_ops pxa_videobuf_ops = { .buf_setup = pxa_videobuf_setup, .buf_prepare = pxa_videobuf_prepare, @@ -525,7 +671,6 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status); CISR = status; - return IRQ_HANDLED; } @@ -571,8 +716,11 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) /* disable capture, disable interrupts */ CICR0 = 0x3ff; + /* Stop DMA engine */ - DCSR(pcdev->dma_chan_y) = 0; + DCSR(pcdev->dma_chans[0]) = 0; + DCSR(pcdev->dma_chans[1]) = 0; + DCSR(pcdev->dma_chans[2]) = 0; icd->ops->release(icd); @@ -625,7 +773,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) 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; + u32 cicr0, cicr1, cicr4 = 0; int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); if (ret < 0) @@ -702,7 +850,25 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) cicr0 = CICR0; if (cicr0 & CICR0_ENB) CICR0 = cicr0 & ~CICR0_ENB; - CICR1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw; + + cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw; + + switch (pixfmt) { + case V4L2_PIX_FMT_YUV422P: + cicr1 |= CICR1_YCBCR_F; + case V4L2_PIX_FMT_YUYV: + cicr1 |= CICR1_COLOR_SP_VAL(2); + break; + case V4L2_PIX_FMT_RGB555: + cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) | + CICR1_TBIT | CICR1_COLOR_SP_VAL(1); + break; + case V4L2_PIX_FMT_RGB565: + cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2); + break; + } + + CICR1 = cicr1; CICR2 = 0; CICR3 = CICR3_LPF_VAL(icd->height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); @@ -905,16 +1071,36 @@ static int pxa_camera_probe(struct platform_device *pdev) 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) { + pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, + pxa_camera_dma_irq_y, pcdev); + if (pcdev->dma_chans[0] < 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); + dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); - DRCMR68 = pcdev->dma_chan_y | DRCMR_MAPVLD; + pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH, + pxa_camera_dma_irq_u, pcdev); + if (pcdev->dma_chans[1] < 0) { + dev_err(pcdev->dev, "Can't request DMA for U\n"); + err = -ENOMEM; + goto exit_free_dma_y; + } + dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); + + pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH, + pxa_camera_dma_irq_v, pcdev); + if (pcdev->dma_chans[0] < 0) { + dev_err(pcdev->dev, "Can't request DMA for V\n"); + err = -ENOMEM; + goto exit_free_dma_u; + } + dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); + + DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD; + DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD; + DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD; /* request irq */ err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME, @@ -936,7 +1122,11 @@ static int pxa_camera_probe(struct platform_device *pdev) exit_free_irq: free_irq(pcdev->irq, pcdev); exit_free_dma: - pxa_free_dma(pcdev->dma_chan_y); + pxa_free_dma(pcdev->dma_chans[2]); +exit_free_dma_u: + pxa_free_dma(pcdev->dma_chans[1]); +exit_free_dma_y: + pxa_free_dma(pcdev->dma_chans[0]); exit_iounmap: iounmap(base); exit_release: @@ -956,7 +1146,9 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev) clk_put(pcdev->clk); - pxa_free_dma(pcdev->dma_chan_y); + pxa_free_dma(pcdev->dma_chans[0]); + pxa_free_dma(pcdev->dma_chans[1]); + pxa_free_dma(pcdev->dma_chans[2]); free_irq(pcdev->irq, pcdev); soc_camera_host_unregister(&pxa_soc_camera_host); From e7c506881973d0c762d660005be54c4095219c59 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 10:37:49 -0300 Subject: [PATCH 393/452] V4L/DVB (7670): pxa-camera: handle FIFO overruns FIFO overruns are not seldom on PXA camera interface FIFOs. Handle them by dropping the corrupted frame, waiting for the next start-of-frame, and restarting capture. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 59 +++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index b999bda23c48..1dcfd9109c57 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -118,6 +118,7 @@ struct pxa_camera_dev { unsigned int irq; void __iomem *base; + int channels; unsigned int dma_chans[3]; struct pxacamera_platform_data *pdata; @@ -398,14 +399,10 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, } else { struct pxa_cam_dma *buf_dma; struct pxa_cam_dma *act_dma; - int channels = 1; int nents; int i; - if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) - channels = 3; - - for (i = 0; i < channels; i++) { + for (i = 0; i < pcdev->channels; i++) { buf_dma = &buf->dmas[i]; act_dma = &active->dmas[i]; nents = buf_dma->sglen; @@ -445,20 +442,6 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, DCSR(pcdev->dma_chans[i]) = DCSR_RUN; } -#ifdef DEBUG - if (CISR & (CISR_IFO_0 | CISR_IFO_1 | CISR_IFO_2)) { - dev_warn(pcdev->dev, "FIFO overrun\n"); - for (i = 0; i < channels; i++) - DDADR(pcdev->dma_chans[i]) = - pcdev->active->dmas[i].sg_dma; - - CICR0 &= ~CICR0_ENB; - CIFR |= CIFR_RESET_F; - for (i = 0; i < channels; i++) - DCSR(pcdev->dma_chans[i]) = DCSR_RUN; - CICR0 |= CICR0_ENB; - } -#endif } spin_unlock_irqrestore(&pcdev->lock, flags); @@ -522,7 +505,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, { struct pxa_buffer *buf; unsigned long flags; - unsigned int status; + u32 status, camera_status, overrun; struct videobuf_buffer *vb; spin_lock_irqsave(&pcdev->lock, flags); @@ -546,6 +529,25 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, goto out; } + camera_status = CISR; + overrun = CISR_IFO_0; + if (pcdev->channels == 3) + overrun |= CISR_IFO_1 | CISR_IFO_2; + if (camera_status & overrun) { + dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status); + /* Stop the Capture Interface */ + CICR0 &= ~CICR0_ENB; + /* Stop DMA */ + DCSR(channel) = 0; + /* Reset the FIFOs */ + CIFR |= CIFR_RESET_F; + /* Enable End-Of-Frame Interrupt */ + CICR0 &= ~CICR0_EOFM; + /* Restart the Capture Interface */ + CICR0 |= CICR0_ENB; + goto out; + } + vb = &pcdev->active->vb; buf = container_of(vb, struct pxa_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); @@ -670,7 +672,21 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status); + if (!status) + return IRQ_NONE; + CISR = status; + + if (status & CISR_EOF) { + int i; + for (i = 0; i < pcdev->channels; i++) { + DDADR(pcdev->dma_chans[i]) = + pcdev->active->dmas[i].sg_dma; + DCSR(pcdev->dma_chans[i]) = DCSR_RUN; + } + CICR0 |= CICR0_EOFM; + } + return IRQ_HANDLED; } @@ -785,6 +801,8 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) if (!common_flags) return -EINVAL; + pcdev->channels = 1; + /* Make choises, based on platform preferences */ if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { @@ -855,6 +873,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) switch (pixfmt) { case V4L2_PIX_FMT_YUV422P: + pcdev->channels = 3; cicr1 |= CICR1_YCBCR_F; case V4L2_PIX_FMT_YUYV: cicr1 |= CICR1_COLOR_SP_VAL(2); From 5aa2110f3f33feb4a0c67a4996dc400dc594bc1d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 10:40:23 -0300 Subject: [PATCH 394/452] V4L/DVB (7671): pxa-camera: fix DMA sg-list coalescing for more than 2 buffers Currently the pxa-camera driver has a bug, visible when the user requests more than 2 video buffers. When the third buffer is queued, it is not appended to the DMA-descriptor list of the second buffer, but is again appended to the first buffer. Fix it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 35 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 1dcfd9109c57..7cc8e9b19fb7 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -102,11 +102,6 @@ struct pxa_buffer { enum pxa_camera_active_dma active_dma; }; -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 @@ -131,6 +126,7 @@ struct pxa_camera_dev { spinlock_t lock; struct pxa_buffer *active; + struct pxa_dma_desc *sg_tail[3]; }; static const char *pxa_cam_driver_description = "PXA_Camera"; @@ -144,11 +140,14 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { 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; dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); /* planar capture requires Y, U and V buffers to be page aligned */ - if (icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P) { + if (pcdev->channels == 3) { *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */ *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */ *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */ @@ -296,7 +295,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, if (ret) goto fail; - if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) { + if (pcdev->channels == 3) { /* FIXME the calculations should be more precise */ sglen_y = dma->sglen / 2; sglen_u = sglen_v = dma->sglen / 4 + 1; @@ -318,7 +317,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, goto fail; } - if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) { + if (pcdev->channels == 3) { /* init DMA for U channel */ ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u, sglen_y, 0x30, size_u); @@ -343,7 +342,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 0; buf->active_dma = DMA_Y; - if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) + if (pcdev->channels == 3) buf->active_dma |= DMA_U | DMA_V; return 0; @@ -371,6 +370,7 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); struct pxa_buffer *active; unsigned long flags; + int i; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -383,15 +383,11 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, if (!active) { CIFR |= CIFR_RESET_F; - DDADR(pcdev->dma_chans[0]) = buf->dmas[0].sg_dma; - DCSR(pcdev->dma_chans[0]) = DCSR_RUN; - if (buf->fmt->fourcc == V4L2_PIX_FMT_YUV422P) { - DDADR(pcdev->dma_chans[1]) = buf->dmas[1].sg_dma; - DCSR(pcdev->dma_chans[1]) = DCSR_RUN; - - DDADR(pcdev->dma_chans[2]) = buf->dmas[2].sg_dma; - DCSR(pcdev->dma_chans[2]) = DCSR_RUN; + for (i = 0; i < pcdev->channels; i++) { + DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma; + DCSR(pcdev->dma_chans[i]) = DCSR_RUN; + pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen - 1; } pcdev->active = buf; @@ -400,7 +396,6 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct pxa_cam_dma *buf_dma; struct pxa_cam_dma *act_dma; int nents; - int i; for (i = 0; i < pcdev->channels; i++) { buf_dma = &buf->dmas[i]; @@ -412,8 +407,8 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, /* Add the descriptors we just initialized to the currently running chain */ - act_dma->sg_cpu[act_dma->sglen - 1].ddadr = - buf_dma->sg_dma; + pcdev->sg_tail[i]->ddadr = buf_dma->sg_dma; + pcdev->sg_tail[i] = buf_dma->sg_cpu + buf_dma->sglen - 1; /* Setup a dummy descriptor with the DMA engines current * state From a38d6e37c0bc073bae5eff37c939978974ea9712 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 22 Apr 2008 15:37:01 -0300 Subject: [PATCH 395/452] V4L/DVB (7672): dib7000p: Add output mode param to the attach struct This allows future drivers to select the most appropriate output mode. Signed-off-by: Steven Toth Reviewed-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib7000p.c | 8 +++++++- drivers/media/dvb/frontends/dib7000p.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 47c23e29753e..1a0142e0d741 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -1168,7 +1168,7 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe, ret = dib7000p_tune(fe, fep); /* make this a config parameter */ - dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO); + dib7000p_set_output_mode(state, state->cfg.output_mode); return ret; } @@ -1330,6 +1330,12 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, st->gpio_val = cfg->gpio_val; st->gpio_dir = cfg->gpio_dir; + /* Ensure the output mode remains at the previous default if it's + * not specifically set by the caller. + */ + if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) + st->cfg.output_mode = OUTMODE_MPEG2_FIFO; + demod = &st->demod; demod->demodulator_priv = st; memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index eefcac8b5244..081bd81f3da2 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -31,6 +31,8 @@ struct dib7000p_config { u8 spur_protect; int (*agc_control) (struct dvb_frontend *, u8 before); + + u8 output_mode; }; #define DEFAULT_DIB7000P_I2C_ADDRESS 18 From 6676237398d0c2e61e5a3a27e0951f60d6ef6fe3 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 22 Apr 2008 15:38:26 -0300 Subject: [PATCH 396/452] V4L/DVB (7673): cx23885: Add support for the Hauppauge HVR1400 DVB-T mode is now supported using the DiBcom dib7000p demodulator and the Xceive xc3028L silicon tuner. Analog mode is not supported. Signed-off-by: Steven Toth Reviewed-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 26 +++++ drivers/media/video/cx23885/cx23885-dvb.c | 113 ++++++++++++++++++++ drivers/media/video/cx23885/cx23885-i2c.c | 4 +- drivers/media/video/cx23885/cx23885.h | 1 + 5 files changed, 144 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index b057a3c9f8ff..929b90c8387f 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -7,3 +7,4 @@ 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717] 7 -> Hauppauge WinTV-HVR1200 [0070:71d1] 8 -> Hauppauge WinTV-HVR1700 [0070:8101] + 9 -> Hauppauge WinTV-HVR1400 [0070:8010] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 859510f7469c..0f4b325f2d89 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -138,6 +138,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1700", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1400] = { + .name = "Hauppauge WinTV-HVR1400", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -197,6 +201,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x8101, .card = CX23885_BOARD_HAUPPAUGE_HVR1700, + }, { + .subvendor = 0x0070, + .subdevice = 0x8010, + .card = CX23885_BOARD_HAUPPAUGE_HVR1400, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -251,6 +259,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */ case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ + case 80019: + /* WinTV-HVR1400 (Express Card, Retail, IR, + * DVB-T and Basic analog */ case 81519: /* WinTV-HVR1700 (PCIe, Retail, No IR, half height, * DVB-T and MPEG2 HW Encoder */ @@ -358,6 +369,18 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* GPIO-22 IIS WCLK */ /* GPIO-23 IIS BCLK */ + /* Put the parts into reset and back */ + cx_set(GP0_IO, 0x00050000); + mdelay(20); + cx_clear(GP0_IO, 0x00000005); + mdelay(20); + cx_set(GP0_IO, 0x00050005); + break; + case CX23885_BOARD_HAUPPAUGE_HVR1400: + /* GPIO-0 Dibcom7000p demodulator reset */ + /* GPIO-2 xc3028L tuner reset */ + /* GPIO-13 LED */ + /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); @@ -376,6 +399,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1200: + case CX23885_BOARD_HAUPPAUGE_HVR1400: /* FIXME: Implement me */ break; } @@ -400,6 +424,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: + case CX23885_BOARD_HAUPPAUGE_HVR1400: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0x80); break; @@ -425,6 +450,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: + case CX23885_BOARD_HAUPPAUGE_HVR1400: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 1b9a85e43d44..870d6e197d65 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -40,6 +40,8 @@ #include "dvb-pll.h" #include "tuner-xc2028.h" #include "tuner-simple.h" +#include "dib7000p.h" +#include "dibx000_common.h" static unsigned int debug; @@ -189,6 +191,92 @@ static struct tda18271_config hauppauge_hvr1200_tuner_config = { .gate = TDA18271_GATE_ANALOG, }; +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.000000 + * With external clock = 30.000000 */ +struct dibx000_bandwidth_config xc3028_bw_config = { + 60000, /* internal */ + 30000, /* sampling */ + 1, /* pll_cfg: prediv */ + 8, /* pll_cfg: ratio */ + 3, /* pll_cfg: range */ + 1, /* pll_cfg: reset */ + 0, /* pll_cfg: bypass */ + 0, /* misc: refdiv */ + 0, /* misc: bypclk_div */ + 1, /* misc: IO_CLK_en_core */ + 1, /* misc: ADClkSrc */ + 0, /* misc: 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 hauppauge_hvr1400_dib7000_config = { + .output_mpeg2_in_188_bytes = 1, + .hostbus_diversity = 1, + .tuner_is_baseband = 0, + .update_lna = NULL, + + .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, + + .pwm_freq_div = 0, + .agc_control = NULL, + .spur_protect = 0, + + .output_mode = OUTMODE_MPEG2_SERIAL, +}; + static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) { struct cx23885_tsport *port = ptr; @@ -343,6 +431,31 @@ static int dvb_register(struct cx23885_tsport *port) &hauppauge_hvr1200_tuner_config); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1400: + i2c_bus = &dev->i2c_bus[0]; + port->dvb.frontend = dvb_attach(dib7000p_attach, + &i2c_bus->i2c_adap, + 0x12, &hauppauge_hvr1400_dib7000_config); + if (port->dvb.frontend != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->i2c_bus[1].i2c_adap, + .i2c_addr = 0x64, + .callback = cx23885_hvr1500_xc3028_callback, + }; + static struct xc2028_ctrl ctl = { + .fname = "xc3028L-v36.fw", + .max_len = 64, + .demod = 5000, + .d2633 = 1 + }; + + fe = dvb_attach(xc2028_attach, + port->dvb.frontend, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctl); + } + break; default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->name); diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 85f9d5ef17d0..3928945df5f5 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -354,6 +354,7 @@ static struct i2c_client cx23885_i2c_client_template = { static char *i2c_devs[128] = { [0x10 >> 1] = "tda10048", + [0x12 >> 1] = "dib7000pc", [ 0x1c >> 1 ] = "lgdt3303", [ 0x86 >> 1 ] = "tda9887", [ 0x32 >> 1 ] = "cx24227", @@ -361,7 +362,8 @@ static char *i2c_devs[128] = { [ 0x84 >> 1 ] = "tda8295", [ 0xa0 >> 1 ] = "eeprom", [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275", - [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275/xc5000", + [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028", + [0xc8 >> 1] = "tuner/xc3028L", }; static void do_i2c_scan(char *name, struct i2c_client *c) diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index c5496e08c949..3705e6019ce9 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -61,6 +61,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1500 6 #define CX23885_BOARD_HAUPPAUGE_HVR1200 7 #define CX23885_BOARD_HAUPPAUGE_HVR1700 8 +#define CX23885_BOARD_HAUPPAUGE_HVR1400 9 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ From d5b3d9ff368dee5e87d9987161ff258d87ecc7c0 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 22 Apr 2008 22:52:01 -0300 Subject: [PATCH 397/452] V4L/DVB (7674): tda10048: Adding an SNR table Trying to improve the SNR reporting. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10048.c | 157 +++++++++++++++++++++++-- 1 file changed, 147 insertions(+), 10 deletions(-) diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c index 701dd02b0d07..090fb7dd93c6 100644 --- a/drivers/media/dvb/frontends/tda10048.c +++ b/drivers/media/dvb/frontends/tda10048.c @@ -26,6 +26,7 @@ #include #include #include "dvb_frontend.h" +#include "dvb_math.h" #include "tda10048.h" #define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw" @@ -563,31 +564,167 @@ static int tda10048_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) { struct tda10048_state *state = fe->demodulator_priv; - u16 v; + u8 v; dprintk(1, "%s()\n", __func__); + *signal_strength = 65535; + v = tda10048_readreg(state, TDA10048_NP_OUT); - if (v == 0) - *signal_strength = 100; - else { - /* TODO: Apply .db math for correct values */ - *signal_strength = v; - } + if (v > 0) + *signal_strength -= (v << 8) | v; return 0; } +/* SNR lookup table */ +static struct snr_tab { + u8 val; + u8 data; +} snr_tab[] = { + { 0, 0 }, + { 1, 246 }, + { 2, 215 }, + { 3, 198 }, + { 4, 185 }, + { 5, 176 }, + { 6, 168 }, + { 7, 161 }, + { 8, 155 }, + { 9, 150 }, + { 10, 146 }, + { 11, 141 }, + { 12, 138 }, + { 13, 134 }, + { 14, 131 }, + { 15, 128 }, + { 16, 125 }, + { 17, 122 }, + { 18, 120 }, + { 19, 118 }, + { 20, 115 }, + { 21, 113 }, + { 22, 111 }, + { 23, 109 }, + { 24, 107 }, + { 25, 106 }, + { 26, 104 }, + { 27, 102 }, + { 28, 101 }, + { 29, 99 }, + { 30, 98 }, + { 31, 96 }, + { 32, 95 }, + { 33, 94 }, + { 34, 92 }, + { 35, 91 }, + { 36, 90 }, + { 37, 89 }, + { 38, 88 }, + { 39, 86 }, + { 40, 85 }, + { 41, 84 }, + { 42, 83 }, + { 43, 82 }, + { 44, 81 }, + { 45, 80 }, + { 46, 79 }, + { 47, 78 }, + { 48, 77 }, + { 49, 76 }, + { 50, 76 }, + { 51, 75 }, + { 52, 74 }, + { 53, 73 }, + { 54, 72 }, + { 56, 71 }, + { 57, 70 }, + { 58, 69 }, + { 60, 68 }, + { 61, 67 }, + { 63, 66 }, + { 64, 65 }, + { 66, 64 }, + { 67, 63 }, + { 68, 62 }, + { 69, 62 }, + { 70, 61 }, + { 72, 60 }, + { 74, 59 }, + { 75, 58 }, + { 77, 57 }, + { 79, 56 }, + { 81, 55 }, + { 83, 54 }, + { 85, 53 }, + { 87, 52 }, + { 89, 51 }, + { 91, 50 }, + { 93, 49 }, + { 95, 48 }, + { 97, 47 }, + { 100, 46 }, + { 102, 45 }, + { 104, 44 }, + { 107, 43 }, + { 109, 42 }, + { 112, 41 }, + { 114, 40 }, + { 117, 39 }, + { 120, 38 }, + { 123, 37 }, + { 125, 36 }, + { 128, 35 }, + { 131, 34 }, + { 134, 33 }, + { 138, 32 }, + { 141, 31 }, + { 144, 30 }, + { 147, 29 }, + { 151, 28 }, + { 154, 27 }, + { 158, 26 }, + { 162, 25 }, + { 165, 24 }, + { 169, 23 }, + { 173, 22 }, + { 177, 21 }, + { 181, 20 }, + { 186, 19 }, + { 190, 18 }, + { 194, 17 }, + { 199, 16 }, + { 204, 15 }, + { 208, 14 }, + { 213, 13 }, + { 218, 12 }, + { 223, 11 }, + { 229, 10 }, + { 234, 9 }, + { 239, 8 }, + { 245, 7 }, + { 251, 6 }, + { 255, 5 }, +}; + static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr) { struct tda10048_state *state = fe->demodulator_priv; + u8 v; + int i, ret = -EINVAL; dprintk(1, "%s()\n", __func__); - /* TODO: This result should be the same as signal strength */ - *snr = tda10048_readreg(state, TDA10048_NP_OUT); + v = tda10048_readreg(state, TDA10048_NP_OUT); + for (i = 0; i < ARRAY_SIZE(snr_tab); i++) { + if (v <= snr_tab[i].val) { + *snr = snr_tab[i].data; + ret = 0; + break; + } + } - return 0; + return ret; } static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) From 548899c76e101bdf6228569d6ee6992e8c20da76 Mon Sep 17 00:00:00 2001 From: Dmitry Belimov Date: Wed, 23 Apr 2008 14:01:52 -0300 Subject: [PATCH 398/452] V4L/DVB (7675): tea5767 autodetection is not working on some saa7134 boards Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tea5767.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 833f2768958d..f6e7d7ad8424 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -393,11 +393,6 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) return EINVAL; } - /* It seems that tea5767 returns 0xff after the 5th byte */ - if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { - printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n"); - return EINVAL; - } return 0; } From 8fb737b7dc94e495be02c775afe1e7de0e06f3f5 Mon Sep 17 00:00:00 2001 From: Dmitry Belimov Date: Wed, 23 Apr 2008 14:07:09 -0300 Subject: [PATCH 399/452] V4L/DVB (7676): saa7134: fix: Properly handle busy states on i2c bus There are two conditions, reported by saa7134 that indicates that the I2C bus is busy: TO_SCL and TO_ARB. On both states, it needs to wait for I2C release, before using the bus. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-i2c.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index ba71dd0040be..2ccfaba0c490 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -140,6 +140,8 @@ static inline int i2c_is_busy(enum i2c_status status) { switch (status) { case BUSY: + case TO_SCL: + case TO_ARB: return true; default: return false; From b34dddbe4b88bf59e7607d1fc504eee43570c6a4 Mon Sep 17 00:00:00 2001 From: Dmitry Belimov Date: Wed, 23 Apr 2008 14:09:08 -0300 Subject: [PATCH 400/452] V4L/DVB (7677): saa7134: Add/fix Beholder entries Beholder TV/FM tuners: Changes: Add support Beholder Columbus PCMCIA card. Add key map for remote control of Beholder Columbus PCMCIA card. Fix gpiomask for all Beholder tuners. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 4 +- drivers/media/common/ir-keymaps.c | 70 ++++++++++++++++++ drivers/media/video/saa7134/saa7134-cards.c | 80 ++++++++++++++++++--- drivers/media/video/saa7134/saa7134-input.c | 13 +++- include/media/ir-common.h | 1 + 5 files changed, 157 insertions(+), 11 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index fe925b335c94..44d84dd15ad6 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -25,8 +25,8 @@ 24 -> KNC One TV-Station DVR [1894:a006] 25 -> ASUS TV-FM 7133 [1043:4843] 26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b] - 27 -> Manli MuchTV M-TV002/Behold TV 403 FM - 28 -> Manli MuchTV M-TV001/Behold TV 401 + 27 -> Manli MuchTV M-TV002 + 28 -> Manli MuchTV M-TV001 29 -> Nagase Sangyo TransGear 3000TV [1461:050c] 30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4] 31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5] diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 65f810cde605..a3485817e46c 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2043,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_behold); +/* Beholder Intl. Ltd. 2008 + * Dmitry Belimov d.belimov@google.com + * Keytable is used by BeholdTV Columbus + * The "ascii-art picture" below (in comments, first row + * is the keycode in hex, and subsequent row(s) shows + * the button labels (several variants when appropriate) + * helps to descide which keycodes to assign to the buttons. + */ +IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { + + /* 0x13 0x11 0x1C 0x12 * + * Mute Source TV/FM Power * + * */ + + [0x13] = KEY_MUTE, + [0x11] = KEY_PROPS, + [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */ + [0x12] = KEY_POWER, + + /* 0x01 0x02 0x03 0x0D * + * 1 2 3 Stereo * + * * + * 0x04 0x05 0x06 0x19 * + * 4 5 6 Snapshot * + * * + * 0x07 0x08 0x09 0x10 * + * 7 8 9 Zoom * + * */ + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x0D] = KEY_SETUP, /* Setup key */ + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x19] = KEY_BOOKMARKS, /* Snapshot key */ + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x10] = KEY_ZOOM, + + /* 0x0A 0x00 0x0B 0x0C * + * RECALL 0 ChannelUp VolumeUp * + * */ + [0x0A] = KEY_AGAIN, + [0x00] = KEY_0, + [0x0B] = KEY_CHANNELUP, + [0x0C] = KEY_VOLUMEUP, + + /* 0x1B 0x1D 0x15 0x18 * + * Timeshift Record ChannelDown VolumeDown * + * */ + + [0x1B] = KEY_REWIND, + [0x1D] = KEY_RECORD, + [0x15] = KEY_CHANNELDOWN, + [0x18] = KEY_VOLUMEDOWN, + + /* 0x0E 0x1E 0x0F 0x1A * + * Stop Pause Previouse Next * + * */ + + [0x0E] = KEY_STOP, + [0x1E] = KEY_PAUSE, + [0x0F] = KEY_PREVIOUS, + [0x1A] = KEY_NEXT, + +}; +EXPORT_SYMBOL_GPL(ir_codes_behold_columbus); + /* * Remote control for the Genius TVGO A11MCE * Adrian Pardini diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 82fe19c3b1db..98375955a84b 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -30,6 +30,7 @@ #include "tuner-xc2028.h" #include #include +#include "tea5767.h" /* commly used strings */ static char name_mute[] = "mute"; @@ -1049,7 +1050,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_MANLI_MTV002] = { /* Ognjen Nastic */ - .name = "Manli MuchTV M-TV002/Behold TV 403 FM", + .name = "Manli MuchTV M-TV002", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_PAL, .radio_type = UNSET, @@ -1076,7 +1077,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_MANLI_MTV001] = { /* Ognjen Nastic UNTESTED */ - .name = "Manli MuchTV M-TV001/Behold TV 401", + .name = "Manli MuchTV M-TV001", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_PAL, .radio_type = UNSET, @@ -2198,6 +2199,8 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_BEHOLD_409FM] = { /* , Sergey */ + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 409 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -2205,6 +2208,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3576,12 +3580,15 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_401] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 401", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3602,12 +3609,15 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_403] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 403", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3624,12 +3634,15 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_403FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 403 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3650,6 +3663,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_405] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 405", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3657,6 +3672,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3674,6 +3690,8 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_BEHOLD_405FM] = { /* Sergey */ + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 405 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3681,6 +3699,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3701,6 +3720,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_407] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 407", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3708,7 +3729,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0xc0c000, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3728,6 +3749,8 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_407FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 407 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3735,7 +3758,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0xc0c000, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3760,6 +3783,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_409] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 409", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3767,6 +3792,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3783,6 +3809,8 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_505FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 505 FM/RDS", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3790,6 +3818,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3814,6 +3843,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_507_9FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3821,6 +3852,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3841,6 +3873,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV Columbus TVFM", .audio_clock = 0x00187de7, .tuner_type = TUNER_ALPS_TSBE5_PAL, @@ -3848,23 +3882,28 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x000A8004, .inputs = {{ .name = name_tv, .vmux = 3, .amux = TV, .tv = 1, - },{ + .gpio = 0x000A8004, + }, { .name = name_comp1, .vmux = 1, .amux = LINE1, - },{ + .gpio = 0x000A8000, + }, { .name = name_svideo, .vmux = 8, .amux = LINE1, - }}, + .gpio = 0x000A8000, + } }, .radio = { .name = name_radio, .amux = LINE2, + .gpio = 0x000A8000, }, }, [SAA7134_BOARD_BEHOLD_607_9FM] = { @@ -5471,7 +5510,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_CARDBUS: 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); @@ -5482,6 +5520,18 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); msleep(10); break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + /* power-down tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0); + msleep(10); + /* power-up tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004); + msleep(10); + /* remote via GPIO */ + dev->has_remote = SAA7134_REMOTE_GPIO; + break; case SAA7134_BOARD_RTD_VFG7350: /* @@ -5770,6 +5820,20 @@ int saa7134_board_init2(struct saa7134_dev *dev) break; } break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + { + struct v4l2_priv_tun_config tea5767_cfg; + struct tea5767_ctrl ctl; + + dev->i2c_client.addr = 0xC0; + /* set TEA5767(analog FM) defines */ + memset(&ctl, 0, sizeof(ctl)); + ctl.xtal_freq = TEA5767_HIGH_LO_13MHz; + tea5767_cfg.tuner = TUNER_TEA5767; + tea5767_cfg.priv = &ctl; + saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg); + } + break; } if (dev->tuner_type == TUNER_XC2028) { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 65f8e594d6fb..767ff30832f2 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -331,6 +331,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: + ir_codes = ir_codes_manli; + mask_keycode = 0x001f00; + mask_keyup = 0x004000; + polling = 50; /* ms */ + break; case SAA7134_BOARD_BEHOLD_409FM: case SAA7134_BOARD_BEHOLD_401: case SAA7134_BOARD_BEHOLD_403: @@ -343,7 +348,13 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_505FM: case SAA7134_BOARD_BEHOLD_507_9FM: ir_codes = ir_codes_manli; - mask_keycode = 0x001f00; + mask_keycode = 0x003f00; + mask_keyup = 0x004000; + polling = 50; /* ms */ + break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + ir_codes = ir_codes_behold_columbus; + mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; // ms break; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 75a3482866fe..bfee8be5d63f 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -142,6 +142,7 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; From e7f677f33664200b3d75ffc625d218b84ac43875 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 16 Mar 2008 01:13:17 -0300 Subject: [PATCH 401/452] V4L/DVB (7678): pvrusb2: Fix stupid string typo that has been reproducing wildly Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 3434b0e6d675..f489aab112dc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -49,7 +49,7 @@ static const char *pvr2_fw1_names_29xxx[] = { }; static const struct pvr2_device_desc pvr2_device_29xxx = { - .description = "WinTV PVR USB2 Model Category 29xxxx", + .description = "WinTV PVR USB2 Model Category 29xxx", .shortname = "29xxx", .client_modules.lst = pvr2_client_29xxx, .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx), @@ -80,7 +80,7 @@ static const char *pvr2_fw1_names_24xxx[] = { }; static const struct pvr2_device_desc pvr2_device_24xxx = { - .description = "WinTV PVR USB2 Model Category 24xxxx", + .description = "WinTV PVR USB2 Model Category 24xxx", .shortname = "24xxx", .client_modules.lst = pvr2_client_24xxx, .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx), @@ -210,7 +210,7 @@ static const char *pvr2_fw1_names_73xxx[] = { }; static const struct pvr2_device_desc pvr2_device_73xxx = { - .description = "WinTV PVR USB2 Model Category 73xxxx", + .description = "WinTV PVR USB2 Model Category 73xxx", .shortname = "73xxx", .client_modules.lst = pvr2_client_73xxx, .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx), @@ -241,7 +241,7 @@ static const char *pvr2_fw1_names_75xxx[] = { }; static const struct pvr2_device_desc pvr2_device_75xxx = { - .description = "WinTV PVR USB2 Model Category 75xxxx", + .description = "WinTV PVR USB2 Model Category 75xxx", .shortname = "75xxx", .client_modules.lst = pvr2_client_75xxx, .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), From 04910bdc5c172af9bc937a8869e7f2907db4443f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 3 Feb 2008 23:46:16 -0300 Subject: [PATCH 402/452] V4L/DVB (7679): pvrusb2: add DVB API framework Add basic framework for the DVB API. This is enough to control the tuner & demod of the digital frontend, but the stream & buffer handling is still missing. Additional note from Mike Isely - also, since these changes are still very experimental arrange for DVB changes to be compiled in via new CONFIG_VIDEO_PVRUSB2_DVB option, for now. Signed-off-by: Michael Krufky Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Makefile | 6 + drivers/media/video/pvrusb2/pvrusb2-devattr.h | 4 + drivers/media/video/pvrusb2/pvrusb2-dvb.c | 179 ++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-dvb.h | 33 ++++ .../video/pvrusb2/pvrusb2-hdw-internal.h | 3 + drivers/media/video/pvrusb2/pvrusb2-main.c | 7 + 6 files changed, 232 insertions(+) create mode 100644 drivers/media/video/pvrusb2/pvrusb2-dvb.c create mode 100644 drivers/media/video/pvrusb2/pvrusb2-dvb.h diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile index 47284e558648..b0fa3ece5aa2 100644 --- a/drivers/media/video/pvrusb2/Makefile +++ b/drivers/media/video/pvrusb2/Makefile @@ -1,5 +1,6 @@ obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o +obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ @@ -9,6 +10,11 @@ pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ + $(obj-pvrusb2-dvb-y) \ $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o + +EXTRA_CFLAGS += -Idrivers/media/video +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index fb5f5d17e8cb..cc2c4d78cf41 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -23,6 +23,7 @@ #include #include +#include "pvrusb2-dvb.h" /* @@ -65,6 +66,9 @@ struct pvr2_device_desc { was initialized from internal ROM. */ struct pvr2_string_table fx2_firmware; + /* callback functions to handle attachment of digital tuner & demod */ + struct pvr2_dvb_props *dvb_props; + /* 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 diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c new file mode 100644 index 000000000000..18c18db2fe3c --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -0,0 +1,179 @@ +/* + * pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver. + * + * Copyright (C) 2007, 2008 Michael Krufky + * + * 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 + * + * 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 + * + */ + +#include "dvbdev.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-hdw.h" +#include "pvrusb2-dvb.h" + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n", + dvbdmxfeed->pid, dvbdmxfeed->type); + return 0; /* FIXME: pvr2_dvb_ctrl_feed(dvbdmxfeed, 1); */ +} + +static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n", + dvbdmxfeed->pid, dvbdmxfeed->type); + return 0; /* FIXME: pvr2_dvb_ctrl_feed(dvbdmxfeed, 0); */ +} + +static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap) +{ + int ret; + + ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb", + THIS_MODULE/*&hdw->usb_dev->owner*/, + &adap->pvr->hdw->usb_dev->dev, + adapter_nr); + if (ret < 0) { + err("dvb_register_adapter failed: error %d", ret); + goto err; + } + adap->dvb_adap.priv = adap; + + adap->demux.dmx.capabilities = DMX_TS_FILTERING | + DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + adap->demux.priv = adap; + adap->demux.filternum = 256; + adap->demux.feednum = 256; + adap->demux.start_feed = pvr2_dvb_start_feed; + adap->demux.stop_feed = pvr2_dvb_stop_feed; + adap->demux.write_to_decoder = NULL; + + ret = dvb_dmx_init(&adap->demux); + if (ret < 0) { + err("dvb_dmx_init failed: error %d", ret); + goto err_dmx; + } + + adap->dmxdev.filternum = adap->demux.filternum; + adap->dmxdev.demux = &adap->demux.dmx; + adap->dmxdev.capabilities = 0; + + ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap); + if (ret < 0) { + err("dvb_dmxdev_init failed: error %d", ret); + goto err_dmx_dev; + } + + dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); + + adap->digital_up = 1; + + return 0; + +err_dmx_dev: + dvb_dmx_release(&adap->demux); +err_dmx: + dvb_unregister_adapter(&adap->dvb_adap); +err: + return ret; +} + +static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) +{ + if (adap->digital_up) { + printk(KERN_DEBUG "unregistering DVB devices\n"); + dvb_net_release(&adap->dvb_net); + adap->demux.dmx.close(&adap->demux.dmx); + dvb_dmxdev_release(&adap->dmxdev); + dvb_dmx_release(&adap->demux); + dvb_unregister_adapter(&adap->dvb_adap); + adap->digital_up = 0; + } + return 0; +} + +static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) +{ + struct pvr2_dvb_props *dvb_props = adap->pvr->hdw->hdw_desc->dvb_props; + + if (dvb_props == NULL) { + err("fe_props not defined!"); + return -EINVAL; + } + + if (dvb_props->frontend_attach == NULL) { + err("frontend_attach not defined!"); + return -EINVAL; + } + + if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) { + + if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) { + err("frontend registration failed!"); + dvb_frontend_detach(adap->fe); + adap->fe = NULL; + return -ENODEV; + } + + if (dvb_props->tuner_attach) + dvb_props->tuner_attach(adap); + + if (adap->fe->ops.analog_ops.standby) + adap->fe->ops.analog_ops.standby(adap->fe); + + } else { + err("no frontend was attached!"); + return -ENODEV; + } + + return 0; +} + +static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap) +{ + if (adap->fe != NULL) { + dvb_unregister_frontend(adap->fe); + dvb_frontend_detach(adap->fe); + } + return 0; +} + +int pvr2_dvb_init(struct pvr2_context *pvr) +{ + int ret = 0; + + pvr->hdw->dvb.pvr = pvr; + + ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb); + if (ret < 0) + goto fail; + + ret = pvr2_dvb_frontend_init(&pvr->hdw->dvb); +fail: + return ret; +} + +int pvr2_dvb_exit(struct pvr2_context *pvr) +{ + pvr2_dvb_frontend_exit(&pvr->hdw->dvb); + pvr2_dvb_adapter_exit(&pvr->hdw->dvb); + + pvr->hdw->dvb.pvr = NULL; + + return 0; +} diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h new file mode 100644 index 000000000000..0aff05cb9415 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h @@ -0,0 +1,33 @@ +#ifndef __PVRUSB2_DVB_H__ +#define __PVRUSB2_DVB_H__ + +#include "dvb_frontend.h" +#include "dvb_demux.h" +#include "dvb_net.h" +#include "dmxdev.h" +#include "pvrusb2-context.h" + +struct pvr2_dvb_adapter { + struct pvr2_context *pvr; + + struct dvb_adapter dvb_adap; + struct dmxdev dmxdev; + struct dvb_demux demux; + struct dvb_net dvb_net; + struct dvb_frontend *fe; + + int feedcount; + int max_feed_count; + + unsigned int digital_up:1; +}; + +struct pvr2_dvb_props { + int (*frontend_attach) (struct pvr2_dvb_adapter *); + int (*tuner_attach) (struct pvr2_dvb_adapter *); +}; + +int pvr2_dvb_init(struct pvr2_context *pvr); +int pvr2_dvb_exit(struct pvr2_context *pvr); + +#endif /* __PVRUSB2_DVB_H__ */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index c725495826ce..6fe0a882209f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -41,6 +41,7 @@ #include "pvrusb2-io.h" #include #include "pvrusb2-devattr.h" +#include "pvrusb2-dvb.h" /* Legal values for PVR2_CID_HSM */ #define PVR2_CVAL_HSM_FAIL 0 @@ -373,6 +374,8 @@ struct pvr2_hdw { struct pvr2_ctrl *controls; unsigned int control_cnt; + + struct pvr2_dvb_adapter dvb; }; /* This function gets the current frequency */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index b63b2265503a..68f4a7480737 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -60,6 +60,10 @@ static void pvr_setup_attach(struct pvr2_context *pvr) { /* Create association with v4l layer */ pvr2_v4l2_create(pvr); +#ifdef CONFIG_VIDEO_PVRUSB2_DVB + /* Create association with dvb layer */ + pvr2_dvb_init(pvr); +#endif #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS pvr2_sysfs_create(pvr,class_ptr); #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ @@ -95,6 +99,9 @@ static void pvr_disconnect(struct usb_interface *intf) pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr); +#ifdef CONFIG_VIDEO_PVRUSB2_DVB + pvr2_dvb_exit(pvr); +#endif usb_set_intfdata (intf, NULL); pvr2_context_disconnect(pvr); From 99443ae04f7002530f666ba0747f7b1ecafb3002 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 3 Feb 2008 23:48:09 -0300 Subject: [PATCH 403/452] V4L/DVB (7680): pvrusb2-dvb: add pvr2_dvb_bus_ctrl to allow frontends to negotiate bus access This function is just a skeleton for now - a placeholder to remind us to fix it. Signed-off-by: Michael Krufky Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 18c18db2fe3c..250462265a41 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -39,6 +39,17 @@ static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) return 0; /* FIXME: pvr2_dvb_ctrl_feed(dvbdmxfeed, 0); */ } +static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) +{ + /* TO DO: This function will call into the core and request for + * input to be set to 'dtv' if (acquire) and if it isn't set already. + * + * If (!acquire) then we should do nothing -- don't switch inputs + * again unless the analog side of the driver requests the bus. + */ + return 0; +} + static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap) { int ret; @@ -136,6 +147,9 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) if (adap->fe->ops.analog_ops.standby) adap->fe->ops.analog_ops.standby(adap->fe); + /* Ensure all frontends negotiate bus access */ + adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl; + } else { err("no frontend was attached!"); return -ENODEV; From d8abe97d0063cf77e9bbbee076181e4657c7e09c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 3 Feb 2008 23:55:07 -0300 Subject: [PATCH 404/452] V4L/DVB (7681): pvrusb2-dvb: start working on streaming / buffer handling code start work on streaming / buffer handling code to feed the software demux Signed-off-by: Michael Krufky Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 44 +++++++++++++++++++++-- drivers/media/video/pvrusb2/pvrusb2-dvb.h | 3 ++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 250462265a41..c85477709e6e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -18,6 +18,7 @@ * */ +#include #include "dvbdev.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-hdw.h" @@ -25,18 +26,56 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) +{ + struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv; + int newfeedcount, ret = 0; + + if (adap == NULL) + return -ENODEV; + + mutex_lock(&adap->lock); + newfeedcount = adap->feedcount + (onoff ? 1 : -1); + + if (newfeedcount == 0) { + printk(KERN_DEBUG "stop feeding\n"); + + ret = kthread_stop(adap->thread); + adap->thread = NULL; + } + + adap->feedcount = newfeedcount; + + if (adap->feedcount == onoff && adap->feedcount > 0) { + if (NULL != adap->thread) + goto fail; + + printk(KERN_DEBUG "start feeding\n"); + + if (IS_ERR(adap->thread)) { + ret = PTR_ERR(adap->thread); + adap->thread = NULL; + } + //ret = newfeedcount; + } +fail: + mutex_unlock(&adap->lock); + + return ret; +} + static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) { printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type); - return 0; /* FIXME: pvr2_dvb_ctrl_feed(dvbdmxfeed, 1); */ + return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1); } static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type); - return 0; /* FIXME: pvr2_dvb_ctrl_feed(dvbdmxfeed, 0); */ + return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0); } static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) @@ -172,6 +211,7 @@ int pvr2_dvb_init(struct pvr2_context *pvr) int ret = 0; pvr->hdw->dvb.pvr = pvr; + mutex_init(&pvr->hdw->dvb.lock); ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb); if (ret < 0) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h index 0aff05cb9415..98728d44a4b6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h @@ -19,6 +19,9 @@ struct pvr2_dvb_adapter { int feedcount; int max_feed_count; + struct task_struct *thread; + struct mutex lock; + unsigned int digital_up:1; }; From bb8ce9d9143c0fe2b5cdf65fa41250446805a4be Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 4 Feb 2008 00:00:19 -0300 Subject: [PATCH 405/452] V4L/DVB (7682): pvrusb2-dvb: finish up stream & buffer handling Signed-off-by: Michael Krufky Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 187 ++++++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index c85477709e6e..bde85c973058 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -19,13 +19,198 @@ */ #include +#include #include "dvbdev.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-hdw.h" +#include "pvrusb2-io.h" #include "pvrusb2-dvb.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +#define BUFFER_COUNT 32 +#define BUFFER_SIZE PAGE_ALIGN(0x4000) + +struct pvr2_dvb_fh { + struct pvr2_channel channel; + struct pvr2_stream *stream; + struct pvr2_dvb_adapter *adap; + wait_queue_head_t wait_data; + char *buffer_storage[BUFFER_COUNT]; +}; + +static void pvr2_dvb_notify(struct pvr2_dvb_fh *fhp) +{ + wake_up(&fhp->wait_data); +} + +static int pvr2_dvb_fh_init(struct pvr2_dvb_fh *fh, + struct pvr2_dvb_adapter *adap) +{ + struct pvr2_context *pvr = adap->pvr; + unsigned int idx; + int ret; + struct pvr2_buffer *bp; + + init_waitqueue_head(&fh->wait_data); + + fh->adap = adap; + + pvr2_channel_init(&fh->channel, adap->pvr); + + ret = pvr2_channel_claim_stream(&fh->channel, &pvr->video_stream); + /* somebody else already has the stream */ + if (ret != 0) + return ret; + + fh->stream = pvr->video_stream.stream; + + for (idx = 0; idx < BUFFER_COUNT; idx++) { + fh->buffer_storage[idx] = kmalloc(BUFFER_SIZE, GFP_KERNEL); + if (!(fh->buffer_storage[idx])) + break; + } + + if (idx < BUFFER_COUNT) { + /* An allocation appears to have failed */ + ret = -ENOMEM; + goto cleanup; + } + + pvr2_stream_set_callback(pvr->video_stream.stream, + (pvr2_stream_callback) pvr2_dvb_notify, fh); + + ret = pvr2_stream_set_buffer_count(fh->stream, BUFFER_COUNT); + if (ret < 0) + return ret; + + for (idx = 0; idx < BUFFER_COUNT; idx++) { + bp = pvr2_stream_get_buffer(fh->stream, idx); + pvr2_buffer_set_buffer(bp, + fh->buffer_storage[idx], + BUFFER_SIZE); + } + + ret = pvr2_hdw_set_streaming(fh->channel.hdw, 1); + if (ret < 0) + goto cleanup; + + while ((bp = pvr2_stream_get_idle_buffer(fh->stream)) != 0) { + ret = pvr2_buffer_queue(bp); + if (ret < 0) + goto cleanup; + } + + return ret; + +cleanup: + if (fh->stream) + pvr2_stream_kill(fh->stream); + + for (idx = 0; idx < BUFFER_COUNT; idx++) { + if (!(fh->buffer_storage[idx])) + continue; + + kfree(fh->buffer_storage[idx]); + } + pvr2_channel_done(&fh->channel); + + return ret; +} + +static void pvr2_dvb_fh_done(struct pvr2_dvb_fh *fh) +{ + unsigned int idx; + + pvr2_hdw_set_streaming(fh->channel.hdw, 0); + + pvr2_stream_kill(fh->stream); + +// pvr2_channel_claim_stream(&fh->channel, NULL); + + for (idx = 0; idx < BUFFER_COUNT; idx++) { + if (!(fh->buffer_storage[idx])) + continue; + + kfree(fh->buffer_storage[idx]); + } + + pvr2_channel_done(&fh->channel); +} + +static int pvr2_dvb_feed_thread(void *data) +{ + struct pvr2_dvb_adapter *adap = data; + struct pvr2_dvb_fh fh; + int ret; + unsigned int count; + struct pvr2_buffer *bp; + + printk(KERN_DEBUG "dvb thread started\n"); + set_freezable(); + + memset(&fh, 0, sizeof(fh)); + + ret = pvr2_dvb_fh_init(&fh, adap); + if (ret != 0) + return ret; + + for (;;) { + if ((0 == adap->feedcount) || (kthread_should_stop())) + break; + + /* Not sure about this... */ + try_to_freeze(); + + bp = pvr2_stream_get_ready_buffer(fh.stream); + if (bp != NULL) { + count = pvr2_buffer_get_count(bp); + if (count) { + dvb_dmx_swfilter( + &adap->demux, + fh.buffer_storage[ + pvr2_buffer_get_id(bp)], + count); + } else { + ret = pvr2_buffer_get_status(bp); + if (ret < 0) + break; + } + ret = pvr2_buffer_queue(bp); + if (ret < 0) + break; + + /* Since we know we did something to a buffer, + just go back and try again. No point in + blocking unless we really ran out of + buffers to process. */ + continue; + } + + + /* Wait until more buffers become available. */ + ret = wait_event_interruptible( + fh.wait_data, + pvr2_stream_get_ready_count(fh.stream) > 0); + if (ret < 0) + break; + } + + pvr2_dvb_fh_done(&fh); + + /* If we get here and ret is < 0, then an error has occurred. + Probably would be a good idea to communicate that to DVB core... */ + + printk(KERN_DEBUG "dvb thread stopped\n"); + + /* from videobuf-dvb.c: */ + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + return 0; +} + static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) { struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv; @@ -52,6 +237,8 @@ static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) printk(KERN_DEBUG "start feeding\n"); + adap->thread = kthread_run(pvr2_dvb_feed_thread, + adap, "pvrusb2-dvb"); if (IS_ERR(adap->thread)) { ret = PTR_ERR(adap->thread); adap->thread = NULL; From bde316a4f1094f9a3da402c44f7315e1a94fb332 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 10 Feb 2008 05:33:37 -0300 Subject: [PATCH 406/452] V4L/DVB (7683): pvrusb2-dvb: set to DTV mode before attaching frontend Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index bde85c973058..69ac59aa654c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -346,13 +346,31 @@ static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) { - struct pvr2_dvb_props *dvb_props = adap->pvr->hdw->hdw_desc->dvb_props; + struct pvr2_hdw *hdw = adap->pvr->hdw; + struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; + int ret; if (dvb_props == NULL) { err("fe_props not defined!"); return -EINVAL; } + /* FIXME: This code should be moved into the core, + * and should only be called if we don't already have + * control of the bus. + * + * We can't call "pvr2_dvb_bus_ctrl(adap->fe, 1)" from here, + * because adap->fe isn't defined yet. + */ + ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_by_id(hdw, + PVR2_CID_INPUT), + PVR2_CVAL_INPUT_DTV); + if (ret != 0) + return ret; + + pvr2_hdw_commit_ctl(hdw); + + if (dvb_props->frontend_attach == NULL) { err("frontend_attach not defined!"); return -EINVAL; From bc4b02caa875f8e2146c724a931f32b087d7e9b0 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 4 Feb 2008 00:12:16 -0300 Subject: [PATCH 407/452] V4L/DVB (7684): pvrusb2: Add VIDEO_PVRUSB2_DVB config variable Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Kconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 6fc1b8be1a1f..3432b25becc6 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -58,6 +58,23 @@ config VIDEO_PVRUSB2_SYSFS Note: This feature is experimental and subject to change. +config VIDEO_PVRUSB2_DVB + bool "pvrusb2 DVB support (EXPERIMENTAL)" + default n + depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL + ---help--- + + This option enables compilation of a DVB interface for the + pvrusb2 driver. Currently this is very very experimental. + It is also limiting - the DVB interface can only access the + side of hybrid devices, and there are going to be issues if + you attempt to mess with the V4L side at the same time. + Don't turn this on unless you know what you are doing. + + If you are in doubt, say N. + + Note: This feature is very experimental and might break + config VIDEO_PVRUSB2_DEBUGIFC bool "pvrusb2 debug interface" depends on VIDEO_PVRUSB2_SYSFS From 48e5329fe8dea9ce88074a10787b619a3fe7175f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 4 Feb 2008 01:00:33 -0300 Subject: [PATCH 408/452] V4L/DVB (7685): pvrusb2: Fix really bad typo if DVB config option description Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 3432b25becc6..546c3289dc13 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -67,9 +67,10 @@ config VIDEO_PVRUSB2_DVB This option enables compilation of a DVB interface for the pvrusb2 driver. Currently this is very very experimental. It is also limiting - the DVB interface can only access the - side of hybrid devices, and there are going to be issues if - you attempt to mess with the V4L side at the same time. - Don't turn this on unless you know what you are doing. + digital side of hybrid devices, and there are going to be + issues if you attempt to mess with the V4L side at the same + time. Don't turn this on unless you know what you are + doing. If you are in doubt, say N. From e2780fb41102f9844ae6182c03908f03c3cb9163 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 4 Feb 2008 04:22:21 -0300 Subject: [PATCH 409/452] V4L/DVB (7686): pvrusb2: Fix broken debug interface build Fix pvrusb2 kbuild typo introduced when pvrusb2-dvb was added. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile index b0fa3ece5aa2..5b3083c89aa9 100644 --- a/drivers/media/video/pvrusb2/Makefile +++ b/drivers/media/video/pvrusb2/Makefile @@ -1,6 +1,6 @@ obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o -obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o +obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ From ceb4340deb9bf5f8371d47ef906a83e6784345b0 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 6 Feb 2008 04:24:51 -0300 Subject: [PATCH 410/452] V4L/DVB (7687): pvrusb2: Fix oops in pvrusb2-dvb The pvrusb2-dvb feed thread cannot be allowed to exit by itself without first waiting for kthread_should_stop() to return true. Otherwise the driver will have a dangling task_struct context, which will cause a very nasty kernel oops. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 69ac59aa654c..dd693a1980e8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -138,9 +138,8 @@ static void pvr2_dvb_fh_done(struct pvr2_dvb_fh *fh) pvr2_channel_done(&fh->channel); } -static int pvr2_dvb_feed_thread(void *data) +static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) { - struct pvr2_dvb_adapter *adap = data; struct pvr2_dvb_fh fh; int ret; unsigned int count; @@ -203,12 +202,18 @@ static int pvr2_dvb_feed_thread(void *data) printk(KERN_DEBUG "dvb thread stopped\n"); + return 0; +} + +static int pvr2_dvb_feed_thread(void *data) +{ + int stat = pvr2_dvb_feed_func(data); /* from videobuf-dvb.c: */ while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); schedule(); } - return 0; + return stat; } static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) From a36416d0a70899d3724d2e69e378062e06252a41 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 6 Feb 2008 06:59:48 -0300 Subject: [PATCH 411/452] V4L/DVB (7688): pvrusb2: Clean up dvb streaming start/stop Eliminate the need for a separate pvr2_dvb_fh; since in the DVB context there can only ever be a single instance then there is no need for a separate instance to handle streaming state. This simplifies the module. Also move streaming start/stop out of the feed thread and into the driver's main context - which makes it possible for streaming start up failures to be detected by the DVB core. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 316 ++++++++++------------ drivers/media/video/pvrusb2/pvrusb2-dvb.h | 10 +- 2 files changed, 153 insertions(+), 173 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index dd693a1980e8..ab608412b41e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -28,156 +28,39 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -#define BUFFER_COUNT 32 -#define BUFFER_SIZE PAGE_ALIGN(0x4000) - -struct pvr2_dvb_fh { - struct pvr2_channel channel; - struct pvr2_stream *stream; - struct pvr2_dvb_adapter *adap; - wait_queue_head_t wait_data; - char *buffer_storage[BUFFER_COUNT]; -}; - -static void pvr2_dvb_notify(struct pvr2_dvb_fh *fhp) -{ - wake_up(&fhp->wait_data); -} - -static int pvr2_dvb_fh_init(struct pvr2_dvb_fh *fh, - struct pvr2_dvb_adapter *adap) -{ - struct pvr2_context *pvr = adap->pvr; - unsigned int idx; - int ret; - struct pvr2_buffer *bp; - - init_waitqueue_head(&fh->wait_data); - - fh->adap = adap; - - pvr2_channel_init(&fh->channel, adap->pvr); - - ret = pvr2_channel_claim_stream(&fh->channel, &pvr->video_stream); - /* somebody else already has the stream */ - if (ret != 0) - return ret; - - fh->stream = pvr->video_stream.stream; - - for (idx = 0; idx < BUFFER_COUNT; idx++) { - fh->buffer_storage[idx] = kmalloc(BUFFER_SIZE, GFP_KERNEL); - if (!(fh->buffer_storage[idx])) - break; - } - - if (idx < BUFFER_COUNT) { - /* An allocation appears to have failed */ - ret = -ENOMEM; - goto cleanup; - } - - pvr2_stream_set_callback(pvr->video_stream.stream, - (pvr2_stream_callback) pvr2_dvb_notify, fh); - - ret = pvr2_stream_set_buffer_count(fh->stream, BUFFER_COUNT); - if (ret < 0) - return ret; - - for (idx = 0; idx < BUFFER_COUNT; idx++) { - bp = pvr2_stream_get_buffer(fh->stream, idx); - pvr2_buffer_set_buffer(bp, - fh->buffer_storage[idx], - BUFFER_SIZE); - } - - ret = pvr2_hdw_set_streaming(fh->channel.hdw, 1); - if (ret < 0) - goto cleanup; - - while ((bp = pvr2_stream_get_idle_buffer(fh->stream)) != 0) { - ret = pvr2_buffer_queue(bp); - if (ret < 0) - goto cleanup; - } - - return ret; - -cleanup: - if (fh->stream) - pvr2_stream_kill(fh->stream); - - for (idx = 0; idx < BUFFER_COUNT; idx++) { - if (!(fh->buffer_storage[idx])) - continue; - - kfree(fh->buffer_storage[idx]); - } - pvr2_channel_done(&fh->channel); - - return ret; -} - -static void pvr2_dvb_fh_done(struct pvr2_dvb_fh *fh) -{ - unsigned int idx; - - pvr2_hdw_set_streaming(fh->channel.hdw, 0); - - pvr2_stream_kill(fh->stream); - -// pvr2_channel_claim_stream(&fh->channel, NULL); - - for (idx = 0; idx < BUFFER_COUNT; idx++) { - if (!(fh->buffer_storage[idx])) - continue; - - kfree(fh->buffer_storage[idx]); - } - - pvr2_channel_done(&fh->channel); -} - static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) { - struct pvr2_dvb_fh fh; int ret; unsigned int count; struct pvr2_buffer *bp; + struct pvr2_stream *stream; printk(KERN_DEBUG "dvb thread started\n"); set_freezable(); - memset(&fh, 0, sizeof(fh)); - - ret = pvr2_dvb_fh_init(&fh, adap); - if (ret != 0) - return ret; + stream = adap->channel.stream->stream; for (;;) { - if ((0 == adap->feedcount) || (kthread_should_stop())) - break; + if (kthread_should_stop()) break; /* Not sure about this... */ try_to_freeze(); - bp = pvr2_stream_get_ready_buffer(fh.stream); + bp = pvr2_stream_get_ready_buffer(stream); if (bp != NULL) { count = pvr2_buffer_get_count(bp); if (count) { dvb_dmx_swfilter( &adap->demux, - fh.buffer_storage[ - pvr2_buffer_get_id(bp)], + adap->buffer_storage[ + pvr2_buffer_get_id(bp)], count); } else { ret = pvr2_buffer_get_status(bp); - if (ret < 0) - break; + if (ret < 0) break; } ret = pvr2_buffer_queue(bp); - if (ret < 0) - break; + if (ret < 0) break; /* Since we know we did something to a buffer, just go back and try again. No point in @@ -189,14 +72,11 @@ static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) /* Wait until more buffers become available. */ ret = wait_event_interruptible( - fh.wait_data, - pvr2_stream_get_ready_count(fh.stream) > 0); - if (ret < 0) - break; + adap->buffer_wait_data, + pvr2_stream_get_ready_count(stream) > 0); + if (ret < 0) break; } - pvr2_dvb_fh_done(&fh); - /* If we get here and ret is < 0, then an error has occurred. Probably would be a good idea to communicate that to DVB core... */ @@ -216,41 +96,131 @@ static int pvr2_dvb_feed_thread(void *data) return stat; } -static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) +static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap) { - struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv; - int newfeedcount, ret = 0; + wake_up(&adap->buffer_wait_data); +} - if (adap == NULL) - return -ENODEV; +static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap) +{ + unsigned int idx; + struct pvr2_stream *stream; - mutex_lock(&adap->lock); - newfeedcount = adap->feedcount + (onoff ? 1 : -1); - - if (newfeedcount == 0) { - printk(KERN_DEBUG "stop feeding\n"); - - ret = kthread_stop(adap->thread); + if (adap->thread) { + kthread_stop(adap->thread); adap->thread = NULL; } - adap->feedcount = newfeedcount; - - if (adap->feedcount == onoff && adap->feedcount > 0) { - if (NULL != adap->thread) - goto fail; - - printk(KERN_DEBUG "start feeding\n"); - - adap->thread = kthread_run(pvr2_dvb_feed_thread, - adap, "pvrusb2-dvb"); - if (IS_ERR(adap->thread)) { - ret = PTR_ERR(adap->thread); - adap->thread = NULL; - } - //ret = newfeedcount; + if (adap->channel.stream) { + stream = adap->channel.stream->stream; + } else { + stream = NULL; } -fail: + if (stream) { + pvr2_hdw_set_streaming(adap->channel.hdw, 0); + pvr2_stream_set_callback(stream, NULL, NULL); + pvr2_stream_kill(stream); + pvr2_stream_set_buffer_count(stream, 0); + pvr2_channel_claim_stream(&adap->channel, NULL); + } + + if (adap->stream_run) { + for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { + if (!(adap->buffer_storage[idx])) continue; + kfree(adap->buffer_storage[idx]); + adap->buffer_storage[idx] = 0; + } + adap->stream_run = 0; + } +} + +static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap) +{ + struct pvr2_context *pvr = adap->channel.mc_head; + unsigned int idx; + int ret; + struct pvr2_buffer *bp; + struct pvr2_stream *stream = 0; + + if (adap->stream_run) return -EIO; + + ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream); + /* somebody else already has the stream */ + if (ret < 0) return ret; + + stream = adap->channel.stream->stream; + + for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { + adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE, + GFP_KERNEL); + if (!(adap->buffer_storage[idx])) return -ENOMEM; + } + + pvr2_stream_set_callback(pvr->video_stream.stream, + (pvr2_stream_callback) pvr2_dvb_notify, adap); + + ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT); + if (ret < 0) return ret; + + for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { + bp = pvr2_stream_get_buffer(stream, idx); + pvr2_buffer_set_buffer(bp, + adap->buffer_storage[idx], + PVR2_DVB_BUFFER_SIZE); + } + + ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1); + if (ret < 0) return ret; + + while ((bp = pvr2_stream_get_idle_buffer(stream)) != 0) { + ret = pvr2_buffer_queue(bp); + if (ret < 0) return ret; + } + + adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb"); + + if (IS_ERR(adap->thread)) { + ret = PTR_ERR(adap->thread); + adap->thread = NULL; + return ret; + } + + adap->stream_run = !0; + + return 0; +} + +static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap) +{ + int ret = pvr2_dvb_stream_do_start(adap); + if (ret < 0) pvr2_dvb_stream_end(adap); + return ret; +} + +static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) +{ + struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv; + int ret = 0; + + if (adap == NULL) return -ENODEV; + + mutex_lock(&adap->lock); + do { + if (onoff) { + if (!adap->feedcount) { + printk(KERN_DEBUG "start feeding\n"); + ret = pvr2_dvb_stream_start(adap); + if (ret < 0) break; + } + (adap->feedcount)++; + } else if (adap->feedcount > 0) { + (adap->feedcount)--; + if (!adap->feedcount) { + printk(KERN_DEBUG "stop feeding\n"); + pvr2_dvb_stream_end(adap); + } + } + } while (0); mutex_unlock(&adap->lock); return ret; @@ -287,7 +257,7 @@ static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap) ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb", THIS_MODULE/*&hdw->usb_dev->owner*/, - &adap->pvr->hdw->usb_dev->dev, + &adap->channel.hdw->usb_dev->dev, adapter_nr); if (ret < 0) { err("dvb_register_adapter failed: error %d", ret); @@ -351,7 +321,7 @@ static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) { - struct pvr2_hdw *hdw = adap->pvr->hdw; + struct pvr2_hdw *hdw = adap->channel.hdw; struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; int ret; @@ -419,14 +389,14 @@ static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap) int pvr2_dvb_init(struct pvr2_context *pvr) { int ret = 0; - - pvr->hdw->dvb.pvr = pvr; + struct pvr2_dvb_adapter *adap; + adap = &pvr->hdw->dvb; + adap->init = !0; + pvr2_channel_init(&adap->channel, pvr); + init_waitqueue_head(&adap->buffer_wait_data); mutex_init(&pvr->hdw->dvb.lock); - ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb); - if (ret < 0) - goto fail; - + if (ret < 0) goto fail; ret = pvr2_dvb_frontend_init(&pvr->hdw->dvb); fail: return ret; @@ -434,10 +404,12 @@ fail: int pvr2_dvb_exit(struct pvr2_context *pvr) { - pvr2_dvb_frontend_exit(&pvr->hdw->dvb); - pvr2_dvb_adapter_exit(&pvr->hdw->dvb); - - pvr->hdw->dvb.pvr = NULL; - + struct pvr2_dvb_adapter *adap; + adap = &pvr->hdw->dvb; + if (!adap->init) return 0; + pvr2_dvb_stream_end(adap); + pvr2_dvb_frontend_exit(adap); + pvr2_dvb_adapter_exit(adap); + pvr2_channel_done(&adap->channel); return 0; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h index 98728d44a4b6..651324ffab3d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h @@ -7,8 +7,11 @@ #include "dmxdev.h" #include "pvrusb2-context.h" +#define PVR2_DVB_BUFFER_COUNT 32 +#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000) + struct pvr2_dvb_adapter { - struct pvr2_context *pvr; + struct pvr2_channel channel; struct dvb_adapter dvb_adap; struct dmxdev dmxdev; @@ -23,6 +26,11 @@ struct pvr2_dvb_adapter { struct mutex lock; unsigned int digital_up:1; + unsigned int stream_run:1; + unsigned int init:1; + + wait_queue_head_t buffer_wait_data; + char *buffer_storage[PVR2_DVB_BUFFER_COUNT]; }; struct pvr2_dvb_props { From 891d99efc5be16d2762bdbb9d0486f7250990eee Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 9 Feb 2008 15:44:30 -0300 Subject: [PATCH 412/452] V4L/DVB (7689): pvrusb2-dvb: Rework module tear-down Rather than making an explicit call to tear down the pvrusb2-dvb module, use the callback in the pvr2_channel structure. This has the advantage that now tear-down only happens when it makes sense. The previous implementation had scenarios where it was possible for the tear-down call to happen without a prior initialization. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 31 +++++++++++++--------- drivers/media/video/pvrusb2/pvrusb2-dvb.h | 2 -- drivers/media/video/pvrusb2/pvrusb2-main.c | 3 --- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index ab608412b41e..38077b2c5282 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -386,30 +386,37 @@ static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap) return 0; } +static void pvr2_dvb_done(struct pvr2_dvb_adapter *adap) +{ + pvr2_dvb_stream_end(adap); + pvr2_dvb_frontend_exit(adap); + pvr2_dvb_adapter_exit(adap); + pvr2_channel_done(&adap->channel); +} + +static void pvr2_dvb_internal_check(struct pvr2_channel *chp) +{ + struct pvr2_dvb_adapter *adap; + adap = container_of(chp, struct pvr2_dvb_adapter, channel); + if (!adap->channel.mc_head->disconnect_flag) return; + pvr2_dvb_done(adap); +} + int pvr2_dvb_init(struct pvr2_context *pvr) { int ret = 0; struct pvr2_dvb_adapter *adap; adap = &pvr->hdw->dvb; - adap->init = !0; pvr2_channel_init(&adap->channel, pvr); + adap->channel.check_func = pvr2_dvb_internal_check; init_waitqueue_head(&adap->buffer_wait_data); mutex_init(&pvr->hdw->dvb.lock); ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb); if (ret < 0) goto fail; ret = pvr2_dvb_frontend_init(&pvr->hdw->dvb); + return ret; fail: + pvr2_channel_done(&adap->channel); return ret; } -int pvr2_dvb_exit(struct pvr2_context *pvr) -{ - struct pvr2_dvb_adapter *adap; - adap = &pvr->hdw->dvb; - if (!adap->init) return 0; - pvr2_dvb_stream_end(adap); - pvr2_dvb_frontend_exit(adap); - pvr2_dvb_adapter_exit(adap); - pvr2_channel_done(&adap->channel); - return 0; -} diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h index 651324ffab3d..1326f6f455a6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h @@ -27,7 +27,6 @@ struct pvr2_dvb_adapter { unsigned int digital_up:1; unsigned int stream_run:1; - unsigned int init:1; wait_queue_head_t buffer_wait_data; char *buffer_storage[PVR2_DVB_BUFFER_COUNT]; @@ -39,6 +38,5 @@ struct pvr2_dvb_props { }; int pvr2_dvb_init(struct pvr2_context *pvr); -int pvr2_dvb_exit(struct pvr2_context *pvr); #endif /* __PVRUSB2_DVB_H__ */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index 68f4a7480737..42b4c8d5a1ed 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -99,9 +99,6 @@ static void pvr_disconnect(struct usb_interface *intf) pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr); -#ifdef CONFIG_VIDEO_PVRUSB2_DVB - pvr2_dvb_exit(pvr); -#endif usb_set_intfdata (intf, NULL); pvr2_context_disconnect(pvr); From 7dcc48fb55d18258e7db039f44a031e6828e6bad Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 9 Feb 2008 15:55:54 -0300 Subject: [PATCH 413/452] V4L/DVB (7690): pvrusb2-dvb: Remove digital_up flag Other pvrusb2-dvb changes have made the digital_up flag obsolete. So kill it. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 17 ++++++----------- drivers/media/video/pvrusb2/pvrusb2-dvb.h | 1 - 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 38077b2c5282..f32d052ff4e6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -293,8 +293,6 @@ static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap) dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); - adap->digital_up = 1; - return 0; err_dmx_dev: @@ -307,15 +305,12 @@ err: static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) { - if (adap->digital_up) { - printk(KERN_DEBUG "unregistering DVB devices\n"); - dvb_net_release(&adap->dvb_net); - adap->demux.dmx.close(&adap->demux.dmx); - dvb_dmxdev_release(&adap->dmxdev); - dvb_dmx_release(&adap->demux); - dvb_unregister_adapter(&adap->dvb_adap); - adap->digital_up = 0; - } + printk(KERN_DEBUG "unregistering DVB devices\n"); + dvb_net_release(&adap->dvb_net); + adap->demux.dmx.close(&adap->demux.dmx); + dvb_dmxdev_release(&adap->dmxdev); + dvb_dmx_release(&adap->demux); + dvb_unregister_adapter(&adap->dvb_adap); return 0; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h index 1326f6f455a6..e37cb7bc2fc6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h @@ -25,7 +25,6 @@ struct pvr2_dvb_adapter { struct task_struct *thread; struct mutex lock; - unsigned int digital_up:1; unsigned int stream_run:1; wait_queue_head_t buffer_wait_data; From 129a2f5efd95959c44a2bfeea8ee8b7c17252db6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 9 Feb 2008 16:29:52 -0300 Subject: [PATCH 414/452] V4L/DVB (7691): pvrusb2-dvb: Don't initialize if device lacks a digital side In the end we'd like the dvb interface to always be present - even for analog devices (via the mpeg encoder). However right now pvrusb2-dvb won't operate correctly if the hardware doesn't have a digital tuner, so don't initialize the DVB interface unless we know we have a digital tuner. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index f32d052ff4e6..177240051674 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -401,16 +401,25 @@ int pvr2_dvb_init(struct pvr2_context *pvr) { int ret = 0; struct pvr2_dvb_adapter *adap; + if (!pvr->hdw->hdw_desc->dvb_props) { + /* Device lacks a digital interface so don't set up + the DVB side of the driver either. For now. */ + return 0; + } adap = &pvr->hdw->dvb; pvr2_channel_init(&adap->channel, pvr); adap->channel.check_func = pvr2_dvb_internal_check; init_waitqueue_head(&adap->buffer_wait_data); mutex_init(&pvr->hdw->dvb.lock); ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb); - if (ret < 0) goto fail; + if (ret < 0) goto fail1; ret = pvr2_dvb_frontend_init(&pvr->hdw->dvb); - return ret; -fail: + if (ret < 0) goto fail2; + return 0; + +fail2: + pvr2_dvb_adapter_exit(adap); +fail1: pvr2_channel_done(&adap->channel); return ret; } From c5317b17f6ca74531a6c707873dc5d25f1877ac3 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 9 Feb 2008 19:47:07 -0300 Subject: [PATCH 415/452] V4L/DVB (7692): pvrusb2-dvb: Further clean up dvb init/tear-down Move pvr2_dvb_adapter usage out of the pvrusb2 driver core - it's really private to the pvrusb2-dvb module and nothing outside of the dvb implementation should care about it. Creation / destruction of the pvr2_dvb_adapter instance is now contained entirely within pvrusb2-dvb.c. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 20 ++++++++++--------- drivers/media/video/pvrusb2/pvrusb2-dvb.h | 2 +- .../video/pvrusb2/pvrusb2-hdw-internal.h | 3 --- drivers/media/video/pvrusb2/pvrusb2-main.c | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 177240051674..1a7c3ddace07 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -381,12 +381,13 @@ static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap) return 0; } -static void pvr2_dvb_done(struct pvr2_dvb_adapter *adap) +static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap) { pvr2_dvb_stream_end(adap); pvr2_dvb_frontend_exit(adap); pvr2_dvb_adapter_exit(adap); pvr2_channel_done(&adap->channel); + kfree(adap); } static void pvr2_dvb_internal_check(struct pvr2_channel *chp) @@ -394,10 +395,10 @@ static void pvr2_dvb_internal_check(struct pvr2_channel *chp) struct pvr2_dvb_adapter *adap; adap = container_of(chp, struct pvr2_dvb_adapter, channel); if (!adap->channel.mc_head->disconnect_flag) return; - pvr2_dvb_done(adap); + pvr2_dvb_destroy(adap); } -int pvr2_dvb_init(struct pvr2_context *pvr) +struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr) { int ret = 0; struct pvr2_dvb_adapter *adap; @@ -406,21 +407,22 @@ int pvr2_dvb_init(struct pvr2_context *pvr) the DVB side of the driver either. For now. */ return 0; } - adap = &pvr->hdw->dvb; + adap = kzalloc(sizeof(*adap), GFP_KERNEL); + if (!adap) return adap; pvr2_channel_init(&adap->channel, pvr); adap->channel.check_func = pvr2_dvb_internal_check; init_waitqueue_head(&adap->buffer_wait_data); - mutex_init(&pvr->hdw->dvb.lock); - ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb); + mutex_init(&adap->lock); + ret = pvr2_dvb_adapter_init(adap); if (ret < 0) goto fail1; - ret = pvr2_dvb_frontend_init(&pvr->hdw->dvb); + ret = pvr2_dvb_frontend_init(adap); if (ret < 0) goto fail2; - return 0; + return adap; fail2: pvr2_dvb_adapter_exit(adap); fail1: pvr2_channel_done(&adap->channel); - return ret; + return NULL; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h index e37cb7bc2fc6..884ff916a352 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h @@ -36,6 +36,6 @@ struct pvr2_dvb_props { int (*tuner_attach) (struct pvr2_dvb_adapter *); }; -int pvr2_dvb_init(struct pvr2_context *pvr); +struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr); #endif /* __PVRUSB2_DVB_H__ */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 6fe0a882209f..c725495826ce 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -41,7 +41,6 @@ #include "pvrusb2-io.h" #include #include "pvrusb2-devattr.h" -#include "pvrusb2-dvb.h" /* Legal values for PVR2_CID_HSM */ #define PVR2_CVAL_HSM_FAIL 0 @@ -374,8 +373,6 @@ struct pvr2_hdw { struct pvr2_ctrl *controls; unsigned int control_cnt; - - struct pvr2_dvb_adapter dvb; }; /* This function gets the current frequency */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index 42b4c8d5a1ed..54d9f168d7ad 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -62,7 +62,7 @@ static void pvr_setup_attach(struct pvr2_context *pvr) pvr2_v4l2_create(pvr); #ifdef CONFIG_VIDEO_PVRUSB2_DVB /* Create association with dvb layer */ - pvr2_dvb_init(pvr); + pvr2_dvb_create(pvr); #endif #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS pvr2_sysfs_create(pvr,class_ptr); From e6d1186543784222024da9c688766effd2ca3163 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 9 Feb 2008 19:47:52 -0300 Subject: [PATCH 416/452] V4L/DVB (7693): pvrusb2-dvb: Change usage of 0 --> NULL Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 1a7c3ddace07..58ef5caba83a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -405,7 +405,7 @@ struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr) if (!pvr->hdw->hdw_desc->dvb_props) { /* Device lacks a digital interface so don't set up the DVB side of the driver either. For now. */ - return 0; + return NULL; } adap = kzalloc(sizeof(*adap), GFP_KERNEL); if (!adap) return adap; From ce52f81138512dc9c4b0ab00f11806000b597a45 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 16 Mar 2008 02:12:12 -0300 Subject: [PATCH 417/452] V4L/DVB (7694): pvrusb2: Fix compilation goof when CONFIG_VIDEO_PVRUSB2_DVB is off Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index cc2c4d78cf41..dd4e5adefd8f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -23,7 +23,9 @@ #include #include +#ifdef CONFIG_VIDEO_PVRUSB2_DVB #include "pvrusb2-dvb.h" +#endif /* From 98e184d978c9fdd294c169e468ab4a3e51a8be2d Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:28:20 -0300 Subject: [PATCH 418/452] V4L/DVB (7695): pvrusb2: Make associativity of == and && explicit (cosmetic) 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 8bdb807b19b8..6a820b713fec 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3400,8 +3400,8 @@ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) { int status,cc; if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) && - hdw->hdw_desc->digital_control_scheme == - PVR2_DIGITAL_SCHEME_HAUPPAUGE) { + (hdw->hdw_desc->digital_control_scheme == + PVR2_DIGITAL_SCHEME_HAUPPAUGE)) { cc = (runFl ? FX2CMD_HCW_DTV_STREAMING_ON : FX2CMD_HCW_DTV_STREAMING_OFF); From 38d9a2cf2db30b37dde81ec5f8b4de0fd9843ccc Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:30:48 -0300 Subject: [PATCH 419/452] V4L/DVB (7696): pvrusb2: state control tweak Don't trigger a pathway state change if it's already been triggered (eliminates some wasted processing and some debug output noise) Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 6a820b713fec..307a38d91c85 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2401,7 +2401,7 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) } } - if (hdw->input_dirty && + if (hdw->input_dirty && hdw->state_pathway_ok && (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) != hdw->pathway_state)) { From b9a37d9124dc834f2448558dbbe766eee077b954 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:31:40 -0300 Subject: [PATCH 420/452] V4L/DVB (7697): pvrusb2: Fix misleading bit of debug output (trivial) Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 307a38d91c85..4329e4366f9f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3796,7 +3796,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, (hdw->state_encoder_config ? " " : (hdw->state_encoder_waitok ? - "" : " ")), + "" : " ")), (hdw->state_usbstream_run ? " " : " "), (hdw->state_pathway_ok ? From be9cbb7c559eddea19604abafb89faf9c8666715 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:32:23 -0300 Subject: [PATCH 421/452] V4L/DVB (7698): pvrusb2: Remove never-reached break statements (trivial) Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 4329e4366f9f..16c7df9c093f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3801,13 +3801,11 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, " " : " "), (hdw->state_pathway_ok ? " " : "")); - break; case 3: return scnprintf( buf,acnt, "state: %s", pvr2_get_state_name(hdw->master_state)); - break; default: break; } return 0; From ad0992e97c5416e431e19dcfd4f6c84448dc1bc2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:34:45 -0300 Subject: [PATCH 422/452] V4L/DVB (7699): pvrusb2: Implement statistics for USB I/O performance / tracking Implement a mechanism in the pvrusb2 driver for gathering statistics on the stream buffering, including bytes transferred, buffers handled, buffers in flight, etc. This is useful for debugging certain classes of streaming issues and for determining if the buffer pool size is generally correct for the driver. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- .../media/video/pvrusb2/pvrusb2-debugifc.c | 24 +++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 18 +++++++++++ drivers/media/video/pvrusb2/pvrusb2-io.c | 30 +++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-io.h | 12 ++++++++ 4 files changed, 84 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index b0687430fdd4..b53121c78ff9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -164,6 +164,8 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw, int ccnt; int ret; u32 gpio_dir,gpio_in,gpio_out; + struct pvr2_stream_stats stats; + struct pvr2_stream *sp; ret = pvr2_hdw_is_hsm(hdw); ccnt = scnprintf(buf,acnt,"USB link speed: %s\n", @@ -182,6 +184,24 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw, pvr2_hdw_get_streaming(hdw) ? "on" : "off"); bcnt += ccnt; acnt -= ccnt; buf += ccnt; + + sp = pvr2_hdw_get_video_stream(hdw); + if (sp) { + pvr2_stream_get_stats(sp, &stats, 0); + ccnt = scnprintf( + buf,acnt, + "Bytes streamed=%u" + " URBs: queued=%u idle=%u ready=%u" + " processed=%u failed=%u\n", + stats.bytes_processed, + stats.buffers_in_queue, + stats.buffers_in_idle, + stats.buffers_in_ready, + stats.buffers_processed, + stats.buffers_failed); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + } + return bcnt; } @@ -220,6 +240,10 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf, return pvr2_hdw_cmd_decoder_reset(hdw); } else if (debugifc_match_keyword(wptr,wlen,"worker")) { return pvr2_hdw_untrip(hdw); + } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) { + pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw), + NULL, !0); + return 0; } return -EINVAL; } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 16c7df9c093f..a26b5251ec1b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3806,6 +3806,24 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, buf,acnt, "state: %s", pvr2_get_state_name(hdw->master_state)); + case 4: { + struct pvr2_stream_stats stats; + if (!hdw->vid_stream) break; + pvr2_stream_get_stats(hdw->vid_stream, + &stats, + 0); + return scnprintf( + buf,acnt, + "Bytes streamed=%u" + " URBs: queued=%u idle=%u ready=%u" + " processed=%u failed=%u", + stats.bytes_processed, + stats.buffers_in_queue, + stats.buffers_in_idle, + stats.buffers_in_ready, + stats.buffers_processed, + stats.buffers_failed); + } default: break; } return 0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c index a9889ff96ecc..7aff8b720064 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-io.c +++ b/drivers/media/video/pvrusb2/pvrusb2-io.c @@ -80,6 +80,10 @@ struct pvr2_stream { /* Tracking state for tolerating errors */ unsigned int fail_count; unsigned int fail_tolerance; + + unsigned int buffers_processed; + unsigned int buffers_failed; + unsigned int bytes_processed; }; struct pvr2_buffer { @@ -446,6 +450,8 @@ static void buffer_complete(struct urb *urb) (urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (urb->status == -ESHUTDOWN)) { + (sp->buffers_processed)++; + sp->bytes_processed += urb->actual_length; bp->used_count = urb->actual_length; if (sp->fail_count) { pvr2_trace(PVR2_TRACE_TOLERANCE, @@ -457,11 +463,13 @@ static void buffer_complete(struct urb *urb) // We can tolerate this error, because we're below the // threshold... (sp->fail_count)++; + (sp->buffers_failed)++; pvr2_trace(PVR2_TRACE_TOLERANCE, "stream %p ignoring error %d" " - fail count increased to %u", sp,urb->status,sp->fail_count); } else { + (sp->buffers_failed)++; bp->status = urb->status; } spin_unlock_irqrestore(&sp->list_lock,irq_flags); @@ -515,6 +523,28 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp, } while(0); mutex_unlock(&sp->mutex); } +void pvr2_stream_get_stats(struct pvr2_stream *sp, + struct pvr2_stream_stats *stats, + int zero_counts) +{ + unsigned long irq_flags; + spin_lock_irqsave(&sp->list_lock,irq_flags); + if (stats) { + stats->buffers_in_queue = sp->q_count; + stats->buffers_in_idle = sp->i_count; + stats->buffers_in_ready = sp->r_count; + stats->buffers_processed = sp->buffers_processed; + stats->buffers_failed = sp->buffers_failed; + stats->bytes_processed = sp->bytes_processed; + } + if (zero_counts) { + sp->buffers_processed = 0; + sp->buffers_failed = 0; + sp->bytes_processed = 0; + } + spin_unlock_irqrestore(&sp->list_lock,irq_flags); +} + /* Query / set the nominal buffer count */ int pvr2_stream_get_buffer_count(struct pvr2_stream *sp) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h index 93279cc2a35e..42fcf8281a87 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-io.h +++ b/drivers/media/video/pvrusb2/pvrusb2-io.h @@ -36,6 +36,15 @@ enum pvr2_buffer_state { struct pvr2_stream; struct pvr2_buffer; +struct pvr2_stream_stats { + unsigned int buffers_in_queue; + unsigned int buffers_in_idle; + unsigned int buffers_in_ready; + unsigned int buffers_processed; + unsigned int buffers_failed; + unsigned int bytes_processed; +}; + /* Initialize / tear down stream structure */ struct pvr2_stream *pvr2_stream_create(void); void pvr2_stream_destroy(struct pvr2_stream *); @@ -45,6 +54,9 @@ void pvr2_stream_setup(struct pvr2_stream *, void pvr2_stream_set_callback(struct pvr2_stream *, pvr2_stream_callback func, void *data); +void pvr2_stream_get_stats(struct pvr2_stream *, + struct pvr2_stream_stats *, + int zero_counts); /* Query / set the nominal buffer count */ int pvr2_stream_get_buffer_count(struct pvr2_stream *); From 448cb48e6e2fcd3a948cc549c5c6ab7f84440a54 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:36:25 -0300 Subject: [PATCH 423/452] V4L/DVB (7700): pvrusb2: Make FX2 command codes unsigned constants Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h index a866c949243c..abaada31e66e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h +++ b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h @@ -22,41 +22,41 @@ #ifndef _PVRUSB2_FX2_CMD_H_ #define _PVRUSB2_FX2_CMD_H_ -#define FX2CMD_MEM_WRITE_DWORD 0x01 -#define FX2CMD_MEM_READ_DWORD 0x02 +#define FX2CMD_MEM_WRITE_DWORD 0x01u +#define FX2CMD_MEM_READ_DWORD 0x02u -#define FX2CMD_MEM_READ_64BYTES 0x28 +#define FX2CMD_MEM_READ_64BYTES 0x28u -#define FX2CMD_REG_WRITE 0x04 -#define FX2CMD_REG_READ 0x05 -#define FX2CMD_MEMSEL 0x06 +#define FX2CMD_REG_WRITE 0x04u +#define FX2CMD_REG_READ 0x05u +#define FX2CMD_MEMSEL 0x06u -#define FX2CMD_I2C_WRITE 0x08 -#define FX2CMD_I2C_READ 0x09 +#define FX2CMD_I2C_WRITE 0x08u +#define FX2CMD_I2C_READ 0x09u -#define FX2CMD_GET_USB_SPEED 0x0b +#define FX2CMD_GET_USB_SPEED 0x0bu -#define FX2CMD_STREAMING_ON 0x36 -#define FX2CMD_STREAMING_OFF 0x37 +#define FX2CMD_STREAMING_ON 0x36u +#define FX2CMD_STREAMING_OFF 0x37u -#define FX2CMD_FWPOST1 0x52 +#define FX2CMD_FWPOST1 0x52u -#define FX2CMD_POWER_OFF 0xdc -#define FX2CMD_POWER_ON 0xde +#define FX2CMD_POWER_OFF 0xdcu +#define FX2CMD_POWER_ON 0xdeu -#define FX2CMD_DEEP_RESET 0xdd +#define FX2CMD_DEEP_RESET 0xddu -#define FX2CMD_GET_EEPROM_ADDR 0xeb -#define FX2CMD_GET_IR_CODE 0xec +#define FX2CMD_GET_EEPROM_ADDR 0xebu +#define FX2CMD_GET_IR_CODE 0xecu -#define FX2CMD_HCW_DEMOD_RESETIN 0xf0 -#define FX2CMD_HCW_DTV_STREAMING_ON 0xf1 -#define FX2CMD_HCW_DTV_STREAMING_OFF 0xf2 +#define FX2CMD_HCW_DEMOD_RESETIN 0xf0u +#define FX2CMD_HCW_DTV_STREAMING_ON 0xf1u +#define FX2CMD_HCW_DTV_STREAMING_OFF 0xf2u -#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 +#define FX2CMD_ONAIR_DTV_STREAMING_ON 0xa0u +#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u +#define FX2CMD_ONAIR_DTV_POWER_ON 0xa2u +#define FX2CMD_ONAIR_DTV_POWER_OFF 0xa3u #endif /* _PVRUSB2_FX2_CMD_H_ */ From 1c9d10d4d2e791a9eacd9f919dec78c5bc6737e8 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:38:54 -0300 Subject: [PATCH 424/452] V4L/DVB (7701): pvrusb2: Centralize handling of simple FX2 commands Numerous places in the driver need to issue simple commands to the FX2 microcontroller (e.g. only 1 or 2 bytes, no reply needed). Previously each place that did this, had to take lock, set up a central buffer, and call the function to perform the handshake. This change puts these steps into a single spot. This also has the effect of removing the need to mess with the control lock from numerous places in the code. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 198 +++++++++++++--------- 1 file changed, 116 insertions(+), 82 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index a26b5251ec1b..063aed0067cd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -216,6 +216,39 @@ static const char *pvr2_state_names[] = { }; +struct pvr2_fx2cmd_desc { + unsigned char id; + unsigned char *desc; +}; + +static const struct pvr2_fx2cmd_desc pvr2_fx2cmd_desc[] = { + {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"}, + {FX2CMD_MEM_READ_DWORD, "read encoder dword"}, + {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"}, + {FX2CMD_REG_WRITE, "write encoder register"}, + {FX2CMD_REG_READ, "read encoder register"}, + {FX2CMD_MEMSEL, "encoder memsel"}, + {FX2CMD_I2C_WRITE, "i2c write"}, + {FX2CMD_I2C_READ, "i2c read"}, + {FX2CMD_GET_USB_SPEED, "get USB speed"}, + {FX2CMD_STREAMING_ON, "stream on"}, + {FX2CMD_STREAMING_OFF, "stream off"}, + {FX2CMD_FWPOST1, "fwpost1"}, + {FX2CMD_POWER_OFF, "power off"}, + {FX2CMD_POWER_ON, "power on"}, + {FX2CMD_DEEP_RESET, "deep reset"}, + {FX2CMD_GET_EEPROM_ADDR, "get rom addr"}, + {FX2CMD_GET_IR_CODE, "get IR code"}, + {FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"}, + {FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"}, + {FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"}, + {FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"}, + {FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"}, + {FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"}, + {FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"}, +}; + + static void pvr2_hdw_state_sched(struct pvr2_hdw *); static int pvr2_hdw_state_eval(struct pvr2_hdw *); static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); @@ -231,6 +264,7 @@ static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); static void pvr2_hdw_quiescent_timeout(unsigned long); static void pvr2_hdw_encoder_wait_timeout(unsigned long); +static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32); static int pvr2_send_request_ex(struct pvr2_hdw *hdw, unsigned int timeout,int probe_fl, void *write_data,unsigned int write_len, @@ -1219,13 +1253,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/ ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/ ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/ - LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = FX2CMD_FWPOST1; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); - hdw->cmd_buffer[0] = FX2CMD_MEMSEL; - hdw->cmd_buffer[1] = 0; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0); - } while (0); LOCK_GIVE(hdw->ctl_lock); + ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1); + ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16)); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, @@ -1290,11 +1319,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/ ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/ - LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = FX2CMD_MEMSEL; - hdw->cmd_buffer[1] = 0; - ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0); - } while (0); LOCK_GIVE(hdw->ctl_lock); + ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16)); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, @@ -3093,6 +3118,67 @@ int pvr2_send_request(struct pvr2_hdw *hdw, read_data,read_len); } + +static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode) +{ + int ret; + unsigned int cnt = 1; + unsigned int args = 0; + LOCK_TAKE(hdw->ctl_lock); + hdw->cmd_buffer[0] = cmdcode & 0xffu; + args = (cmdcode >> 8) & 0xffu; + args = (args > 2) ? 2 : args; + if (args) { + cnt += args; + hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu; + if (args > 1) { + hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu; + } + } + if (pvrusb2_debug & PVR2_TRACE_INIT) { + unsigned int idx; + unsigned int ccnt,bcnt; + char tbuf[50]; + cmdcode &= 0xffu; + bcnt = 0; + ccnt = scnprintf(tbuf+bcnt, + sizeof(tbuf)-bcnt, + "Sending FX2 command 0x%x",cmdcode); + bcnt += ccnt; + for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) { + if (pvr2_fx2cmd_desc[idx].id == cmdcode) { + ccnt = scnprintf(tbuf+bcnt, + sizeof(tbuf)-bcnt, + " \"%s\"", + pvr2_fx2cmd_desc[idx].desc); + bcnt += ccnt; + break; + } + } + if (args) { + ccnt = scnprintf(tbuf+bcnt, + sizeof(tbuf)-bcnt, + " (%u",hdw->cmd_buffer[1]); + bcnt += ccnt; + if (args > 1) { + ccnt = scnprintf(tbuf+bcnt, + sizeof(tbuf)-bcnt, + ",%u",hdw->cmd_buffer[2]); + bcnt += ccnt; + } + ccnt = scnprintf(tbuf+bcnt, + sizeof(tbuf)-bcnt, + ")"); + bcnt += ccnt; + } + pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf); + } + ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0); + LOCK_GIVE(hdw->ctl_lock); + return ret; +} + + int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data) { int ret; @@ -3200,40 +3286,19 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val) int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw) { - int status; - LOCK_TAKE(hdw->ctl_lock); do { - pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset"); - hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET; - status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); - } while (0); LOCK_GIVE(hdw->ctl_lock); - return status; + return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET); } -static int pvr2_hdw_cmd_power_ctrl(struct pvr2_hdw *hdw, int onoff) -{ - int status; - LOCK_TAKE(hdw->ctl_lock); do { - 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); + return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON); } + int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw) { - return pvr2_hdw_cmd_power_ctrl(hdw, 0); + return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF); } @@ -3260,55 +3325,29 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) 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 (%s)", - (onoff ? "on" : "off")); - 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; + hdw->flag_ok = !0; + return pvr2_issue_simple_cmd(hdw, + FX2CMD_HCW_DEMOD_RESETIN | + (1 << 8) | + ((onoff ? 1 : 0) << 16)); } 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 (%s)", - (onoff ? "on" : "off")); - 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; + hdw->flag_ok = !0; + return pvr2_issue_simple_cmd(hdw,(onoff ? + FX2CMD_ONAIR_DTV_POWER_ON : + FX2CMD_ONAIR_DTV_POWER_OFF)); } 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); - status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0); - } while (0); LOCK_GIVE(hdw->ctl_lock); - return status; + return pvr2_issue_simple_cmd(hdw,(onoff ? + FX2CMD_ONAIR_DTV_STREAMING_ON : + FX2CMD_ONAIR_DTV_STREAMING_OFF)); } @@ -3398,7 +3437,7 @@ static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff) /* Stop / start video stream transport */ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) { - int status,cc; + int cc; if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) && (hdw->hdw_desc->digital_control_scheme == PVR2_DIGITAL_SCHEME_HAUPPAUGE)) { @@ -3410,12 +3449,7 @@ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF); } - - LOCK_TAKE(hdw->ctl_lock); do { - 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; + return pvr2_issue_simple_cmd(hdw,cc); } From bb0c2fe0c423d6501395e626501dd8747823cafb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:41:19 -0300 Subject: [PATCH 425/452] V4L/DVB (7702): pvrusb2: Rework USB streaming start/stop execution The commands to start / stop USB streaming for an analog device are fairly standard, owing to the fact that all supported devices apparently started from the same common reference design. However with digital mode, the commands seem to vary by vendor. This change makes that variance more explicit. It also cleans up a related problem for OnAir devices which prevented digital mode from working at all. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 52 ++++++++++++++++------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 063aed0067cd..b711328400e1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3377,9 +3377,7 @@ static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl) /* 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); + pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl); break; default: break; } @@ -3437,19 +3435,43 @@ static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff) /* Stop / start video stream transport */ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) { - int 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); + int ret; + + /* If we're in analog mode, then just issue the usual analog + command. */ + if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { + return pvr2_issue_simple_cmd(hdw, + (runFl ? + FX2CMD_STREAMING_ON : + FX2CMD_STREAMING_OFF)); + /*Note: Not reached */ + } + + if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) { + /* Whoops, we don't know what mode we're in... */ + return -EINVAL; + } + + /* To get here we have to be in digital mode. The mechanism here + is unfortunately different for different vendors. So we switch + on the device's digital scheme attribute in order to figure out + what to do. */ + switch (hdw->hdw_desc->digital_control_scheme) { + case PVR2_DIGITAL_SCHEME_HAUPPAUGE: + return pvr2_issue_simple_cmd(hdw, + (runFl ? + FX2CMD_HCW_DTV_STREAMING_ON : + FX2CMD_HCW_DTV_STREAMING_OFF)); + case PVR2_DIGITAL_SCHEME_ONAIR: + ret = pvr2_issue_simple_cmd(hdw, + (runFl ? + FX2CMD_STREAMING_ON : + FX2CMD_STREAMING_OFF)); + if (ret) return ret; + return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl); + default: + return -EINVAL; } - return pvr2_issue_simple_cmd(hdw,cc); } From 694dca2b80d5e17f5edddacf4fcdacc1091623f2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:42:10 -0300 Subject: [PATCH 426/452] V4L/DVB (7703): pvrusb2: Fix minor problem involving ARRAY_SIZE confusion 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(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b711328400e1..195e974f5eb0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -216,12 +216,12 @@ static const char *pvr2_state_names[] = { }; -struct pvr2_fx2cmd_desc { +struct pvr2_fx2cmd_descdef { unsigned char id; unsigned char *desc; }; -static const struct pvr2_fx2cmd_desc pvr2_fx2cmd_desc[] = { +static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = { {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"}, {FX2CMD_MEM_READ_DWORD, "read encoder dword"}, {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"}, From 1b1b8d7841684d9d6273c479abe39d517dfb8cb8 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 28 Mar 2008 05:43:45 -0300 Subject: [PATCH 427/452] V4L/DVB (7704): pvrusb2: Fix slop involving use of struct which might not be defined When the DVB interface is not compiled, the pvr2_dvb_props struct is not available - so it really should be ifdef'ed out as well. This didn't cause an error because in this context its usage was as an opaque pointer. But it really shouldn't be present at all if DVB is not enabled. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index dd4e5adefd8f..38913519a818 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -68,9 +68,11 @@ struct pvr2_device_desc { was initialized from internal ROM. */ struct pvr2_string_table fx2_firmware; +#ifdef CONFIG_VIDEO_PVRUSB2_DVB /* callback functions to handle attachment of digital tuner & demod */ struct pvr2_dvb_props *dvb_props; +#endif /* 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 From 906a495741bf63a7448ca4c452d70f937549e9ad Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 28 Mar 2008 05:47:47 -0300 Subject: [PATCH 428/452] V4L/DVB (7705): pvrusb2: Enable OnAir digital operation Signed-off-by: Michael Krufky Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 75 ++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index f489aab112dc..6794862bbb19 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -32,7 +32,11 @@ pvr2_device_desc structures. /* This is needed in order to pull in tuner type ids... */ #include #include - +#ifdef CONFIG_VIDEO_PVRUSB2_DVB +#include "pvrusb2-hdw-internal.h" +#include "lgdt330x.h" +#include "tuner-simple.h" +#endif /*------------------------------------------------------------------------*/ @@ -147,6 +151,38 @@ static const struct pvr2_device_desc pvr2_device_gotview_2d = { /*------------------------------------------------------------------------*/ /* OnAir Creator */ +#ifdef CONFIG_VIDEO_PVRUSB2_DVB +static struct lgdt330x_config pvr2_lgdt3303_config = { + .demod_address = 0x0e, + .demod_chip = LGDT3303, + .clock_polarity_flip = 1, +}; + +static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap) +{ + adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config, + &adap->channel.hdw->i2c_adap); + if (adap->fe) + return 0; + + return -EIO; +} + +static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap) +{ + dvb_attach(simple_tuner_attach, adap->fe, + &adap->channel.hdw->i2c_adap, 0x61, + TUNER_LG_TDVS_H06XF); + + return 0; +} + +struct pvr2_dvb_props pvr2_onair_creator_fe_props = { + .frontend_attach = pvr2_lgdt3303_attach, + .tuner_attach = pvr2_lgh06xf_attach, +}; +#endif + static const char *pvr2_client_onair_creator[] = { "saa7115", "tuner", @@ -165,6 +201,9 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, .default_std_mask = V4L2_STD_NTSC_M, +#ifdef CONFIG_VIDEO_PVRUSB2_DVB + .dvb_props = &pvr2_onair_creator_fe_props, +#endif }; #endif @@ -174,6 +213,37 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { /*------------------------------------------------------------------------*/ /* OnAir USB 2.0 */ +#ifdef CONFIG_VIDEO_PVRUSB2_DVB +static struct lgdt330x_config pvr2_lgdt3302_config = { + .demod_address = 0x0e, + .demod_chip = LGDT3302, +}; + +static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap) +{ + adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config, + &adap->channel.hdw->i2c_adap); + if (adap->fe) + return 0; + + return -EIO; +} + +static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap) +{ + dvb_attach(simple_tuner_attach, adap->fe, + &adap->channel.hdw->i2c_adap, 0x61, + TUNER_PHILIPS_FCV1236D); + + return 0; +} + +struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { + .frontend_attach = pvr2_lgdt3302_attach, + .tuner_attach = pvr2_fcv1236d_attach, +}; +#endif + static const char *pvr2_client_onair_usb2[] = { "saa7115", "tuner", @@ -192,6 +262,9 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, .default_std_mask = V4L2_STD_NTSC_M, +#ifdef CONFIG_VIDEO_PVRUSB2_DVB + .dvb_props = &pvr2_onair_usb2_fe_props, +#endif }; #endif From c881284151e35479ffee26a571b6e9769c351095 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 28 Mar 2008 05:48:44 -0300 Subject: [PATCH 429/452] V4L/DVB (7706): pvrusb2: create a separate pvr2_device_desc structure for 751xx models Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 6794862bbb19..9598f80ecd4d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -313,9 +313,27 @@ static const char *pvr2_fw1_names_75xxx[] = { "v4l-pvrusb2-73xxx-01.fw", }; -static const struct pvr2_device_desc pvr2_device_75xxx = { - .description = "WinTV PVR USB2 Model Category 75xxx", - .shortname = "75xxx", +static const struct pvr2_device_desc pvr2_device_750xx = { + .description = "WinTV PVR USB2 Model Category 750xx", + .shortname = "750xx", + .client_modules.lst = pvr2_client_75xxx, + .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), + .fx2_firmware.lst = pvr2_fw1_names_75xxx, + .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), + .flag_has_cx25840 = !0, + .flag_has_hauppauge_rom = !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, + .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, +}; + +static const struct pvr2_device_desc pvr2_device_751xx = { + .description = "WinTV PVR USB2 Model Category 751xx", + .shortname = "751xx", .client_modules.lst = pvr2_client_75xxx, .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), .fx2_firmware.lst = pvr2_fw1_names_75xxx, @@ -355,9 +373,9 @@ struct usb_device_id pvr2_device_table[] = { { USB_DEVICE(0x2040, 0x7300), .driver_info = (kernel_ulong_t)&pvr2_device_73xxx}, { USB_DEVICE(0x2040, 0x7500), - .driver_info = (kernel_ulong_t)&pvr2_device_75xxx}, + .driver_info = (kernel_ulong_t)&pvr2_device_750xx}, { USB_DEVICE(0x2040, 0x7501), - .driver_info = (kernel_ulong_t)&pvr2_device_75xxx}, + .driver_info = (kernel_ulong_t)&pvr2_device_751xx}, { } }; From 087886eb111fde9659d69c030ea618b3c242e39c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 28 Mar 2008 05:49:36 -0300 Subject: [PATCH 430/452] V4L/DVB (7707): pvrusb2-dvb: add atsc/qam support for Hauppauge pvrusb2 model 750xx Signed-off-by: Michael Krufky Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 9598f80ecd4d..64a29adcfd92 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -35,6 +35,9 @@ pvr2_device_desc structures. #ifdef CONFIG_VIDEO_PVRUSB2_DVB #include "pvrusb2-hdw-internal.h" #include "lgdt330x.h" +#include "s5h1409.h" +#include "tda18271.h" +#include "tda8290.h" #include "tuner-simple.h" #endif @@ -304,6 +307,60 @@ static const struct pvr2_device_desc pvr2_device_73xxx = { /*------------------------------------------------------------------------*/ /* Hauppauge PVR-USB2 Model 75xxx */ +#ifdef CONFIG_VIDEO_PVRUSB2_DVB +static struct s5h1409_config pvr2_s5h1409_config = { + .demod_address = 0x32 >> 1, + .output_mode = S5H1409_PARALLEL_OUTPUT, + .gpio = S5H1409_GPIO_OFF, + .qam_if = 4000, + .inversion = S5H1409_INVERSION_ON, + .status_mode = S5H1409_DEMODLOCKING, +}; + +static struct tda829x_config tda829x_no_probe = { + .probe_tuner = TDA829X_DONT_PROBE, +}; + +static struct tda18271_std_map hauppauge_tda18271_std_map = { + .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 = { + .std_map = &hauppauge_tda18271_std_map, + .gate = TDA18271_GATE_ANALOG, +}; + +static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap) +{ + adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config, + &adap->channel.hdw->i2c_adap); + if (adap->fe) + return 0; + + return -EIO; +} + +static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) +{ + dvb_attach(tda829x_attach, adap->fe, + &adap->channel.hdw->i2c_adap, 0x42, + &tda829x_no_probe); + dvb_attach(tda18271_attach, adap->fe, 0x60, + &adap->channel.hdw->i2c_adap, + &hauppauge_tda18271_config); + + return 0; +} + +struct pvr2_dvb_props pvr2_750xx_dvb_props = { + .frontend_attach = pvr2_s5h1409_attach, + .tuner_attach = pvr2_tda18271_8295_attach, +}; +#endif + static const char *pvr2_client_75xxx[] = { "cx25840", "tuner", @@ -329,6 +386,9 @@ static const struct pvr2_device_desc pvr2_device_750xx = { .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, .default_std_mask = V4L2_STD_NTSC_M, .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, +#ifdef CONFIG_VIDEO_PVRUSB2_DVB + .dvb_props = &pvr2_750xx_dvb_props, +#endif }; static const struct pvr2_device_desc pvr2_device_751xx = { From 07b80264c3ede47593e83189cce82b31100053f6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 30 Mar 2008 20:36:31 -0300 Subject: [PATCH 431/452] V4L/DVB (7708): pvrusb2-dvb: Fix stuck thread on streaming abort If the device fails to stream, the feed thread will block forever waiting for buffers. But while in this state it was not looking for an exit condition from the driver DVB interface. This caused the thread to jam. Implement a new stop flag (which will be set appropriately) to tell the thread to stop. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 10 ++++++++-- drivers/media/video/pvrusb2/pvrusb2-dvb.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 58ef5caba83a..d82fceae4689 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -41,6 +41,7 @@ static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) stream = adap->channel.stream->stream; for (;;) { + if (adap->feed_thread_stop) break; if (kthread_should_stop()) break; /* Not sure about this... */ @@ -70,10 +71,12 @@ static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) } - /* Wait until more buffers become available. */ + /* Wait until more buffers become available or we're + told not to wait any longer. */ ret = wait_event_interruptible( adap->buffer_wait_data, - pvr2_stream_get_ready_count(stream) > 0); + (pvr2_stream_get_ready_count(stream) > 0) || + adap->feed_thread_stop); if (ret < 0) break; } @@ -107,6 +110,8 @@ static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap) struct pvr2_stream *stream; if (adap->thread) { + adap->feed_thread_stop = !0; + pvr2_dvb_notify(adap); kthread_stop(adap->thread); adap->thread = NULL; } @@ -177,6 +182,7 @@ static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap) if (ret < 0) return ret; } + adap->feed_thread_stop = 0; adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb"); if (IS_ERR(adap->thread)) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h index 884ff916a352..2dd0d4ef22a2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h @@ -28,6 +28,7 @@ struct pvr2_dvb_adapter { unsigned int stream_run:1; wait_queue_head_t buffer_wait_data; + int feed_thread_stop; char *buffer_storage[PVR2_DVB_BUFFER_COUNT]; }; From 72998b71096e364002269a8cacc0524937d479c6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Thu, 3 Apr 2008 04:51:19 -0300 Subject: [PATCH 432/452] V4L/DVB (7709): pvrusb2: New device attribute for encoder usage in digital mode Some tuners seem to not work in digital mode unless the encoder is healthy. Implement a device attribute to represent this flag and modify the core state machines to enforce this requirement. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 2 ++ drivers/media/video/pvrusb2/pvrusb2-devattr.h | 7 ++++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 33 ++++++++++++++----- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 64a29adcfd92..74c92a470eb6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -201,6 +201,7 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, + .flag_digital_requires_cx23416 = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, .default_std_mask = V4L2_STD_NTSC_M, @@ -262,6 +263,7 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, + .flag_digital_requires_cx23416 = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, .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 38913519a818..c2e2b06fe2e0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -106,6 +106,13 @@ struct pvr2_device_desc { /* If set, we don't bother trying to load cx23416 firmware. */ int flag_skip_cx23416_firmware:1; + /* If set, the encoder must be healthy in order for digital mode to + work (otherwise we assume that digital streaming will work even + if we fail to locate firmware for the encoder). If the device + doesn't support digital streaming then this flag has no + effect. */ + int flag_digital_requires_cx23416:1; + /* Device has a hauppauge eeprom which we can interrogate. */ int flag_has_hauppauge_rom:1; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 195e974f5eb0..539fe17105e7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3502,7 +3502,12 @@ 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 (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) { + if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0; + } else 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); @@ -3687,14 +3692,19 @@ 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) { + int fl = !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; + fl = (hdw->state_encoder_ok && + hdw->state_encoder_run); + } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) && + (hdw->hdw_desc->flag_digital_requires_cx23416)) { + fl = hdw->state_encoder_ok; + } + if (fl && + 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; @@ -3705,6 +3715,9 @@ static int state_eval_usbstream_run(struct pvr2_hdw *hdw) if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { if (!hdw->state_encoder_ok || !hdw->state_encoder_run) return 0; + } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) && + (hdw->hdw_desc->flag_digital_requires_cx23416)) { + if (!hdw->state_encoder_ok) return 0; } if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0; hdw->state_usbstream_run = !0; @@ -3943,7 +3956,9 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw) st = PVR2_STATE_DEAD; } else if (hdw->fw1_state != FW1_STATE_OK) { st = PVR2_STATE_COLD; - } else if (analog_mode && !hdw->state_encoder_ok) { + } else if ((analog_mode || + hdw->hdw_desc->flag_digital_requires_cx23416) && + !hdw->state_encoder_ok) { st = PVR2_STATE_WARM; } else if (hdw->flag_tripped || (analog_mode && hdw->flag_decoder_missed)) { From d913d6303072ca194919d851e6743ad8c3a7563d Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 6 Apr 2008 04:04:35 -0300 Subject: [PATCH 433/452] V4L/DVB (7710): pvrusb2: Implement critical digital streaming quirk for onair devices Implement timed measurement of encoder operation for the first time it is run. This allows the driver to note when the encoder has been run successfully for at least 1/4 second. On top of that implement various bits to ensure that the encoder has been run once before digital streaming for OnAir devices. This is done via several core state machine tweaks. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-encoder.c | 9 ++ .../video/pvrusb2/pvrusb2-hdw-internal.h | 4 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 150 +++++++++++++++++- 3 files changed, 156 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 324d1bd8500d..c46d367f7472 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -278,11 +278,20 @@ static int pvr2_encoder_cmd(void *ctxt, ret = -EBUSY; } if (ret) { + del_timer_sync(&hdw->encoder_run_timer); hdw->state_encoder_ok = 0; pvr2_trace(PVR2_TRACE_STBITS, "State bit %s <-- %s", "state_encoder_ok", (hdw->state_encoder_ok ? "true" : "false")); + if (hdw->state_encoder_runok) { + hdw->state_encoder_runok = 0; + pvr2_trace(PVR2_TRACE_STBITS, + "State bit %s <-- %s", + "state_encoder_runok", + (hdw->state_encoder_runok ? + "true" : "false")); + } pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Giving up on command." diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index c725495826ce..a67dcf84b596 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -238,6 +238,7 @@ struct pvr2_hdw { int state_encoder_run; /* Encoder is running */ int state_encoder_config; /* Encoder is configured */ int state_encoder_waitok; /* Encoder pre-wait done */ + int state_encoder_runok; /* Encoder has run for >= .25 sec */ int state_decoder_run; /* Decoder is running */ int state_usbstream_run; /* FX2 is streaming */ int state_decoder_quiescent; /* Decoder idle for > 50msec */ @@ -267,6 +268,9 @@ struct pvr2_hdw { /* Timer for measuring encoder pre-wait time */ struct timer_list encoder_wait_timer; + /* Timer for measuring encoder minimum run time */ + struct timer_list encoder_run_timer; + /* Place to block while waiting for state changes */ wait_queue_head_t state_wait_data; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 539fe17105e7..4f6bb58ca5fc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -264,6 +264,7 @@ static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); static void pvr2_hdw_quiescent_timeout(unsigned long); static void pvr2_hdw_encoder_wait_timeout(unsigned long); +static void pvr2_hdw_encoder_run_timeout(unsigned long); static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32); static int pvr2_send_request_ex(struct pvr2_hdw *hdw, unsigned int timeout,int probe_fl, @@ -1236,6 +1237,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) time we configure the encoder, then we'll fully configure it. */ hdw->enc_cur_valid = 0; + /* Encoder is about to be reset so note that as far as we're + concerned now, the encoder has never been run. */ + del_timer_sync(&hdw->encoder_run_timer); + if (hdw->state_encoder_runok) { + hdw->state_encoder_runok = 0; + trace_stbit("state_encoder_runok",hdw->state_encoder_runok); + } + /* First prepare firmware loading */ ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/ ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/ @@ -1882,6 +1891,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->encoder_wait_timer.data = (unsigned long)hdw; hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout; + init_timer(&hdw->encoder_run_timer); + hdw->encoder_run_timer.data = (unsigned long)hdw; + hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout; + hdw->master_state = PVR2_STATE_DEAD; init_waitqueue_head(&hdw->state_wait_data); @@ -2082,6 +2095,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, fail: if (hdw) { del_timer_sync(&hdw->quiescent_timer); + del_timer_sync(&hdw->encoder_run_timer); del_timer_sync(&hdw->encoder_wait_timer); if (hdw->workqueue) { flush_workqueue(hdw->workqueue); @@ -2144,6 +2158,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) hdw->workqueue = NULL; } del_timer_sync(&hdw->quiescent_timer); + del_timer_sync(&hdw->encoder_run_timer); del_timer_sync(&hdw->encoder_wait_timer); if (hdw->fw_buffer) { kfree(hdw->fw_buffer); @@ -3584,23 +3599,116 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw) } +/* Return true if the encoder should not be running. */ +static int state_check_disable_encoder_run(struct pvr2_hdw *hdw) +{ + if (!hdw->state_encoder_ok) { + /* Encoder isn't healthy at the moment, so stop it. */ + return !0; + } + if (!hdw->state_pathway_ok) { + /* Mode is not understood at the moment (i.e. it wants to + change), so encoder must be stopped. */ + return !0; + } + + switch (hdw->pathway_state) { + case PVR2_PATHWAY_ANALOG: + if (!hdw->state_decoder_run) { + /* We're in analog mode and the decoder is not + running; thus the encoder should be stopped as + well. */ + return !0; + } + break; + case PVR2_PATHWAY_DIGITAL: + if (hdw->state_encoder_runok) { + /* This is a funny case. We're in digital mode so + really the encoder should be stopped. However + if it really is running, only kill it after + runok has been set. This gives a chance for the + onair quirk to function (encoder must run + briefly first, at least once, before onair + digital streaming can work). */ + return !0; + } + break; + default: + /* Unknown mode; so encoder should be stopped. */ + return !0; + } + + /* If we get here, we haven't found a reason to stop the + encoder. */ + return 0; +} + + +/* Return true if the encoder should be running. */ +static int state_check_enable_encoder_run(struct pvr2_hdw *hdw) +{ + if (!hdw->state_encoder_ok) { + /* Don't run the encoder if it isn't healthy... */ + return 0; + } + if (!hdw->state_pathway_ok) { + /* Don't run the encoder if we don't (yet) know what mode + we need to be in... */ + return 0; + } + + switch (hdw->pathway_state) { + case PVR2_PATHWAY_ANALOG: + if (hdw->state_decoder_run) { + /* In analog mode, if the decoder is running, then + run the encoder. */ + return !0; + } + break; + case PVR2_PATHWAY_DIGITAL: + if ((hdw->hdw_desc->digital_control_scheme == + PVR2_DIGITAL_SCHEME_ONAIR) && + !hdw->state_encoder_runok) { + /* This is a quirk. OnAir hardware won't stream + digital until the encoder has been run at least + once, for a minimal period of time (empiricially + measured to be 1/4 second). So if we're on + OnAir hardware and the encoder has never been + run at all, then start the encoder. Normal + state machine logic in the driver will + automatically handle the remaining bits. */ + return !0; + } + break; + default: + /* For completeness (unknown mode; encoder won't run ever) */ + break; + } + /* If we get here, then we haven't found any reason to run the + encoder, so don't run it. */ + return 0; +} + + /* Evaluate whether or not state_encoder_run can change */ static int state_eval_encoder_run(struct pvr2_hdw *hdw) { if (hdw->state_encoder_run) { + if (!state_check_disable_encoder_run(hdw)) return 0; if (hdw->state_encoder_ok) { - if (hdw->state_decoder_run && - hdw->state_pathway_ok) return 0; + del_timer_sync(&hdw->encoder_run_timer); 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 (!state_check_enable_encoder_run(hdw)) return 0; if (pvr2_encoder_start(hdw) < 0) return !0; hdw->state_encoder_run = !0; + if (!hdw->state_encoder_runok) { + hdw->encoder_run_timer.expires = + jiffies + (HZ*250/1000); + add_timer(&hdw->encoder_run_timer); + } } trace_stbit("state_encoder_run",hdw->state_encoder_run); return !0; @@ -3629,6 +3737,19 @@ static void pvr2_hdw_encoder_wait_timeout(unsigned long data) } +/* Timeout function for encoder run timer. */ +static void pvr2_hdw_encoder_run_timeout(unsigned long data) +{ + struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; + if (!hdw->state_encoder_runok) { + hdw->state_encoder_runok = !0; + trace_stbit("state_encoder_runok",hdw->state_encoder_runok); + hdw->state_stale = !0; + queue_work(hdw->workqueue,&hdw->workpoll); + } +} + + /* Evaluate whether or not state_decoder_run can change */ static int state_eval_decoder_run(struct pvr2_hdw *hdw) { @@ -3718,6 +3839,16 @@ static int state_eval_usbstream_run(struct pvr2_hdw *hdw) } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) && (hdw->hdw_desc->flag_digital_requires_cx23416)) { if (!hdw->state_encoder_ok) return 0; + if (hdw->state_encoder_run) return 0; + if (hdw->hdw_desc->digital_control_scheme == + PVR2_DIGITAL_SCHEME_ONAIR) { + /* OnAir digital receivers won't stream + unless the analog encoder has run first. + Why? I have no idea. But don't even + try until we know the analog side is + known to have run. */ + if (!hdw->state_encoder_runok) return 0; + } } if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0; hdw->state_usbstream_run = !0; @@ -3861,7 +3992,12 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, (hdw->state_encoder_ok ? "" : " "), (hdw->state_encoder_run ? - " " : " "), + (hdw->state_encoder_runok ? + " " : + " ") : + (hdw->state_encoder_runok ? + " " : + " ")), (hdw->state_encoder_config ? " " : (hdw->state_encoder_waitok ? From e5be15c63804e05b5a94197524023702a259e308 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 7 Apr 2008 02:22:04 -0300 Subject: [PATCH 434/452] V4L/DVB (7711): pvrusb2: Fix race on module unload The pvrusb2 driver - for basically forever - was not enforcing a proper module tear-down. Kernel threads are used inside the driver and all must be gone before the module can be safely removed. This changeset reimplements a chunk of pvrusb2-context.c to enforce this correctly. Unfortunately this is not a simple fix. The new implementation also cuts back on kernel thread usage; instead of there being 1 control thread per instance now it's just 1 control thread shared by all instances. (By dropping to a single thread then the module exit function can block on its shutdown and the thread itself can monitor and cleanly shut down all of the other instances first.) Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-context.c | 204 +++++++++++++----- drivers/media/video/pvrusb2/pvrusb2-context.h | 9 +- drivers/media/video/pvrusb2/pvrusb2-main.c | 12 ++ 3 files changed, 174 insertions(+), 51 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index 22bd8302c4aa..e7a2ed58bde2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -23,100 +23,206 @@ #include "pvrusb2-ioread.h" #include "pvrusb2-hdw.h" #include "pvrusb2-debug.h" +#include #include #include #include #include +static struct pvr2_context *pvr2_context_exist_first; +static struct pvr2_context *pvr2_context_exist_last; +static struct pvr2_context *pvr2_context_notify_first; +static struct pvr2_context *pvr2_context_notify_last; +static DEFINE_MUTEX(pvr2_context_mutex); +static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data); +static struct task_struct *pvr2_context_thread_ptr; + + +static void pvr2_context_set_notify(struct pvr2_context *mp, int fl) +{ + int signal_flag = 0; + mutex_lock(&pvr2_context_mutex); + if (fl) { + if (!mp->notify_flag) { + signal_flag = (pvr2_context_notify_first == NULL); + mp->notify_prev = pvr2_context_notify_last; + mp->notify_next = NULL; + pvr2_context_notify_last = mp; + if (mp->notify_prev) { + mp->notify_prev->notify_next = mp; + } else { + pvr2_context_notify_first = mp; + } + mp->notify_flag = !0; + } + } else { + if (mp->notify_flag) { + mp->notify_flag = 0; + if (mp->notify_next) { + mp->notify_next->notify_prev = mp->notify_prev; + } else { + pvr2_context_notify_last = mp->notify_prev; + } + if (mp->notify_prev) { + mp->notify_prev->notify_next = mp->notify_next; + } else { + pvr2_context_notify_first = mp->notify_next; + } + } + } + mutex_unlock(&pvr2_context_mutex); + if (signal_flag) wake_up(&pvr2_context_sync_data); +} + static void pvr2_context_destroy(struct pvr2_context *mp) { pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp); if (mp->hdw) pvr2_hdw_destroy(mp->hdw); + pvr2_context_set_notify(mp, 0); + mutex_lock(&pvr2_context_mutex); + if (mp->exist_next) { + mp->exist_next->exist_prev = mp->exist_prev; + } else { + pvr2_context_exist_last = mp->exist_prev; + } + if (mp->exist_prev) { + mp->exist_prev->exist_next = mp->exist_next; + } else { + pvr2_context_exist_first = mp->exist_next; + } + if (!pvr2_context_exist_first) { + /* Trigger wakeup on control thread in case it is waiting + for an exit condition. */ + wake_up(&pvr2_context_sync_data); + } + mutex_unlock(&pvr2_context_mutex); kfree(mp); } static void pvr2_context_notify(struct pvr2_context *mp) { - mp->notify_flag = !0; - wake_up(&mp->wait_data); + pvr2_context_set_notify(mp,!0); } -static int pvr2_context_thread(void *_mp) +static void pvr2_context_check(struct pvr2_context *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 { + struct pvr2_channel *ch1, *ch2; + pvr2_trace(PVR2_TRACE_CTXT, + "pvr2_context %p (notify)", mp); + if (!mp->initialized_flag && !mp->disconnect_flag) { + mp->initialized_flag = !0; 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 %p (initialize)", 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 continue anyway. We need + to do this in order to await the expected + disconnect (which we will detect in the normal + course of operation). */ + } } - /* 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); - } - } - wait_event_interruptible(mp->wait_data, mp->notify_flag); + for (ch1 = mp->mc_first; ch1; ch1 = ch2) { + ch2 = ch1->mc_next; + if (ch1->check_func) ch1->check_func(ch1); } - pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread end)",mp); - pvr2_context_destroy(mp); + + if (mp->disconnect_flag && !mp->mc_first) { + /* Go away... */ + pvr2_context_destroy(mp); + return; + } +} + + +static int pvr2_context_shutok(void) +{ + return kthread_should_stop() && (pvr2_context_exist_first == NULL); +} + + +static int pvr2_context_thread_func(void *foo) +{ + struct pvr2_context *mp; + + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start"); + + do { + while ((mp = pvr2_context_notify_first) != NULL) { + pvr2_context_set_notify(mp, 0); + pvr2_context_check(mp); + } + wait_event_interruptible( + pvr2_context_sync_data, + ((pvr2_context_notify_first != NULL) || + pvr2_context_shutok())); + } while (!pvr2_context_shutok()); + + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end"); + return 0; } +int pvr2_context_global_init(void) +{ + pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func, + 0, + "pvrusb2-context"); + return (pvr2_context_thread_ptr ? 0 : -ENOMEM); +} + + +void pvr2_context_global_done(void) +{ + kthread_stop(pvr2_context_thread_ptr); +} + + struct pvr2_context *pvr2_context_create( struct usb_interface *intf, 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_CTXT,"pvr2_context %p (create)",mp); - init_waitqueue_head(&mp->wait_data); mp->setup_func = setup_func; mutex_init(&mp->mutex); + mutex_lock(&pvr2_context_mutex); + mp->exist_prev = pvr2_context_exist_last; + mp->exist_next = NULL; + pvr2_context_exist_last = mp; + if (mp->exist_prev) { + mp->exist_prev->exist_next = mp; + } else { + pvr2_context_exist_first = mp; + } + mutex_unlock(&pvr2_context_mutex); mp->hdw = pvr2_hdw_create(intf,devid); if (!mp->hdw) { pvr2_context_destroy(mp); mp = NULL; goto done; } - thread = kthread_run(pvr2_context_thread, mp, "pvrusb2-context"); - if (!thread) { - pvr2_context_destroy(mp); - mp = NULL; - goto done; - } + pvr2_context_set_notify(mp, !0); done: return mp; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h index 127ec53e0913..6fb6ab022851 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.h +++ b/drivers/media/video/pvrusb2/pvrusb2-context.h @@ -40,14 +40,17 @@ struct pvr2_context_stream { struct pvr2_context { struct pvr2_channel *mc_first; struct pvr2_channel *mc_last; + struct pvr2_context *exist_next; + struct pvr2_context *exist_prev; + struct pvr2_context *notify_next; + struct pvr2_context *notify_prev; struct pvr2_hdw *hdw; struct pvr2_context_stream video_stream; struct mutex mutex; int notify_flag; + int initialized_flag; int disconnect_flag; - wait_queue_head_t wait_data; - /* Called after pvr2_context initialization is complete */ void (*setup_func)(struct pvr2_context *); @@ -74,6 +77,8 @@ int pvr2_channel_claim_stream(struct pvr2_channel *, struct pvr2_ioread *pvr2_channel_create_mpeg_stream( struct pvr2_context_stream *); +int pvr2_context_global_init(void); +void pvr2_context_global_done(void); #endif /* __PVRUSB2_CONTEXT_H */ /* diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index 54d9f168d7ad..332aced8a5a1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -125,6 +125,12 @@ static int __init pvr_init(void) pvr2_trace(PVR2_TRACE_INIT,"pvr_init"); + ret = pvr2_context_global_init(); + if (ret != 0) { + pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret); + return ret; + } + #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS class_ptr = pvr2_sysfs_class_create(); #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ @@ -136,6 +142,8 @@ static int __init pvr_init(void) if (pvrusb2_debug) info("Debug mask is %d (0x%x)", pvrusb2_debug,pvrusb2_debug); + pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); + return ret; } @@ -148,6 +156,10 @@ static void __exit pvr_exit(void) #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS pvr2_sysfs_class_destroy(class_ptr); #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ + + pvr2_context_global_done(); + + pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete"); } module_init(pvr_init); From 97f26ff6049a7fff5460cebe392ad1d699dc434c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 7 Apr 2008 02:22:43 -0300 Subject: [PATCH 435/452] V4L/DVB (7712): pvrusb2: Close connect/disconnect race If a disconnect happens before initialization is completed, the pvrusb2 driver can accidentally touch dangling pointers. The whole initialization function must be protected by the big_lock, and once inside that lock, the initialization function should abort if it is discovered that a disconnect has already taken place. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 4f6bb58ca5fc..f907a56c587d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1854,10 +1854,19 @@ int pvr2_hdw_initialize(struct pvr2_hdw *hdw, void *callback_data) { LOCK_TAKE(hdw->big_lock); do { + if (hdw->flag_disconnected) { + /* Handle a race here: If we're already + disconnected by this point, then give up. If we + get past this then we'll remain connected for + the duration of initialization since the entire + initialization sequence is now protected by the + big_lock. */ + break; + } hdw->state_data = callback_data; hdw->state_func = callback_func; + pvr2_hdw_setup(hdw); } while (0); LOCK_GIVE(hdw->big_lock); - pvr2_hdw_setup(hdw); return hdw->flag_init_ok; } From 13e027a8bf2a507334fa0d30246ce619ff581cbb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 7 Apr 2008 02:57:13 -0300 Subject: [PATCH 436/452] V4L/DVB (7713): pvrusb2: Implement cleaner DVB kernel thread shutdown Earlier fix to handle DVB feed thread aborts was overly-aggressive. We can take better advantage of what kthread_stop() can do. This change simplifies things. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 6 +----- drivers/media/video/pvrusb2/pvrusb2-dvb.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index d82fceae4689..c20eef0f077e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -41,7 +41,6 @@ static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) stream = adap->channel.stream->stream; for (;;) { - if (adap->feed_thread_stop) break; if (kthread_should_stop()) break; /* Not sure about this... */ @@ -76,7 +75,7 @@ static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) ret = wait_event_interruptible( adap->buffer_wait_data, (pvr2_stream_get_ready_count(stream) > 0) || - adap->feed_thread_stop); + kthread_should_stop()); if (ret < 0) break; } @@ -110,8 +109,6 @@ static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap) struct pvr2_stream *stream; if (adap->thread) { - adap->feed_thread_stop = !0; - pvr2_dvb_notify(adap); kthread_stop(adap->thread); adap->thread = NULL; } @@ -182,7 +179,6 @@ static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap) if (ret < 0) return ret; } - adap->feed_thread_stop = 0; adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb"); if (IS_ERR(adap->thread)) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h index 2dd0d4ef22a2..884ff916a352 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h @@ -28,7 +28,6 @@ struct pvr2_dvb_adapter { unsigned int stream_run:1; wait_queue_head_t buffer_wait_data; - int feed_thread_stop; char *buffer_storage[PVR2_DVB_BUFFER_COUNT]; }; From 18ecbb4771eb0ecf297e996966b3c42f69cd6c02 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 9 Apr 2008 05:14:11 -0300 Subject: [PATCH 437/452] V4L/DVB (7714): pvrusb2: Fix hang on module removal The pvrusb2 driver was getting had by this scenario: 1. Task A calls kthread_stop() for task B. 2. Before exiting, then Task B calls kthread_stop() for task C. The problem is, kthread_stop() wants to allocate an internal resource to itself (i.e. acquire a lock), which won't be released until kthread_stop() returns. But kthread_stop() won't return until task B is dead. But task B won't die until it finishes its call to kthread_stop() for task C, and that will block waiting on the resource already allocated inside task A. Deadlock. With the pvrusb2 driver, task A is the caller to pvr_exit(), task B is the control thread run inside of pvrusb2-context.c, and task C is any worker thread run inside of pvrusb2-hdw.c. This problem got introduced by the previous threading setup change, which was itself an attempt to fix a module tear-down race (which it actually did fix). The lesson here is that a task being waited on as part of a kthread_stop() simply cannot be allow to also issue a kthread_stop() - or we make sure not to issue the enclosing kthread_stop() until we know that the inner kthread_stop() has completed first. The solution for the pvrusb2 driver is some hackish code which changes the main control thread tear down into a two step process. This then makes it possible to delay issuing the kthread_stop() on the control thread until after we know that everything has been torn down first. (And yes, we really need that kthread_stop() because it's the only way to safely guarantee that a module-referencing kernel thread has safely returned back out of the module before we finally remove the module.) Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-context.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index e7a2ed58bde2..a2ce022c515a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -35,6 +35,9 @@ static struct pvr2_context *pvr2_context_notify_first; static struct pvr2_context *pvr2_context_notify_last; static DEFINE_MUTEX(pvr2_context_mutex); static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data); +static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data); +static int pvr2_context_cleanup_flag; +static int pvr2_context_cleaned_flag; static struct task_struct *pvr2_context_thread_ptr; @@ -153,7 +156,7 @@ static void pvr2_context_check(struct pvr2_context *mp) static int pvr2_context_shutok(void) { - return kthread_should_stop() && (pvr2_context_exist_first == NULL); + return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL); } @@ -174,6 +177,15 @@ static int pvr2_context_thread_func(void *foo) pvr2_context_shutok())); } while (!pvr2_context_shutok()); + pvr2_context_cleaned_flag = !0; + wake_up(&pvr2_context_cleanup_data); + + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up"); + + wait_event_interruptible( + pvr2_context_sync_data, + kthread_should_stop()); + pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end"); return 0; @@ -191,6 +203,11 @@ int pvr2_context_global_init(void) void pvr2_context_global_done(void) { + pvr2_context_cleanup_flag = !0; + wake_up(&pvr2_context_sync_data); + wait_event_interruptible( + pvr2_context_cleanup_data, + pvr2_context_cleaned_flag); kthread_stop(pvr2_context_thread_ptr); } From 49844c291a02a8630215f779fa44b3198d0a4f5b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 9 Apr 2008 05:44:57 -0300 Subject: [PATCH 438/452] V4L/DVB (7715): pvrusb2: Clean out all use of __FUNCTION__ Apparently the kernel developers no longer consider it proper etiquette to use __FUNCTION__; everyone must instead use __func__ (even though it breaks with older compilers). And worse still, actual effort is being expended to sweep this change throughout the kernel source tree. Don't these people have better things to do? So... Completely clean out all use of __FUNCTION__ from the pvrusb2 driver (it was just in the sysfs interface). I'm not going to use __func__ either. So there. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 49 ++++++++++++--------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 78ecfcbdd0b9..0ff7a836a8a2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -608,8 +608,9 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); if (ret) { - printk(KERN_WARNING "%s: sysfs_create_group error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "sysfs_create_group error: %d", + ret); return; } cip->created_ok = !0; @@ -640,15 +641,17 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) sfp->debugifc = dip; ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd); if (ret < 0) { - printk(KERN_WARNING "%s: device_create_file error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_create_file error: %d", + ret); } else { dip->debugcmd_created_ok = !0; } ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo); if (ret < 0) { - printk(KERN_WARNING "%s: device_create_file error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_create_file error: %d", + ret); } else { dip->debuginfo_created_ok = !0; } @@ -851,8 +854,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp, class_dev->driver_data = sfp; ret = device_register(class_dev); if (ret) { - printk(KERN_ERR "%s: device_register failed\n", - __FUNCTION__); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_register failed"); kfree(class_dev); return; } @@ -864,8 +867,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp, ret = device_create_file(sfp->class_dev, &sfp->attr_v4l_minor_number); if (ret < 0) { - printk(KERN_WARNING "%s: device_create_file error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_create_file error: %d", + ret); } else { sfp->v4l_minor_number_created_ok = !0; } @@ -877,8 +881,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp, ret = device_create_file(sfp->class_dev, &sfp->attr_v4l_radio_minor_number); if (ret < 0) { - printk(KERN_WARNING "%s: device_create_file error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_create_file error: %d", + ret); } else { sfp->v4l_radio_minor_number_created_ok = !0; } @@ -889,8 +894,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->attr_unit_number.store = NULL; ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number); if (ret < 0) { - printk(KERN_WARNING "%s: device_create_file error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_create_file error: %d", + ret); } else { sfp->unit_number_created_ok = !0; } @@ -902,8 +908,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp, ret = device_create_file(sfp->class_dev, &sfp->attr_bus_info); if (ret < 0) { - printk(KERN_WARNING "%s: device_create_file error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_create_file error: %d", + ret); } else { sfp->bus_info_created_ok = !0; } @@ -915,8 +922,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp, ret = device_create_file(sfp->class_dev, &sfp->attr_hdw_name); if (ret < 0) { - printk(KERN_WARNING "%s: device_create_file error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_create_file error: %d", + ret); } else { sfp->hdw_name_created_ok = !0; } @@ -928,8 +936,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp, ret = device_create_file(sfp->class_dev, &sfp->attr_hdw_desc); if (ret < 0) { - printk(KERN_WARNING "%s: device_create_file error: %d\n", - __FUNCTION__, ret); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "device_create_file error: %d", + ret); } else { sfp->hdw_desc_created_ok = !0; } From f55a871241899ea2ecc85670d7c9a83e4de29637 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 18 Apr 2008 05:38:56 -0300 Subject: [PATCH 439/452] V4L/DVB (7716): pvrusb2: clean up global functions This patch contains the following cleanups: - make the following needlessly global function static: - pvr2_hdw_set_cur_freq() - #if 0 the following unused global functions: - pvr2_hdw_get_state_name() - pvr2_hdw_get_debug_info_unlocked() - pvr2_hdw_get_debug_info_locked() Signed-off-by: Adrian Bunk Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 48 +---------------------- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 3 -- 2 files changed, 1 insertion(+), 50 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f907a56c587d..63d0af759ed8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1024,7 +1024,7 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw) /* Set the currently tuned frequency and account for all possible driver-core side effects of this action. */ -void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val) +static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val) { if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { if (hdw->freqSelector) { @@ -1405,11 +1405,6 @@ int pvr2_hdw_untrip(struct pvr2_hdw *hdw) } -const char *pvr2_hdw_get_state_name(unsigned int id) -{ - if (id >= ARRAY_SIZE(pvr2_state_names)) return NULL; - return pvr2_state_names[id]; -} int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw) @@ -4150,47 +4145,6 @@ static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw) } -void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw, - struct pvr2_hdw_debug_info *ptr) -{ - ptr->big_lock_held = hdw->big_lock_held; - ptr->ctl_lock_held = hdw->ctl_lock_held; - ptr->flag_disconnected = hdw->flag_disconnected; - ptr->flag_init_ok = hdw->flag_init_ok; - ptr->flag_ok = hdw->flag_ok; - ptr->fw1_state = hdw->fw1_state; - ptr->flag_decoder_missed = hdw->flag_decoder_missed; - ptr->flag_tripped = hdw->flag_tripped; - ptr->state_encoder_ok = hdw->state_encoder_ok; - ptr->state_encoder_run = hdw->state_encoder_run; - ptr->state_decoder_run = hdw->state_decoder_run; - ptr->state_usbstream_run = hdw->state_usbstream_run; - ptr->state_decoder_quiescent = hdw->state_decoder_quiescent; - ptr->state_pipeline_config = hdw->state_pipeline_config; - ptr->state_pipeline_req = hdw->state_pipeline_req; - ptr->state_pipeline_pause = hdw->state_pipeline_pause; - ptr->state_pipeline_idle = hdw->state_pipeline_idle; - ptr->cmd_debug_state = hdw->cmd_debug_state; - ptr->cmd_code = hdw->cmd_debug_code; - ptr->cmd_debug_write_len = hdw->cmd_debug_write_len; - ptr->cmd_debug_read_len = hdw->cmd_debug_read_len; - ptr->cmd_debug_timeout = hdw->ctl_timeout_flag; - ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag; - ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag; - ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status; - ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status; -} - - -void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw, - struct pvr2_hdw_debug_info *ptr) -{ - LOCK_TAKE(hdw->ctl_lock); do { - pvr2_hdw_get_debug_info_unlocked(hdw,ptr); - } while(0); LOCK_GIVE(hdw->ctl_lock); -} - - int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp) { return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index a868e52a73a3..74c2503f8e3f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -91,9 +91,6 @@ enum pvr2_v4l_type { /* Translate configuration enum to a string label */ const char *pvr2_config_get_name(enum pvr2_config); -/* Translate a master state enum to a string label */ -const char *pvr2_hdw_get_state_name(unsigned int); - struct pvr2_hdw; /* Create and return a structure for interacting with the underlying From 95814bc2b792dced5296a710704de7d5ecec2776 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 19 Apr 2008 15:36:51 -0300 Subject: [PATCH 440/452] V4L/DVB (7717): pvrusb2-dvb: add DVB-T support for Hauppauge pvrusb2 model 73xxx Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 74c92a470eb6..43c49fb66209 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -36,6 +36,7 @@ pvr2_device_desc structures. #include "pvrusb2-hdw-internal.h" #include "lgdt330x.h" #include "s5h1409.h" +#include "tda10048.h" #include "tda18271.h" #include "tda8290.h" #include "tuner-simple.h" @@ -278,6 +279,50 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { /*------------------------------------------------------------------------*/ /* Hauppauge PVR-USB2 Model 73xxx */ +#ifdef CONFIG_VIDEO_PVRUSB2_DVB +static struct tda10048_config hauppauge_tda10048_config = { + .demod_address = 0x10 >> 1, + .output_mode = TDA10048_PARALLEL_OUTPUT, + .fwbulkwritelen = TDA10048_BULKWRITE_50, + .inversion = TDA10048_INVERSION_ON, +}; + +static struct tda829x_config tda829x_no_probe = { + .probe_tuner = TDA829X_DONT_PROBE, +}; + +static struct tda18271_config hauppauge_tda18271_dvb_config = { + .gate = TDA18271_GATE_ANALOG, +}; + +static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap) +{ + adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config, + &adap->channel.hdw->i2c_adap); + if (adap->fe) + return 0; + + return -EIO; +} + +static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) +{ + dvb_attach(tda829x_attach, adap->fe, + &adap->channel.hdw->i2c_adap, 0x42, + &tda829x_no_probe); + dvb_attach(tda18271_attach, adap->fe, 0x60, + &adap->channel.hdw->i2c_adap, + &hauppauge_tda18271_dvb_config); + + return 0; +} + +struct pvr2_dvb_props pvr2_73xxx_dvb_props = { + .frontend_attach = pvr2_tda10048_attach, + .tuner_attach = pvr2_73xxx_tda18271_8295_attach, +}; +#endif + static const char *pvr2_client_73xxx[] = { "cx25840", "tuner", @@ -302,6 +347,9 @@ static const struct pvr2_device_desc pvr2_device_73xxx = { .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, +#ifdef CONFIG_VIDEO_PVRUSB2_DVB + .dvb_props = &pvr2_73xxx_dvb_props, +#endif }; @@ -319,10 +367,6 @@ static struct s5h1409_config pvr2_s5h1409_config = { .status_mode = S5H1409_DEMODLOCKING, }; -static struct tda829x_config tda829x_no_probe = { - .probe_tuner = TDA829X_DONT_PROBE, -}; - static struct tda18271_std_map hauppauge_tda18271_std_map = { .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3, .if_lvl = 6, .rfagc_top = 0x37, }, From d3f8d8fb304a8b9a81eae16ff7b50f5379f2437e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 20 Apr 2008 02:42:55 -0300 Subject: [PATCH 441/452] V4L/DVB (7718): pvrusb2-dvb: update Kbuild selections These changes are required with the addition of digital television support for the Hauppauge HVR1900 & HVR1950, the OnAir Creator and Sasem USB HDTV Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 546c3289dc13..a8da90f69dd9 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -62,6 +62,12 @@ config VIDEO_PVRUSB2_DVB bool "pvrusb2 DVB support (EXPERIMENTAL)" default n depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL + select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_S5H1409 if !DVB_FE_CUSTOMISE + select DVB_TDA10048 if !DVB_FE_CUSTOMIZE + select DVB_TDA18271 if !DVB_FE_CUSTOMIZE + select TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE ---help--- This option enables compilation of a DVB interface for the From 1cb03b76d09d20accfa5c1664c16ba6566f539a0 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 21 Apr 2008 03:47:43 -0300 Subject: [PATCH 442/452] V4L/DVB (7719): pvrusb2: Implement input selection enforcement In the pvrusb2 driver, different interfaces (e.g. V4L, DVB) have Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-context.c | 69 +++++++++ drivers/media/video/pvrusb2/pvrusb2-context.h | 3 + drivers/media/video/pvrusb2/pvrusb2-dvb.c | 47 +++---- .../video/pvrusb2/pvrusb2-hdw-internal.h | 4 +- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 132 +++++++++++++++--- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 13 ++ drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 52 ++++--- 7 files changed, 246 insertions(+), 74 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index a2ce022c515a..b5db6a5bab31 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -245,6 +245,22 @@ struct pvr2_context *pvr2_context_create( } +static void pvr2_context_reset_input_limits(struct pvr2_context *mp) +{ + unsigned int tmsk,mmsk; + struct pvr2_channel *cp; + struct pvr2_hdw *hdw = mp->hdw; + mmsk = pvr2_hdw_get_input_available(hdw); + tmsk = mmsk; + for (cp = mp->mc_first; cp; cp = cp->mc_next) { + if (!cp->input_mask) continue; + tmsk &= cp->input_mask; + } + pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk); + pvr2_hdw_commit_ctl(hdw); +} + + static void pvr2_context_enter(struct pvr2_context *mp) { mutex_lock(&mp->mutex); @@ -300,7 +316,9 @@ void pvr2_channel_done(struct pvr2_channel *cp) { struct pvr2_context *mp = cp->mc_head; pvr2_context_enter(mp); + cp->input_mask = 0; pvr2_channel_disclaim_stream(cp); + pvr2_context_reset_input_limits(mp); if (cp->mc_next) { cp->mc_next->mc_prev = cp->mc_prev; } else { @@ -316,6 +334,57 @@ void pvr2_channel_done(struct pvr2_channel *cp) } +int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk) +{ + unsigned int tmsk,mmsk; + int ret = 0; + struct pvr2_channel *p2; + struct pvr2_hdw *hdw = cp->hdw; + + mmsk = pvr2_hdw_get_input_available(hdw); + cmsk &= mmsk; + if (cmsk == cp->input_mask) { + /* No change; nothing to do */ + return 0; + } + + pvr2_context_enter(cp->mc_head); + do { + if (!cmsk) { + cp->input_mask = 0; + pvr2_context_reset_input_limits(cp->mc_head); + break; + } + tmsk = mmsk; + for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) { + if (p2 == cp) continue; + if (!p2->input_mask) continue; + tmsk &= p2->input_mask; + } + if (!(tmsk & cmsk)) { + ret = -EPERM; + break; + } + tmsk &= cmsk; + if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) { + /* Internal failure changing allowed list; probably + should not happen, but react if it does. */ + break; + } + cp->input_mask = cmsk; + pvr2_hdw_commit_ctl(hdw); + } while (0); + pvr2_context_exit(cp->mc_head); + return ret; +} + + +unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp) +{ + return cp->input_mask; +} + + int pvr2_channel_claim_stream(struct pvr2_channel *cp, struct pvr2_context_stream *sp) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h index 6fb6ab022851..745e270233c2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.h +++ b/drivers/media/video/pvrusb2/pvrusb2-context.h @@ -62,6 +62,7 @@ struct pvr2_channel { struct pvr2_channel *mc_prev; struct pvr2_context_stream *stream; struct pvr2_hdw *hdw; + unsigned int input_mask; void (*check_func)(struct pvr2_channel *); }; @@ -72,6 +73,8 @@ void pvr2_context_disconnect(struct pvr2_context *); void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *); void pvr2_channel_done(struct pvr2_channel *); +int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int); +unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *); int pvr2_channel_claim_stream(struct pvr2_channel *, struct pvr2_context_stream *); struct pvr2_ioread *pvr2_channel_create_mpeg_stream( diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index c20eef0f077e..2e64f98d1241 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -244,13 +244,10 @@ static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) { - /* TO DO: This function will call into the core and request for - * input to be set to 'dtv' if (acquire) and if it isn't set already. - * - * If (!acquire) then we should do nothing -- don't switch inputs - * again unless the analog side of the driver requests the bus. - */ - return 0; + struct pvr2_dvb_adapter *adap = fe->dvb->priv; + return pvr2_channel_limit_inputs( + &adap->channel, + (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0)); } static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap) @@ -320,32 +317,26 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) { struct pvr2_hdw *hdw = adap->channel.hdw; struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; - int ret; + int ret = 0; if (dvb_props == NULL) { err("fe_props not defined!"); return -EINVAL; } - /* FIXME: This code should be moved into the core, - * and should only be called if we don't already have - * control of the bus. - * - * We can't call "pvr2_dvb_bus_ctrl(adap->fe, 1)" from here, - * because adap->fe isn't defined yet. - */ - ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_by_id(hdw, - PVR2_CID_INPUT), - PVR2_CVAL_INPUT_DTV); - if (ret != 0) + ret = pvr2_channel_limit_inputs( + &adap->channel, + (1 << PVR2_CVAL_INPUT_DTV)); + if (ret) { + err("failed to grab control of dtv input (code=%d)", + ret); return ret; - - pvr2_hdw_commit_ctl(hdw); - + } if (dvb_props->frontend_attach == NULL) { err("frontend_attach not defined!"); - return -EINVAL; + ret = -EINVAL; + goto done; } if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) { @@ -354,7 +345,8 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) err("frontend registration failed!"); dvb_frontend_detach(adap->fe); adap->fe = NULL; - return -ENODEV; + ret = -ENODEV; + goto done; } if (dvb_props->tuner_attach) @@ -368,10 +360,13 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) } else { err("no frontend was attached!"); - return -ENODEV; + ret = -ENODEV; + return ret; } - return 0; + done: + pvr2_channel_limit_inputs(&adap->channel, 0); + return ret; } static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index a67dcf84b596..a3fe251d6fd9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -336,8 +336,10 @@ struct pvr2_hdw { int v4l_minor_number_vbi; int v4l_minor_number_radio; - /* Bit mask of PVR2_CVAL_INPUT choices which are valid */ + /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */ unsigned int input_avail_mask; + /* Bit mask of PVR2_CVAL_INPUT choices which are currenly allowed */ + unsigned int input_allowed_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 63d0af759ed8..72e9056557bd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -249,6 +249,7 @@ static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = { }; +static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v); static void pvr2_hdw_state_sched(struct pvr2_hdw *); static int pvr2_hdw_state_eval(struct pvr2_hdw *); static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); @@ -404,30 +405,12 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp) static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) { - return ((1 << v) & cptr->hdw->input_avail_mask) != 0; + return ((1 << v) & cptr->hdw->input_allowed_mask) != 0; } static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) { - struct pvr2_hdw *hdw = cptr->hdw; - - if (hdw->input_val != v) { - hdw->input_val = v; - hdw->input_dirty = !0; - } - - /* Handle side effects - if we switch to a mode that needs the RF - tuner, then select the right frequency choice as well and mark - it dirty. */ - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - hdw->freqSelector = 0; - hdw->freqDirty = !0; - } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) || - (hdw->input_val == PVR2_CVAL_INPUT_DTV)) { - hdw->freqSelector = 1; - hdw->freqDirty = !0; - } - return 0; + return pvr2_hdw_set_input(cptr->hdw,v); } static int ctrl_isdirty_input(struct pvr2_ctrl *cptr) @@ -1916,6 +1899,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, 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->input_allowed_mask = hdw->input_avail_mask; /* If not a hybrid device, pathway_state never changes. So initialize it here to what it should forever be. */ @@ -3948,6 +3932,24 @@ static int pvr2_hdw_state_update(struct pvr2_hdw *hdw) } +static unsigned int print_input_mask(unsigned int msk, + char *buf,unsigned int acnt) +{ + unsigned int idx,ccnt; + unsigned int tcnt = 0; + for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) { + if (!((1 << idx) & msk)) continue; + ccnt = scnprintf(buf+tcnt, + acnt-tcnt, + "%s%s", + (tcnt ? ", " : ""), + control_values_input[idx]); + tcnt += ccnt; + } + return tcnt; +} + + static const char *pvr2_pathway_state_name(int id) { switch (id) { @@ -4016,6 +4018,28 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, "state: %s", pvr2_get_state_name(hdw->master_state)); case 4: { + unsigned int tcnt = 0; + unsigned int ccnt; + + ccnt = scnprintf(buf, + acnt, + "Hardware supported inputs: "); + tcnt += ccnt; + tcnt += print_input_mask(hdw->input_avail_mask, + buf+tcnt, + acnt-tcnt); + if (hdw->input_avail_mask != hdw->input_allowed_mask) { + ccnt = scnprintf(buf+tcnt, + acnt-tcnt, + "; allowed inputs: "); + tcnt += ccnt; + tcnt += print_input_mask(hdw->input_allowed_mask, + buf+tcnt, + acnt-tcnt); + } + return tcnt; + } + case 5: { struct pvr2_stream_stats stats; if (!hdw->vid_stream) break; pvr2_stream_get_stats(hdw->vid_stream, @@ -4210,6 +4234,74 @@ unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw) } +unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw) +{ + return hdw->input_allowed_mask; +} + + +static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v) +{ + if (hdw->input_val != v) { + hdw->input_val = v; + hdw->input_dirty = !0; + } + + /* Handle side effects - if we switch to a mode that needs the RF + tuner, then select the right frequency choice as well and mark + it dirty. */ + if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { + hdw->freqSelector = 0; + hdw->freqDirty = !0; + } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) || + (hdw->input_val == PVR2_CVAL_INPUT_DTV)) { + hdw->freqSelector = 1; + hdw->freqDirty = !0; + } + return 0; +} + + +int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw, + unsigned int change_mask, + unsigned int change_val) +{ + int ret = 0; + unsigned int nv,m,idx; + LOCK_TAKE(hdw->big_lock); + do { + nv = hdw->input_allowed_mask & ~change_mask; + nv |= (change_val & change_mask); + nv &= hdw->input_avail_mask; + if (!nv) { + /* No legal modes left; return error instead. */ + ret = -EPERM; + break; + } + hdw->input_allowed_mask = nv; + if ((1 << hdw->input_val) & hdw->input_allowed_mask) { + /* Current mode is still in the allowed mask, so + we're done. */ + break; + } + /* Select and switch to a mode that is still in the allowed + mask */ + if (!hdw->input_allowed_mask) { + /* Nothing legal; give up */ + break; + } + m = hdw->input_allowed_mask; + for (idx = 0; idx < (sizeof(m) << 3); idx++) { + if (!((1 << idx) & m)) continue; + pvr2_hdw_set_input(hdw,idx); + break; + } + } while (0); + LOCK_GIVE(hdw->big_lock); + return ret; +} + + /* 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 74c2503f8e3f..20295e0c1995 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -149,6 +149,19 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *); * will be according to PVR_CVAL_INPUT_xxxx definitions. */ unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *); +/* Return a bit mask of allowed input selections for this device. Mask bits + * will be according to PVR_CVAL_INPUT_xxxx definitions. */ +unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *); + +/* Change the set of allowed input selections for this device. Both + change_mask and change_valu are mask bits according to + PVR_CVAL_INPUT_xxxx definitions. The change_mask parameter indicate + which settings are being changed and the change_val parameter indicates + whether corresponding settings are being set or cleared. */ +int pvr2_hdw_set_input_allowed(struct pvr2_hdw *, + unsigned int change_mask, + unsigned int change_val); + /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 249d7488e482..b415141b2859 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -57,7 +57,6 @@ struct pvr2_v4l2_fh { struct pvr2_v4l2_fh *vprev; wait_queue_head_t wait_data; int fw_mode_flag; - int prev_input_val; }; struct pvr2_v4l2 { @@ -900,20 +899,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) v4l2_prio_close(&vp->prio, &fhp->prio); file->private_data = NULL; - /* 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 { @@ -944,6 +929,8 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) struct pvr2_v4l2_fh *fhp; struct pvr2_v4l2 *vp; struct pvr2_hdw *hdw; + unsigned int input_mask = 0; + int ret = 0; dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); @@ -969,6 +956,29 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); pvr2_channel_init(&fhp->channel,vp->channel.mc_head); + if (dip->v4l_type == VFL_TYPE_RADIO) { + /* Opening device as a radio, legal input selection subset + is just the radio. */ + input_mask = (1 << PVR2_CVAL_INPUT_RADIO); + } else { + /* Opening the main V4L device, legal input selection + subset includes all analog inputs. */ + input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) | + (1 << PVR2_CVAL_INPUT_TV) | + (1 << PVR2_CVAL_INPUT_COMPOSITE) | + (1 << PVR2_CVAL_INPUT_SVIDEO)); + } + ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask); + if (ret) { + pvr2_channel_done(&fhp->channel); + pvr2_trace(PVR2_TRACE_STRUCT, + "Destroying pvr_v4l2_fh id=%p (input mask error)", + fhp); + + kfree(fhp); + return ret; + } + fhp->vnext = NULL; fhp->vprev = vp->vlast; if (vp->vlast) { @@ -979,18 +989,6 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) 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; v4l2_prio_open(&vp->prio,&fhp->prio); From 17a7b6642da13f789471895677c98736ac85f43a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 21 Apr 2008 03:48:41 -0300 Subject: [PATCH 443/452] V4L/DVB (7720): pvrusb2: Fix bad error code on cx23416 firmware load failure Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 72e9056557bd..a3e40adc2c13 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1265,7 +1265,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) " must be a multiple of %zu bytes", fw_files[fwidx],sizeof(u32)); release_firmware(fw_entry); - return -1; + return -EINVAL; } fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); From 21684ba921d7758dc9264e0de64475b8a636ee95 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 21 Apr 2008 03:49:33 -0300 Subject: [PATCH 444/452] V4L/DVB (7721): pvrusb2: Restructure cx23416 firmware loading to have a common exit point Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index a3e40adc2c13..19de395a5fcb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1252,7 +1252,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) pvr2_trace(PVR2_TRACE_ERROR_LEGS, "firmware2 upload prep failed, ret=%d",ret); release_firmware(fw_entry); - return ret; + goto done; } /* Now send firmware */ @@ -1265,7 +1265,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) " must be a multiple of %zu bytes", fw_files[fwidx],sizeof(u32)); release_firmware(fw_entry); - return -EINVAL; + ret = -EINVAL; + goto done; } fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); @@ -1273,7 +1274,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) release_firmware(fw_entry); pvr2_trace(PVR2_TRACE_ERROR_LEGS, "failed to allocate memory for firmware2 upload"); - return -ENOMEM; + ret = -ENOMEM; + goto done; } pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT); @@ -1304,7 +1306,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "firmware2 upload transfer failure"); - return ret; + goto done; } /* Finish upload */ @@ -1317,6 +1319,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) pvr2_trace(PVR2_TRACE_ERROR_LEGS, "firmware2 upload post-proc failure"); } + + done: return ret; } From 1df59f0b908bfcdc35d1ea2319290ece272bf576 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 21 Apr 2008 03:50:39 -0300 Subject: [PATCH 445/452] V4L/DVB (7722): pvrusb2: Implement FM radio support for Gotview USB2.0 DVD 2 Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 4 ++- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index ffdc45c324e5..97350b048b8d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -84,7 +84,9 @@ static const struct routing_scheme_item routing_schemegv[] = { .vid = CX25840_COMPOSITE2, .aud = CX25840_AUDIO5, }, - [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */ + [PVR2_CVAL_INPUT_RADIO] = { + /* line-in is used for radio and composite. A GPIO is + used to switch between the two choices. */ .vid = CX25840_COMPOSITE1, .aud = CX25840_AUDIO_SERIAL, }, diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 43c49fb66209..2dd06a90adce 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -124,6 +124,7 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = { .flag_has_cx25840 = !0, .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .flag_has_analogtuner = !0, + .flag_has_fmradio = !0, .flag_has_composite = !0, .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW, diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 19de395a5fcb..0a868888f389 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1321,6 +1321,12 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) } done: + if (hdw->hdw_desc->signal_routing_scheme == + PVR2_ROUTING_SCHEME_GOTVIEW) { + /* Ensure that GPIO 11 is set to output for GOTVIEW + hardware. */ + pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0); + } return ret; } @@ -1735,6 +1741,13 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; + if (hdw->hdw_desc->signal_routing_scheme == + PVR2_ROUTING_SCHEME_GOTVIEW) { + /* Ensure that GPIO 11 is set to output for GOTVIEW + hardware. */ + pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0); + } + pvr2_hdw_commit_setup(hdw); hdw->vid_stream = pvr2_stream_create(); @@ -2498,6 +2511,20 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) hdw->active_stream_type = hdw->desired_stream_type; } + if (hdw->hdw_desc->signal_routing_scheme == + PVR2_ROUTING_SCHEME_GOTVIEW) { + u32 b; + /* Handle GOTVIEW audio switching */ + pvr2_hdw_gpio_get_out(hdw,&b); + if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { + /* Set GPIO 11 */ + pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0); + } else { + /* Clear GPIO 11 */ + pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0); + } + } + /* Now execute i2c core update */ pvr2_i2c_core_sync(hdw); From e57b1c80065f7922e3ba464f54254c7ce983a3a4 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 21 Apr 2008 03:52:34 -0300 Subject: [PATCH 446/452] V4L/DVB (7723): pvrusb2: Clean up input selection list generation in V4L interface Change how list of possible pvrusb2 inputs is generated to include only those interfaces that make sense for the interface instance. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 69 ++++++++++++---------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index b415141b2859..087a18245560 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -57,6 +57,9 @@ struct pvr2_v4l2_fh { struct pvr2_v4l2_fh *vprev; wait_queue_head_t wait_data; int fw_mode_flag; + /* Map contiguous ordinal value to input id */ + unsigned char *input_map; + unsigned int input_cnt; }; struct pvr2_v4l2 { @@ -66,10 +69,6 @@ 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... */ @@ -269,11 +268,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, memset(&tmp,0,sizeof(tmp)); tmp.index = vi->index; ret = 0; - if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { + if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { ret = -EINVAL; break; } - val = vp->input_map[vi->index]; + val = fh->input_map[vi->index]; switch (val) { case PVR2_CVAL_INPUT_TV: case PVR2_CVAL_INPUT_DTV: @@ -321,8 +320,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, val = 0; ret = pvr2_ctrl_get_value(cptr,&val); vi->index = 0; - for (idx = 0; idx < vp->input_cnt; idx++) { - if (vp->input_map[idx] == val) { + for (idx = 0; idx < fh->input_cnt; idx++) { + if (fh->input_map[idx] == val) { vi->index = idx; break; } @@ -333,13 +332,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_INPUT: { struct v4l2_input *vi = (struct v4l2_input *)arg; - if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { + if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { ret = -ERANGE; break; } ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), - vp->input_map[vi->index]); + fh->input_map[vi->index]); break; } @@ -838,10 +837,6 @@ 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); @@ -915,6 +910,10 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) pvr2_channel_done(&fhp->channel); pvr2_trace(PVR2_TRACE_STRUCT, "Destroying pvr_v4l2_fh id=%p",fhp); + if (fhp->input_map) { + kfree(fhp->input_map); + fhp->input_map = NULL; + } kfree(fhp); if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { pvr2_v4l2_destroy_no_lock(vp); @@ -930,6 +929,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) struct pvr2_v4l2 *vp; struct pvr2_hdw *hdw; unsigned int input_mask = 0; + unsigned int input_cnt,idx; int ret = 0; dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); @@ -979,6 +979,27 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) return ret; } + 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++; + } + fhp->input_cnt = input_cnt; + fhp->input_map = kzalloc(input_cnt,GFP_KERNEL); + if (!fhp->input_map) { + pvr2_channel_done(&fhp->channel); + pvr2_trace(PVR2_TRACE_STRUCT, + "Destroying pvr_v4l2_fh id=%p (input map failure)", + fhp); + kfree(fhp); + return -ENOMEM; + } + input_cnt = 0; + for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { + if (!(input_mask & (1 << idx))) continue; + fhp->input_map[input_cnt++] = idx; + } + fhp->vnext = NULL; fhp->vprev = vp->vlast; if (vp->vlast) { @@ -1217,8 +1238,6 @@ 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; @@ -1227,26 +1246,12 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) 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); - if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) { + if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) & + (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); From b1b81f1db73f00e595585b16aa31293a791964c0 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sun, 13 Jan 2008 23:42:44 -0300 Subject: [PATCH 447/452] V4L/DVB (7725): cx23885: Add generic cx23417 hardware encoder support cx23885: Add generic cx23417 hardware encoder support. Signed-off-by: Steven Toth Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/Makefile | 2 +- drivers/media/video/cx23885/cx23885-417.c | 1764 ++++++++++++++++++++ drivers/media/video/cx23885/cx23885-core.c | 163 +- drivers/media/video/cx23885/cx23885.h | 23 + 4 files changed, 1921 insertions(+), 31 deletions(-) create mode 100644 drivers/media/video/cx23885/cx23885-417.c diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index 32c90be50602..d7b0721af062 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile @@ -1,4 +1,4 @@ -cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o +cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c new file mode 100644 index 000000000000..acdd3b6b3e7c --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -0,0 +1,1764 @@ +/* + * + * Support for a cx23417 mpeg encoder via cx23885 host port. + * + * (c) 2004 Jelle Foks + * (c) 2004 Gerd Knorr + * (c) 2008 Steven Toth + * - CX23885/7/8 support + * + * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "cx23885.h" +#include "media/cx2341x.h" + +#define CX23885_FIRM_IMAGE_SIZE 376836 +#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" + +static unsigned int mpegbufs = 32; +module_param(mpegbufs, int, 0644); +MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32"); +static unsigned int mpeglines = 32; +module_param(mpeglines, int, 0644); +MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32"); +static unsigned int mpeglinesize = 512; +module_param(mpeglinesize, int, 0644); +MODULE_PARM_DESC(mpeglinesize, + "number of bytes in each line of an MPEG buffer, range 512-1024"); + +static unsigned int v4l_debug; +module_param(v4l_debug, int, 0644); +MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages"); + +#define dprintk(level, fmt, arg...)\ + do { if (v4l_debug >= level) \ + printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\ + } while (0) + +static struct cx23885_tvnorm cx23885_tvnorms[] = { + { + .name = "NTSC-M", + .id = V4L2_STD_NTSC_M, + }, { + .name = "NTSC-JP", + .id = V4L2_STD_NTSC_M_JP, + }, { + .name = "PAL-BG", + .id = V4L2_STD_PAL_BG, + }, { + .name = "PAL-DK", + .id = V4L2_STD_PAL_DK, + }, { + .name = "PAL-I", + .id = V4L2_STD_PAL_I, + }, { + .name = "PAL-M", + .id = V4L2_STD_PAL_M, + }, { + .name = "PAL-N", + .id = V4L2_STD_PAL_N, + }, { + .name = "PAL-Nc", + .id = V4L2_STD_PAL_Nc, + }, { + .name = "PAL-60", + .id = V4L2_STD_PAL_60, + }, { + .name = "SECAM-L", + .id = V4L2_STD_SECAM_L, + }, { + .name = "SECAM-DK", + .id = V4L2_STD_SECAM_DK, + } +}; + +/* ------------------------------------------------------------------ */ +enum cx23885_capture_type { + CX23885_MPEG_CAPTURE, + CX23885_RAW_CAPTURE, + CX23885_RAW_PASSTHRU_CAPTURE +}; +enum cx23885_capture_bits { + CX23885_RAW_BITS_NONE = 0x00, + CX23885_RAW_BITS_YUV_CAPTURE = 0x01, + CX23885_RAW_BITS_PCM_CAPTURE = 0x02, + CX23885_RAW_BITS_VBI_CAPTURE = 0x04, + CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08, + CX23885_RAW_BITS_TO_HOST_CAPTURE = 0x10 +}; +enum cx23885_capture_end { + CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */ + CX23885_END_NOW, /* stop immediately, no irq */ +}; +enum cx23885_framerate { + CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */ + CX23885_FRAMERATE_PAL_25 /* PAL: 25fps */ +}; +enum cx23885_stream_port { + CX23885_OUTPUT_PORT_MEMORY, + CX23885_OUTPUT_PORT_STREAMING, + CX23885_OUTPUT_PORT_SERIAL +}; +enum cx23885_data_xfer_status { + CX23885_MORE_BUFFERS_FOLLOW, + CX23885_LAST_BUFFER, +}; +enum cx23885_picture_mask { + CX23885_PICTURE_MASK_NONE, + CX23885_PICTURE_MASK_I_FRAMES, + CX23885_PICTURE_MASK_I_P_FRAMES = 0x3, + CX23885_PICTURE_MASK_ALL_FRAMES = 0x7, +}; +enum cx23885_vbi_mode_bits { + CX23885_VBI_BITS_SLICED, + CX23885_VBI_BITS_RAW, +}; +enum cx23885_vbi_insertion_bits { + CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA, + CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1, + CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1, + CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, + CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, +}; +enum cx23885_dma_unit { + CX23885_DMA_BYTES, + CX23885_DMA_FRAMES, +}; +enum cx23885_dma_transfer_status_bits { + CX23885_DMA_TRANSFER_BITS_DONE = 0x01, + CX23885_DMA_TRANSFER_BITS_ERROR = 0x04, + CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10, +}; +enum cx23885_pause { + CX23885_PAUSE_ENCODING, + CX23885_RESUME_ENCODING, +}; +enum cx23885_copyright { + CX23885_COPYRIGHT_OFF, + CX23885_COPYRIGHT_ON, +}; +enum cx23885_notification_type { + CX23885_NOTIFICATION_REFRESH, +}; +enum cx23885_notification_status { + CX23885_NOTIFICATION_OFF, + CX23885_NOTIFICATION_ON, +}; +enum cx23885_notification_mailbox { + CX23885_NOTIFICATION_NO_MAILBOX = -1, +}; +enum cx23885_field1_lines { + CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */ + CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */ + CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */ +}; +enum cx23885_field2_lines { + CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */ + CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */ + CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */ +}; +enum cx23885_custom_data_type { + CX23885_CUSTOM_EXTENSION_USR_DATA, + CX23885_CUSTOM_PRIVATE_PACKET, +}; +enum cx23885_mute { + CX23885_UNMUTE, + CX23885_MUTE, +}; +enum cx23885_mute_video_mask { + CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00, + CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000, + CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000, +}; +enum cx23885_mute_video_shift { + CX23885_MUTE_VIDEO_V_SHIFT = 8, + CX23885_MUTE_VIDEO_U_SHIFT = 16, + CX23885_MUTE_VIDEO_Y_SHIFT = 24, +}; + +/* defines below are from ivtv-driver.h */ +#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF + +/* Firmware API commands */ +#define IVTV_API_STD_TIMEOUT 500 + +/* Registers */ +/* IVTV_REG_OFFSET */ +#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8) +#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC) +#define IVTV_REG_SPU (0x9050) +#define IVTV_REG_HW_BLOCKS (0x9054) +#define IVTV_REG_VPU (0x9058) +#define IVTV_REG_APU (0xA064) + +/**** Bit definitions for MC417_RWD and MC417_OEN registers *** + bits 31-16 ++-----------+ +| Reserved | ++-----------+ + bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8 ++-------+-------+-------+-------+-------+-------+-------+-------+ +| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0| ++-------+-------+-------+-------+-------+-------+-------+-------+ + bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 ++-------+-------+-------+-------+-------+-------+-------+-------+ +|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0| ++-------+-------+-------+-------+-------+-------+-------+-------+ +***/ +#define MC417_MIWR 0x8000 +#define MC417_MIRD 0x4000 +#define MC417_MICS 0x2000 +#define MC417_MIRDY 0x1000 +#define MC417_MIADDR 0x0F00 +#define MC417_MIDATA 0x00FF + +/* MIADDR* nibble definitions */ +#define MCI_MEMORY_DATA_BYTE0 0x000 +#define MCI_MEMORY_DATA_BYTE1 0x100 +#define MCI_MEMORY_DATA_BYTE2 0x200 +#define MCI_MEMORY_DATA_BYTE3 0x300 +#define MCI_MEMORY_ADDRESS_BYTE2 0x400 +#define MCI_MEMORY_ADDRESS_BYTE1 0x500 +#define MCI_MEMORY_ADDRESS_BYTE0 0x600 +#define MCI_REGISTER_DATA_BYTE0 0x800 +#define MCI_REGISTER_DATA_BYTE1 0x900 +#define MCI_REGISTER_DATA_BYTE2 0xA00 +#define MCI_REGISTER_DATA_BYTE3 0xB00 +#define MCI_REGISTER_ADDRESS_BYTE0 0xC00 +#define MCI_REGISTER_ADDRESS_BYTE1 0xD00 +#define MCI_REGISTER_MODE 0xE00 + +/* Read and write modes */ +#define MCI_MODE_REGISTER_READ 0 +#define MCI_MODE_REGISTER_WRITE 1 +#define MCI_MODE_MEMORY_READ 0 +#define MCI_MODE_MEMORY_WRITE 0x40 + +/*** Bit definitions for MC417_CTL register **** + bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0 ++--------+-------------+--------+--------------+------------+ +|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN| ++--------+-------------+--------+--------------+------------+ +***/ +#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030) +#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006) +#define MC417_UART_GPIO_EN 0x00000001 + +/* Values for speed control */ +#define MC417_SPD_CTL_SLOW 0x1 +#define MC417_SPD_CTL_MEDIUM 0x0 +#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */ + +/* Values for GPIO select */ +#define MC417_GPIO_SEL_GPIO3 0x3 +#define MC417_GPIO_SEL_GPIO2 0x2 +#define MC417_GPIO_SEL_GPIO1 0x1 +#define MC417_GPIO_SEL_GPIO0 0x0 + +void cx23885_mc417_init(struct cx23885_dev *dev) +{ + u32 regval; + + dprintk(2, "%s()\n", __func__); + + /* Configure MC417_CTL register to defaults. */ + regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST) | + MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3) | + MC417_UART_GPIO_EN; + cx_write(MC417_CTL, regval); + + /* Configure MC417_OEN to defaults. */ + regval = MC417_MIRDY; + cx_write(MC417_OEN, regval); + + /* Configure MC417_RWD to defaults. */ + regval = MC417_MIWR | MC417_MIRD | MC417_MICS; + cx_write(MC417_RWD, regval); +} + +static int mc417_wait_ready(struct cx23885_dev *dev) +{ + u32 mi_ready; + unsigned long timeout = jiffies + msecs_to_jiffies(1); + + for (;;) { + mi_ready = cx_read(MC417_RWD) & MC417_MIRDY; + if (mi_ready != 0) + return 0; + if (time_after(jiffies, timeout)) + return -1; + udelay(1); + } +} + +static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value) +{ + u32 regval; + + /* Enable MC417 GPIO outputs except for MC417_MIRDY, + * which is an input. + */ + cx_write(MC417_OEN, MC417_MIRDY); + + /* Write data byte 0 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 | + (value & 0x000000FF); + cx_write(MC417_RWD, regval); + + /* Transition CS/WR to effect write transaction across bus. */ + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write data byte 1 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 | + ((value >> 8) & 0x000000FF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write data byte 2 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 | + ((value >> 16) & 0x000000FF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write data byte 3 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 | + ((value >> 24) & 0x000000FF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write address byte 0 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 | + (address & 0xFF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write address byte 1 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 | + ((address >> 8) & 0xFF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Indicate that this is a write. */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE | + MCI_MODE_REGISTER_WRITE; + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Wait for the trans to complete (MC417_MIRDY asserted). */ + return mc417_wait_ready(dev); +} + +static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value) +{ + int retval; + u32 regval; + u32 tempval; + u32 dataval; + + /* Enable MC417 GPIO outputs except for MC417_MIRDY, + * which is an input. + */ + cx_write(MC417_OEN, MC417_MIRDY); + + /* Write address byte 0 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 | + ((address & 0x00FF)); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write address byte 1 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 | + ((address >> 8) & 0xFF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Indicate that this is a register read. */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE | + MCI_MODE_REGISTER_READ; + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Wait for the trans to complete (MC417_MIRDY asserted). */ + retval = mc417_wait_ready(dev); + + /* switch the DAT0-7 GPIO[10:3] to input mode */ + cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA); + + /* Read data byte 0 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0; + cx_write(MC417_RWD, regval); + + /* Transition RD to effect read transaction across bus. + * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)? + * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its + * input only...) + */ + regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0; + cx_write(MC417_RWD, regval); + + /* Collect byte */ + tempval = cx_read(MC417_RWD); + dataval = tempval & 0x000000FF; + + /* Bring CS and RD high. */ + regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; + cx_write(MC417_RWD, regval); + + /* Read data byte 1 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1; + cx_write(MC417_RWD, regval); + regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1; + cx_write(MC417_RWD, regval); + tempval = cx_read(MC417_RWD); + dataval |= ((tempval & 0x000000FF) << 8); + regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; + cx_write(MC417_RWD, regval); + + /* Read data byte 2 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2; + cx_write(MC417_RWD, regval); + regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2; + cx_write(MC417_RWD, regval); + tempval = cx_read(MC417_RWD); + dataval |= ((tempval & 0x000000FF) << 16); + regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; + cx_write(MC417_RWD, regval); + + /* Read data byte 3 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3; + cx_write(MC417_RWD, regval); + regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3; + cx_write(MC417_RWD, regval); + tempval = cx_read(MC417_RWD); + dataval |= ((tempval & 0x000000FF) << 24); + regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; + cx_write(MC417_RWD, regval); + + *value = dataval; + + return retval; +} + +int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value) +{ + u32 regval; + + /* Enable MC417 GPIO outputs except for MC417_MIRDY, + * which is an input. + */ + cx_write(MC417_OEN, MC417_MIRDY); + + /* Write data byte 0 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 | + (value & 0x000000FF); + cx_write(MC417_RWD, regval); + + /* Transition CS/WR to effect write transaction across bus. */ + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write data byte 1 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 | + ((value >> 8) & 0x000000FF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write data byte 2 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 | + ((value >> 16) & 0x000000FF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write data byte 3 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 | + ((value >> 24) & 0x000000FF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write address byte 2 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 | + MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write address byte 1 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 | + ((address >> 8) & 0xFF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write address byte 0 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 | + (address & 0xFF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Wait for the trans to complete (MC417_MIRDY asserted). */ + return mc417_wait_ready(dev); +} + +int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value) +{ + int retval; + u32 regval; + u32 tempval; + u32 dataval; + + /* Enable MC417 GPIO outputs except for MC417_MIRDY, + * which is an input. + */ + cx_write(MC417_OEN, MC417_MIRDY); + + /* Write address byte 2 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 | + MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write address byte 1 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 | + ((address >> 8) & 0xFF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Write address byte 0 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 | + (address & 0xFF); + cx_write(MC417_RWD, regval); + regval |= MC417_MICS | MC417_MIWR; + cx_write(MC417_RWD, regval); + + /* Wait for the trans to complete (MC417_MIRDY asserted). */ + retval = mc417_wait_ready(dev); + + /* switch the DAT0-7 GPIO[10:3] to input mode */ + cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA); + + /* Read data byte 3 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3; + cx_write(MC417_RWD, regval); + + /* Transition RD to effect read transaction across bus. */ + regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3; + cx_write(MC417_RWD, regval); + + /* Collect byte */ + tempval = cx_read(MC417_RWD); + dataval = ((tempval & 0x000000FF) << 24); + + /* Bring CS and RD high. */ + regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; + cx_write(MC417_RWD, regval); + + /* Read data byte 2 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2; + cx_write(MC417_RWD, regval); + regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2; + cx_write(MC417_RWD, regval); + tempval = cx_read(MC417_RWD); + dataval |= ((tempval & 0x000000FF) << 16); + regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; + cx_write(MC417_RWD, regval); + + /* Read data byte 1 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1; + cx_write(MC417_RWD, regval); + regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1; + cx_write(MC417_RWD, regval); + tempval = cx_read(MC417_RWD); + dataval |= ((tempval & 0x000000FF) << 8); + regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; + cx_write(MC417_RWD, regval); + + /* Read data byte 0 */ + regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0; + cx_write(MC417_RWD, regval); + regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0; + cx_write(MC417_RWD, regval); + tempval = cx_read(MC417_RWD); + dataval |= (tempval & 0x000000FF); + regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; + cx_write(MC417_RWD, regval); + + *value = dataval; + + return retval; +} + +/* ------------------------------------------------------------------ */ + +/* MPEG encoder API */ +char *cmd_to_str(int cmd) +{ + switch (cmd) { + case CX2341X_ENC_PING_FW: + return "PING_FW"; + case CX2341X_ENC_START_CAPTURE: + return "START_CAPTURE"; + case CX2341X_ENC_STOP_CAPTURE: + return "STOP_CAPTURE"; + case CX2341X_ENC_SET_AUDIO_ID: + return "SET_AUDIO_ID"; + case CX2341X_ENC_SET_VIDEO_ID: + return "SET_VIDEO_ID"; + case CX2341X_ENC_SET_PCR_ID: + return "SET_PCR_PID"; + case CX2341X_ENC_SET_FRAME_RATE: + return "SET_FRAME_RATE"; + case CX2341X_ENC_SET_FRAME_SIZE: + return "SET_FRAME_SIZE"; + case CX2341X_ENC_SET_BIT_RATE: + return "SET_BIT_RATE"; + case CX2341X_ENC_SET_GOP_PROPERTIES: + return "SET_GOP_PROPERTIES"; + case CX2341X_ENC_SET_ASPECT_RATIO: + return "SET_ASPECT_RATIO"; + case CX2341X_ENC_SET_DNR_FILTER_MODE: + return "SET_DNR_FILTER_PROPS"; + case CX2341X_ENC_SET_DNR_FILTER_PROPS: + return "SET_DNR_FILTER_PROPS"; + case CX2341X_ENC_SET_CORING_LEVELS: + return "SET_CORING_LEVELS"; + case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE: + return "SET_SPATIAL_FILTER_TYPE"; + case CX2341X_ENC_SET_VBI_LINE: + return "SET_VBI_LINE"; + case CX2341X_ENC_SET_STREAM_TYPE: + return "SET_STREAM_TYPE"; + case CX2341X_ENC_SET_OUTPUT_PORT: + return "SET_OUTPUT_PORT"; + case CX2341X_ENC_SET_AUDIO_PROPERTIES: + return "SET_AUDIO_PROPERTIES"; + case CX2341X_ENC_HALT_FW: + return "HALT_FW"; + case CX2341X_ENC_GET_VERSION: + return "GET_VERSION"; + case CX2341X_ENC_SET_GOP_CLOSURE: + return "SET_GOP_CLOSURE"; + case CX2341X_ENC_GET_SEQ_END: + return "GET_SEQ_END"; + case CX2341X_ENC_SET_PGM_INDEX_INFO: + return "SET_PGM_INDEX_INFO"; + case CX2341X_ENC_SET_VBI_CONFIG: + return "SET_VBI_CONFIG"; + case CX2341X_ENC_SET_DMA_BLOCK_SIZE: + return "SET_DMA_BLOCK_SIZE"; + case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10: + return "GET_PREV_DMA_INFO_MB_10"; + case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9: + return "GET_PREV_DMA_INFO_MB_9"; + case CX2341X_ENC_SCHED_DMA_TO_HOST: + return "SCHED_DMA_TO_HOST"; + case CX2341X_ENC_INITIALIZE_INPUT: + return "INITIALIZE_INPUT"; + case CX2341X_ENC_SET_FRAME_DROP_RATE: + return "SET_FRAME_DROP_RATE"; + case CX2341X_ENC_PAUSE_ENCODER: + return "PAUSE_ENCODER"; + case CX2341X_ENC_REFRESH_INPUT: + return "REFRESH_INPUT"; + case CX2341X_ENC_SET_COPYRIGHT: + return "SET_COPYRIGHT"; + case CX2341X_ENC_SET_EVENT_NOTIFICATION: + return "SET_EVENT_NOTIFICATION"; + case CX2341X_ENC_SET_NUM_VSYNC_LINES: + return "SET_NUM_VSYNC_LINES"; + case CX2341X_ENC_SET_PLACEHOLDER: + return "SET_PLACEHOLDER"; + case CX2341X_ENC_MUTE_VIDEO: + return "MUTE_VIDEO"; + case CX2341X_ENC_MUTE_AUDIO: + return "MUTE_AUDIO"; + case CX2341X_ENC_MISC: + return "MISC"; + default: + return "UNKNOWN"; + } +} + +static int cx23885_mbox_func(void *priv, + u32 command, + int in, + int out, + u32 data[CX2341X_MBOX_MAX_DATA]) +{ + struct cx23885_dev *dev = priv; + unsigned long timeout; + u32 value, flag, retval = 0; + int i; + + dprintk(3, "%s: command(0x%X) = %s\n", __func__, command, + cmd_to_str(command)); + + /* this may not be 100% safe if we can't read any memory location + without side effects */ + mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value); + if (value != 0x12345678) { + printk(KERN_ERR + "Firmware and/or mailbox pointer not initialized " + "or corrupted, signature = 0x%x, cmd = %s\n", value, + cmd_to_str(command)); + return -1; + } + + /* This read looks at 32 bits, but flag is only 8 bits. + * Seems we also bail if CMD or TIMEOUT bytes are set??? + */ + mc417_memory_read(dev, dev->cx23417_mailbox, &flag); + if (flag) { + printk(KERN_ERR "ERROR: Mailbox appears to be in use " + "(%x), cmd = %s\n", flag, cmd_to_str(command)); + return -1; + } + + flag |= 1; /* tell 'em we're working on it */ + mc417_memory_write(dev, dev->cx23417_mailbox, flag); + + /* write command + args + fill remaining with zeros */ + /* command code */ + mc417_memory_write(dev, dev->cx23417_mailbox + 1, command); + mc417_memory_write(dev, dev->cx23417_mailbox + 3, + IVTV_API_STD_TIMEOUT); /* timeout */ + for (i = 0; i < in; i++) { + mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]); + dprintk(3, "API Input %d = %d\n", i, data[i]); + } + for (; i < CX2341X_MBOX_MAX_DATA; i++) + mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0); + + flag |= 3; /* tell 'em we're done writing */ + mc417_memory_write(dev, dev->cx23417_mailbox, flag); + + /* wait for firmware to handle the API command */ + timeout = jiffies + msecs_to_jiffies(10); + for (;;) { + mc417_memory_read(dev, dev->cx23417_mailbox, &flag); + if (0 != (flag & 4)) + break; + if (time_after(jiffies, timeout)) { + printk(KERN_ERR "ERROR: API Mailbox timeout\n"); + return -1; + } + udelay(10); + } + + /* read output values */ + for (i = 0; i < out; i++) { + mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i); + dprintk(3, "API Output %d = %d\n", i, data[i]); + } + + mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval); + dprintk(3, "API result = %d\n", retval); + + flag = 0; + mc417_memory_write(dev, dev->cx23417_mailbox, flag); + + return retval; +} + +/* We don't need to call the API often, so using just one + * mailbox will probably suffice + */ +static int cx23885_api_cmd(struct cx23885_dev *dev, + u32 command, + u32 inputcnt, + u32 outputcnt, + ...) +{ + u32 data[CX2341X_MBOX_MAX_DATA]; + va_list vargs; + int i, err; + + dprintk(3, "%s() cmds = 0x%08x\n", __func__, command); + + va_start(vargs, outputcnt); + for (i = 0; i < inputcnt; i++) + data[i] = va_arg(vargs, int); + + err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data); + for (i = 0; i < outputcnt; i++) { + int *vptr = va_arg(vargs, int *); + *vptr = data[i]; + } + va_end(vargs); + + return err; +} + +static int cx23885_find_mailbox(struct cx23885_dev *dev) +{ + u32 signature[4] = { + 0x12345678, 0x34567812, 0x56781234, 0x78123456 + }; + int signaturecnt = 0; + u32 value; + int i; + + dprintk(2, "%s()\n", __func__); + + for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) { + mc417_memory_read(dev, i, &value); + if (value == signature[signaturecnt]) + signaturecnt++; + else + signaturecnt = 0; + if (4 == signaturecnt) { + dprintk(1, "Mailbox signature found at 0x%x\n", i+1); + return i+1; + } + } + printk(KERN_ERR "Mailbox signature values not found!\n"); + return -1; +} + +static int cx23885_load_firmware(struct cx23885_dev *dev) +{ + static const unsigned char magic[8] = { + 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa + }; + const struct firmware *firmware; + int i, retval = 0; + u32 value = 0; + u32 gpio_output = 0; + u32 checksum = 0; + u32 *dataptr; + + dprintk(2, "%s()\n", __func__); + + /* Save GPIO settings before reset of APU */ + retval |= mc417_memory_read(dev, 0x9020, &gpio_output); + retval |= mc417_memory_read(dev, 0x900C, &value); + + retval = mc417_register_write(dev, + IVTV_REG_VPU, 0xFFFFFFED); + retval |= mc417_register_write(dev, + IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= mc417_register_write(dev, + IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800); + retval |= mc417_register_write(dev, + IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); + retval |= mc417_register_write(dev, + IVTV_REG_APU, 0); + + if (retval != 0) { + printk(KERN_ERR "%s: Error with mc417_register_write\n", + __func__); + return -1; + } + + retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME, + &dev->pci->dev); + + if (retval != 0) { + printk(KERN_ERR + "ERROR: Hotplug firmware request failed (%s).\n", + CX2341X_FIRM_ENC_FILENAME); + printk(KERN_ERR "Please fix your hotplug setup, the board will " + "not work without firmware loaded!\n"); + return -1; + } + + if (firmware->size != CX23885_FIRM_IMAGE_SIZE) { + printk(KERN_ERR "ERROR: Firmware size mismatch " + "(have %zd, expected %d)\n", + firmware->size, CX23885_FIRM_IMAGE_SIZE); + release_firmware(firmware); + return -1; + } + + if (0 != memcmp(firmware->data, magic, 8)) { + printk(KERN_ERR + "ERROR: Firmware magic mismatch, wrong file?\n"); + release_firmware(firmware); + return -1; + } + + /* transfer to the chip */ + dprintk(2, "Loading firmware ...\n"); + dataptr = (u32 *)firmware->data; + for (i = 0; i < (firmware->size >> 2); i++) { + value = *dataptr; + checksum += ~value; + if (mc417_memory_write(dev, i, value) != 0) { + printk(KERN_ERR "ERROR: Loading firmware failed!\n"); + release_firmware(firmware); + return -1; + } + dataptr++; + } + + /* read back to verify with the checksum */ + dprintk(1, "Verifying firmware ...\n"); + for (i--; i >= 0; i--) { + if (mc417_memory_read(dev, i, &value) != 0) { + printk(KERN_ERR "ERROR: Reading firmware failed!\n"); + release_firmware(firmware); + return -1; + } + checksum -= ~value; + } + if (checksum) { + printk(KERN_ERR + "ERROR: Firmware load failed (checksum mismatch).\n"); + release_firmware(firmware); + return -1; + } + release_firmware(firmware); + dprintk(1, "Firmware upload successful.\n"); + + retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS, + IVTV_CMD_HW_BLOCKS_RST); + + /* Restore GPIO settings, make sure EIO14 is enabled as an output. */ + dprintk(2, "%s: GPIO output EIO 0-15 was = 0x%x\n", + __func__, gpio_output); + /* Power-up seems to have GPIOs AFU. This was causing digital side + * to fail at power-up. Seems GPIOs should be set to 0x10ff0411 at + * power-up. + * gpio_output |= (1<<14); + */ + /* Note: GPIO14 is specific to the HVR1800 here */ + gpio_output = 0x10ff0411 | (1<<14); + retval |= mc417_register_write(dev, 0x9020, gpio_output | (1<<14)); + dprintk(2, "%s: GPIO output EIO 0-15 now = 0x%x\n", + __func__, gpio_output); + + dprintk(1, "%s: GPIO value EIO 0-15 was = 0x%x\n", + __func__, value); + value |= (1<<14); + dprintk(1, "%s: GPIO value EIO 0-15 now = 0x%x\n", + __func__, value); + retval |= mc417_register_write(dev, 0x900C, value); + + retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); + retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); + + if (retval < 0) + printk(KERN_ERR "%s: Error with mc417_register_write\n", + __func__); + return 0; +} + +void cx23885_417_check_encoder(struct cx23885_dev *dev) +{ + u32 status, seq; + + status = seq = 0; + cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq); + dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq); +} + +static void cx23885_codec_settings(struct cx23885_dev *dev) +{ + dprintk(1, "%s()\n", __func__); + + /* assign frame size */ + cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, + dev->ts1.height, dev->ts1.width); + + dev->mpeg_params.width = dev->ts1.width; + dev->mpeg_params.height = dev->ts1.height; + dev->mpeg_params.is_50hz = + (dev->encodernorm.id & V4L2_STD_625_50) != 0; + + cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params); + + cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1); + cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); +} + +static int cx23885_initialize_codec(struct cx23885_dev *dev) +{ + int version; + int retval; + u32 i, data[7]; + + dprintk(1, "%s()\n", __func__); + + retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ + if (retval < 0) { + dprintk(2, "%s() PING OK\n", __func__); + retval = cx23885_load_firmware(dev); + if (retval < 0) { + printk(KERN_ERR "%s() f/w load failed\n", __func__); + return retval; + } + dev->cx23417_mailbox = cx23885_find_mailbox(dev); + if (dev->cx23417_mailbox < 0) { + printk(KERN_ERR "%s() mailbox < 0, error\n", + __func__); + return -1; + } + retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); + if (retval < 0) { + printk(KERN_ERR + "ERROR: cx23417 firmware ping failed!\n"); + return -1; + } + retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, + &version); + if (retval < 0) { + printk(KERN_ERR "ERROR: cx23417 firmware get encoder :" + "version failed!\n"); + return -1; + } + dprintk(1, "cx23417 firmware version is 0x%08x\n", version); + msleep(200); + } + + cx23885_codec_settings(dev); + msleep(60); + + cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, + CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115); + cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, + CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0); + + /* Setup to capture VBI */ + data[0] = 0x0001BD00; + data[1] = 1; /* frames per interrupt */ + data[2] = 4; /* total bufs */ + data[3] = 0x91559155; /* start codes */ + data[4] = 0x206080C0; /* stop codes */ + data[5] = 6; /* lines */ + data[6] = 64; /* BPL */ + + cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1], + data[2], data[3], data[4], data[5], data[6]); + + for (i = 2; i <= 24; i++) { + int valid; + + valid = ((i >= 19) && (i <= 21)); + cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i, + valid, 0 , 0, 0); + cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, + i | 0x80000000, valid, 0, 0, 0); + } + + cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE); + msleep(60); + + /* initialize the video input */ + cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); + msleep(60); + + /* Enable VIP style pixel invalidation so we work with scaled mode */ + mc417_memory_write(dev, 2120, 0x00000080); + + /* start capturing to the host interface */ + cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, + CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE); + msleep(10); + + return 0; +} + +/* ------------------------------------------------------------------ */ + +static int bb_buf_setup(struct videobuf_queue *q, + unsigned int *count, unsigned int *size) +{ + struct cx23885_fh *fh = q->priv_data; + + fh->dev->ts1.ts_packet_size = mpeglinesize; + fh->dev->ts1.ts_packet_count = mpeglines; + + *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; + *count = mpegbufs; + + return 0; +} + +static int bb_buf_prepare(struct videobuf_queue *q, + struct videobuf_buffer *vb, enum v4l2_field field) +{ + struct cx23885_fh *fh = q->priv_data; + return cx23885_buf_prepare(q, &fh->dev->ts1, + (struct cx23885_buffer *)vb, + field); +} + +static void bb_buf_queue(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + struct cx23885_fh *fh = q->priv_data; + cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb); +} + +static void bb_buf_release(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + cx23885_free_buffer(q, (struct cx23885_buffer *)vb); +} + +static struct videobuf_queue_ops cx23885_qops = { + .buf_setup = bb_buf_setup, + .buf_prepare = bb_buf_prepare, + .buf_queue = bb_buf_queue, + .buf_release = bb_buf_release, +}; + +/* ------------------------------------------------------------------ */ + +static const u32 *ctrl_classes[] = { + cx2341x_mpeg_ctrls, + NULL +}; + +static int cx23885_queryctrl(struct cx23885_dev *dev, + struct v4l2_queryctrl *qctrl) +{ + qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); + if (qctrl->id == 0) + return -EINVAL; + + /* MPEG V4L2 controls */ + if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl)) + qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; + + return 0; +} + +static int cx23885_querymenu(struct cx23885_dev *dev, + struct v4l2_querymenu *qmenu) +{ + struct v4l2_queryctrl qctrl; + + qctrl.id = qmenu->id; + cx23885_queryctrl(dev, &qctrl); + return v4l2_ctrl_query_menu(qmenu, &qctrl, + cx2341x_ctrl_get_menu(qmenu->id)); +} + +int cx23885_do_ioctl(struct inode *inode, struct file *file, int radio, + struct cx23885_dev *dev, unsigned int cmd, void *arg, + v4l2_kioctl driver_ioctl) +{ + int err; + + switch (cmd) { + /* ---------- tv norms ---------- */ + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *e = arg; + unsigned int i; + + i = e->index; + if (i >= ARRAY_SIZE(cx23885_tvnorms)) + return -EINVAL; + err = v4l2_video_std_construct(e, + cx23885_tvnorms[e->index].id, + cx23885_tvnorms[e->index].name); + e->index = i; + if (err < 0) + return err; + return 0; + } + case VIDIOC_G_STD: + { + v4l2_std_id *id = arg; + + *id = dev->encodernorm.id; + return 0; + } + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++) + if (*id & cx23885_tvnorms[i].id) + break; + if (i == ARRAY_SIZE(cx23885_tvnorms)) + return -EINVAL; + dev->encodernorm = cx23885_tvnorms[i]; + + return 0; + } + + /* ------ input switching ---------- */ + case VIDIOC_ENUMINPUT: + { + struct cx23885_input *input; + struct v4l2_input *i = arg; + unsigned int n; + + n = i->index; + if (n >= 4) + return -EINVAL; + input = &cx23885_boards[dev->board].input[n]; + if (input->type == 0) + return -EINVAL; + memset(i, 0, sizeof(*i)); + i->index = n; + /* FIXME + * strcpy(i->name, input->name); */ + strcpy(i->name, "unset"); + if (input->type == CX23885_VMUX_TELEVISION || + input->type == CX23885_VMUX_CABLE) + i->type = V4L2_INPUT_TYPE_TUNER; + else + i->type = V4L2_INPUT_TYPE_CAMERA; + + for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++) + i->std |= cx23885_tvnorms[n].id; + return 0; + } + case VIDIOC_G_INPUT: + { + unsigned int *i = arg; + + *i = dev->input; + return 0; + } + case VIDIOC_S_INPUT: + { + unsigned int *i = arg; + + if (*i >= 4) + return -EINVAL; + + return 0; + } + + /* --- tuner ioctls ------------------------------------------ */ + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *t = arg; + + if (UNSET == dev->tuner_type) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + memset(t, 0, sizeof(*t)); + strcpy(t->name, "Television"); + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t); + cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); + + dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type); + + return 0; + } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *t = arg; + + if (UNSET == dev->tuner_type) + return -EINVAL; + + /* Update the A/V core */ + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t); + + return 0; + } + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + memset(f, 0, sizeof(*f)); + if (UNSET == dev->tuner_type) + return -EINVAL; + f->type = V4L2_TUNER_ANALOG_TV; + f->frequency = dev->freq; + + /* Assumption that tuner is always on bus 1 */ + cx23885_call_i2c_clients(&dev->i2c_bus[1], + VIDIOC_G_FREQUENCY, f); + + return 0; + } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n", + dev->tuner_type); + dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n", + f->tuner, f->type); + if (UNSET == dev->tuner_type) + return -EINVAL; + if (f->tuner != 0) + return -EINVAL; + if (f->type != V4L2_TUNER_ANALOG_TV) + return -EINVAL; + dev->freq = f->frequency; + + /* Assumption that tuner is always on bus 1 */ + cx23885_call_i2c_clients(&dev->i2c_bus[1], + VIDIOC_S_FREQUENCY, f); + return 0; + } + case VIDIOC_S_CTRL: + { + /* Update the A/V core */ + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, arg); + return 0; + } + default: + /* Convert V4L ioctl to V4L2 and call mpeg_do_ioctl + * (driver_ioctl) */ + return v4l_compat_translate_ioctl(inode, file, cmd, arg, + driver_ioctl); + } + + return 0; +} + +static int mpeg_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct cx23885_fh *fh = file->private_data; + struct cx23885_dev *dev = fh->dev; + struct cx23885_tsport *tsport = &dev->ts1; + + if (v4l_debug > 1) + v4l_print_ioctl(dev->name, cmd); + + switch (cmd) { + + /* --- capabilities ------------------------------------------ */ + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + memset(cap, 0, sizeof(*cap)); + strcpy(cap->driver, dev->name); + strlcpy(cap->card, cx23885_boards[tsport->dev->board].name, + sizeof(cap->card)); + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); + cap->version = CX23885_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING | + 0; + if (UNSET != dev->tuner_type) + cap->capabilities |= V4L2_CAP_TUNER; + + return 0; + } + + /* --- capture ioctls ---------------------------------------- */ + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + int index; + + index = f->index; + if (index != 0) + return -EINVAL; + + memset(f, 0, sizeof(*f)); + f->index = index; + strlcpy(f->description, "MPEG", sizeof(f->description)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->pixelformat = V4L2_PIX_FMT_MPEG; + return 0; + } + case VIDIOC_G_FMT: + { + struct v4l2_format *f = arg; + + memset(f, 0, sizeof(*f)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = + dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; + f->fmt.pix.colorspace = 0; + f->fmt.pix.width = dev->ts1.width; + f->fmt.pix.height = dev->ts1.height; + f->fmt.pix.field = fh->mpegq.field; + dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", + dev->ts1.width, dev->ts1.height, fh->mpegq.field); + return 0; + } + case VIDIOC_TRY_FMT: + { + struct v4l2_format *f = arg; + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = + dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; + f->fmt.pix.sizeimage = + f->fmt.pix.colorspace = 0; + dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", + dev->ts1.width, dev->ts1.height, fh->mpegq.field); + return 0; + } + case VIDIOC_S_FMT: + { + struct v4l2_format *f = arg; + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = + dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; + f->fmt.pix.colorspace = 0; + dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", + f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); + return 0; + } + + /* --- streaming capture ------------------------------------- */ + case VIDIOC_REQBUFS: + return videobuf_reqbufs(&fh->mpegq, arg); + + case VIDIOC_QUERYBUF: + return videobuf_querybuf(&fh->mpegq, arg); + + case VIDIOC_QBUF: + return videobuf_qbuf(&fh->mpegq, arg); + + case VIDIOC_DQBUF: + return videobuf_dqbuf(&fh->mpegq, arg, + file->f_flags & O_NONBLOCK); + + case VIDIOC_STREAMON: + return videobuf_streamon(&fh->mpegq); + + case VIDIOC_STREAMOFF: + return videobuf_streamoff(&fh->mpegq); + + case VIDIOC_G_EXT_CTRLS: + { + struct v4l2_ext_controls *f = arg; + + if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, cmd); + } + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: + { + struct v4l2_ext_controls *f = arg; + struct cx2341x_mpeg_params p; + int err; + + if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + p = dev->mpeg_params; + err = cx2341x_ext_ctrls(&p, 0, f, cmd); + if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) { + err = cx2341x_update(dev, cx23885_mbox_func, + &dev->mpeg_params, &p); + dev->mpeg_params = p; + } + return err; + } + case VIDIOC_S_FREQUENCY: + { + cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, + CX23885_END_NOW, CX23885_MPEG_CAPTURE, + CX23885_RAW_BITS_NONE); + cx23885_do_ioctl(inode, file, 0, dev, cmd, arg, + mpeg_do_ioctl); + cx23885_initialize_codec(dev); + + return 0; + } + case VIDIOC_LOG_STATUS: + { + char name[32 + 2]; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO + "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS, + NULL); + cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS, + NULL); + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS, + NULL); + cx2341x_log_status(&dev->mpeg_params, name); + printk(KERN_INFO + "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; + } + case VIDIOC_QUERYMENU: + return cx23885_querymenu(dev, arg); + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *c = arg; + + return cx23885_queryctrl(dev, c); + } + + default: + return cx23885_do_ioctl(inode, file, 0, dev, cmd, arg, + mpeg_do_ioctl); + } + return 0; +} + +static int mpeg_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl); +} + +static int mpeg_open(struct inode *inode, struct file *file) +{ + int minor = iminor(inode); + struct cx23885_dev *h, *dev = NULL; + struct list_head *list; + struct cx23885_fh *fh; + + dprintk(2, "%s()\n", __func__); + + list_for_each(list, &cx23885_devlist) { + h = list_entry(list, struct cx23885_dev, devlist); + if (h->v4l_device->minor == minor) { + dev = h; + break; + } + } + + if (dev == NULL) + return -ENODEV; + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) + return -ENOMEM; + + file->private_data = fh; + fh->dev = dev; + + videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops, + &dev->pci->dev, &dev->ts1.slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx23885_buffer), + fh); + + return 0; +} + +static int mpeg_release(struct inode *inode, struct file *file) +{ + struct cx23885_fh *fh = file->private_data; + struct cx23885_dev *dev = fh->dev; + + dprintk(2, "%s()\n", __func__); + + /* FIXME: Review this crap */ + /* Shut device down on last close */ + if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) { + if (atomic_dec_return(&dev->v4l_reader_count) == 0) { + /* stop mpeg capture */ + cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, + CX23885_END_NOW, CX23885_MPEG_CAPTURE, + CX23885_RAW_BITS_NONE); + + msleep(500); + cx23885_417_check_encoder(dev); + + cx23885_cancel_buffers(&fh->dev->ts1); + } + } + + if (fh->mpegq.streaming) + videobuf_streamoff(&fh->mpegq); + if (fh->mpegq.reading) + videobuf_read_stop(&fh->mpegq); + + videobuf_mmap_free(&fh->mpegq); + file->private_data = NULL; + kfree(fh); + + return 0; +} + +static ssize_t mpeg_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct cx23885_fh *fh = file->private_data; + struct cx23885_dev *dev = fh->dev; + + dprintk(2, "%s()\n", __func__); + + /* Deal w/ A/V decoder * and mpeg encoder sync issues. */ + /* Start mpeg encoder on first read. */ + if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { + if (atomic_inc_return(&dev->v4l_reader_count) == 1) { + if (cx23885_initialize_codec(dev) < 0) + return -EINVAL; + } + } + + return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0, + file->f_flags & O_NONBLOCK); +} + +static unsigned int mpeg_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct cx23885_fh *fh = file->private_data; + struct cx23885_dev *dev = fh->dev; + + dprintk(2, "%s\n", __func__); + + return videobuf_poll_stream(file, &fh->mpegq, wait); +} + +static int mpeg_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct cx23885_fh *fh = file->private_data; + struct cx23885_dev *dev = fh->dev; + + dprintk(2, "%s()\n", __func__); + + return videobuf_mmap_mapper(&fh->mpegq, vma); +} + +static struct file_operations mpeg_fops = { + .owner = THIS_MODULE, + .open = mpeg_open, + .release = mpeg_release, + .read = mpeg_read, + .poll = mpeg_poll, + .mmap = mpeg_mmap, + .ioctl = mpeg_ioctl, + .llseek = no_llseek, +}; + +static struct video_device cx23885_mpeg_template = { + .name = "cx23885", + .type = VID_TYPE_CAPTURE | + VID_TYPE_TUNER | + VID_TYPE_SCALES | + VID_TYPE_MPEG_ENCODER, + .fops = &mpeg_fops, + .minor = -1, +}; + +void cx23885_417_unregister(struct cx23885_dev *dev) +{ + dprintk(1, "%s()\n", __func__); + + if (dev->v4l_device) { + if (-1 != dev->v4l_device->minor) + video_unregister_device(dev->v4l_device); + else + video_device_release(dev->v4l_device); + dev->v4l_device = NULL; + } +} + +static struct video_device *cx23885_video_dev_alloc( + struct cx23885_tsport *tsport, + struct pci_dev *pci, + struct video_device *template, + char *type) +{ + struct video_device *vfd; + struct cx23885_dev *dev = tsport->dev; + + dprintk(1, "%s()\n", __func__); + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; + snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, + type, cx23885_boards[tsport->dev->board].name); + vfd->dev = &pci->dev; + vfd->release = video_device_release; + return vfd; +} + +int cx23885_417_register(struct cx23885_dev *dev) +{ + /* FIXME: Port1 hardcoded here */ + int err = -ENODEV; + struct cx23885_tsport *tsport = &dev->ts1; + + dprintk(1, "%s()\n", __func__); + + if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER) + return err; + + /* Set default TV standard */ + dev->encodernorm = cx23885_tvnorms[0]; + + if (dev->encodernorm.id & V4L2_STD_525_60) + tsport->height = 480; + else + tsport->height = 576; + + tsport->width = 720; + cx2341x_fill_defaults(&dev->mpeg_params); + + dev->mpeg_params.port = CX2341X_PORT_SERIAL; + + /* Allocate and initialize V4L video device */ + dev->v4l_device = cx23885_video_dev_alloc(tsport, + dev->pci, &cx23885_mpeg_template, "mpeg"); + err = video_register_device(dev->v4l_device, + VFL_TYPE_GRABBER, -1); + if (err < 0) { + printk(KERN_INFO "%s: can't register mpeg device\n", dev->name); + return err; + } + + /* Initialize MC417 registers */ + cx23885_mc417_init(dev); + + printk(KERN_INFO "%s: registered device video%d [mpeg]\n", + dev->name, dev->v4l_device->minor & 0x1f); + + return 0; +} diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index b23d60801ed0..7f7446a76465 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = { static int cx23885_risc_decode(u32 risc) { static char *instr[16] = { - [ RISC_SYNC >> 28 ] = "sync", - [ RISC_WRITE >> 28 ] = "write", - [ RISC_WRITEC >> 28 ] = "writec", - [ RISC_READ >> 28 ] = "read", - [ RISC_READC >> 28 ] = "readc", - [ RISC_JUMP >> 28 ] = "jump", - [ RISC_SKIP >> 28 ] = "skip", - [ RISC_WRITERM >> 28 ] = "writerm", - [ RISC_WRITECM >> 28 ] = "writecm", - [ RISC_WRITECR >> 28 ] = "writecr", + [RISC_SYNC >> 28] = "sync", + [RISC_WRITE >> 28] = "write", + [RISC_WRITEC >> 28] = "writec", + [RISC_READ >> 28] = "read", + [RISC_READC >> 28] = "readc", + [RISC_JUMP >> 28] = "jump", + [RISC_SKIP >> 28] = "skip", + [RISC_WRITERM >> 28] = "writerm", + [RISC_WRITECM >> 28] = "writecm", + [RISC_WRITECR >> 28] = "writecr", }; static int incr[16] = { - [ RISC_WRITE >> 28 ] = 3, - [ RISC_JUMP >> 28 ] = 3, - [ RISC_SKIP >> 28 ] = 1, - [ RISC_SYNC >> 28 ] = 1, - [ RISC_WRITERM >> 28 ] = 3, - [ RISC_WRITECM >> 28 ] = 3, - [ RISC_WRITECR >> 28 ] = 4, + [RISC_WRITE >> 28] = 3, + [RISC_JUMP >> 28] = 3, + [RISC_SKIP >> 28] = 1, + [RISC_SYNC >> 28] = 1, + [RISC_WRITERM >> 28] = 3, + [RISC_WRITECM >> 28] = 3, + [RISC_WRITECR >> 28] = 4, }; static char *bits[] = { "12", "13", "14", "resync", @@ -518,6 +518,8 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p /* Transport bus init dma queue - Common settings */ port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */ port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */ + port->vld_misc_val = 0x0; + port->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4); spin_lock_init(&port->slock); port->dev = dev; @@ -544,7 +546,7 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p port->reg_ts_clk_en = VID_B_TS_CLK_EN; port->reg_src_sel = VID_B_SRC_SEL; port->reg_ts_int_msk = VID_B_INT_MSK; - port->reg_ts_int_stat = VID_B_INT_STAT; + port->reg_ts_int_stat = VID_B_INT_STAT; port->sram_chno = SRAM_CH03; /* VID_B */ port->pci_irqmask = 0x02; /* VID_B bit1 */ break; @@ -697,10 +699,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) dev->i2c_bus[2].reg_wdata = I2C3_WDATA; dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ - if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) + if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) || + (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)) cx23885_init_tsport(dev, &dev->ts1, 1); - if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) + if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) || + (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)) cx23885_init_tsport(dev, &dev->ts2, 2); if (get_resources(dev) < 0) { @@ -760,11 +764,26 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n", __func__); } + } else + if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) { + if (cx23885_417_register(dev) < 0) { + printk(KERN_ERR + "%s() Failed to register 417 on VID_B\n", + __func__); + } } if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { if (cx23885_dvb_register(&dev->ts2) < 0) { - printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n", + printk(KERN_ERR + "%s() Failed to register dvb on VID_C\n", + __func__); + } + } else + if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) { + if (cx23885_417_register(dev) < 0) { + printk(KERN_ERR + "%s() Failed to register 417 on VID_C\n", __func__); } } @@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev) if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) cx23885_video_unregister(dev); - if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) cx23885_dvb_unregister(&dev->ts1); - if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) + if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) + cx23885_417_unregister(dev); + + if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) cx23885_dvb_unregister(&dev->ts2); + if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) + cx23885_417_unregister(dev); + cx23885_i2c_unregister(&dev->i2c_bus[2]); cx23885_i2c_unregister(&dev->i2c_bus[1]); cx23885_i2c_unregister(&dev->i2c_bus[0]); @@ -1043,9 +1068,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port, if(port->reg_src_sel) cx_write(port->reg_src_sel, port->src_sel_val); - cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4); + cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val); cx_write(port->reg_ts_clk_en, port->ts_clk_en_val); - cx_write(port->reg_vld_misc, 0x00); + cx_write(port->reg_vld_misc, port->vld_misc_val); cx_write(port->reg_gen_ctrl, port->gen_ctrl_val); udelay(100); @@ -1239,6 +1264,16 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason, spin_unlock_irqrestore(&port->slock, flags); } +void cx23885_cancel_buffers(struct cx23885_tsport *port) +{ + struct cx23885_dev *dev = port->dev; + struct cx23885_dmaqueue *q = &port->mpegq; + + dprintk(1, "%s()\n", __FUNCTION__); + del_timer_sync(&q->timeout); + cx23885_stop_dma(port); + do_cancel_buffers(port, "cancel", 0); +} static void cx23885_timeout(unsigned long data) { @@ -1254,16 +1289,77 @@ static void cx23885_timeout(unsigned long data) do_cancel_buffers(port, "timeout", 1); } +int cx23885_irq_417(struct cx23885_dev *dev, u32 status) +{ + /* FIXME: port1 assumption here. */ + struct cx23885_tsport *port = &dev->ts1; + int count = 0; + int handled = 0; + + if (status == 0) + return handled; + + count = cx_read(port->reg_gpcnt); + dprintk(7, "status: 0x%08x mask: 0x%08x count: 0x%x\n", + status, cx_read(port->reg_ts_int_msk), count); + + if ((status & VID_B_MSK_BAD_PKT) || + (status & VID_B_MSK_OPC_ERR) || + (status & VID_B_MSK_VBI_OPC_ERR) || + (status & VID_B_MSK_SYNC) || + (status & VID_B_MSK_VBI_SYNC) || + (status & VID_B_MSK_OF) || + (status & VID_B_MSK_VBI_OF)) { + printk(KERN_ERR "%s: V4L mpeg risc op code error, status " + "= 0x%x\n", dev->name, status); + if (status & VID_B_MSK_BAD_PKT) + dprintk(1, " VID_B_MSK_BAD_PKT\n"); + if (status & VID_B_MSK_OPC_ERR) + dprintk(1, " VID_B_MSK_OPC_ERR\n"); + if (status & VID_B_MSK_VBI_OPC_ERR) + dprintk(1, " VID_B_MSK_VBI_OPC_ERR\n"); + if (status & VID_B_MSK_SYNC) + dprintk(1, " VID_B_MSK_SYNC\n"); + if (status & VID_B_MSK_VBI_SYNC) + dprintk(1, " VID_B_MSK_VBI_SYNC\n"); + if (status & VID_B_MSK_OF) + dprintk(1, " VID_B_MSK_OF\n"); + if (status & VID_B_MSK_VBI_OF) + dprintk(1, " VID_B_MSK_VBI_OF\n"); + + cx_clear(port->reg_dma_ctl, port->dma_ctl_val); + cx23885_sram_channel_dump(dev, + &dev->sram_channels[port->sram_chno]); + cx23885_417_check_encoder(dev); + } else if (status & VID_B_MSK_RISCI1) { + dprintk(7, " VID_B_MSK_RISCI1\n"); + spin_lock(&port->slock); + cx23885_wakeup(port, &port->mpegq, count); + spin_unlock(&port->slock); + } else if (status & VID_B_MSK_RISCI2) { + dprintk(7, " VID_B_MSK_RISCI2\n"); + spin_lock(&port->slock); + cx23885_restart_queue(port, &port->mpegq); + spin_unlock(&port->slock); + } + if (status) { + cx_write(port->reg_ts_int_stat, status); + handled = 1; + } + + return handled; +} + static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status) { struct cx23885_dev *dev = port->dev; int handled = 0; u32 count; - if ( (status & VID_BC_MSK_OPC_ERR) || - (status & VID_BC_MSK_BAD_PKT) || - (status & VID_BC_MSK_SYNC) || - (status & VID_BC_MSK_OF)) + if ((status & VID_BC_MSK_OPC_ERR) || + (status & VID_BC_MSK_BAD_PKT) || + (status & VID_BC_MSK_SYNC) || + (status & VID_BC_MSK_OF)) { if (status & VID_BC_MSK_OPC_ERR) dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR); @@ -1277,7 +1373,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status) printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name); cx_clear(port->reg_dma_ctl, port->dma_ctl_val); - cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]); + cx23885_sram_channel_dump(dev, + &dev->sram_channels[port->sram_chno]); } else if (status & VID_BC_MSK_RISCI1) { @@ -1378,11 +1475,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) if (ts1_status) { if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) handled += cx23885_irq_ts(ts1, ts1_status); + else + if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) + handled += cx23885_irq_417(dev, ts1_status); } if (ts2_status) { if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) handled += cx23885_irq_ts(ts2, ts2_status); + else + if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) + handled += cx23885_irq_417(dev, ts2_status); } if (vida_status) diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 3705e6019ce9..e42b6878ba23 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -32,6 +32,7 @@ #include "btcx-risc.h" #include "cx23885-reg.h" +#include "media/cx2341x.h" #include #include @@ -157,6 +158,7 @@ typedef enum { CX23885_MPEG_UNDEFINED = 0, CX23885_MPEG_DVB, CX23885_ANALOG_VIDEO, + CX23885_MPEG_ENCODER, } port_t; struct cx23885_board { @@ -255,6 +257,8 @@ struct cx23885_tsport { u32 gen_ctrl_val; u32 ts_clk_en_val; u32 src_sel_val; + u32 vld_misc_val; + u32 hw_sop_ctrl_val; }; struct cx23885_dev { @@ -315,6 +319,14 @@ struct cx23885_dev { struct cx23885_dmaqueue vidq; struct cx23885_dmaqueue vbiq; spinlock_t slock; + + /* MPEG Encoder ONLY settings */ + u32 cx23417_mailbox; + struct cx2341x_mpeg_params mpeg_params; + struct video_device *v4l_device; + atomic_t v4l_reader_count; + struct cx23885_tvnorm encodernorm; + }; extern struct list_head cx23885_devlist; @@ -435,6 +447,17 @@ extern int cx23885_i2c_unregister(struct cx23885_i2c *bus); extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd, void *arg); +/* ----------------------------------------------------------- */ +/* cx23885-417.c */ +extern int cx23885_417_register(struct cx23885_dev *dev); +extern void cx23885_417_unregister(struct cx23885_dev *dev); +extern int cx23885_irq_417(struct cx23885_dev *dev, u32 status); +extern void cx23885_417_check_encoder(struct cx23885_dev *dev); +extern void cx23885_mc417_init(struct cx23885_dev *dev); +extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value); +extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value); + + /* ----------------------------------------------------------- */ /* tv norms */ From a589b66546d3d81e28dd95d3463c9e9da3d68728 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sun, 13 Jan 2008 23:44:47 -0300 Subject: [PATCH 448/452] V4L/DVB (7726): cx23885: Enable cx23417 support on the HVR1800 cx23885: Enable cx23417 support on the HVR1800 Signed-off-by: Steven Toth Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 22 +++++++++- drivers/media/video/cx23885/cx23885-core.c | 45 ++++++++++++++++++++- drivers/media/video/cx23885/cx23885-i2c.c | 23 +++++++++++ drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 0f4b325f2d89..6ebf58724a01 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -73,6 +73,7 @@ struct cx23885_board cx23885_boards[] = { [CX23885_BOARD_HAUPPAUGE_HVR1800] = { .name = "Hauppauge WinTV-HVR1800", .porta = CX23885_ANALOG_VIDEO, + .portb = CX23885_MPEG_ENCODER, .portc = CX23885_MPEG_DVB, .tuner_type = TUNER_PHILIPS_TDA8290, .tuner_addr = 0x42, /* 0x84 >> 1 */ @@ -336,6 +337,10 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* GPIO-15-18 cx23417 READY, CS, RD, WR */ /* GPIO-19 IR_RX */ + /* CX23417 GPIO's */ + /* EIO15 Zilog Reset */ + /* EIO14 S5H1409/CX24227 Reset */ + /* Force the TDA8295A into reset and back */ cx_set(GP0_IO, 0x00040004); mdelay(20); @@ -443,10 +448,25 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; + case CX23885_BOARD_HAUPPAUGE_HVR1800: + /* Defaults for VID B - Analog encoder */ + /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */ + ts1->gen_ctrl_val = 0x10e; + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + + /* APB_TSVALERR_POL (active low)*/ + ts1->vld_misc_val = 0x2000; + ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc); + + /* Defaults for VID C */ + ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ + ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: - case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 7f7446a76465..f24abcd06dea 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -1037,6 +1037,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port, struct cx23885_buffer *buf) { struct cx23885_dev *dev = port->dev; + u32 reg; dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__, buf->vb.width, buf->vb.height, buf->vb.field); @@ -1062,6 +1063,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port, return -EINVAL; } + if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) + cx23885_av_clk(dev, 0); + udelay(100); /* If the port supports SRC SELECT, configure it */ @@ -1079,6 +1083,21 @@ static int cx23885_start_dma(struct cx23885_tsport *port, cx_write(port->reg_gpcnt_ctl, 3); q->count = 1; + if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) { + + reg = cx_read(PAD_CTRL); + reg = reg & ~0x1; /* Clear TS1_OE */ + + /* FIXME, bit 2 writing here is questionable */ + /* set TS1_SOP_OE and TS1_OE_HI */ + reg = reg | 0xa; + cx_write(PAD_CTRL, reg); + + /* FIXME and these two registers should be documented. */ + cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011); + cx_write(ALT_PIN_OUT_SEL, 0x10100045); + } + switch(dev->bridge) { case CX23885_BRIDGE_885: case CX23885_BRIDGE_887: @@ -1094,6 +1113,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port, cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */ + if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) + cx23885_av_clk(dev, 1); + if (debug > 4) cx23885_tsport_reg_dump(port); @@ -1103,12 +1125,32 @@ static int cx23885_start_dma(struct cx23885_tsport *port, static int cx23885_stop_dma(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; + u32 reg; + dprintk(1, "%s()\n", __func__); /* Stop interrupts and DMA */ cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val); cx_clear(port->reg_dma_ctl, port->dma_ctl_val); + if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) { + + reg = cx_read(PAD_CTRL); + + /* Set TS1_OE */ + reg = reg | 0x1; + + /* clear TS1_SOP_OE and TS1_OE_HI */ + reg = reg & ~0xa; + cx_write(PAD_CTRL, reg); + cx_write(port->reg_src_sel, 0); + cx_write(port->reg_gen_ctrl, 8); + + } + + if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) + cx23885_av_clk(dev, 0); + return 0; } @@ -1525,7 +1567,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%llx\n", dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, - dev->pci_lat, (unsigned long long)pci_resource_start(pci_dev,0)); + dev->pci_lat, + (unsigned long long)pci_resource_start(pci_dev, 0)); pci_set_master(pci_dev); if (!pci_dma_supported(pci_dev, 0xffffffff)) { diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 3928945df5f5..c6bb0a05bc1c 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -423,6 +423,29 @@ int cx23885_i2c_unregister(struct cx23885_i2c *bus) return 0; } +void cx23885_av_clk(struct cx23885_dev *dev, int enable) +{ + /* write 0 to bus 2 addr 0x144 via i2x_xfer() */ + char buffer[3]; + struct i2c_msg msg; + dprintk(1, "%s(enabled = %d)\n", __func__, enable); + + /* Register 0x144 */ + buffer[0] = 0x01; + buffer[1] = 0x44; + if (enable == 1) + buffer[2] = 0x05; + else + buffer[2] = 0x00; + + msg.addr = 0x44; + msg.flags = I2C_M_TEN; + msg.len = 3; + msg.buf = buffer; + + i2c_xfer(&dev->i2c_bus[2].i2c_adap, &msg, 1); +} + /* ----------------------------------------------------------------------- */ /* diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index e42b6878ba23..32af87f25e7b 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -446,6 +446,7 @@ extern int cx23885_i2c_register(struct cx23885_i2c *bus); extern int cx23885_i2c_unregister(struct cx23885_i2c *bus); extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd, void *arg); +extern void cx23885_av_clk(struct cx23885_dev *dev, int enable); /* ----------------------------------------------------------- */ /* cx23885-417.c */ From 867e835f4db4eba6d49072382cc05fc210c4ed1c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 23 Apr 2008 17:27:27 -0300 Subject: [PATCH 449/452] V4L/DVB (7728): tea5761: bugzilla #10462: tea5761 autodetection code were broken Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tea5761.c | 15 ++++++++++----- drivers/media/video/tuner-core.c | 6 +++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c index bd5ad549c1df..b93cdef9ac73 100644 --- a/drivers/media/video/tea5761.c +++ b/drivers/media/video/tea5761.c @@ -247,14 +247,19 @@ int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) { printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc); - return EINVAL; + return -EINVAL; } - if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) { - printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]); - return EINVAL; + if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) { + printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x." + " It is not a TEA5761\n", + buffer[13], buffer[14], buffer[15]); + return -EINVAL; } - printk(KERN_WARNING "TEA5761 detected.\n"); + printk(KERN_WARNING "tea5761: TEA%02x%02x detected. " + "Manufacturer ID= 0x%02x\n", + buffer[14], buffer[15], buffer[13]); + return 0; } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index e886f48a2909..529e00952a8d 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -1111,8 +1111,8 @@ static int tuner_probe(struct i2c_client *client) if (!no_autodetect) { switch (client->addr) { case 0x10: - if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr) - != EINVAL) { + if (tea5761_autodetection(t->i2c->adapter, + t->i2c->addr) >= 0) { t->type = TUNER_TEA5761; t->mode_mask = T_RADIO; t->mode = T_STANDBY; @@ -1124,7 +1124,7 @@ static int tuner_probe(struct i2c_client *client) goto register_client; } - break; + return -ENODEV; case 0x42: case 0x43: case 0x4a: From d2b213f7b76f187c4391079c7581d3a08b940133 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 20 Apr 2008 11:27:36 -0300 Subject: [PATCH 450/452] V4L/DVB (7729): Fix VIDIOCGAP corruption in ivtv Frank Bennett reported that ivtv was causing skype to crash. With help from one of their developers he showed it was a kernel problem. VIDIOCGCAP copies a name into a fixed length buffer - ivtv uses names that are too long and does not truncate them so corrupts a few bytes of the app data area. Possibly the names also want trimming but for now this should fix the corruption case. Signed-off-by: Alan Cox Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 90f59c4155ae..15cac1812122 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -742,7 +742,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void memset(vcap, 0, sizeof(*vcap)); strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */ - strcpy(vcap->card, itv->card_name); /* card type */ + strncpy(vcap->card, itv->card_name, + sizeof(vcap->card)-1); /* card type */ strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */ vcap->version = IVTV_DRIVER_VERSION; /* version */ vcap->capabilities = itv->v4l2_cap; /* capabilities */ From c21f1e2e39a1012f57c33d21af5c909cf2ae3b9a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 24 Apr 2008 10:56:41 -0300 Subject: [PATCH 451/452] V4L/DVB (7730): tuner-xc2028: Fix SCODE load for MTS firmwares There are different tables for MTS firmwares. This should be taken into account while selecting the proper firmware. While at tuner-xc2028.h, improve some comments. Thanks to Edward J. Sheldrake for helping to diagnose such troubles with PAL/I standard. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-xc2028-types.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h index 17633c316c28..74dc46a71f64 100644 --- a/drivers/media/video/tuner-xc2028-types.h +++ b/drivers/media/video/tuner-xc2028-types.h @@ -57,11 +57,13 @@ /* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M) and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr) There are variants both with and without NOGD + Those firmwares produce better result with LCD displays */ #define LCD (1<<12) /* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M) and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr) + The NOGD firmwares don't have group delay compensation filter */ #define NOGD (1<<13) @@ -88,7 +90,10 @@ /* This flag identifies that the scode table has a new format */ #define HAS_IF (1 << 30) -#define SCODE_TYPES SCODE +/* There are different scode tables for MTS and non-MTS. + The MTS firmwares support mono only + */ +#define SCODE_TYPES (SCODE | MTS) /* Newer types not defined on videodev2.h. From b0166ab3a6ae6d7af8d9a21a7836154963c69a11 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 24 Apr 2008 11:19:55 -0300 Subject: [PATCH 452/452] V4L/DVB (7731): tuner-xc2028: fix signal strength calculus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-xc2028.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index a32094e545f7..cc3db7d79a0d 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -844,21 +844,28 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength) /* Sync Lock Indicator */ rc = xc2028_get_reg(priv, 0x0002, &frq_lock); - if (rc < 0 || frq_lock == 0) + if (rc < 0) goto ret; - /* Frequency is locked. Return signal quality */ + /* Frequency is locked */ + if (frq_lock == 1) + signal = 32768; /* Get SNR of the video signal */ rc = xc2028_get_reg(priv, 0x0040, &signal); if (rc < 0) - signal = -frq_lock; + goto ret; + + /* Use both frq_lock and signal to generate the result */ + signal = signal || ((signal & 0x07) << 12); ret: mutex_unlock(&priv->lock); *strength = signal; + tuner_dbg("signal strength is %d\n", signal); + return rc; }