18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Afatech AF9033 demodulator driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 68c2ecf20Sopenharmony_ci * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "af9033_priv.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistruct af9033_dev { 128c2ecf20Sopenharmony_ci struct i2c_client *client; 138c2ecf20Sopenharmony_ci struct regmap *regmap; 148c2ecf20Sopenharmony_ci struct dvb_frontend fe; 158c2ecf20Sopenharmony_ci struct af9033_config cfg; 168c2ecf20Sopenharmony_ci bool is_af9035; 178c2ecf20Sopenharmony_ci bool is_it9135; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci u32 bandwidth_hz; 208c2ecf20Sopenharmony_ci bool ts_mode_parallel; 218c2ecf20Sopenharmony_ci bool ts_mode_serial; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci enum fe_status fe_status; 248c2ecf20Sopenharmony_ci u64 post_bit_error_prev; /* for old read_ber we return (curr - prev) */ 258c2ecf20Sopenharmony_ci u64 post_bit_error; 268c2ecf20Sopenharmony_ci u64 post_bit_count; 278c2ecf20Sopenharmony_ci u64 error_block_count; 288c2ecf20Sopenharmony_ci u64 total_block_count; 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* Write reg val table using reg addr auto increment */ 328c2ecf20Sopenharmony_cistatic int af9033_wr_reg_val_tab(struct af9033_dev *dev, 338c2ecf20Sopenharmony_ci const struct reg_val *tab, int tab_len) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 368c2ecf20Sopenharmony_ci#define MAX_TAB_LEN 212 378c2ecf20Sopenharmony_ci int ret, i, j; 388c2ecf20Sopenharmony_ci u8 buf[1 + MAX_TAB_LEN]; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "tab_len=%d\n", tab_len); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci if (tab_len > sizeof(buf)) { 438c2ecf20Sopenharmony_ci dev_warn(&client->dev, "tab len %d is too big\n", tab_len); 448c2ecf20Sopenharmony_ci return -EINVAL; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci for (i = 0, j = 0; i < tab_len; i++) { 488c2ecf20Sopenharmony_ci buf[j] = tab[i].val; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) { 518c2ecf20Sopenharmony_ci ret = regmap_bulk_write(dev->regmap, tab[i].reg - j, 528c2ecf20Sopenharmony_ci buf, j + 1); 538c2ecf20Sopenharmony_ci if (ret) 548c2ecf20Sopenharmony_ci goto err; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci j = 0; 578c2ecf20Sopenharmony_ci } else { 588c2ecf20Sopenharmony_ci j++; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci return 0; 638c2ecf20Sopenharmony_cierr: 648c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 658c2ecf20Sopenharmony_ci return ret; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic int af9033_init(struct dvb_frontend *fe) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 718c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 728c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 738c2ecf20Sopenharmony_ci int ret, i, len; 748c2ecf20Sopenharmony_ci unsigned int utmp; 758c2ecf20Sopenharmony_ci const struct reg_val *init; 768c2ecf20Sopenharmony_ci u8 buf[4]; 778c2ecf20Sopenharmony_ci struct reg_val_mask tab[] = { 788c2ecf20Sopenharmony_ci { 0x80fb24, 0x00, 0x08 }, 798c2ecf20Sopenharmony_ci { 0x80004c, 0x00, 0xff }, 808c2ecf20Sopenharmony_ci { 0x00f641, dev->cfg.tuner, 0xff }, 818c2ecf20Sopenharmony_ci { 0x80f5ca, 0x01, 0x01 }, 828c2ecf20Sopenharmony_ci { 0x80f715, 0x01, 0x01 }, 838c2ecf20Sopenharmony_ci { 0x00f41f, 0x04, 0x04 }, 848c2ecf20Sopenharmony_ci { 0x00f41a, 0x01, 0x01 }, 858c2ecf20Sopenharmony_ci { 0x80f731, 0x00, 0x01 }, 868c2ecf20Sopenharmony_ci { 0x00d91e, 0x00, 0x01 }, 878c2ecf20Sopenharmony_ci { 0x00d919, 0x00, 0x01 }, 888c2ecf20Sopenharmony_ci { 0x80f732, 0x00, 0x01 }, 898c2ecf20Sopenharmony_ci { 0x00d91f, 0x00, 0x01 }, 908c2ecf20Sopenharmony_ci { 0x00d91a, 0x00, 0x01 }, 918c2ecf20Sopenharmony_ci { 0x80f730, 0x00, 0x01 }, 928c2ecf20Sopenharmony_ci { 0x80f778, 0x00, 0xff }, 938c2ecf20Sopenharmony_ci { 0x80f73c, 0x01, 0x01 }, 948c2ecf20Sopenharmony_ci { 0x80f776, 0x00, 0x01 }, 958c2ecf20Sopenharmony_ci { 0x00d8fd, 0x01, 0xff }, 968c2ecf20Sopenharmony_ci { 0x00d830, 0x01, 0xff }, 978c2ecf20Sopenharmony_ci { 0x00d831, 0x00, 0xff }, 988c2ecf20Sopenharmony_ci { 0x00d832, 0x00, 0xff }, 998c2ecf20Sopenharmony_ci { 0x80f985, dev->ts_mode_serial, 0x01 }, 1008c2ecf20Sopenharmony_ci { 0x80f986, dev->ts_mode_parallel, 0x01 }, 1018c2ecf20Sopenharmony_ci { 0x00d827, 0x00, 0xff }, 1028c2ecf20Sopenharmony_ci { 0x00d829, 0x00, 0xff }, 1038c2ecf20Sopenharmony_ci { 0x800045, dev->cfg.adc_multiplier, 0xff }, 1048c2ecf20Sopenharmony_ci }; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* Main clk control */ 1098c2ecf20Sopenharmony_ci utmp = div_u64((u64)dev->cfg.clock * 0x80000, 1000000); 1108c2ecf20Sopenharmony_ci buf[0] = (utmp >> 0) & 0xff; 1118c2ecf20Sopenharmony_ci buf[1] = (utmp >> 8) & 0xff; 1128c2ecf20Sopenharmony_ci buf[2] = (utmp >> 16) & 0xff; 1138c2ecf20Sopenharmony_ci buf[3] = (utmp >> 24) & 0xff; 1148c2ecf20Sopenharmony_ci ret = regmap_bulk_write(dev->regmap, 0x800025, buf, 4); 1158c2ecf20Sopenharmony_ci if (ret) 1168c2ecf20Sopenharmony_ci goto err; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "clk=%u clk_cw=%08x\n", dev->cfg.clock, utmp); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* ADC clk control */ 1218c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { 1228c2ecf20Sopenharmony_ci if (clock_adc_lut[i].clock == dev->cfg.clock) 1238c2ecf20Sopenharmony_ci break; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci if (i == ARRAY_SIZE(clock_adc_lut)) { 1268c2ecf20Sopenharmony_ci dev_err(&client->dev, "Couldn't find ADC config for clock %d\n", 1278c2ecf20Sopenharmony_ci dev->cfg.clock); 1288c2ecf20Sopenharmony_ci goto err; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci utmp = div_u64((u64)clock_adc_lut[i].adc * 0x80000, 1000000); 1328c2ecf20Sopenharmony_ci buf[0] = (utmp >> 0) & 0xff; 1338c2ecf20Sopenharmony_ci buf[1] = (utmp >> 8) & 0xff; 1348c2ecf20Sopenharmony_ci buf[2] = (utmp >> 16) & 0xff; 1358c2ecf20Sopenharmony_ci ret = regmap_bulk_write(dev->regmap, 0x80f1cd, buf, 3); 1368c2ecf20Sopenharmony_ci if (ret) 1378c2ecf20Sopenharmony_ci goto err; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "adc=%u adc_cw=%06x\n", 1408c2ecf20Sopenharmony_ci clock_adc_lut[i].adc, utmp); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* Config register table */ 1438c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tab); i++) { 1448c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, tab[i].reg, tab[i].mask, 1458c2ecf20Sopenharmony_ci tab[i].val); 1468c2ecf20Sopenharmony_ci if (ret) 1478c2ecf20Sopenharmony_ci goto err; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* Demod clk output */ 1518c2ecf20Sopenharmony_ci if (dev->cfg.dyn0_clk) { 1528c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x80fba8, 0x00); 1538c2ecf20Sopenharmony_ci if (ret) 1548c2ecf20Sopenharmony_ci goto err; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* TS interface */ 1588c2ecf20Sopenharmony_ci if (dev->cfg.ts_mode == AF9033_TS_MODE_USB) { 1598c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x80f9a5, 0x01, 0x00); 1608c2ecf20Sopenharmony_ci if (ret) 1618c2ecf20Sopenharmony_ci goto err; 1628c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x80f9b5, 0x01, 0x01); 1638c2ecf20Sopenharmony_ci if (ret) 1648c2ecf20Sopenharmony_ci goto err; 1658c2ecf20Sopenharmony_ci } else { 1668c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x80f990, 0x01, 0x00); 1678c2ecf20Sopenharmony_ci if (ret) 1688c2ecf20Sopenharmony_ci goto err; 1698c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x80f9b5, 0x01, 0x00); 1708c2ecf20Sopenharmony_ci if (ret) 1718c2ecf20Sopenharmony_ci goto err; 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci /* Demod core settings */ 1758c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "load ofsm settings\n"); 1768c2ecf20Sopenharmony_ci switch (dev->cfg.tuner) { 1778c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 1788c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 1798c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 1808c2ecf20Sopenharmony_ci len = ARRAY_SIZE(ofsm_init_it9135_v1); 1818c2ecf20Sopenharmony_ci init = ofsm_init_it9135_v1; 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 1848c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 1858c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 1868c2ecf20Sopenharmony_ci len = ARRAY_SIZE(ofsm_init_it9135_v2); 1878c2ecf20Sopenharmony_ci init = ofsm_init_it9135_v2; 1888c2ecf20Sopenharmony_ci break; 1898c2ecf20Sopenharmony_ci default: 1908c2ecf20Sopenharmony_ci len = ARRAY_SIZE(ofsm_init); 1918c2ecf20Sopenharmony_ci init = ofsm_init; 1928c2ecf20Sopenharmony_ci break; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci ret = af9033_wr_reg_val_tab(dev, init, len); 1968c2ecf20Sopenharmony_ci if (ret) 1978c2ecf20Sopenharmony_ci goto err; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* Demod tuner specific settings */ 2008c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "load tuner specific settings\n"); 2018c2ecf20Sopenharmony_ci switch (dev->cfg.tuner) { 2028c2ecf20Sopenharmony_ci case AF9033_TUNER_TUA9001: 2038c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tua9001); 2048c2ecf20Sopenharmony_ci init = tuner_init_tua9001; 2058c2ecf20Sopenharmony_ci break; 2068c2ecf20Sopenharmony_ci case AF9033_TUNER_FC0011: 2078c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_fc0011); 2088c2ecf20Sopenharmony_ci init = tuner_init_fc0011; 2098c2ecf20Sopenharmony_ci break; 2108c2ecf20Sopenharmony_ci case AF9033_TUNER_MXL5007T: 2118c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_mxl5007t); 2128c2ecf20Sopenharmony_ci init = tuner_init_mxl5007t; 2138c2ecf20Sopenharmony_ci break; 2148c2ecf20Sopenharmony_ci case AF9033_TUNER_TDA18218: 2158c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tda18218); 2168c2ecf20Sopenharmony_ci init = tuner_init_tda18218; 2178c2ecf20Sopenharmony_ci break; 2188c2ecf20Sopenharmony_ci case AF9033_TUNER_FC2580: 2198c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_fc2580); 2208c2ecf20Sopenharmony_ci init = tuner_init_fc2580; 2218c2ecf20Sopenharmony_ci break; 2228c2ecf20Sopenharmony_ci case AF9033_TUNER_FC0012: 2238c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_fc0012); 2248c2ecf20Sopenharmony_ci init = tuner_init_fc0012; 2258c2ecf20Sopenharmony_ci break; 2268c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 2278c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_it9135_38); 2288c2ecf20Sopenharmony_ci init = tuner_init_it9135_38; 2298c2ecf20Sopenharmony_ci break; 2308c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 2318c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_it9135_51); 2328c2ecf20Sopenharmony_ci init = tuner_init_it9135_51; 2338c2ecf20Sopenharmony_ci break; 2348c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 2358c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_it9135_52); 2368c2ecf20Sopenharmony_ci init = tuner_init_it9135_52; 2378c2ecf20Sopenharmony_ci break; 2388c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 2398c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_it9135_60); 2408c2ecf20Sopenharmony_ci init = tuner_init_it9135_60; 2418c2ecf20Sopenharmony_ci break; 2428c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 2438c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_it9135_61); 2448c2ecf20Sopenharmony_ci init = tuner_init_it9135_61; 2458c2ecf20Sopenharmony_ci break; 2468c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 2478c2ecf20Sopenharmony_ci len = ARRAY_SIZE(tuner_init_it9135_62); 2488c2ecf20Sopenharmony_ci init = tuner_init_it9135_62; 2498c2ecf20Sopenharmony_ci break; 2508c2ecf20Sopenharmony_ci default: 2518c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "unsupported tuner ID=%d\n", 2528c2ecf20Sopenharmony_ci dev->cfg.tuner); 2538c2ecf20Sopenharmony_ci ret = -ENODEV; 2548c2ecf20Sopenharmony_ci goto err; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci ret = af9033_wr_reg_val_tab(dev, init, len); 2588c2ecf20Sopenharmony_ci if (ret) 2598c2ecf20Sopenharmony_ci goto err; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { 2628c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x00d91c, 0x01, 0x01); 2638c2ecf20Sopenharmony_ci if (ret) 2648c2ecf20Sopenharmony_ci goto err; 2658c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x00d917, 0x01, 0x00); 2668c2ecf20Sopenharmony_ci if (ret) 2678c2ecf20Sopenharmony_ci goto err; 2688c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x00d916, 0x01, 0x00); 2698c2ecf20Sopenharmony_ci if (ret) 2708c2ecf20Sopenharmony_ci goto err; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci switch (dev->cfg.tuner) { 2748c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 2758c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 2768c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 2778c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x800000, 0x01); 2788c2ecf20Sopenharmony_ci if (ret) 2798c2ecf20Sopenharmony_ci goto err; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci dev->bandwidth_hz = 0; /* Force to program all parameters */ 2838c2ecf20Sopenharmony_ci /* Init stats here in order signal app which stats are supported */ 2848c2ecf20Sopenharmony_ci c->strength.len = 1; 2858c2ecf20Sopenharmony_ci c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2868c2ecf20Sopenharmony_ci c->cnr.len = 1; 2878c2ecf20Sopenharmony_ci c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2888c2ecf20Sopenharmony_ci c->block_count.len = 1; 2898c2ecf20Sopenharmony_ci c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2908c2ecf20Sopenharmony_ci c->block_error.len = 1; 2918c2ecf20Sopenharmony_ci c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2928c2ecf20Sopenharmony_ci c->post_bit_count.len = 1; 2938c2ecf20Sopenharmony_ci c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2948c2ecf20Sopenharmony_ci c->post_bit_error.len = 1; 2958c2ecf20Sopenharmony_ci c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return 0; 2988c2ecf20Sopenharmony_cierr: 2998c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 3008c2ecf20Sopenharmony_ci return ret; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic int af9033_sleep(struct dvb_frontend *fe) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 3068c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 3078c2ecf20Sopenharmony_ci int ret; 3088c2ecf20Sopenharmony_ci unsigned int utmp; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x80004c, 0x01); 3138c2ecf20Sopenharmony_ci if (ret) 3148c2ecf20Sopenharmony_ci goto err; 3158c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x800000, 0x00); 3168c2ecf20Sopenharmony_ci if (ret) 3178c2ecf20Sopenharmony_ci goto err; 3188c2ecf20Sopenharmony_ci ret = regmap_read_poll_timeout(dev->regmap, 0x80004c, utmp, utmp == 0, 3198c2ecf20Sopenharmony_ci 5000, 1000000); 3208c2ecf20Sopenharmony_ci if (ret) 3218c2ecf20Sopenharmony_ci goto err; 3228c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x80fb24, 0x08, 0x08); 3238c2ecf20Sopenharmony_ci if (ret) 3248c2ecf20Sopenharmony_ci goto err; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* Prevent current leak by setting TS interface to parallel mode */ 3278c2ecf20Sopenharmony_ci if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { 3288c2ecf20Sopenharmony_ci /* Enable parallel TS */ 3298c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x00d917, 0x01, 0x00); 3308c2ecf20Sopenharmony_ci if (ret) 3318c2ecf20Sopenharmony_ci goto err; 3328c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x00d916, 0x01, 0x01); 3338c2ecf20Sopenharmony_ci if (ret) 3348c2ecf20Sopenharmony_ci goto err; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci return 0; 3388c2ecf20Sopenharmony_cierr: 3398c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 3408c2ecf20Sopenharmony_ci return ret; 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic int af9033_get_tune_settings(struct dvb_frontend *fe, 3448c2ecf20Sopenharmony_ci struct dvb_frontend_tune_settings *fesettings) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci /* 800 => 2000 because IT9135 v2 is slow to gain lock */ 3478c2ecf20Sopenharmony_ci fesettings->min_delay_ms = 2000; 3488c2ecf20Sopenharmony_ci fesettings->step_size = 0; 3498c2ecf20Sopenharmony_ci fesettings->max_drift = 0; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci return 0; 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic int af9033_set_frontend(struct dvb_frontend *fe) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 3578c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 3588c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 3598c2ecf20Sopenharmony_ci int ret, i; 3608c2ecf20Sopenharmony_ci unsigned int utmp, adc_freq; 3618c2ecf20Sopenharmony_ci u8 tmp, buf[3], bandwidth_reg_val; 3628c2ecf20Sopenharmony_ci u32 if_frequency; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u\n", 3658c2ecf20Sopenharmony_ci c->frequency, c->bandwidth_hz); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /* Check bandwidth */ 3688c2ecf20Sopenharmony_ci switch (c->bandwidth_hz) { 3698c2ecf20Sopenharmony_ci case 6000000: 3708c2ecf20Sopenharmony_ci bandwidth_reg_val = 0x00; 3718c2ecf20Sopenharmony_ci break; 3728c2ecf20Sopenharmony_ci case 7000000: 3738c2ecf20Sopenharmony_ci bandwidth_reg_val = 0x01; 3748c2ecf20Sopenharmony_ci break; 3758c2ecf20Sopenharmony_ci case 8000000: 3768c2ecf20Sopenharmony_ci bandwidth_reg_val = 0x02; 3778c2ecf20Sopenharmony_ci break; 3788c2ecf20Sopenharmony_ci default: 3798c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "invalid bandwidth_hz\n"); 3808c2ecf20Sopenharmony_ci ret = -EINVAL; 3818c2ecf20Sopenharmony_ci goto err; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci /* Program tuner */ 3858c2ecf20Sopenharmony_ci if (fe->ops.tuner_ops.set_params) 3868c2ecf20Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci /* Coefficients */ 3898c2ecf20Sopenharmony_ci if (c->bandwidth_hz != dev->bandwidth_hz) { 3908c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { 3918c2ecf20Sopenharmony_ci if (coeff_lut[i].clock == dev->cfg.clock && 3928c2ecf20Sopenharmony_ci coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { 3938c2ecf20Sopenharmony_ci break; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci if (i == ARRAY_SIZE(coeff_lut)) { 3978c2ecf20Sopenharmony_ci dev_err(&client->dev, 3988c2ecf20Sopenharmony_ci "Couldn't find config for clock %u\n", 3998c2ecf20Sopenharmony_ci dev->cfg.clock); 4008c2ecf20Sopenharmony_ci ret = -EINVAL; 4018c2ecf20Sopenharmony_ci goto err; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci ret = regmap_bulk_write(dev->regmap, 0x800001, coeff_lut[i].val, 4058c2ecf20Sopenharmony_ci sizeof(coeff_lut[i].val)); 4068c2ecf20Sopenharmony_ci if (ret) 4078c2ecf20Sopenharmony_ci goto err; 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* IF frequency control */ 4118c2ecf20Sopenharmony_ci if (c->bandwidth_hz != dev->bandwidth_hz) { 4128c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { 4138c2ecf20Sopenharmony_ci if (clock_adc_lut[i].clock == dev->cfg.clock) 4148c2ecf20Sopenharmony_ci break; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci if (i == ARRAY_SIZE(clock_adc_lut)) { 4178c2ecf20Sopenharmony_ci dev_err(&client->dev, 4188c2ecf20Sopenharmony_ci "Couldn't find ADC clock for clock %u\n", 4198c2ecf20Sopenharmony_ci dev->cfg.clock); 4208c2ecf20Sopenharmony_ci ret = -EINVAL; 4218c2ecf20Sopenharmony_ci goto err; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci adc_freq = clock_adc_lut[i].adc; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (dev->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X) 4268c2ecf20Sopenharmony_ci adc_freq = 2 * adc_freq; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci /* Get used IF frequency */ 4298c2ecf20Sopenharmony_ci if (fe->ops.tuner_ops.get_if_frequency) 4308c2ecf20Sopenharmony_ci fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); 4318c2ecf20Sopenharmony_ci else 4328c2ecf20Sopenharmony_ci if_frequency = 0; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x800000, 4358c2ecf20Sopenharmony_ci adc_freq); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci if (!dev->cfg.spec_inv && if_frequency) 4388c2ecf20Sopenharmony_ci utmp = 0x800000 - utmp; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci buf[0] = (utmp >> 0) & 0xff; 4418c2ecf20Sopenharmony_ci buf[1] = (utmp >> 8) & 0xff; 4428c2ecf20Sopenharmony_ci buf[2] = (utmp >> 16) & 0xff; 4438c2ecf20Sopenharmony_ci ret = regmap_bulk_write(dev->regmap, 0x800029, buf, 3); 4448c2ecf20Sopenharmony_ci if (ret) 4458c2ecf20Sopenharmony_ci goto err; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "if_frequency_cw=%06x\n", utmp); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci dev->bandwidth_hz = c->bandwidth_hz; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x80f904, 0x03, 4538c2ecf20Sopenharmony_ci bandwidth_reg_val); 4548c2ecf20Sopenharmony_ci if (ret) 4558c2ecf20Sopenharmony_ci goto err; 4568c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x800040, 0x00); 4578c2ecf20Sopenharmony_ci if (ret) 4588c2ecf20Sopenharmony_ci goto err; 4598c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x800047, 0x00); 4608c2ecf20Sopenharmony_ci if (ret) 4618c2ecf20Sopenharmony_ci goto err; 4628c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x80f999, 0x01, 0x00); 4638c2ecf20Sopenharmony_ci if (ret) 4648c2ecf20Sopenharmony_ci goto err; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci if (c->frequency <= 230000000) 4678c2ecf20Sopenharmony_ci tmp = 0x00; /* VHF */ 4688c2ecf20Sopenharmony_ci else 4698c2ecf20Sopenharmony_ci tmp = 0x01; /* UHF */ 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x80004b, tmp); 4728c2ecf20Sopenharmony_ci if (ret) 4738c2ecf20Sopenharmony_ci goto err; 4748c2ecf20Sopenharmony_ci /* Reset FSM */ 4758c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x800000, 0x00); 4768c2ecf20Sopenharmony_ci if (ret) 4778c2ecf20Sopenharmony_ci goto err; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci return 0; 4808c2ecf20Sopenharmony_cierr: 4818c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 4828c2ecf20Sopenharmony_ci return ret; 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic int af9033_get_frontend(struct dvb_frontend *fe, 4868c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 4898c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 4908c2ecf20Sopenharmony_ci int ret; 4918c2ecf20Sopenharmony_ci u8 buf[8]; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci /* Read all needed TPS registers */ 4968c2ecf20Sopenharmony_ci ret = regmap_bulk_read(dev->regmap, 0x80f900, buf, 8); 4978c2ecf20Sopenharmony_ci if (ret) 4988c2ecf20Sopenharmony_ci goto err; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci switch ((buf[0] >> 0) & 3) { 5018c2ecf20Sopenharmony_ci case 0: 5028c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_2K; 5038c2ecf20Sopenharmony_ci break; 5048c2ecf20Sopenharmony_ci case 1: 5058c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_8K; 5068c2ecf20Sopenharmony_ci break; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci switch ((buf[1] >> 0) & 3) { 5108c2ecf20Sopenharmony_ci case 0: 5118c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_32; 5128c2ecf20Sopenharmony_ci break; 5138c2ecf20Sopenharmony_ci case 1: 5148c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_16; 5158c2ecf20Sopenharmony_ci break; 5168c2ecf20Sopenharmony_ci case 2: 5178c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_8; 5188c2ecf20Sopenharmony_ci break; 5198c2ecf20Sopenharmony_ci case 3: 5208c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_4; 5218c2ecf20Sopenharmony_ci break; 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci switch ((buf[2] >> 0) & 7) { 5258c2ecf20Sopenharmony_ci case 0: 5268c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_NONE; 5278c2ecf20Sopenharmony_ci break; 5288c2ecf20Sopenharmony_ci case 1: 5298c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_1; 5308c2ecf20Sopenharmony_ci break; 5318c2ecf20Sopenharmony_ci case 2: 5328c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_2; 5338c2ecf20Sopenharmony_ci break; 5348c2ecf20Sopenharmony_ci case 3: 5358c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_4; 5368c2ecf20Sopenharmony_ci break; 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci switch ((buf[3] >> 0) & 3) { 5408c2ecf20Sopenharmony_ci case 0: 5418c2ecf20Sopenharmony_ci c->modulation = QPSK; 5428c2ecf20Sopenharmony_ci break; 5438c2ecf20Sopenharmony_ci case 1: 5448c2ecf20Sopenharmony_ci c->modulation = QAM_16; 5458c2ecf20Sopenharmony_ci break; 5468c2ecf20Sopenharmony_ci case 2: 5478c2ecf20Sopenharmony_ci c->modulation = QAM_64; 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci switch ((buf[4] >> 0) & 3) { 5528c2ecf20Sopenharmony_ci case 0: 5538c2ecf20Sopenharmony_ci c->bandwidth_hz = 6000000; 5548c2ecf20Sopenharmony_ci break; 5558c2ecf20Sopenharmony_ci case 1: 5568c2ecf20Sopenharmony_ci c->bandwidth_hz = 7000000; 5578c2ecf20Sopenharmony_ci break; 5588c2ecf20Sopenharmony_ci case 2: 5598c2ecf20Sopenharmony_ci c->bandwidth_hz = 8000000; 5608c2ecf20Sopenharmony_ci break; 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci switch ((buf[6] >> 0) & 7) { 5648c2ecf20Sopenharmony_ci case 0: 5658c2ecf20Sopenharmony_ci c->code_rate_HP = FEC_1_2; 5668c2ecf20Sopenharmony_ci break; 5678c2ecf20Sopenharmony_ci case 1: 5688c2ecf20Sopenharmony_ci c->code_rate_HP = FEC_2_3; 5698c2ecf20Sopenharmony_ci break; 5708c2ecf20Sopenharmony_ci case 2: 5718c2ecf20Sopenharmony_ci c->code_rate_HP = FEC_3_4; 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci case 3: 5748c2ecf20Sopenharmony_ci c->code_rate_HP = FEC_5_6; 5758c2ecf20Sopenharmony_ci break; 5768c2ecf20Sopenharmony_ci case 4: 5778c2ecf20Sopenharmony_ci c->code_rate_HP = FEC_7_8; 5788c2ecf20Sopenharmony_ci break; 5798c2ecf20Sopenharmony_ci case 5: 5808c2ecf20Sopenharmony_ci c->code_rate_HP = FEC_NONE; 5818c2ecf20Sopenharmony_ci break; 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci switch ((buf[7] >> 0) & 7) { 5858c2ecf20Sopenharmony_ci case 0: 5868c2ecf20Sopenharmony_ci c->code_rate_LP = FEC_1_2; 5878c2ecf20Sopenharmony_ci break; 5888c2ecf20Sopenharmony_ci case 1: 5898c2ecf20Sopenharmony_ci c->code_rate_LP = FEC_2_3; 5908c2ecf20Sopenharmony_ci break; 5918c2ecf20Sopenharmony_ci case 2: 5928c2ecf20Sopenharmony_ci c->code_rate_LP = FEC_3_4; 5938c2ecf20Sopenharmony_ci break; 5948c2ecf20Sopenharmony_ci case 3: 5958c2ecf20Sopenharmony_ci c->code_rate_LP = FEC_5_6; 5968c2ecf20Sopenharmony_ci break; 5978c2ecf20Sopenharmony_ci case 4: 5988c2ecf20Sopenharmony_ci c->code_rate_LP = FEC_7_8; 5998c2ecf20Sopenharmony_ci break; 6008c2ecf20Sopenharmony_ci case 5: 6018c2ecf20Sopenharmony_ci c->code_rate_LP = FEC_NONE; 6028c2ecf20Sopenharmony_ci break; 6038c2ecf20Sopenharmony_ci } 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci return 0; 6068c2ecf20Sopenharmony_cierr: 6078c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 6088c2ecf20Sopenharmony_ci return ret; 6098c2ecf20Sopenharmony_ci} 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_cistatic int af9033_read_status(struct dvb_frontend *fe, enum fe_status *status) 6128c2ecf20Sopenharmony_ci{ 6138c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 6148c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 6158c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 6168c2ecf20Sopenharmony_ci int ret, tmp = 0; 6178c2ecf20Sopenharmony_ci u8 buf[7]; 6188c2ecf20Sopenharmony_ci unsigned int utmp, utmp1; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci *status = 0; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci /* Radio channel status: 0=no result, 1=has signal, 2=no signal */ 6258c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x800047, &utmp); 6268c2ecf20Sopenharmony_ci if (ret) 6278c2ecf20Sopenharmony_ci goto err; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci /* Has signal */ 6308c2ecf20Sopenharmony_ci if (utmp == 0x01) 6318c2ecf20Sopenharmony_ci *status |= FE_HAS_SIGNAL; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci if (utmp != 0x02) { 6348c2ecf20Sopenharmony_ci /* TPS lock */ 6358c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x80f5a9, &utmp); 6368c2ecf20Sopenharmony_ci if (ret) 6378c2ecf20Sopenharmony_ci goto err; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci if ((utmp >> 0) & 0x01) 6408c2ecf20Sopenharmony_ci *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 6418c2ecf20Sopenharmony_ci FE_HAS_VITERBI; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /* Full lock */ 6448c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x80f999, &utmp); 6458c2ecf20Sopenharmony_ci if (ret) 6468c2ecf20Sopenharmony_ci goto err; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci if ((utmp >> 0) & 0x01) 6498c2ecf20Sopenharmony_ci *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 6508c2ecf20Sopenharmony_ci FE_HAS_VITERBI | FE_HAS_SYNC | 6518c2ecf20Sopenharmony_ci FE_HAS_LOCK; 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci dev->fe_status = *status; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci /* Signal strength */ 6578c2ecf20Sopenharmony_ci if (dev->fe_status & FE_HAS_SIGNAL) { 6588c2ecf20Sopenharmony_ci if (dev->is_af9035) { 6598c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x80004a, &utmp); 6608c2ecf20Sopenharmony_ci if (ret) 6618c2ecf20Sopenharmony_ci goto err; 6628c2ecf20Sopenharmony_ci tmp = -utmp * 1000; 6638c2ecf20Sopenharmony_ci } else { 6648c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x8000f7, &utmp); 6658c2ecf20Sopenharmony_ci if (ret) 6668c2ecf20Sopenharmony_ci goto err; 6678c2ecf20Sopenharmony_ci tmp = (utmp - 100) * 1000; 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci c->strength.len = 1; 6718c2ecf20Sopenharmony_ci c->strength.stat[0].scale = FE_SCALE_DECIBEL; 6728c2ecf20Sopenharmony_ci c->strength.stat[0].svalue = tmp; 6738c2ecf20Sopenharmony_ci } else { 6748c2ecf20Sopenharmony_ci c->strength.len = 1; 6758c2ecf20Sopenharmony_ci c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci /* CNR */ 6798c2ecf20Sopenharmony_ci if (dev->fe_status & FE_HAS_VITERBI) { 6808c2ecf20Sopenharmony_ci /* Read raw SNR value */ 6818c2ecf20Sopenharmony_ci ret = regmap_bulk_read(dev->regmap, 0x80002c, buf, 3); 6828c2ecf20Sopenharmony_ci if (ret) 6838c2ecf20Sopenharmony_ci goto err; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci utmp1 = buf[2] << 16 | buf[1] << 8 | buf[0] << 0; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci /* Read superframe number */ 6888c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x80f78b, &utmp); 6898c2ecf20Sopenharmony_ci if (ret) 6908c2ecf20Sopenharmony_ci goto err; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci if (utmp) 6938c2ecf20Sopenharmony_ci utmp1 /= utmp; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci /* Read current transmission mode */ 6968c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x80f900, &utmp); 6978c2ecf20Sopenharmony_ci if (ret) 6988c2ecf20Sopenharmony_ci goto err; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci switch ((utmp >> 0) & 3) { 7018c2ecf20Sopenharmony_ci case 0: 7028c2ecf20Sopenharmony_ci /* 2k */ 7038c2ecf20Sopenharmony_ci utmp1 *= 4; 7048c2ecf20Sopenharmony_ci break; 7058c2ecf20Sopenharmony_ci case 1: 7068c2ecf20Sopenharmony_ci /* 8k */ 7078c2ecf20Sopenharmony_ci utmp1 *= 1; 7088c2ecf20Sopenharmony_ci break; 7098c2ecf20Sopenharmony_ci case 2: 7108c2ecf20Sopenharmony_ci /* 4k */ 7118c2ecf20Sopenharmony_ci utmp1 *= 2; 7128c2ecf20Sopenharmony_ci break; 7138c2ecf20Sopenharmony_ci default: 7148c2ecf20Sopenharmony_ci utmp1 *= 0; 7158c2ecf20Sopenharmony_ci break; 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci /* Read current modulation */ 7198c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x80f903, &utmp); 7208c2ecf20Sopenharmony_ci if (ret) 7218c2ecf20Sopenharmony_ci goto err; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci switch ((utmp >> 0) & 3) { 7248c2ecf20Sopenharmony_ci case 0: 7258c2ecf20Sopenharmony_ci /* 7268c2ecf20Sopenharmony_ci * QPSK 7278c2ecf20Sopenharmony_ci * CNR[dB] 13 * -log10((1690000 - value) / value) + 2.6 7288c2ecf20Sopenharmony_ci * value [653799, 1689999], 2.6 / 13 = 3355443 7298c2ecf20Sopenharmony_ci */ 7308c2ecf20Sopenharmony_ci utmp1 = clamp(utmp1, 653799U, 1689999U); 7318c2ecf20Sopenharmony_ci utmp1 = ((u64)(intlog10(utmp1) 7328c2ecf20Sopenharmony_ci - intlog10(1690000 - utmp1) 7338c2ecf20Sopenharmony_ci + 3355443) * 13 * 1000) >> 24; 7348c2ecf20Sopenharmony_ci break; 7358c2ecf20Sopenharmony_ci case 1: 7368c2ecf20Sopenharmony_ci /* 7378c2ecf20Sopenharmony_ci * QAM-16 7388c2ecf20Sopenharmony_ci * CNR[dB] 6 * log10((value - 370000) / (828000 - value)) + 15.7 7398c2ecf20Sopenharmony_ci * value [371105, 827999], 15.7 / 6 = 43900382 7408c2ecf20Sopenharmony_ci */ 7418c2ecf20Sopenharmony_ci utmp1 = clamp(utmp1, 371105U, 827999U); 7428c2ecf20Sopenharmony_ci utmp1 = ((u64)(intlog10(utmp1 - 370000) 7438c2ecf20Sopenharmony_ci - intlog10(828000 - utmp1) 7448c2ecf20Sopenharmony_ci + 43900382) * 6 * 1000) >> 24; 7458c2ecf20Sopenharmony_ci break; 7468c2ecf20Sopenharmony_ci case 2: 7478c2ecf20Sopenharmony_ci /* 7488c2ecf20Sopenharmony_ci * QAM-64 7498c2ecf20Sopenharmony_ci * CNR[dB] 8 * log10((value - 193000) / (425000 - value)) + 23.8 7508c2ecf20Sopenharmony_ci * value [193246, 424999], 23.8 / 8 = 49912218 7518c2ecf20Sopenharmony_ci */ 7528c2ecf20Sopenharmony_ci utmp1 = clamp(utmp1, 193246U, 424999U); 7538c2ecf20Sopenharmony_ci utmp1 = ((u64)(intlog10(utmp1 - 193000) 7548c2ecf20Sopenharmony_ci - intlog10(425000 - utmp1) 7558c2ecf20Sopenharmony_ci + 49912218) * 8 * 1000) >> 24; 7568c2ecf20Sopenharmony_ci break; 7578c2ecf20Sopenharmony_ci default: 7588c2ecf20Sopenharmony_ci utmp1 = 0; 7598c2ecf20Sopenharmony_ci break; 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "cnr=%u\n", utmp1); 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 7658c2ecf20Sopenharmony_ci c->cnr.stat[0].svalue = utmp1; 7668c2ecf20Sopenharmony_ci } else { 7678c2ecf20Sopenharmony_ci c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci /* UCB/PER/BER */ 7718c2ecf20Sopenharmony_ci if (dev->fe_status & FE_HAS_LOCK) { 7728c2ecf20Sopenharmony_ci /* Outer FEC, 204 byte packets */ 7738c2ecf20Sopenharmony_ci u16 abort_packet_count, rsd_packet_count; 7748c2ecf20Sopenharmony_ci /* Inner FEC, bits */ 7758c2ecf20Sopenharmony_ci u32 rsd_bit_err_count; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci /* 7788c2ecf20Sopenharmony_ci * Packet count used for measurement is 10000 7798c2ecf20Sopenharmony_ci * (rsd_packet_count). Maybe it should be increased? 7808c2ecf20Sopenharmony_ci */ 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci ret = regmap_bulk_read(dev->regmap, 0x800032, buf, 7); 7838c2ecf20Sopenharmony_ci if (ret) 7848c2ecf20Sopenharmony_ci goto err; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci abort_packet_count = (buf[1] << 8) | (buf[0] << 0); 7878c2ecf20Sopenharmony_ci rsd_bit_err_count = (buf[4] << 16) | (buf[3] << 8) | buf[2]; 7888c2ecf20Sopenharmony_ci rsd_packet_count = (buf[6] << 8) | (buf[5] << 0); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci dev->error_block_count += abort_packet_count; 7918c2ecf20Sopenharmony_ci dev->total_block_count += rsd_packet_count; 7928c2ecf20Sopenharmony_ci dev->post_bit_error += rsd_bit_err_count; 7938c2ecf20Sopenharmony_ci dev->post_bit_count += rsd_packet_count * 204 * 8; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci c->block_count.len = 1; 7968c2ecf20Sopenharmony_ci c->block_count.stat[0].scale = FE_SCALE_COUNTER; 7978c2ecf20Sopenharmony_ci c->block_count.stat[0].uvalue = dev->total_block_count; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci c->block_error.len = 1; 8008c2ecf20Sopenharmony_ci c->block_error.stat[0].scale = FE_SCALE_COUNTER; 8018c2ecf20Sopenharmony_ci c->block_error.stat[0].uvalue = dev->error_block_count; 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci c->post_bit_count.len = 1; 8048c2ecf20Sopenharmony_ci c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 8058c2ecf20Sopenharmony_ci c->post_bit_count.stat[0].uvalue = dev->post_bit_count; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci c->post_bit_error.len = 1; 8088c2ecf20Sopenharmony_ci c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 8098c2ecf20Sopenharmony_ci c->post_bit_error.stat[0].uvalue = dev->post_bit_error; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci return 0; 8138c2ecf20Sopenharmony_cierr: 8148c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 8158c2ecf20Sopenharmony_ci return ret; 8168c2ecf20Sopenharmony_ci} 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_cistatic int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) 8198c2ecf20Sopenharmony_ci{ 8208c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 8218c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 8228c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; 8238c2ecf20Sopenharmony_ci int ret; 8248c2ecf20Sopenharmony_ci unsigned int utmp; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci /* Use DVBv5 CNR */ 8298c2ecf20Sopenharmony_ci if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) { 8308c2ecf20Sopenharmony_ci /* Return 0.1 dB for AF9030 and 0-0xffff for IT9130. */ 8318c2ecf20Sopenharmony_ci if (dev->is_af9035) { 8328c2ecf20Sopenharmony_ci /* 1000x => 10x (0.1 dB) */ 8338c2ecf20Sopenharmony_ci *snr = div_s64(c->cnr.stat[0].svalue, 100); 8348c2ecf20Sopenharmony_ci } else { 8358c2ecf20Sopenharmony_ci /* 1000x => 1x (1 dB) */ 8368c2ecf20Sopenharmony_ci *snr = div_s64(c->cnr.stat[0].svalue, 1000); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* Read current modulation */ 8398c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x80f903, &utmp); 8408c2ecf20Sopenharmony_ci if (ret) 8418c2ecf20Sopenharmony_ci goto err; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci /* scale value to 0x0000-0xffff */ 8448c2ecf20Sopenharmony_ci switch ((utmp >> 0) & 3) { 8458c2ecf20Sopenharmony_ci case 0: 8468c2ecf20Sopenharmony_ci *snr = *snr * 0xffff / 23; 8478c2ecf20Sopenharmony_ci break; 8488c2ecf20Sopenharmony_ci case 1: 8498c2ecf20Sopenharmony_ci *snr = *snr * 0xffff / 26; 8508c2ecf20Sopenharmony_ci break; 8518c2ecf20Sopenharmony_ci case 2: 8528c2ecf20Sopenharmony_ci *snr = *snr * 0xffff / 32; 8538c2ecf20Sopenharmony_ci break; 8548c2ecf20Sopenharmony_ci default: 8558c2ecf20Sopenharmony_ci goto err; 8568c2ecf20Sopenharmony_ci } 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci } else { 8598c2ecf20Sopenharmony_ci *snr = 0; 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci return 0; 8638c2ecf20Sopenharmony_cierr: 8648c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 8658c2ecf20Sopenharmony_ci return ret; 8668c2ecf20Sopenharmony_ci} 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_cistatic int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 8698c2ecf20Sopenharmony_ci{ 8708c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 8718c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 8728c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; 8738c2ecf20Sopenharmony_ci int ret, tmp, power_real; 8748c2ecf20Sopenharmony_ci unsigned int utmp; 8758c2ecf20Sopenharmony_ci u8 gain_offset, buf[7]; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci if (dev->is_af9035) { 8808c2ecf20Sopenharmony_ci /* Read signal strength of 0-100 scale */ 8818c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x800048, &utmp); 8828c2ecf20Sopenharmony_ci if (ret) 8838c2ecf20Sopenharmony_ci goto err; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci /* Scale value to 0x0000-0xffff */ 8868c2ecf20Sopenharmony_ci *strength = utmp * 0xffff / 100; 8878c2ecf20Sopenharmony_ci } else { 8888c2ecf20Sopenharmony_ci ret = regmap_read(dev->regmap, 0x8000f7, &utmp); 8898c2ecf20Sopenharmony_ci if (ret) 8908c2ecf20Sopenharmony_ci goto err; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci ret = regmap_bulk_read(dev->regmap, 0x80f900, buf, 7); 8938c2ecf20Sopenharmony_ci if (ret) 8948c2ecf20Sopenharmony_ci goto err; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci if (c->frequency <= 300000000) 8978c2ecf20Sopenharmony_ci gain_offset = 7; /* VHF */ 8988c2ecf20Sopenharmony_ci else 8998c2ecf20Sopenharmony_ci gain_offset = 4; /* UHF */ 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci power_real = (utmp - 100 - gain_offset) - 9028c2ecf20Sopenharmony_ci power_reference[((buf[3] >> 0) & 3)][((buf[6] >> 0) & 7)]; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci if (power_real < -15) 9058c2ecf20Sopenharmony_ci tmp = 0; 9068c2ecf20Sopenharmony_ci else if ((power_real >= -15) && (power_real < 0)) 9078c2ecf20Sopenharmony_ci tmp = (2 * (power_real + 15)) / 3; 9088c2ecf20Sopenharmony_ci else if ((power_real >= 0) && (power_real < 20)) 9098c2ecf20Sopenharmony_ci tmp = 4 * power_real + 10; 9108c2ecf20Sopenharmony_ci else if ((power_real >= 20) && (power_real < 35)) 9118c2ecf20Sopenharmony_ci tmp = (2 * (power_real - 20)) / 3 + 90; 9128c2ecf20Sopenharmony_ci else 9138c2ecf20Sopenharmony_ci tmp = 100; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci /* Scale value to 0x0000-0xffff */ 9168c2ecf20Sopenharmony_ci *strength = tmp * 0xffff / 100; 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci return 0; 9208c2ecf20Sopenharmony_cierr: 9218c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 9228c2ecf20Sopenharmony_ci return ret; 9238c2ecf20Sopenharmony_ci} 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_cistatic int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) 9268c2ecf20Sopenharmony_ci{ 9278c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci *ber = (dev->post_bit_error - dev->post_bit_error_prev); 9308c2ecf20Sopenharmony_ci dev->post_bit_error_prev = dev->post_bit_error; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci return 0; 9338c2ecf20Sopenharmony_ci} 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_cistatic int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 9368c2ecf20Sopenharmony_ci{ 9378c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci *ucblocks = dev->error_block_count; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci return 0; 9428c2ecf20Sopenharmony_ci} 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_cistatic int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 9478c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 9488c2ecf20Sopenharmony_ci int ret; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "enable=%d\n", enable); 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x00fa04, 0x01, enable); 9538c2ecf20Sopenharmony_ci if (ret) 9548c2ecf20Sopenharmony_ci goto err; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci return 0; 9578c2ecf20Sopenharmony_cierr: 9588c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 9598c2ecf20Sopenharmony_ci return ret; 9608c2ecf20Sopenharmony_ci} 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_cistatic int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) 9638c2ecf20Sopenharmony_ci{ 9648c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 9658c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 9668c2ecf20Sopenharmony_ci int ret; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "onoff=%d\n", onoff); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci ret = regmap_update_bits(dev->regmap, 0x80f993, 0x01, onoff); 9718c2ecf20Sopenharmony_ci if (ret) 9728c2ecf20Sopenharmony_ci goto err; 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci return 0; 9758c2ecf20Sopenharmony_cierr: 9768c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 9778c2ecf20Sopenharmony_ci return ret; 9788c2ecf20Sopenharmony_ci} 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_cistatic int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid, 9818c2ecf20Sopenharmony_ci int onoff) 9828c2ecf20Sopenharmony_ci{ 9838c2ecf20Sopenharmony_ci struct af9033_dev *dev = fe->demodulator_priv; 9848c2ecf20Sopenharmony_ci struct i2c_client *client = dev->client; 9858c2ecf20Sopenharmony_ci int ret; 9868c2ecf20Sopenharmony_ci u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff}; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n", 9898c2ecf20Sopenharmony_ci index, pid, onoff); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (pid > 0x1fff) 9928c2ecf20Sopenharmony_ci return 0; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci ret = regmap_bulk_write(dev->regmap, 0x80f996, wbuf, 2); 9958c2ecf20Sopenharmony_ci if (ret) 9968c2ecf20Sopenharmony_ci goto err; 9978c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x80f994, onoff); 9988c2ecf20Sopenharmony_ci if (ret) 9998c2ecf20Sopenharmony_ci goto err; 10008c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x80f995, index); 10018c2ecf20Sopenharmony_ci if (ret) 10028c2ecf20Sopenharmony_ci goto err; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci return 0; 10058c2ecf20Sopenharmony_cierr: 10068c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 10078c2ecf20Sopenharmony_ci return ret; 10088c2ecf20Sopenharmony_ci} 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops af9033_ops = { 10118c2ecf20Sopenharmony_ci .delsys = {SYS_DVBT}, 10128c2ecf20Sopenharmony_ci .info = { 10138c2ecf20Sopenharmony_ci .name = "Afatech AF9033 (DVB-T)", 10148c2ecf20Sopenharmony_ci .frequency_min_hz = 174 * MHz, 10158c2ecf20Sopenharmony_ci .frequency_max_hz = 862 * MHz, 10168c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 250 * kHz, 10178c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_1_2 | 10188c2ecf20Sopenharmony_ci FE_CAN_FEC_2_3 | 10198c2ecf20Sopenharmony_ci FE_CAN_FEC_3_4 | 10208c2ecf20Sopenharmony_ci FE_CAN_FEC_5_6 | 10218c2ecf20Sopenharmony_ci FE_CAN_FEC_7_8 | 10228c2ecf20Sopenharmony_ci FE_CAN_FEC_AUTO | 10238c2ecf20Sopenharmony_ci FE_CAN_QPSK | 10248c2ecf20Sopenharmony_ci FE_CAN_QAM_16 | 10258c2ecf20Sopenharmony_ci FE_CAN_QAM_64 | 10268c2ecf20Sopenharmony_ci FE_CAN_QAM_AUTO | 10278c2ecf20Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | 10288c2ecf20Sopenharmony_ci FE_CAN_GUARD_INTERVAL_AUTO | 10298c2ecf20Sopenharmony_ci FE_CAN_HIERARCHY_AUTO | 10308c2ecf20Sopenharmony_ci FE_CAN_RECOVER | 10318c2ecf20Sopenharmony_ci FE_CAN_MUTE_TS 10328c2ecf20Sopenharmony_ci }, 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci .init = af9033_init, 10358c2ecf20Sopenharmony_ci .sleep = af9033_sleep, 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci .get_tune_settings = af9033_get_tune_settings, 10388c2ecf20Sopenharmony_ci .set_frontend = af9033_set_frontend, 10398c2ecf20Sopenharmony_ci .get_frontend = af9033_get_frontend, 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci .read_status = af9033_read_status, 10428c2ecf20Sopenharmony_ci .read_snr = af9033_read_snr, 10438c2ecf20Sopenharmony_ci .read_signal_strength = af9033_read_signal_strength, 10448c2ecf20Sopenharmony_ci .read_ber = af9033_read_ber, 10458c2ecf20Sopenharmony_ci .read_ucblocks = af9033_read_ucblocks, 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci .i2c_gate_ctrl = af9033_i2c_gate_ctrl, 10488c2ecf20Sopenharmony_ci}; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_cistatic int af9033_probe(struct i2c_client *client, 10518c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 10528c2ecf20Sopenharmony_ci{ 10538c2ecf20Sopenharmony_ci struct af9033_config *cfg = client->dev.platform_data; 10548c2ecf20Sopenharmony_ci struct af9033_dev *dev; 10558c2ecf20Sopenharmony_ci int ret; 10568c2ecf20Sopenharmony_ci u8 buf[8]; 10578c2ecf20Sopenharmony_ci u32 reg; 10588c2ecf20Sopenharmony_ci static const struct regmap_config regmap_config = { 10598c2ecf20Sopenharmony_ci .reg_bits = 24, 10608c2ecf20Sopenharmony_ci .val_bits = 8, 10618c2ecf20Sopenharmony_ci }; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci /* Allocate memory for the internal state */ 10648c2ecf20Sopenharmony_ci dev = kzalloc(sizeof(*dev), GFP_KERNEL); 10658c2ecf20Sopenharmony_ci if (!dev) { 10668c2ecf20Sopenharmony_ci ret = -ENOMEM; 10678c2ecf20Sopenharmony_ci goto err; 10688c2ecf20Sopenharmony_ci } 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci /* Setup the state */ 10718c2ecf20Sopenharmony_ci dev->client = client; 10728c2ecf20Sopenharmony_ci memcpy(&dev->cfg, cfg, sizeof(dev->cfg)); 10738c2ecf20Sopenharmony_ci switch (dev->cfg.ts_mode) { 10748c2ecf20Sopenharmony_ci case AF9033_TS_MODE_PARALLEL: 10758c2ecf20Sopenharmony_ci dev->ts_mode_parallel = true; 10768c2ecf20Sopenharmony_ci break; 10778c2ecf20Sopenharmony_ci case AF9033_TS_MODE_SERIAL: 10788c2ecf20Sopenharmony_ci dev->ts_mode_serial = true; 10798c2ecf20Sopenharmony_ci break; 10808c2ecf20Sopenharmony_ci case AF9033_TS_MODE_USB: 10818c2ecf20Sopenharmony_ci /* USB mode for AF9035 */ 10828c2ecf20Sopenharmony_ci default: 10838c2ecf20Sopenharmony_ci break; 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci if (dev->cfg.clock != 12000000) { 10878c2ecf20Sopenharmony_ci ret = -ENODEV; 10888c2ecf20Sopenharmony_ci dev_err(&client->dev, 10898c2ecf20Sopenharmony_ci "Unsupported clock %u Hz. Only 12000000 Hz is supported currently\n", 10908c2ecf20Sopenharmony_ci dev->cfg.clock); 10918c2ecf20Sopenharmony_ci goto err_kfree; 10928c2ecf20Sopenharmony_ci } 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci /* Create regmap */ 10958c2ecf20Sopenharmony_ci dev->regmap = regmap_init_i2c(client, ®map_config); 10968c2ecf20Sopenharmony_ci if (IS_ERR(dev->regmap)) { 10978c2ecf20Sopenharmony_ci ret = PTR_ERR(dev->regmap); 10988c2ecf20Sopenharmony_ci goto err_kfree; 10998c2ecf20Sopenharmony_ci } 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci /* Firmware version */ 11028c2ecf20Sopenharmony_ci switch (dev->cfg.tuner) { 11038c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_38: 11048c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_51: 11058c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_52: 11068c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_60: 11078c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_61: 11088c2ecf20Sopenharmony_ci case AF9033_TUNER_IT9135_62: 11098c2ecf20Sopenharmony_ci dev->is_it9135 = true; 11108c2ecf20Sopenharmony_ci reg = 0x004bfc; 11118c2ecf20Sopenharmony_ci break; 11128c2ecf20Sopenharmony_ci default: 11138c2ecf20Sopenharmony_ci dev->is_af9035 = true; 11148c2ecf20Sopenharmony_ci reg = 0x0083e9; 11158c2ecf20Sopenharmony_ci break; 11168c2ecf20Sopenharmony_ci } 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci ret = regmap_bulk_read(dev->regmap, reg, &buf[0], 4); 11198c2ecf20Sopenharmony_ci if (ret) 11208c2ecf20Sopenharmony_ci goto err_regmap_exit; 11218c2ecf20Sopenharmony_ci ret = regmap_bulk_read(dev->regmap, 0x804191, &buf[4], 4); 11228c2ecf20Sopenharmony_ci if (ret) 11238c2ecf20Sopenharmony_ci goto err_regmap_exit; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci dev_info(&client->dev, 11268c2ecf20Sopenharmony_ci "firmware version: LINK %d.%d.%d.%d - OFDM %d.%d.%d.%d\n", 11278c2ecf20Sopenharmony_ci buf[0], buf[1], buf[2], buf[3], 11288c2ecf20Sopenharmony_ci buf[4], buf[5], buf[6], buf[7]); 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci /* Sleep as chip seems to be partly active by default */ 11318c2ecf20Sopenharmony_ci /* IT9135 did not like to sleep at that early */ 11328c2ecf20Sopenharmony_ci if (dev->is_af9035) { 11338c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x80004c, 0x01); 11348c2ecf20Sopenharmony_ci if (ret) 11358c2ecf20Sopenharmony_ci goto err_regmap_exit; 11368c2ecf20Sopenharmony_ci ret = regmap_write(dev->regmap, 0x800000, 0x00); 11378c2ecf20Sopenharmony_ci if (ret) 11388c2ecf20Sopenharmony_ci goto err_regmap_exit; 11398c2ecf20Sopenharmony_ci } 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci /* Create dvb frontend */ 11428c2ecf20Sopenharmony_ci memcpy(&dev->fe.ops, &af9033_ops, sizeof(dev->fe.ops)); 11438c2ecf20Sopenharmony_ci dev->fe.demodulator_priv = dev; 11448c2ecf20Sopenharmony_ci *cfg->fe = &dev->fe; 11458c2ecf20Sopenharmony_ci if (cfg->ops) { 11468c2ecf20Sopenharmony_ci cfg->ops->pid_filter = af9033_pid_filter; 11478c2ecf20Sopenharmony_ci cfg->ops->pid_filter_ctrl = af9033_pid_filter_ctrl; 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci cfg->regmap = dev->regmap; 11508c2ecf20Sopenharmony_ci i2c_set_clientdata(client, dev); 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci dev_info(&client->dev, "Afatech AF9033 successfully attached\n"); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci return 0; 11558c2ecf20Sopenharmony_cierr_regmap_exit: 11568c2ecf20Sopenharmony_ci regmap_exit(dev->regmap); 11578c2ecf20Sopenharmony_cierr_kfree: 11588c2ecf20Sopenharmony_ci kfree(dev); 11598c2ecf20Sopenharmony_cierr: 11608c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "failed=%d\n", ret); 11618c2ecf20Sopenharmony_ci return ret; 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_cistatic int af9033_remove(struct i2c_client *client) 11658c2ecf20Sopenharmony_ci{ 11668c2ecf20Sopenharmony_ci struct af9033_dev *dev = i2c_get_clientdata(client); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci dev_dbg(&client->dev, "\n"); 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci regmap_exit(dev->regmap); 11718c2ecf20Sopenharmony_ci kfree(dev); 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci return 0; 11748c2ecf20Sopenharmony_ci} 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_cistatic const struct i2c_device_id af9033_id_table[] = { 11778c2ecf20Sopenharmony_ci {"af9033", 0}, 11788c2ecf20Sopenharmony_ci {} 11798c2ecf20Sopenharmony_ci}; 11808c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, af9033_id_table); 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_cistatic struct i2c_driver af9033_driver = { 11838c2ecf20Sopenharmony_ci .driver = { 11848c2ecf20Sopenharmony_ci .name = "af9033", 11858c2ecf20Sopenharmony_ci .suppress_bind_attrs = true, 11868c2ecf20Sopenharmony_ci }, 11878c2ecf20Sopenharmony_ci .probe = af9033_probe, 11888c2ecf20Sopenharmony_ci .remove = af9033_remove, 11898c2ecf20Sopenharmony_ci .id_table = af9033_id_table, 11908c2ecf20Sopenharmony_ci}; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_cimodule_i2c_driver(af9033_driver); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ciMODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 11958c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); 11968c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1197