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