18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * NXP TDA18250 silicon tuner driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2017 Olli Salonen <olli.salonen@iki.fi> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "tda18250_priv.h" 98c2ecf20Sopenharmony_ci#include <linux/regmap.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops tda18250_ops; 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistatic int tda18250_power_control(struct dvb_frontend *fe, 148c2ecf20Sopenharmony_ci unsigned int power_state) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci struct i2c_client *client = fe->tuner_priv; 178c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 188c2ecf20Sopenharmony_ci int ret; 198c2ecf20Sopenharmony_ci unsigned int utmp; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "power state: %d", power_state); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci switch (power_state) { 248c2ecf20Sopenharmony_ci case TDA18250_POWER_NORMAL: 258c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R06_POWER2, 0x07, 0x00); 268c2ecf20Sopenharmony_ci if (ret) 278c2ecf20Sopenharmony_ci goto err; 288c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R25_REF, 0xc0, 0xc0); 298c2ecf20Sopenharmony_ci if (ret) 308c2ecf20Sopenharmony_ci goto err; 318c2ecf20Sopenharmony_ci break; 328c2ecf20Sopenharmony_ci case TDA18250_POWER_STANDBY: 338c2ecf20Sopenharmony_ci if (dev->loopthrough) { 348c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, 358c2ecf20Sopenharmony_ci R25_REF, 0xc0, 0x80); 368c2ecf20Sopenharmony_ci if (ret) 378c2ecf20Sopenharmony_ci goto err; 388c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, 398c2ecf20Sopenharmony_ci R06_POWER2, 0x07, 0x02); 408c2ecf20Sopenharmony_ci if (ret) 418c2ecf20Sopenharmony_ci goto err; 428c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, 438c2ecf20Sopenharmony_ci R10_LT1, 0x80, 0x00); 448c2ecf20Sopenharmony_ci if (ret) 458c2ecf20Sopenharmony_ci goto err; 468c2ecf20Sopenharmony_ci } else { 478c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, 488c2ecf20Sopenharmony_ci R25_REF, 0xc0, 0x80); 498c2ecf20Sopenharmony_ci if (ret) 508c2ecf20Sopenharmony_ci goto err; 518c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, 528c2ecf20Sopenharmony_ci R06_POWER2, 0x07, 0x01); 538c2ecf20Sopenharmony_ci if (ret) 548c2ecf20Sopenharmony_ci goto err; 558c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 568c2ecf20Sopenharmony_ci R0D_AGC12, &utmp); 578c2ecf20Sopenharmony_ci if (ret) 588c2ecf20Sopenharmony_ci goto err; 598c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, 608c2ecf20Sopenharmony_ci R0D_AGC12, 0x03, 0x03); 618c2ecf20Sopenharmony_ci if (ret) 628c2ecf20Sopenharmony_ci goto err; 638c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, 648c2ecf20Sopenharmony_ci R10_LT1, 0x80, 0x80); 658c2ecf20Sopenharmony_ci if (ret) 668c2ecf20Sopenharmony_ci goto err; 678c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, 688c2ecf20Sopenharmony_ci R0D_AGC12, 0x03, utmp & 0x03); 698c2ecf20Sopenharmony_ci if (ret) 708c2ecf20Sopenharmony_ci goto err; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci break; 738c2ecf20Sopenharmony_ci default: 748c2ecf20Sopenharmony_ci ret = -EINVAL; 758c2ecf20Sopenharmony_ci goto err; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return 0; 798c2ecf20Sopenharmony_cierr: 808c2ecf20Sopenharmony_ci return ret; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic int tda18250_wait_for_irq(struct dvb_frontend *fe, 848c2ecf20Sopenharmony_ci int maxwait, int step, u8 irq) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci struct i2c_client *client = fe->tuner_priv; 878c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 888c2ecf20Sopenharmony_ci int ret; 898c2ecf20Sopenharmony_ci unsigned long timeout; 908c2ecf20Sopenharmony_ci bool triggered; 918c2ecf20Sopenharmony_ci unsigned int utmp; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci triggered = false; 948c2ecf20Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(maxwait); 958c2ecf20Sopenharmony_ci while (!time_after(jiffies, timeout)) { 968c2ecf20Sopenharmony_ci // check for the IRQ 978c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, R08_IRQ1, &utmp); 988c2ecf20Sopenharmony_ci if (ret) 998c2ecf20Sopenharmony_ci goto err; 1008c2ecf20Sopenharmony_ci if ((utmp & irq) == irq) { 1018c2ecf20Sopenharmony_ci triggered = true; 1028c2ecf20Sopenharmony_ci break; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci msleep(step); 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "waited IRQ (0x%02x) %d ms, triggered: %s", irq, 1088c2ecf20Sopenharmony_ci jiffies_to_msecs(jiffies) - 1098c2ecf20Sopenharmony_ci (jiffies_to_msecs(timeout) - maxwait), 1108c2ecf20Sopenharmony_ci triggered ? "true" : "false"); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (!triggered) 1138c2ecf20Sopenharmony_ci return -ETIMEDOUT; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci return 0; 1168c2ecf20Sopenharmony_cierr: 1178c2ecf20Sopenharmony_ci return ret; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic int tda18250_init(struct dvb_frontend *fe) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct i2c_client *client = fe->tuner_priv; 1238c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 1248c2ecf20Sopenharmony_ci int ret, i; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* default values for various regs */ 1278c2ecf20Sopenharmony_ci static const u8 init_regs[][2] = { 1288c2ecf20Sopenharmony_ci { R0C_AGC11, 0xc7 }, 1298c2ecf20Sopenharmony_ci { R0D_AGC12, 0x5d }, 1308c2ecf20Sopenharmony_ci { R0E_AGC13, 0x40 }, 1318c2ecf20Sopenharmony_ci { R0F_AGC14, 0x0e }, 1328c2ecf20Sopenharmony_ci { R10_LT1, 0x47 }, 1338c2ecf20Sopenharmony_ci { R11_LT2, 0x4e }, 1348c2ecf20Sopenharmony_ci { R12_AGC21, 0x26 }, 1358c2ecf20Sopenharmony_ci { R13_AGC22, 0x60 }, 1368c2ecf20Sopenharmony_ci { R18_AGC32, 0x37 }, 1378c2ecf20Sopenharmony_ci { R19_AGC33, 0x09 }, 1388c2ecf20Sopenharmony_ci { R1A_AGCK, 0x00 }, 1398c2ecf20Sopenharmony_ci { R1E_WI_FI, 0x29 }, 1408c2ecf20Sopenharmony_ci { R1F_RF_BPF, 0x06 }, 1418c2ecf20Sopenharmony_ci { R20_IR_MIX, 0xc6 }, 1428c2ecf20Sopenharmony_ci { R21_IF_AGC, 0x00 }, 1438c2ecf20Sopenharmony_ci { R2C_PS1, 0x75 }, 1448c2ecf20Sopenharmony_ci { R2D_PS2, 0x06 }, 1458c2ecf20Sopenharmony_ci { R2E_PS3, 0x07 }, 1468c2ecf20Sopenharmony_ci { R30_RSSI2, 0x0e }, 1478c2ecf20Sopenharmony_ci { R31_IRQ_CTRL, 0x00 }, 1488c2ecf20Sopenharmony_ci { R39_SD5, 0x00 }, 1498c2ecf20Sopenharmony_ci { R3B_REGU, 0x55 }, 1508c2ecf20Sopenharmony_ci { R3C_RCCAL1, 0xa7 }, 1518c2ecf20Sopenharmony_ci { R3F_IRCAL2, 0x85 }, 1528c2ecf20Sopenharmony_ci { R40_IRCAL3, 0x87 }, 1538c2ecf20Sopenharmony_ci { R41_IRCAL4, 0xc0 }, 1548c2ecf20Sopenharmony_ci { R43_PD1, 0x40 }, 1558c2ecf20Sopenharmony_ci { R44_PD2, 0xc0 }, 1568c2ecf20Sopenharmony_ci { R46_CPUMP, 0x0c }, 1578c2ecf20Sopenharmony_ci { R47_LNAPOL, 0x64 }, 1588c2ecf20Sopenharmony_ci { R4B_XTALOSC1, 0x30 }, 1598c2ecf20Sopenharmony_ci { R59_AGC2_UP2, 0x05 }, 1608c2ecf20Sopenharmony_ci { R5B_AGC_AUTO, 0x07 }, 1618c2ecf20Sopenharmony_ci { R5C_AGC_DEBUG, 0x00 }, 1628c2ecf20Sopenharmony_ci }; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* crystal related regs depend on frequency */ 1658c2ecf20Sopenharmony_ci static const u8 xtal_regs[][5] = { 1668c2ecf20Sopenharmony_ci /* reg: 4d 4e 4f 50 51 */ 1678c2ecf20Sopenharmony_ci [TDA18250_XTAL_FREQ_16MHZ] = { 0x3e, 0x80, 0x50, 0x00, 0x20 }, 1688c2ecf20Sopenharmony_ci [TDA18250_XTAL_FREQ_24MHZ] = { 0x5d, 0xc0, 0xec, 0x00, 0x18 }, 1698c2ecf20Sopenharmony_ci [TDA18250_XTAL_FREQ_25MHZ] = { 0x61, 0xa8, 0xec, 0x80, 0x19 }, 1708c2ecf20Sopenharmony_ci [TDA18250_XTAL_FREQ_27MHZ] = { 0x69, 0x78, 0x8d, 0x80, 0x1b }, 1718c2ecf20Sopenharmony_ci [TDA18250_XTAL_FREQ_30MHZ] = { 0x75, 0x30, 0x8f, 0x00, 0x1e }, 1728c2ecf20Sopenharmony_ci }; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci ret = tda18250_power_control(fe, TDA18250_POWER_NORMAL); 1778c2ecf20Sopenharmony_ci if (ret) 1788c2ecf20Sopenharmony_ci goto err; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci msleep(20); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (dev->warm) 1838c2ecf20Sopenharmony_ci goto warm; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci /* set initial register values */ 1868c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(init_regs); i++) { 1878c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, init_regs[i][0], 1888c2ecf20Sopenharmony_ci init_regs[i][1]); 1898c2ecf20Sopenharmony_ci if (ret) 1908c2ecf20Sopenharmony_ci goto err; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* set xtal related regs */ 1948c2ecf20Sopenharmony_ci ret = regmap_bulk_write(dev->regmap, R4D_XTALFLX1, 1958c2ecf20Sopenharmony_ci xtal_regs[dev->xtal_freq], 5); 1968c2ecf20Sopenharmony_ci if (ret) 1978c2ecf20Sopenharmony_ci goto err; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R10_LT1, 0x80, 2008c2ecf20Sopenharmony_ci dev->loopthrough ? 0x00 : 0x80); 2018c2ecf20Sopenharmony_ci if (ret) 2028c2ecf20Sopenharmony_ci goto err; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* clear IRQ */ 2058c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R0A_IRQ3, TDA18250_IRQ_HW_INIT); 2068c2ecf20Sopenharmony_ci if (ret) 2078c2ecf20Sopenharmony_ci goto err; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* start HW init */ 2108c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R2A_MSM1, 0x70); 2118c2ecf20Sopenharmony_ci if (ret) 2128c2ecf20Sopenharmony_ci goto err; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R2B_MSM2, 0x01); 2158c2ecf20Sopenharmony_ci if (ret) 2168c2ecf20Sopenharmony_ci goto err; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci ret = tda18250_wait_for_irq(fe, 500, 10, TDA18250_IRQ_HW_INIT); 2198c2ecf20Sopenharmony_ci if (ret) 2208c2ecf20Sopenharmony_ci goto err; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* tuner calibration */ 2238c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R2A_MSM1, 0x02); 2248c2ecf20Sopenharmony_ci if (ret) 2258c2ecf20Sopenharmony_ci goto err; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R2B_MSM2, 0x01); 2288c2ecf20Sopenharmony_ci if (ret) 2298c2ecf20Sopenharmony_ci goto err; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci ret = tda18250_wait_for_irq(fe, 500, 10, TDA18250_IRQ_CAL); 2328c2ecf20Sopenharmony_ci if (ret) 2338c2ecf20Sopenharmony_ci goto err; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci dev->warm = true; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ciwarm: 2388c2ecf20Sopenharmony_ci /* power up LNA */ 2398c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R0C_AGC11, 0x80, 0x00); 2408c2ecf20Sopenharmony_ci if (ret) 2418c2ecf20Sopenharmony_ci goto err; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return 0; 2448c2ecf20Sopenharmony_cierr: 2458c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d", ret); 2468c2ecf20Sopenharmony_ci return ret; 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic int tda18250_set_agc(struct dvb_frontend *fe) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci struct i2c_client *client = fe->tuner_priv; 2528c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 2538c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 2548c2ecf20Sopenharmony_ci int ret; 2558c2ecf20Sopenharmony_ci u8 utmp, utmp2; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R1F_RF_BPF, 0x87, 0x06); 2608c2ecf20Sopenharmony_ci if (ret) 2618c2ecf20Sopenharmony_ci goto err; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci utmp = ((c->frequency < 100000000) && 2648c2ecf20Sopenharmony_ci ((c->delivery_system == SYS_DVBC_ANNEX_A) || 2658c2ecf20Sopenharmony_ci (c->delivery_system == SYS_DVBC_ANNEX_C)) && 2668c2ecf20Sopenharmony_ci (c->bandwidth_hz == 6000000)) ? 0x80 : 0x00; 2678c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R5A_H3H5, utmp); 2688c2ecf20Sopenharmony_ci if (ret) 2698c2ecf20Sopenharmony_ci goto err; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* AGC1 */ 2728c2ecf20Sopenharmony_ci switch (c->delivery_system) { 2738c2ecf20Sopenharmony_ci case SYS_ATSC: 2748c2ecf20Sopenharmony_ci case SYS_DVBT: 2758c2ecf20Sopenharmony_ci case SYS_DVBT2: 2768c2ecf20Sopenharmony_ci utmp = 4; 2778c2ecf20Sopenharmony_ci break; 2788c2ecf20Sopenharmony_ci default: /* DVB-C/QAM */ 2798c2ecf20Sopenharmony_ci switch (c->bandwidth_hz) { 2808c2ecf20Sopenharmony_ci case 6000000: 2818c2ecf20Sopenharmony_ci utmp = (c->frequency < 800000000) ? 6 : 4; 2828c2ecf20Sopenharmony_ci break; 2838c2ecf20Sopenharmony_ci default: /* 7.935 and 8 MHz */ 2848c2ecf20Sopenharmony_ci utmp = (c->frequency < 100000000) ? 2 : 3; 2858c2ecf20Sopenharmony_ci break; 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci break; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R0C_AGC11, 0x07, utmp); 2918c2ecf20Sopenharmony_ci if (ret) 2928c2ecf20Sopenharmony_ci goto err; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* AGC2 */ 2958c2ecf20Sopenharmony_ci switch (c->delivery_system) { 2968c2ecf20Sopenharmony_ci case SYS_ATSC: 2978c2ecf20Sopenharmony_ci case SYS_DVBT: 2988c2ecf20Sopenharmony_ci case SYS_DVBT2: 2998c2ecf20Sopenharmony_ci utmp = (c->frequency < 320000000) ? 20 : 16; 3008c2ecf20Sopenharmony_ci utmp2 = (c->frequency < 320000000) ? 22 : 18; 3018c2ecf20Sopenharmony_ci break; 3028c2ecf20Sopenharmony_ci default: /* DVB-C/QAM */ 3038c2ecf20Sopenharmony_ci switch (c->bandwidth_hz) { 3048c2ecf20Sopenharmony_ci case 6000000: 3058c2ecf20Sopenharmony_ci if (c->frequency < 600000000) { 3068c2ecf20Sopenharmony_ci utmp = 18; 3078c2ecf20Sopenharmony_ci utmp2 = 22; 3088c2ecf20Sopenharmony_ci } else if (c->frequency < 800000000) { 3098c2ecf20Sopenharmony_ci utmp = 16; 3108c2ecf20Sopenharmony_ci utmp2 = 20; 3118c2ecf20Sopenharmony_ci } else { 3128c2ecf20Sopenharmony_ci utmp = 14; 3138c2ecf20Sopenharmony_ci utmp2 = 16; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci break; 3168c2ecf20Sopenharmony_ci default: /* 7.935 and 8 MHz */ 3178c2ecf20Sopenharmony_ci utmp = (c->frequency < 320000000) ? 16 : 18; 3188c2ecf20Sopenharmony_ci utmp2 = (c->frequency < 320000000) ? 18 : 20; 3198c2ecf20Sopenharmony_ci break; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R58_AGC2_UP1, 0x1f, utmp2+8); 3248c2ecf20Sopenharmony_ci if (ret) 3258c2ecf20Sopenharmony_ci goto err; 3268c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R13_AGC22, 0x1f, utmp); 3278c2ecf20Sopenharmony_ci if (ret) 3288c2ecf20Sopenharmony_ci goto err; 3298c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R14_AGC23, 0x1f, utmp2); 3308c2ecf20Sopenharmony_ci if (ret) 3318c2ecf20Sopenharmony_ci goto err; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci switch (c->delivery_system) { 3348c2ecf20Sopenharmony_ci case SYS_ATSC: 3358c2ecf20Sopenharmony_ci case SYS_DVBT: 3368c2ecf20Sopenharmony_ci case SYS_DVBT2: 3378c2ecf20Sopenharmony_ci utmp = 98; 3388c2ecf20Sopenharmony_ci break; 3398c2ecf20Sopenharmony_ci default: /* DVB-C/QAM */ 3408c2ecf20Sopenharmony_ci utmp = 90; 3418c2ecf20Sopenharmony_ci break; 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R16_AGC25, 0xf8, utmp); 3448c2ecf20Sopenharmony_ci if (ret) 3458c2ecf20Sopenharmony_ci goto err; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R12_AGC21, 0x60, 3488c2ecf20Sopenharmony_ci (c->frequency > 800000000) ? 0x40 : 0x20); 3498c2ecf20Sopenharmony_ci if (ret) 3508c2ecf20Sopenharmony_ci goto err; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci /* AGC3 */ 3538c2ecf20Sopenharmony_ci switch (c->delivery_system) { 3548c2ecf20Sopenharmony_ci case SYS_ATSC: 3558c2ecf20Sopenharmony_ci case SYS_DVBT: 3568c2ecf20Sopenharmony_ci case SYS_DVBT2: 3578c2ecf20Sopenharmony_ci utmp = (c->frequency < 320000000) ? 5 : 7; 3588c2ecf20Sopenharmony_ci utmp2 = (c->frequency < 320000000) ? 10 : 12; 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci default: /* DVB-C/QAM */ 3618c2ecf20Sopenharmony_ci utmp = 7; 3628c2ecf20Sopenharmony_ci utmp2 = 12; 3638c2ecf20Sopenharmony_ci break; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R17_AGC31, (utmp << 4) | utmp2); 3668c2ecf20Sopenharmony_ci if (ret) 3678c2ecf20Sopenharmony_ci goto err; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* S2D */ 3708c2ecf20Sopenharmony_ci switch (c->delivery_system) { 3718c2ecf20Sopenharmony_ci case SYS_ATSC: 3728c2ecf20Sopenharmony_ci case SYS_DVBT: 3738c2ecf20Sopenharmony_ci case SYS_DVBT2: 3748c2ecf20Sopenharmony_ci if (c->bandwidth_hz == 8000000) 3758c2ecf20Sopenharmony_ci utmp = 0x04; 3768c2ecf20Sopenharmony_ci else 3778c2ecf20Sopenharmony_ci utmp = (c->frequency < 320000000) ? 0x04 : 0x02; 3788c2ecf20Sopenharmony_ci break; 3798c2ecf20Sopenharmony_ci default: /* DVB-C/QAM */ 3808c2ecf20Sopenharmony_ci if (c->bandwidth_hz == 6000000) 3818c2ecf20Sopenharmony_ci utmp = ((c->frequency > 172544000) && 3828c2ecf20Sopenharmony_ci (c->frequency < 320000000)) ? 0x04 : 0x02; 3838c2ecf20Sopenharmony_ci else /* 7.935 and 8 MHz */ 3848c2ecf20Sopenharmony_ci utmp = ((c->frequency > 320000000) && 3858c2ecf20Sopenharmony_ci (c->frequency < 600000000)) ? 0x02 : 0x04; 3868c2ecf20Sopenharmony_ci break; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R20_IR_MIX, 0x06, utmp); 3898c2ecf20Sopenharmony_ci if (ret) 3908c2ecf20Sopenharmony_ci goto err; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci switch (c->delivery_system) { 3938c2ecf20Sopenharmony_ci case SYS_ATSC: 3948c2ecf20Sopenharmony_ci case SYS_DVBT: 3958c2ecf20Sopenharmony_ci case SYS_DVBT2: 3968c2ecf20Sopenharmony_ci utmp = 0; 3978c2ecf20Sopenharmony_ci break; 3988c2ecf20Sopenharmony_ci default: /* DVB-C/QAM */ 3998c2ecf20Sopenharmony_ci utmp = (c->frequency < 600000000) ? 0 : 3; 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R16_AGC25, 0x03, utmp); 4038c2ecf20Sopenharmony_ci if (ret) 4048c2ecf20Sopenharmony_ci goto err; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci utmp = 0x09; 4078c2ecf20Sopenharmony_ci switch (c->delivery_system) { 4088c2ecf20Sopenharmony_ci case SYS_ATSC: 4098c2ecf20Sopenharmony_ci case SYS_DVBT: 4108c2ecf20Sopenharmony_ci case SYS_DVBT2: 4118c2ecf20Sopenharmony_ci if (c->bandwidth_hz == 8000000) 4128c2ecf20Sopenharmony_ci utmp = 0x0c; 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci default: /* DVB-C/QAM */ 4158c2ecf20Sopenharmony_ci utmp = 0x0c; 4168c2ecf20Sopenharmony_ci break; 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R0F_AGC14, 0x3f, utmp); 4198c2ecf20Sopenharmony_ci if (ret) 4208c2ecf20Sopenharmony_ci goto err; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci return 0; 4238c2ecf20Sopenharmony_cierr: 4248c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d", ret); 4258c2ecf20Sopenharmony_ci return ret; 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_cistatic int tda18250_pll_calc(struct dvb_frontend *fe, u8 *rdiv, 4298c2ecf20Sopenharmony_ci u8 *ndiv, u8 *icp) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci struct i2c_client *client = fe->tuner_priv; 4328c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 4338c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 4348c2ecf20Sopenharmony_ci int ret; 4358c2ecf20Sopenharmony_ci unsigned int uval, exp, lopd, scale; 4368c2ecf20Sopenharmony_ci unsigned long fvco; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, R34_MD1, &uval); 4398c2ecf20Sopenharmony_ci if (ret) 4408c2ecf20Sopenharmony_ci goto err; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci exp = (uval & 0x70) >> 4; 4438c2ecf20Sopenharmony_ci if (exp > 5) 4448c2ecf20Sopenharmony_ci exp = 0; 4458c2ecf20Sopenharmony_ci lopd = 1 << (exp - 1); 4468c2ecf20Sopenharmony_ci scale = uval & 0x0f; 4478c2ecf20Sopenharmony_ci fvco = lopd * scale * ((c->frequency / 1000) + dev->if_frequency); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci switch (dev->xtal_freq) { 4508c2ecf20Sopenharmony_ci case TDA18250_XTAL_FREQ_16MHZ: 4518c2ecf20Sopenharmony_ci *rdiv = 1; 4528c2ecf20Sopenharmony_ci *ndiv = 0; 4538c2ecf20Sopenharmony_ci *icp = (fvco < 6622000) ? 0x05 : 0x02; 4548c2ecf20Sopenharmony_ci break; 4558c2ecf20Sopenharmony_ci case TDA18250_XTAL_FREQ_24MHZ: 4568c2ecf20Sopenharmony_ci case TDA18250_XTAL_FREQ_25MHZ: 4578c2ecf20Sopenharmony_ci *rdiv = 3; 4588c2ecf20Sopenharmony_ci *ndiv = 1; 4598c2ecf20Sopenharmony_ci *icp = (fvco < 6622000) ? 0x05 : 0x02; 4608c2ecf20Sopenharmony_ci break; 4618c2ecf20Sopenharmony_ci case TDA18250_XTAL_FREQ_27MHZ: 4628c2ecf20Sopenharmony_ci if (fvco < 6643000) { 4638c2ecf20Sopenharmony_ci *rdiv = 2; 4648c2ecf20Sopenharmony_ci *ndiv = 0; 4658c2ecf20Sopenharmony_ci *icp = 0x05; 4668c2ecf20Sopenharmony_ci } else if (fvco < 6811000) { 4678c2ecf20Sopenharmony_ci *rdiv = 2; 4688c2ecf20Sopenharmony_ci *ndiv = 0; 4698c2ecf20Sopenharmony_ci *icp = 0x06; 4708c2ecf20Sopenharmony_ci } else { 4718c2ecf20Sopenharmony_ci *rdiv = 3; 4728c2ecf20Sopenharmony_ci *ndiv = 1; 4738c2ecf20Sopenharmony_ci *icp = 0x02; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci break; 4768c2ecf20Sopenharmony_ci case TDA18250_XTAL_FREQ_30MHZ: 4778c2ecf20Sopenharmony_ci *rdiv = 2; 4788c2ecf20Sopenharmony_ci *ndiv = 0; 4798c2ecf20Sopenharmony_ci *icp = (fvco < 6811000) ? 0x05 : 0x02; 4808c2ecf20Sopenharmony_ci break; 4818c2ecf20Sopenharmony_ci default: 4828c2ecf20Sopenharmony_ci return -EINVAL; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci dev_dbg(&client->dev, 4868c2ecf20Sopenharmony_ci "lopd=%d scale=%u fvco=%lu, rdiv=%d ndiv=%d icp=%d", 4878c2ecf20Sopenharmony_ci lopd, scale, fvco, *rdiv, *ndiv, *icp); 4888c2ecf20Sopenharmony_ci return 0; 4898c2ecf20Sopenharmony_cierr: 4908c2ecf20Sopenharmony_ci return ret; 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic int tda18250_set_params(struct dvb_frontend *fe) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci struct i2c_client *client = fe->tuner_priv; 4968c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 4978c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 4988c2ecf20Sopenharmony_ci u32 if_khz; 4998c2ecf20Sopenharmony_ci int ret; 5008c2ecf20Sopenharmony_ci unsigned int i, j; 5018c2ecf20Sopenharmony_ci u8 utmp; 5028c2ecf20Sopenharmony_ci u8 buf[3]; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci #define REG 0 5058c2ecf20Sopenharmony_ci #define MASK 1 5068c2ecf20Sopenharmony_ci #define DVBT_6 2 5078c2ecf20Sopenharmony_ci #define DVBT_7 3 5088c2ecf20Sopenharmony_ci #define DVBT_8 4 5098c2ecf20Sopenharmony_ci #define DVBC_6 5 5108c2ecf20Sopenharmony_ci #define DVBC_8 6 5118c2ecf20Sopenharmony_ci #define ATSC 7 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci static const u8 delsys_params[][16] = { 5148c2ecf20Sopenharmony_ci [REG] = { 0x22, 0x23, 0x24, 0x21, 0x0d, 0x0c, 0x0f, 0x14, 5158c2ecf20Sopenharmony_ci 0x0e, 0x12, 0x58, 0x59, 0x1a, 0x19, 0x1e, 0x30 }, 5168c2ecf20Sopenharmony_ci [MASK] = { 0x77, 0xff, 0xff, 0x87, 0xf0, 0x78, 0x07, 0xe0, 5178c2ecf20Sopenharmony_ci 0x60, 0x0f, 0x60, 0x0f, 0x33, 0x30, 0x80, 0x06 }, 5188c2ecf20Sopenharmony_ci [DVBT_6] = { 0x51, 0x03, 0x83, 0x82, 0x40, 0x48, 0x01, 0xe0, 5198c2ecf20Sopenharmony_ci 0x60, 0x0f, 0x60, 0x05, 0x03, 0x10, 0x00, 0x04 }, 5208c2ecf20Sopenharmony_ci [DVBT_7] = { 0x52, 0x03, 0x85, 0x82, 0x40, 0x48, 0x01, 0xe0, 5218c2ecf20Sopenharmony_ci 0x60, 0x0f, 0x60, 0x05, 0x03, 0x10, 0x00, 0x04 }, 5228c2ecf20Sopenharmony_ci [DVBT_8] = { 0x53, 0x03, 0x87, 0x82, 0x40, 0x48, 0x06, 0xe0, 5238c2ecf20Sopenharmony_ci 0x60, 0x07, 0x60, 0x05, 0x03, 0x10, 0x00, 0x04 }, 5248c2ecf20Sopenharmony_ci [DVBC_6] = { 0x32, 0x05, 0x86, 0x82, 0x50, 0x00, 0x06, 0x60, 5258c2ecf20Sopenharmony_ci 0x40, 0x0e, 0x60, 0x05, 0x33, 0x10, 0x00, 0x04 }, 5268c2ecf20Sopenharmony_ci [DVBC_8] = { 0x53, 0x03, 0x88, 0x82, 0x50, 0x00, 0x06, 0x60, 5278c2ecf20Sopenharmony_ci 0x40, 0x0e, 0x60, 0x05, 0x33, 0x10, 0x00, 0x04 }, 5288c2ecf20Sopenharmony_ci [ATSC] = { 0x51, 0x03, 0x83, 0x82, 0x40, 0x48, 0x01, 0xe0, 5298c2ecf20Sopenharmony_ci 0x40, 0x0e, 0x60, 0x05, 0x03, 0x00, 0x80, 0x04 }, 5308c2ecf20Sopenharmony_ci }; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci dev_dbg(&client->dev, 5338c2ecf20Sopenharmony_ci "delivery_system=%d frequency=%u bandwidth_hz=%u", 5348c2ecf20Sopenharmony_ci c->delivery_system, c->frequency, c->bandwidth_hz); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci switch (c->delivery_system) { 5388c2ecf20Sopenharmony_ci case SYS_ATSC: 5398c2ecf20Sopenharmony_ci j = ATSC; 5408c2ecf20Sopenharmony_ci if_khz = dev->if_atsc; 5418c2ecf20Sopenharmony_ci break; 5428c2ecf20Sopenharmony_ci case SYS_DVBT: 5438c2ecf20Sopenharmony_ci case SYS_DVBT2: 5448c2ecf20Sopenharmony_ci if (c->bandwidth_hz == 0) { 5458c2ecf20Sopenharmony_ci ret = -EINVAL; 5468c2ecf20Sopenharmony_ci goto err; 5478c2ecf20Sopenharmony_ci } else if (c->bandwidth_hz <= 6000000) { 5488c2ecf20Sopenharmony_ci j = DVBT_6; 5498c2ecf20Sopenharmony_ci if_khz = dev->if_dvbt_6; 5508c2ecf20Sopenharmony_ci } else if (c->bandwidth_hz <= 7000000) { 5518c2ecf20Sopenharmony_ci j = DVBT_7; 5528c2ecf20Sopenharmony_ci if_khz = dev->if_dvbt_7; 5538c2ecf20Sopenharmony_ci } else if (c->bandwidth_hz <= 8000000) { 5548c2ecf20Sopenharmony_ci j = DVBT_8; 5558c2ecf20Sopenharmony_ci if_khz = dev->if_dvbt_8; 5568c2ecf20Sopenharmony_ci } else { 5578c2ecf20Sopenharmony_ci ret = -EINVAL; 5588c2ecf20Sopenharmony_ci goto err; 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci break; 5618c2ecf20Sopenharmony_ci case SYS_DVBC_ANNEX_A: 5628c2ecf20Sopenharmony_ci case SYS_DVBC_ANNEX_C: 5638c2ecf20Sopenharmony_ci if (c->bandwidth_hz == 0) { 5648c2ecf20Sopenharmony_ci ret = -EINVAL; 5658c2ecf20Sopenharmony_ci goto err; 5668c2ecf20Sopenharmony_ci } else if (c->bandwidth_hz <= 6000000) { 5678c2ecf20Sopenharmony_ci j = DVBC_6; 5688c2ecf20Sopenharmony_ci if_khz = dev->if_dvbc_6; 5698c2ecf20Sopenharmony_ci } else if (c->bandwidth_hz <= 8000000) { 5708c2ecf20Sopenharmony_ci j = DVBC_8; 5718c2ecf20Sopenharmony_ci if_khz = dev->if_dvbc_8; 5728c2ecf20Sopenharmony_ci } else { 5738c2ecf20Sopenharmony_ci ret = -EINVAL; 5748c2ecf20Sopenharmony_ci goto err; 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci break; 5778c2ecf20Sopenharmony_ci default: 5788c2ecf20Sopenharmony_ci ret = -EINVAL; 5798c2ecf20Sopenharmony_ci dev_err(&client->dev, "unsupported delivery system=%d", 5808c2ecf20Sopenharmony_ci c->delivery_system); 5818c2ecf20Sopenharmony_ci goto err; 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci /* set delivery system dependent registers */ 5858c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 5868c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, delsys_params[REG][i], 5878c2ecf20Sopenharmony_ci delsys_params[MASK][i], delsys_params[j][i]); 5888c2ecf20Sopenharmony_ci if (ret) 5898c2ecf20Sopenharmony_ci goto err; 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci /* set IF if needed */ 5938c2ecf20Sopenharmony_ci if (dev->if_frequency != if_khz) { 5948c2ecf20Sopenharmony_ci utmp = DIV_ROUND_CLOSEST(if_khz, 50); 5958c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R26_IF, utmp); 5968c2ecf20Sopenharmony_ci if (ret) 5978c2ecf20Sopenharmony_ci goto err; 5988c2ecf20Sopenharmony_ci dev->if_frequency = if_khz; 5998c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "set IF=%u kHz", if_khz); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci ret = tda18250_set_agc(fe); 6048c2ecf20Sopenharmony_ci if (ret) 6058c2ecf20Sopenharmony_ci goto err; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R1A_AGCK, 0x03, 0x01); 6088c2ecf20Sopenharmony_ci if (ret) 6098c2ecf20Sopenharmony_ci goto err; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R14_AGC23, 0x40, 0x00); 6128c2ecf20Sopenharmony_ci if (ret) 6138c2ecf20Sopenharmony_ci goto err; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /* set frequency */ 6168c2ecf20Sopenharmony_ci buf[0] = ((c->frequency / 1000) >> 16) & 0xff; 6178c2ecf20Sopenharmony_ci buf[1] = ((c->frequency / 1000) >> 8) & 0xff; 6188c2ecf20Sopenharmony_ci buf[2] = ((c->frequency / 1000) >> 0) & 0xff; 6198c2ecf20Sopenharmony_ci ret = regmap_bulk_write(dev->regmap, R27_RF1, buf, 3); 6208c2ecf20Sopenharmony_ci if (ret) 6218c2ecf20Sopenharmony_ci goto err; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R0A_IRQ3, TDA18250_IRQ_TUNE); 6248c2ecf20Sopenharmony_ci if (ret) 6258c2ecf20Sopenharmony_ci goto err; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci /* initial tune */ 6288c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R2A_MSM1, 0x01); 6298c2ecf20Sopenharmony_ci if (ret) 6308c2ecf20Sopenharmony_ci goto err; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R2B_MSM2, 0x01); 6338c2ecf20Sopenharmony_ci if (ret) 6348c2ecf20Sopenharmony_ci goto err; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci ret = tda18250_wait_for_irq(fe, 500, 10, TDA18250_IRQ_TUNE); 6378c2ecf20Sopenharmony_ci if (ret) 6388c2ecf20Sopenharmony_ci goto err; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci /* calc ndiv and rdiv */ 6418c2ecf20Sopenharmony_ci ret = tda18250_pll_calc(fe, &buf[0], &buf[1], &buf[2]); 6428c2ecf20Sopenharmony_ci if (ret) 6438c2ecf20Sopenharmony_ci goto err; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R4F_XTALFLX3, 0xe0, 6468c2ecf20Sopenharmony_ci (buf[0] << 6) | (buf[1] << 5)); 6478c2ecf20Sopenharmony_ci if (ret) 6488c2ecf20Sopenharmony_ci goto err; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci /* clear IRQ */ 6518c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R0A_IRQ3, TDA18250_IRQ_TUNE); 6528c2ecf20Sopenharmony_ci if (ret) 6538c2ecf20Sopenharmony_ci goto err; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R46_CPUMP, 0x07, 0x00); 6568c2ecf20Sopenharmony_ci if (ret) 6578c2ecf20Sopenharmony_ci goto err; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R39_SD5, 0x03, 0x00); 6608c2ecf20Sopenharmony_ci if (ret) 6618c2ecf20Sopenharmony_ci goto err; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci /* tune again */ 6648c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R2A_MSM1, 0x01); /* tune */ 6658c2ecf20Sopenharmony_ci if (ret) 6668c2ecf20Sopenharmony_ci goto err; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, R2B_MSM2, 0x01); /* go */ 6698c2ecf20Sopenharmony_ci if (ret) 6708c2ecf20Sopenharmony_ci goto err; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci ret = tda18250_wait_for_irq(fe, 500, 10, TDA18250_IRQ_TUNE); 6738c2ecf20Sopenharmony_ci if (ret) 6748c2ecf20Sopenharmony_ci goto err; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci /* pll locking */ 6778c2ecf20Sopenharmony_ci msleep(20); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R2B_MSM2, 0x04, 0x04); 6808c2ecf20Sopenharmony_ci if (ret) 6818c2ecf20Sopenharmony_ci goto err; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci msleep(20); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci /* restore AGCK */ 6868c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R1A_AGCK, 0x03, 0x03); 6878c2ecf20Sopenharmony_ci if (ret) 6888c2ecf20Sopenharmony_ci goto err; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R14_AGC23, 0x40, 0x40); 6918c2ecf20Sopenharmony_ci if (ret) 6928c2ecf20Sopenharmony_ci goto err; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci /* charge pump */ 6958c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R46_CPUMP, 0x07, buf[2]); 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci return 0; 6988c2ecf20Sopenharmony_cierr: 6998c2ecf20Sopenharmony_ci return ret; 7008c2ecf20Sopenharmony_ci} 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_cistatic int tda18250_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 7038c2ecf20Sopenharmony_ci{ 7048c2ecf20Sopenharmony_ci struct i2c_client *client = fe->tuner_priv; 7058c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci *frequency = dev->if_frequency * 1000; 7088c2ecf20Sopenharmony_ci return 0; 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_cistatic int tda18250_sleep(struct dvb_frontend *fe) 7128c2ecf20Sopenharmony_ci{ 7138c2ecf20Sopenharmony_ci struct i2c_client *client = fe->tuner_priv; 7148c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 7158c2ecf20Sopenharmony_ci int ret; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci /* power down LNA */ 7208c2ecf20Sopenharmony_ci ret = regmap_write_bits(dev->regmap, R0C_AGC11, 0x80, 0x00); 7218c2ecf20Sopenharmony_ci if (ret) 7228c2ecf20Sopenharmony_ci return ret; 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci /* set if freq to 0 in order to make sure it's set after wake up */ 7258c2ecf20Sopenharmony_ci dev->if_frequency = 0; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci ret = tda18250_power_control(fe, TDA18250_POWER_STANDBY); 7288c2ecf20Sopenharmony_ci return ret; 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops tda18250_ops = { 7328c2ecf20Sopenharmony_ci .info = { 7338c2ecf20Sopenharmony_ci .name = "NXP TDA18250", 7348c2ecf20Sopenharmony_ci .frequency_min_hz = 42 * MHz, 7358c2ecf20Sopenharmony_ci .frequency_max_hz = 870 * MHz, 7368c2ecf20Sopenharmony_ci }, 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci .init = tda18250_init, 7398c2ecf20Sopenharmony_ci .set_params = tda18250_set_params, 7408c2ecf20Sopenharmony_ci .get_if_frequency = tda18250_get_if_frequency, 7418c2ecf20Sopenharmony_ci .sleep = tda18250_sleep, 7428c2ecf20Sopenharmony_ci}; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_cistatic int tda18250_probe(struct i2c_client *client, 7458c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 7468c2ecf20Sopenharmony_ci{ 7478c2ecf20Sopenharmony_ci struct tda18250_config *cfg = client->dev.platform_data; 7488c2ecf20Sopenharmony_ci struct dvb_frontend *fe = cfg->fe; 7498c2ecf20Sopenharmony_ci struct tda18250_dev *dev; 7508c2ecf20Sopenharmony_ci int ret; 7518c2ecf20Sopenharmony_ci unsigned char chip_id[3]; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci /* some registers are always read from HW */ 7548c2ecf20Sopenharmony_ci static const struct regmap_range tda18250_yes_ranges[] = { 7558c2ecf20Sopenharmony_ci regmap_reg_range(R05_POWER1, R0B_IRQ4), 7568c2ecf20Sopenharmony_ci regmap_reg_range(R21_IF_AGC, R21_IF_AGC), 7578c2ecf20Sopenharmony_ci regmap_reg_range(R2A_MSM1, R2B_MSM2), 7588c2ecf20Sopenharmony_ci regmap_reg_range(R2F_RSSI1, R31_IRQ_CTRL), 7598c2ecf20Sopenharmony_ci }; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci static const struct regmap_access_table tda18250_volatile_table = { 7628c2ecf20Sopenharmony_ci .yes_ranges = tda18250_yes_ranges, 7638c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(tda18250_yes_ranges), 7648c2ecf20Sopenharmony_ci }; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci static const struct regmap_config tda18250_regmap_config = { 7678c2ecf20Sopenharmony_ci .reg_bits = 8, 7688c2ecf20Sopenharmony_ci .val_bits = 8, 7698c2ecf20Sopenharmony_ci .max_register = TDA18250_NUM_REGS - 1, 7708c2ecf20Sopenharmony_ci .volatile_table = &tda18250_volatile_table, 7718c2ecf20Sopenharmony_ci }; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci dev = kzalloc(sizeof(*dev), GFP_KERNEL); 7748c2ecf20Sopenharmony_ci if (!dev) { 7758c2ecf20Sopenharmony_ci ret = -ENOMEM; 7768c2ecf20Sopenharmony_ci goto err; 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci i2c_set_clientdata(client, dev); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci dev->fe = cfg->fe; 7828c2ecf20Sopenharmony_ci dev->loopthrough = cfg->loopthrough; 7838c2ecf20Sopenharmony_ci if (cfg->xtal_freq < TDA18250_XTAL_FREQ_MAX) { 7848c2ecf20Sopenharmony_ci dev->xtal_freq = cfg->xtal_freq; 7858c2ecf20Sopenharmony_ci } else { 7868c2ecf20Sopenharmony_ci ret = -EINVAL; 7878c2ecf20Sopenharmony_ci dev_err(&client->dev, "xtal_freq invalid=%d", cfg->xtal_freq); 7888c2ecf20Sopenharmony_ci goto err_kfree; 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci dev->if_dvbt_6 = cfg->if_dvbt_6; 7918c2ecf20Sopenharmony_ci dev->if_dvbt_7 = cfg->if_dvbt_7; 7928c2ecf20Sopenharmony_ci dev->if_dvbt_8 = cfg->if_dvbt_8; 7938c2ecf20Sopenharmony_ci dev->if_dvbc_6 = cfg->if_dvbc_6; 7948c2ecf20Sopenharmony_ci dev->if_dvbc_8 = cfg->if_dvbc_8; 7958c2ecf20Sopenharmony_ci dev->if_atsc = cfg->if_atsc; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci dev->if_frequency = 0; 7988c2ecf20Sopenharmony_ci dev->warm = false; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci dev->regmap = devm_regmap_init_i2c(client, &tda18250_regmap_config); 8018c2ecf20Sopenharmony_ci if (IS_ERR(dev->regmap)) { 8028c2ecf20Sopenharmony_ci ret = PTR_ERR(dev->regmap); 8038c2ecf20Sopenharmony_ci goto err_kfree; 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci /* read the three chip ID registers */ 8078c2ecf20Sopenharmony_ci regmap_bulk_read(dev->regmap, R00_ID1, &chip_id, 3); 8088c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "chip_id=%02x:%02x:%02x", 8098c2ecf20Sopenharmony_ci chip_id[0], chip_id[1], chip_id[2]); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci switch (chip_id[0]) { 8128c2ecf20Sopenharmony_ci case 0xc7: 8138c2ecf20Sopenharmony_ci dev->slave = false; 8148c2ecf20Sopenharmony_ci break; 8158c2ecf20Sopenharmony_ci case 0x47: 8168c2ecf20Sopenharmony_ci dev->slave = true; 8178c2ecf20Sopenharmony_ci break; 8188c2ecf20Sopenharmony_ci default: 8198c2ecf20Sopenharmony_ci ret = -ENODEV; 8208c2ecf20Sopenharmony_ci goto err_kfree; 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci if (chip_id[1] != 0x4a) { 8248c2ecf20Sopenharmony_ci ret = -ENODEV; 8258c2ecf20Sopenharmony_ci goto err_kfree; 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci switch (chip_id[2]) { 8298c2ecf20Sopenharmony_ci case 0x20: 8308c2ecf20Sopenharmony_ci dev_info(&client->dev, 8318c2ecf20Sopenharmony_ci "NXP TDA18250AHN/%s successfully identified", 8328c2ecf20Sopenharmony_ci dev->slave ? "S" : "M"); 8338c2ecf20Sopenharmony_ci break; 8348c2ecf20Sopenharmony_ci case 0x21: 8358c2ecf20Sopenharmony_ci dev_info(&client->dev, 8368c2ecf20Sopenharmony_ci "NXP TDA18250BHN/%s successfully identified", 8378c2ecf20Sopenharmony_ci dev->slave ? "S" : "M"); 8388c2ecf20Sopenharmony_ci break; 8398c2ecf20Sopenharmony_ci default: 8408c2ecf20Sopenharmony_ci ret = -ENODEV; 8418c2ecf20Sopenharmony_ci goto err_kfree; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci fe->tuner_priv = client; 8458c2ecf20Sopenharmony_ci memcpy(&fe->ops.tuner_ops, &tda18250_ops, 8468c2ecf20Sopenharmony_ci sizeof(struct dvb_tuner_ops)); 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci /* put the tuner in standby */ 8498c2ecf20Sopenharmony_ci tda18250_power_control(fe, TDA18250_POWER_STANDBY); 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci return 0; 8528c2ecf20Sopenharmony_cierr_kfree: 8538c2ecf20Sopenharmony_ci kfree(dev); 8548c2ecf20Sopenharmony_cierr: 8558c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d", ret); 8568c2ecf20Sopenharmony_ci return ret; 8578c2ecf20Sopenharmony_ci} 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_cistatic int tda18250_remove(struct i2c_client *client) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci struct tda18250_dev *dev = i2c_get_clientdata(client); 8628c2ecf20Sopenharmony_ci struct dvb_frontend *fe = dev->fe; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); 8678c2ecf20Sopenharmony_ci fe->tuner_priv = NULL; 8688c2ecf20Sopenharmony_ci kfree(dev); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci return 0; 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_cistatic const struct i2c_device_id tda18250_id_table[] = { 8748c2ecf20Sopenharmony_ci {"tda18250", 0}, 8758c2ecf20Sopenharmony_ci {} 8768c2ecf20Sopenharmony_ci}; 8778c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, tda18250_id_table); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic struct i2c_driver tda18250_driver = { 8808c2ecf20Sopenharmony_ci .driver = { 8818c2ecf20Sopenharmony_ci .name = "tda18250", 8828c2ecf20Sopenharmony_ci }, 8838c2ecf20Sopenharmony_ci .probe = tda18250_probe, 8848c2ecf20Sopenharmony_ci .remove = tda18250_remove, 8858c2ecf20Sopenharmony_ci .id_table = tda18250_id_table, 8868c2ecf20Sopenharmony_ci}; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_cimodule_i2c_driver(tda18250_driver); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("NXP TDA18250 silicon tuner driver"); 8918c2ecf20Sopenharmony_ciMODULE_AUTHOR("Olli Salonen <olli.salonen@iki.fi>"); 8928c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 893