1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29a0bf528SMauro Carvalho Chehab /* 39a0bf528SMauro Carvalho Chehab * Afatech AF9033 demodulator driver 49a0bf528SMauro Carvalho Chehab * 59a0bf528SMauro Carvalho Chehab * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 69a0bf528SMauro Carvalho Chehab * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> 79a0bf528SMauro Carvalho Chehab */ 89a0bf528SMauro Carvalho Chehab 99a0bf528SMauro Carvalho Chehab #include "af9033_priv.h" 109a0bf528SMauro Carvalho Chehab 1109611caaSAntti Palosaari struct af9033_dev { 12f5b00a76SAntti Palosaari struct i2c_client *client; 13bc85d5e2SAntti Palosaari struct regmap *regmap; 149a0bf528SMauro Carvalho Chehab struct dvb_frontend fe; 159a0bf528SMauro Carvalho Chehab struct af9033_config cfg; 1683f11619SAntti Palosaari bool is_af9035; 1783f11619SAntti Palosaari bool is_it9135; 189a0bf528SMauro Carvalho Chehab 199a0bf528SMauro Carvalho Chehab u32 bandwidth_hz; 209a0bf528SMauro Carvalho Chehab bool ts_mode_parallel; 219a0bf528SMauro Carvalho Chehab bool ts_mode_serial; 229a0bf528SMauro Carvalho Chehab 230df289a2SMauro Carvalho Chehab enum fe_status fe_status; 24e53c4744SAntti Palosaari u64 post_bit_error_prev; /* for old read_ber we return (curr - prev) */ 256bb096c9SAntti Palosaari u64 post_bit_error; 266bb096c9SAntti Palosaari u64 post_bit_count; 27204f4319SAntti Palosaari u64 error_block_count; 28204f4319SAntti Palosaari u64 total_block_count; 299a0bf528SMauro Carvalho Chehab }; 309a0bf528SMauro Carvalho Chehab 3181e19912SAntti Palosaari /* Write reg val table using reg addr auto increment */ 3209611caaSAntti Palosaari static int af9033_wr_reg_val_tab(struct af9033_dev *dev, 333bf5e552SAntti Palosaari const struct reg_val *tab, int tab_len) 343bf5e552SAntti Palosaari { 3581e19912SAntti Palosaari struct i2c_client *client = dev->client; 36d18a88b1SAntti Palosaari #define MAX_TAB_LEN 212 373bf5e552SAntti Palosaari int ret, i, j; 38d18a88b1SAntti Palosaari u8 buf[1 + MAX_TAB_LEN]; 39d18a88b1SAntti Palosaari 4081e19912SAntti Palosaari dev_dbg(&client->dev, "tab_len=%d\n", tab_len); 4137ebaf68SMauro Carvalho Chehab 4237ebaf68SMauro Carvalho Chehab if (tab_len > sizeof(buf)) { 4381e19912SAntti Palosaari dev_warn(&client->dev, "tab len %d is too big\n", tab_len); 4437ebaf68SMauro Carvalho Chehab return -EINVAL; 4537ebaf68SMauro Carvalho Chehab } 463bf5e552SAntti Palosaari 473bf5e552SAntti Palosaari for (i = 0, j = 0; i < tab_len; i++) { 483bf5e552SAntti Palosaari buf[j] = tab[i].val; 493bf5e552SAntti Palosaari 503bf5e552SAntti Palosaari if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) { 51bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, tab[i].reg - j, 52bc85d5e2SAntti Palosaari buf, j + 1); 53bc85d5e2SAntti Palosaari if (ret) 543bf5e552SAntti Palosaari goto err; 553bf5e552SAntti Palosaari 563bf5e552SAntti Palosaari j = 0; 573bf5e552SAntti Palosaari } else { 583bf5e552SAntti Palosaari j++; 593bf5e552SAntti Palosaari } 603bf5e552SAntti Palosaari } 613bf5e552SAntti Palosaari 623bf5e552SAntti Palosaari return 0; 633bf5e552SAntti Palosaari err: 6481e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 653bf5e552SAntti Palosaari return ret; 663bf5e552SAntti Palosaari } 673bf5e552SAntti Palosaari 689a0bf528SMauro Carvalho Chehab static int af9033_init(struct dvb_frontend *fe) 699a0bf528SMauro Carvalho Chehab { 7009611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 7181e19912SAntti Palosaari struct i2c_client *client = dev->client; 722db4d179SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 739a0bf528SMauro Carvalho Chehab int ret, i, len; 74c2feb9ffSAntti Palosaari unsigned int utmp; 759a0bf528SMauro Carvalho Chehab const struct reg_val *init; 769a0bf528SMauro Carvalho Chehab u8 buf[4]; 779a0bf528SMauro Carvalho Chehab struct reg_val_mask tab[] = { 789a0bf528SMauro Carvalho Chehab { 0x80fb24, 0x00, 0x08 }, 799a0bf528SMauro Carvalho Chehab { 0x80004c, 0x00, 0xff }, 8009611caaSAntti Palosaari { 0x00f641, dev->cfg.tuner, 0xff }, 819a0bf528SMauro Carvalho Chehab { 0x80f5ca, 0x01, 0x01 }, 829a0bf528SMauro Carvalho Chehab { 0x80f715, 0x01, 0x01 }, 839a0bf528SMauro Carvalho Chehab { 0x00f41f, 0x04, 0x04 }, 849a0bf528SMauro Carvalho Chehab { 0x00f41a, 0x01, 0x01 }, 859a0bf528SMauro Carvalho Chehab { 0x80f731, 0x00, 0x01 }, 869a0bf528SMauro Carvalho Chehab { 0x00d91e, 0x00, 0x01 }, 879a0bf528SMauro Carvalho Chehab { 0x00d919, 0x00, 0x01 }, 889a0bf528SMauro Carvalho Chehab { 0x80f732, 0x00, 0x01 }, 899a0bf528SMauro Carvalho Chehab { 0x00d91f, 0x00, 0x01 }, 909a0bf528SMauro Carvalho Chehab { 0x00d91a, 0x00, 0x01 }, 919a0bf528SMauro Carvalho Chehab { 0x80f730, 0x00, 0x01 }, 929a0bf528SMauro Carvalho Chehab { 0x80f778, 0x00, 0xff }, 939a0bf528SMauro Carvalho Chehab { 0x80f73c, 0x01, 0x01 }, 949a0bf528SMauro Carvalho Chehab { 0x80f776, 0x00, 0x01 }, 959a0bf528SMauro Carvalho Chehab { 0x00d8fd, 0x01, 0xff }, 969a0bf528SMauro Carvalho Chehab { 0x00d830, 0x01, 0xff }, 979a0bf528SMauro Carvalho Chehab { 0x00d831, 0x00, 0xff }, 989a0bf528SMauro Carvalho Chehab { 0x00d832, 0x00, 0xff }, 9909611caaSAntti Palosaari { 0x80f985, dev->ts_mode_serial, 0x01 }, 10009611caaSAntti Palosaari { 0x80f986, dev->ts_mode_parallel, 0x01 }, 1019a0bf528SMauro Carvalho Chehab { 0x00d827, 0x00, 0xff }, 1029a0bf528SMauro Carvalho Chehab { 0x00d829, 0x00, 0xff }, 10309611caaSAntti Palosaari { 0x800045, dev->cfg.adc_multiplier, 0xff }, 1049a0bf528SMauro Carvalho Chehab }; 1059a0bf528SMauro Carvalho Chehab 10681e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 10781e19912SAntti Palosaari 10881e19912SAntti Palosaari /* Main clk control */ 109c2feb9ffSAntti Palosaari utmp = div_u64((u64)dev->cfg.clock * 0x80000, 1000000); 110c2feb9ffSAntti Palosaari buf[0] = (utmp >> 0) & 0xff; 111c2feb9ffSAntti Palosaari buf[1] = (utmp >> 8) & 0xff; 112c2feb9ffSAntti Palosaari buf[2] = (utmp >> 16) & 0xff; 113c2feb9ffSAntti Palosaari buf[3] = (utmp >> 24) & 0xff; 114bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x800025, buf, 4); 115bc85d5e2SAntti Palosaari if (ret) 1169a0bf528SMauro Carvalho Chehab goto err; 1179a0bf528SMauro Carvalho Chehab 11881e19912SAntti Palosaari dev_dbg(&client->dev, "clk=%u clk_cw=%08x\n", dev->cfg.clock, utmp); 119c2feb9ffSAntti Palosaari 12081e19912SAntti Palosaari /* ADC clk control */ 1219a0bf528SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { 12209611caaSAntti Palosaari if (clock_adc_lut[i].clock == dev->cfg.clock) 1239a0bf528SMauro Carvalho Chehab break; 1249a0bf528SMauro Carvalho Chehab } 125060f79d5SMauro Carvalho Chehab if (i == ARRAY_SIZE(clock_adc_lut)) { 12681e19912SAntti Palosaari dev_err(&client->dev, "Couldn't find ADC config for clock %d\n", 127060f79d5SMauro Carvalho Chehab dev->cfg.clock); 128060f79d5SMauro Carvalho Chehab goto err; 129060f79d5SMauro Carvalho Chehab } 1309a0bf528SMauro Carvalho Chehab 131c2feb9ffSAntti Palosaari utmp = div_u64((u64)clock_adc_lut[i].adc * 0x80000, 1000000); 132c2feb9ffSAntti Palosaari buf[0] = (utmp >> 0) & 0xff; 133c2feb9ffSAntti Palosaari buf[1] = (utmp >> 8) & 0xff; 134c2feb9ffSAntti Palosaari buf[2] = (utmp >> 16) & 0xff; 135bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x80f1cd, buf, 3); 136bc85d5e2SAntti Palosaari if (ret) 1379a0bf528SMauro Carvalho Chehab goto err; 1389a0bf528SMauro Carvalho Chehab 13981e19912SAntti Palosaari dev_dbg(&client->dev, "adc=%u adc_cw=%06x\n", 140c2feb9ffSAntti Palosaari clock_adc_lut[i].adc, utmp); 141c2feb9ffSAntti Palosaari 14281e19912SAntti Palosaari /* Config register table */ 1439a0bf528SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(tab); i++) { 144bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, tab[i].reg, tab[i].mask, 145bc85d5e2SAntti Palosaari tab[i].val); 146bc85d5e2SAntti Palosaari if (ret) 1479a0bf528SMauro Carvalho Chehab goto err; 1489a0bf528SMauro Carvalho Chehab } 1499a0bf528SMauro Carvalho Chehab 15081e19912SAntti Palosaari /* Demod clk output */ 15109611caaSAntti Palosaari if (dev->cfg.dyn0_clk) { 152bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80fba8, 0x00); 153bc85d5e2SAntti Palosaari if (ret) 1549dc0f3feSAntti Palosaari goto err; 1559dc0f3feSAntti Palosaari } 1569dc0f3feSAntti Palosaari 15781e19912SAntti Palosaari /* TS interface */ 15809611caaSAntti Palosaari if (dev->cfg.ts_mode == AF9033_TS_MODE_USB) { 159bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f9a5, 0x01, 0x00); 160bc85d5e2SAntti Palosaari if (ret) 1619a0bf528SMauro Carvalho Chehab goto err; 162bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f9b5, 0x01, 0x01); 163bc85d5e2SAntti Palosaari if (ret) 1649a0bf528SMauro Carvalho Chehab goto err; 1659a0bf528SMauro Carvalho Chehab } else { 166bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f990, 0x01, 0x00); 167bc85d5e2SAntti Palosaari if (ret) 1689a0bf528SMauro Carvalho Chehab goto err; 169bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f9b5, 0x01, 0x00); 170bc85d5e2SAntti Palosaari if (ret) 1719a0bf528SMauro Carvalho Chehab goto err; 1729a0bf528SMauro Carvalho Chehab } 1739a0bf528SMauro Carvalho Chehab 17481e19912SAntti Palosaari /* Demod core settings */ 17581e19912SAntti Palosaari dev_dbg(&client->dev, "load ofsm settings\n"); 17609611caaSAntti Palosaari switch (dev->cfg.tuner) { 177fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_38: 178fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_51: 179fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_52: 180463c399cSAntti Palosaari len = ARRAY_SIZE(ofsm_init_it9135_v1); 181463c399cSAntti Palosaari init = ofsm_init_it9135_v1; 182463c399cSAntti Palosaari break; 183fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_60: 184fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_61: 185fe8eece1SAntti Palosaari case AF9033_TUNER_IT9135_62: 186463c399cSAntti Palosaari len = ARRAY_SIZE(ofsm_init_it9135_v2); 187463c399cSAntti Palosaari init = ofsm_init_it9135_v2; 188fe8eece1SAntti Palosaari break; 189fe8eece1SAntti Palosaari default: 1909a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(ofsm_init); 1919a0bf528SMauro Carvalho Chehab init = ofsm_init; 192fe8eece1SAntti Palosaari break; 193fe8eece1SAntti Palosaari } 194fe8eece1SAntti Palosaari 19509611caaSAntti Palosaari ret = af9033_wr_reg_val_tab(dev, init, len); 196bc85d5e2SAntti Palosaari if (ret) 1979a0bf528SMauro Carvalho Chehab goto err; 1989a0bf528SMauro Carvalho Chehab 19981e19912SAntti Palosaari /* Demod tuner specific settings */ 20081e19912SAntti Palosaari dev_dbg(&client->dev, "load tuner specific settings\n"); 20109611caaSAntti Palosaari switch (dev->cfg.tuner) { 2029a0bf528SMauro Carvalho Chehab case AF9033_TUNER_TUA9001: 2039a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(tuner_init_tua9001); 2049a0bf528SMauro Carvalho Chehab init = tuner_init_tua9001; 2059a0bf528SMauro Carvalho Chehab break; 2069a0bf528SMauro Carvalho Chehab case AF9033_TUNER_FC0011: 2079a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(tuner_init_fc0011); 2089a0bf528SMauro Carvalho Chehab init = tuner_init_fc0011; 2099a0bf528SMauro Carvalho Chehab break; 2109a0bf528SMauro Carvalho Chehab case AF9033_TUNER_MXL5007T: 2119a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(tuner_init_mxl5007t); 2129a0bf528SMauro Carvalho Chehab init = tuner_init_mxl5007t; 2139a0bf528SMauro Carvalho Chehab break; 2149a0bf528SMauro Carvalho Chehab case AF9033_TUNER_TDA18218: 2159a0bf528SMauro Carvalho Chehab len = ARRAY_SIZE(tuner_init_tda18218); 2169a0bf528SMauro Carvalho Chehab init = tuner_init_tda18218; 2179a0bf528SMauro Carvalho Chehab break; 218d67ceb33SOliver Schinagl case AF9033_TUNER_FC2580: 219d67ceb33SOliver Schinagl len = ARRAY_SIZE(tuner_init_fc2580); 220d67ceb33SOliver Schinagl init = tuner_init_fc2580; 221d67ceb33SOliver Schinagl break; 222e713ad15SAntti Palosaari case AF9033_TUNER_FC0012: 223e713ad15SAntti Palosaari len = ARRAY_SIZE(tuner_init_fc0012); 224e713ad15SAntti Palosaari init = tuner_init_fc0012; 225e713ad15SAntti Palosaari break; 2264902bb39SAntti Palosaari case AF9033_TUNER_IT9135_38: 227a72cbb77SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_38); 228a72cbb77SAntti Palosaari init = tuner_init_it9135_38; 229a72cbb77SAntti Palosaari break; 2304902bb39SAntti Palosaari case AF9033_TUNER_IT9135_51: 231bb2e12a6SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_51); 232bb2e12a6SAntti Palosaari init = tuner_init_it9135_51; 233bb2e12a6SAntti Palosaari break; 2344902bb39SAntti Palosaari case AF9033_TUNER_IT9135_52: 23522d729f3SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_52); 23622d729f3SAntti Palosaari init = tuner_init_it9135_52; 23722d729f3SAntti Palosaari break; 2384902bb39SAntti Palosaari case AF9033_TUNER_IT9135_60: 239a49f53a0SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_60); 240a49f53a0SAntti Palosaari init = tuner_init_it9135_60; 241a49f53a0SAntti Palosaari break; 2424902bb39SAntti Palosaari case AF9033_TUNER_IT9135_61: 24385211323SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_61); 24485211323SAntti Palosaari init = tuner_init_it9135_61; 24585211323SAntti Palosaari break; 2464902bb39SAntti Palosaari case AF9033_TUNER_IT9135_62: 247dc4a2c40SAntti Palosaari len = ARRAY_SIZE(tuner_init_it9135_62); 248dc4a2c40SAntti Palosaari init = tuner_init_it9135_62; 2494902bb39SAntti Palosaari break; 2509a0bf528SMauro Carvalho Chehab default: 25181e19912SAntti Palosaari dev_dbg(&client->dev, "unsupported tuner ID=%d\n", 2526a087f1fSAntti Palosaari dev->cfg.tuner); 2539a0bf528SMauro Carvalho Chehab ret = -ENODEV; 2549a0bf528SMauro Carvalho Chehab goto err; 2559a0bf528SMauro Carvalho Chehab } 2569a0bf528SMauro Carvalho Chehab 25709611caaSAntti Palosaari ret = af9033_wr_reg_val_tab(dev, init, len); 258bc85d5e2SAntti Palosaari if (ret) 2599a0bf528SMauro Carvalho Chehab goto err; 2609a0bf528SMauro Carvalho Chehab 26109611caaSAntti Palosaari if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { 262bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d91c, 0x01, 0x01); 263bc85d5e2SAntti Palosaari if (ret) 2649805992fSJose Alberto Reguero goto err; 265bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d917, 0x01, 0x00); 266bc85d5e2SAntti Palosaari if (ret) 2679805992fSJose Alberto Reguero goto err; 268bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d916, 0x01, 0x00); 269bc85d5e2SAntti Palosaari if (ret) 2709805992fSJose Alberto Reguero goto err; 2719805992fSJose Alberto Reguero } 2729805992fSJose Alberto Reguero 27309611caaSAntti Palosaari switch (dev->cfg.tuner) { 274086991ddSAntti Palosaari case AF9033_TUNER_IT9135_60: 275086991ddSAntti Palosaari case AF9033_TUNER_IT9135_61: 276086991ddSAntti Palosaari case AF9033_TUNER_IT9135_62: 277bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800000, 0x01); 278bc85d5e2SAntti Palosaari if (ret) 279086991ddSAntti Palosaari goto err; 280086991ddSAntti Palosaari } 281086991ddSAntti Palosaari 28281e19912SAntti Palosaari dev->bandwidth_hz = 0; /* Force to program all parameters */ 28381e19912SAntti Palosaari /* Init stats here in order signal app which stats are supported */ 2842db4d179SAntti Palosaari c->strength.len = 1; 2852db4d179SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2862db4d179SAntti Palosaari c->cnr.len = 1; 2872db4d179SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2882db4d179SAntti Palosaari c->block_count.len = 1; 2892db4d179SAntti Palosaari c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2902db4d179SAntti Palosaari c->block_error.len = 1; 2912db4d179SAntti Palosaari c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2922db4d179SAntti Palosaari c->post_bit_count.len = 1; 2932db4d179SAntti Palosaari c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2942db4d179SAntti Palosaari c->post_bit_error.len = 1; 2952db4d179SAntti Palosaari c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2969a0bf528SMauro Carvalho Chehab 2979a0bf528SMauro Carvalho Chehab return 0; 2989a0bf528SMauro Carvalho Chehab err: 29981e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 3009a0bf528SMauro Carvalho Chehab return ret; 3019a0bf528SMauro Carvalho Chehab } 3029a0bf528SMauro Carvalho Chehab 3039a0bf528SMauro Carvalho Chehab static int af9033_sleep(struct dvb_frontend *fe) 3049a0bf528SMauro Carvalho Chehab { 30509611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 30681e19912SAntti Palosaari struct i2c_client *client = dev->client; 307bc85d5e2SAntti Palosaari int ret; 308bc85d5e2SAntti Palosaari unsigned int utmp; 3099a0bf528SMauro Carvalho Chehab 31081e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 31181e19912SAntti Palosaari 312bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80004c, 0x01); 313bc85d5e2SAntti Palosaari if (ret) 3149a0bf528SMauro Carvalho Chehab goto err; 315bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800000, 0x00); 316bc85d5e2SAntti Palosaari if (ret) 3179a0bf528SMauro Carvalho Chehab goto err; 318bc85d5e2SAntti Palosaari ret = regmap_read_poll_timeout(dev->regmap, 0x80004c, utmp, utmp == 0, 319bc85d5e2SAntti Palosaari 5000, 1000000); 320bc85d5e2SAntti Palosaari if (ret) 3219a0bf528SMauro Carvalho Chehab goto err; 322bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80fb24, 0x08, 0x08); 323bc85d5e2SAntti Palosaari if (ret) 3249a0bf528SMauro Carvalho Chehab goto err; 3259a0bf528SMauro Carvalho Chehab 32681e19912SAntti Palosaari /* Prevent current leak by setting TS interface to parallel mode */ 32709611caaSAntti Palosaari if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { 32881e19912SAntti Palosaari /* Enable parallel TS */ 329bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d917, 0x01, 0x00); 330bc85d5e2SAntti Palosaari if (ret) 3319a0bf528SMauro Carvalho Chehab goto err; 332bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00d916, 0x01, 0x01); 333bc85d5e2SAntti Palosaari if (ret) 3349a0bf528SMauro Carvalho Chehab goto err; 3359a0bf528SMauro Carvalho Chehab } 3369a0bf528SMauro Carvalho Chehab 3379a0bf528SMauro Carvalho Chehab return 0; 3389a0bf528SMauro Carvalho Chehab err: 33981e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 3409a0bf528SMauro Carvalho Chehab return ret; 3419a0bf528SMauro Carvalho Chehab } 3429a0bf528SMauro Carvalho Chehab 3439a0bf528SMauro Carvalho Chehab static int af9033_get_tune_settings(struct dvb_frontend *fe, 3449a0bf528SMauro Carvalho Chehab struct dvb_frontend_tune_settings *fesettings) 3459a0bf528SMauro Carvalho Chehab { 346fe8eece1SAntti Palosaari /* 800 => 2000 because IT9135 v2 is slow to gain lock */ 347fe8eece1SAntti Palosaari fesettings->min_delay_ms = 2000; 3489a0bf528SMauro Carvalho Chehab fesettings->step_size = 0; 3499a0bf528SMauro Carvalho Chehab fesettings->max_drift = 0; 3509a0bf528SMauro Carvalho Chehab 3519a0bf528SMauro Carvalho Chehab return 0; 3529a0bf528SMauro Carvalho Chehab } 3539a0bf528SMauro Carvalho Chehab 3549a0bf528SMauro Carvalho Chehab static int af9033_set_frontend(struct dvb_frontend *fe) 3559a0bf528SMauro Carvalho Chehab { 35609611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 35781e19912SAntti Palosaari struct i2c_client *client = dev->client; 3589a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 359c2feb9ffSAntti Palosaari int ret, i; 360c2feb9ffSAntti Palosaari unsigned int utmp, adc_freq; 3619a0bf528SMauro Carvalho Chehab u8 tmp, buf[3], bandwidth_reg_val; 362c2feb9ffSAntti Palosaari u32 if_frequency; 3639a0bf528SMauro Carvalho Chehab 36481e19912SAntti Palosaari dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u\n", 3656a087f1fSAntti Palosaari c->frequency, c->bandwidth_hz); 3669a0bf528SMauro Carvalho Chehab 36781e19912SAntti Palosaari /* Check bandwidth */ 3689a0bf528SMauro Carvalho Chehab switch (c->bandwidth_hz) { 3699a0bf528SMauro Carvalho Chehab case 6000000: 3709a0bf528SMauro Carvalho Chehab bandwidth_reg_val = 0x00; 3719a0bf528SMauro Carvalho Chehab break; 3729a0bf528SMauro Carvalho Chehab case 7000000: 3739a0bf528SMauro Carvalho Chehab bandwidth_reg_val = 0x01; 3749a0bf528SMauro Carvalho Chehab break; 3759a0bf528SMauro Carvalho Chehab case 8000000: 3769a0bf528SMauro Carvalho Chehab bandwidth_reg_val = 0x02; 3779a0bf528SMauro Carvalho Chehab break; 3789a0bf528SMauro Carvalho Chehab default: 37981e19912SAntti Palosaari dev_dbg(&client->dev, "invalid bandwidth_hz\n"); 3809a0bf528SMauro Carvalho Chehab ret = -EINVAL; 3819a0bf528SMauro Carvalho Chehab goto err; 3829a0bf528SMauro Carvalho Chehab } 3839a0bf528SMauro Carvalho Chehab 38481e19912SAntti Palosaari /* Program tuner */ 3859a0bf528SMauro Carvalho Chehab if (fe->ops.tuner_ops.set_params) 3869a0bf528SMauro Carvalho Chehab fe->ops.tuner_ops.set_params(fe); 3879a0bf528SMauro Carvalho Chehab 38881e19912SAntti Palosaari /* Coefficients */ 38909611caaSAntti Palosaari if (c->bandwidth_hz != dev->bandwidth_hz) { 3909a0bf528SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { 39109611caaSAntti Palosaari if (coeff_lut[i].clock == dev->cfg.clock && 3929a0bf528SMauro Carvalho Chehab coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { 3939a0bf528SMauro Carvalho Chehab break; 3949a0bf528SMauro Carvalho Chehab } 3959a0bf528SMauro Carvalho Chehab } 396060f79d5SMauro Carvalho Chehab if (i == ARRAY_SIZE(coeff_lut)) { 39781e19912SAntti Palosaari dev_err(&client->dev, 39881e19912SAntti Palosaari "Couldn't find config for clock %u\n", 399060f79d5SMauro Carvalho Chehab dev->cfg.clock); 400060f79d5SMauro Carvalho Chehab ret = -EINVAL; 401060f79d5SMauro Carvalho Chehab goto err; 402060f79d5SMauro Carvalho Chehab } 403060f79d5SMauro Carvalho Chehab 404bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x800001, coeff_lut[i].val, 405bc85d5e2SAntti Palosaari sizeof(coeff_lut[i].val)); 406bc85d5e2SAntti Palosaari if (ret) 407bc85d5e2SAntti Palosaari goto err; 4089a0bf528SMauro Carvalho Chehab } 4099a0bf528SMauro Carvalho Chehab 41081e19912SAntti Palosaari /* IF frequency control */ 41109611caaSAntti Palosaari if (c->bandwidth_hz != dev->bandwidth_hz) { 4129a0bf528SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { 41309611caaSAntti Palosaari if (clock_adc_lut[i].clock == dev->cfg.clock) 4149a0bf528SMauro Carvalho Chehab break; 4159a0bf528SMauro Carvalho Chehab } 416060f79d5SMauro Carvalho Chehab if (i == ARRAY_SIZE(clock_adc_lut)) { 41781e19912SAntti Palosaari dev_err(&client->dev, 41881e19912SAntti Palosaari "Couldn't find ADC clock for clock %u\n", 419060f79d5SMauro Carvalho Chehab dev->cfg.clock); 420060f79d5SMauro Carvalho Chehab ret = -EINVAL; 421060f79d5SMauro Carvalho Chehab goto err; 422060f79d5SMauro Carvalho Chehab } 4239a0bf528SMauro Carvalho Chehab adc_freq = clock_adc_lut[i].adc; 4249a0bf528SMauro Carvalho Chehab 425c2feb9ffSAntti Palosaari if (dev->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X) 426c2feb9ffSAntti Palosaari adc_freq = 2 * adc_freq; 427c2feb9ffSAntti Palosaari 42881e19912SAntti Palosaari /* Get used IF frequency */ 4299a0bf528SMauro Carvalho Chehab if (fe->ops.tuner_ops.get_if_frequency) 4309a0bf528SMauro Carvalho Chehab fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); 4319a0bf528SMauro Carvalho Chehab else 4329a0bf528SMauro Carvalho Chehab if_frequency = 0; 4339a0bf528SMauro Carvalho Chehab 434c2feb9ffSAntti Palosaari utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x800000, 435c2feb9ffSAntti Palosaari adc_freq); 4369a0bf528SMauro Carvalho Chehab 437c2feb9ffSAntti Palosaari if (!dev->cfg.spec_inv && if_frequency) 438c2feb9ffSAntti Palosaari utmp = 0x800000 - utmp; 439182b967eSHans-Frieder Vogt 440c2feb9ffSAntti Palosaari buf[0] = (utmp >> 0) & 0xff; 441c2feb9ffSAntti Palosaari buf[1] = (utmp >> 8) & 0xff; 442c2feb9ffSAntti Palosaari buf[2] = (utmp >> 16) & 0xff; 443bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x800029, buf, 3); 444bc85d5e2SAntti Palosaari if (ret) 4459a0bf528SMauro Carvalho Chehab goto err; 4469a0bf528SMauro Carvalho Chehab 44781e19912SAntti Palosaari dev_dbg(&client->dev, "if_frequency_cw=%06x\n", utmp); 448c2feb9ffSAntti Palosaari 44909611caaSAntti Palosaari dev->bandwidth_hz = c->bandwidth_hz; 4509a0bf528SMauro Carvalho Chehab } 4519a0bf528SMauro Carvalho Chehab 452bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f904, 0x03, 453bc85d5e2SAntti Palosaari bandwidth_reg_val); 454bc85d5e2SAntti Palosaari if (ret) 4559a0bf528SMauro Carvalho Chehab goto err; 456bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800040, 0x00); 457bc85d5e2SAntti Palosaari if (ret) 4589a0bf528SMauro Carvalho Chehab goto err; 459bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800047, 0x00); 460bc85d5e2SAntti Palosaari if (ret) 4619a0bf528SMauro Carvalho Chehab goto err; 462bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f999, 0x01, 0x00); 463bc85d5e2SAntti Palosaari if (ret) 4649a0bf528SMauro Carvalho Chehab goto err; 4659a0bf528SMauro Carvalho Chehab 4669a0bf528SMauro Carvalho Chehab if (c->frequency <= 230000000) 4679a0bf528SMauro Carvalho Chehab tmp = 0x00; /* VHF */ 4689a0bf528SMauro Carvalho Chehab else 4699a0bf528SMauro Carvalho Chehab tmp = 0x01; /* UHF */ 4709a0bf528SMauro Carvalho Chehab 471bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80004b, tmp); 472bc85d5e2SAntti Palosaari if (ret) 4739a0bf528SMauro Carvalho Chehab goto err; 47481e19912SAntti Palosaari /* Reset FSM */ 475bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800000, 0x00); 476bc85d5e2SAntti Palosaari if (ret) 4779a0bf528SMauro Carvalho Chehab goto err; 4789a0bf528SMauro Carvalho Chehab 4799a0bf528SMauro Carvalho Chehab return 0; 4809a0bf528SMauro Carvalho Chehab err: 48181e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 4829a0bf528SMauro Carvalho Chehab return ret; 4839a0bf528SMauro Carvalho Chehab } 4849a0bf528SMauro Carvalho Chehab 4857e3e68bcSMauro Carvalho Chehab static int af9033_get_frontend(struct dvb_frontend *fe, 4867e3e68bcSMauro Carvalho Chehab struct dtv_frontend_properties *c) 4879a0bf528SMauro Carvalho Chehab { 48809611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 48981e19912SAntti Palosaari struct i2c_client *client = dev->client; 4909a0bf528SMauro Carvalho Chehab int ret; 4919a0bf528SMauro Carvalho Chehab u8 buf[8]; 4929a0bf528SMauro Carvalho Chehab 49381e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 4949a0bf528SMauro Carvalho Chehab 49581e19912SAntti Palosaari /* Read all needed TPS registers */ 496bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x80f900, buf, 8); 497bc85d5e2SAntti Palosaari if (ret) 4989a0bf528SMauro Carvalho Chehab goto err; 4999a0bf528SMauro Carvalho Chehab 5009a0bf528SMauro Carvalho Chehab switch ((buf[0] >> 0) & 3) { 5019a0bf528SMauro Carvalho Chehab case 0: 5029a0bf528SMauro Carvalho Chehab c->transmission_mode = TRANSMISSION_MODE_2K; 5039a0bf528SMauro Carvalho Chehab break; 5049a0bf528SMauro Carvalho Chehab case 1: 5059a0bf528SMauro Carvalho Chehab c->transmission_mode = TRANSMISSION_MODE_8K; 5069a0bf528SMauro Carvalho Chehab break; 5079a0bf528SMauro Carvalho Chehab } 5089a0bf528SMauro Carvalho Chehab 5099a0bf528SMauro Carvalho Chehab switch ((buf[1] >> 0) & 3) { 5109a0bf528SMauro Carvalho Chehab case 0: 5119a0bf528SMauro Carvalho Chehab c->guard_interval = GUARD_INTERVAL_1_32; 5129a0bf528SMauro Carvalho Chehab break; 5139a0bf528SMauro Carvalho Chehab case 1: 5149a0bf528SMauro Carvalho Chehab c->guard_interval = GUARD_INTERVAL_1_16; 5159a0bf528SMauro Carvalho Chehab break; 5169a0bf528SMauro Carvalho Chehab case 2: 5179a0bf528SMauro Carvalho Chehab c->guard_interval = GUARD_INTERVAL_1_8; 5189a0bf528SMauro Carvalho Chehab break; 5199a0bf528SMauro Carvalho Chehab case 3: 5209a0bf528SMauro Carvalho Chehab c->guard_interval = GUARD_INTERVAL_1_4; 5219a0bf528SMauro Carvalho Chehab break; 5229a0bf528SMauro Carvalho Chehab } 5239a0bf528SMauro Carvalho Chehab 5249a0bf528SMauro Carvalho Chehab switch ((buf[2] >> 0) & 7) { 5259a0bf528SMauro Carvalho Chehab case 0: 5269a0bf528SMauro Carvalho Chehab c->hierarchy = HIERARCHY_NONE; 5279a0bf528SMauro Carvalho Chehab break; 5289a0bf528SMauro Carvalho Chehab case 1: 5299a0bf528SMauro Carvalho Chehab c->hierarchy = HIERARCHY_1; 5309a0bf528SMauro Carvalho Chehab break; 5319a0bf528SMauro Carvalho Chehab case 2: 5329a0bf528SMauro Carvalho Chehab c->hierarchy = HIERARCHY_2; 5339a0bf528SMauro Carvalho Chehab break; 5349a0bf528SMauro Carvalho Chehab case 3: 5359a0bf528SMauro Carvalho Chehab c->hierarchy = HIERARCHY_4; 5369a0bf528SMauro Carvalho Chehab break; 5379a0bf528SMauro Carvalho Chehab } 5389a0bf528SMauro Carvalho Chehab 5399a0bf528SMauro Carvalho Chehab switch ((buf[3] >> 0) & 3) { 5409a0bf528SMauro Carvalho Chehab case 0: 5419a0bf528SMauro Carvalho Chehab c->modulation = QPSK; 5429a0bf528SMauro Carvalho Chehab break; 5439a0bf528SMauro Carvalho Chehab case 1: 5449a0bf528SMauro Carvalho Chehab c->modulation = QAM_16; 5459a0bf528SMauro Carvalho Chehab break; 5469a0bf528SMauro Carvalho Chehab case 2: 5479a0bf528SMauro Carvalho Chehab c->modulation = QAM_64; 5489a0bf528SMauro Carvalho Chehab break; 5499a0bf528SMauro Carvalho Chehab } 5509a0bf528SMauro Carvalho Chehab 5519a0bf528SMauro Carvalho Chehab switch ((buf[4] >> 0) & 3) { 5529a0bf528SMauro Carvalho Chehab case 0: 5539a0bf528SMauro Carvalho Chehab c->bandwidth_hz = 6000000; 5549a0bf528SMauro Carvalho Chehab break; 5559a0bf528SMauro Carvalho Chehab case 1: 5569a0bf528SMauro Carvalho Chehab c->bandwidth_hz = 7000000; 5579a0bf528SMauro Carvalho Chehab break; 5589a0bf528SMauro Carvalho Chehab case 2: 5599a0bf528SMauro Carvalho Chehab c->bandwidth_hz = 8000000; 5609a0bf528SMauro Carvalho Chehab break; 5619a0bf528SMauro Carvalho Chehab } 5629a0bf528SMauro Carvalho Chehab 5639a0bf528SMauro Carvalho Chehab switch ((buf[6] >> 0) & 7) { 5649a0bf528SMauro Carvalho Chehab case 0: 5659a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_1_2; 5669a0bf528SMauro Carvalho Chehab break; 5679a0bf528SMauro Carvalho Chehab case 1: 5689a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_2_3; 5699a0bf528SMauro Carvalho Chehab break; 5709a0bf528SMauro Carvalho Chehab case 2: 5719a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_3_4; 5729a0bf528SMauro Carvalho Chehab break; 5739a0bf528SMauro Carvalho Chehab case 3: 5749a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_5_6; 5759a0bf528SMauro Carvalho Chehab break; 5769a0bf528SMauro Carvalho Chehab case 4: 5779a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_7_8; 5789a0bf528SMauro Carvalho Chehab break; 5799a0bf528SMauro Carvalho Chehab case 5: 5809a0bf528SMauro Carvalho Chehab c->code_rate_HP = FEC_NONE; 5819a0bf528SMauro Carvalho Chehab break; 5829a0bf528SMauro Carvalho Chehab } 5839a0bf528SMauro Carvalho Chehab 5849a0bf528SMauro Carvalho Chehab switch ((buf[7] >> 0) & 7) { 5859a0bf528SMauro Carvalho Chehab case 0: 5869a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_1_2; 5879a0bf528SMauro Carvalho Chehab break; 5889a0bf528SMauro Carvalho Chehab case 1: 5899a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_2_3; 5909a0bf528SMauro Carvalho Chehab break; 5919a0bf528SMauro Carvalho Chehab case 2: 5929a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_3_4; 5939a0bf528SMauro Carvalho Chehab break; 5949a0bf528SMauro Carvalho Chehab case 3: 5959a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_5_6; 5969a0bf528SMauro Carvalho Chehab break; 5979a0bf528SMauro Carvalho Chehab case 4: 5989a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_7_8; 5999a0bf528SMauro Carvalho Chehab break; 6009a0bf528SMauro Carvalho Chehab case 5: 6019a0bf528SMauro Carvalho Chehab c->code_rate_LP = FEC_NONE; 6029a0bf528SMauro Carvalho Chehab break; 6039a0bf528SMauro Carvalho Chehab } 6049a0bf528SMauro Carvalho Chehab 6059a0bf528SMauro Carvalho Chehab return 0; 6069a0bf528SMauro Carvalho Chehab err: 60781e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 6089a0bf528SMauro Carvalho Chehab return ret; 6099a0bf528SMauro Carvalho Chehab } 6109a0bf528SMauro Carvalho Chehab 6110df289a2SMauro Carvalho Chehab static int af9033_read_status(struct dvb_frontend *fe, enum fe_status *status) 6129a0bf528SMauro Carvalho Chehab { 61309611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 61481e19912SAntti Palosaari struct i2c_client *client = dev->client; 615659a0999SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 616239dd616SAntti Palosaari int ret, tmp = 0; 617bc85d5e2SAntti Palosaari u8 buf[7]; 618239dd616SAntti Palosaari unsigned int utmp, utmp1; 619659a0999SAntti Palosaari 62081e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 6219a0bf528SMauro Carvalho Chehab 6229a0bf528SMauro Carvalho Chehab *status = 0; 6239a0bf528SMauro Carvalho Chehab 62481e19912SAntti Palosaari /* Radio channel status: 0=no result, 1=has signal, 2=no signal */ 625bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x800047, &utmp); 626bc85d5e2SAntti Palosaari if (ret) 6279a0bf528SMauro Carvalho Chehab goto err; 6289a0bf528SMauro Carvalho Chehab 62981e19912SAntti Palosaari /* Has signal */ 630bc85d5e2SAntti Palosaari if (utmp == 0x01) 6319a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SIGNAL; 6329a0bf528SMauro Carvalho Chehab 633bc85d5e2SAntti Palosaari if (utmp != 0x02) { 6349a0bf528SMauro Carvalho Chehab /* TPS lock */ 635bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f5a9, &utmp); 636bc85d5e2SAntti Palosaari if (ret) 6379a0bf528SMauro Carvalho Chehab goto err; 6389a0bf528SMauro Carvalho Chehab 639bc85d5e2SAntti Palosaari if ((utmp >> 0) & 0x01) 6409a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 6419a0bf528SMauro Carvalho Chehab FE_HAS_VITERBI; 6429a0bf528SMauro Carvalho Chehab 64381e19912SAntti Palosaari /* Full lock */ 644bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f999, &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 | FE_HAS_SYNC | 6519a0bf528SMauro Carvalho Chehab FE_HAS_LOCK; 6529a0bf528SMauro Carvalho Chehab } 6539a0bf528SMauro Carvalho Chehab 65483f11619SAntti Palosaari dev->fe_status = *status; 65583f11619SAntti Palosaari 65681e19912SAntti Palosaari /* Signal strength */ 657659a0999SAntti Palosaari if (dev->fe_status & FE_HAS_SIGNAL) { 658659a0999SAntti Palosaari if (dev->is_af9035) { 659bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80004a, &utmp); 660659a0999SAntti Palosaari if (ret) 661659a0999SAntti Palosaari goto err; 662bc85d5e2SAntti Palosaari tmp = -utmp * 1000; 663659a0999SAntti Palosaari } else { 664bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x8000f7, &utmp); 665659a0999SAntti Palosaari if (ret) 666659a0999SAntti Palosaari goto err; 667bc85d5e2SAntti Palosaari tmp = (utmp - 100) * 1000; 668659a0999SAntti Palosaari } 669659a0999SAntti Palosaari 670659a0999SAntti Palosaari c->strength.len = 1; 671659a0999SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_DECIBEL; 672659a0999SAntti Palosaari c->strength.stat[0].svalue = tmp; 673659a0999SAntti Palosaari } else { 674659a0999SAntti Palosaari c->strength.len = 1; 675659a0999SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 676659a0999SAntti Palosaari } 677659a0999SAntti Palosaari 678659a0999SAntti Palosaari /* CNR */ 679659a0999SAntti Palosaari if (dev->fe_status & FE_HAS_VITERBI) { 68081e19912SAntti Palosaari /* Read raw SNR value */ 681bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x80002c, buf, 3); 682659a0999SAntti Palosaari if (ret) 683659a0999SAntti Palosaari goto err; 684659a0999SAntti Palosaari 685239dd616SAntti Palosaari utmp1 = buf[2] << 16 | buf[1] << 8 | buf[0] << 0; 686659a0999SAntti Palosaari 68781e19912SAntti Palosaari /* Read superframe number */ 688bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f78b, &utmp); 689659a0999SAntti Palosaari if (ret) 690659a0999SAntti Palosaari goto err; 691659a0999SAntti Palosaari 692bc85d5e2SAntti Palosaari if (utmp) 693239dd616SAntti Palosaari utmp1 /= utmp; 694659a0999SAntti Palosaari 69581e19912SAntti Palosaari /* Read current transmission mode */ 696bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f900, &utmp); 697659a0999SAntti Palosaari if (ret) 698659a0999SAntti Palosaari goto err; 699659a0999SAntti Palosaari 700bc85d5e2SAntti Palosaari switch ((utmp >> 0) & 3) { 701659a0999SAntti Palosaari case 0: 702239dd616SAntti Palosaari /* 2k */ 703239dd616SAntti Palosaari utmp1 *= 4; 704659a0999SAntti Palosaari break; 705659a0999SAntti Palosaari case 1: 706239dd616SAntti Palosaari /* 8k */ 707239dd616SAntti Palosaari utmp1 *= 1; 708659a0999SAntti Palosaari break; 709659a0999SAntti Palosaari case 2: 710239dd616SAntti Palosaari /* 4k */ 711239dd616SAntti Palosaari utmp1 *= 2; 712659a0999SAntti Palosaari break; 713659a0999SAntti Palosaari default: 714239dd616SAntti Palosaari utmp1 *= 0; 715659a0999SAntti Palosaari break; 716659a0999SAntti Palosaari } 717659a0999SAntti Palosaari 71881e19912SAntti Palosaari /* Read current modulation */ 719bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f903, &utmp); 720659a0999SAntti Palosaari if (ret) 721659a0999SAntti Palosaari goto err; 722659a0999SAntti Palosaari 723bc85d5e2SAntti Palosaari switch ((utmp >> 0) & 3) { 724659a0999SAntti Palosaari case 0: 725239dd616SAntti Palosaari /* 726239dd616SAntti Palosaari * QPSK 727239dd616SAntti Palosaari * CNR[dB] 13 * -log10((1690000 - value) / value) + 2.6 728239dd616SAntti Palosaari * value [653799, 1689999], 2.6 / 13 = 3355443 729239dd616SAntti Palosaari */ 730239dd616SAntti Palosaari utmp1 = clamp(utmp1, 653799U, 1689999U); 731239dd616SAntti Palosaari utmp1 = ((u64)(intlog10(utmp1) 732239dd616SAntti Palosaari - intlog10(1690000 - utmp1) 733239dd616SAntti Palosaari + 3355443) * 13 * 1000) >> 24; 734659a0999SAntti Palosaari break; 735659a0999SAntti Palosaari case 1: 736239dd616SAntti Palosaari /* 737239dd616SAntti Palosaari * QAM-16 738239dd616SAntti Palosaari * CNR[dB] 6 * log10((value - 370000) / (828000 - value)) + 15.7 739239dd616SAntti Palosaari * value [371105, 827999], 15.7 / 6 = 43900382 740239dd616SAntti Palosaari */ 741239dd616SAntti Palosaari utmp1 = clamp(utmp1, 371105U, 827999U); 742239dd616SAntti Palosaari utmp1 = ((u64)(intlog10(utmp1 - 370000) 743239dd616SAntti Palosaari - intlog10(828000 - utmp1) 744239dd616SAntti Palosaari + 43900382) * 6 * 1000) >> 24; 745659a0999SAntti Palosaari break; 746659a0999SAntti Palosaari case 2: 747239dd616SAntti Palosaari /* 748239dd616SAntti Palosaari * QAM-64 749239dd616SAntti Palosaari * CNR[dB] 8 * log10((value - 193000) / (425000 - value)) + 23.8 750239dd616SAntti Palosaari * value [193246, 424999], 23.8 / 8 = 49912218 751239dd616SAntti Palosaari */ 752239dd616SAntti Palosaari utmp1 = clamp(utmp1, 193246U, 424999U); 753239dd616SAntti Palosaari utmp1 = ((u64)(intlog10(utmp1 - 193000) 754239dd616SAntti Palosaari - intlog10(425000 - utmp1) 755239dd616SAntti Palosaari + 49912218) * 8 * 1000) >> 24; 756659a0999SAntti Palosaari break; 757659a0999SAntti Palosaari default: 758239dd616SAntti Palosaari utmp1 = 0; 759659a0999SAntti Palosaari break; 760659a0999SAntti Palosaari } 761659a0999SAntti Palosaari 762239dd616SAntti Palosaari dev_dbg(&client->dev, "cnr=%u\n", utmp1); 763659a0999SAntti Palosaari 764659a0999SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 765239dd616SAntti Palosaari c->cnr.stat[0].svalue = utmp1; 766659a0999SAntti Palosaari } else { 767659a0999SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 768659a0999SAntti Palosaari } 769659a0999SAntti Palosaari 770659a0999SAntti Palosaari /* UCB/PER/BER */ 771659a0999SAntti Palosaari if (dev->fe_status & FE_HAS_LOCK) { 77281e19912SAntti Palosaari /* Outer FEC, 204 byte packets */ 773659a0999SAntti Palosaari u16 abort_packet_count, rsd_packet_count; 77481e19912SAntti Palosaari /* Inner FEC, bits */ 775659a0999SAntti Palosaari u32 rsd_bit_err_count; 776659a0999SAntti Palosaari 777659a0999SAntti Palosaari /* 778659a0999SAntti Palosaari * Packet count used for measurement is 10000 779659a0999SAntti Palosaari * (rsd_packet_count). Maybe it should be increased? 780659a0999SAntti Palosaari */ 781659a0999SAntti Palosaari 782bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x800032, buf, 7); 783659a0999SAntti Palosaari if (ret) 784659a0999SAntti Palosaari goto err; 785659a0999SAntti Palosaari 786659a0999SAntti Palosaari abort_packet_count = (buf[1] << 8) | (buf[0] << 0); 787659a0999SAntti Palosaari rsd_bit_err_count = (buf[4] << 16) | (buf[3] << 8) | buf[2]; 788659a0999SAntti Palosaari rsd_packet_count = (buf[6] << 8) | (buf[5] << 0); 789659a0999SAntti Palosaari 790659a0999SAntti Palosaari dev->error_block_count += abort_packet_count; 791659a0999SAntti Palosaari dev->total_block_count += rsd_packet_count; 792659a0999SAntti Palosaari dev->post_bit_error += rsd_bit_err_count; 793659a0999SAntti Palosaari dev->post_bit_count += rsd_packet_count * 204 * 8; 794659a0999SAntti Palosaari 795659a0999SAntti Palosaari c->block_count.len = 1; 796659a0999SAntti Palosaari c->block_count.stat[0].scale = FE_SCALE_COUNTER; 797659a0999SAntti Palosaari c->block_count.stat[0].uvalue = dev->total_block_count; 798659a0999SAntti Palosaari 799659a0999SAntti Palosaari c->block_error.len = 1; 800659a0999SAntti Palosaari c->block_error.stat[0].scale = FE_SCALE_COUNTER; 801659a0999SAntti Palosaari c->block_error.stat[0].uvalue = dev->error_block_count; 802659a0999SAntti Palosaari 803659a0999SAntti Palosaari c->post_bit_count.len = 1; 804659a0999SAntti Palosaari c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 805659a0999SAntti Palosaari c->post_bit_count.stat[0].uvalue = dev->post_bit_count; 806659a0999SAntti Palosaari 807659a0999SAntti Palosaari c->post_bit_error.len = 1; 808659a0999SAntti Palosaari c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 809659a0999SAntti Palosaari c->post_bit_error.stat[0].uvalue = dev->post_bit_error; 810659a0999SAntti Palosaari } 811659a0999SAntti Palosaari 8129a0bf528SMauro Carvalho Chehab return 0; 8139a0bf528SMauro Carvalho Chehab err: 81481e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 8159a0bf528SMauro Carvalho Chehab return ret; 8169a0bf528SMauro Carvalho Chehab } 8179a0bf528SMauro Carvalho Chehab 8189a0bf528SMauro Carvalho Chehab static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) 8199a0bf528SMauro Carvalho Chehab { 82009611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 82181e19912SAntti Palosaari struct i2c_client *client = dev->client; 8226b457786SAntti Palosaari struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; 8236d03f6a8SBimow Chen int ret; 824bc85d5e2SAntti Palosaari unsigned int utmp; 8259a0bf528SMauro Carvalho Chehab 82681e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 82781e19912SAntti Palosaari 82881e19912SAntti Palosaari /* Use DVBv5 CNR */ 8296d03f6a8SBimow Chen if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) { 830c3a80cd0SAntti Palosaari /* Return 0.1 dB for AF9030 and 0-0xffff for IT9130. */ 831c3a80cd0SAntti Palosaari if (dev->is_af9035) { 832c3a80cd0SAntti Palosaari /* 1000x => 10x (0.1 dB) */ 833c3a80cd0SAntti Palosaari *snr = div_s64(c->cnr.stat[0].svalue, 100); 834c3a80cd0SAntti Palosaari } else { 835c3a80cd0SAntti Palosaari /* 1000x => 1x (1 dB) */ 8366d03f6a8SBimow Chen *snr = div_s64(c->cnr.stat[0].svalue, 1000); 8376d03f6a8SBimow Chen 83881e19912SAntti Palosaari /* Read current modulation */ 839bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x80f903, &utmp); 8406d03f6a8SBimow Chen if (ret) 8416d03f6a8SBimow Chen goto err; 8426d03f6a8SBimow Chen 8436d03f6a8SBimow Chen /* scale value to 0x0000-0xffff */ 844bc85d5e2SAntti Palosaari switch ((utmp >> 0) & 3) { 8456d03f6a8SBimow Chen case 0: 846c3a80cd0SAntti Palosaari *snr = *snr * 0xffff / 23; 8476d03f6a8SBimow Chen break; 8486d03f6a8SBimow Chen case 1: 849c3a80cd0SAntti Palosaari *snr = *snr * 0xffff / 26; 8506d03f6a8SBimow Chen break; 8516d03f6a8SBimow Chen case 2: 852c3a80cd0SAntti Palosaari *snr = *snr * 0xffff / 32; 8536d03f6a8SBimow Chen break; 8546d03f6a8SBimow Chen default: 8556d03f6a8SBimow Chen goto err; 8566d03f6a8SBimow Chen } 857c3a80cd0SAntti Palosaari } 8586d03f6a8SBimow Chen } else { 8596b457786SAntti Palosaari *snr = 0; 8606d03f6a8SBimow Chen } 8619a0bf528SMauro Carvalho Chehab 8629a0bf528SMauro Carvalho Chehab return 0; 8636d03f6a8SBimow Chen err: 86481e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 8656d03f6a8SBimow Chen return ret; 8669a0bf528SMauro Carvalho Chehab } 8679a0bf528SMauro Carvalho Chehab 8689a0bf528SMauro Carvalho Chehab static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 8699a0bf528SMauro Carvalho Chehab { 87009611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 87181e19912SAntti Palosaari struct i2c_client *client = dev->client; 8723adec272SBimow Chen struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; 8733adec272SBimow Chen int ret, tmp, power_real; 874bc85d5e2SAntti Palosaari unsigned int utmp; 875bc85d5e2SAntti Palosaari u8 gain_offset, buf[7]; 8769a0bf528SMauro Carvalho Chehab 87781e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 87881e19912SAntti Palosaari 8793adec272SBimow Chen if (dev->is_af9035) { 88081e19912SAntti Palosaari /* Read signal strength of 0-100 scale */ 881bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x800048, &utmp); 882bc85d5e2SAntti Palosaari if (ret) 8830b0d9628SAntti Palosaari goto err; 8840b0d9628SAntti Palosaari 88581e19912SAntti Palosaari /* Scale value to 0x0000-0xffff */ 886bc85d5e2SAntti Palosaari *strength = utmp * 0xffff / 100; 8873adec272SBimow Chen } else { 888bc85d5e2SAntti Palosaari ret = regmap_read(dev->regmap, 0x8000f7, &utmp); 889bc85d5e2SAntti Palosaari if (ret) 8901620d221SAntti Palosaari goto err; 8911620d221SAntti Palosaari 892bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x80f900, buf, 7); 893bc85d5e2SAntti Palosaari if (ret) 8941620d221SAntti Palosaari goto err; 8953adec272SBimow Chen 8963adec272SBimow Chen if (c->frequency <= 300000000) 8973adec272SBimow Chen gain_offset = 7; /* VHF */ 8983adec272SBimow Chen else 8993adec272SBimow Chen gain_offset = 4; /* UHF */ 9003adec272SBimow Chen 901bc85d5e2SAntti Palosaari power_real = (utmp - 100 - gain_offset) - 9023adec272SBimow Chen power_reference[((buf[3] >> 0) & 3)][((buf[6] >> 0) & 7)]; 9033adec272SBimow Chen 9043adec272SBimow Chen if (power_real < -15) 9053adec272SBimow Chen tmp = 0; 9063adec272SBimow Chen else if ((power_real >= -15) && (power_real < 0)) 9073adec272SBimow Chen tmp = (2 * (power_real + 15)) / 3; 9083adec272SBimow Chen else if ((power_real >= 0) && (power_real < 20)) 9093adec272SBimow Chen tmp = 4 * power_real + 10; 9103adec272SBimow Chen else if ((power_real >= 20) && (power_real < 35)) 9113adec272SBimow Chen tmp = (2 * (power_real - 20)) / 3 + 90; 9123adec272SBimow Chen else 9133adec272SBimow Chen tmp = 100; 9149a0bf528SMauro Carvalho Chehab 91581e19912SAntti Palosaari /* Scale value to 0x0000-0xffff */ 9163adec272SBimow Chen *strength = tmp * 0xffff / 100; 9173adec272SBimow Chen } 9183adec272SBimow Chen 9199a0bf528SMauro Carvalho Chehab return 0; 9209a0bf528SMauro Carvalho Chehab err: 92181e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 9229a0bf528SMauro Carvalho Chehab return ret; 9239a0bf528SMauro Carvalho Chehab } 9249a0bf528SMauro Carvalho Chehab 9259a0bf528SMauro Carvalho Chehab static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) 9269a0bf528SMauro Carvalho Chehab { 92709611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 9289a0bf528SMauro Carvalho Chehab 929e53c4744SAntti Palosaari *ber = (dev->post_bit_error - dev->post_bit_error_prev); 930e53c4744SAntti Palosaari dev->post_bit_error_prev = dev->post_bit_error; 9319a0bf528SMauro Carvalho Chehab 9329a0bf528SMauro Carvalho Chehab return 0; 9339a0bf528SMauro Carvalho Chehab } 9349a0bf528SMauro Carvalho Chehab 9359a0bf528SMauro Carvalho Chehab static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 9369a0bf528SMauro Carvalho Chehab { 93709611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 9389a0bf528SMauro Carvalho Chehab 9391d0ceae4SAntti Palosaari *ucblocks = dev->error_block_count; 94081e19912SAntti Palosaari 9419a0bf528SMauro Carvalho Chehab return 0; 9429a0bf528SMauro Carvalho Chehab } 9439a0bf528SMauro Carvalho Chehab 9449a0bf528SMauro Carvalho Chehab static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 9459a0bf528SMauro Carvalho Chehab { 94609611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 94781e19912SAntti Palosaari struct i2c_client *client = dev->client; 9489a0bf528SMauro Carvalho Chehab int ret; 9499a0bf528SMauro Carvalho Chehab 95081e19912SAntti Palosaari dev_dbg(&client->dev, "enable=%d\n", enable); 9519a0bf528SMauro Carvalho Chehab 952bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x00fa04, 0x01, enable); 953bc85d5e2SAntti Palosaari if (ret) 9549a0bf528SMauro Carvalho Chehab goto err; 9559a0bf528SMauro Carvalho Chehab 9569a0bf528SMauro Carvalho Chehab return 0; 9579a0bf528SMauro Carvalho Chehab err: 95881e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 9599a0bf528SMauro Carvalho Chehab return ret; 9609a0bf528SMauro Carvalho Chehab } 9619a0bf528SMauro Carvalho Chehab 962ed97a6feSMauro Carvalho Chehab static int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) 963040cf86cSAntti Palosaari { 96409611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 96581e19912SAntti Palosaari struct i2c_client *client = dev->client; 966040cf86cSAntti Palosaari int ret; 967040cf86cSAntti Palosaari 96881e19912SAntti Palosaari dev_dbg(&client->dev, "onoff=%d\n", onoff); 969040cf86cSAntti Palosaari 970bc85d5e2SAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x80f993, 0x01, onoff); 971bc85d5e2SAntti Palosaari if (ret) 972040cf86cSAntti Palosaari goto err; 973040cf86cSAntti Palosaari 974040cf86cSAntti Palosaari return 0; 975040cf86cSAntti Palosaari err: 97681e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 977040cf86cSAntti Palosaari return ret; 978040cf86cSAntti Palosaari } 979040cf86cSAntti Palosaari 98024e419a0SAntti Palosaari static int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid, 98124e419a0SAntti Palosaari int onoff) 982040cf86cSAntti Palosaari { 98309611caaSAntti Palosaari struct af9033_dev *dev = fe->demodulator_priv; 98481e19912SAntti Palosaari struct i2c_client *client = dev->client; 985040cf86cSAntti Palosaari int ret; 986040cf86cSAntti Palosaari u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff}; 987040cf86cSAntti Palosaari 98881e19912SAntti Palosaari dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n", 9896a087f1fSAntti Palosaari index, pid, onoff); 990040cf86cSAntti Palosaari 991040cf86cSAntti Palosaari if (pid > 0x1fff) 992040cf86cSAntti Palosaari return 0; 993040cf86cSAntti Palosaari 994bc85d5e2SAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x80f996, wbuf, 2); 995bc85d5e2SAntti Palosaari if (ret) 996040cf86cSAntti Palosaari goto err; 997bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80f994, onoff); 998bc85d5e2SAntti Palosaari if (ret) 999040cf86cSAntti Palosaari goto err; 1000bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80f995, index); 1001bc85d5e2SAntti Palosaari if (ret) 1002040cf86cSAntti Palosaari goto err; 1003040cf86cSAntti Palosaari 1004040cf86cSAntti Palosaari return 0; 1005040cf86cSAntti Palosaari err: 100681e19912SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 1007040cf86cSAntti Palosaari return ret; 1008040cf86cSAntti Palosaari } 1009040cf86cSAntti Palosaari 1010bd336e63SMax Kellermann static const struct dvb_frontend_ops af9033_ops = { 10119a0bf528SMauro Carvalho Chehab .delsys = {SYS_DVBT}, 10129a0bf528SMauro Carvalho Chehab .info = { 10139a0bf528SMauro Carvalho Chehab .name = "Afatech AF9033 (DVB-T)", 1014f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 174 * MHz, 1015f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 862 * MHz, 1016f1b1eabfSMauro Carvalho Chehab .frequency_stepsize_hz = 250 * kHz, 10179a0bf528SMauro Carvalho Chehab .caps = FE_CAN_FEC_1_2 | 10189a0bf528SMauro Carvalho Chehab FE_CAN_FEC_2_3 | 10199a0bf528SMauro Carvalho Chehab FE_CAN_FEC_3_4 | 10209a0bf528SMauro Carvalho Chehab FE_CAN_FEC_5_6 | 10219a0bf528SMauro Carvalho Chehab FE_CAN_FEC_7_8 | 10229a0bf528SMauro Carvalho Chehab FE_CAN_FEC_AUTO | 10239a0bf528SMauro Carvalho Chehab FE_CAN_QPSK | 10249a0bf528SMauro Carvalho Chehab FE_CAN_QAM_16 | 10259a0bf528SMauro Carvalho Chehab FE_CAN_QAM_64 | 10269a0bf528SMauro Carvalho Chehab FE_CAN_QAM_AUTO | 10279a0bf528SMauro Carvalho Chehab FE_CAN_TRANSMISSION_MODE_AUTO | 10289a0bf528SMauro Carvalho Chehab FE_CAN_GUARD_INTERVAL_AUTO | 10299a0bf528SMauro Carvalho Chehab FE_CAN_HIERARCHY_AUTO | 10309a0bf528SMauro Carvalho Chehab FE_CAN_RECOVER | 10319a0bf528SMauro Carvalho Chehab FE_CAN_MUTE_TS 10329a0bf528SMauro Carvalho Chehab }, 10339a0bf528SMauro Carvalho Chehab 10349a0bf528SMauro Carvalho Chehab .init = af9033_init, 10359a0bf528SMauro Carvalho Chehab .sleep = af9033_sleep, 10369a0bf528SMauro Carvalho Chehab 10379a0bf528SMauro Carvalho Chehab .get_tune_settings = af9033_get_tune_settings, 10389a0bf528SMauro Carvalho Chehab .set_frontend = af9033_set_frontend, 10399a0bf528SMauro Carvalho Chehab .get_frontend = af9033_get_frontend, 10409a0bf528SMauro Carvalho Chehab 10419a0bf528SMauro Carvalho Chehab .read_status = af9033_read_status, 10429a0bf528SMauro Carvalho Chehab .read_snr = af9033_read_snr, 10439a0bf528SMauro Carvalho Chehab .read_signal_strength = af9033_read_signal_strength, 10449a0bf528SMauro Carvalho Chehab .read_ber = af9033_read_ber, 10459a0bf528SMauro Carvalho Chehab .read_ucblocks = af9033_read_ucblocks, 10469a0bf528SMauro Carvalho Chehab 10479a0bf528SMauro Carvalho Chehab .i2c_gate_ctrl = af9033_i2c_gate_ctrl, 10489a0bf528SMauro Carvalho Chehab }; 10499a0bf528SMauro Carvalho Chehab 1050f5b00a76SAntti Palosaari static int af9033_probe(struct i2c_client *client, 1051f5b00a76SAntti Palosaari const struct i2c_device_id *id) 1052f5b00a76SAntti Palosaari { 1053f5b00a76SAntti Palosaari struct af9033_config *cfg = client->dev.platform_data; 1054f5b00a76SAntti Palosaari struct af9033_dev *dev; 1055f5b00a76SAntti Palosaari int ret; 1056f5b00a76SAntti Palosaari u8 buf[8]; 1057f5b00a76SAntti Palosaari u32 reg; 1058bc85d5e2SAntti Palosaari static const struct regmap_config regmap_config = { 1059bc85d5e2SAntti Palosaari .reg_bits = 24, 1060bc85d5e2SAntti Palosaari .val_bits = 8, 1061bc85d5e2SAntti Palosaari }; 1062bc85d5e2SAntti Palosaari 106381e19912SAntti Palosaari /* Allocate memory for the internal state */ 106481e19912SAntti Palosaari dev = kzalloc(sizeof(*dev), GFP_KERNEL); 106581e19912SAntti Palosaari if (!dev) { 1066f5b00a76SAntti Palosaari ret = -ENOMEM; 1067f5b00a76SAntti Palosaari goto err; 1068f5b00a76SAntti Palosaari } 1069f5b00a76SAntti Palosaari 107081e19912SAntti Palosaari /* Setup the state */ 1071f5b00a76SAntti Palosaari dev->client = client; 107281e19912SAntti Palosaari memcpy(&dev->cfg, cfg, sizeof(dev->cfg)); 107381e19912SAntti Palosaari switch (dev->cfg.ts_mode) { 107481e19912SAntti Palosaari case AF9033_TS_MODE_PARALLEL: 107581e19912SAntti Palosaari dev->ts_mode_parallel = true; 107681e19912SAntti Palosaari break; 107781e19912SAntti Palosaari case AF9033_TS_MODE_SERIAL: 107881e19912SAntti Palosaari dev->ts_mode_serial = true; 107981e19912SAntti Palosaari break; 108081e19912SAntti Palosaari case AF9033_TS_MODE_USB: 108181e19912SAntti Palosaari /* USB mode for AF9035 */ 108281e19912SAntti Palosaari default: 108381e19912SAntti Palosaari break; 108481e19912SAntti Palosaari } 1085f5b00a76SAntti Palosaari 1086f5b00a76SAntti Palosaari if (dev->cfg.clock != 12000000) { 1087f5b00a76SAntti Palosaari ret = -ENODEV; 108881e19912SAntti Palosaari dev_err(&client->dev, 108981e19912SAntti Palosaari "Unsupported clock %u Hz. Only 12000000 Hz is supported currently\n", 10906a087f1fSAntti Palosaari dev->cfg.clock); 1091f5b00a76SAntti Palosaari goto err_kfree; 1092f5b00a76SAntti Palosaari } 1093f5b00a76SAntti Palosaari 1094bc85d5e2SAntti Palosaari /* Create regmap */ 1095bc85d5e2SAntti Palosaari dev->regmap = regmap_init_i2c(client, ®map_config); 1096bc85d5e2SAntti Palosaari if (IS_ERR(dev->regmap)) { 1097bc85d5e2SAntti Palosaari ret = PTR_ERR(dev->regmap); 1098bc85d5e2SAntti Palosaari goto err_kfree; 1099bc85d5e2SAntti Palosaari } 1100bc85d5e2SAntti Palosaari 110181e19912SAntti Palosaari /* Firmware version */ 1102f5b00a76SAntti Palosaari switch (dev->cfg.tuner) { 1103f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_38: 1104f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_51: 1105f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_52: 1106f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_60: 1107f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_61: 1108f5b00a76SAntti Palosaari case AF9033_TUNER_IT9135_62: 110983f11619SAntti Palosaari dev->is_it9135 = true; 1110f5b00a76SAntti Palosaari reg = 0x004bfc; 1111f5b00a76SAntti Palosaari break; 1112f5b00a76SAntti Palosaari default: 111383f11619SAntti Palosaari dev->is_af9035 = true; 1114f5b00a76SAntti Palosaari reg = 0x0083e9; 1115f5b00a76SAntti Palosaari break; 1116f5b00a76SAntti Palosaari } 1117f5b00a76SAntti Palosaari 1118bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, reg, &buf[0], 4); 1119bc85d5e2SAntti Palosaari if (ret) 1120bc85d5e2SAntti Palosaari goto err_regmap_exit; 1121bc85d5e2SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x804191, &buf[4], 4); 1122bc85d5e2SAntti Palosaari if (ret) 1123bc85d5e2SAntti Palosaari goto err_regmap_exit; 1124f5b00a76SAntti Palosaari 112581e19912SAntti Palosaari dev_info(&client->dev, 11266a087f1fSAntti Palosaari "firmware version: LINK %d.%d.%d.%d - OFDM %d.%d.%d.%d\n", 112781e19912SAntti Palosaari buf[0], buf[1], buf[2], buf[3], 112881e19912SAntti Palosaari buf[4], buf[5], buf[6], buf[7]); 1129f5b00a76SAntti Palosaari 113081e19912SAntti Palosaari /* Sleep as chip seems to be partly active by default */ 1131f5b00a76SAntti Palosaari /* IT9135 did not like to sleep at that early */ 113209a446d2SVictor Toso if (dev->is_af9035) { 1133bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x80004c, 0x01); 1134bc85d5e2SAntti Palosaari if (ret) 1135bc85d5e2SAntti Palosaari goto err_regmap_exit; 1136bc85d5e2SAntti Palosaari ret = regmap_write(dev->regmap, 0x800000, 0x00); 1137bc85d5e2SAntti Palosaari if (ret) 1138bc85d5e2SAntti Palosaari goto err_regmap_exit; 1139f5b00a76SAntti Palosaari } 1140f5b00a76SAntti Palosaari 114181e19912SAntti Palosaari /* Create dvb frontend */ 114281e19912SAntti Palosaari memcpy(&dev->fe.ops, &af9033_ops, sizeof(dev->fe.ops)); 1143f5b00a76SAntti Palosaari dev->fe.demodulator_priv = dev; 1144f5b00a76SAntti Palosaari *cfg->fe = &dev->fe; 1145f5b00a76SAntti Palosaari if (cfg->ops) { 1146f5b00a76SAntti Palosaari cfg->ops->pid_filter = af9033_pid_filter; 1147f5b00a76SAntti Palosaari cfg->ops->pid_filter_ctrl = af9033_pid_filter_ctrl; 1148f5b00a76SAntti Palosaari } 11493461831aSAntti Palosaari cfg->regmap = dev->regmap; 1150f5b00a76SAntti Palosaari i2c_set_clientdata(client, dev); 1151f5b00a76SAntti Palosaari 115281e19912SAntti Palosaari dev_info(&client->dev, "Afatech AF9033 successfully attached\n"); 115381e19912SAntti Palosaari 1154f5b00a76SAntti Palosaari return 0; 1155bc85d5e2SAntti Palosaari err_regmap_exit: 1156bc85d5e2SAntti Palosaari regmap_exit(dev->regmap); 1157f5b00a76SAntti Palosaari err_kfree: 1158f5b00a76SAntti Palosaari kfree(dev); 1159f5b00a76SAntti Palosaari err: 11606a087f1fSAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 1161f5b00a76SAntti Palosaari return ret; 1162f5b00a76SAntti Palosaari } 1163f5b00a76SAntti Palosaari 1164f5b00a76SAntti Palosaari static int af9033_remove(struct i2c_client *client) 1165f5b00a76SAntti Palosaari { 1166f5b00a76SAntti Palosaari struct af9033_dev *dev = i2c_get_clientdata(client); 1167f5b00a76SAntti Palosaari 116881e19912SAntti Palosaari dev_dbg(&client->dev, "\n"); 1169f5b00a76SAntti Palosaari 1170bc85d5e2SAntti Palosaari regmap_exit(dev->regmap); 1171f5b00a76SAntti Palosaari kfree(dev); 1172f5b00a76SAntti Palosaari 1173f5b00a76SAntti Palosaari return 0; 1174f5b00a76SAntti Palosaari } 1175f5b00a76SAntti Palosaari 1176f5b00a76SAntti Palosaari static const struct i2c_device_id af9033_id_table[] = { 1177f5b00a76SAntti Palosaari {"af9033", 0}, 1178f5b00a76SAntti Palosaari {} 1179f5b00a76SAntti Palosaari }; 1180f5b00a76SAntti Palosaari MODULE_DEVICE_TABLE(i2c, af9033_id_table); 1181f5b00a76SAntti Palosaari 1182f5b00a76SAntti Palosaari static struct i2c_driver af9033_driver = { 1183f5b00a76SAntti Palosaari .driver = { 1184f5b00a76SAntti Palosaari .name = "af9033", 118572812175SAntti Palosaari .suppress_bind_attrs = true, 1186f5b00a76SAntti Palosaari }, 1187f5b00a76SAntti Palosaari .probe = af9033_probe, 1188f5b00a76SAntti Palosaari .remove = af9033_remove, 1189f5b00a76SAntti Palosaari .id_table = af9033_id_table, 1190f5b00a76SAntti Palosaari }; 1191f5b00a76SAntti Palosaari 1192f5b00a76SAntti Palosaari module_i2c_driver(af9033_driver); 1193f5b00a76SAntti Palosaari 11949a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 11959a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); 11969a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL"); 1197