1 /* 2 * Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator 3 * ATBM8830, ATBM8831 4 * 5 * Copyright (C) 2009 David T.L. Wong <davidtlwong@gmail.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #include <asm/div64.h> 23 #include "dvb_frontend.h" 24 25 #include "atbm8830.h" 26 #include "atbm8830_priv.h" 27 28 #define dprintk(args...) \ 29 do { \ 30 if (debug) \ 31 printk(KERN_DEBUG "atbm8830: " args); \ 32 } while (0) 33 34 static int debug; 35 36 module_param(debug, int, 0644); 37 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 38 39 static int atbm8830_write_reg(struct atbm_state *priv, u16 reg, u8 data) 40 { 41 int ret = 0; 42 u8 dev_addr; 43 u8 buf1[] = { reg >> 8, reg & 0xFF }; 44 u8 buf2[] = { data }; 45 struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 }; 46 struct i2c_msg msg2 = { .flags = 0, .buf = buf2, .len = 1 }; 47 48 dev_addr = priv->config->demod_address; 49 msg1.addr = dev_addr; 50 msg2.addr = dev_addr; 51 52 if (debug >= 2) 53 dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, data); 54 55 ret = i2c_transfer(priv->i2c, &msg1, 1); 56 if (ret != 1) 57 return -EIO; 58 59 ret = i2c_transfer(priv->i2c, &msg2, 1); 60 return (ret != 1) ? -EIO : 0; 61 } 62 63 static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data) 64 { 65 int ret; 66 u8 dev_addr; 67 68 u8 buf1[] = { reg >> 8, reg & 0xFF }; 69 u8 buf2[] = { 0 }; 70 struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 }; 71 struct i2c_msg msg2 = { .flags = I2C_M_RD, .buf = buf2, .len = 1 }; 72 73 dev_addr = priv->config->demod_address; 74 msg1.addr = dev_addr; 75 msg2.addr = dev_addr; 76 77 ret = i2c_transfer(priv->i2c, &msg1, 1); 78 if (ret != 1) { 79 dprintk("%s: error reg=0x%04x, ret=%i\n", __func__, reg, ret); 80 return -EIO; 81 } 82 83 ret = i2c_transfer(priv->i2c, &msg2, 1); 84 if (ret != 1) 85 return -EIO; 86 87 *p_data = buf2[0]; 88 if (debug >= 2) 89 dprintk("%s: reg=0x%04X, data=0x%02X\n", 90 __func__, reg, buf2[0]); 91 92 return 0; 93 } 94 95 /* Lock register latch so that multi-register read is atomic */ 96 static inline int atbm8830_reglatch_lock(struct atbm_state *priv, int lock) 97 { 98 return atbm8830_write_reg(priv, REG_READ_LATCH, lock ? 1 : 0); 99 } 100 101 static int set_osc_freq(struct atbm_state *priv, u32 freq /*in kHz*/) 102 { 103 u32 val; 104 u64 t; 105 106 /* 0x100000 * freq / 30.4MHz */ 107 t = (u64)0x100000 * freq; 108 do_div(t, 30400); 109 val = t; 110 111 atbm8830_write_reg(priv, REG_OSC_CLK, val); 112 atbm8830_write_reg(priv, REG_OSC_CLK + 1, val >> 8); 113 atbm8830_write_reg(priv, REG_OSC_CLK + 2, val >> 16); 114 115 return 0; 116 } 117 118 static int set_if_freq(struct atbm_state *priv, u32 freq /*in kHz*/) 119 { 120 121 u32 fs = priv->config->osc_clk_freq; 122 u64 t; 123 u32 val; 124 u8 dat; 125 126 if (freq != 0) { 127 /* 2 * PI * (freq - fs) / fs * (2 ^ 22) */ 128 t = (u64) 2 * 31416 * (freq - fs); 129 t <<= 22; 130 do_div(t, fs); 131 do_div(t, 1000); 132 val = t; 133 134 atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 1); 135 atbm8830_write_reg(priv, REG_IF_FREQ, val); 136 atbm8830_write_reg(priv, REG_IF_FREQ+1, val >> 8); 137 atbm8830_write_reg(priv, REG_IF_FREQ+2, val >> 16); 138 139 atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat); 140 dat &= 0xFC; 141 atbm8830_write_reg(priv, REG_ADC_CONFIG, dat); 142 } else { 143 /* Zero IF */ 144 atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 0); 145 146 atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat); 147 dat &= 0xFC; 148 dat |= 0x02; 149 atbm8830_write_reg(priv, REG_ADC_CONFIG, dat); 150 151 if (priv->config->zif_swap_iq) 152 atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x03); 153 else 154 atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x01); 155 } 156 157 return 0; 158 } 159 160 static int is_locked(struct atbm_state *priv, u8 *locked) 161 { 162 u8 status; 163 164 atbm8830_read_reg(priv, REG_LOCK_STATUS, &status); 165 166 if (locked != NULL) 167 *locked = (status == 1); 168 return 0; 169 } 170 171 static int set_agc_config(struct atbm_state *priv, 172 u8 min, u8 max, u8 hold_loop) 173 { 174 /* no effect if both min and max are zero */ 175 if (!min && !max) 176 return 0; 177 178 atbm8830_write_reg(priv, REG_AGC_MIN, min); 179 atbm8830_write_reg(priv, REG_AGC_MAX, max); 180 atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop); 181 182 return 0; 183 } 184 185 static int set_static_channel_mode(struct atbm_state *priv) 186 { 187 int i; 188 189 for (i = 0; i < 5; i++) 190 atbm8830_write_reg(priv, 0x099B + i, 0x08); 191 192 atbm8830_write_reg(priv, 0x095B, 0x7F); 193 atbm8830_write_reg(priv, 0x09CB, 0x01); 194 atbm8830_write_reg(priv, 0x09CC, 0x7F); 195 atbm8830_write_reg(priv, 0x09CD, 0x7F); 196 atbm8830_write_reg(priv, 0x0E01, 0x20); 197 198 /* For single carrier */ 199 atbm8830_write_reg(priv, 0x0B03, 0x0A); 200 atbm8830_write_reg(priv, 0x0935, 0x10); 201 atbm8830_write_reg(priv, 0x0936, 0x08); 202 atbm8830_write_reg(priv, 0x093E, 0x08); 203 atbm8830_write_reg(priv, 0x096E, 0x06); 204 205 /* frame_count_max0 */ 206 atbm8830_write_reg(priv, 0x0B09, 0x00); 207 /* frame_count_max1 */ 208 atbm8830_write_reg(priv, 0x0B0A, 0x08); 209 210 return 0; 211 } 212 213 static int set_ts_config(struct atbm_state *priv) 214 { 215 const struct atbm8830_config *cfg = priv->config; 216 217 /*Set parallel/serial ts mode*/ 218 atbm8830_write_reg(priv, REG_TS_SERIAL, cfg->serial_ts ? 1 : 0); 219 atbm8830_write_reg(priv, REG_TS_CLK_MODE, cfg->serial_ts ? 1 : 0); 220 /*Set ts sampling edge*/ 221 atbm8830_write_reg(priv, REG_TS_SAMPLE_EDGE, 222 cfg->ts_sampling_edge ? 1 : 0); 223 /*Set ts clock freerun*/ 224 atbm8830_write_reg(priv, REG_TS_CLK_FREERUN, 225 cfg->ts_clk_gated ? 0 : 1); 226 227 return 0; 228 } 229 230 static int atbm8830_init(struct dvb_frontend *fe) 231 { 232 struct atbm_state *priv = fe->demodulator_priv; 233 const struct atbm8830_config *cfg = priv->config; 234 235 /*Set oscillator frequency*/ 236 set_osc_freq(priv, cfg->osc_clk_freq); 237 238 /*Set IF frequency*/ 239 set_if_freq(priv, cfg->if_freq); 240 241 /*Set AGC Config*/ 242 set_agc_config(priv, cfg->agc_min, cfg->agc_max, 243 cfg->agc_hold_loop); 244 245 /*Set static channel mode*/ 246 set_static_channel_mode(priv); 247 248 set_ts_config(priv); 249 /*Turn off DSP reset*/ 250 atbm8830_write_reg(priv, 0x000A, 0); 251 252 /*SW version test*/ 253 atbm8830_write_reg(priv, 0x020C, 11); 254 255 /* Run */ 256 atbm8830_write_reg(priv, REG_DEMOD_RUN, 1); 257 258 return 0; 259 } 260 261 262 static void atbm8830_release(struct dvb_frontend *fe) 263 { 264 struct atbm_state *state = fe->demodulator_priv; 265 dprintk("%s\n", __func__); 266 267 kfree(state); 268 } 269 270 static int atbm8830_set_fe(struct dvb_frontend *fe) 271 { 272 struct atbm_state *priv = fe->demodulator_priv; 273 int i; 274 u8 locked = 0; 275 dprintk("%s\n", __func__); 276 277 /* set frequency */ 278 if (fe->ops.tuner_ops.set_params) { 279 if (fe->ops.i2c_gate_ctrl) 280 fe->ops.i2c_gate_ctrl(fe, 1); 281 fe->ops.tuner_ops.set_params(fe); 282 if (fe->ops.i2c_gate_ctrl) 283 fe->ops.i2c_gate_ctrl(fe, 0); 284 } 285 286 /* start auto lock */ 287 for (i = 0; i < 10; i++) { 288 mdelay(100); 289 dprintk("Try %d\n", i); 290 is_locked(priv, &locked); 291 if (locked != 0) { 292 dprintk("ATBM8830 locked!\n"); 293 break; 294 } 295 } 296 297 return 0; 298 } 299 300 static int atbm8830_get_fe(struct dvb_frontend *fe) 301 { 302 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 303 dprintk("%s\n", __func__); 304 305 /* TODO: get real readings from device */ 306 /* inversion status */ 307 c->inversion = INVERSION_OFF; 308 309 /* bandwidth */ 310 c->bandwidth_hz = 8000000; 311 312 c->code_rate_HP = FEC_AUTO; 313 c->code_rate_LP = FEC_AUTO; 314 315 c->modulation = QAM_AUTO; 316 317 /* transmission mode */ 318 c->transmission_mode = TRANSMISSION_MODE_AUTO; 319 320 /* guard interval */ 321 c->guard_interval = GUARD_INTERVAL_AUTO; 322 323 /* hierarchy */ 324 c->hierarchy = HIERARCHY_NONE; 325 326 return 0; 327 } 328 329 static int atbm8830_get_tune_settings(struct dvb_frontend *fe, 330 struct dvb_frontend_tune_settings *fesettings) 331 { 332 fesettings->min_delay_ms = 0; 333 fesettings->step_size = 0; 334 fesettings->max_drift = 0; 335 return 0; 336 } 337 338 static int atbm8830_read_status(struct dvb_frontend *fe, fe_status_t *fe_status) 339 { 340 struct atbm_state *priv = fe->demodulator_priv; 341 u8 locked = 0; 342 u8 agc_locked = 0; 343 344 dprintk("%s\n", __func__); 345 *fe_status = 0; 346 347 is_locked(priv, &locked); 348 if (locked) { 349 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 350 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 351 } 352 dprintk("%s: fe_status=0x%x\n", __func__, *fe_status); 353 354 atbm8830_read_reg(priv, REG_AGC_LOCK, &agc_locked); 355 dprintk("AGC Lock: %d\n", agc_locked); 356 357 return 0; 358 } 359 360 static int atbm8830_read_ber(struct dvb_frontend *fe, u32 *ber) 361 { 362 struct atbm_state *priv = fe->demodulator_priv; 363 u32 frame_err; 364 u8 t; 365 366 dprintk("%s\n", __func__); 367 368 atbm8830_reglatch_lock(priv, 1); 369 370 atbm8830_read_reg(priv, REG_FRAME_ERR_CNT + 1, &t); 371 frame_err = t & 0x7F; 372 frame_err <<= 8; 373 atbm8830_read_reg(priv, REG_FRAME_ERR_CNT, &t); 374 frame_err |= t; 375 376 atbm8830_reglatch_lock(priv, 0); 377 378 *ber = frame_err * 100 / 32767; 379 380 dprintk("%s: ber=0x%x\n", __func__, *ber); 381 return 0; 382 } 383 384 static int atbm8830_read_signal_strength(struct dvb_frontend *fe, u16 *signal) 385 { 386 struct atbm_state *priv = fe->demodulator_priv; 387 u32 pwm; 388 u8 t; 389 390 dprintk("%s\n", __func__); 391 atbm8830_reglatch_lock(priv, 1); 392 393 atbm8830_read_reg(priv, REG_AGC_PWM_VAL + 1, &t); 394 pwm = t & 0x03; 395 pwm <<= 8; 396 atbm8830_read_reg(priv, REG_AGC_PWM_VAL, &t); 397 pwm |= t; 398 399 atbm8830_reglatch_lock(priv, 0); 400 401 dprintk("AGC PWM = 0x%02X\n", pwm); 402 pwm = 0x400 - pwm; 403 404 *signal = pwm * 0x10000 / 0x400; 405 406 return 0; 407 } 408 409 static int atbm8830_read_snr(struct dvb_frontend *fe, u16 *snr) 410 { 411 dprintk("%s\n", __func__); 412 *snr = 0; 413 return 0; 414 } 415 416 static int atbm8830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 417 { 418 dprintk("%s\n", __func__); 419 *ucblocks = 0; 420 return 0; 421 } 422 423 static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 424 { 425 struct atbm_state *priv = fe->demodulator_priv; 426 427 return atbm8830_write_reg(priv, REG_I2C_GATE, enable ? 1 : 0); 428 } 429 430 static struct dvb_frontend_ops atbm8830_ops = { 431 .delsys = { SYS_DTMB }, 432 .info = { 433 .name = "AltoBeam ATBM8830/8831 DMB-TH", 434 .frequency_min = 474000000, 435 .frequency_max = 858000000, 436 .frequency_stepsize = 10000, 437 .caps = 438 FE_CAN_FEC_AUTO | 439 FE_CAN_QAM_AUTO | 440 FE_CAN_TRANSMISSION_MODE_AUTO | 441 FE_CAN_GUARD_INTERVAL_AUTO 442 }, 443 444 .release = atbm8830_release, 445 446 .init = atbm8830_init, 447 .sleep = NULL, 448 .write = NULL, 449 .i2c_gate_ctrl = atbm8830_i2c_gate_ctrl, 450 451 .set_frontend = atbm8830_set_fe, 452 .get_frontend = atbm8830_get_fe, 453 .get_tune_settings = atbm8830_get_tune_settings, 454 455 .read_status = atbm8830_read_status, 456 .read_ber = atbm8830_read_ber, 457 .read_signal_strength = atbm8830_read_signal_strength, 458 .read_snr = atbm8830_read_snr, 459 .read_ucblocks = atbm8830_read_ucblocks, 460 }; 461 462 struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config, 463 struct i2c_adapter *i2c) 464 { 465 struct atbm_state *priv = NULL; 466 u8 data = 0; 467 468 dprintk("%s()\n", __func__); 469 470 if (config == NULL || i2c == NULL) 471 return NULL; 472 473 priv = kzalloc(sizeof(struct atbm_state), GFP_KERNEL); 474 if (priv == NULL) 475 goto error_out; 476 477 priv->config = config; 478 priv->i2c = i2c; 479 480 /* check if the demod is there */ 481 if (atbm8830_read_reg(priv, REG_CHIP_ID, &data) != 0) { 482 dprintk("%s atbm8830/8831 not found at i2c addr 0x%02X\n", 483 __func__, priv->config->demod_address); 484 goto error_out; 485 } 486 dprintk("atbm8830 chip id: 0x%02X\n", data); 487 488 memcpy(&priv->frontend.ops, &atbm8830_ops, 489 sizeof(struct dvb_frontend_ops)); 490 priv->frontend.demodulator_priv = priv; 491 492 atbm8830_init(&priv->frontend); 493 494 atbm8830_i2c_gate_ctrl(&priv->frontend, 1); 495 496 return &priv->frontend; 497 498 error_out: 499 dprintk("%s() error_out\n", __func__); 500 kfree(priv); 501 return NULL; 502 503 } 504 EXPORT_SYMBOL(atbm8830_attach); 505 506 MODULE_DESCRIPTION("AltoBeam ATBM8830/8831 GB20600 demodulator driver"); 507 MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>"); 508 MODULE_LICENSE("GPL"); 509