diff options
Diffstat (limited to 'linux/drivers')
-rw-r--r-- | linux/drivers/media/Kconfig | 5 | ||||
-rw-r--r-- | linux/drivers/media/video/Makefile | 3 | ||||
-rw-r--r-- | linux/drivers/media/video/tuner-core.c | 38 | ||||
-rw-r--r-- | linux/drivers/media/video/tuner-simple.c | 442 | ||||
-rw-r--r-- | linux/drivers/media/video/tuner-simple.h | 11 | ||||
-rw-r--r-- | linux/drivers/media/video/tuner-types.c | 6 |
6 files changed, 303 insertions, 202 deletions
diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig index 707b20d7e..a9de06af5 100644 --- a/linux/drivers/media/Kconfig +++ b/linux/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/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 991f8de0a..cd4ee0584 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/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 @@ -85,6 +85,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/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 95bb41cee..2117254b7 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -342,20 +342,10 @@ 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) -{ - struct simple_tuner_config cfg = { - .type = t->type, - .tun = &tuners[t->type] - }; - simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); -} - static void attach_tda829x(struct tuner *t) { struct tda829x_config cfg = { @@ -381,11 +371,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) { @@ -438,7 +423,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; @@ -446,7 +436,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: { @@ -484,7 +479,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; } diff --git a/linux/drivers/media/video/tuner-simple.c b/linux/drivers/media/video/tuner-simple.c index 1cb81befe..5f4b2153e 100644 --- a/linux/drivers/media/video/tuner-simple.c +++ b/linux/drivers/media/video/tuner-simple.c @@ -187,84 +187,91 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength) /* ---------------------------------------------------------------------- */ -static int simple_set_tv_freq(struct dvb_frontend *fe, - struct analog_parameters *params) +static inline char *tuner_param_name(enum param_type type) { - struct tuner_simple_priv *priv = fe->tuner_priv; - u8 config, cb, tuneraddr; - u16 div; - struct tunertype *tun; - u8 buffer[4]; - int rc, IFPCoff, i, j; - enum param_type desired_type; - struct tuner_params *t_params; + char *name; - tun = priv->tun; + 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; +} - /* IFPCoff = Video Intermediate Frequency - Vif: - 940 =16*58.75 NTSC/J (Japan) - 732 =16*45.75 M/N STD - 704 =16*44 ATSC (at DVB code) - 632 =16*39.50 I U.K. - 622.4=16*38.90 B/G D/K I, L STD - 592 =16*37.00 D China - 590 =16.36.875 B Australia - 543.2=16*33.95 L' STD - 171.2=16*10.70 FM Radio (at set_radio_freq) - */ +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; - if (params->std == V4L2_STD_NTSC_M_JP) { - IFPCoff = 940; - desired_type = TUNER_PARAM_TYPE_NTSC; - } else if ((params->std & V4L2_STD_MN) && - !(params->std & ~V4L2_STD_MN)) { - IFPCoff = 732; - desired_type = TUNER_PARAM_TYPE_NTSC; - } else if (params->std == V4L2_STD_SECAM_LC) { - IFPCoff = 543; - desired_type = TUNER_PARAM_TYPE_SECAM; - } else { - IFPCoff = 623; - desired_type = TUNER_PARAM_TYPE_PAL; - } + for (i = 0; i < tun->count; i++) + if (desired_type == tun->params[i].type) + break; - 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; + if (i == tun->count) { + tuner_dbg("desired params (%s) undefined for tuner %d\n", + tuner_param_name(desired_type), priv->type); + i = 0; } - t_params = &tun->params[j]; + + 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 (params->frequency > t_params->ranges[i].limit) + if (*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; + 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; - /* i == 0 -> VHF_LO - * i == 1 -> VHF_HI - * i == 2 -> UHF */ - tuner_dbg("tv: param %d, range %d\n", j, i); + *config = t_params->ranges[i].config; + *cb = t_params->ranges[i].cb; - div = params->frequency + IFPCoff + offset; + 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); - 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); + return i; +} + +/* ---------------------------------------------------------------------- */ + +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) { @@ -272,45 +279,45 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, /* 0x01 -> ??? no change ??? */ /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ - cb &= ~0x03; + *cb &= ~0x03; if (params->std & V4L2_STD_SECAM_L) /* also valid for V4L2_STD_SECAM */ - cb |= PHILIPS_MF_SET_STD_L; + *cb |= PHILIPS_MF_SET_STD_L; else if (params->std & V4L2_STD_SECAM_LC) - cb |= PHILIPS_MF_SET_STD_LC; + *cb |= PHILIPS_MF_SET_STD_LC; else /* V4L2_STD_B|V4L2_STD_GH */ - cb |= PHILIPS_MF_SET_STD_BG; + *cb |= PHILIPS_MF_SET_STD_BG; break; case TUNER_TEMIC_4046FM5: - cb &= ~0x0f; + *cb &= ~0x0f; if (params->std & V4L2_STD_PAL_BG) { - cb |= TEMIC_SET_PAL_BG; + *cb |= TEMIC_SET_PAL_BG; } else if (params->std & V4L2_STD_PAL_I) { - cb |= TEMIC_SET_PAL_I; + *cb |= TEMIC_SET_PAL_I; } else if (params->std & V4L2_STD_PAL_DK) { - cb |= TEMIC_SET_PAL_DK; + *cb |= TEMIC_SET_PAL_DK; } else if (params->std & V4L2_STD_SECAM_L) { - cb |= TEMIC_SET_PAL_L; + *cb |= TEMIC_SET_PAL_L; } break; case TUNER_PHILIPS_FQ1216ME: - cb &= ~0x0f; + *cb &= ~0x0f; if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { - cb |= PHILIPS_SET_PAL_BGDK; + *cb |= PHILIPS_SET_PAL_BGDK; } else if (params->std & V4L2_STD_PAL_I) { - cb |= PHILIPS_SET_PAL_I; + *cb |= PHILIPS_SET_PAL_I; } else if (params->std & V4L2_STD_SECAM_L) { - cb |= PHILIPS_SET_PAL_L; + *cb |= PHILIPS_SET_PAL_L; } break; @@ -320,15 +327,15 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, /* 0x01 -> ATSC antenna input 2 */ /* 0x02 -> NTSC antenna input 1 */ /* 0x03 -> NTSC antenna input 2 */ - cb &= ~0x03; + *cb &= ~0x03; if (!(params->std & V4L2_STD_ATSC)) - cb |= 2; + *cb |= 2; /* FIXME: input */ break; case TUNER_MICROTUNE_4042FI5: /* Set the charge pump for fast tuning */ - config |= TUNER_CHARGE_PUMP; + *config |= TUNER_CHARGE_PUMP; break; case TUNER_PHILIPS_TUV1236D: @@ -340,9 +347,9 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, buffer[1] = 0x00; buffer[2] = 0x17; buffer[3] = 0x00; - cb &= ~0x40; + *cb &= ~0x40; if (params->std & V4L2_STD_ATSC) { - cb |= 0x40; + *cb |= 0x40; buffer[1] = 0x04; } /* set to the correct mode (analog or digital) */ @@ -361,68 +368,14 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, break; } - if (t_params->cb_first_if_lower_freq && div < priv->last_div) { - buffer[0] = config; - buffer[1] = cb; - buffer[2] = (div>>8) & 0x7f; - buffer[3] = div & 0xff; - } else { - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; - buffer[2] = config; - buffer[3] = cb; - } - priv->last_div = div; - 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)); - - tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &config; - - if (params->std == V4L2_STD_SECAM_LC) { - if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc) - config |= TDA9887_PORT1_ACTIVE; - if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) - config |= TDA9887_PORT2_ACTIVE; - } else { - if (t_params->port1_active) - config |= TDA9887_PORT1_ACTIVE; - if (t_params->port2_active) - config |= TDA9887_PORT2_ACTIVE; - } - if (t_params->intercarrier_mode) - config |= TDA9887_INTERCARRIER; - if (is_secam_l) { - if (i == 0 && t_params->default_top_secam_low) - config |= TDA9887_TOP(t_params->default_top_secam_low); - else if (i == 1 && t_params->default_top_secam_mid) - 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 { - 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) - config |= TDA9887_TOP(t_params->default_top_mid); - else if (t_params->default_top_high) - config |= TDA9887_TOP(t_params->default_top_high); - } - if (t_params->default_pll_gating_18) - config |= TDA9887_GATING_18; - i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG, - &tda9887_cfg); - } - tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0], buffer[1], buffer[2], buffer[3]); + return 0; +} - 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); +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: @@ -489,6 +442,169 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, break; } } + + return 0; +} + +static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + switch (priv->type) { + case TUNER_TENA_9533_DI: + case TUNER_YMEC_TVF_5533MF: + tuner_dbg("This tuner doesn't have FM. " + "Most cards have a TEA5767 for FM\n"); + return 0; + case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FMD1216ME_MK3: + case TUNER_LG_NTSC_TAPE: + case TUNER_PHILIPS_FM1256_IH3: + buffer[3] = 0x19; + break; + case TUNER_TNF_5335MF: + buffer[3] = 0x11; + break; + case TUNER_LG_PAL_FM: + buffer[3] = 0xa5; + break; + case TUNER_THOMSON_DTT761X: + buffer[3] = 0x39; + break; + case TUNER_MICROTUNE_4049FM5: + default: + buffer[3] = 0xa4; + break; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int simple_set_tv_freq(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u8 config, cb; + u16 div; + struct tunertype *tun; + u8 buffer[4]; + int rc, IFPCoff, i; + enum param_type desired_type; + struct tuner_params *t_params; + + tun = priv->tun; + + /* IFPCoff = Video Intermediate Frequency - Vif: + 940 =16*58.75 NTSC/J (Japan) + 732 =16*45.75 M/N STD + 704 =16*44 ATSC (at DVB code) + 632 =16*39.50 I U.K. + 622.4=16*38.90 B/G D/K I, L STD + 592 =16*37.00 D China + 590 =16.36.875 B Australia + 543.2=16*33.95 L' STD + 171.2=16*10.70 FM Radio (at set_radio_freq) + */ + + if (params->std == V4L2_STD_NTSC_M_JP) { + IFPCoff = 940; + desired_type = TUNER_PARAM_TYPE_NTSC; + } else if ((params->std & V4L2_STD_MN) && + !(params->std & ~V4L2_STD_MN)) { + IFPCoff = 732; + desired_type = TUNER_PARAM_TYPE_NTSC; + } else if (params->std == V4L2_STD_SECAM_LC) { + IFPCoff = 543; + desired_type = TUNER_PARAM_TYPE_SECAM; + } else { + IFPCoff = 623; + desired_type = TUNER_PARAM_TYPE_PAL; + } + + t_params = simple_tuner_params(fe, desired_type); + + i = simple_config_lookup(fe, t_params, ¶ms->frequency, + &config, &cb); + + div = params->frequency + IFPCoff + offset; + + tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " + "Offset=%d.%02d MHz, div=%0d\n", + params->frequency / 16, params->frequency % 16 * 100 / 16, + IFPCoff / 16, IFPCoff % 16 * 100 / 16, + offset / 16, offset % 16 * 100 / 16, div); + + /* tv norm specific stuff for multi-norm tuners */ + simple_std_setup(fe, params, &buffer[1], &config, &cb); + + if (t_params->cb_first_if_lower_freq && div < priv->last_div) { + buffer[0] = config; + buffer[1] = cb; + buffer[2] = (div>>8) & 0x7f; + buffer[3] = div & 0xff; + } else { + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; + buffer[2] = config; + buffer[3] = cb; + } + priv->last_div = div; + 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)); + + tda9887_cfg.tuner = TUNER_TDA9887; + tda9887_cfg.priv = &config; + + if (params->std == V4L2_STD_SECAM_LC) { + if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc) + config |= TDA9887_PORT1_ACTIVE; + if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) + config |= TDA9887_PORT2_ACTIVE; + } else { + if (t_params->port1_active) + config |= TDA9887_PORT1_ACTIVE; + if (t_params->port2_active) + config |= TDA9887_PORT2_ACTIVE; + } + if (t_params->intercarrier_mode) + config |= TDA9887_INTERCARRIER; + if (is_secam_l) { + if (i == 0 && t_params->default_top_secam_low) + config |= TDA9887_TOP(t_params->default_top_secam_low); + else if (i == 1 && t_params->default_top_secam_mid) + 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 { + 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) + config |= TDA9887_TOP(t_params->default_top_mid); + else if (t_params->default_top_high) + config |= TDA9887_TOP(t_params->default_top_high); + } + if (t_params->default_pll_gating_18) + config |= TDA9887_GATING_18; + i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG, + &tda9887_cfg); + } + 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); + + simple_post_tune(fe, &buffer[0], div, config, cb); + return 0; } @@ -529,33 +645,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 */ @@ -666,10 +756,16 @@ 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; + 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; @@ -677,15 +773,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/linux/drivers/media/video/tuner-simple.h b/linux/drivers/media/video/tuner-simple.h index 9089939a8..bf425f325 100644 --- a/linux/drivers/media/video/tuner-simple.h +++ b/linux/drivers/media/video/tuner-simple.h @@ -20,23 +20,16 @@ #include <linux/i2c.h> #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; diff --git a/linux/drivers/media/video/tuner-types.c b/linux/drivers/media/video/tuner-types.c index 8b78a2140..7eb3c6315 100644 --- a/linux/drivers/media/video/tuner-types.c +++ b/linux/drivers/media/video/tuner-types.c @@ -1528,5 +1528,11 @@ 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"); |