Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/media/tuners/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 12 kB image not shown  

Impressum mt2060.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
*
 *  Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
 *
 *  Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
 */


/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/dvb/frontend.h>
#include <linux/i2c.h>
#include <linux/slab.h>

#include <media/dvb_frontend.h>

#include "mt2060.h"
#include "mt2060_priv.h"

static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
structmt2060_priv*privfe-;
#define dprintkfrequencypriv-;

// Reads a single register
staticint mt2060_readreg(  *,  reg u8val
{
 struct ;
  { .
  {java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 };
 int  ret
 u8 *b goto;

 b java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
  !bjava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
  return -ENOMEM;

 b[0] = reg;
 b[1] = 0;

 msg[0].buf = b;
 msg[1].buf = b + 1;

 if (i2c_transfer(priv->i2c, msg, 2) != 2) {
  printk(KERN_WARNING "mt2060 I2C read failed\n");
    -;
 }
 *val
 kfree:

  rc;
}

// Writes a single register
staticint (struct  *rivu8regu8val
{
  >.2( ) /* close i2c_gate */
  .addr = priv->cfg->i2c_address, .flags = 0, .len = 2
 };
 u8 *buf;
 int rc = 0;

 buf = kmalloc
 if  return ret;
  return-;

 buf0 = ;
 buf[1] = val

 msgstatic intmt2060_sleep(struct  *fe

 if (i2c_transfer
  printk structstruct mt2060_priv *riv=fe->;
  int ret
 }
 kfree(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 return rc;
}

// Writes a set of consecutive registers
staticint mt2060_writeregs(struct mt2060_priv*riv,8 *, u8len
{
 int  (priv->cfg->clock_out<6  0);
 u8 *xfer_buf;
 int rc = 0;
 struct i2c_msg msg = {
  .addrif(ret)
 }gotoerr_i2c_gate_ctrl

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  (xfer_buf
 java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0

 msg.buf

rem = len - 1;rem>0 rem - priv->i2c_max_regs){
 fe->=NULL
  msg.len java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  [0]=buf[0 +  1  rem
  memcpy(&xfer_buf[1], &buf[1 + len - 1 - rem], val_len);

  if (i2c_transfer(priv->i2c, &msg, 1 .info = {{
  printkKERN_WARNING" I2Cwrite failed(len=%in,val_len;
  =EREMOTEIO
    6* MHz,
  }
 .frequency_step_hz=5 *kHz

 kfree(fer_buf
 return rcjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}sleep          t2060_sleep

// Initialisation sequences
// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49
staticu8 mt2060_config1]={
 REG_LO1C1get_frequency mt2060_get_frequency
 0x3F .et_if_frequency=mt2060_get_if_frequency
};

// FMCG=2, GP2=0, GP1=0
static u8
 REG_MISC_CTRL,
 0x20,0E x300, x80 0xff0, x2c 0x42
};

//  VGAG=3, V1CSE=1

#ifdef  MT2060_SPURCHECK
/* The function below calculates the frequency offset between the output frequency if2struct dvb_frontend  (struct  fe  i2c_adapter *i2c,  mt2060_config cfg u16if1
 and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */

staticint(u32 o1u32lo2 )
{
 int I,J;
 int dia,diamin,diff;
 diamin=1000000;
 for (I = 1; I < 10; I++) {
  J = ((2*I*lo1)/lo2+1)/2;
  diff = I ( ==NULL
  if    NULL
  diajava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
if dia )dia-ia
 diamin dia diamin;
 }
 return diamin>  ;
}

if(>.)

/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */priv,&)! ){
  ;
{
 u32
 intIJ;
 I=0;
 J=1000;

 Spur=mt2060_spurcalc NULL
  Spur )java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
  /* Potential spurs detected */
 dprintk"Spursbefore :f_lo1 d f_lo2 d kHz"java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
   if>psi2c_gate_ctrl)
  fe-opsic_gate_ctrl(fe 0 /* close i2c_gate */
  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
EXPORT_SYMBOL_GPL();

 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   J=-J; I=-I; Spur=Sp2
  } 
   Spur=Sp1 dvb_frontend*;

 mt2060_priv **ev
  int ret;
 u8;
  }
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   (int)(lo1+I),(int)(lo2+I));
 }
 return I;
}
#endif

#define IF2  36150       // IF2 frequency = 36.150 MHz
#define FREF 16000       // Quartz oscillator 16 MHz

static int mt2060_set_params(struct dvb_frontend*e)
{
 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 struct mt2060_priv *priv;
 inti0
 u32ret=-EINVAL
 u8 got ;
 u32
 
 u8b[8]
2 ;

 priv >;

 if1 = priv->if1_freq;
 b[0] = REG_LO1B1;
 b[1] = 0xFF;

 if (fe->ops.i2c_gate_ctrl
  >.2(fe1 /* open i2c_gate */

 mt2060_writeregs(priv,>.  pdata-;

 freq = c->frequency>c =client-;

 = +  *00java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
 f_lo1(f_lo1  25) 20java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
 f_lo2   -freq- IF2;
 // From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise
 f_lo2lo2  (lo2+2) /0  5
  err

java.lang.NullPointerException
 / LO-related spurs detection and correction
 num1   = mt2060_spurcheck ) {
 f_lo1 et=-;
 f_lo2 gotoerr
#endifjava.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 //Frequency LO1 = 16MHz * (DIV1 + NUM1/64 )  mt2060_writeregdev REG_MISC_CTRL 0);
     (/)
 div1err
 mt2060_calibrate)

 Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 )
 num2 = f_lo2 * 64  )
 div2 = num2 / 8192;
 num2=0;

 (client-,"Microtunesuccessfully \)java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
>  ;
 if (freq <= 26000client)
 if (freq ;
 :
 dev_dbgclient->ev"failed%n" ret
  freq< 500)   x50else
 if (freq <= 645000) lnaband = 0x40; else
  freq<= 730000) lnaband = 0x30; else
 if (freq <= 810000 lnaband = 00; else lnaband=0x10;

 [0java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 1
 b[1] = lnaband{"mt2060" ,
 b[{java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
 b3  num2 x0F  |((num13 < )java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
 b[4 = num2>>4java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
 []=(num2>1)  )|( <<1;

dprintkdMHz))java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
dprintkPLL=dkHz%  =dkHz,int,(),(ntf_lo2
 dprintk("PLL .remove = mt2060_remove
 dprintk =mt2060_id_table

 mt2060_writeregs(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 //Waits for pll lock or timeout
 i = 0;
 do {
  mt2060_readreg(priv,REG_LO_STATUS,b);
  if (MODULE_DESCRIPTION"icrotune MT2060s driver";
   break;
  msleep(4);
  i++;
   (i10)java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16

 if (fe->ops.i2c_gate_ctrl)
  fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */

 return 0;
}

static void mt2060_calibrate(struct mt2060_priv *priv)
{
 u8 b = 0;
 int i = 0;

 if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1)))
  return;
 if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
  return;

 /* initialize the clock output */
 mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);

 do {
  b |= (1 << 6); // FM1SS;
  mt2060_writereg(priv, REG_LO2C1,b);
  msleep(20);

  if (i == 0) {
   b |= (1 << 7); // FM1CA;
   mt2060_writereg(priv, REG_LO2C1,b);
   b &= ~(1 << 7); // FM1CA;
   msleep(20);
  }

  b &= ~(1 << 6); // FM1SS
  mt2060_writereg(priv, REG_LO2C1,b);

  msleep(20);
  i++;
 } while (i < 9);

 i = 0;
 while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
  msleep(20);

 if (i <= 10) {
  mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
  dprintk("calibration was successful: %d", (int)priv->fmfreq);
 } else
  dprintk("FMCAL timed out");
}

static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
 struct mt2060_priv *priv = fe->tuner_priv;
 *frequency = priv->frequency;
 return 0;
}

static int mt2060_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
{
 *frequency = IF2 * 1000;
 return 0;
}

static int mt2060_init(struct dvb_frontend *fe)
{
 struct mt2060_priv *priv = fe->tuner_priv;
 int ret;

 if (fe->ops.i2c_gate_ctrl)
  fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */

 if (priv->sleep) {
  ret = mt2060_writereg(priv, REG_MISC_CTRL, 0x20);
  if (ret)
   goto err_i2c_gate_ctrl;
 }

 ret = mt2060_writereg(priv, REG_VGAG,
         (priv->cfg->clock_out << 6) | 0x33);

err_i2c_gate_ctrl:
 if (fe->ops.i2c_gate_ctrl)
  fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */

 return ret;
}

static int mt2060_sleep(struct dvb_frontend *fe)
{
 struct mt2060_priv *priv = fe->tuner_priv;
 int ret;

 if (fe->ops.i2c_gate_ctrl)
  fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */

 ret = mt2060_writereg(priv, REG_VGAG,
         (priv->cfg->clock_out << 6) | 0x30);
 if (ret)
  goto err_i2c_gate_ctrl;

 if (priv->sleep)
  ret = mt2060_writereg(priv, REG_MISC_CTRL, 0xe8);

err_i2c_gate_ctrl:
 if (fe->ops.i2c_gate_ctrl)
  fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */

 return ret;
}

static void mt2060_release(struct dvb_frontend *fe)
{
 kfree(fe->tuner_priv);
 fe->tuner_priv = NULL;
}

static const struct dvb_tuner_ops mt2060_tuner_ops = {
 .info = {
  .name              = "Microtune MT2060",
  .frequency_min_hz  =  48 * MHz,
  .frequency_max_hz  = 860 * MHz,
  .frequency_step_hz =  50 * kHz,
 },

 .release       = mt2060_release,

 .init          = mt2060_init,
 .sleep         = mt2060_sleep,

 .set_params    = mt2060_set_params,
 .get_frequency = mt2060_get_frequency,
 .get_if_frequency = mt2060_get_if_frequency,
};

/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
{
 struct mt2060_priv *priv = NULL;
 u8 id = 0;

 priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL);
 if (priv == NULL)
  return NULL;

 priv->cfg      = cfg;
 priv->i2c      = i2c;
 priv->if1_freq = if1;
 priv->i2c_max_regs = ~0;

 if (fe->ops.i2c_gate_ctrl)
  fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */

 if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
  kfree(priv);
  return NULL;
 }

 if (id != PART_REV) {
  kfree(priv);
  return NULL;
 }
 printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
 memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));

 fe->tuner_priv = priv;

 mt2060_calibrate(priv);

 if (fe->ops.i2c_gate_ctrl)
  fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */

 return fe;
}
EXPORT_SYMBOL_GPL(mt2060_attach);

static int mt2060_probe(struct i2c_client *client)
{
 struct mt2060_platform_data *pdata = client->dev.platform_data;
 struct dvb_frontend *fe;
 struct mt2060_priv *dev;
 int ret;
 u8 chip_id;

 dev_dbg(&client->dev, "\n");

 if (!pdata) {
  dev_err(&client->dev, "Cannot proceed without platform data\n");
  ret = -EINVAL;
  goto err;
 }

 dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
 if (!dev) {
  ret = -ENOMEM;
  goto err;
 }

 fe = pdata->dvb_frontend;
 dev->config.i2c_address = client->addr;
 dev->config.clock_out = pdata->clock_out;
 dev->cfg = &dev->config;
 dev->i2c = client->adapter;
 dev->if1_freq = pdata->if1 ? pdata->if1 : 1220;
 dev->client = client;
 dev->i2c_max_regs = pdata->i2c_write_max ? pdata->i2c_write_max - 1 : ~0;
 dev->sleep = true;

 ret = mt2060_readreg(dev, REG_PART_REV, &chip_id);
 if (ret) {
  ret = -ENODEV;
  goto err;
 }

 dev_dbg(&client->dev, "chip id=%02x\n", chip_id);

 if (chip_id != PART_REV) {
  ret = -ENODEV;
  goto err;
 }

 /* Power on, calibrate, sleep */
 ret = mt2060_writereg(dev, REG_MISC_CTRL, 0x20);
 if (ret)
  goto err;
 mt2060_calibrate(dev);
 ret = mt2060_writereg(dev, REG_MISC_CTRL, 0xe8);
 if (ret)
  goto err;

 dev_info(&client->dev, "Microtune MT2060 successfully identified\n");
 memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(fe->ops.tuner_ops));
 fe->ops.tuner_ops.release = NULL;
 fe->tuner_priv = dev;
 i2c_set_clientdata(client, dev);

 return 0;
err:
 dev_dbg(&client->dev, "failed=%d\n", ret);
 return ret;
}

static void mt2060_remove(struct i2c_client *client)
{
 dev_dbg(&client->dev, "\n");
}

static const struct i2c_device_id mt2060_id_table[] = {
 { "mt2060" },
 {}
};
MODULE_DEVICE_TABLE(i2c, mt2060_id_table);

static struct i2c_driver mt2060_driver = {
 .driver = {
  .name = "mt2060",
  .suppress_bind_attrs = true,
 },
 .probe  = mt2060_probe,
 .remove  = mt2060_remove,
 .id_table = mt2060_id_table,
};

module_i2c_driver(mt2060_driver);

MODULE_AUTHOR("Olivier DANET");
MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver");
MODULE_LICENSE("GPL");

Messung V0.5
C=96 H=92 G=93

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.4Bemerkung:  ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.