162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Afatech AF9013 demodulator driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> 662306a36Sopenharmony_ci * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Thanks to Afatech who kindly provided information. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "af9013_priv.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistruct af9013_state { 1462306a36Sopenharmony_ci struct i2c_client *client; 1562306a36Sopenharmony_ci struct regmap *regmap; 1662306a36Sopenharmony_ci struct i2c_mux_core *muxc; 1762306a36Sopenharmony_ci struct dvb_frontend fe; 1862306a36Sopenharmony_ci u32 clk; 1962306a36Sopenharmony_ci u8 tuner; 2062306a36Sopenharmony_ci u32 if_frequency; 2162306a36Sopenharmony_ci u8 ts_mode; 2262306a36Sopenharmony_ci u8 ts_output_pin; 2362306a36Sopenharmony_ci bool spec_inv; 2462306a36Sopenharmony_ci u8 api_version[4]; 2562306a36Sopenharmony_ci u8 gpio[4]; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci u32 bandwidth_hz; 2862306a36Sopenharmony_ci enum fe_status fe_status; 2962306a36Sopenharmony_ci /* RF and IF AGC limits used for signal strength calc */ 3062306a36Sopenharmony_ci u8 strength_en, rf_agc_50, rf_agc_80, if_agc_50, if_agc_80; 3162306a36Sopenharmony_ci unsigned long set_frontend_jiffies; 3262306a36Sopenharmony_ci unsigned long read_status_jiffies; 3362306a36Sopenharmony_ci unsigned long strength_jiffies; 3462306a36Sopenharmony_ci unsigned long cnr_jiffies; 3562306a36Sopenharmony_ci unsigned long ber_ucb_jiffies; 3662306a36Sopenharmony_ci u16 dvbv3_snr; 3762306a36Sopenharmony_ci u16 dvbv3_strength; 3862306a36Sopenharmony_ci u32 dvbv3_ber; 3962306a36Sopenharmony_ci u32 dvbv3_ucblocks; 4062306a36Sopenharmony_ci bool first_tune; 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci struct i2c_client *client = state->client; 4662306a36Sopenharmony_ci int ret; 4762306a36Sopenharmony_ci u8 pos; 4862306a36Sopenharmony_ci u16 addr; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci dev_dbg(&client->dev, "gpio %u, gpioval %02x\n", gpio, gpioval); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci /* 5362306a36Sopenharmony_ci * GPIO0 & GPIO1 0xd735 5462306a36Sopenharmony_ci * GPIO2 & GPIO3 0xd736 5562306a36Sopenharmony_ci */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci switch (gpio) { 5862306a36Sopenharmony_ci case 0: 5962306a36Sopenharmony_ci case 1: 6062306a36Sopenharmony_ci addr = 0xd735; 6162306a36Sopenharmony_ci break; 6262306a36Sopenharmony_ci case 2: 6362306a36Sopenharmony_ci case 3: 6462306a36Sopenharmony_ci addr = 0xd736; 6562306a36Sopenharmony_ci break; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci default: 6862306a36Sopenharmony_ci ret = -EINVAL; 6962306a36Sopenharmony_ci goto err; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci switch (gpio) { 7362306a36Sopenharmony_ci case 0: 7462306a36Sopenharmony_ci case 2: 7562306a36Sopenharmony_ci pos = 0; 7662306a36Sopenharmony_ci break; 7762306a36Sopenharmony_ci case 1: 7862306a36Sopenharmony_ci case 3: 7962306a36Sopenharmony_ci default: 8062306a36Sopenharmony_ci pos = 4; 8162306a36Sopenharmony_ci break; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, addr, 0x0f << pos, 8562306a36Sopenharmony_ci gpioval << pos); 8662306a36Sopenharmony_ci if (ret) 8762306a36Sopenharmony_ci goto err; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci return 0; 9062306a36Sopenharmony_cierr: 9162306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 9262306a36Sopenharmony_ci return ret; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic int af9013_get_tune_settings(struct dvb_frontend *fe, 9662306a36Sopenharmony_ci struct dvb_frontend_tune_settings *fesettings) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci fesettings->min_delay_ms = 800; 9962306a36Sopenharmony_ci fesettings->step_size = 0; 10062306a36Sopenharmony_ci fesettings->max_drift = 0; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic int af9013_set_frontend(struct dvb_frontend *fe) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 10862306a36Sopenharmony_ci struct i2c_client *client = state->client; 10962306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 11062306a36Sopenharmony_ci int ret, i, sampling_freq; 11162306a36Sopenharmony_ci bool auto_mode, spec_inv; 11262306a36Sopenharmony_ci u8 buf[6]; 11362306a36Sopenharmony_ci u32 if_frequency, freq_cw; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci dev_dbg(&client->dev, "frequency %u, bandwidth_hz %u\n", 11662306a36Sopenharmony_ci c->frequency, c->bandwidth_hz); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* program tuner */ 11962306a36Sopenharmony_ci if (fe->ops.tuner_ops.set_params) { 12062306a36Sopenharmony_ci ret = fe->ops.tuner_ops.set_params(fe); 12162306a36Sopenharmony_ci if (ret) 12262306a36Sopenharmony_ci goto err; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci /* program CFOE coefficients */ 12662306a36Sopenharmony_ci if (c->bandwidth_hz != state->bandwidth_hz) { 12762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { 12862306a36Sopenharmony_ci if (coeff_lut[i].clock == state->clk && 12962306a36Sopenharmony_ci coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* Return an error if can't find bandwidth or the right clock */ 13562306a36Sopenharmony_ci if (i == ARRAY_SIZE(coeff_lut)) { 13662306a36Sopenharmony_ci ret = -EINVAL; 13762306a36Sopenharmony_ci goto err; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0xae00, coeff_lut[i].val, 14162306a36Sopenharmony_ci sizeof(coeff_lut[i].val)); 14262306a36Sopenharmony_ci if (ret) 14362306a36Sopenharmony_ci goto err; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* program frequency control */ 14762306a36Sopenharmony_ci if (c->bandwidth_hz != state->bandwidth_hz || state->first_tune) { 14862306a36Sopenharmony_ci /* get used IF frequency */ 14962306a36Sopenharmony_ci if (fe->ops.tuner_ops.get_if_frequency) { 15062306a36Sopenharmony_ci ret = fe->ops.tuner_ops.get_if_frequency(fe, 15162306a36Sopenharmony_ci &if_frequency); 15262306a36Sopenharmony_ci if (ret) 15362306a36Sopenharmony_ci goto err; 15462306a36Sopenharmony_ci } else { 15562306a36Sopenharmony_ci if_frequency = state->if_frequency; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci dev_dbg(&client->dev, "if_frequency %u\n", if_frequency); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci sampling_freq = if_frequency; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci while (sampling_freq > (state->clk / 2)) 16362306a36Sopenharmony_ci sampling_freq -= state->clk; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci if (sampling_freq < 0) { 16662306a36Sopenharmony_ci sampling_freq *= -1; 16762306a36Sopenharmony_ci spec_inv = state->spec_inv; 16862306a36Sopenharmony_ci } else { 16962306a36Sopenharmony_ci spec_inv = !state->spec_inv; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci freq_cw = DIV_ROUND_CLOSEST_ULL((u64)sampling_freq * 0x800000, 17362306a36Sopenharmony_ci state->clk); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci if (spec_inv) 17662306a36Sopenharmony_ci freq_cw = 0x800000 - freq_cw; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci buf[0] = (freq_cw >> 0) & 0xff; 17962306a36Sopenharmony_ci buf[1] = (freq_cw >> 8) & 0xff; 18062306a36Sopenharmony_ci buf[2] = (freq_cw >> 16) & 0x7f; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci freq_cw = 0x800000 - freq_cw; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci buf[3] = (freq_cw >> 0) & 0xff; 18562306a36Sopenharmony_ci buf[4] = (freq_cw >> 8) & 0xff; 18662306a36Sopenharmony_ci buf[5] = (freq_cw >> 16) & 0x7f; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0xd140, buf, 3); 18962306a36Sopenharmony_ci if (ret) 19062306a36Sopenharmony_ci goto err; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0x9be7, buf, 6); 19362306a36Sopenharmony_ci if (ret) 19462306a36Sopenharmony_ci goto err; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* clear TPS lock flag */ 19862306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd330, 0x08, 0x08); 19962306a36Sopenharmony_ci if (ret) 20062306a36Sopenharmony_ci goto err; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci /* clear MPEG2 lock flag */ 20362306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd507, 0x40, 0x00); 20462306a36Sopenharmony_ci if (ret) 20562306a36Sopenharmony_ci goto err; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* empty channel function */ 20862306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0x9bfe, 0x01, 0x00); 20962306a36Sopenharmony_ci if (ret) 21062306a36Sopenharmony_ci goto err; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* empty DVB-T channel function */ 21362306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0x9bc2, 0x01, 0x00); 21462306a36Sopenharmony_ci if (ret) 21562306a36Sopenharmony_ci goto err; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* transmission parameters */ 21862306a36Sopenharmony_ci auto_mode = false; 21962306a36Sopenharmony_ci memset(buf, 0, 3); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci switch (c->transmission_mode) { 22262306a36Sopenharmony_ci case TRANSMISSION_MODE_AUTO: 22362306a36Sopenharmony_ci auto_mode = true; 22462306a36Sopenharmony_ci break; 22562306a36Sopenharmony_ci case TRANSMISSION_MODE_2K: 22662306a36Sopenharmony_ci break; 22762306a36Sopenharmony_ci case TRANSMISSION_MODE_8K: 22862306a36Sopenharmony_ci buf[0] |= (1 << 0); 22962306a36Sopenharmony_ci break; 23062306a36Sopenharmony_ci default: 23162306a36Sopenharmony_ci dev_dbg(&client->dev, "invalid transmission_mode\n"); 23262306a36Sopenharmony_ci auto_mode = true; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci switch (c->guard_interval) { 23662306a36Sopenharmony_ci case GUARD_INTERVAL_AUTO: 23762306a36Sopenharmony_ci auto_mode = true; 23862306a36Sopenharmony_ci break; 23962306a36Sopenharmony_ci case GUARD_INTERVAL_1_32: 24062306a36Sopenharmony_ci break; 24162306a36Sopenharmony_ci case GUARD_INTERVAL_1_16: 24262306a36Sopenharmony_ci buf[0] |= (1 << 2); 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci case GUARD_INTERVAL_1_8: 24562306a36Sopenharmony_ci buf[0] |= (2 << 2); 24662306a36Sopenharmony_ci break; 24762306a36Sopenharmony_ci case GUARD_INTERVAL_1_4: 24862306a36Sopenharmony_ci buf[0] |= (3 << 2); 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci default: 25162306a36Sopenharmony_ci dev_dbg(&client->dev, "invalid guard_interval\n"); 25262306a36Sopenharmony_ci auto_mode = true; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci switch (c->hierarchy) { 25662306a36Sopenharmony_ci case HIERARCHY_AUTO: 25762306a36Sopenharmony_ci auto_mode = true; 25862306a36Sopenharmony_ci break; 25962306a36Sopenharmony_ci case HIERARCHY_NONE: 26062306a36Sopenharmony_ci break; 26162306a36Sopenharmony_ci case HIERARCHY_1: 26262306a36Sopenharmony_ci buf[0] |= (1 << 4); 26362306a36Sopenharmony_ci break; 26462306a36Sopenharmony_ci case HIERARCHY_2: 26562306a36Sopenharmony_ci buf[0] |= (2 << 4); 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci case HIERARCHY_4: 26862306a36Sopenharmony_ci buf[0] |= (3 << 4); 26962306a36Sopenharmony_ci break; 27062306a36Sopenharmony_ci default: 27162306a36Sopenharmony_ci dev_dbg(&client->dev, "invalid hierarchy\n"); 27262306a36Sopenharmony_ci auto_mode = true; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci switch (c->modulation) { 27662306a36Sopenharmony_ci case QAM_AUTO: 27762306a36Sopenharmony_ci auto_mode = true; 27862306a36Sopenharmony_ci break; 27962306a36Sopenharmony_ci case QPSK: 28062306a36Sopenharmony_ci break; 28162306a36Sopenharmony_ci case QAM_16: 28262306a36Sopenharmony_ci buf[1] |= (1 << 6); 28362306a36Sopenharmony_ci break; 28462306a36Sopenharmony_ci case QAM_64: 28562306a36Sopenharmony_ci buf[1] |= (2 << 6); 28662306a36Sopenharmony_ci break; 28762306a36Sopenharmony_ci default: 28862306a36Sopenharmony_ci dev_dbg(&client->dev, "invalid modulation\n"); 28962306a36Sopenharmony_ci auto_mode = true; 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* Use HP. How and which case we can switch to LP? */ 29362306a36Sopenharmony_ci buf[1] |= (1 << 4); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci switch (c->code_rate_HP) { 29662306a36Sopenharmony_ci case FEC_AUTO: 29762306a36Sopenharmony_ci auto_mode = true; 29862306a36Sopenharmony_ci break; 29962306a36Sopenharmony_ci case FEC_1_2: 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci case FEC_2_3: 30262306a36Sopenharmony_ci buf[2] |= (1 << 0); 30362306a36Sopenharmony_ci break; 30462306a36Sopenharmony_ci case FEC_3_4: 30562306a36Sopenharmony_ci buf[2] |= (2 << 0); 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci case FEC_5_6: 30862306a36Sopenharmony_ci buf[2] |= (3 << 0); 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci case FEC_7_8: 31162306a36Sopenharmony_ci buf[2] |= (4 << 0); 31262306a36Sopenharmony_ci break; 31362306a36Sopenharmony_ci default: 31462306a36Sopenharmony_ci dev_dbg(&client->dev, "invalid code_rate_HP\n"); 31562306a36Sopenharmony_ci auto_mode = true; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci switch (c->code_rate_LP) { 31962306a36Sopenharmony_ci case FEC_AUTO: 32062306a36Sopenharmony_ci auto_mode = true; 32162306a36Sopenharmony_ci break; 32262306a36Sopenharmony_ci case FEC_1_2: 32362306a36Sopenharmony_ci break; 32462306a36Sopenharmony_ci case FEC_2_3: 32562306a36Sopenharmony_ci buf[2] |= (1 << 3); 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci case FEC_3_4: 32862306a36Sopenharmony_ci buf[2] |= (2 << 3); 32962306a36Sopenharmony_ci break; 33062306a36Sopenharmony_ci case FEC_5_6: 33162306a36Sopenharmony_ci buf[2] |= (3 << 3); 33262306a36Sopenharmony_ci break; 33362306a36Sopenharmony_ci case FEC_7_8: 33462306a36Sopenharmony_ci buf[2] |= (4 << 3); 33562306a36Sopenharmony_ci break; 33662306a36Sopenharmony_ci case FEC_NONE: 33762306a36Sopenharmony_ci break; 33862306a36Sopenharmony_ci default: 33962306a36Sopenharmony_ci dev_dbg(&client->dev, "invalid code_rate_LP\n"); 34062306a36Sopenharmony_ci auto_mode = true; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci switch (c->bandwidth_hz) { 34462306a36Sopenharmony_ci case 6000000: 34562306a36Sopenharmony_ci break; 34662306a36Sopenharmony_ci case 7000000: 34762306a36Sopenharmony_ci buf[1] |= (1 << 2); 34862306a36Sopenharmony_ci break; 34962306a36Sopenharmony_ci case 8000000: 35062306a36Sopenharmony_ci buf[1] |= (2 << 2); 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci default: 35362306a36Sopenharmony_ci dev_dbg(&client->dev, "invalid bandwidth_hz\n"); 35462306a36Sopenharmony_ci ret = -EINVAL; 35562306a36Sopenharmony_ci goto err; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0xd3c0, buf, 3); 35962306a36Sopenharmony_ci if (ret) 36062306a36Sopenharmony_ci goto err; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (auto_mode) { 36362306a36Sopenharmony_ci /* clear easy mode flag */ 36462306a36Sopenharmony_ci ret = regmap_write(state->regmap, 0xaefd, 0x00); 36562306a36Sopenharmony_ci if (ret) 36662306a36Sopenharmony_ci goto err; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci dev_dbg(&client->dev, "auto params\n"); 36962306a36Sopenharmony_ci } else { 37062306a36Sopenharmony_ci /* set easy mode flag */ 37162306a36Sopenharmony_ci ret = regmap_write(state->regmap, 0xaefd, 0x01); 37262306a36Sopenharmony_ci if (ret) 37362306a36Sopenharmony_ci goto err; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci ret = regmap_write(state->regmap, 0xaefe, 0x00); 37662306a36Sopenharmony_ci if (ret) 37762306a36Sopenharmony_ci goto err; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci dev_dbg(&client->dev, "manual params\n"); 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* Reset FSM */ 38362306a36Sopenharmony_ci ret = regmap_write(state->regmap, 0xffff, 0x00); 38462306a36Sopenharmony_ci if (ret) 38562306a36Sopenharmony_ci goto err; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci state->bandwidth_hz = c->bandwidth_hz; 38862306a36Sopenharmony_ci state->set_frontend_jiffies = jiffies; 38962306a36Sopenharmony_ci state->first_tune = false; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci return 0; 39262306a36Sopenharmony_cierr: 39362306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 39462306a36Sopenharmony_ci return ret; 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic int af9013_get_frontend(struct dvb_frontend *fe, 39862306a36Sopenharmony_ci struct dtv_frontend_properties *c) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 40162306a36Sopenharmony_ci struct i2c_client *client = state->client; 40262306a36Sopenharmony_ci int ret; 40362306a36Sopenharmony_ci u8 buf[3]; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci ret = regmap_bulk_read(state->regmap, 0xd3c0, buf, 3); 40862306a36Sopenharmony_ci if (ret) 40962306a36Sopenharmony_ci goto err; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci switch ((buf[1] >> 6) & 3) { 41262306a36Sopenharmony_ci case 0: 41362306a36Sopenharmony_ci c->modulation = QPSK; 41462306a36Sopenharmony_ci break; 41562306a36Sopenharmony_ci case 1: 41662306a36Sopenharmony_ci c->modulation = QAM_16; 41762306a36Sopenharmony_ci break; 41862306a36Sopenharmony_ci case 2: 41962306a36Sopenharmony_ci c->modulation = QAM_64; 42062306a36Sopenharmony_ci break; 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci switch ((buf[0] >> 0) & 3) { 42462306a36Sopenharmony_ci case 0: 42562306a36Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_2K; 42662306a36Sopenharmony_ci break; 42762306a36Sopenharmony_ci case 1: 42862306a36Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_8K; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci switch ((buf[0] >> 2) & 3) { 43262306a36Sopenharmony_ci case 0: 43362306a36Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_32; 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci case 1: 43662306a36Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_16; 43762306a36Sopenharmony_ci break; 43862306a36Sopenharmony_ci case 2: 43962306a36Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_8; 44062306a36Sopenharmony_ci break; 44162306a36Sopenharmony_ci case 3: 44262306a36Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_4; 44362306a36Sopenharmony_ci break; 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci switch ((buf[0] >> 4) & 7) { 44762306a36Sopenharmony_ci case 0: 44862306a36Sopenharmony_ci c->hierarchy = HIERARCHY_NONE; 44962306a36Sopenharmony_ci break; 45062306a36Sopenharmony_ci case 1: 45162306a36Sopenharmony_ci c->hierarchy = HIERARCHY_1; 45262306a36Sopenharmony_ci break; 45362306a36Sopenharmony_ci case 2: 45462306a36Sopenharmony_ci c->hierarchy = HIERARCHY_2; 45562306a36Sopenharmony_ci break; 45662306a36Sopenharmony_ci case 3: 45762306a36Sopenharmony_ci c->hierarchy = HIERARCHY_4; 45862306a36Sopenharmony_ci break; 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci switch ((buf[2] >> 0) & 7) { 46262306a36Sopenharmony_ci case 0: 46362306a36Sopenharmony_ci c->code_rate_HP = FEC_1_2; 46462306a36Sopenharmony_ci break; 46562306a36Sopenharmony_ci case 1: 46662306a36Sopenharmony_ci c->code_rate_HP = FEC_2_3; 46762306a36Sopenharmony_ci break; 46862306a36Sopenharmony_ci case 2: 46962306a36Sopenharmony_ci c->code_rate_HP = FEC_3_4; 47062306a36Sopenharmony_ci break; 47162306a36Sopenharmony_ci case 3: 47262306a36Sopenharmony_ci c->code_rate_HP = FEC_5_6; 47362306a36Sopenharmony_ci break; 47462306a36Sopenharmony_ci case 4: 47562306a36Sopenharmony_ci c->code_rate_HP = FEC_7_8; 47662306a36Sopenharmony_ci break; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci switch ((buf[2] >> 3) & 7) { 48062306a36Sopenharmony_ci case 0: 48162306a36Sopenharmony_ci c->code_rate_LP = FEC_1_2; 48262306a36Sopenharmony_ci break; 48362306a36Sopenharmony_ci case 1: 48462306a36Sopenharmony_ci c->code_rate_LP = FEC_2_3; 48562306a36Sopenharmony_ci break; 48662306a36Sopenharmony_ci case 2: 48762306a36Sopenharmony_ci c->code_rate_LP = FEC_3_4; 48862306a36Sopenharmony_ci break; 48962306a36Sopenharmony_ci case 3: 49062306a36Sopenharmony_ci c->code_rate_LP = FEC_5_6; 49162306a36Sopenharmony_ci break; 49262306a36Sopenharmony_ci case 4: 49362306a36Sopenharmony_ci c->code_rate_LP = FEC_7_8; 49462306a36Sopenharmony_ci break; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci switch ((buf[1] >> 2) & 3) { 49862306a36Sopenharmony_ci case 0: 49962306a36Sopenharmony_ci c->bandwidth_hz = 6000000; 50062306a36Sopenharmony_ci break; 50162306a36Sopenharmony_ci case 1: 50262306a36Sopenharmony_ci c->bandwidth_hz = 7000000; 50362306a36Sopenharmony_ci break; 50462306a36Sopenharmony_ci case 2: 50562306a36Sopenharmony_ci c->bandwidth_hz = 8000000; 50662306a36Sopenharmony_ci break; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci return 0; 51062306a36Sopenharmony_cierr: 51162306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 51262306a36Sopenharmony_ci return ret; 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_cistatic int af9013_read_status(struct dvb_frontend *fe, enum fe_status *status) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 51862306a36Sopenharmony_ci struct i2c_client *client = state->client; 51962306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 52062306a36Sopenharmony_ci int ret, stmp1; 52162306a36Sopenharmony_ci unsigned int utmp, utmp1, utmp2, utmp3, utmp4; 52262306a36Sopenharmony_ci u8 buf[7]; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* 52762306a36Sopenharmony_ci * Return status from the cache if it is younger than 2000ms with the 52862306a36Sopenharmony_ci * exception of last tune is done during 4000ms. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ci if (time_is_after_jiffies(state->read_status_jiffies + msecs_to_jiffies(2000)) && 53162306a36Sopenharmony_ci time_is_before_jiffies(state->set_frontend_jiffies + msecs_to_jiffies(4000))) { 53262306a36Sopenharmony_ci *status = state->fe_status; 53362306a36Sopenharmony_ci } else { 53462306a36Sopenharmony_ci /* MPEG2 lock */ 53562306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0xd507, &utmp); 53662306a36Sopenharmony_ci if (ret) 53762306a36Sopenharmony_ci goto err; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci if ((utmp >> 6) & 0x01) { 54062306a36Sopenharmony_ci utmp1 = FE_HAS_SIGNAL | FE_HAS_CARRIER | 54162306a36Sopenharmony_ci FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 54262306a36Sopenharmony_ci } else { 54362306a36Sopenharmony_ci /* TPS lock */ 54462306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0xd330, &utmp); 54562306a36Sopenharmony_ci if (ret) 54662306a36Sopenharmony_ci goto err; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci if ((utmp >> 3) & 0x01) 54962306a36Sopenharmony_ci utmp1 = FE_HAS_SIGNAL | FE_HAS_CARRIER | 55062306a36Sopenharmony_ci FE_HAS_VITERBI; 55162306a36Sopenharmony_ci else 55262306a36Sopenharmony_ci utmp1 = 0; 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci dev_dbg(&client->dev, "fe_status %02x\n", utmp1); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci state->read_status_jiffies = jiffies; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci state->fe_status = utmp1; 56062306a36Sopenharmony_ci *status = utmp1; 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* Signal strength */ 56462306a36Sopenharmony_ci switch (state->strength_en) { 56562306a36Sopenharmony_ci case 0: 56662306a36Sopenharmony_ci /* Check if we support signal strength */ 56762306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0x9bee, &utmp); 56862306a36Sopenharmony_ci if (ret) 56962306a36Sopenharmony_ci goto err; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci if ((utmp >> 0) & 0x01) { 57262306a36Sopenharmony_ci /* Read agc values for signal strength estimation */ 57362306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0x9bbd, &utmp1); 57462306a36Sopenharmony_ci if (ret) 57562306a36Sopenharmony_ci goto err; 57662306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0x9bd0, &utmp2); 57762306a36Sopenharmony_ci if (ret) 57862306a36Sopenharmony_ci goto err; 57962306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0x9be2, &utmp3); 58062306a36Sopenharmony_ci if (ret) 58162306a36Sopenharmony_ci goto err; 58262306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0x9be4, &utmp4); 58362306a36Sopenharmony_ci if (ret) 58462306a36Sopenharmony_ci goto err; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci state->rf_agc_50 = utmp1; 58762306a36Sopenharmony_ci state->rf_agc_80 = utmp2; 58862306a36Sopenharmony_ci state->if_agc_50 = utmp3; 58962306a36Sopenharmony_ci state->if_agc_80 = utmp4; 59062306a36Sopenharmony_ci dev_dbg(&client->dev, 59162306a36Sopenharmony_ci "rf_agc_50 %u, rf_agc_80 %u, if_agc_50 %u, if_agc_80 %u\n", 59262306a36Sopenharmony_ci utmp1, utmp2, utmp3, utmp4); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci state->strength_en = 1; 59562306a36Sopenharmony_ci } else { 59662306a36Sopenharmony_ci /* Signal strength is not supported */ 59762306a36Sopenharmony_ci state->strength_en = 2; 59862306a36Sopenharmony_ci break; 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci fallthrough; 60162306a36Sopenharmony_ci case 1: 60262306a36Sopenharmony_ci if (time_is_after_jiffies(state->strength_jiffies + msecs_to_jiffies(2000))) 60362306a36Sopenharmony_ci break; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci /* Read value */ 60662306a36Sopenharmony_ci ret = regmap_bulk_read(state->regmap, 0xd07c, buf, 2); 60762306a36Sopenharmony_ci if (ret) 60862306a36Sopenharmony_ci goto err; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* 61162306a36Sopenharmony_ci * Construct line equation from tuner dependent -80/-50 dBm agc 61262306a36Sopenharmony_ci * limits and use it to map current agc value to dBm estimate 61362306a36Sopenharmony_ci */ 61462306a36Sopenharmony_ci #define agc_gain (buf[0] + buf[1]) 61562306a36Sopenharmony_ci #define agc_gain_50dbm (state->rf_agc_50 + state->if_agc_50) 61662306a36Sopenharmony_ci #define agc_gain_80dbm (state->rf_agc_80 + state->if_agc_80) 61762306a36Sopenharmony_ci stmp1 = 30000 * (agc_gain - agc_gain_80dbm) / 61862306a36Sopenharmony_ci (agc_gain_50dbm - agc_gain_80dbm) - 80000; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci dev_dbg(&client->dev, 62162306a36Sopenharmony_ci "strength %d, agc_gain %d, agc_gain_50dbm %d, agc_gain_80dbm %d\n", 62262306a36Sopenharmony_ci stmp1, agc_gain, agc_gain_50dbm, agc_gain_80dbm); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci state->strength_jiffies = jiffies; 62562306a36Sopenharmony_ci /* Convert [-90, -30] dBm to [0x0000, 0xffff] for dvbv3 */ 62662306a36Sopenharmony_ci utmp1 = clamp(stmp1 + 90000, 0, 60000); 62762306a36Sopenharmony_ci state->dvbv3_strength = div_u64((u64)utmp1 * 0xffff, 60000); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci c->strength.stat[0].scale = FE_SCALE_DECIBEL; 63062306a36Sopenharmony_ci c->strength.stat[0].svalue = stmp1; 63162306a36Sopenharmony_ci break; 63262306a36Sopenharmony_ci default: 63362306a36Sopenharmony_ci c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 63462306a36Sopenharmony_ci break; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci /* CNR */ 63862306a36Sopenharmony_ci switch (state->fe_status & FE_HAS_VITERBI) { 63962306a36Sopenharmony_ci case FE_HAS_VITERBI: 64062306a36Sopenharmony_ci if (time_is_after_jiffies(state->cnr_jiffies + msecs_to_jiffies(2000))) 64162306a36Sopenharmony_ci break; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* Check if cnr ready */ 64462306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0xd2e1, &utmp); 64562306a36Sopenharmony_ci if (ret) 64662306a36Sopenharmony_ci goto err; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci if (!((utmp >> 3) & 0x01)) { 64962306a36Sopenharmony_ci dev_dbg(&client->dev, "cnr not ready\n"); 65062306a36Sopenharmony_ci break; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci /* Read value */ 65462306a36Sopenharmony_ci ret = regmap_bulk_read(state->regmap, 0xd2e3, buf, 3); 65562306a36Sopenharmony_ci if (ret) 65662306a36Sopenharmony_ci goto err; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci utmp1 = buf[2] << 16 | buf[1] << 8 | buf[0] << 0; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* Read current modulation */ 66162306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0xd3c1, &utmp); 66262306a36Sopenharmony_ci if (ret) 66362306a36Sopenharmony_ci goto err; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci switch ((utmp >> 6) & 3) { 66662306a36Sopenharmony_ci case 0: 66762306a36Sopenharmony_ci /* 66862306a36Sopenharmony_ci * QPSK 66962306a36Sopenharmony_ci * CNR[dB] 13 * -log10((1690000 - value) / value) + 2.6 67062306a36Sopenharmony_ci * value [653799, 1689999], 2.6 / 13 = 3355443 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci utmp1 = clamp(utmp1, 653799U, 1689999U); 67362306a36Sopenharmony_ci utmp1 = ((u64)(intlog10(utmp1) 67462306a36Sopenharmony_ci - intlog10(1690000 - utmp1) 67562306a36Sopenharmony_ci + 3355443) * 13 * 1000) >> 24; 67662306a36Sopenharmony_ci break; 67762306a36Sopenharmony_ci case 1: 67862306a36Sopenharmony_ci /* 67962306a36Sopenharmony_ci * QAM-16 68062306a36Sopenharmony_ci * CNR[dB] 6 * log10((value - 370000) / (828000 - value)) + 15.7 68162306a36Sopenharmony_ci * value [371105, 827999], 15.7 / 6 = 43900382 68262306a36Sopenharmony_ci */ 68362306a36Sopenharmony_ci utmp1 = clamp(utmp1, 371105U, 827999U); 68462306a36Sopenharmony_ci utmp1 = ((u64)(intlog10(utmp1 - 370000) 68562306a36Sopenharmony_ci - intlog10(828000 - utmp1) 68662306a36Sopenharmony_ci + 43900382) * 6 * 1000) >> 24; 68762306a36Sopenharmony_ci break; 68862306a36Sopenharmony_ci case 2: 68962306a36Sopenharmony_ci /* 69062306a36Sopenharmony_ci * QAM-64 69162306a36Sopenharmony_ci * CNR[dB] 8 * log10((value - 193000) / (425000 - value)) + 23.8 69262306a36Sopenharmony_ci * value [193246, 424999], 23.8 / 8 = 49912218 69362306a36Sopenharmony_ci */ 69462306a36Sopenharmony_ci utmp1 = clamp(utmp1, 193246U, 424999U); 69562306a36Sopenharmony_ci utmp1 = ((u64)(intlog10(utmp1 - 193000) 69662306a36Sopenharmony_ci - intlog10(425000 - utmp1) 69762306a36Sopenharmony_ci + 49912218) * 8 * 1000) >> 24; 69862306a36Sopenharmony_ci break; 69962306a36Sopenharmony_ci default: 70062306a36Sopenharmony_ci dev_dbg(&client->dev, "invalid modulation %u\n", 70162306a36Sopenharmony_ci (utmp >> 6) & 3); 70262306a36Sopenharmony_ci utmp1 = 0; 70362306a36Sopenharmony_ci break; 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci dev_dbg(&client->dev, "cnr %u\n", utmp1); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci state->cnr_jiffies = jiffies; 70962306a36Sopenharmony_ci state->dvbv3_snr = utmp1 / 100; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 71262306a36Sopenharmony_ci c->cnr.stat[0].svalue = utmp1; 71362306a36Sopenharmony_ci break; 71462306a36Sopenharmony_ci default: 71562306a36Sopenharmony_ci c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 71662306a36Sopenharmony_ci break; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* BER / PER */ 72062306a36Sopenharmony_ci switch (state->fe_status & FE_HAS_SYNC) { 72162306a36Sopenharmony_ci case FE_HAS_SYNC: 72262306a36Sopenharmony_ci if (time_is_after_jiffies(state->ber_ucb_jiffies + msecs_to_jiffies(2000))) 72362306a36Sopenharmony_ci break; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci /* Check if ber / ucb is ready */ 72662306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0xd391, &utmp); 72762306a36Sopenharmony_ci if (ret) 72862306a36Sopenharmony_ci goto err; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci if (!((utmp >> 4) & 0x01)) { 73162306a36Sopenharmony_ci dev_dbg(&client->dev, "ber not ready\n"); 73262306a36Sopenharmony_ci break; 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci /* Read value */ 73662306a36Sopenharmony_ci ret = regmap_bulk_read(state->regmap, 0xd385, buf, 7); 73762306a36Sopenharmony_ci if (ret) 73862306a36Sopenharmony_ci goto err; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci utmp1 = buf[4] << 16 | buf[3] << 8 | buf[2] << 0; 74162306a36Sopenharmony_ci utmp2 = (buf[1] << 8 | buf[0] << 0) * 204 * 8; 74262306a36Sopenharmony_ci utmp3 = buf[6] << 8 | buf[5] << 0; 74362306a36Sopenharmony_ci utmp4 = buf[1] << 8 | buf[0] << 0; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci /* Use 10000 TS packets for measure */ 74662306a36Sopenharmony_ci if (utmp4 != 10000) { 74762306a36Sopenharmony_ci buf[0] = (10000 >> 0) & 0xff; 74862306a36Sopenharmony_ci buf[1] = (10000 >> 8) & 0xff; 74962306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0xd385, buf, 2); 75062306a36Sopenharmony_ci if (ret) 75162306a36Sopenharmony_ci goto err; 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci /* Reset ber / ucb counter */ 75562306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd391, 0x20, 0x20); 75662306a36Sopenharmony_ci if (ret) 75762306a36Sopenharmony_ci goto err; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci dev_dbg(&client->dev, "post_bit_error %u, post_bit_count %u\n", 76062306a36Sopenharmony_ci utmp1, utmp2); 76162306a36Sopenharmony_ci dev_dbg(&client->dev, "block_error %u, block_count %u\n", 76262306a36Sopenharmony_ci utmp3, utmp4); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci state->ber_ucb_jiffies = jiffies; 76562306a36Sopenharmony_ci state->dvbv3_ber = utmp1; 76662306a36Sopenharmony_ci state->dvbv3_ucblocks += utmp3; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 76962306a36Sopenharmony_ci c->post_bit_error.stat[0].uvalue += utmp1; 77062306a36Sopenharmony_ci c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 77162306a36Sopenharmony_ci c->post_bit_count.stat[0].uvalue += utmp2; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci c->block_error.stat[0].scale = FE_SCALE_COUNTER; 77462306a36Sopenharmony_ci c->block_error.stat[0].uvalue += utmp3; 77562306a36Sopenharmony_ci c->block_count.stat[0].scale = FE_SCALE_COUNTER; 77662306a36Sopenharmony_ci c->block_count.stat[0].uvalue += utmp4; 77762306a36Sopenharmony_ci break; 77862306a36Sopenharmony_ci default: 77962306a36Sopenharmony_ci c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 78062306a36Sopenharmony_ci c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 78362306a36Sopenharmony_ci c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 78462306a36Sopenharmony_ci break; 78562306a36Sopenharmony_ci } 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci return 0; 78862306a36Sopenharmony_cierr: 78962306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 79062306a36Sopenharmony_ci return ret; 79162306a36Sopenharmony_ci} 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_cistatic int af9013_read_snr(struct dvb_frontend *fe, u16 *snr) 79462306a36Sopenharmony_ci{ 79562306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci *snr = state->dvbv3_snr; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci return 0; 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci *strength = state->dvbv3_strength; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci return 0; 80962306a36Sopenharmony_ci} 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_cistatic int af9013_read_ber(struct dvb_frontend *fe, u32 *ber) 81262306a36Sopenharmony_ci{ 81362306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci *ber = state->dvbv3_ber; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci return 0; 81862306a36Sopenharmony_ci} 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cistatic int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci *ucblocks = state->dvbv3_ucblocks; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci return 0; 82762306a36Sopenharmony_ci} 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_cistatic int af9013_init(struct dvb_frontend *fe) 83062306a36Sopenharmony_ci{ 83162306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 83262306a36Sopenharmony_ci struct i2c_client *client = state->client; 83362306a36Sopenharmony_ci int ret, i, len; 83462306a36Sopenharmony_ci unsigned int utmp; 83562306a36Sopenharmony_ci u8 buf[3]; 83662306a36Sopenharmony_ci const struct af9013_reg_mask_val *tab; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci /* ADC on */ 84162306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd73a, 0x08, 0x00); 84262306a36Sopenharmony_ci if (ret) 84362306a36Sopenharmony_ci goto err; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci /* Clear reset */ 84662306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd417, 0x02, 0x00); 84762306a36Sopenharmony_ci if (ret) 84862306a36Sopenharmony_ci goto err; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci /* Disable reset */ 85162306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd417, 0x10, 0x00); 85262306a36Sopenharmony_ci if (ret) 85362306a36Sopenharmony_ci goto err; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci /* write API version to firmware */ 85662306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0x9bf2, state->api_version, 4); 85762306a36Sopenharmony_ci if (ret) 85862306a36Sopenharmony_ci goto err; 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci /* program ADC control */ 86162306a36Sopenharmony_ci switch (state->clk) { 86262306a36Sopenharmony_ci case 28800000: /* 28.800 MHz */ 86362306a36Sopenharmony_ci utmp = 0; 86462306a36Sopenharmony_ci break; 86562306a36Sopenharmony_ci case 20480000: /* 20.480 MHz */ 86662306a36Sopenharmony_ci utmp = 1; 86762306a36Sopenharmony_ci break; 86862306a36Sopenharmony_ci case 28000000: /* 28.000 MHz */ 86962306a36Sopenharmony_ci utmp = 2; 87062306a36Sopenharmony_ci break; 87162306a36Sopenharmony_ci case 25000000: /* 25.000 MHz */ 87262306a36Sopenharmony_ci utmp = 3; 87362306a36Sopenharmony_ci break; 87462306a36Sopenharmony_ci default: 87562306a36Sopenharmony_ci ret = -EINVAL; 87662306a36Sopenharmony_ci goto err; 87762306a36Sopenharmony_ci } 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0x9bd2, 0x0f, utmp); 88062306a36Sopenharmony_ci if (ret) 88162306a36Sopenharmony_ci goto err; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci utmp = div_u64((u64)state->clk * 0x80000, 1000000); 88462306a36Sopenharmony_ci buf[0] = (utmp >> 0) & 0xff; 88562306a36Sopenharmony_ci buf[1] = (utmp >> 8) & 0xff; 88662306a36Sopenharmony_ci buf[2] = (utmp >> 16) & 0xff; 88762306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0xd180, buf, 3); 88862306a36Sopenharmony_ci if (ret) 88962306a36Sopenharmony_ci goto err; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci /* Demod core settings */ 89262306a36Sopenharmony_ci dev_dbg(&client->dev, "load demod core settings\n"); 89362306a36Sopenharmony_ci len = ARRAY_SIZE(demod_init_tab); 89462306a36Sopenharmony_ci tab = demod_init_tab; 89562306a36Sopenharmony_ci for (i = 0; i < len; i++) { 89662306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, tab[i].reg, tab[i].mask, 89762306a36Sopenharmony_ci tab[i].val); 89862306a36Sopenharmony_ci if (ret) 89962306a36Sopenharmony_ci goto err; 90062306a36Sopenharmony_ci } 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci /* Demod tuner specific settings */ 90362306a36Sopenharmony_ci dev_dbg(&client->dev, "load tuner specific settings\n"); 90462306a36Sopenharmony_ci switch (state->tuner) { 90562306a36Sopenharmony_ci case AF9013_TUNER_MXL5003D: 90662306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_mxl5003d); 90762306a36Sopenharmony_ci tab = tuner_init_tab_mxl5003d; 90862306a36Sopenharmony_ci break; 90962306a36Sopenharmony_ci case AF9013_TUNER_MXL5005D: 91062306a36Sopenharmony_ci case AF9013_TUNER_MXL5005R: 91162306a36Sopenharmony_ci case AF9013_TUNER_MXL5007T: 91262306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_mxl5005); 91362306a36Sopenharmony_ci tab = tuner_init_tab_mxl5005; 91462306a36Sopenharmony_ci break; 91562306a36Sopenharmony_ci case AF9013_TUNER_ENV77H11D5: 91662306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_env77h11d5); 91762306a36Sopenharmony_ci tab = tuner_init_tab_env77h11d5; 91862306a36Sopenharmony_ci break; 91962306a36Sopenharmony_ci case AF9013_TUNER_MT2060: 92062306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_mt2060); 92162306a36Sopenharmony_ci tab = tuner_init_tab_mt2060; 92262306a36Sopenharmony_ci break; 92362306a36Sopenharmony_ci case AF9013_TUNER_MC44S803: 92462306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_mc44s803); 92562306a36Sopenharmony_ci tab = tuner_init_tab_mc44s803; 92662306a36Sopenharmony_ci break; 92762306a36Sopenharmony_ci case AF9013_TUNER_QT1010: 92862306a36Sopenharmony_ci case AF9013_TUNER_QT1010A: 92962306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_qt1010); 93062306a36Sopenharmony_ci tab = tuner_init_tab_qt1010; 93162306a36Sopenharmony_ci break; 93262306a36Sopenharmony_ci case AF9013_TUNER_MT2060_2: 93362306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_mt2060_2); 93462306a36Sopenharmony_ci tab = tuner_init_tab_mt2060_2; 93562306a36Sopenharmony_ci break; 93662306a36Sopenharmony_ci case AF9013_TUNER_TDA18271: 93762306a36Sopenharmony_ci case AF9013_TUNER_TDA18218: 93862306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_tda18271); 93962306a36Sopenharmony_ci tab = tuner_init_tab_tda18271; 94062306a36Sopenharmony_ci break; 94162306a36Sopenharmony_ci case AF9013_TUNER_UNKNOWN: 94262306a36Sopenharmony_ci default: 94362306a36Sopenharmony_ci len = ARRAY_SIZE(tuner_init_tab_unknown); 94462306a36Sopenharmony_ci tab = tuner_init_tab_unknown; 94562306a36Sopenharmony_ci break; 94662306a36Sopenharmony_ci } 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci for (i = 0; i < len; i++) { 94962306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, tab[i].reg, tab[i].mask, 95062306a36Sopenharmony_ci tab[i].val); 95162306a36Sopenharmony_ci if (ret) 95262306a36Sopenharmony_ci goto err; 95362306a36Sopenharmony_ci } 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci /* TS interface */ 95662306a36Sopenharmony_ci if (state->ts_output_pin == 7) 95762306a36Sopenharmony_ci utmp = 1 << 3 | state->ts_mode << 1; 95862306a36Sopenharmony_ci else 95962306a36Sopenharmony_ci utmp = 0 << 3 | state->ts_mode << 1; 96062306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd500, 0x0e, utmp); 96162306a36Sopenharmony_ci if (ret) 96262306a36Sopenharmony_ci goto err; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci /* enable lock led */ 96562306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd730, 0x01, 0x01); 96662306a36Sopenharmony_ci if (ret) 96762306a36Sopenharmony_ci goto err; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci state->first_tune = true; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci return 0; 97262306a36Sopenharmony_cierr: 97362306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 97462306a36Sopenharmony_ci return ret; 97562306a36Sopenharmony_ci} 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_cistatic int af9013_sleep(struct dvb_frontend *fe) 97862306a36Sopenharmony_ci{ 97962306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 98062306a36Sopenharmony_ci struct i2c_client *client = state->client; 98162306a36Sopenharmony_ci int ret; 98262306a36Sopenharmony_ci unsigned int utmp; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci /* disable lock led */ 98762306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd730, 0x01, 0x00); 98862306a36Sopenharmony_ci if (ret) 98962306a36Sopenharmony_ci goto err; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci /* Enable reset */ 99262306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd417, 0x10, 0x10); 99362306a36Sopenharmony_ci if (ret) 99462306a36Sopenharmony_ci goto err; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci /* Start reset execution */ 99762306a36Sopenharmony_ci ret = regmap_write(state->regmap, 0xaeff, 0x01); 99862306a36Sopenharmony_ci if (ret) 99962306a36Sopenharmony_ci goto err; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci /* Wait reset performs */ 100262306a36Sopenharmony_ci ret = regmap_read_poll_timeout(state->regmap, 0xd417, utmp, 100362306a36Sopenharmony_ci (utmp >> 1) & 0x01, 5000, 1000000); 100462306a36Sopenharmony_ci if (ret) 100562306a36Sopenharmony_ci goto err; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (!((utmp >> 1) & 0x01)) { 100862306a36Sopenharmony_ci ret = -ETIMEDOUT; 100962306a36Sopenharmony_ci goto err; 101062306a36Sopenharmony_ci } 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci /* ADC off */ 101362306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd73a, 0x08, 0x08); 101462306a36Sopenharmony_ci if (ret) 101562306a36Sopenharmony_ci goto err; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci return 0; 101862306a36Sopenharmony_cierr: 101962306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 102062306a36Sopenharmony_ci return ret; 102162306a36Sopenharmony_ci} 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_cistatic const struct dvb_frontend_ops af9013_ops; 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_cistatic int af9013_download_firmware(struct af9013_state *state) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci struct i2c_client *client = state->client; 102862306a36Sopenharmony_ci int ret, i, len, rem; 102962306a36Sopenharmony_ci unsigned int utmp; 103062306a36Sopenharmony_ci u8 buf[4]; 103162306a36Sopenharmony_ci u16 checksum = 0; 103262306a36Sopenharmony_ci const struct firmware *firmware; 103362306a36Sopenharmony_ci const char *name = AF9013_FIRMWARE; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci /* Check whether firmware is already running */ 103862306a36Sopenharmony_ci ret = regmap_read(state->regmap, 0x98be, &utmp); 103962306a36Sopenharmony_ci if (ret) 104062306a36Sopenharmony_ci goto err; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci dev_dbg(&client->dev, "firmware status %02x\n", utmp); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci if (utmp == 0x0c) 104562306a36Sopenharmony_ci return 0; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci dev_info(&client->dev, "found a '%s' in cold state, will try to load a firmware\n", 104862306a36Sopenharmony_ci af9013_ops.info.name); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci /* Request the firmware, will block and timeout */ 105162306a36Sopenharmony_ci ret = request_firmware(&firmware, name, &client->dev); 105262306a36Sopenharmony_ci if (ret) { 105362306a36Sopenharmony_ci dev_info(&client->dev, "firmware file '%s' not found %d\n", 105462306a36Sopenharmony_ci name, ret); 105562306a36Sopenharmony_ci goto err; 105662306a36Sopenharmony_ci } 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci dev_info(&client->dev, "downloading firmware from file '%s'\n", 105962306a36Sopenharmony_ci name); 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci /* Write firmware checksum & size */ 106262306a36Sopenharmony_ci for (i = 0; i < firmware->size; i++) 106362306a36Sopenharmony_ci checksum += firmware->data[i]; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci buf[0] = (checksum >> 8) & 0xff; 106662306a36Sopenharmony_ci buf[1] = (checksum >> 0) & 0xff; 106762306a36Sopenharmony_ci buf[2] = (firmware->size >> 8) & 0xff; 106862306a36Sopenharmony_ci buf[3] = (firmware->size >> 0) & 0xff; 106962306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0x50fc, buf, 4); 107062306a36Sopenharmony_ci if (ret) 107162306a36Sopenharmony_ci goto err_release_firmware; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci /* Download firmware */ 107462306a36Sopenharmony_ci #define LEN_MAX 16 107562306a36Sopenharmony_ci for (rem = firmware->size; rem > 0; rem -= LEN_MAX) { 107662306a36Sopenharmony_ci len = min(LEN_MAX, rem); 107762306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 107862306a36Sopenharmony_ci 0x5100 + firmware->size - rem, 107962306a36Sopenharmony_ci &firmware->data[firmware->size - rem], 108062306a36Sopenharmony_ci len); 108162306a36Sopenharmony_ci if (ret) { 108262306a36Sopenharmony_ci dev_err(&client->dev, "firmware download failed %d\n", 108362306a36Sopenharmony_ci ret); 108462306a36Sopenharmony_ci goto err_release_firmware; 108562306a36Sopenharmony_ci } 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci release_firmware(firmware); 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci /* Boot firmware */ 109162306a36Sopenharmony_ci ret = regmap_write(state->regmap, 0xe205, 0x01); 109262306a36Sopenharmony_ci if (ret) 109362306a36Sopenharmony_ci goto err; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci /* Check firmware status. 0c=OK, 04=fail */ 109662306a36Sopenharmony_ci ret = regmap_read_poll_timeout(state->regmap, 0x98be, utmp, 109762306a36Sopenharmony_ci (utmp == 0x0c || utmp == 0x04), 109862306a36Sopenharmony_ci 5000, 1000000); 109962306a36Sopenharmony_ci if (ret) 110062306a36Sopenharmony_ci goto err; 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci dev_dbg(&client->dev, "firmware status %02x\n", utmp); 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci if (utmp == 0x04) { 110562306a36Sopenharmony_ci ret = -ENODEV; 110662306a36Sopenharmony_ci dev_err(&client->dev, "firmware did not run\n"); 110762306a36Sopenharmony_ci goto err; 110862306a36Sopenharmony_ci } else if (utmp != 0x0c) { 110962306a36Sopenharmony_ci ret = -ENODEV; 111062306a36Sopenharmony_ci dev_err(&client->dev, "firmware boot timeout\n"); 111162306a36Sopenharmony_ci goto err; 111262306a36Sopenharmony_ci } 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci dev_info(&client->dev, "found a '%s' in warm state\n", 111562306a36Sopenharmony_ci af9013_ops.info.name); 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci return 0; 111862306a36Sopenharmony_cierr_release_firmware: 111962306a36Sopenharmony_ci release_firmware(firmware); 112062306a36Sopenharmony_cierr: 112162306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 112262306a36Sopenharmony_ci return ret; 112362306a36Sopenharmony_ci} 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_cistatic const struct dvb_frontend_ops af9013_ops = { 112662306a36Sopenharmony_ci .delsys = { SYS_DVBT }, 112762306a36Sopenharmony_ci .info = { 112862306a36Sopenharmony_ci .name = "Afatech AF9013", 112962306a36Sopenharmony_ci .frequency_min_hz = 174 * MHz, 113062306a36Sopenharmony_ci .frequency_max_hz = 862 * MHz, 113162306a36Sopenharmony_ci .frequency_stepsize_hz = 250 * kHz, 113262306a36Sopenharmony_ci .caps = FE_CAN_FEC_1_2 | 113362306a36Sopenharmony_ci FE_CAN_FEC_2_3 | 113462306a36Sopenharmony_ci FE_CAN_FEC_3_4 | 113562306a36Sopenharmony_ci FE_CAN_FEC_5_6 | 113662306a36Sopenharmony_ci FE_CAN_FEC_7_8 | 113762306a36Sopenharmony_ci FE_CAN_FEC_AUTO | 113862306a36Sopenharmony_ci FE_CAN_QPSK | 113962306a36Sopenharmony_ci FE_CAN_QAM_16 | 114062306a36Sopenharmony_ci FE_CAN_QAM_64 | 114162306a36Sopenharmony_ci FE_CAN_QAM_AUTO | 114262306a36Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | 114362306a36Sopenharmony_ci FE_CAN_GUARD_INTERVAL_AUTO | 114462306a36Sopenharmony_ci FE_CAN_HIERARCHY_AUTO | 114562306a36Sopenharmony_ci FE_CAN_RECOVER | 114662306a36Sopenharmony_ci FE_CAN_MUTE_TS 114762306a36Sopenharmony_ci }, 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci .init = af9013_init, 115062306a36Sopenharmony_ci .sleep = af9013_sleep, 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci .get_tune_settings = af9013_get_tune_settings, 115362306a36Sopenharmony_ci .set_frontend = af9013_set_frontend, 115462306a36Sopenharmony_ci .get_frontend = af9013_get_frontend, 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci .read_status = af9013_read_status, 115762306a36Sopenharmony_ci .read_snr = af9013_read_snr, 115862306a36Sopenharmony_ci .read_signal_strength = af9013_read_signal_strength, 115962306a36Sopenharmony_ci .read_ber = af9013_read_ber, 116062306a36Sopenharmony_ci .read_ucblocks = af9013_read_ucblocks, 116162306a36Sopenharmony_ci}; 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_cistatic int af9013_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) 116462306a36Sopenharmony_ci{ 116562306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 116662306a36Sopenharmony_ci struct i2c_client *client = state->client; 116762306a36Sopenharmony_ci int ret; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci dev_dbg(&client->dev, "onoff %d\n", onoff); 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0xd503, 0x01, onoff); 117262306a36Sopenharmony_ci if (ret) 117362306a36Sopenharmony_ci goto err; 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci return 0; 117662306a36Sopenharmony_cierr: 117762306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 117862306a36Sopenharmony_ci return ret; 117962306a36Sopenharmony_ci} 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_cistatic int af9013_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, 118262306a36Sopenharmony_ci int onoff) 118362306a36Sopenharmony_ci{ 118462306a36Sopenharmony_ci struct af9013_state *state = fe->demodulator_priv; 118562306a36Sopenharmony_ci struct i2c_client *client = state->client; 118662306a36Sopenharmony_ci int ret; 118762306a36Sopenharmony_ci u8 buf[2]; 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci dev_dbg(&client->dev, "index %d, pid %04x, onoff %d\n", 119062306a36Sopenharmony_ci index, pid, onoff); 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci if (pid > 0x1fff) { 119362306a36Sopenharmony_ci /* 0x2000 is kernel virtual pid for whole ts (all pids) */ 119462306a36Sopenharmony_ci ret = 0; 119562306a36Sopenharmony_ci goto err; 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci buf[0] = (pid >> 0) & 0xff; 119962306a36Sopenharmony_ci buf[1] = (pid >> 8) & 0xff; 120062306a36Sopenharmony_ci ret = regmap_bulk_write(state->regmap, 0xd505, buf, 2); 120162306a36Sopenharmony_ci if (ret) 120262306a36Sopenharmony_ci goto err; 120362306a36Sopenharmony_ci ret = regmap_write(state->regmap, 0xd504, onoff << 5 | index << 0); 120462306a36Sopenharmony_ci if (ret) 120562306a36Sopenharmony_ci goto err; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci return 0; 120862306a36Sopenharmony_cierr: 120962306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 121062306a36Sopenharmony_ci return ret; 121162306a36Sopenharmony_ci} 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_cistatic struct dvb_frontend *af9013_get_dvb_frontend(struct i2c_client *client) 121462306a36Sopenharmony_ci{ 121562306a36Sopenharmony_ci struct af9013_state *state = i2c_get_clientdata(client); 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci return &state->fe; 122062306a36Sopenharmony_ci} 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cistatic struct i2c_adapter *af9013_get_i2c_adapter(struct i2c_client *client) 122362306a36Sopenharmony_ci{ 122462306a36Sopenharmony_ci struct af9013_state *state = i2c_get_clientdata(client); 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci return state->muxc->adapter[0]; 122962306a36Sopenharmony_ci} 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci/* 123262306a36Sopenharmony_ci * XXX: Hackish solution. We use virtual register, reg bit 16, to carry info 123362306a36Sopenharmony_ci * about i2c adapter locking. Own locking is needed because i2c mux call has 123462306a36Sopenharmony_ci * already locked i2c adapter. 123562306a36Sopenharmony_ci */ 123662306a36Sopenharmony_cistatic int af9013_select(struct i2c_mux_core *muxc, u32 chan) 123762306a36Sopenharmony_ci{ 123862306a36Sopenharmony_ci struct af9013_state *state = i2c_mux_priv(muxc); 123962306a36Sopenharmony_ci struct i2c_client *client = state->client; 124062306a36Sopenharmony_ci int ret; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci if (state->ts_mode == AF9013_TS_MODE_USB) 124562306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0x1d417, 0x08, 0x08); 124662306a36Sopenharmony_ci else 124762306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0x1d607, 0x04, 0x04); 124862306a36Sopenharmony_ci if (ret) 124962306a36Sopenharmony_ci goto err; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci return 0; 125262306a36Sopenharmony_cierr: 125362306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 125462306a36Sopenharmony_ci return ret; 125562306a36Sopenharmony_ci} 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_cistatic int af9013_deselect(struct i2c_mux_core *muxc, u32 chan) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci struct af9013_state *state = i2c_mux_priv(muxc); 126062306a36Sopenharmony_ci struct i2c_client *client = state->client; 126162306a36Sopenharmony_ci int ret; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci if (state->ts_mode == AF9013_TS_MODE_USB) 126662306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0x1d417, 0x08, 0x00); 126762306a36Sopenharmony_ci else 126862306a36Sopenharmony_ci ret = regmap_update_bits(state->regmap, 0x1d607, 0x04, 0x00); 126962306a36Sopenharmony_ci if (ret) 127062306a36Sopenharmony_ci goto err; 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci return 0; 127362306a36Sopenharmony_cierr: 127462306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 127562306a36Sopenharmony_ci return ret; 127662306a36Sopenharmony_ci} 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci/* Own I2C access routines needed for regmap as chip uses extra command byte */ 127962306a36Sopenharmony_cistatic int af9013_wregs(struct i2c_client *client, u8 cmd, u16 reg, 128062306a36Sopenharmony_ci const u8 *val, int len, u8 lock) 128162306a36Sopenharmony_ci{ 128262306a36Sopenharmony_ci int ret; 128362306a36Sopenharmony_ci u8 buf[21]; 128462306a36Sopenharmony_ci struct i2c_msg msg[1] = { 128562306a36Sopenharmony_ci { 128662306a36Sopenharmony_ci .addr = client->addr, 128762306a36Sopenharmony_ci .flags = 0, 128862306a36Sopenharmony_ci .len = 3 + len, 128962306a36Sopenharmony_ci .buf = buf, 129062306a36Sopenharmony_ci } 129162306a36Sopenharmony_ci }; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci if (3 + len > sizeof(buf)) { 129462306a36Sopenharmony_ci ret = -EINVAL; 129562306a36Sopenharmony_ci goto err; 129662306a36Sopenharmony_ci } 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci buf[0] = (reg >> 8) & 0xff; 129962306a36Sopenharmony_ci buf[1] = (reg >> 0) & 0xff; 130062306a36Sopenharmony_ci buf[2] = cmd; 130162306a36Sopenharmony_ci memcpy(&buf[3], val, len); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci if (lock) 130462306a36Sopenharmony_ci i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT); 130562306a36Sopenharmony_ci ret = __i2c_transfer(client->adapter, msg, 1); 130662306a36Sopenharmony_ci if (lock) 130762306a36Sopenharmony_ci i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT); 130862306a36Sopenharmony_ci if (ret < 0) { 130962306a36Sopenharmony_ci goto err; 131062306a36Sopenharmony_ci } else if (ret != 1) { 131162306a36Sopenharmony_ci ret = -EREMOTEIO; 131262306a36Sopenharmony_ci goto err; 131362306a36Sopenharmony_ci } 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci return 0; 131662306a36Sopenharmony_cierr: 131762306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 131862306a36Sopenharmony_ci return ret; 131962306a36Sopenharmony_ci} 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_cistatic int af9013_rregs(struct i2c_client *client, u8 cmd, u16 reg, 132262306a36Sopenharmony_ci u8 *val, int len, u8 lock) 132362306a36Sopenharmony_ci{ 132462306a36Sopenharmony_ci int ret; 132562306a36Sopenharmony_ci u8 buf[3]; 132662306a36Sopenharmony_ci struct i2c_msg msg[2] = { 132762306a36Sopenharmony_ci { 132862306a36Sopenharmony_ci .addr = client->addr, 132962306a36Sopenharmony_ci .flags = 0, 133062306a36Sopenharmony_ci .len = 3, 133162306a36Sopenharmony_ci .buf = buf, 133262306a36Sopenharmony_ci }, { 133362306a36Sopenharmony_ci .addr = client->addr, 133462306a36Sopenharmony_ci .flags = I2C_M_RD, 133562306a36Sopenharmony_ci .len = len, 133662306a36Sopenharmony_ci .buf = val, 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci }; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci buf[0] = (reg >> 8) & 0xff; 134162306a36Sopenharmony_ci buf[1] = (reg >> 0) & 0xff; 134262306a36Sopenharmony_ci buf[2] = cmd; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci if (lock) 134562306a36Sopenharmony_ci i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT); 134662306a36Sopenharmony_ci ret = __i2c_transfer(client->adapter, msg, 2); 134762306a36Sopenharmony_ci if (lock) 134862306a36Sopenharmony_ci i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT); 134962306a36Sopenharmony_ci if (ret < 0) { 135062306a36Sopenharmony_ci goto err; 135162306a36Sopenharmony_ci } else if (ret != 2) { 135262306a36Sopenharmony_ci ret = -EREMOTEIO; 135362306a36Sopenharmony_ci goto err; 135462306a36Sopenharmony_ci } 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci return 0; 135762306a36Sopenharmony_cierr: 135862306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 135962306a36Sopenharmony_ci return ret; 136062306a36Sopenharmony_ci} 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_cistatic int af9013_regmap_write(void *context, const void *data, size_t count) 136362306a36Sopenharmony_ci{ 136462306a36Sopenharmony_ci struct i2c_client *client = context; 136562306a36Sopenharmony_ci struct af9013_state *state = i2c_get_clientdata(client); 136662306a36Sopenharmony_ci int ret, i; 136762306a36Sopenharmony_ci u8 cmd; 136862306a36Sopenharmony_ci u8 lock = !((u8 *)data)[0]; 136962306a36Sopenharmony_ci u16 reg = ((u8 *)data)[1] << 8 | ((u8 *)data)[2] << 0; 137062306a36Sopenharmony_ci u8 *val = &((u8 *)data)[3]; 137162306a36Sopenharmony_ci const unsigned int len = count - 3; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci if (state->ts_mode == AF9013_TS_MODE_USB && (reg & 0xff00) != 0xae00) { 137462306a36Sopenharmony_ci cmd = 0 << 7|0 << 6|(len - 1) << 2|1 << 1|1 << 0; 137562306a36Sopenharmony_ci ret = af9013_wregs(client, cmd, reg, val, len, lock); 137662306a36Sopenharmony_ci if (ret) 137762306a36Sopenharmony_ci goto err; 137862306a36Sopenharmony_ci } else if (reg >= 0x5100 && reg < 0x8fff) { 137962306a36Sopenharmony_ci /* Firmware download */ 138062306a36Sopenharmony_ci cmd = 1 << 7|1 << 6|(len - 1) << 2|1 << 1|1 << 0; 138162306a36Sopenharmony_ci ret = af9013_wregs(client, cmd, reg, val, len, lock); 138262306a36Sopenharmony_ci if (ret) 138362306a36Sopenharmony_ci goto err; 138462306a36Sopenharmony_ci } else { 138562306a36Sopenharmony_ci cmd = 0 << 7|0 << 6|(1 - 1) << 2|1 << 1|1 << 0; 138662306a36Sopenharmony_ci for (i = 0; i < len; i++) { 138762306a36Sopenharmony_ci ret = af9013_wregs(client, cmd, reg + i, val + i, 1, 138862306a36Sopenharmony_ci lock); 138962306a36Sopenharmony_ci if (ret) 139062306a36Sopenharmony_ci goto err; 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci } 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci return 0; 139562306a36Sopenharmony_cierr: 139662306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 139762306a36Sopenharmony_ci return ret; 139862306a36Sopenharmony_ci} 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_cistatic int af9013_regmap_read(void *context, const void *reg_buf, 140162306a36Sopenharmony_ci size_t reg_size, void *val_buf, size_t val_size) 140262306a36Sopenharmony_ci{ 140362306a36Sopenharmony_ci struct i2c_client *client = context; 140462306a36Sopenharmony_ci struct af9013_state *state = i2c_get_clientdata(client); 140562306a36Sopenharmony_ci int ret, i; 140662306a36Sopenharmony_ci u8 cmd; 140762306a36Sopenharmony_ci u8 lock = !((u8 *)reg_buf)[0]; 140862306a36Sopenharmony_ci u16 reg = ((u8 *)reg_buf)[1] << 8 | ((u8 *)reg_buf)[2] << 0; 140962306a36Sopenharmony_ci u8 *val = &((u8 *)val_buf)[0]; 141062306a36Sopenharmony_ci const unsigned int len = val_size; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci if (state->ts_mode == AF9013_TS_MODE_USB && (reg & 0xff00) != 0xae00) { 141362306a36Sopenharmony_ci cmd = 0 << 7|0 << 6|(len - 1) << 2|1 << 1|0 << 0; 141462306a36Sopenharmony_ci ret = af9013_rregs(client, cmd, reg, val_buf, len, lock); 141562306a36Sopenharmony_ci if (ret) 141662306a36Sopenharmony_ci goto err; 141762306a36Sopenharmony_ci } else { 141862306a36Sopenharmony_ci cmd = 0 << 7|0 << 6|(1 - 1) << 2|1 << 1|0 << 0; 141962306a36Sopenharmony_ci for (i = 0; i < len; i++) { 142062306a36Sopenharmony_ci ret = af9013_rregs(client, cmd, reg + i, val + i, 1, 142162306a36Sopenharmony_ci lock); 142262306a36Sopenharmony_ci if (ret) 142362306a36Sopenharmony_ci goto err; 142462306a36Sopenharmony_ci } 142562306a36Sopenharmony_ci } 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci return 0; 142862306a36Sopenharmony_cierr: 142962306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 143062306a36Sopenharmony_ci return ret; 143162306a36Sopenharmony_ci} 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_cistatic int af9013_probe(struct i2c_client *client) 143462306a36Sopenharmony_ci{ 143562306a36Sopenharmony_ci struct af9013_state *state; 143662306a36Sopenharmony_ci struct af9013_platform_data *pdata = client->dev.platform_data; 143762306a36Sopenharmony_ci struct dtv_frontend_properties *c; 143862306a36Sopenharmony_ci int ret, i; 143962306a36Sopenharmony_ci u8 firmware_version[4]; 144062306a36Sopenharmony_ci static const struct regmap_bus regmap_bus = { 144162306a36Sopenharmony_ci .read = af9013_regmap_read, 144262306a36Sopenharmony_ci .write = af9013_regmap_write, 144362306a36Sopenharmony_ci }; 144462306a36Sopenharmony_ci static const struct regmap_config regmap_config = { 144562306a36Sopenharmony_ci /* Actual reg is 16 bits, see i2c adapter lock */ 144662306a36Sopenharmony_ci .reg_bits = 24, 144762306a36Sopenharmony_ci .val_bits = 8, 144862306a36Sopenharmony_ci }; 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci state = kzalloc(sizeof(*state), GFP_KERNEL); 145162306a36Sopenharmony_ci if (!state) { 145262306a36Sopenharmony_ci ret = -ENOMEM; 145362306a36Sopenharmony_ci goto err; 145462306a36Sopenharmony_ci } 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci /* Setup the state */ 145962306a36Sopenharmony_ci state->client = client; 146062306a36Sopenharmony_ci i2c_set_clientdata(client, state); 146162306a36Sopenharmony_ci state->clk = pdata->clk; 146262306a36Sopenharmony_ci state->tuner = pdata->tuner; 146362306a36Sopenharmony_ci state->if_frequency = pdata->if_frequency; 146462306a36Sopenharmony_ci state->ts_mode = pdata->ts_mode; 146562306a36Sopenharmony_ci state->ts_output_pin = pdata->ts_output_pin; 146662306a36Sopenharmony_ci state->spec_inv = pdata->spec_inv; 146762306a36Sopenharmony_ci memcpy(&state->api_version, pdata->api_version, sizeof(state->api_version)); 146862306a36Sopenharmony_ci memcpy(&state->gpio, pdata->gpio, sizeof(state->gpio)); 146962306a36Sopenharmony_ci state->regmap = regmap_init(&client->dev, ®map_bus, client, 147062306a36Sopenharmony_ci ®map_config); 147162306a36Sopenharmony_ci if (IS_ERR(state->regmap)) { 147262306a36Sopenharmony_ci ret = PTR_ERR(state->regmap); 147362306a36Sopenharmony_ci goto err_kfree; 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci /* Create mux i2c adapter */ 147662306a36Sopenharmony_ci state->muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0, 147762306a36Sopenharmony_ci af9013_select, af9013_deselect); 147862306a36Sopenharmony_ci if (!state->muxc) { 147962306a36Sopenharmony_ci ret = -ENOMEM; 148062306a36Sopenharmony_ci goto err_regmap_exit; 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci state->muxc->priv = state; 148362306a36Sopenharmony_ci ret = i2c_mux_add_adapter(state->muxc, 0, 0, 0); 148462306a36Sopenharmony_ci if (ret) 148562306a36Sopenharmony_ci goto err_regmap_exit; 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci /* Download firmware */ 148862306a36Sopenharmony_ci if (state->ts_mode != AF9013_TS_MODE_USB) { 148962306a36Sopenharmony_ci ret = af9013_download_firmware(state); 149062306a36Sopenharmony_ci if (ret) 149162306a36Sopenharmony_ci goto err_i2c_mux_del_adapters; 149262306a36Sopenharmony_ci } 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci /* Firmware version */ 149562306a36Sopenharmony_ci ret = regmap_bulk_read(state->regmap, 0x5103, firmware_version, 149662306a36Sopenharmony_ci sizeof(firmware_version)); 149762306a36Sopenharmony_ci if (ret) 149862306a36Sopenharmony_ci goto err_i2c_mux_del_adapters; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci /* Set GPIOs */ 150162306a36Sopenharmony_ci for (i = 0; i < sizeof(state->gpio); i++) { 150262306a36Sopenharmony_ci ret = af9013_set_gpio(state, i, state->gpio[i]); 150362306a36Sopenharmony_ci if (ret) 150462306a36Sopenharmony_ci goto err_i2c_mux_del_adapters; 150562306a36Sopenharmony_ci } 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci /* Create dvb frontend */ 150862306a36Sopenharmony_ci memcpy(&state->fe.ops, &af9013_ops, sizeof(state->fe.ops)); 150962306a36Sopenharmony_ci state->fe.demodulator_priv = state; 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci /* Setup callbacks */ 151262306a36Sopenharmony_ci pdata->get_dvb_frontend = af9013_get_dvb_frontend; 151362306a36Sopenharmony_ci pdata->get_i2c_adapter = af9013_get_i2c_adapter; 151462306a36Sopenharmony_ci pdata->pid_filter = af9013_pid_filter; 151562306a36Sopenharmony_ci pdata->pid_filter_ctrl = af9013_pid_filter_ctrl; 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci /* Init stats to indicate which stats are supported */ 151862306a36Sopenharmony_ci c = &state->fe.dtv_property_cache; 151962306a36Sopenharmony_ci c->strength.len = 1; 152062306a36Sopenharmony_ci c->cnr.len = 1; 152162306a36Sopenharmony_ci c->post_bit_error.len = 1; 152262306a36Sopenharmony_ci c->post_bit_count.len = 1; 152362306a36Sopenharmony_ci c->block_error.len = 1; 152462306a36Sopenharmony_ci c->block_count.len = 1; 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci dev_info(&client->dev, "Afatech AF9013 successfully attached\n"); 152762306a36Sopenharmony_ci dev_info(&client->dev, "firmware version: %d.%d.%d.%d\n", 152862306a36Sopenharmony_ci firmware_version[0], firmware_version[1], 152962306a36Sopenharmony_ci firmware_version[2], firmware_version[3]); 153062306a36Sopenharmony_ci return 0; 153162306a36Sopenharmony_cierr_i2c_mux_del_adapters: 153262306a36Sopenharmony_ci i2c_mux_del_adapters(state->muxc); 153362306a36Sopenharmony_cierr_regmap_exit: 153462306a36Sopenharmony_ci regmap_exit(state->regmap); 153562306a36Sopenharmony_cierr_kfree: 153662306a36Sopenharmony_ci kfree(state); 153762306a36Sopenharmony_cierr: 153862306a36Sopenharmony_ci dev_dbg(&client->dev, "failed %d\n", ret); 153962306a36Sopenharmony_ci return ret; 154062306a36Sopenharmony_ci} 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_cistatic void af9013_remove(struct i2c_client *client) 154362306a36Sopenharmony_ci{ 154462306a36Sopenharmony_ci struct af9013_state *state = i2c_get_clientdata(client); 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci dev_dbg(&client->dev, "\n"); 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci i2c_mux_del_adapters(state->muxc); 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci regmap_exit(state->regmap); 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci kfree(state); 155362306a36Sopenharmony_ci} 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_cistatic const struct i2c_device_id af9013_id_table[] = { 155662306a36Sopenharmony_ci {"af9013", 0}, 155762306a36Sopenharmony_ci {} 155862306a36Sopenharmony_ci}; 155962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, af9013_id_table); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_cistatic struct i2c_driver af9013_driver = { 156262306a36Sopenharmony_ci .driver = { 156362306a36Sopenharmony_ci .name = "af9013", 156462306a36Sopenharmony_ci .suppress_bind_attrs = true, 156562306a36Sopenharmony_ci }, 156662306a36Sopenharmony_ci .probe = af9013_probe, 156762306a36Sopenharmony_ci .remove = af9013_remove, 156862306a36Sopenharmony_ci .id_table = af9013_id_table, 156962306a36Sopenharmony_ci}; 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_cimodule_i2c_driver(af9013_driver); 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ciMODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 157462306a36Sopenharmony_ciMODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver"); 157562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 157662306a36Sopenharmony_ciMODULE_FIRMWARE(AF9013_FIRMWARE); 1577