Path: blob/master/drivers/media/common/tuners/tuner-simple.c
15112 views
/*1* i2c tv tuner chip device driver2* controls all those simple 4-control-bytes style tuners.3*4* This "tuner-simple" module was split apart from the original "tuner" module.5*/6#include <linux/delay.h>7#include <linux/i2c.h>8#include <linux/videodev2.h>9#include <media/tuner.h>10#include <media/v4l2-common.h>11#include <media/tuner-types.h>12#include "tuner-i2c.h"13#include "tuner-simple.h"1415static int debug;16module_param(debug, int, 0644);17MODULE_PARM_DESC(debug, "enable verbose debug messages");1819#define TUNER_SIMPLE_MAX 6420static unsigned int simple_devcount;2122static int offset;23module_param(offset, int, 0664);24MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");2526static unsigned int atv_input[TUNER_SIMPLE_MAX] = \27{ [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };28static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \29{ [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };30module_param_array(atv_input, int, NULL, 0644);31module_param_array(dtv_input, int, NULL, 0644);32MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");33MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");3435/* ---------------------------------------------------------------------- */3637/* tv standard selection for Temic 4046 FM538this value takes the low bits of control byte 239from datasheet Rev.01, Feb.0040standard BG I L L2 D41picture IF 38.9 38.9 38.9 33.95 38.942sound 1 33.4 32.9 32.4 40.45 32.443sound 2 33.1644NICAM 33.05 32.348 33.05 33.0545*/46#define TEMIC_SET_PAL_I 0x0547#define TEMIC_SET_PAL_DK 0x0948#define TEMIC_SET_PAL_L 0x0a /* SECAM ? */49#define TEMIC_SET_PAL_L2 0x0b /* change IF ! */50#define TEMIC_SET_PAL_BG 0x0c5152/* tv tuner system standard selection for Philips FQ1216ME53this value takes the low bits of control byte 254from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")55standard BG DK I L L`56picture carrier 38.90 38.90 38.90 38.90 33.9557colour 34.47 34.47 34.47 34.47 38.3858sound 1 33.40 32.40 32.90 32.40 40.4559sound 2 33.16 - - - -60NICAM 33.05 33.05 32.35 33.05 39.8061*/62#define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/63#define PHILIPS_SET_PAL_BGDK 0x0964#define PHILIPS_SET_PAL_L2 0x0a65#define PHILIPS_SET_PAL_L 0x0b6667/* system switching for Philips FI1216MF MK268from datasheet "1996 Jul 09",69standard BG L L'70picture carrier 38.90 38.90 33.9571colour 34.47 34.37 38.3872sound 1 33.40 32.40 40.4573sound 2 33.16 - -74NICAM 33.05 33.05 39.8075*/76#define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */77#define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */78#define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */7980/* Control byte */8182#define TUNER_RATIO_MASK 0x06 /* Bit cb1:cb2 */83#define TUNER_RATIO_SELECT_50 0x0084#define TUNER_RATIO_SELECT_32 0x0285#define TUNER_RATIO_SELECT_166 0x0486#define TUNER_RATIO_SELECT_62 0x068788#define TUNER_CHARGE_PUMP 0x40 /* Bit cb6 */8990/* Status byte */9192#define TUNER_POR 0x8093#define TUNER_FL 0x4094#define TUNER_MODE 0x3895#define TUNER_AFC 0x0796#define TUNER_SIGNAL 0x0797#define TUNER_STEREO 0x109899#define TUNER_PLL_LOCKED 0x40100#define TUNER_STEREO_MK3 0x04101102static DEFINE_MUTEX(tuner_simple_list_mutex);103static LIST_HEAD(hybrid_tuner_instance_list);104105struct tuner_simple_priv {106unsigned int nr;107u16 last_div;108109struct tuner_i2c_props i2c_props;110struct list_head hybrid_tuner_instance_list;111112unsigned int type;113struct tunertype *tun;114115u32 frequency;116u32 bandwidth;117};118119/* ---------------------------------------------------------------------- */120121static int tuner_read_status(struct dvb_frontend *fe)122{123struct tuner_simple_priv *priv = fe->tuner_priv;124unsigned char byte;125126if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))127return 0;128129return byte;130}131132static inline int tuner_signal(const int status)133{134return (status & TUNER_SIGNAL) << 13;135}136137static inline int tuner_stereo(const int type, const int status)138{139switch (type) {140case TUNER_PHILIPS_FM1216ME_MK3:141case TUNER_PHILIPS_FM1236_MK3:142case TUNER_PHILIPS_FM1256_IH3:143case TUNER_LG_NTSC_TAPE:144case TUNER_TCL_MF02GIP_5N:145return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);146case TUNER_PHILIPS_FM1216MK5:147return status | TUNER_STEREO;148default:149return status & TUNER_STEREO;150}151}152153static inline int tuner_islocked(const int status)154{155return (status & TUNER_FL);156}157158static inline int tuner_afcstatus(const int status)159{160return (status & TUNER_AFC) - 2;161}162163164static int simple_get_status(struct dvb_frontend *fe, u32 *status)165{166struct tuner_simple_priv *priv = fe->tuner_priv;167int tuner_status;168169if (priv->i2c_props.adap == NULL)170return -EINVAL;171172tuner_status = tuner_read_status(fe);173174*status = 0;175176if (tuner_islocked(tuner_status))177*status = TUNER_STATUS_LOCKED;178if (tuner_stereo(priv->type, tuner_status))179*status |= TUNER_STATUS_STEREO;180181tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status));182183return 0;184}185186static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)187{188struct tuner_simple_priv *priv = fe->tuner_priv;189int signal;190191if (priv->i2c_props.adap == NULL)192return -EINVAL;193194signal = tuner_signal(tuner_read_status(fe));195196*strength = signal;197198tuner_dbg("Signal strength: %d\n", signal);199200return 0;201}202203/* ---------------------------------------------------------------------- */204205static inline char *tuner_param_name(enum param_type type)206{207char *name;208209switch (type) {210case TUNER_PARAM_TYPE_RADIO:211name = "radio";212break;213case TUNER_PARAM_TYPE_PAL:214name = "pal";215break;216case TUNER_PARAM_TYPE_SECAM:217name = "secam";218break;219case TUNER_PARAM_TYPE_NTSC:220name = "ntsc";221break;222case TUNER_PARAM_TYPE_DIGITAL:223name = "digital";224break;225default:226name = "unknown";227break;228}229return name;230}231232static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,233enum param_type desired_type)234{235struct tuner_simple_priv *priv = fe->tuner_priv;236struct tunertype *tun = priv->tun;237int i;238239for (i = 0; i < tun->count; i++)240if (desired_type == tun->params[i].type)241break;242243/* use default tuner params if desired_type not available */244if (i == tun->count) {245tuner_dbg("desired params (%s) undefined for tuner %d\n",246tuner_param_name(desired_type), priv->type);247i = 0;248}249250tuner_dbg("using tuner params #%d (%s)\n", i,251tuner_param_name(tun->params[i].type));252253return &tun->params[i];254}255256static int simple_config_lookup(struct dvb_frontend *fe,257struct tuner_params *t_params,258unsigned *frequency, u8 *config, u8 *cb)259{260struct tuner_simple_priv *priv = fe->tuner_priv;261int i;262263for (i = 0; i < t_params->count; i++) {264if (*frequency > t_params->ranges[i].limit)265continue;266break;267}268if (i == t_params->count) {269tuner_dbg("frequency out of range (%d > %d)\n",270*frequency, t_params->ranges[i - 1].limit);271*frequency = t_params->ranges[--i].limit;272}273*config = t_params->ranges[i].config;274*cb = t_params->ranges[i].cb;275276tuner_dbg("freq = %d.%02d (%d), range = %d, "277"config = 0x%02x, cb = 0x%02x\n",278*frequency / 16, *frequency % 16 * 100 / 16, *frequency,279i, *config, *cb);280281return i;282}283284/* ---------------------------------------------------------------------- */285286static void simple_set_rf_input(struct dvb_frontend *fe,287u8 *config, u8 *cb, unsigned int rf)288{289struct tuner_simple_priv *priv = fe->tuner_priv;290291switch (priv->type) {292case TUNER_PHILIPS_TUV1236D:293switch (rf) {294case 1:295*cb |= 0x08;296break;297default:298*cb &= ~0x08;299break;300}301break;302case TUNER_PHILIPS_FCV1236D:303switch (rf) {304case 1:305*cb |= 0x01;306break;307default:308*cb &= ~0x01;309break;310}311break;312default:313break;314}315}316317static int simple_std_setup(struct dvb_frontend *fe,318struct analog_parameters *params,319u8 *config, u8 *cb)320{321struct tuner_simple_priv *priv = fe->tuner_priv;322int rc;323324/* tv norm specific stuff for multi-norm tuners */325switch (priv->type) {326case TUNER_PHILIPS_SECAM: /* FI1216MF */327/* 0x01 -> ??? no change ??? */328/* 0x02 -> PAL BDGHI / SECAM L */329/* 0x04 -> ??? PAL others / SECAM others ??? */330*cb &= ~0x03;331if (params->std & V4L2_STD_SECAM_L)332/* also valid for V4L2_STD_SECAM */333*cb |= PHILIPS_MF_SET_STD_L;334else if (params->std & V4L2_STD_SECAM_LC)335*cb |= PHILIPS_MF_SET_STD_LC;336else /* V4L2_STD_B|V4L2_STD_GH */337*cb |= PHILIPS_MF_SET_STD_BG;338break;339340case TUNER_TEMIC_4046FM5:341*cb &= ~0x0f;342343if (params->std & V4L2_STD_PAL_BG) {344*cb |= TEMIC_SET_PAL_BG;345346} else if (params->std & V4L2_STD_PAL_I) {347*cb |= TEMIC_SET_PAL_I;348349} else if (params->std & V4L2_STD_PAL_DK) {350*cb |= TEMIC_SET_PAL_DK;351352} else if (params->std & V4L2_STD_SECAM_L) {353*cb |= TEMIC_SET_PAL_L;354355}356break;357358case TUNER_PHILIPS_FQ1216ME:359*cb &= ~0x0f;360361if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {362*cb |= PHILIPS_SET_PAL_BGDK;363364} else if (params->std & V4L2_STD_PAL_I) {365*cb |= PHILIPS_SET_PAL_I;366367} else if (params->std & V4L2_STD_SECAM_L) {368*cb |= PHILIPS_SET_PAL_L;369370}371break;372373case TUNER_PHILIPS_FCV1236D:374/* 0x00 -> ATSC antenna input 1 */375/* 0x01 -> ATSC antenna input 2 */376/* 0x02 -> NTSC antenna input 1 */377/* 0x03 -> NTSC antenna input 2 */378*cb &= ~0x03;379if (!(params->std & V4L2_STD_ATSC))380*cb |= 2;381break;382383case TUNER_MICROTUNE_4042FI5:384/* Set the charge pump for fast tuning */385*config |= TUNER_CHARGE_PUMP;386break;387388case TUNER_PHILIPS_TUV1236D:389{390struct tuner_i2c_props i2c = priv->i2c_props;391/* 0x40 -> ATSC antenna input 1 */392/* 0x48 -> ATSC antenna input 2 */393/* 0x00 -> NTSC antenna input 1 */394/* 0x08 -> NTSC antenna input 2 */395u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};396*cb &= ~0x40;397if (params->std & V4L2_STD_ATSC) {398*cb |= 0x40;399buffer[1] = 0x04;400}401/* set to the correct mode (analog or digital) */402i2c.addr = 0x0a;403rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2);404if (2 != rc)405tuner_warn("i2c i/o error: rc == %d "406"(should be 2)\n", rc);407rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2);408if (2 != rc)409tuner_warn("i2c i/o error: rc == %d "410"(should be 2)\n", rc);411break;412}413}414if (atv_input[priv->nr])415simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);416417return 0;418}419420static int simple_set_aux_byte(struct dvb_frontend *fe, u8 config, u8 aux)421{422struct tuner_simple_priv *priv = fe->tuner_priv;423int rc;424u8 buffer[2];425426buffer[0] = (config & ~0x38) | 0x18;427buffer[1] = aux;428429tuner_dbg("setting aux byte: 0x%02x 0x%02x\n", buffer[0], buffer[1]);430431rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);432if (2 != rc)433tuner_warn("i2c i/o error: rc == %d (should be 2)\n", rc);434435return rc == 2 ? 0 : rc;436}437438static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,439u16 div, u8 config, u8 cb)440{441struct tuner_simple_priv *priv = fe->tuner_priv;442int rc;443444switch (priv->type) {445case TUNER_LG_TDVS_H06XF:446simple_set_aux_byte(fe, config, 0x20);447break;448case TUNER_PHILIPS_FQ1216LME_MK3:449simple_set_aux_byte(fe, config, 0x60); /* External AGC */450break;451case TUNER_MICROTUNE_4042FI5:452{453/* FIXME - this may also work for other tuners */454unsigned long timeout = jiffies + msecs_to_jiffies(1);455u8 status_byte = 0;456457/* Wait until the PLL locks */458for (;;) {459if (time_after(jiffies, timeout))460return 0;461rc = tuner_i2c_xfer_recv(&priv->i2c_props,462&status_byte, 1);463if (1 != rc) {464tuner_warn("i2c i/o read error: rc == %d "465"(should be 1)\n", rc);466break;467}468if (status_byte & TUNER_PLL_LOCKED)469break;470udelay(10);471}472473/* Set the charge pump for optimized phase noise figure */474config &= ~TUNER_CHARGE_PUMP;475buffer[0] = (div>>8) & 0x7f;476buffer[1] = div & 0xff;477buffer[2] = config;478buffer[3] = cb;479tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",480buffer[0], buffer[1], buffer[2], buffer[3]);481482rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);483if (4 != rc)484tuner_warn("i2c i/o error: rc == %d "485"(should be 4)\n", rc);486break;487}488}489490return 0;491}492493static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)494{495struct tuner_simple_priv *priv = fe->tuner_priv;496497switch (priv->type) {498case TUNER_TENA_9533_DI:499case TUNER_YMEC_TVF_5533MF:500tuner_dbg("This tuner doesn't have FM. "501"Most cards have a TEA5767 for FM\n");502return 0;503case TUNER_PHILIPS_FM1216ME_MK3:504case TUNER_PHILIPS_FM1236_MK3:505case TUNER_PHILIPS_FMD1216ME_MK3:506case TUNER_PHILIPS_FMD1216MEX_MK3:507case TUNER_LG_NTSC_TAPE:508case TUNER_PHILIPS_FM1256_IH3:509case TUNER_TCL_MF02GIP_5N:510buffer[3] = 0x19;511break;512case TUNER_PHILIPS_FM1216MK5:513buffer[2] = 0x88;514buffer[3] = 0x09;515break;516case TUNER_TNF_5335MF:517buffer[3] = 0x11;518break;519case TUNER_LG_PAL_FM:520buffer[3] = 0xa5;521break;522case TUNER_THOMSON_DTT761X:523buffer[3] = 0x39;524break;525case TUNER_PHILIPS_FQ1216LME_MK3:526case TUNER_PHILIPS_FQ1236_MK5:527tuner_err("This tuner doesn't have FM\n");528/* Set the low band for sanity, since it covers 88-108 MHz */529buffer[3] = 0x01;530break;531case TUNER_MICROTUNE_4049FM5:532default:533buffer[3] = 0xa4;534break;535}536537return 0;538}539540/* ---------------------------------------------------------------------- */541542static int simple_set_tv_freq(struct dvb_frontend *fe,543struct analog_parameters *params)544{545struct tuner_simple_priv *priv = fe->tuner_priv;546u8 config, cb;547u16 div;548u8 buffer[4];549int rc, IFPCoff, i;550enum param_type desired_type;551struct tuner_params *t_params;552553/* IFPCoff = Video Intermediate Frequency - Vif:554940 =16*58.75 NTSC/J (Japan)555732 =16*45.75 M/N STD556704 =16*44 ATSC (at DVB code)557632 =16*39.50 I U.K.558622.4=16*38.90 B/G D/K I, L STD559592 =16*37.00 D China560590 =16.36.875 B Australia561543.2=16*33.95 L' STD562171.2=16*10.70 FM Radio (at set_radio_freq)563*/564565if (params->std == V4L2_STD_NTSC_M_JP) {566IFPCoff = 940;567desired_type = TUNER_PARAM_TYPE_NTSC;568} else if ((params->std & V4L2_STD_MN) &&569!(params->std & ~V4L2_STD_MN)) {570IFPCoff = 732;571desired_type = TUNER_PARAM_TYPE_NTSC;572} else if (params->std == V4L2_STD_SECAM_LC) {573IFPCoff = 543;574desired_type = TUNER_PARAM_TYPE_SECAM;575} else {576IFPCoff = 623;577desired_type = TUNER_PARAM_TYPE_PAL;578}579580t_params = simple_tuner_params(fe, desired_type);581582i = simple_config_lookup(fe, t_params, ¶ms->frequency,583&config, &cb);584585div = params->frequency + IFPCoff + offset;586587tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "588"Offset=%d.%02d MHz, div=%0d\n",589params->frequency / 16, params->frequency % 16 * 100 / 16,590IFPCoff / 16, IFPCoff % 16 * 100 / 16,591offset / 16, offset % 16 * 100 / 16, div);592593/* tv norm specific stuff for multi-norm tuners */594simple_std_setup(fe, params, &config, &cb);595596if (t_params->cb_first_if_lower_freq && div < priv->last_div) {597buffer[0] = config;598buffer[1] = cb;599buffer[2] = (div>>8) & 0x7f;600buffer[3] = div & 0xff;601} else {602buffer[0] = (div>>8) & 0x7f;603buffer[1] = div & 0xff;604buffer[2] = config;605buffer[3] = cb;606}607priv->last_div = div;608if (t_params->has_tda9887) {609struct v4l2_priv_tun_config tda9887_cfg;610int tda_config = 0;611int is_secam_l = (params->std & (V4L2_STD_SECAM_L |612V4L2_STD_SECAM_LC)) &&613!(params->std & ~(V4L2_STD_SECAM_L |614V4L2_STD_SECAM_LC));615616tda9887_cfg.tuner = TUNER_TDA9887;617tda9887_cfg.priv = &tda_config;618619if (params->std == V4L2_STD_SECAM_LC) {620if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)621tda_config |= TDA9887_PORT1_ACTIVE;622if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)623tda_config |= TDA9887_PORT2_ACTIVE;624} else {625if (t_params->port1_active)626tda_config |= TDA9887_PORT1_ACTIVE;627if (t_params->port2_active)628tda_config |= TDA9887_PORT2_ACTIVE;629}630if (t_params->intercarrier_mode)631tda_config |= TDA9887_INTERCARRIER;632if (is_secam_l) {633if (i == 0 && t_params->default_top_secam_low)634tda_config |= TDA9887_TOP(t_params->default_top_secam_low);635else if (i == 1 && t_params->default_top_secam_mid)636tda_config |= TDA9887_TOP(t_params->default_top_secam_mid);637else if (t_params->default_top_secam_high)638tda_config |= TDA9887_TOP(t_params->default_top_secam_high);639} else {640if (i == 0 && t_params->default_top_low)641tda_config |= TDA9887_TOP(t_params->default_top_low);642else if (i == 1 && t_params->default_top_mid)643tda_config |= TDA9887_TOP(t_params->default_top_mid);644else if (t_params->default_top_high)645tda_config |= TDA9887_TOP(t_params->default_top_high);646}647if (t_params->default_pll_gating_18)648tda_config |= TDA9887_GATING_18;649i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,650&tda9887_cfg);651}652tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",653buffer[0], buffer[1], buffer[2], buffer[3]);654655rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);656if (4 != rc)657tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);658659simple_post_tune(fe, &buffer[0], div, config, cb);660661return 0;662}663664static int simple_set_radio_freq(struct dvb_frontend *fe,665struct analog_parameters *params)666{667struct tunertype *tun;668struct tuner_simple_priv *priv = fe->tuner_priv;669u8 buffer[4];670u16 div;671int rc, j;672struct tuner_params *t_params;673unsigned int freq = params->frequency;674675tun = priv->tun;676677for (j = tun->count-1; j > 0; j--)678if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)679break;680/* default t_params (j=0) will be used if desired type wasn't found */681t_params = &tun->params[j];682683/* Select Radio 1st IF used */684switch (t_params->radio_if) {685case 0: /* 10.7 MHz */686freq += (unsigned int)(10.7*16000);687break;688case 1: /* 33.3 MHz */689freq += (unsigned int)(33.3*16000);690break;691case 2: /* 41.3 MHz */692freq += (unsigned int)(41.3*16000);693break;694default:695tuner_warn("Unsupported radio_if value %d\n",696t_params->radio_if);697return 0;698}699700buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |701TUNER_RATIO_SELECT_50; /* 50 kHz step */702703/* Bandswitch byte */704simple_radio_bandswitch(fe, &buffer[0]);705706/* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps707freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =708freq * (1/800) */709div = (freq + 400) / 800;710711if (t_params->cb_first_if_lower_freq && div < priv->last_div) {712buffer[0] = buffer[2];713buffer[1] = buffer[3];714buffer[2] = (div>>8) & 0x7f;715buffer[3] = div & 0xff;716} else {717buffer[0] = (div>>8) & 0x7f;718buffer[1] = div & 0xff;719}720721tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",722buffer[0], buffer[1], buffer[2], buffer[3]);723priv->last_div = div;724725if (t_params->has_tda9887) {726int config = 0;727struct v4l2_priv_tun_config tda9887_cfg;728729tda9887_cfg.tuner = TUNER_TDA9887;730tda9887_cfg.priv = &config;731732if (t_params->port1_active &&733!t_params->port1_fm_high_sensitivity)734config |= TDA9887_PORT1_ACTIVE;735if (t_params->port2_active &&736!t_params->port2_fm_high_sensitivity)737config |= TDA9887_PORT2_ACTIVE;738if (t_params->intercarrier_mode)739config |= TDA9887_INTERCARRIER;740/* if (t_params->port1_set_for_fm_mono)741config &= ~TDA9887_PORT1_ACTIVE;*/742if (t_params->fm_gain_normal)743config |= TDA9887_GAIN_NORMAL;744if (t_params->radio_if == 2)745config |= TDA9887_RIF_41_3;746i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,747&tda9887_cfg);748}749rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);750if (4 != rc)751tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);752753return 0;754}755756static int simple_set_params(struct dvb_frontend *fe,757struct analog_parameters *params)758{759struct tuner_simple_priv *priv = fe->tuner_priv;760int ret = -EINVAL;761762if (priv->i2c_props.adap == NULL)763return -EINVAL;764765switch (params->mode) {766case V4L2_TUNER_RADIO:767ret = simple_set_radio_freq(fe, params);768priv->frequency = params->frequency * 125 / 2;769break;770case V4L2_TUNER_ANALOG_TV:771case V4L2_TUNER_DIGITAL_TV:772ret = simple_set_tv_freq(fe, params);773priv->frequency = params->frequency * 62500;774break;775}776priv->bandwidth = 0;777778return ret;779}780781static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,782const struct dvb_frontend_parameters *params)783{784struct tuner_simple_priv *priv = fe->tuner_priv;785786switch (priv->type) {787case TUNER_PHILIPS_FMD1216ME_MK3:788case TUNER_PHILIPS_FMD1216MEX_MK3:789if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&790params->frequency >= 158870000)791buf[3] |= 0x08;792break;793case TUNER_PHILIPS_TD1316:794/* determine band */795buf[3] |= (params->frequency < 161000000) ? 1 :796(params->frequency < 444000000) ? 2 : 4;797798/* setup PLL filter */799if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)800buf[3] |= 1 << 3;801break;802case TUNER_PHILIPS_TUV1236D:803case TUNER_PHILIPS_FCV1236D:804{805unsigned int new_rf;806807if (dtv_input[priv->nr])808new_rf = dtv_input[priv->nr];809else810switch (params->u.vsb.modulation) {811case QAM_64:812case QAM_256:813new_rf = 1;814break;815case VSB_8:816default:817new_rf = 0;818break;819}820simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);821break;822}823default:824break;825}826}827828static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,829const struct dvb_frontend_parameters *params)830{831/* This function returns the tuned frequency on success, 0 on error */832struct tuner_simple_priv *priv = fe->tuner_priv;833struct tunertype *tun = priv->tun;834static struct tuner_params *t_params;835u8 config, cb;836u32 div;837int ret;838unsigned frequency = params->frequency / 62500;839840if (!tun->stepsize) {841/* tuner-core was loaded before the digital tuner was842* configured and somehow picked the wrong tuner type */843tuner_err("attempt to treat tuner %d (%s) as digital tuner "844"without stepsize defined.\n",845priv->type, priv->tun->name);846return 0; /* failure */847}848849t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);850ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);851if (ret < 0)852return 0; /* failure */853854div = ((frequency + t_params->iffreq) * 62500 + offset +855tun->stepsize/2) / tun->stepsize;856857buf[0] = div >> 8;858buf[1] = div & 0xff;859buf[2] = config;860buf[3] = cb;861862simple_set_dvb(fe, buf, params);863864tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",865tun->name, div, buf[0], buf[1], buf[2], buf[3]);866867/* calculate the frequency we set it to */868return (div * tun->stepsize) - t_params->iffreq;869}870871static int simple_dvb_calc_regs(struct dvb_frontend *fe,872struct dvb_frontend_parameters *params,873u8 *buf, int buf_len)874{875struct tuner_simple_priv *priv = fe->tuner_priv;876u32 frequency;877878if (buf_len < 5)879return -EINVAL;880881frequency = simple_dvb_configure(fe, buf+1, params);882if (frequency == 0)883return -EINVAL;884885buf[0] = priv->i2c_props.addr;886887priv->frequency = frequency;888priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?889params->u.ofdm.bandwidth : 0;890891return 5;892}893894static int simple_dvb_set_params(struct dvb_frontend *fe,895struct dvb_frontend_parameters *params)896{897struct tuner_simple_priv *priv = fe->tuner_priv;898u32 prev_freq, prev_bw;899int ret;900u8 buf[5];901902if (priv->i2c_props.adap == NULL)903return -EINVAL;904905prev_freq = priv->frequency;906prev_bw = priv->bandwidth;907908ret = simple_dvb_calc_regs(fe, params, buf, 5);909if (ret != 5)910goto fail;911912/* put analog demod in standby when tuning digital */913if (fe->ops.analog_ops.standby)914fe->ops.analog_ops.standby(fe);915916if (fe->ops.i2c_gate_ctrl)917fe->ops.i2c_gate_ctrl(fe, 1);918919/* buf[0] contains the i2c address, but *920* we already have it in i2c_props.addr */921ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4);922if (ret != 4)923goto fail;924925return 0;926fail:927/* calc_regs sets frequency and bandwidth. if we failed, unset them */928priv->frequency = prev_freq;929priv->bandwidth = prev_bw;930931return ret;932}933934static int simple_init(struct dvb_frontend *fe)935{936struct tuner_simple_priv *priv = fe->tuner_priv;937938if (priv->i2c_props.adap == NULL)939return -EINVAL;940941if (priv->tun->initdata) {942int ret;943944if (fe->ops.i2c_gate_ctrl)945fe->ops.i2c_gate_ctrl(fe, 1);946947ret = tuner_i2c_xfer_send(&priv->i2c_props,948priv->tun->initdata + 1,949priv->tun->initdata[0]);950if (ret != priv->tun->initdata[0])951return ret;952}953954return 0;955}956957static int simple_sleep(struct dvb_frontend *fe)958{959struct tuner_simple_priv *priv = fe->tuner_priv;960961if (priv->i2c_props.adap == NULL)962return -EINVAL;963964if (priv->tun->sleepdata) {965int ret;966967if (fe->ops.i2c_gate_ctrl)968fe->ops.i2c_gate_ctrl(fe, 1);969970ret = tuner_i2c_xfer_send(&priv->i2c_props,971priv->tun->sleepdata + 1,972priv->tun->sleepdata[0]);973if (ret != priv->tun->sleepdata[0])974return ret;975}976977return 0;978}979980static int simple_release(struct dvb_frontend *fe)981{982struct tuner_simple_priv *priv = fe->tuner_priv;983984mutex_lock(&tuner_simple_list_mutex);985986if (priv)987hybrid_tuner_release_state(priv);988989mutex_unlock(&tuner_simple_list_mutex);990991fe->tuner_priv = NULL;992993return 0;994}995996static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)997{998struct tuner_simple_priv *priv = fe->tuner_priv;999*frequency = priv->frequency;1000return 0;1001}10021003static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)1004{1005struct tuner_simple_priv *priv = fe->tuner_priv;1006*bandwidth = priv->bandwidth;1007return 0;1008}10091010static struct dvb_tuner_ops simple_tuner_ops = {1011.init = simple_init,1012.sleep = simple_sleep,1013.set_analog_params = simple_set_params,1014.set_params = simple_dvb_set_params,1015.calc_regs = simple_dvb_calc_regs,1016.release = simple_release,1017.get_frequency = simple_get_frequency,1018.get_bandwidth = simple_get_bandwidth,1019.get_status = simple_get_status,1020.get_rf_strength = simple_get_rf_strength,1021};10221023struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,1024struct i2c_adapter *i2c_adap,1025u8 i2c_addr,1026unsigned int type)1027{1028struct tuner_simple_priv *priv = NULL;1029int instance;10301031if (type >= tuner_count) {1032printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",1033__func__, type, tuner_count-1);1034return NULL;1035}10361037/* If i2c_adap is set, check that the tuner is at the correct address.1038* Otherwise, if i2c_adap is NULL, the tuner will be programmed directly1039* by the digital demod via calc_regs.1040*/1041if (i2c_adap != NULL) {1042u8 b[1];1043struct i2c_msg msg = {1044.addr = i2c_addr, .flags = I2C_M_RD,1045.buf = b, .len = 1,1046};10471048if (fe->ops.i2c_gate_ctrl)1049fe->ops.i2c_gate_ctrl(fe, 1);10501051if (1 != i2c_transfer(i2c_adap, &msg, 1))1052printk(KERN_WARNING "tuner-simple %d-%04x: "1053"unable to probe %s, proceeding anyway.",1054i2c_adapter_id(i2c_adap), i2c_addr,1055tuners[type].name);10561057if (fe->ops.i2c_gate_ctrl)1058fe->ops.i2c_gate_ctrl(fe, 0);1059}10601061mutex_lock(&tuner_simple_list_mutex);10621063instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,1064hybrid_tuner_instance_list,1065i2c_adap, i2c_addr,1066"tuner-simple");1067switch (instance) {1068case 0:1069mutex_unlock(&tuner_simple_list_mutex);1070return NULL;1071case 1:1072fe->tuner_priv = priv;10731074priv->type = type;1075priv->tun = &tuners[type];1076priv->nr = simple_devcount++;1077break;1078default:1079fe->tuner_priv = priv;1080break;1081}10821083mutex_unlock(&tuner_simple_list_mutex);10841085memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,1086sizeof(struct dvb_tuner_ops));10871088if (type != priv->type)1089tuner_warn("couldn't set type to %d. Using %d (%s) instead\n",1090type, priv->type, priv->tun->name);1091else1092tuner_info("type set to %d (%s)\n",1093priv->type, priv->tun->name);10941095if ((debug) || ((atv_input[priv->nr] > 0) ||1096(dtv_input[priv->nr] > 0))) {1097if (0 == atv_input[priv->nr])1098tuner_info("tuner %d atv rf input will be "1099"autoselected\n", priv->nr);1100else1101tuner_info("tuner %d atv rf input will be "1102"set to input %d (insmod option)\n",1103priv->nr, atv_input[priv->nr]);1104if (0 == dtv_input[priv->nr])1105tuner_info("tuner %d dtv rf input will be "1106"autoselected\n", priv->nr);1107else1108tuner_info("tuner %d dtv rf input will be "1109"set to input %d (insmod option)\n",1110priv->nr, dtv_input[priv->nr]);1111}11121113strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,1114sizeof(fe->ops.tuner_ops.info.name));11151116return fe;1117}1118EXPORT_SYMBOL_GPL(simple_tuner_attach);11191120MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");1121MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");1122MODULE_LICENSE("GPL");11231124/*1125* Overrides for Emacs so that we follow Linus's tabbing style.1126* ---------------------------------------------------------------------------1127* Local variables:1128* c-basic-offset: 81129* End:1130*/113111321133