1695efd010b1328b25462128e48856e87c8df4314Antti Palosaari/* 2695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * Montage M88TS2022 silicon tuner driver 3695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * 4695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> 5695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * 6695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * This program is free software; you can redistribute it and/or modify 7695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * it under the terms of the GNU General Public License as published by 8695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * the Free Software Foundation; either version 2 of the License, or 9695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * (at your option) any later version. 10695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * 11695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * This program is distributed in the hope that it will be useful, 12695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * but WITHOUT ANY WARRANTY; without even the implied warranty of 13695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * GNU General Public License for more details. 15695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * 16695efd010b1328b25462128e48856e87c8df4314Antti Palosaari * Some calculations are taken from existing TS2020 driver. 17695efd010b1328b25462128e48856e87c8df4314Antti Palosaari */ 18695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 19695efd010b1328b25462128e48856e87c8df4314Antti Palosaari#include "m88ts2022_priv.h" 20695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 21f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaaristatic int m88ts2022_cmd(struct m88ts2022_dev *dev, int op, int sleep, u8 reg, 22f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari u8 mask, u8 val, u8 *reg_val) 23695efd010b1328b25462128e48856e87c8df4314Antti Palosaari{ 24695efd010b1328b25462128e48856e87c8df4314Antti Palosaari int ret, i; 2535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari unsigned int utmp; 26695efd010b1328b25462128e48856e87c8df4314Antti Palosaari struct m88ts2022_reg_val reg_vals[] = { 27695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x51, 0x1f - op}, 28695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x51, 0x1f}, 29695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x50, 0x00 + op}, 30695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x50, 0x00}, 31695efd010b1328b25462128e48856e87c8df4314Antti Palosaari }; 32695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 33695efd010b1328b25462128e48856e87c8df4314Antti Palosaari for (i = 0; i < 2; i++) { 34eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari dev_dbg(&dev->client->dev, 35b8d67ab656288457a6728284d3a054544f629979Antti Palosaari "i=%d op=%02x reg=%02x mask=%02x val=%02x\n", 36b8d67ab656288457a6728284d3a054544f629979Antti Palosaari i, op, reg, mask, val); 37695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 38695efd010b1328b25462128e48856e87c8df4314Antti Palosaari for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 3935c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, reg_vals[i].reg, 40695efd010b1328b25462128e48856e87c8df4314Antti Palosaari reg_vals[i].val); 41695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 42695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 43695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 44695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 45695efd010b1328b25462128e48856e87c8df4314Antti Palosaari usleep_range(sleep * 1000, sleep * 10000); 46695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 4735c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_read(dev->regmap, reg, &utmp); 48695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 49695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 50695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 5135c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari if ((utmp & mask) != val) 52695efd010b1328b25462128e48856e87c8df4314Antti Palosaari break; 53695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 54695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 55695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (reg_val) 5635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari *reg_val = utmp; 57695efd010b1328b25462128e48856e87c8df4314Antti Palosaarierr: 58695efd010b1328b25462128e48856e87c8df4314Antti Palosaari return ret; 59695efd010b1328b25462128e48856e87c8df4314Antti Palosaari} 60695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 61695efd010b1328b25462128e48856e87c8df4314Antti Palosaaristatic int m88ts2022_set_params(struct dvb_frontend *fe) 62695efd010b1328b25462128e48856e87c8df4314Antti Palosaari{ 63eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct m88ts2022_dev *dev = fe->tuner_priv; 64695efd010b1328b25462128e48856e87c8df4314Antti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 65c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari int ret; 6635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari unsigned int utmp, frequency_khz, frequency_offset_khz, f_3db_hz; 67c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari unsigned int f_ref_khz, f_vco_khz, div_ref, div_out, pll_n, gdiv28; 68c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari u8 buf[3], u8tmp, cap_code, lpf_gm, lpf_mxdiv, div_max, div_min; 69c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari u16 u16tmp; 706380b975b76478ee0fd7c43d8833a52dfb5b57ebAntti Palosaari 71eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari dev_dbg(&dev->client->dev, 72b8d67ab656288457a6728284d3a054544f629979Antti Palosaari "frequency=%d symbol_rate=%d rolloff=%d\n", 73b8d67ab656288457a6728284d3a054544f629979Antti Palosaari c->frequency, c->symbol_rate, c->rolloff); 74c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari /* 75c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari * Integer-N PLL synthesizer 76c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari * kHz is used for all calculations to keep calculations within 32-bit 77c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari */ 78eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari f_ref_khz = DIV_ROUND_CLOSEST(dev->cfg.clock, 1000); 79c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari div_ref = DIV_ROUND_CLOSEST(f_ref_khz, 2000); 80695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 81695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (c->symbol_rate < 5000000) 82c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari frequency_offset_khz = 3000; /* 3 MHz */ 83695efd010b1328b25462128e48856e87c8df4314Antti Palosaari else 84c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari frequency_offset_khz = 0; 85695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 86c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari frequency_khz = c->frequency + frequency_offset_khz; 87695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 88695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (frequency_khz < 1103000) { 89c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari div_out = 4; 90695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x1b; 91695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } else { 92c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari div_out = 2; 93695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x0b; 94695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 95695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 96695efd010b1328b25462128e48856e87c8df4314Antti Palosaari buf[0] = u8tmp; 97695efd010b1328b25462128e48856e87c8df4314Antti Palosaari buf[1] = 0x40; 9835c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_bulk_write(dev->regmap, 0x10, buf, 2); 99695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 100695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 101695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 102c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari f_vco_khz = frequency_khz * div_out; 103c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari pll_n = f_vco_khz * div_ref / f_ref_khz; 104c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari pll_n += pll_n % 2; 105eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari dev->frequency_khz = pll_n * f_ref_khz / div_ref / div_out; 106695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 107c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari if (pll_n < 4095) 108c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari u16tmp = pll_n - 1024; 109c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari else if (pll_n < 6143) 110c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari u16tmp = pll_n + 1024; 111695efd010b1328b25462128e48856e87c8df4314Antti Palosaari else 112c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari u16tmp = pll_n + 3072; 113695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 114c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari buf[0] = (u16tmp >> 8) & 0x3f; 115c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari buf[1] = (u16tmp >> 0) & 0xff; 116c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari buf[2] = div_ref - 8; 11735c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_bulk_write(dev->regmap, 0x01, buf, 3); 118695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 119695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 120695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 121eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari dev_dbg(&dev->client->dev, 122b8d67ab656288457a6728284d3a054544f629979Antti Palosaari "frequency=%u offset=%d f_vco_khz=%u pll_n=%u div_ref=%u div_out=%u\n", 123b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev->frequency_khz, dev->frequency_khz - c->frequency, 124b8d67ab656288457a6728284d3a054544f629979Antti Palosaari f_vco_khz, pll_n, div_ref, div_out); 125695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 126f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari ret = m88ts2022_cmd(dev, 0x10, 5, 0x15, 0x40, 0x00, NULL); 127695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 128695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 129695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 13035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_read(dev->regmap, 0x14, &utmp); 131695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 132695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 133695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 13435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari utmp &= 0x7f; 13535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari if (utmp < 64) { 13635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_update_bits(dev->regmap, 0x10, 0x80, 0x80); 137695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 138695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 139695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 14035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x11, 0x6f); 141695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 142695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 143695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 144f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari ret = m88ts2022_cmd(dev, 0x10, 5, 0x15, 0x40, 0x00, NULL); 145695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 146695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 147695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 148695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 14935c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_read(dev->regmap, 0x14, &utmp); 150695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 151695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 152695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 15335c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari utmp &= 0x1f; 15435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari if (utmp > 19) { 15535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_update_bits(dev->regmap, 0x10, 0x02, 0x00); 156695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 157695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 158695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 159695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 160f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari ret = m88ts2022_cmd(dev, 0x08, 5, 0x3c, 0xff, 0x00, NULL); 161695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 162695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 163695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 16435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x25, 0x00); 165695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 166695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 167695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 16835c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x27, 0x70); 169695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 170695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 171695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 17235c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x41, 0x09); 173695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 174695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 175695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 17635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x08, 0x0b); 177695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 178695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 179695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 180c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari /* filters */ 181c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari gdiv28 = DIV_ROUND_CLOSEST(f_ref_khz * 1694U, 1000000U); 182695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 18335c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x04, gdiv28); 184695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 185695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 186695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 187f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp); 188695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 189695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 190695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 191695efd010b1328b25462128e48856e87c8df4314Antti Palosaari cap_code = u8tmp & 0x3f; 192695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 19335c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x41, 0x0d); 194695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 195695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 196695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 197f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp); 198695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 199695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 200695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 201695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp &= 0x3f; 202695efd010b1328b25462128e48856e87c8df4314Antti Palosaari cap_code = (cap_code + u8tmp) / 2; 203695efd010b1328b25462128e48856e87c8df4314Antti Palosaari gdiv28 = gdiv28 * 207 / (cap_code * 2 + 151); 204695efd010b1328b25462128e48856e87c8df4314Antti Palosaari div_max = gdiv28 * 135 / 100; 205695efd010b1328b25462128e48856e87c8df4314Antti Palosaari div_min = gdiv28 * 78 / 100; 206c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari div_max = clamp_val(div_max, 0U, 63U); 207c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari 208f538e085138e519e25ae0828bd6c6e7492ce8ca4Antti Palosaari f_3db_hz = mult_frac(c->symbol_rate, 135, 200); 209c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari f_3db_hz += 2000000U + (frequency_offset_khz * 1000U); 210c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari f_3db_hz = clamp(f_3db_hz, 7000000U, 40000000U); 211695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 212c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari#define LPF_COEFF 3200U 213c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari lpf_gm = DIV_ROUND_CLOSEST(f_3db_hz * gdiv28, LPF_COEFF * f_ref_khz); 214c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari lpf_gm = clamp_val(lpf_gm, 1U, 23U); 215c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari 216c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari lpf_mxdiv = DIV_ROUND_CLOSEST(lpf_gm * LPF_COEFF * f_ref_khz, f_3db_hz); 217c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari if (lpf_mxdiv < div_min) 218c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari lpf_mxdiv = DIV_ROUND_CLOSEST(++lpf_gm * LPF_COEFF * f_ref_khz, f_3db_hz); 219c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari lpf_mxdiv = clamp_val(lpf_mxdiv, 0U, div_max); 220695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 22135c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x04, lpf_mxdiv); 222695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 223695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 224695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 22535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x06, lpf_gm); 226695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 227695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 228695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 229f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp); 230695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 231695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 232695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 233695efd010b1328b25462128e48856e87c8df4314Antti Palosaari cap_code = u8tmp & 0x3f; 234695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 23535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x41, 0x09); 236695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 237695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 238695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 239f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp); 240695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 241695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 242695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 243695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp &= 0x3f; 244695efd010b1328b25462128e48856e87c8df4314Antti Palosaari cap_code = (cap_code + u8tmp) / 2; 245695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 246695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = cap_code | 0x80; 24735c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x25, u8tmp); 248695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 249695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 250695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 25135c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x27, 0x30); 252695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 253695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 254695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 25535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x08, 0x09); 256695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 257695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 258695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 259f461694b965b8cdf67c330d14c802a74acf7bec1Antti Palosaari ret = m88ts2022_cmd(dev, 0x01, 20, 0x21, 0xff, 0x00, NULL); 260695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 261695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 262695efd010b1328b25462128e48856e87c8df4314Antti Palosaarierr: 263695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 264b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&dev->client->dev, "failed=%d\n", ret); 265695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 266695efd010b1328b25462128e48856e87c8df4314Antti Palosaari return ret; 267695efd010b1328b25462128e48856e87c8df4314Antti Palosaari} 268695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 269695efd010b1328b25462128e48856e87c8df4314Antti Palosaaristatic int m88ts2022_init(struct dvb_frontend *fe) 270695efd010b1328b25462128e48856e87c8df4314Antti Palosaari{ 271eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct m88ts2022_dev *dev = fe->tuner_priv; 272695efd010b1328b25462128e48856e87c8df4314Antti Palosaari int ret, i; 273695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8 u8tmp; 274695efd010b1328b25462128e48856e87c8df4314Antti Palosaari static const struct m88ts2022_reg_val reg_vals[] = { 275695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x7d, 0x9d}, 276695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x7c, 0x9a}, 277695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x7a, 0x76}, 278695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x3b, 0x01}, 279695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x63, 0x88}, 280695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x61, 0x85}, 281695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x22, 0x30}, 282695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x30, 0x40}, 283695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x20, 0x23}, 284695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x24, 0x02}, 285695efd010b1328b25462128e48856e87c8df4314Antti Palosaari {0x12, 0xa0}, 286695efd010b1328b25462128e48856e87c8df4314Antti Palosaari }; 2876380b975b76478ee0fd7c43d8833a52dfb5b57ebAntti Palosaari 288b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&dev->client->dev, "\n"); 289695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 29035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x00, 0x01); 291695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 292695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 293695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 29435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x00, 0x03); 295695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 296695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 297695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 298eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari switch (dev->cfg.clock_out) { 299695efd010b1328b25462128e48856e87c8df4314Antti Palosaari case M88TS2022_CLOCK_OUT_DISABLED: 300695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x60; 301695efd010b1328b25462128e48856e87c8df4314Antti Palosaari break; 302695efd010b1328b25462128e48856e87c8df4314Antti Palosaari case M88TS2022_CLOCK_OUT_ENABLED: 303695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x70; 30435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x05, dev->cfg.clock_out_div); 305695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 306695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 307695efd010b1328b25462128e48856e87c8df4314Antti Palosaari break; 308695efd010b1328b25462128e48856e87c8df4314Antti Palosaari case M88TS2022_CLOCK_OUT_ENABLED_XTALOUT: 309695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x6c; 310695efd010b1328b25462128e48856e87c8df4314Antti Palosaari break; 311695efd010b1328b25462128e48856e87c8df4314Antti Palosaari default: 312695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 313695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 314695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 31535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x42, u8tmp); 316695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 317695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 318695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 319eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari if (dev->cfg.loop_through) 320695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0xec; 321695efd010b1328b25462128e48856e87c8df4314Antti Palosaari else 322695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x6c; 323695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 32435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x62, u8tmp); 325695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 326695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 327695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 328695efd010b1328b25462128e48856e87c8df4314Antti Palosaari for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 32935c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, reg_vals[i].reg, reg_vals[i].val); 330695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 331695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 332695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 333695efd010b1328b25462128e48856e87c8df4314Antti Palosaarierr: 334695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 335b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&dev->client->dev, "failed=%d\n", ret); 336695efd010b1328b25462128e48856e87c8df4314Antti Palosaari return ret; 337695efd010b1328b25462128e48856e87c8df4314Antti Palosaari} 338695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 339695efd010b1328b25462128e48856e87c8df4314Antti Palosaaristatic int m88ts2022_sleep(struct dvb_frontend *fe) 340695efd010b1328b25462128e48856e87c8df4314Antti Palosaari{ 341eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct m88ts2022_dev *dev = fe->tuner_priv; 342695efd010b1328b25462128e48856e87c8df4314Antti Palosaari int ret; 3436380b975b76478ee0fd7c43d8833a52dfb5b57ebAntti Palosaari 344b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&dev->client->dev, "\n"); 345695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 34635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x00, 0x00); 347695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 348695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 349695efd010b1328b25462128e48856e87c8df4314Antti Palosaarierr: 350695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 351b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&dev->client->dev, "failed=%d\n", ret); 352695efd010b1328b25462128e48856e87c8df4314Antti Palosaari return ret; 353695efd010b1328b25462128e48856e87c8df4314Antti Palosaari} 354695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 355695efd010b1328b25462128e48856e87c8df4314Antti Palosaaristatic int m88ts2022_get_frequency(struct dvb_frontend *fe, u32 *frequency) 356695efd010b1328b25462128e48856e87c8df4314Antti Palosaari{ 357eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct m88ts2022_dev *dev = fe->tuner_priv; 3586380b975b76478ee0fd7c43d8833a52dfb5b57ebAntti Palosaari 359b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&dev->client->dev, "\n"); 360695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 361eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari *frequency = dev->frequency_khz; 362695efd010b1328b25462128e48856e87c8df4314Antti Palosaari return 0; 363695efd010b1328b25462128e48856e87c8df4314Antti Palosaari} 364695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 365695efd010b1328b25462128e48856e87c8df4314Antti Palosaaristatic int m88ts2022_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 366695efd010b1328b25462128e48856e87c8df4314Antti Palosaari{ 367eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct m88ts2022_dev *dev = fe->tuner_priv; 3686380b975b76478ee0fd7c43d8833a52dfb5b57ebAntti Palosaari 369b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&dev->client->dev, "\n"); 370695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 371695efd010b1328b25462128e48856e87c8df4314Antti Palosaari *frequency = 0; /* Zero-IF */ 372695efd010b1328b25462128e48856e87c8df4314Antti Palosaari return 0; 373695efd010b1328b25462128e48856e87c8df4314Antti Palosaari} 374695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 375695efd010b1328b25462128e48856e87c8df4314Antti Palosaaristatic int m88ts2022_get_rf_strength(struct dvb_frontend *fe, u16 *strength) 376695efd010b1328b25462128e48856e87c8df4314Antti Palosaari{ 377eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct m88ts2022_dev *dev = fe->tuner_priv; 378695efd010b1328b25462128e48856e87c8df4314Antti Palosaari int ret; 379c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari u16 gain, u16tmp; 38035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari unsigned int utmp, gain1, gain2, gain3; 381695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 38235c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_read(dev->regmap, 0x3d, &utmp); 383695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 384695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 385695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 38635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari gain1 = (utmp >> 0) & 0x1f; 387c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari gain1 = clamp(gain1, 0U, 15U); 388695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 38935c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_read(dev->regmap, 0x21, &utmp); 390695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 391695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 392695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 39335c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari gain2 = (utmp >> 0) & 0x1f; 394c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari gain2 = clamp(gain2, 2U, 16U); 395695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 39635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_read(dev->regmap, 0x66, &utmp); 397695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 398695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 399695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 40035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari gain3 = (utmp >> 3) & 0x07; 401c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari gain3 = clamp(gain3, 0U, 6U); 402695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 403695efd010b1328b25462128e48856e87c8df4314Antti Palosaari gain = gain1 * 265 + gain2 * 338 + gain3 * 285; 404695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 405695efd010b1328b25462128e48856e87c8df4314Antti Palosaari /* scale value to 0x0000-0xffff */ 406695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u16tmp = (0xffff - gain); 407c19314b09bc0839736f2c74422b21de36a86e7b7Antti Palosaari u16tmp = clamp_val(u16tmp, 59000U, 61500U); 408695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 409695efd010b1328b25462128e48856e87c8df4314Antti Palosaari *strength = (u16tmp - 59000) * 0xffff / (61500 - 59000); 410695efd010b1328b25462128e48856e87c8df4314Antti Palosaarierr: 411695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 412b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&dev->client->dev, "failed=%d\n", ret); 413695efd010b1328b25462128e48856e87c8df4314Antti Palosaari return ret; 414695efd010b1328b25462128e48856e87c8df4314Antti Palosaari} 415695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 416695efd010b1328b25462128e48856e87c8df4314Antti Palosaaristatic const struct dvb_tuner_ops m88ts2022_tuner_ops = { 417695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .info = { 418695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .name = "Montage M88TS2022", 419695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .frequency_min = 950000, 420695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .frequency_max = 2150000, 421695efd010b1328b25462128e48856e87c8df4314Antti Palosaari }, 422695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 423695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .init = m88ts2022_init, 424695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .sleep = m88ts2022_sleep, 425695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .set_params = m88ts2022_set_params, 426695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 427695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .get_frequency = m88ts2022_get_frequency, 428695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .get_if_frequency = m88ts2022_get_if_frequency, 429695efd010b1328b25462128e48856e87c8df4314Antti Palosaari .get_rf_strength = m88ts2022_get_rf_strength, 430695efd010b1328b25462128e48856e87c8df4314Antti Palosaari}; 431695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 432eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaaristatic int m88ts2022_probe(struct i2c_client *client, 433eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari const struct i2c_device_id *id) 434695efd010b1328b25462128e48856e87c8df4314Antti Palosaari{ 435eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari struct m88ts2022_config *cfg = client->dev.platform_data; 436eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari struct dvb_frontend *fe = cfg->fe; 437eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct m88ts2022_dev *dev; 438695efd010b1328b25462128e48856e87c8df4314Antti Palosaari int ret; 43935c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari u8 u8tmp; 44035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari unsigned int utmp; 44135c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari static const struct regmap_config regmap_config = { 44235c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari .reg_bits = 8, 44335c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari .val_bits = 8, 44435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari }; 445695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 446eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari dev = kzalloc(sizeof(*dev), GFP_KERNEL); 447eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari if (!dev) { 448695efd010b1328b25462128e48856e87c8df4314Antti Palosaari ret = -ENOMEM; 449b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_err(&client->dev, "kzalloc() failed\n"); 450695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 451695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 452695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 453eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari memcpy(&dev->cfg, cfg, sizeof(struct m88ts2022_config)); 454eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari dev->client = client; 45535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari dev->regmap = devm_regmap_init_i2c(client, ®map_config); 45635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari if (IS_ERR(dev->regmap)) { 45735c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = PTR_ERR(dev->regmap); 45835c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari goto err; 45935c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari } 460695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 461695efd010b1328b25462128e48856e87c8df4314Antti Palosaari /* check if the tuner is there */ 46235c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_read(dev->regmap, 0x00, &utmp); 463695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 464695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 465695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 46635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari if ((utmp & 0x03) == 0x00) { 46735c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x00, 0x01); 46835c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari if (ret) 469695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 470695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 471695efd010b1328b25462128e48856e87c8df4314Antti Palosaari usleep_range(2000, 50000); 472695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 473695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 47435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x00, 0x03); 475695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 476695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 477695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 478695efd010b1328b25462128e48856e87c8df4314Antti Palosaari usleep_range(2000, 50000); 479695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 48035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_read(dev->regmap, 0x00, &utmp); 481695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 482695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 483695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 48435c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari dev_dbg(&dev->client->dev, "chip_id=%02x\n", utmp); 485695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 48635c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari switch (utmp) { 487695efd010b1328b25462128e48856e87c8df4314Antti Palosaari case 0xc3: 488695efd010b1328b25462128e48856e87c8df4314Antti Palosaari case 0x83: 489695efd010b1328b25462128e48856e87c8df4314Antti Palosaari break; 490695efd010b1328b25462128e48856e87c8df4314Antti Palosaari default: 491695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 492695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 493695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 494eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari switch (dev->cfg.clock_out) { 495695efd010b1328b25462128e48856e87c8df4314Antti Palosaari case M88TS2022_CLOCK_OUT_DISABLED: 496695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x60; 497695efd010b1328b25462128e48856e87c8df4314Antti Palosaari break; 498695efd010b1328b25462128e48856e87c8df4314Antti Palosaari case M88TS2022_CLOCK_OUT_ENABLED: 499695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x70; 50035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x05, dev->cfg.clock_out_div); 501695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 502695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 503695efd010b1328b25462128e48856e87c8df4314Antti Palosaari break; 504695efd010b1328b25462128e48856e87c8df4314Antti Palosaari case M88TS2022_CLOCK_OUT_ENABLED_XTALOUT: 505695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x6c; 506695efd010b1328b25462128e48856e87c8df4314Antti Palosaari break; 507695efd010b1328b25462128e48856e87c8df4314Antti Palosaari default: 508695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 509695efd010b1328b25462128e48856e87c8df4314Antti Palosaari } 510695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 51135c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x42, u8tmp); 512695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 513695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 514695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 515eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari if (dev->cfg.loop_through) 516695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0xec; 517695efd010b1328b25462128e48856e87c8df4314Antti Palosaari else 518695efd010b1328b25462128e48856e87c8df4314Antti Palosaari u8tmp = 0x6c; 519695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 52035c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x62, u8tmp); 521695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 522695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 523695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 524695efd010b1328b25462128e48856e87c8df4314Antti Palosaari /* sleep */ 52535c77a85463cacf7fe2fa8e998698170c42e80f6Antti Palosaari ret = regmap_write(dev->regmap, 0x00, 0x00); 526695efd010b1328b25462128e48856e87c8df4314Antti Palosaari if (ret) 527695efd010b1328b25462128e48856e87c8df4314Antti Palosaari goto err; 528695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 529b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_info(&dev->client->dev, "Montage M88TS2022 successfully identified\n"); 530695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 531eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari fe->tuner_priv = dev; 532695efd010b1328b25462128e48856e87c8df4314Antti Palosaari memcpy(&fe->ops.tuner_ops, &m88ts2022_tuner_ops, 533695efd010b1328b25462128e48856e87c8df4314Antti Palosaari sizeof(struct dvb_tuner_ops)); 534eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari 535eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari i2c_set_clientdata(client, dev); 536eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari return 0; 537695efd010b1328b25462128e48856e87c8df4314Antti Palosaarierr: 538b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 539eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari kfree(dev); 540eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari return ret; 541eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari} 542eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari 543eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaaristatic int m88ts2022_remove(struct i2c_client *client) 544eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari{ 545eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct m88ts2022_dev *dev = i2c_get_clientdata(client); 546eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari struct dvb_frontend *fe = dev->cfg.fe; 5476380b975b76478ee0fd7c43d8833a52dfb5b57ebAntti Palosaari 548b8d67ab656288457a6728284d3a054544f629979Antti Palosaari dev_dbg(&client->dev, "\n"); 549695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 550eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); 551eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari fe->tuner_priv = NULL; 552eb773df5d2cf68be127b2ee146336f888962a521Antti Palosaari kfree(dev); 553eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari 554eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari return 0; 555695efd010b1328b25462128e48856e87c8df4314Antti Palosaari} 556eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari 557eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaaristatic const struct i2c_device_id m88ts2022_id[] = { 558eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari {"m88ts2022", 0}, 559eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari {} 560eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari}; 561eafa2ad6e46c523da7d6970306167b24c861504fAntti PalosaariMODULE_DEVICE_TABLE(i2c, m88ts2022_id); 562eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari 563eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaaristatic struct i2c_driver m88ts2022_driver = { 564eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari .driver = { 565eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari .owner = THIS_MODULE, 566eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari .name = "m88ts2022", 567eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari }, 568eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari .probe = m88ts2022_probe, 569eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari .remove = m88ts2022_remove, 570eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari .id_table = m88ts2022_id, 571eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari}; 572eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaari 573eafa2ad6e46c523da7d6970306167b24c861504fAntti Palosaarimodule_i2c_driver(m88ts2022_driver); 574695efd010b1328b25462128e48856e87c8df4314Antti Palosaari 575695efd010b1328b25462128e48856e87c8df4314Antti PalosaariMODULE_DESCRIPTION("Montage M88TS2022 silicon tuner driver"); 576695efd010b1328b25462128e48856e87c8df4314Antti PalosaariMODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 577695efd010b1328b25462128e48856e87c8df4314Antti PalosaariMODULE_LICENSE("GPL"); 578