19a0bf528SMauro Carvalho Chehab /* 29a0bf528SMauro Carvalho Chehab * Afatech AF9033 demodulator driver 39a0bf528SMauro Carvalho Chehab * 49a0bf528SMauro Carvalho Chehab * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 59a0bf528SMauro Carvalho Chehab * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> 69a0bf528SMauro Carvalho Chehab * 79a0bf528SMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 89a0bf528SMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 99a0bf528SMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 109a0bf528SMauro Carvalho Chehab * (at your option) any later version. 119a0bf528SMauro Carvalho Chehab * 129a0bf528SMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 139a0bf528SMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 149a0bf528SMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 159a0bf528SMauro Carvalho Chehab * GNU General Public License for more details. 169a0bf528SMauro Carvalho Chehab */ 179a0bf528SMauro Carvalho Chehab 189a0bf528SMauro Carvalho Chehab #include "af9033_priv.h" 199a0bf528SMauro Carvalho Chehab 2009611caaSAntti Palosaari struct af9033_dev { 21f5b00a76SAntti Palosaari struct i2c_client *client; 22bc85d5e2SAntti Palosaari struct regmap *regmap; 239a0bf528SMauro Carvalho Chehab struct dvb_frontend fe; 249a0bf528SMauro Carvalho Chehab struct af9033_config cfg; 2583f11619SAntti Palosaari bool is_af9035; 2683f11619SAntti Palosaari bool is_it9135; 279a0bf528SMauro Carvalho Chehab 289a0bf528SMauro Carvalho Chehab u32 bandwidth_hz; 299a0bf528SMauro Carvalho Chehab bool ts_mode_parallel; 309a0bf528SMauro Carvalho Chehab bool ts_mode_serial; 319a0bf528SMauro Carvalho Chehab 320df289a2SMauro Carvalho Chehab enum fe_status fe_status; 33e53c4744SAntti Palosaari u64 post_bit_error_prev; /* for old read_ber we return (curr - prev) */ 346bb096c9SAntti Palosaari u64 post_bit_error; 356bb096c9SAntti Palosaari u64 post_bit_count; 36204f4319SAntti Palosaari u64 error_block_count; 37204f4319SAntti Palosaari u64 total_block_count; 389a0bf528SMauro Carvalho Chehab }; 399a0bf528SMauro Carvalho Chehab 4081e19912SAntti Palosaari /* Write reg val table using reg addr auto increment */ 4109611caaSAntti Palosaari static int af9033_wr_reg_val_tab(struct af9033_dev *dev, 423bf5e552SAntti Palosaari const struct reg_val *tab, int tab_len) 433bf5e552SAntti Palosaari { 4481e19912SAntti Palosaari struct i2c_client *client = dev->client; 45d18a88b1SAntti Palosaari #define MAX_TAB_LEN 212 463bf5e552SAntti Palosaari int ret, i, j; 47d18a88b1SAntti Palosaari u8 buf[1 + MAX_TAB_LEN]; 48d18a88b1SAntti Palosaari 4981e19912SAntti Palosaari dev_dbg(&client->dev, "tab_len=%d\n", tab_len); 5037ebaf68SMauro Carvalho Chehab 5137ebaf68SMauro Carvalho Chehab if (tab_len > sizeof(buf)) { 5281e19912SAntti Palosaari dev_warn(&client->dev, "tab len %d is too big\n", tab_len); 5337ebaf68SMauro Carvalho Chehab return -EINVAL; 5437ebaf68SMauro Carvalho Chehab } 553bf5e552SAntti Palosaari 563bf5e552SAntti Palosaari for (i = 0, j = 0; i < tab_len; i++) { 573bf5e552SAntti Palosaari buf[j] = tab[i].val; 583bf5e552SAntti Palosaari 593bf5e552SAntti Palosaari if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) { 60bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, tab[i].reg - j, 61bc85d5e2SAntti Palosaari buf, j + 1); 62bc85d5e2SAntti Palosaari if (ret) 633bf5e552SAntti Palosaari goto err; 643bf5e552SAntti Palosaari 653bf5e552SAntti Palosaari j = 0; 663bf5e552SAntti Palosaari } else { 673bf5e552SAntti Palosaari j++; 683bf5e552SAntti Palosaari } 693bf5e552SAntti Palosaari } 703bf5e552SAntti Palosaari 713bf5e552SAntti Palosaari return 0; 723bf5e552SAntti Palosaari err: 7381e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 743bf5e552SAntti Palosaari return ret; 753bf5e552SAntti Palosaari } 763bf5e552SAntti Palosaari 779a0bf528SMauro Carvalho Chehab static int af9033_init(struct dvb_frontend *fe) 789a0bf528SMauro Carvalho Chehab { 7909611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 8081e19912SAntti Palosaari struct i2c_client *client = dev->client; 812db4d179SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 829a0bf528SMauro Carvalho Chehab int ret, i, len; 83c2feb9ffSAntti Palosaari unsigned int utmp; 849a0bf528SMauro Carvalho Chehab const struct reg_val *init; 859a0bf528SMauro Carvalho Chehab u8 buf[4]; 869a0bf528SMauro Carvalho Chehab struct reg_val_mask tab[] = { 879a0bf528SMauro Carvalho Chehab { 0x80fb24, 0x00, 0x08 }, 889a0bf528SMauro Carvalho Chehab { 0x80004c, 0x00, 0xff }, 8909611caaSAntti Palosaari { 0x00f641, dev->cfg.tuner, 0xff }, 909a0bf528SMauro Carvalho Chehab { 0x80f5ca, 0x01, 0x01 }, 919a0bf528SMauro Carvalho Chehab { 0x80f715, 0x01, 0x01 }, 929a0bf528SMauro Carvalho Chehab { 0x00f41f, 0x04, 0x04 }, 939a0bf528SMauro Carvalho Chehab { 0x00f41a, 0x01, 0x01 }, 949a0bf528SMauro Carvalho Chehab { 0x80f731, 0x00, 0x01 }, 959a0bf528SMauro Carvalho Chehab { 0x00d91e, 0x00, 0x01 }, 969a0bf528SMauro Carvalho Chehab { 0x00d919, 0x00, 0x01 }, 979a0bf528SMauro Carvalho Chehab { 0x80f732, 0x00, 0x01 }, 989a0bf528SMauro Carvalho Chehab { 0x00d91f, 0x00, 0x01 }, 999a0bf528SMauro Carvalho Chehab { 0x00d91a, 0x00, 0x01 }, 1009a0bf528SMauro Carvalho Chehab { 0x80f730, 0x00, 0x01 }, 1019a0bf528SMauro Carvalho Chehab { 0x80f778, 0x00, 0xff }, 1029a0bf528SMauro Carvalho Chehab { 0x80f73c, 0x01, 0x01 }, 1039a0bf528SMauro Carvalho Chehab { 0x80f776, 0x00, 0x01 }, 1049a0bf528SMauro Carvalho Chehab { 0x00d8fd, 0x01, 0xff }, 1059a0bf528SMauro Carvalho Chehab { 0x00d830, 0x01, 0xff }, 1069a0bf528SMauro Carvalho Chehab { 0x00d831, 0x00, 0xff }, 1079a0bf528SMauro Carvalho Chehab { 0x00d832, 0x00, 0xff }, 10809611caaSAntti Palosaari { 0x80f985, dev->ts_mode_serial, 0x01 }, 10909611caaSAntti Palosaari { 0x80f986, dev->ts_mode_parallel, 0x01 }, 1109a0bf528SMauro Carvalho Chehab { 0x00d827, 0x00, 0xff }, 1119a0bf528SMauro Carvalho Chehab { 0x00d829, 0x00, 0xff }, 11209611caaSAntti Palosaari { 0x800045, dev->cfg.adc_multiplier, 0xff }, 1139a0bf528SMauro Carvalho Chehab }; 1149a0bf528SMauro Carvalho Chehab 11581e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 11681e19912SAntti Palosaari 11781e19912SAntti Palosaari /* Main clk control */ 118c2feb9ffSAntti Palosaari utmp = div_u64((u64)dev->cfg.clock * 0x80000, 1000000); 119c2feb9ffSAntti Palosaari buf[0] = (utmp >> 0) & 0xff; 120c2feb9ffSAntti Palosaari buf[1] = (utmp >> 8) & 0xff; 121c2feb9ffSAntti Palosaari buf[2] = (utmp >> 16) & 0xff; 122c2feb9ffSAntti Palosaari buf[3] = (utmp >> 24) & 0xff; 123bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x800025, buf, 4); 124bc85d5e2SAntti Palosaari if (ret) 1259a0bf528SMauro Carvalho Chehab goto err; 1269a0bf528SMauro Carvalho Chehab 12781e19912SAntti Palosaari dev_dbg(&client->dev, "clk=%u clk_cw=%08x\n", dev->cfg.clock, utmp); 128c2feb9ffSAntti Palosaari 12981e19912SAntti Palosaari /* ADC clk control */ 1309a0bf528SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { 13109611caaSAntti Palosaari if (clock_adc_lut[i].clock == dev->cfg.clock) 1329a0bf528SMauro Carvalho Chehab break; 1339a0bf528SMauro Carvalho Chehab } 134060f79d5SMauro Carvalho Chehab if (i == ARRAY_SIZE(clock_adc_lut)) { 13581e19912SAntti Palosaari dev_err(&client->dev, "Couldn't find ADC config for clock %d\n", 136060f79d5SMauro Carvalho Chehab dev->cfg.clock); 137060f79d5SMauro Carvalho Chehab goto err; 138060f79d5SMauro Carvalho Chehab } 1399a0bf528SMauro Carvalho Chehab 140c2feb9ffSAntti Palosaari utmp = div_u64((u64)clock_adc_lut[i].adc * 0x80000, 1000000); 141c2feb9ffSAntti Palosaari buf[0] = (utmp >> 0) & 0xff; 142c2feb9ffSAntti Palosaari buf[1] = (utmp >> 8) & 0xff; 143c2feb9ffSAntti Palosaari buf[2] = (utmp >> 16) & 0xff; 144bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x80f1cd, buf, 3); 145bc85d5e2SAntti Palosaari if (ret) 1469a0bf528SMauro Carvalho Chehab goto err; 1479a0bf528SMauro Carvalho Chehab 14881e19912SAntti Palosaari dev_dbg(&client->dev, "adc=%u adc_cw=%06x\n", 149c2feb9ffSAntti Palosaari clock_adc_lut[i].adc, utmp); 150c2feb9ffSAntti Palosaari 15181e19912SAntti Palosaari /* Config register table */ 1529a0bf528SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(tab); i++) { 153bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, tab[i].reg, tab[i].mask, 154bc85d5e2SAntti Palosaari tab[i].val); 155bc85d5e2SAntti Palosaari if (ret) 1569a0bf528SMauro Carvalho Chehab goto err; 1579a0bf528SMauro Carvalho Chehab } 1589a0bf528SMauro Carvalho Chehab 15981e19912SAntti Palosaari /* Demod clk output */ 16009611caaSAntti Palosaari if (dev->cfg.dyn0_clk) { 161bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80fba8, 0x00); 162bc85d5e2SAntti Palosaari if (ret) 1639dc0f3feSAntti Palosaari goto err; 1649dc0f3feSAntti Palosaari } 1659dc0f3feSAntti Palosaari 16681e19912SAntti Palosaari /* TS interface */ 16709611caaSAntti Palosaari if (dev->cfg.ts_mode == AF9033_TS_MODE_USB) { 168bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f9a5, 0x01, 0x00); 169bc85d5e2SAntti Palosaari if (ret) 1709a0bf528SMauro Carvalho Chehab goto err; 171bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f9b5, 0x01, 0x01); 172bc85d5e2SAntti Palosaari if (ret) 1739a0bf528SMauro Carvalho Chehab goto err; 1749a0bf528SMauro Carvalho Chehab } else { 175bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f990, 0x01, 0x00); 176bc85d5e2SAntti Palosaari if (ret) 1779a0bf528SMauro Carvalho Chehab goto err; 178bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f9b5, 0x01, 0x00); 179bc85d5e2SAntti Palosaari if (ret) 1809a0bf528SMauro Carvalho Chehab goto err; 1819a0bf528SMauro Carvalho Chehab } 1829a0bf528SMauro Carvalho Chehab 18381e19912SAntti Palosaari /* Demod core settings */ 18481e19912SAntti Palosaari dev_dbg(&client->dev, "load ofsm settings\n"); 18509611caaSAntti Palosaari switch (dev->cfg.tuner) { 186fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_38: 187fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_51: 188fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_52: 189463c399cSAntti Palosaari len = ARRAY_SIZE(ofsm_init_it9135_v1); 190463c399cSAntti Palosaari init = ofsm_init_it9135_v1; 191463c399cSAntti Palosaari break; 192fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_60: 193fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_61: 194fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_62: 195463c399cSAntti Palosaari len = ARRAY_SIZE(ofsm_init_it9135_v2); 196463c399cSAntti Palosaari init = ofsm_init_it9135_v2; 197fe8eece1SAntti Palosaari break; 198fe8eece1SAntti Palosaari default: 1999a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(ofsm_init); 2009a0bf528SMauro Carvalho Chehab init = ofsm_init; 201fe8eece1SAntti Palosaari break; 202fe8eece1SAntti Palosaari } 203fe8eece1SAntti Palosaari 20409611caaSAntti Palosaari ret = af9033_wr_reg_val_tab(dev, init, len); 205bc85d5e2SAntti Palosaari if (ret) 2069a0bf528SMauro Carvalho Chehab goto err; 2079a0bf528SMauro Carvalho Chehab 20881e19912SAntti Palosaari /* Demod tuner specific settings */ 20981e19912SAntti Palosaari dev_dbg(&client->dev, "load tuner specific settings\n"); 21009611caaSAntti Palosaari switch (dev->cfg.tuner) { 2119a0bf528SMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 2129a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(tuner_init_tua9001); 2139a0bf528SMauro Carvalho Chehab init = tuner_init_tua9001; 2149a0bf528SMauro Carvalho Chehab break; 2159a0bf528SMauro Carvalho Chehab case AF9033_TUNER_FC0011: 2169a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(tuner_init_fc0011); 2179a0bf528SMauro Carvalho Chehab init = tuner_init_fc0011; 2189a0bf528SMauro Carvalho Chehab break; 2199a0bf528SMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 2209a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(tuner_init_mxl5007t); 2219a0bf528SMauro Carvalho Chehab init = tuner_init_mxl5007t; 2229a0bf528SMauro Carvalho Chehab break; 2239a0bf528SMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 2249a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(tuner_init_tda18218); 2259a0bf528SMauro Carvalho Chehab init = tuner_init_tda18218; 2269a0bf528SMauro Carvalho Chehab break; 227d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 228d67ceb33SOliver Schinagl len = ARRAY_SIZE(tuner_init_fc2580); 229d67ceb33SOliver Schinagl init = tuner_init_fc2580; 230d67ceb33SOliver Schinagl break; 231e713ad15SAntti Palosaari case AF9033_TUNER_FC0012: 232e713ad15SAntti Palosaari len = ARRAY_SIZE(tuner_init_fc0012); 233e713ad15SAntti Palosaari init = tuner_init_fc0012; 234e713ad15SAntti Palosaari break; 2354902bb39SAntti Palosaari case AF9033_TUNER_IT9135_38: 236a72cbb77SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_38); 237a72cbb77SAntti Palosaari init = tuner_init_it9135_38; 238a72cbb77SAntti Palosaari break; 2394902bb39SAntti Palosaari case AF9033_TUNER_IT9135_51: 240bb2e12a6SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_51); 241bb2e12a6SAntti Palosaari init = tuner_init_it9135_51; 242bb2e12a6SAntti Palosaari break; 2434902bb39SAntti Palosaari case AF9033_TUNER_IT9135_52: 24422d729f3SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_52); 24522d729f3SAntti Palosaari init = tuner_init_it9135_52; 24622d729f3SAntti Palosaari break; 2474902bb39SAntti Palosaari case AF9033_TUNER_IT9135_60: 248a49f53a0SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_60); 249a49f53a0SAntti Palosaari init = tuner_init_it9135_60; 250a49f53a0SAntti Palosaari break; 2514902bb39SAntti Palosaari case AF9033_TUNER_IT9135_61: 25285211323SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_61); 25385211323SAntti Palosaari init = tuner_init_it9135_61; 25485211323SAntti Palosaari break; 2554902bb39SAntti Palosaari case AF9033_TUNER_IT9135_62: 256dc4a2c40SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_62); 257dc4a2c40SAntti Palosaari init = tuner_init_it9135_62; 2584902bb39SAntti Palosaari break; 2599a0bf528SMauro Carvalho Chehab default: 26081e19912SAntti Palosaari dev_dbg(&client->dev, "unsupported tuner ID=%d\n", 2616a087f1fSAntti Palosaari dev->cfg.tuner); 2629a0bf528SMauro Carvalho Chehab ret = -ENODEV; 2639a0bf528SMauro Carvalho Chehab goto err; 2649a0bf528SMauro Carvalho Chehab } 2659a0bf528SMauro Carvalho Chehab 26609611caaSAntti Palosaari ret = af9033_wr_reg_val_tab(dev, init, len); 267bc85d5e2SAntti Palosaari if (ret) 2689a0bf528SMauro Carvalho Chehab goto err; 2699a0bf528SMauro Carvalho Chehab 27009611caaSAntti Palosaari if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { 271bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d91c, 0x01, 0x01); 272bc85d5e2SAntti Palosaari if (ret) 2739805992fSJose Alberto Reguero goto err; 274bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d917, 0x01, 0x00); 275bc85d5e2SAntti Palosaari if (ret) 2769805992fSJose Alberto Reguero goto err; 277bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d916, 0x01, 0x00); 278bc85d5e2SAntti Palosaari if (ret) 2799805992fSJose Alberto Reguero goto err; 2809805992fSJose Alberto Reguero } 2819805992fSJose Alberto Reguero 28209611caaSAntti Palosaari switch (dev->cfg.tuner) { 283086991ddSAntti Palosaari case AF9033_TUNER_IT9135_60: 284086991ddSAntti Palosaari case AF9033_TUNER_IT9135_61: 285086991ddSAntti Palosaari case AF9033_TUNER_IT9135_62: 286bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800000, 0x01); 287bc85d5e2SAntti Palosaari if (ret) 288086991ddSAntti Palosaari goto err; 289086991ddSAntti Palosaari } 290086991ddSAntti Palosaari 29181e19912SAntti Palosaari dev->bandwidth_hz = 0; /* Force to program all parameters */ 29281e19912SAntti Palosaari /* Init stats here in order signal app which stats are supported */ 2932db4d179SAntti Palosaari c->strength.len = 1; 2942db4d179SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2952db4d179SAntti Palosaari c->cnr.len = 1; 2962db4d179SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2972db4d179SAntti Palosaari c->block_count.len = 1; 2982db4d179SAntti Palosaari c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2992db4d179SAntti Palosaari c->block_error.len = 1; 3002db4d179SAntti Palosaari c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3012db4d179SAntti Palosaari c->post_bit_count.len = 1; 3022db4d179SAntti Palosaari c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3032db4d179SAntti Palosaari c->post_bit_error.len = 1; 3042db4d179SAntti Palosaari c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3059a0bf528SMauro Carvalho Chehab 3069a0bf528SMauro Carvalho Chehab return 0; 3079a0bf528SMauro Carvalho Chehab err: 30881e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 3099a0bf528SMauro Carvalho Chehab return ret; 3109a0bf528SMauro Carvalho Chehab } 3119a0bf528SMauro Carvalho Chehab 3129a0bf528SMauro Carvalho Chehab static int af9033_sleep(struct dvb_frontend *fe) 3139a0bf528SMauro Carvalho Chehab { 31409611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 31581e19912SAntti Palosaari struct i2c_client *client = dev->client; 316bc85d5e2SAntti Palosaari int ret; 317bc85d5e2SAntti Palosaari unsigned int utmp; 3189a0bf528SMauro Carvalho Chehab 31981e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 32081e19912SAntti Palosaari 321bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80004c, 0x01); 322bc85d5e2SAntti Palosaari if (ret) 3239a0bf528SMauro Carvalho Chehab goto err; 324bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800000, 0x00); 325bc85d5e2SAntti Palosaari if (ret) 3269a0bf528SMauro Carvalho Chehab goto err; 327bc85d5e2SAntti Palosaari ret = regmap_read_poll_timeout(dev->regmap, 0x80004c, utmp, utmp == 0, 328bc85d5e2SAntti Palosaari 5000, 1000000); 329bc85d5e2SAntti Palosaari if (ret) 3309a0bf528SMauro Carvalho Chehab goto err; 331bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80fb24, 0x08, 0x08); 332bc85d5e2SAntti Palosaari if (ret) 3339a0bf528SMauro Carvalho Chehab goto err; 3349a0bf528SMauro Carvalho Chehab 33581e19912SAntti Palosaari /* Prevent current leak by setting TS interface to parallel mode */ 33609611caaSAntti Palosaari if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { 33781e19912SAntti Palosaari /* Enable parallel TS */ 338bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d917, 0x01, 0x00); 339bc85d5e2SAntti Palosaari if (ret) 3409a0bf528SMauro Carvalho Chehab goto err; 341bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d916, 0x01, 0x01); 342bc85d5e2SAntti Palosaari if (ret) 3439a0bf528SMauro Carvalho Chehab goto err; 3449a0bf528SMauro Carvalho Chehab } 3459a0bf528SMauro Carvalho Chehab 3469a0bf528SMauro Carvalho Chehab return 0; 3479a0bf528SMauro Carvalho Chehab err: 34881e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 3499a0bf528SMauro Carvalho Chehab return ret; 3509a0bf528SMauro Carvalho Chehab } 3519a0bf528SMauro Carvalho Chehab 3529a0bf528SMauro Carvalho Chehab static int af9033_get_tune_settings(struct dvb_frontend *fe, 3539a0bf528SMauro Carvalho Chehab struct dvb_frontend_tune_settings *fesettings) 3549a0bf528SMauro Carvalho Chehab { 355fe8eece1SAntti Palosaari /* 800 => 2000 because IT9135 v2 is slow to gain lock */ 356fe8eece1SAntti Palosaari fesettings->min_delay_ms = 2000; 3579a0bf528SMauro Carvalho Chehab fesettings->step_size = 0; 3589a0bf528SMauro Carvalho Chehab fesettings->max_drift = 0; 3599a0bf528SMauro Carvalho Chehab 3609a0bf528SMauro Carvalho Chehab return 0; 3619a0bf528SMauro Carvalho Chehab } 3629a0bf528SMauro Carvalho Chehab 3639a0bf528SMauro Carvalho Chehab static int af9033_set_frontend(struct dvb_frontend *fe) 3649a0bf528SMauro Carvalho Chehab { 36509611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 36681e19912SAntti Palosaari struct i2c_client *client = dev->client; 3679a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 368c2feb9ffSAntti Palosaari int ret, i; 369c2feb9ffSAntti Palosaari unsigned int utmp, adc_freq; 3709a0bf528SMauro Carvalho Chehab u8 tmp, buf[3], bandwidth_reg_val; 371c2feb9ffSAntti Palosaari u32 if_frequency; 3729a0bf528SMauro Carvalho Chehab 37381e19912SAntti Palosaari dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u\n", 3746a087f1fSAntti Palosaari c->frequency, c->bandwidth_hz); 3759a0bf528SMauro Carvalho Chehab 37681e19912SAntti Palosaari /* Check bandwidth */ 3779a0bf528SMauro Carvalho Chehab switch (c->bandwidth_hz) { 3789a0bf528SMauro Carvalho Chehab case 6000000: 3799a0bf528SMauro Carvalho Chehab bandwidth_reg_val = 0x00; 3809a0bf528SMauro Carvalho Chehab break; 3819a0bf528SMauro Carvalho Chehab case 7000000: 3829a0bf528SMauro Carvalho Chehab bandwidth_reg_val = 0x01; 3839a0bf528SMauro Carvalho Chehab break; 3849a0bf528SMauro Carvalho Chehab case 8000000: 3859a0bf528SMauro Carvalho Chehab bandwidth_reg_val = 0x02; 3869a0bf528SMauro Carvalho Chehab break; 3879a0bf528SMauro Carvalho Chehab default: 38881e19912SAntti Palosaari dev_dbg(&client->dev, "invalid bandwidth_hz\n"); 3899a0bf528SMauro Carvalho Chehab ret = -EINVAL; 3909a0bf528SMauro Carvalho Chehab goto err; 3919a0bf528SMauro Carvalho Chehab } 3929a0bf528SMauro Carvalho Chehab 39381e19912SAntti Palosaari /* Program tuner */ 3949a0bf528SMauro Carvalho Chehab if (fe->ops.tuner_ops.set_params) 3959a0bf528SMauro Carvalho Chehab fe->ops.tuner_ops.set_params(fe); 3969a0bf528SMauro Carvalho Chehab 39781e19912SAntti Palosaari /* Coefficients */ 39809611caaSAntti Palosaari if (c->bandwidth_hz != dev->bandwidth_hz) { 3999a0bf528SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { 40009611caaSAntti Palosaari if (coeff_lut[i].clock == dev->cfg.clock && 4019a0bf528SMauro Carvalho Chehab coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { 4029a0bf528SMauro Carvalho Chehab break; 4039a0bf528SMauro Carvalho Chehab } 4049a0bf528SMauro Carvalho Chehab } 405060f79d5SMauro Carvalho Chehab if (i == ARRAY_SIZE(coeff_lut)) { 40681e19912SAntti Palosaari dev_err(&client->dev, 40781e19912SAntti Palosaari "Couldn't find config for clock %u\n", 408060f79d5SMauro Carvalho Chehab dev->cfg.clock); 409060f79d5SMauro Carvalho Chehab ret = -EINVAL; 410060f79d5SMauro Carvalho Chehab goto err; 411060f79d5SMauro Carvalho Chehab } 412060f79d5SMauro Carvalho Chehab 413bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x800001, coeff_lut[i].val, 414bc85d5e2SAntti Palosaari sizeof(coeff_lut[i].val)); 415bc85d5e2SAntti Palosaari if (ret) 416bc85d5e2SAntti Palosaari goto err; 4179a0bf528SMauro Carvalho Chehab } 4189a0bf528SMauro Carvalho Chehab 41981e19912SAntti Palosaari /* IF frequency control */ 42009611caaSAntti Palosaari if (c->bandwidth_hz != dev->bandwidth_hz) { 4219a0bf528SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { 42209611caaSAntti Palosaari if (clock_adc_lut[i].clock == dev->cfg.clock) 4239a0bf528SMauro Carvalho Chehab break; 4249a0bf528SMauro Carvalho Chehab } 425060f79d5SMauro Carvalho Chehab if (i == ARRAY_SIZE(clock_adc_lut)) { 42681e19912SAntti Palosaari dev_err(&client->dev, 42781e19912SAntti Palosaari "Couldn't find ADC clock for clock %u\n", 428060f79d5SMauro Carvalho Chehab dev->cfg.clock); 429060f79d5SMauro Carvalho Chehab ret = -EINVAL; 430060f79d5SMauro Carvalho Chehab goto err; 431060f79d5SMauro Carvalho Chehab } 4329a0bf528SMauro Carvalho Chehab adc_freq = clock_adc_lut[i].adc; 4339a0bf528SMauro Carvalho Chehab 434c2feb9ffSAntti Palosaari if (dev->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X) 435c2feb9ffSAntti Palosaari adc_freq = 2 * adc_freq; 436c2feb9ffSAntti Palosaari 43781e19912SAntti Palosaari /* Get used IF frequency */ 4389a0bf528SMauro Carvalho Chehab if (fe->ops.tuner_ops.get_if_frequency) 4399a0bf528SMauro Carvalho Chehab fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); 4409a0bf528SMauro Carvalho Chehab else 4419a0bf528SMauro Carvalho Chehab if_frequency = 0; 4429a0bf528SMauro Carvalho Chehab 443c2feb9ffSAntti Palosaari utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x800000, 444c2feb9ffSAntti Palosaari adc_freq); 4459a0bf528SMauro Carvalho Chehab 446c2feb9ffSAntti Palosaari if (!dev->cfg.spec_inv && if_frequency) 447c2feb9ffSAntti Palosaari utmp = 0x800000 - utmp; 448182b967eSHans-Frieder Vogt 449c2feb9ffSAntti Palosaari buf[0] = (utmp >> 0) & 0xff; 450c2feb9ffSAntti Palosaari buf[1] = (utmp >> 8) & 0xff; 451c2feb9ffSAntti Palosaari buf[2] = (utmp >> 16) & 0xff; 452bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x800029, buf, 3); 453bc85d5e2SAntti Palosaari if (ret) 4549a0bf528SMauro Carvalho Chehab goto err; 4559a0bf528SMauro Carvalho Chehab 45681e19912SAntti Palosaari dev_dbg(&client->dev, "if_frequency_cw=%06x\n", utmp); 457c2feb9ffSAntti Palosaari 45809611caaSAntti Palosaari dev->bandwidth_hz = c->bandwidth_hz; 4599a0bf528SMauro Carvalho Chehab } 4609a0bf528SMauro Carvalho Chehab 461bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f904, 0x03, 462bc85d5e2SAntti Palosaari bandwidth_reg_val); 463bc85d5e2SAntti Palosaari if (ret) 4649a0bf528SMauro Carvalho Chehab goto err; 465bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800040, 0x00); 466bc85d5e2SAntti Palosaari if (ret) 4679a0bf528SMauro Carvalho Chehab goto err; 468bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800047, 0x00); 469bc85d5e2SAntti Palosaari if (ret) 4709a0bf528SMauro Carvalho Chehab goto err; 471bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f999, 0x01, 0x00); 472bc85d5e2SAntti Palosaari if (ret) 4739a0bf528SMauro Carvalho Chehab goto err; 4749a0bf528SMauro Carvalho Chehab 4759a0bf528SMauro Carvalho Chehab if (c->frequency <= 230000000) 4769a0bf528SMauro Carvalho Chehab tmp = 0x00; /* VHF */ 4779a0bf528SMauro Carvalho Chehab else 4789a0bf528SMauro Carvalho Chehab tmp = 0x01; /* UHF */ 4799a0bf528SMauro Carvalho Chehab 480bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80004b, tmp); 481bc85d5e2SAntti Palosaari if (ret) 4829a0bf528SMauro Carvalho Chehab goto err; 48381e19912SAntti Palosaari /* Reset FSM */ 484bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800000, 0x00); 485bc85d5e2SAntti Palosaari if (ret) 4869a0bf528SMauro Carvalho Chehab goto err; 4879a0bf528SMauro Carvalho Chehab 4889a0bf528SMauro Carvalho Chehab return 0; 4899a0bf528SMauro Carvalho Chehab err: 49081e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 4919a0bf528SMauro Carvalho Chehab return ret; 4929a0bf528SMauro Carvalho Chehab } 4939a0bf528SMauro Carvalho Chehab 4947e3e68bcSMauro Carvalho Chehab static int af9033_get_frontend(struct dvb_frontend *fe, 4957e3e68bcSMauro Carvalho Chehab struct dtv_frontend_properties *c) 4969a0bf528SMauro Carvalho Chehab { 49709611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 49881e19912SAntti Palosaari struct i2c_client *client = dev->client; 4999a0bf528SMauro Carvalho Chehab int ret; 5009a0bf528SMauro Carvalho Chehab u8 buf[8]; 5019a0bf528SMauro Carvalho Chehab 50281e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 5039a0bf528SMauro Carvalho Chehab 50481e19912SAntti Palosaari /* Read all needed TPS registers */ 505bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x80f900, buf, 8); 506bc85d5e2SAntti Palosaari if (ret) 5079a0bf528SMauro Carvalho Chehab goto err; 5089a0bf528SMauro Carvalho Chehab 5099a0bf528SMauro Carvalho Chehab switch ((buf[0] >> 0) & 3) { 5109a0bf528SMauro Carvalho Chehab case 0: 5119a0bf528SMauro Carvalho Chehab c->transmission_mode = TRANSMISSION_MODE_2K; 5129a0bf528SMauro Carvalho Chehab break; 5139a0bf528SMauro Carvalho Chehab case 1: 5149a0bf528SMauro Carvalho Chehab c->transmission_mode = TRANSMISSION_MODE_8K; 5159a0bf528SMauro Carvalho Chehab break; 5169a0bf528SMauro Carvalho Chehab } 5179a0bf528SMauro Carvalho Chehab 5189a0bf528SMauro Carvalho Chehab switch ((buf[1] >> 0) & 3) { 5199a0bf528SMauro Carvalho Chehab case 0: 5209a0bf528SMauro Carvalho Chehab c->guard_interval = GUARD_INTERVAL_1_32; 5219a0bf528SMauro Carvalho Chehab break; 5229a0bf528SMauro Carvalho Chehab case 1: 5239a0bf528SMauro Carvalho Chehab c->guard_interval = GUARD_INTERVAL_1_16; 5249a0bf528SMauro Carvalho Chehab break; 5259a0bf528SMauro Carvalho Chehab case 2: 5269a0bf528SMauro Carvalho Chehab c->guard_interval = GUARD_INTERVAL_1_8; 5279a0bf528SMauro Carvalho Chehab break; 5289a0bf528SMauro Carvalho Chehab case 3: 5299a0bf528SMauro Carvalho Chehab c->guard_interval = GUARD_INTERVAL_1_4; 5309a0bf528SMauro Carvalho Chehab break; 5319a0bf528SMauro Carvalho Chehab } 5329a0bf528SMauro Carvalho Chehab 5339a0bf528SMauro Carvalho Chehab switch ((buf[2] >> 0) & 7) { 5349a0bf528SMauro Carvalho Chehab case 0: 5359a0bf528SMauro Carvalho Chehab c->hierarchy = HIERARCHY_NONE; 5369a0bf528SMauro Carvalho Chehab break; 5379a0bf528SMauro Carvalho Chehab case 1: 5389a0bf528SMauro Carvalho Chehab c->hierarchy = HIERARCHY_1; 5399a0bf528SMauro Carvalho Chehab break; 5409a0bf528SMauro Carvalho Chehab case 2: 5419a0bf528SMauro Carvalho Chehab c->hierarchy = HIERARCHY_2; 5429a0bf528SMauro Carvalho Chehab break; 5439a0bf528SMauro Carvalho Chehab case 3: 5449a0bf528SMauro Carvalho Chehab c->hierarchy = HIERARCHY_4; 5459a0bf528SMauro Carvalho Chehab break; 5469a0bf528SMauro Carvalho Chehab } 5479a0bf528SMauro Carvalho Chehab 5489a0bf528SMauro Carvalho Chehab switch ((buf[3] >> 0) & 3) { 5499a0bf528SMauro Carvalho Chehab case 0: 5509a0bf528SMauro Carvalho Chehab c->modulation = QPSK; 5519a0bf528SMauro Carvalho Chehab break; 5529a0bf528SMauro Carvalho Chehab case 1: 5539a0bf528SMauro Carvalho Chehab c->modulation = QAM_16; 5549a0bf528SMauro Carvalho Chehab break; 5559a0bf528SMauro Carvalho Chehab case 2: 5569a0bf528SMauro Carvalho Chehab c->modulation = QAM_64; 5579a0bf528SMauro Carvalho Chehab break; 5589a0bf528SMauro Carvalho Chehab } 5599a0bf528SMauro Carvalho Chehab 5609a0bf528SMauro Carvalho Chehab switch ((buf[4] >> 0) & 3) { 5619a0bf528SMauro Carvalho Chehab case 0: 5629a0bf528SMauro Carvalho Chehab c->bandwidth_hz = 6000000; 5639a0bf528SMauro Carvalho Chehab break; 5649a0bf528SMauro Carvalho Chehab case 1: 5659a0bf528SMauro Carvalho Chehab c->bandwidth_hz = 7000000; 5669a0bf528SMauro Carvalho Chehab break; 5679a0bf528SMauro Carvalho Chehab case 2: 5689a0bf528SMauro Carvalho Chehab c->bandwidth_hz = 8000000; 5699a0bf528SMauro Carvalho Chehab break; 5709a0bf528SMauro Carvalho Chehab } 5719a0bf528SMauro Carvalho Chehab 5729a0bf528SMauro Carvalho Chehab switch ((buf[6] >> 0) & 7) { 5739a0bf528SMauro Carvalho Chehab case 0: 5749a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_1_2; 5759a0bf528SMauro Carvalho Chehab break; 5769a0bf528SMauro Carvalho Chehab case 1: 5779a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_2_3; 5789a0bf528SMauro Carvalho Chehab break; 5799a0bf528SMauro Carvalho Chehab case 2: 5809a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_3_4; 5819a0bf528SMauro Carvalho Chehab break; 5829a0bf528SMauro Carvalho Chehab case 3: 5839a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_5_6; 5849a0bf528SMauro Carvalho Chehab break; 5859a0bf528SMauro Carvalho Chehab case 4: 5869a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_7_8; 5879a0bf528SMauro Carvalho Chehab break; 5889a0bf528SMauro Carvalho Chehab case 5: 5899a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_NONE; 5909a0bf528SMauro Carvalho Chehab break; 5919a0bf528SMauro Carvalho Chehab } 5929a0bf528SMauro Carvalho Chehab 5939a0bf528SMauro Carvalho Chehab switch ((buf[7] >> 0) & 7) { 5949a0bf528SMauro Carvalho Chehab case 0: 5959a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_1_2; 5969a0bf528SMauro Carvalho Chehab break; 5979a0bf528SMauro Carvalho Chehab case 1: 5989a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_2_3; 5999a0bf528SMauro Carvalho Chehab break; 6009a0bf528SMauro Carvalho Chehab case 2: 6019a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_3_4; 6029a0bf528SMauro Carvalho Chehab break; 6039a0bf528SMauro Carvalho Chehab case 3: 6049a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_5_6; 6059a0bf528SMauro Carvalho Chehab break; 6069a0bf528SMauro Carvalho Chehab case 4: 6079a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_7_8; 6089a0bf528SMauro Carvalho Chehab break; 6099a0bf528SMauro Carvalho Chehab case 5: 6109a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_NONE; 6119a0bf528SMauro Carvalho Chehab break; 6129a0bf528SMauro Carvalho Chehab } 6139a0bf528SMauro Carvalho Chehab 6149a0bf528SMauro Carvalho Chehab return 0; 6159a0bf528SMauro Carvalho Chehab err: 61681e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 6179a0bf528SMauro Carvalho Chehab return ret; 6189a0bf528SMauro Carvalho Chehab } 6199a0bf528SMauro Carvalho Chehab 6200df289a2SMauro Carvalho Chehab static int af9033_read_status(struct dvb_frontend *fe, enum fe_status *status) 6219a0bf528SMauro Carvalho Chehab { 62209611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 62381e19912SAntti Palosaari struct i2c_client *client = dev->client; 624659a0999SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 625239dd616SAntti Palosaari int ret, tmp = 0; 626bc85d5e2SAntti Palosaari u8 buf[7]; 627239dd616SAntti Palosaari unsigned int utmp, utmp1; 628659a0999SAntti Palosaari 62981e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 6309a0bf528SMauro Carvalho Chehab 6319a0bf528SMauro Carvalho Chehab *status = 0; 6329a0bf528SMauro Carvalho Chehab 63381e19912SAntti Palosaari /* Radio channel status: 0=no result, 1=has signal, 2=no signal */ 634bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x800047, &utmp); 635bc85d5e2SAntti Palosaari if (ret) 6369a0bf528SMauro Carvalho Chehab goto err; 6379a0bf528SMauro Carvalho Chehab 63881e19912SAntti Palosaari /* Has signal */ 639bc85d5e2SAntti Palosaari if (utmp == 0x01) 6409a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SIGNAL; 6419a0bf528SMauro Carvalho Chehab 642bc85d5e2SAntti Palosaari if (utmp != 0x02) { 6439a0bf528SMauro Carvalho Chehab /* TPS lock */ 644bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f5a9, &utmp); 645bc85d5e2SAntti Palosaari if (ret) 6469a0bf528SMauro Carvalho Chehab goto err; 6479a0bf528SMauro Carvalho Chehab 648bc85d5e2SAntti Palosaari if ((utmp >> 0) & 0x01) 6499a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 6509a0bf528SMauro Carvalho Chehab FE_HAS_VITERBI; 6519a0bf528SMauro Carvalho Chehab 65281e19912SAntti Palosaari /* Full lock */ 653bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f999, &utmp); 654bc85d5e2SAntti Palosaari if (ret) 6559a0bf528SMauro Carvalho Chehab goto err; 6569a0bf528SMauro Carvalho Chehab 657bc85d5e2SAntti Palosaari if ((utmp >> 0) & 0x01) 6589a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 6599a0bf528SMauro Carvalho Chehab FE_HAS_VITERBI | FE_HAS_SYNC | 6609a0bf528SMauro Carvalho Chehab FE_HAS_LOCK; 6619a0bf528SMauro Carvalho Chehab } 6629a0bf528SMauro Carvalho Chehab 66383f11619SAntti Palosaari dev->fe_status = *status; 66483f11619SAntti Palosaari 66581e19912SAntti Palosaari /* Signal strength */ 666659a0999SAntti Palosaari if (dev->fe_status & FE_HAS_SIGNAL) { 667659a0999SAntti Palosaari if (dev->is_af9035) { 668bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80004a, &utmp); 669659a0999SAntti Palosaari if (ret) 670659a0999SAntti Palosaari goto err; 671bc85d5e2SAntti Palosaari tmp = -utmp * 1000; 672659a0999SAntti Palosaari } else { 673bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x8000f7, &utmp); 674659a0999SAntti Palosaari if (ret) 675659a0999SAntti Palosaari goto err; 676bc85d5e2SAntti Palosaari tmp = (utmp - 100) * 1000; 677659a0999SAntti Palosaari } 678659a0999SAntti Palosaari 679659a0999SAntti Palosaari c->strength.len = 1; 680659a0999SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_DECIBEL; 681659a0999SAntti Palosaari c->strength.stat[0].svalue = tmp; 682659a0999SAntti Palosaari } else { 683659a0999SAntti Palosaari c->strength.len = 1; 684659a0999SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 685659a0999SAntti Palosaari } 686659a0999SAntti Palosaari 687659a0999SAntti Palosaari /* CNR */ 688659a0999SAntti Palosaari if (dev->fe_status & FE_HAS_VITERBI) { 68981e19912SAntti Palosaari /* Read raw SNR value */ 690bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x80002c, buf, 3); 691659a0999SAntti Palosaari if (ret) 692659a0999SAntti Palosaari goto err; 693659a0999SAntti Palosaari 694239dd616SAntti Palosaari utmp1 = buf[2] << 16 | buf[1] << 8 | buf[0] << 0; 695659a0999SAntti Palosaari 69681e19912SAntti Palosaari /* Read superframe number */ 697bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f78b, &utmp); 698659a0999SAntti Palosaari if (ret) 699659a0999SAntti Palosaari goto err; 700659a0999SAntti Palosaari 701bc85d5e2SAntti Palosaari if (utmp) 702239dd616SAntti Palosaari utmp1 /= utmp; 703659a0999SAntti Palosaari 70481e19912SAntti Palosaari /* Read current transmission mode */ 705bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f900, &utmp); 706659a0999SAntti Palosaari if (ret) 707659a0999SAntti Palosaari goto err; 708659a0999SAntti Palosaari 709bc85d5e2SAntti Palosaari switch ((utmp >> 0) & 3) { 710659a0999SAntti Palosaari case 0: 711239dd616SAntti Palosaari /* 2k */ 712239dd616SAntti Palosaari utmp1 *= 4; 713659a0999SAntti Palosaari break; 714659a0999SAntti Palosaari case 1: 715239dd616SAntti Palosaari /* 8k */ 716239dd616SAntti Palosaari utmp1 *= 1; 717659a0999SAntti Palosaari break; 718659a0999SAntti Palosaari case 2: 719239dd616SAntti Palosaari /* 4k */ 720239dd616SAntti Palosaari utmp1 *= 2; 721659a0999SAntti Palosaari break; 722659a0999SAntti Palosaari default: 723239dd616SAntti Palosaari utmp1 *= 0; 724659a0999SAntti Palosaari break; 725659a0999SAntti Palosaari } 726659a0999SAntti Palosaari 72781e19912SAntti Palosaari /* Read current modulation */ 728bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f903, &utmp); 729659a0999SAntti Palosaari if (ret) 730659a0999SAntti Palosaari goto err; 731659a0999SAntti Palosaari 732bc85d5e2SAntti Palosaari switch ((utmp >> 0) & 3) { 733659a0999SAntti Palosaari case 0: 734239dd616SAntti Palosaari /* 735239dd616SAntti Palosaari * QPSK 736239dd616SAntti Palosaari * CNR[dB] 13 * -log10((1690000 - value) / value) + 2.6 737239dd616SAntti Palosaari * value [653799, 1689999], 2.6 / 13 = 3355443 738239dd616SAntti Palosaari */ 739239dd616SAntti Palosaari utmp1 = clamp(utmp1, 653799U, 1689999U); 740239dd616SAntti Palosaari utmp1 = ((u64)(intlog10(utmp1) 741239dd616SAntti Palosaari - intlog10(1690000 - utmp1) 742239dd616SAntti Palosaari + 3355443) * 13 * 1000) >> 24; 743659a0999SAntti Palosaari break; 744659a0999SAntti Palosaari case 1: 745239dd616SAntti Palosaari /* 746239dd616SAntti Palosaari * QAM-16 747239dd616SAntti Palosaari * CNR[dB] 6 * log10((value - 370000) / (828000 - value)) + 15.7 748239dd616SAntti Palosaari * value [371105, 827999], 15.7 / 6 = 43900382 749239dd616SAntti Palosaari */ 750239dd616SAntti Palosaari utmp1 = clamp(utmp1, 371105U, 827999U); 751239dd616SAntti Palosaari utmp1 = ((u64)(intlog10(utmp1 - 370000) 752239dd616SAntti Palosaari - intlog10(828000 - utmp1) 753239dd616SAntti Palosaari + 43900382) * 6 * 1000) >> 24; 754659a0999SAntti Palosaari break; 755659a0999SAntti Palosaari case 2: 756239dd616SAntti Palosaari /* 757239dd616SAntti Palosaari * QAM-64 758239dd616SAntti Palosaari * CNR[dB] 8 * log10((value - 193000) / (425000 - value)) + 23.8 759239dd616SAntti Palosaari * value [193246, 424999], 23.8 / 8 = 49912218 760239dd616SAntti Palosaari */ 761239dd616SAntti Palosaari utmp1 = clamp(utmp1, 193246U, 424999U); 762239dd616SAntti Palosaari utmp1 = ((u64)(intlog10(utmp1 - 193000) 763239dd616SAntti Palosaari - intlog10(425000 - utmp1) 764239dd616SAntti Palosaari + 49912218) * 8 * 1000) >> 24; 765659a0999SAntti Palosaari break; 766659a0999SAntti Palosaari default: 767239dd616SAntti Palosaari utmp1 = 0; 768659a0999SAntti Palosaari break; 769659a0999SAntti Palosaari } 770659a0999SAntti Palosaari 771239dd616SAntti Palosaari dev_dbg(&client->dev, "cnr=%u\n", utmp1); 772659a0999SAntti Palosaari 773659a0999SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 774239dd616SAntti Palosaari c->cnr.stat[0].svalue = utmp1; 775659a0999SAntti Palosaari } else { 776659a0999SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 777659a0999SAntti Palosaari } 778659a0999SAntti Palosaari 779659a0999SAntti Palosaari /* UCB/PER/BER */ 780659a0999SAntti Palosaari if (dev->fe_status & FE_HAS_LOCK) { 78181e19912SAntti Palosaari /* Outer FEC, 204 byte packets */ 782659a0999SAntti Palosaari u16 abort_packet_count, rsd_packet_count; 78381e19912SAntti Palosaari /* Inner FEC, bits */ 784659a0999SAntti Palosaari u32 rsd_bit_err_count; 785659a0999SAntti Palosaari 786659a0999SAntti Palosaari /* 787659a0999SAntti Palosaari * Packet count used for measurement is 10000 788659a0999SAntti Palosaari * (rsd_packet_count). Maybe it should be increased? 789659a0999SAntti Palosaari */ 790659a0999SAntti Palosaari 791bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x800032, buf, 7); 792659a0999SAntti Palosaari if (ret) 793659a0999SAntti Palosaari goto err; 794659a0999SAntti Palosaari 795659a0999SAntti Palosaari abort_packet_count = (buf[1] << 8) | (buf[0] << 0); 796659a0999SAntti Palosaari rsd_bit_err_count = (buf[4] << 16) | (buf[3] << 8) | buf[2]; 797659a0999SAntti Palosaari rsd_packet_count = (buf[6] << 8) | (buf[5] << 0); 798659a0999SAntti Palosaari 799659a0999SAntti Palosaari dev->error_block_count += abort_packet_count; 800659a0999SAntti Palosaari dev->total_block_count += rsd_packet_count; 801659a0999SAntti Palosaari dev->post_bit_error += rsd_bit_err_count; 802659a0999SAntti Palosaari dev->post_bit_count += rsd_packet_count * 204 * 8; 803659a0999SAntti Palosaari 804659a0999SAntti Palosaari c->block_count.len = 1; 805659a0999SAntti Palosaari c->block_count.stat[0].scale = FE_SCALE_COUNTER; 806659a0999SAntti Palosaari c->block_count.stat[0].uvalue = dev->total_block_count; 807659a0999SAntti Palosaari 808659a0999SAntti Palosaari c->block_error.len = 1; 809659a0999SAntti Palosaari c->block_error.stat[0].scale = FE_SCALE_COUNTER; 810659a0999SAntti Palosaari c->block_error.stat[0].uvalue = dev->error_block_count; 811659a0999SAntti Palosaari 812659a0999SAntti Palosaari c->post_bit_count.len = 1; 813659a0999SAntti Palosaari c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 814659a0999SAntti Palosaari c->post_bit_count.stat[0].uvalue = dev->post_bit_count; 815659a0999SAntti Palosaari 816659a0999SAntti Palosaari c->post_bit_error.len = 1; 817659a0999SAntti Palosaari c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 818659a0999SAntti Palosaari c->post_bit_error.stat[0].uvalue = dev->post_bit_error; 819659a0999SAntti Palosaari } 820659a0999SAntti Palosaari 8219a0bf528SMauro Carvalho Chehab return 0; 8229a0bf528SMauro Carvalho Chehab err: 82381e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 8249a0bf528SMauro Carvalho Chehab return ret; 8259a0bf528SMauro Carvalho Chehab } 8269a0bf528SMauro Carvalho Chehab 8279a0bf528SMauro Carvalho Chehab static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) 8289a0bf528SMauro Carvalho Chehab { 82909611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 83081e19912SAntti Palosaari struct i2c_client *client = dev->client; 8316b457786SAntti Palosaari struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; 8326d03f6a8SBimow Chen int ret; 833bc85d5e2SAntti Palosaari unsigned int utmp; 8349a0bf528SMauro Carvalho Chehab 83581e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 83681e19912SAntti Palosaari 83781e19912SAntti Palosaari /* Use DVBv5 CNR */ 8386d03f6a8SBimow Chen if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) { 839c3a80cd0SAntti Palosaari /* Return 0.1 dB for AF9030 and 0-0xffff for IT9130. */ 840c3a80cd0SAntti Palosaari if (dev->is_af9035) { 841c3a80cd0SAntti Palosaari /* 1000x => 10x (0.1 dB) */ 842c3a80cd0SAntti Palosaari *snr = div_s64(c->cnr.stat[0].svalue, 100); 843c3a80cd0SAntti Palosaari } else { 844c3a80cd0SAntti Palosaari /* 1000x => 1x (1 dB) */ 8456d03f6a8SBimow Chen *snr = div_s64(c->cnr.stat[0].svalue, 1000); 8466d03f6a8SBimow Chen 84781e19912SAntti Palosaari /* Read current modulation */ 848bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f903, &utmp); 8496d03f6a8SBimow Chen if (ret) 8506d03f6a8SBimow Chen goto err; 8516d03f6a8SBimow Chen 8526d03f6a8SBimow Chen /* scale value to 0x0000-0xffff */ 853bc85d5e2SAntti Palosaari switch ((utmp >> 0) & 3) { 8546d03f6a8SBimow Chen case 0: 855c3a80cd0SAntti Palosaari *snr = *snr * 0xffff / 23; 8566d03f6a8SBimow Chen break; 8576d03f6a8SBimow Chen case 1: 858c3a80cd0SAntti Palosaari *snr = *snr * 0xffff / 26; 8596d03f6a8SBimow Chen break; 8606d03f6a8SBimow Chen case 2: 861c3a80cd0SAntti Palosaari *snr = *snr * 0xffff / 32; 8626d03f6a8SBimow Chen break; 8636d03f6a8SBimow Chen default: 8646d03f6a8SBimow Chen goto err; 8656d03f6a8SBimow Chen } 866c3a80cd0SAntti Palosaari } 8676d03f6a8SBimow Chen } else { 8686b457786SAntti Palosaari *snr = 0; 8696d03f6a8SBimow Chen } 8709a0bf528SMauro Carvalho Chehab 8719a0bf528SMauro Carvalho Chehab return 0; 8726d03f6a8SBimow Chen err: 87381e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 8746d03f6a8SBimow Chen return ret; 8759a0bf528SMauro Carvalho Chehab } 8769a0bf528SMauro Carvalho Chehab 8779a0bf528SMauro Carvalho Chehab static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 8789a0bf528SMauro Carvalho Chehab { 87909611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 88081e19912SAntti Palosaari struct i2c_client *client = dev->client; 8813adec272SBimow Chen struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; 8823adec272SBimow Chen int ret, tmp, power_real; 883bc85d5e2SAntti Palosaari unsigned int utmp; 884bc85d5e2SAntti Palosaari u8 gain_offset, buf[7]; 8859a0bf528SMauro Carvalho Chehab 88681e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 88781e19912SAntti Palosaari 8883adec272SBimow Chen if (dev->is_af9035) { 88981e19912SAntti Palosaari /* Read signal strength of 0-100 scale */ 890bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x800048, &utmp); 891bc85d5e2SAntti Palosaari if (ret) 8920b0d9628SAntti Palosaari goto err; 8930b0d9628SAntti Palosaari 89481e19912SAntti Palosaari /* Scale value to 0x0000-0xffff */ 895bc85d5e2SAntti Palosaari *strength = utmp * 0xffff / 100; 8963adec272SBimow Chen } else { 897bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x8000f7, &utmp); 898bc85d5e2SAntti Palosaari if (ret) 8991620d221SAntti Palosaari goto err; 9001620d221SAntti Palosaari 901bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x80f900, buf, 7); 902bc85d5e2SAntti Palosaari if (ret) 9031620d221SAntti Palosaari goto err; 9043adec272SBimow Chen 9053adec272SBimow Chen if (c->frequency <= 300000000) 9063adec272SBimow Chen gain_offset = 7; /* VHF */ 9073adec272SBimow Chen else 9083adec272SBimow Chen gain_offset = 4; /* UHF */ 9093adec272SBimow Chen 910bc85d5e2SAntti Palosaari power_real = (utmp - 100 - gain_offset) - 9113adec272SBimow Chen power_reference[((buf[3] >> 0) & 3)][((buf[6] >> 0) & 7)]; 9123adec272SBimow Chen 9133adec272SBimow Chen if (power_real < -15) 9143adec272SBimow Chen tmp = 0; 9153adec272SBimow Chen else if ((power_real >= -15) && (power_real < 0)) 9163adec272SBimow Chen tmp = (2 * (power_real + 15)) / 3; 9173adec272SBimow Chen else if ((power_real >= 0) && (power_real < 20)) 9183adec272SBimow Chen tmp = 4 * power_real + 10; 9193adec272SBimow Chen else if ((power_real >= 20) && (power_real < 35)) 9203adec272SBimow Chen tmp = (2 * (power_real - 20)) / 3 + 90; 9213adec272SBimow Chen else 9223adec272SBimow Chen tmp = 100; 9239a0bf528SMauro Carvalho Chehab 92481e19912SAntti Palosaari /* Scale value to 0x0000-0xffff */ 9253adec272SBimow Chen *strength = tmp * 0xffff / 100; 9263adec272SBimow Chen } 9273adec272SBimow Chen 9289a0bf528SMauro Carvalho Chehab return 0; 9299a0bf528SMauro Carvalho Chehab err: 93081e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 9319a0bf528SMauro Carvalho Chehab return ret; 9329a0bf528SMauro Carvalho Chehab } 9339a0bf528SMauro Carvalho Chehab 9349a0bf528SMauro Carvalho Chehab static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) 9359a0bf528SMauro Carvalho Chehab { 93609611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 9379a0bf528SMauro Carvalho Chehab 938e53c4744SAntti Palosaari *ber = (dev->post_bit_error - dev->post_bit_error_prev); 939e53c4744SAntti Palosaari dev->post_bit_error_prev = dev->post_bit_error; 9409a0bf528SMauro Carvalho Chehab 9419a0bf528SMauro Carvalho Chehab return 0; 9429a0bf528SMauro Carvalho Chehab } 9439a0bf528SMauro Carvalho Chehab 9449a0bf528SMauro Carvalho Chehab static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 9459a0bf528SMauro Carvalho Chehab { 94609611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 9479a0bf528SMauro Carvalho Chehab 9481d0ceae4SAntti Palosaari *ucblocks = dev->error_block_count; 94981e19912SAntti Palosaari 9509a0bf528SMauro Carvalho Chehab return 0; 9519a0bf528SMauro Carvalho Chehab } 9529a0bf528SMauro Carvalho Chehab 9539a0bf528SMauro Carvalho Chehab static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 9549a0bf528SMauro Carvalho Chehab { 95509611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 95681e19912SAntti Palosaari struct i2c_client *client = dev->client; 9579a0bf528SMauro Carvalho Chehab int ret; 9589a0bf528SMauro Carvalho Chehab 95981e19912SAntti Palosaari dev_dbg(&client->dev, "enable=%d\n", enable); 9609a0bf528SMauro Carvalho Chehab 961bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00fa04, 0x01, enable); 962bc85d5e2SAntti Palosaari if (ret) 9639a0bf528SMauro Carvalho Chehab goto err; 9649a0bf528SMauro Carvalho Chehab 9659a0bf528SMauro Carvalho Chehab return 0; 9669a0bf528SMauro Carvalho Chehab err: 96781e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 9689a0bf528SMauro Carvalho Chehab return ret; 9699a0bf528SMauro Carvalho Chehab } 9709a0bf528SMauro Carvalho Chehab 971ed97a6feSMauro Carvalho Chehab static int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) 972040cf86cSAntti Palosaari { 97309611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 97481e19912SAntti Palosaari struct i2c_client *client = dev->client; 975040cf86cSAntti Palosaari int ret; 976040cf86cSAntti Palosaari 97781e19912SAntti Palosaari dev_dbg(&client->dev, "onoff=%d\n", onoff); 978040cf86cSAntti Palosaari 979bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f993, 0x01, onoff); 980bc85d5e2SAntti Palosaari if (ret) 981040cf86cSAntti Palosaari goto err; 982040cf86cSAntti Palosaari 983040cf86cSAntti Palosaari return 0; 984040cf86cSAntti Palosaari err: 98581e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 986040cf86cSAntti Palosaari return ret; 987040cf86cSAntti Palosaari } 988040cf86cSAntti Palosaari 98924e419a0SAntti Palosaari static int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid, 99024e419a0SAntti Palosaari int onoff) 991040cf86cSAntti Palosaari { 99209611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 99381e19912SAntti Palosaari struct i2c_client *client = dev->client; 994040cf86cSAntti Palosaari int ret; 995040cf86cSAntti Palosaari u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff}; 996040cf86cSAntti Palosaari 99781e19912SAntti Palosaari dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n", 9986a087f1fSAntti Palosaari index, pid, onoff); 999040cf86cSAntti Palosaari 1000040cf86cSAntti Palosaari if (pid > 0x1fff) 1001040cf86cSAntti Palosaari return 0; 1002040cf86cSAntti Palosaari 1003bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x80f996, wbuf, 2); 1004bc85d5e2SAntti Palosaari if (ret) 1005040cf86cSAntti Palosaari goto err; 1006bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80f994, onoff); 1007bc85d5e2SAntti Palosaari if (ret) 1008040cf86cSAntti Palosaari goto err; 1009bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80f995, index); 1010bc85d5e2SAntti Palosaari if (ret) 1011040cf86cSAntti Palosaari goto err; 1012040cf86cSAntti Palosaari 1013040cf86cSAntti Palosaari return 0; 1014040cf86cSAntti Palosaari err: 101581e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 1016040cf86cSAntti Palosaari return ret; 1017040cf86cSAntti Palosaari } 1018040cf86cSAntti Palosaari 1019bd336e63SMax Kellermann static const struct dvb_frontend_ops af9033_ops = { 10209a0bf528SMauro Carvalho Chehab .delsys = {SYS_DVBT}, 10219a0bf528SMauro Carvalho Chehab .info = { 10229a0bf528SMauro Carvalho Chehab .name = "Afatech AF9033 (DVB-T)", 1023f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 174 * MHz, 1024f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 862 * MHz, 1025f1b1eabfSMauro Carvalho Chehab .frequency_stepsize_hz = 250 * kHz, 10269a0bf528SMauro Carvalho Chehab .caps = FE_CAN_FEC_1_2 | 10279a0bf528SMauro Carvalho Chehab FE_CAN_FEC_2_3 | 10289a0bf528SMauro Carvalho Chehab FE_CAN_FEC_3_4 | 10299a0bf528SMauro Carvalho Chehab FE_CAN_FEC_5_6 | 10309a0bf528SMauro Carvalho Chehab FE_CAN_FEC_7_8 | 10319a0bf528SMauro Carvalho Chehab FE_CAN_FEC_AUTO | 10329a0bf528SMauro Carvalho Chehab FE_CAN_QPSK | 10339a0bf528SMauro Carvalho Chehab FE_CAN_QAM_16 | 10349a0bf528SMauro Carvalho Chehab FE_CAN_QAM_64 | 10359a0bf528SMauro Carvalho Chehab FE_CAN_QAM_AUTO | 10369a0bf528SMauro Carvalho Chehab FE_CAN_TRANSMISSION_MODE_AUTO | 10379a0bf528SMauro Carvalho Chehab FE_CAN_GUARD_INTERVAL_AUTO | 10389a0bf528SMauro Carvalho Chehab FE_CAN_HIERARCHY_AUTO | 10399a0bf528SMauro Carvalho Chehab FE_CAN_RECOVER | 10409a0bf528SMauro Carvalho Chehab FE_CAN_MUTE_TS 10419a0bf528SMauro Carvalho Chehab }, 10429a0bf528SMauro Carvalho Chehab 10439a0bf528SMauro Carvalho Chehab .init = af9033_init, 10449a0bf528SMauro Carvalho Chehab .sleep = af9033_sleep, 10459a0bf528SMauro Carvalho Chehab 10469a0bf528SMauro Carvalho Chehab .get_tune_settings = af9033_get_tune_settings, 10479a0bf528SMauro Carvalho Chehab .set_frontend = af9033_set_frontend, 10489a0bf528SMauro Carvalho Chehab .get_frontend = af9033_get_frontend, 10499a0bf528SMauro Carvalho Chehab 10509a0bf528SMauro Carvalho Chehab .read_status = af9033_read_status, 10519a0bf528SMauro Carvalho Chehab .read_snr = af9033_read_snr, 10529a0bf528SMauro Carvalho Chehab .read_signal_strength = af9033_read_signal_strength, 10539a0bf528SMauro Carvalho Chehab .read_ber = af9033_read_ber, 10549a0bf528SMauro Carvalho Chehab .read_ucblocks = af9033_read_ucblocks, 10559a0bf528SMauro Carvalho Chehab 10569a0bf528SMauro Carvalho Chehab .i2c_gate_ctrl = af9033_i2c_gate_ctrl, 10579a0bf528SMauro Carvalho Chehab }; 10589a0bf528SMauro Carvalho Chehab 1059f5b00a76SAntti Palosaari static int af9033_probe(struct i2c_client *client, 1060f5b00a76SAntti Palosaari const struct i2c_device_id *id) 1061f5b00a76SAntti Palosaari { 1062f5b00a76SAntti Palosaari struct af9033_config *cfg = client->dev.platform_data; 1063f5b00a76SAntti Palosaari struct af9033_dev *dev; 1064f5b00a76SAntti Palosaari int ret; 1065f5b00a76SAntti Palosaari u8 buf[8]; 1066f5b00a76SAntti Palosaari u32 reg; 1067bc85d5e2SAntti Palosaari static const struct regmap_config regmap_config = { 1068bc85d5e2SAntti Palosaari .reg_bits = 24, 1069bc85d5e2SAntti Palosaari .val_bits = 8, 1070bc85d5e2SAntti Palosaari }; 1071bc85d5e2SAntti Palosaari 107281e19912SAntti Palosaari /* Allocate memory for the internal state */ 107381e19912SAntti Palosaari dev = kzalloc(sizeof(*dev), GFP_KERNEL); 107481e19912SAntti Palosaari if (!dev) { 1075f5b00a76SAntti Palosaari ret = -ENOMEM; 1076f5b00a76SAntti Palosaari goto err; 1077f5b00a76SAntti Palosaari } 1078f5b00a76SAntti Palosaari 107981e19912SAntti Palosaari /* Setup the state */ 1080f5b00a76SAntti Palosaari dev->client = client; 108181e19912SAntti Palosaari memcpy(&dev->cfg, cfg, sizeof(dev->cfg)); 108281e19912SAntti Palosaari switch (dev->cfg.ts_mode) { 108381e19912SAntti Palosaari case AF9033_TS_MODE_PARALLEL: 108481e19912SAntti Palosaari dev->ts_mode_parallel = true; 108581e19912SAntti Palosaari break; 108681e19912SAntti Palosaari case AF9033_TS_MODE_SERIAL: 108781e19912SAntti Palosaari dev->ts_mode_serial = true; 108881e19912SAntti Palosaari break; 108981e19912SAntti Palosaari case AF9033_TS_MODE_USB: 109081e19912SAntti Palosaari /* USB mode for AF9035 */ 109181e19912SAntti Palosaari default: 109281e19912SAntti Palosaari break; 109381e19912SAntti Palosaari } 1094f5b00a76SAntti Palosaari 1095f5b00a76SAntti Palosaari if (dev->cfg.clock != 12000000) { 1096f5b00a76SAntti Palosaari ret = -ENODEV; 109781e19912SAntti Palosaari dev_err(&client->dev, 109881e19912SAntti Palosaari "Unsupported clock %u Hz. Only 12000000 Hz is supported currently\n", 10996a087f1fSAntti Palosaari dev->cfg.clock); 1100f5b00a76SAntti Palosaari goto err_kfree; 1101f5b00a76SAntti Palosaari } 1102f5b00a76SAntti Palosaari 1103bc85d5e2SAntti Palosaari /* Create regmap */ 1104bc85d5e2SAntti Palosaari dev->regmap = regmap_init_i2c(client, ®map_config); 1105bc85d5e2SAntti Palosaari if (IS_ERR(dev->regmap)) { 1106bc85d5e2SAntti Palosaari ret = PTR_ERR(dev->regmap); 1107bc85d5e2SAntti Palosaari goto err_kfree; 1108bc85d5e2SAntti Palosaari } 1109bc85d5e2SAntti Palosaari 111081e19912SAntti Palosaari /* Firmware version */ 1111f5b00a76SAntti Palosaari switch (dev->cfg.tuner) { 1112f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_38: 1113f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_51: 1114f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_52: 1115f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_60: 1116f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_61: 1117f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_62: 111883f11619SAntti Palosaari dev->is_it9135 = true; 1119f5b00a76SAntti Palosaari reg = 0x004bfc; 1120f5b00a76SAntti Palosaari break; 1121f5b00a76SAntti Palosaari default: 112283f11619SAntti Palosaari dev->is_af9035 = true; 1123f5b00a76SAntti Palosaari reg = 0x0083e9; 1124f5b00a76SAntti Palosaari break; 1125f5b00a76SAntti Palosaari } 1126f5b00a76SAntti Palosaari 1127bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, reg, &buf[0], 4); 1128bc85d5e2SAntti Palosaari if (ret) 1129bc85d5e2SAntti Palosaari goto err_regmap_exit; 1130bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x804191, &buf[4], 4); 1131bc85d5e2SAntti Palosaari if (ret) 1132bc85d5e2SAntti Palosaari goto err_regmap_exit; 1133f5b00a76SAntti Palosaari 113481e19912SAntti Palosaari dev_info(&client->dev, 11356a087f1fSAntti Palosaari "firmware version: LINK %d.%d.%d.%d - OFDM %d.%d.%d.%d\n", 113681e19912SAntti Palosaari buf[0], buf[1], buf[2], buf[3], 113781e19912SAntti Palosaari buf[4], buf[5], buf[6], buf[7]); 1138f5b00a76SAntti Palosaari 113981e19912SAntti Palosaari /* Sleep as chip seems to be partly active by default */ 1140f5b00a76SAntti Palosaari /* IT9135 did not like to sleep at that early */ 114109a446d2SVictor Toso if (dev->is_af9035) { 1142bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80004c, 0x01); 1143bc85d5e2SAntti Palosaari if (ret) 1144bc85d5e2SAntti Palosaari goto err_regmap_exit; 1145bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800000, 0x00); 1146bc85d5e2SAntti Palosaari if (ret) 1147bc85d5e2SAntti Palosaari goto err_regmap_exit; 1148f5b00a76SAntti Palosaari } 1149f5b00a76SAntti Palosaari 115081e19912SAntti Palosaari /* Create dvb frontend */ 115181e19912SAntti Palosaari memcpy(&dev->fe.ops, &af9033_ops, sizeof(dev->fe.ops)); 1152f5b00a76SAntti Palosaari dev->fe.demodulator_priv = dev; 1153f5b00a76SAntti Palosaari *cfg->fe = &dev->fe; 1154f5b00a76SAntti Palosaari if (cfg->ops) { 1155f5b00a76SAntti Palosaari cfg->ops->pid_filter = af9033_pid_filter; 1156f5b00a76SAntti Palosaari cfg->ops->pid_filter_ctrl = af9033_pid_filter_ctrl; 1157f5b00a76SAntti Palosaari } 11583461831aSAntti Palosaari cfg->regmap = dev->regmap; 1159f5b00a76SAntti Palosaari i2c_set_clientdata(client, dev); 1160f5b00a76SAntti Palosaari 116181e19912SAntti Palosaari dev_info(&client->dev, "Afatech AF9033 successfully attached\n"); 116281e19912SAntti Palosaari 1163f5b00a76SAntti Palosaari return 0; 1164bc85d5e2SAntti Palosaari err_regmap_exit: 1165bc85d5e2SAntti Palosaari regmap_exit(dev->regmap); 1166f5b00a76SAntti Palosaari err_kfree: 1167f5b00a76SAntti Palosaari kfree(dev); 1168f5b00a76SAntti Palosaari err: 11696a087f1fSAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 1170f5b00a76SAntti Palosaari return ret; 1171f5b00a76SAntti Palosaari } 1172f5b00a76SAntti Palosaari 1173f5b00a76SAntti Palosaari static int af9033_remove(struct i2c_client *client) 1174f5b00a76SAntti Palosaari { 1175f5b00a76SAntti Palosaari struct af9033_dev *dev = i2c_get_clientdata(client); 1176f5b00a76SAntti Palosaari 117781e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 1178f5b00a76SAntti Palosaari 1179bc85d5e2SAntti Palosaari regmap_exit(dev->regmap); 1180f5b00a76SAntti Palosaari kfree(dev); 1181f5b00a76SAntti Palosaari 1182f5b00a76SAntti Palosaari return 0; 1183f5b00a76SAntti Palosaari } 1184f5b00a76SAntti Palosaari 1185f5b00a76SAntti Palosaari static const struct i2c_device_id af9033_id_table[] = { 1186f5b00a76SAntti Palosaari {"af9033", 0}, 1187f5b00a76SAntti Palosaari {} 1188f5b00a76SAntti Palosaari }; 1189f5b00a76SAntti Palosaari MODULE_DEVICE_TABLE(i2c, af9033_id_table); 1190f5b00a76SAntti Palosaari 1191f5b00a76SAntti Palosaari static struct i2c_driver af9033_driver = { 1192f5b00a76SAntti Palosaari .driver = { 1193f5b00a76SAntti Palosaari .name = "af9033", 119472812175SAntti Palosaari .suppress_bind_attrs = true, 1195f5b00a76SAntti Palosaari }, 1196f5b00a76SAntti Palosaari .probe = af9033_probe, 1197f5b00a76SAntti Palosaari .remove = af9033_remove, 1198f5b00a76SAntti Palosaari .id_table = af9033_id_table, 1199f5b00a76SAntti Palosaari }; 1200f5b00a76SAntti Palosaari 1201f5b00a76SAntti Palosaari module_i2c_driver(af9033_driver); 1202f5b00a76SAntti Palosaari 12039a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 12049a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); 12059a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL"); 1206