Lines Matching +full:gain +full:- +full:offset
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 Montage Technology TS2020 - Silicon Tuner driver
4 Copyright (C) 2009-2012 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
6 Copyright (C) 2009-2012 TurboSight.com
49 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_release()
50 struct i2c_client *client = priv->client; in ts2020_release()
52 dev_dbg(&client->dev, "\n"); in ts2020_release()
59 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_sleep()
63 if (priv->tuner == TS2020_M88TS2020) in ts2020_sleep()
68 ret = regmap_write(priv->regmap, u8tmp, 0x00); in ts2020_sleep()
73 if (!priv->dont_poll) in ts2020_sleep()
74 cancel_delayed_work_sync(&priv->stat_work); in ts2020_sleep()
80 struct dtv_frontend_properties *c = &fe->dtv_property_cache; in ts2020_init()
81 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_init()
85 if (priv->tuner == TS2020_M88TS2020) { in ts2020_init()
86 regmap_write(priv->regmap, 0x42, 0x73); in ts2020_init()
87 regmap_write(priv->regmap, 0x05, priv->clk_out_div); in ts2020_init()
88 regmap_write(priv->regmap, 0x20, 0x27); in ts2020_init()
89 regmap_write(priv->regmap, 0x07, 0x02); in ts2020_init()
90 regmap_write(priv->regmap, 0x11, 0xff); in ts2020_init()
91 regmap_write(priv->regmap, 0x60, 0xf9); in ts2020_init()
92 regmap_write(priv->regmap, 0x08, 0x01); in ts2020_init()
93 regmap_write(priv->regmap, 0x00, 0x41); in ts2020_init()
109 regmap_write(priv->regmap, 0x00, 0x01); in ts2020_init()
110 regmap_write(priv->regmap, 0x00, 0x03); in ts2020_init()
112 switch (priv->clk_out) { in ts2020_init()
118 regmap_write(priv->regmap, 0x05, priv->clk_out_div); in ts2020_init()
128 regmap_write(priv->regmap, 0x42, u8tmp); in ts2020_init()
130 if (priv->loop_through) in ts2020_init()
135 regmap_write(priv->regmap, 0x62, u8tmp); in ts2020_init()
138 regmap_write(priv->regmap, reg_vals[i].reg, in ts2020_init()
143 c->strength.len = 1; in ts2020_init()
144 c->strength.stat[0].scale = FE_SCALE_DECIBEL; in ts2020_init()
145 c->strength.stat[0].uvalue = 0; in ts2020_init()
148 ts2020_stat_work(&priv->stat_work.work); in ts2020_init()
152 static int ts2020_tuner_gate_ctrl(struct dvb_frontend *fe, u8 offset) in ts2020_tuner_gate_ctrl() argument
154 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_tuner_gate_ctrl()
156 ret = regmap_write(priv->regmap, 0x51, 0x1f - offset); in ts2020_tuner_gate_ctrl()
157 ret |= regmap_write(priv->regmap, 0x51, 0x1f); in ts2020_tuner_gate_ctrl()
158 ret |= regmap_write(priv->regmap, 0x50, offset); in ts2020_tuner_gate_ctrl()
159 ret |= regmap_write(priv->regmap, 0x50, 0x00); in ts2020_tuner_gate_ctrl()
166 struct ts2020_priv *dev = fe->tuner_priv; in ts2020_set_tuner_rf()
170 ret = regmap_read(dev->regmap, 0x3d, &utmp); in ts2020_set_tuner_rf()
182 regmap_write(dev->regmap, 0x60, utmp); in ts2020_set_tuner_rf()
190 struct dtv_frontend_properties *c = &fe->dtv_property_cache; in ts2020_set_params()
191 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_set_params()
198 unsigned int frequency_khz = c->frequency; in ts2020_set_params()
201 * Integer-N PLL synthesizer in ts2020_set_params()
202 * kHz is used for all calculations to keep calculations within 32-bit in ts2020_set_params()
208 if (frequency_khz < priv->frequency_div) { in ts2020_set_params()
219 priv->frequency_khz = pll_n * f_ref_khz / div_ref / div_out; in ts2020_set_params()
221 pr_debug("frequency=%u offset=%d f_vco_khz=%u pll_n=%u div_ref=%u div_out=%u\n", in ts2020_set_params()
222 priv->frequency_khz, priv->frequency_khz - c->frequency, in ts2020_set_params()
225 if (priv->tuner == TS2020_M88TS2020) { in ts2020_set_params()
228 ret = regmap_write(priv->regmap, 0x10, reg10); in ts2020_set_params()
232 ret = regmap_write(priv->regmap, 0x10, reg10); in ts2020_set_params()
233 ret |= regmap_write(priv->regmap, 0x11, 0x40); in ts2020_set_params()
236 u16tmp = pll_n - 1024; in ts2020_set_params()
239 buf[2] = div_ref - 8; in ts2020_set_params()
241 ret |= regmap_write(priv->regmap, 0x01, buf[0]); in ts2020_set_params()
242 ret |= regmap_write(priv->regmap, 0x02, buf[1]); in ts2020_set_params()
243 ret |= regmap_write(priv->regmap, 0x03, buf[2]); in ts2020_set_params()
247 return -ENODEV; in ts2020_set_params()
252 if (priv->tuner == TS2020_M88TS2020) in ts2020_set_params()
256 ret |= regmap_write(priv->regmap, 0x04, gdiv28 & 0xff); in ts2020_set_params()
259 return -ENODEV; in ts2020_set_params()
261 if (priv->tuner == TS2020_M88TS2022) { in ts2020_set_params()
262 ret = regmap_write(priv->regmap, 0x25, 0x00); in ts2020_set_params()
263 ret |= regmap_write(priv->regmap, 0x27, 0x70); in ts2020_set_params()
264 ret |= regmap_write(priv->regmap, 0x41, 0x09); in ts2020_set_params()
265 ret |= regmap_write(priv->regmap, 0x08, 0x0b); in ts2020_set_params()
267 return -ENODEV; in ts2020_set_params()
270 regmap_read(priv->regmap, 0x26, &utmp); in ts2020_set_params()
273 f3db = (c->bandwidth_hz / 1000 / 2) + 2000; in ts2020_set_params()
302 ret = regmap_write(priv->regmap, 0x04, lpf_mxdiv); in ts2020_set_params()
303 ret |= regmap_write(priv->regmap, 0x06, nlpf); in ts2020_set_params()
311 return (ret < 0) ? -EINVAL : 0; in ts2020_set_params()
316 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_get_frequency()
318 *frequency = priv->frequency_khz; in ts2020_get_frequency()
324 *frequency = 0; /* Zero-IF */ in ts2020_get_if_frequency()
329 * Get the tuner gain.
330 * @fe: The front end for which we're determining the gain
331 * @v_agc: The voltage of the AGC from the demodulator (0-2600mV)
332 * @_gain: Where to store the gain (in 0.001dB units)
339 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_read_tuner_gain()
344 /* Read the RF gain */ in ts2020_read_tuner_gain()
345 ret = regmap_read(priv->regmap, 0x3d, &utmp); in ts2020_read_tuner_gain()
350 /* Read the baseband gain */ in ts2020_read_tuner_gain()
351 ret = regmap_read(priv->regmap, 0x21, &utmp); in ts2020_read_tuner_gain()
356 switch (priv->tuner) { in ts2020_read_tuner_gain()
362 *_gain = -((__s64)gain1 * 2330 + in ts2020_read_tuner_gain()
366 /* gain in range -19600 to -116850 in units of 0.001dB */ in ts2020_read_tuner_gain()
370 ret = regmap_read(priv->regmap, 0x66, &utmp); in ts2020_read_tuner_gain()
380 *_gain = -((__s64)gain1 * 2650 + in ts2020_read_tuner_gain()
383 v_agc * 176 / 100 * 10 - in ts2020_read_tuner_gain()
385 /* gain in range -47320 to -158950 in units of 0.001dB */ in ts2020_read_tuner_gain()
394 * tuner gain.
398 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_get_tuner_gain()
403 if (priv->get_agc_pwm) { in ts2020_get_tuner_gain()
404 ret = priv->get_agc_pwm(fe, &agc_pwm); in ts2020_get_tuner_gain()
408 switch (priv->tuner) { in ts2020_get_tuner_gain()
410 v_agc = (int)agc_pwm * 20 - 1166; in ts2020_get_tuner_gain()
413 v_agc = (int)agc_pwm * 16 - 670; in ts2020_get_tuner_gain()
431 struct i2c_client *client = priv->client; in ts2020_stat_work()
432 struct dtv_frontend_properties *c = &priv->fe->dtv_property_cache; in ts2020_stat_work()
435 dev_dbg(&client->dev, "\n"); in ts2020_stat_work()
437 ret = ts2020_get_tuner_gain(priv->fe, &c->strength.stat[0].svalue); in ts2020_stat_work()
441 c->strength.stat[0].scale = FE_SCALE_DECIBEL; in ts2020_stat_work()
443 if (!priv->dont_poll) in ts2020_stat_work()
444 schedule_delayed_work(&priv->stat_work, msecs_to_jiffies(2000)); in ts2020_stat_work()
447 dev_dbg(&client->dev, "failed=%d\n", ret); in ts2020_stat_work()
456 struct dtv_frontend_properties *c = &fe->dtv_property_cache; in ts2020_read_signal_strength()
457 struct ts2020_priv *priv = fe->tuner_priv; in ts2020_read_signal_strength()
459 __s64 gain; in ts2020_read_signal_strength() local
461 if (priv->dont_poll) in ts2020_read_signal_strength()
462 ts2020_stat_work(&priv->stat_work.work); in ts2020_read_signal_strength()
464 if (c->strength.stat[0].scale == FE_SCALE_NOT_AVAILABLE) { in ts2020_read_signal_strength()
469 gain = c->strength.stat[0].svalue; in ts2020_read_signal_strength()
471 /* Calculate the signal strength based on the total gain of the tuner */ in ts2020_read_signal_strength()
472 if (gain < -85000) in ts2020_read_signal_strength()
475 else if (gain < -65000) in ts2020_read_signal_strength()
476 /* 0% - 60%: weak signal */ in ts2020_read_signal_strength()
477 strength = 0 + div64_s64((85000 + gain) * 3, 1000); in ts2020_read_signal_strength()
478 else if (gain < -45000) in ts2020_read_signal_strength()
479 /* 60% - 90%: normal signal */ in ts2020_read_signal_strength()
480 strength = 60 + div64_s64((65000 + gain) * 3, 2000); in ts2020_read_signal_strength()
482 /* 90% - 99%: strong signal */ in ts2020_read_signal_strength()
483 strength = 90 + div64_s64((45000 + gain), 5000); in ts2020_read_signal_strength()
520 board_info.addr = config->tuner_address; in ts2020_attach()
533 * serialize whole open / I2C-operation / close sequence at the same.
539 mutex_lock(&dev->regmap_mutex); in ts2020_regmap_lock()
540 if (dev->fe->ops.i2c_gate_ctrl) in ts2020_regmap_lock()
541 dev->fe->ops.i2c_gate_ctrl(dev->fe, 1); in ts2020_regmap_lock()
548 if (dev->fe->ops.i2c_gate_ctrl) in ts2020_regmap_unlock()
549 dev->fe->ops.i2c_gate_ctrl(dev->fe, 0); in ts2020_regmap_unlock()
550 mutex_unlock(&dev->regmap_mutex); in ts2020_regmap_unlock()
555 struct ts2020_config *pdata = client->dev.platform_data; in ts2020_probe()
564 dev_err(&client->dev, "platform data is mandatory\n"); in ts2020_probe()
565 return -EINVAL; in ts2020_probe()
568 fe = pdata->fe; in ts2020_probe()
571 ret = -ENOMEM; in ts2020_probe()
576 mutex_init(&dev->regmap_mutex); in ts2020_probe()
577 dev->regmap_config.reg_bits = 8; in ts2020_probe()
578 dev->regmap_config.val_bits = 8; in ts2020_probe()
579 dev->regmap_config.lock = ts2020_regmap_lock; in ts2020_probe()
580 dev->regmap_config.unlock = ts2020_regmap_unlock; in ts2020_probe()
581 dev->regmap_config.lock_arg = dev; in ts2020_probe()
582 dev->regmap = regmap_init_i2c(client, &dev->regmap_config); in ts2020_probe()
583 if (IS_ERR(dev->regmap)) { in ts2020_probe()
584 ret = PTR_ERR(dev->regmap); in ts2020_probe()
588 dev->i2c = client->adapter; in ts2020_probe()
589 dev->i2c_address = client->addr; in ts2020_probe()
590 dev->loop_through = pdata->loop_through; in ts2020_probe()
591 dev->clk_out = pdata->clk_out; in ts2020_probe()
592 dev->clk_out_div = pdata->clk_out_div; in ts2020_probe()
593 dev->dont_poll = pdata->dont_poll; in ts2020_probe()
594 dev->frequency_div = pdata->frequency_div; in ts2020_probe()
595 dev->fe = fe; in ts2020_probe()
596 dev->get_agc_pwm = pdata->get_agc_pwm; in ts2020_probe()
597 fe->tuner_priv = dev; in ts2020_probe()
598 dev->client = client; in ts2020_probe()
599 INIT_DELAYED_WORK(&dev->stat_work, ts2020_stat_work); in ts2020_probe()
602 ret = regmap_read(dev->regmap, 0x00, &utmp); in ts2020_probe()
607 ret = regmap_write(dev->regmap, 0x00, 0x01); in ts2020_probe()
614 ret = regmap_write(dev->regmap, 0x00, 0x03); in ts2020_probe()
620 ret = regmap_read(dev->regmap, 0x00, &utmp); in ts2020_probe()
624 dev_dbg(&client->dev, "chip_id=%02x\n", utmp); in ts2020_probe()
630 dev->tuner = TS2020_M88TS2020; in ts2020_probe()
632 if (!dev->frequency_div) in ts2020_probe()
633 dev->frequency_div = 1060000; in ts2020_probe()
637 dev->tuner = TS2020_M88TS2022; in ts2020_probe()
639 if (!dev->frequency_div) in ts2020_probe()
640 dev->frequency_div = 1103000; in ts2020_probe()
643 ret = -ENODEV; in ts2020_probe()
647 if (dev->tuner == TS2020_M88TS2022) { in ts2020_probe()
648 switch (dev->clk_out) { in ts2020_probe()
654 ret = regmap_write(dev->regmap, 0x05, dev->clk_out_div); in ts2020_probe()
662 ret = -EINVAL; in ts2020_probe()
666 ret = regmap_write(dev->regmap, 0x42, u8tmp); in ts2020_probe()
670 if (dev->loop_through) in ts2020_probe()
675 ret = regmap_write(dev->regmap, 0x62, u8tmp); in ts2020_probe()
681 ret = regmap_write(dev->regmap, 0x00, 0x00); in ts2020_probe()
685 dev_info(&client->dev, in ts2020_probe()
688 memcpy(&fe->ops.tuner_ops, &ts2020_tuner_ops, in ts2020_probe()
690 if (!pdata->attach_in_use) in ts2020_probe()
691 fe->ops.tuner_ops.release = NULL; in ts2020_probe()
696 regmap_exit(dev->regmap); in ts2020_probe()
700 dev_dbg(&client->dev, "failed=%d\n", ret); in ts2020_probe()
708 dev_dbg(&client->dev, "\n"); in ts2020_remove()
711 if (!dev->dont_poll) in ts2020_remove()
712 cancel_delayed_work_sync(&dev->stat_work); in ts2020_remove()
714 regmap_exit(dev->regmap); in ts2020_remove()
737 MODULE_DESCRIPTION("Montage Technology TS2020 - Silicon tuner driver module");