Michael Krufky | 59067f7 | 2008-01-02 01:58:26 -0300 | [diff] [blame] | 1 | /* |
| 2 | tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner |
| 3 | |
| 4 | Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org> |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 2 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | This program is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License |
| 17 | along with this program; if not, write to the Free Software |
| 18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 19 | */ |
| 20 | |
| 21 | #include "tda18271-priv.h" |
| 22 | |
| 23 | static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) |
| 24 | { |
| 25 | struct tda18271_priv *priv = fe->tuner_priv; |
| 26 | enum tda18271_i2c_gate gate; |
| 27 | int ret = 0; |
| 28 | |
| 29 | switch (priv->gate) { |
| 30 | case TDA18271_GATE_DIGITAL: |
| 31 | case TDA18271_GATE_ANALOG: |
| 32 | gate = priv->gate; |
| 33 | break; |
| 34 | case TDA18271_GATE_AUTO: |
| 35 | default: |
| 36 | switch (priv->mode) { |
| 37 | case TDA18271_DIGITAL: |
| 38 | gate = TDA18271_GATE_DIGITAL; |
| 39 | break; |
| 40 | case TDA18271_ANALOG: |
| 41 | default: |
| 42 | gate = TDA18271_GATE_ANALOG; |
| 43 | break; |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | switch (gate) { |
| 48 | case TDA18271_GATE_ANALOG: |
| 49 | if (fe->ops.analog_ops.i2c_gate_ctrl) |
| 50 | ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable); |
| 51 | break; |
| 52 | case TDA18271_GATE_DIGITAL: |
| 53 | if (fe->ops.i2c_gate_ctrl) |
| 54 | ret = fe->ops.i2c_gate_ctrl(fe, enable); |
| 55 | break; |
| 56 | default: |
| 57 | ret = -EINVAL; |
| 58 | break; |
| 59 | } |
| 60 | |
| 61 | return ret; |
| 62 | }; |
| 63 | |
| 64 | /*---------------------------------------------------------------------*/ |
| 65 | |
| 66 | static void tda18271_dump_regs(struct dvb_frontend *fe, int extended) |
| 67 | { |
| 68 | struct tda18271_priv *priv = fe->tuner_priv; |
| 69 | unsigned char *regs = priv->tda18271_regs; |
| 70 | |
| 71 | tda_reg("=== TDA18271 REG DUMP ===\n"); |
| 72 | tda_reg("ID_BYTE = 0x%02x\n", 0xff & regs[R_ID]); |
| 73 | tda_reg("THERMO_BYTE = 0x%02x\n", 0xff & regs[R_TM]); |
| 74 | tda_reg("POWER_LEVEL_BYTE = 0x%02x\n", 0xff & regs[R_PL]); |
| 75 | tda_reg("EASY_PROG_BYTE_1 = 0x%02x\n", 0xff & regs[R_EP1]); |
| 76 | tda_reg("EASY_PROG_BYTE_2 = 0x%02x\n", 0xff & regs[R_EP2]); |
| 77 | tda_reg("EASY_PROG_BYTE_3 = 0x%02x\n", 0xff & regs[R_EP3]); |
| 78 | tda_reg("EASY_PROG_BYTE_4 = 0x%02x\n", 0xff & regs[R_EP4]); |
| 79 | tda_reg("EASY_PROG_BYTE_5 = 0x%02x\n", 0xff & regs[R_EP5]); |
| 80 | tda_reg("CAL_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_CPD]); |
| 81 | tda_reg("CAL_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_CD1]); |
| 82 | tda_reg("CAL_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_CD2]); |
| 83 | tda_reg("CAL_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_CD3]); |
| 84 | tda_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]); |
| 85 | tda_reg("MAIN_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_MD1]); |
| 86 | tda_reg("MAIN_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_MD2]); |
| 87 | tda_reg("MAIN_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_MD3]); |
| 88 | |
| 89 | /* only dump extended regs if DBG_ADV is set */ |
| 90 | if (!(tda18271_debug & DBG_ADV)) |
| 91 | return; |
| 92 | |
| 93 | /* W indicates write-only registers. |
| 94 | * Register dump for write-only registers shows last value written. */ |
| 95 | |
| 96 | tda_reg("EXTENDED_BYTE_1 = 0x%02x\n", 0xff & regs[R_EB1]); |
| 97 | tda_reg("EXTENDED_BYTE_2 = 0x%02x\n", 0xff & regs[R_EB2]); |
| 98 | tda_reg("EXTENDED_BYTE_3 = 0x%02x\n", 0xff & regs[R_EB3]); |
| 99 | tda_reg("EXTENDED_BYTE_4 = 0x%02x\n", 0xff & regs[R_EB4]); |
| 100 | tda_reg("EXTENDED_BYTE_5 = 0x%02x\n", 0xff & regs[R_EB5]); |
| 101 | tda_reg("EXTENDED_BYTE_6 = 0x%02x\n", 0xff & regs[R_EB6]); |
| 102 | tda_reg("EXTENDED_BYTE_7 = 0x%02x\n", 0xff & regs[R_EB7]); |
| 103 | tda_reg("EXTENDED_BYTE_8 = 0x%02x\n", 0xff & regs[R_EB8]); |
| 104 | tda_reg("EXTENDED_BYTE_9 W = 0x%02x\n", 0xff & regs[R_EB9]); |
| 105 | tda_reg("EXTENDED_BYTE_10 = 0x%02x\n", 0xff & regs[R_EB10]); |
| 106 | tda_reg("EXTENDED_BYTE_11 = 0x%02x\n", 0xff & regs[R_EB11]); |
| 107 | tda_reg("EXTENDED_BYTE_12 = 0x%02x\n", 0xff & regs[R_EB12]); |
| 108 | tda_reg("EXTENDED_BYTE_13 = 0x%02x\n", 0xff & regs[R_EB13]); |
| 109 | tda_reg("EXTENDED_BYTE_14 = 0x%02x\n", 0xff & regs[R_EB14]); |
| 110 | tda_reg("EXTENDED_BYTE_15 = 0x%02x\n", 0xff & regs[R_EB15]); |
| 111 | tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]); |
| 112 | tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]); |
| 113 | tda_reg("EXTENDED_BYTE_18 = 0x%02x\n", 0xff & regs[R_EB18]); |
| 114 | tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]); |
| 115 | tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]); |
| 116 | tda_reg("EXTENDED_BYTE_21 = 0x%02x\n", 0xff & regs[R_EB21]); |
| 117 | tda_reg("EXTENDED_BYTE_22 = 0x%02x\n", 0xff & regs[R_EB22]); |
| 118 | tda_reg("EXTENDED_BYTE_23 = 0x%02x\n", 0xff & regs[R_EB23]); |
| 119 | } |
| 120 | |
| 121 | int tda18271_read_regs(struct dvb_frontend *fe) |
| 122 | { |
| 123 | struct tda18271_priv *priv = fe->tuner_priv; |
| 124 | unsigned char *regs = priv->tda18271_regs; |
| 125 | unsigned char buf = 0x00; |
| 126 | int ret; |
| 127 | struct i2c_msg msg[] = { |
| 128 | { .addr = priv->i2c_addr, .flags = 0, |
| 129 | .buf = &buf, .len = 1 }, |
| 130 | { .addr = priv->i2c_addr, .flags = I2C_M_RD, |
| 131 | .buf = regs, .len = 16 } |
| 132 | }; |
| 133 | |
| 134 | tda18271_i2c_gate_ctrl(fe, 1); |
| 135 | |
| 136 | /* read all registers */ |
| 137 | ret = i2c_transfer(priv->i2c_adap, msg, 2); |
| 138 | |
| 139 | tda18271_i2c_gate_ctrl(fe, 0); |
| 140 | |
| 141 | if (ret != 2) |
| 142 | tda_err("ERROR: i2c_transfer returned: %d\n", ret); |
| 143 | |
| 144 | if (tda18271_debug & DBG_REG) |
| 145 | tda18271_dump_regs(fe, 0); |
| 146 | |
| 147 | return (ret == 2 ? 0 : ret); |
| 148 | } |
| 149 | |
| 150 | int tda18271_read_extended(struct dvb_frontend *fe) |
| 151 | { |
| 152 | struct tda18271_priv *priv = fe->tuner_priv; |
| 153 | unsigned char *regs = priv->tda18271_regs; |
| 154 | unsigned char regdump[TDA18271_NUM_REGS]; |
| 155 | unsigned char buf = 0x00; |
| 156 | int ret, i; |
| 157 | struct i2c_msg msg[] = { |
| 158 | { .addr = priv->i2c_addr, .flags = 0, |
| 159 | .buf = &buf, .len = 1 }, |
| 160 | { .addr = priv->i2c_addr, .flags = I2C_M_RD, |
| 161 | .buf = regdump, .len = TDA18271_NUM_REGS } |
| 162 | }; |
| 163 | |
| 164 | tda18271_i2c_gate_ctrl(fe, 1); |
| 165 | |
| 166 | /* read all registers */ |
| 167 | ret = i2c_transfer(priv->i2c_adap, msg, 2); |
| 168 | |
| 169 | tda18271_i2c_gate_ctrl(fe, 0); |
| 170 | |
| 171 | if (ret != 2) |
| 172 | tda_err("ERROR: i2c_transfer returned: %d\n", ret); |
| 173 | |
| 174 | for (i = 0; i <= TDA18271_NUM_REGS; i++) { |
| 175 | /* don't update write-only registers */ |
| 176 | if ((i != R_EB9) && |
| 177 | (i != R_EB16) && |
| 178 | (i != R_EB17) && |
| 179 | (i != R_EB19) && |
| 180 | (i != R_EB20)) |
| 181 | regs[i] = regdump[i]; |
| 182 | } |
| 183 | |
| 184 | if (tda18271_debug & DBG_REG) |
| 185 | tda18271_dump_regs(fe, 1); |
| 186 | |
| 187 | return (ret == 2 ? 0 : ret); |
| 188 | } |
| 189 | |
| 190 | int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) |
| 191 | { |
| 192 | struct tda18271_priv *priv = fe->tuner_priv; |
| 193 | unsigned char *regs = priv->tda18271_regs; |
| 194 | unsigned char buf[TDA18271_NUM_REGS + 1]; |
| 195 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, |
| 196 | .buf = buf, .len = len + 1 }; |
| 197 | int i, ret; |
| 198 | |
| 199 | BUG_ON((len == 0) || (idx + len > sizeof(buf))); |
| 200 | |
| 201 | buf[0] = idx; |
| 202 | for (i = 1; i <= len; i++) |
| 203 | buf[i] = regs[idx - 1 + i]; |
| 204 | |
| 205 | tda18271_i2c_gate_ctrl(fe, 1); |
| 206 | |
| 207 | /* write registers */ |
| 208 | ret = i2c_transfer(priv->i2c_adap, &msg, 1); |
| 209 | |
| 210 | tda18271_i2c_gate_ctrl(fe, 0); |
| 211 | |
| 212 | if (ret != 1) |
| 213 | tda_err("ERROR: i2c_transfer returned: %d\n", ret); |
| 214 | |
| 215 | return (ret == 1 ? 0 : ret); |
| 216 | } |
| 217 | |
| 218 | /*---------------------------------------------------------------------*/ |
| 219 | |
| 220 | int tda18271_init_regs(struct dvb_frontend *fe) |
| 221 | { |
| 222 | struct tda18271_priv *priv = fe->tuner_priv; |
| 223 | unsigned char *regs = priv->tda18271_regs; |
| 224 | |
| 225 | tda_dbg("initializing registers for device @ %d-%04x\n", |
| 226 | i2c_adapter_id(priv->i2c_adap), priv->i2c_addr); |
| 227 | |
| 228 | /* initialize registers */ |
| 229 | switch (priv->id) { |
| 230 | case TDA18271HDC1: |
| 231 | regs[R_ID] = 0x83; |
| 232 | break; |
| 233 | case TDA18271HDC2: |
| 234 | regs[R_ID] = 0x84; |
| 235 | break; |
| 236 | }; |
| 237 | |
| 238 | regs[R_TM] = 0x08; |
| 239 | regs[R_PL] = 0x80; |
| 240 | regs[R_EP1] = 0xc6; |
| 241 | regs[R_EP2] = 0xdf; |
| 242 | regs[R_EP3] = 0x16; |
| 243 | regs[R_EP4] = 0x60; |
| 244 | regs[R_EP5] = 0x80; |
| 245 | regs[R_CPD] = 0x80; |
| 246 | regs[R_CD1] = 0x00; |
| 247 | regs[R_CD2] = 0x00; |
| 248 | regs[R_CD3] = 0x00; |
| 249 | regs[R_MPD] = 0x00; |
| 250 | regs[R_MD1] = 0x00; |
| 251 | regs[R_MD2] = 0x00; |
| 252 | regs[R_MD3] = 0x00; |
| 253 | |
| 254 | switch (priv->id) { |
| 255 | case TDA18271HDC1: |
| 256 | regs[R_EB1] = 0xff; |
| 257 | break; |
| 258 | case TDA18271HDC2: |
| 259 | regs[R_EB1] = 0xfc; |
| 260 | break; |
| 261 | }; |
| 262 | |
| 263 | regs[R_EB2] = 0x01; |
| 264 | regs[R_EB3] = 0x84; |
| 265 | regs[R_EB4] = 0x41; |
| 266 | regs[R_EB5] = 0x01; |
| 267 | regs[R_EB6] = 0x84; |
| 268 | regs[R_EB7] = 0x40; |
| 269 | regs[R_EB8] = 0x07; |
| 270 | regs[R_EB9] = 0x00; |
| 271 | regs[R_EB10] = 0x00; |
| 272 | regs[R_EB11] = 0x96; |
| 273 | |
| 274 | switch (priv->id) { |
| 275 | case TDA18271HDC1: |
| 276 | regs[R_EB12] = 0x0f; |
| 277 | break; |
| 278 | case TDA18271HDC2: |
| 279 | regs[R_EB12] = 0x33; |
| 280 | break; |
| 281 | }; |
| 282 | |
| 283 | regs[R_EB13] = 0xc1; |
| 284 | regs[R_EB14] = 0x00; |
| 285 | regs[R_EB15] = 0x8f; |
| 286 | regs[R_EB16] = 0x00; |
| 287 | regs[R_EB17] = 0x00; |
| 288 | |
| 289 | switch (priv->id) { |
| 290 | case TDA18271HDC1: |
| 291 | regs[R_EB18] = 0x00; |
| 292 | break; |
| 293 | case TDA18271HDC2: |
| 294 | regs[R_EB18] = 0x8c; |
| 295 | break; |
| 296 | }; |
| 297 | |
| 298 | regs[R_EB19] = 0x00; |
| 299 | regs[R_EB20] = 0x20; |
| 300 | |
| 301 | switch (priv->id) { |
| 302 | case TDA18271HDC1: |
| 303 | regs[R_EB21] = 0x33; |
| 304 | break; |
| 305 | case TDA18271HDC2: |
| 306 | regs[R_EB21] = 0xb3; |
| 307 | break; |
| 308 | }; |
| 309 | |
| 310 | regs[R_EB22] = 0x48; |
| 311 | regs[R_EB23] = 0xb0; |
| 312 | |
| 313 | tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); |
| 314 | |
| 315 | /* setup agc1 gain */ |
| 316 | regs[R_EB17] = 0x00; |
| 317 | tda18271_write_regs(fe, R_EB17, 1); |
| 318 | regs[R_EB17] = 0x03; |
| 319 | tda18271_write_regs(fe, R_EB17, 1); |
| 320 | regs[R_EB17] = 0x43; |
| 321 | tda18271_write_regs(fe, R_EB17, 1); |
| 322 | regs[R_EB17] = 0x4c; |
| 323 | tda18271_write_regs(fe, R_EB17, 1); |
| 324 | |
| 325 | /* setup agc2 gain */ |
| 326 | if ((priv->id) == TDA18271HDC1) { |
| 327 | regs[R_EB20] = 0xa0; |
| 328 | tda18271_write_regs(fe, R_EB20, 1); |
| 329 | regs[R_EB20] = 0xa7; |
| 330 | tda18271_write_regs(fe, R_EB20, 1); |
| 331 | regs[R_EB20] = 0xe7; |
| 332 | tda18271_write_regs(fe, R_EB20, 1); |
| 333 | regs[R_EB20] = 0xec; |
| 334 | tda18271_write_regs(fe, R_EB20, 1); |
| 335 | } |
| 336 | |
| 337 | /* image rejection calibration */ |
| 338 | |
| 339 | /* low-band */ |
| 340 | regs[R_EP3] = 0x1f; |
| 341 | regs[R_EP4] = 0x66; |
| 342 | regs[R_EP5] = 0x81; |
| 343 | regs[R_CPD] = 0xcc; |
| 344 | regs[R_CD1] = 0x6c; |
| 345 | regs[R_CD2] = 0x00; |
| 346 | regs[R_CD3] = 0x00; |
| 347 | regs[R_MPD] = 0xcd; |
| 348 | regs[R_MD1] = 0x77; |
| 349 | regs[R_MD2] = 0x08; |
| 350 | regs[R_MD3] = 0x00; |
| 351 | |
| 352 | switch (priv->id) { |
| 353 | case TDA18271HDC1: |
| 354 | tda18271_write_regs(fe, R_EP3, 11); |
| 355 | break; |
| 356 | case TDA18271HDC2: |
| 357 | tda18271_write_regs(fe, R_EP3, 12); |
| 358 | break; |
| 359 | }; |
| 360 | |
| 361 | if ((priv->id) == TDA18271HDC2) { |
| 362 | /* main pll cp source on */ |
| 363 | regs[R_EB4] = 0x61; |
| 364 | tda18271_write_regs(fe, R_EB4, 1); |
| 365 | msleep(1); |
| 366 | |
| 367 | /* main pll cp source off */ |
| 368 | regs[R_EB4] = 0x41; |
| 369 | tda18271_write_regs(fe, R_EB4, 1); |
| 370 | } |
| 371 | |
| 372 | msleep(5); /* pll locking */ |
| 373 | |
| 374 | /* launch detector */ |
| 375 | tda18271_write_regs(fe, R_EP1, 1); |
| 376 | msleep(5); /* wanted low measurement */ |
| 377 | |
| 378 | regs[R_EP5] = 0x85; |
| 379 | regs[R_CPD] = 0xcb; |
| 380 | regs[R_CD1] = 0x66; |
| 381 | regs[R_CD2] = 0x70; |
| 382 | |
| 383 | tda18271_write_regs(fe, R_EP3, 7); |
| 384 | msleep(5); /* pll locking */ |
| 385 | |
| 386 | /* launch optimization algorithm */ |
| 387 | tda18271_write_regs(fe, R_EP2, 1); |
| 388 | msleep(30); /* image low optimization completion */ |
| 389 | |
| 390 | /* mid-band */ |
| 391 | regs[R_EP5] = 0x82; |
| 392 | regs[R_CPD] = 0xa8; |
| 393 | regs[R_CD2] = 0x00; |
| 394 | regs[R_MPD] = 0xa9; |
| 395 | regs[R_MD1] = 0x73; |
| 396 | regs[R_MD2] = 0x1a; |
| 397 | |
| 398 | tda18271_write_regs(fe, R_EP3, 11); |
| 399 | msleep(5); /* pll locking */ |
| 400 | |
| 401 | tda18271_write_regs(fe, R_EP1, 1); |
| 402 | msleep(5); /* wanted mid measurement */ |
| 403 | |
| 404 | regs[R_EP5] = 0x86; |
| 405 | regs[R_CPD] = 0xa8; |
| 406 | regs[R_CD1] = 0x66; |
| 407 | regs[R_CD2] = 0xa0; |
| 408 | |
| 409 | tda18271_write_regs(fe, R_EP3, 7); |
| 410 | msleep(5); /* pll locking */ |
| 411 | |
| 412 | /* launch optimization algorithm */ |
| 413 | tda18271_write_regs(fe, R_EP2, 1); |
| 414 | msleep(30); /* image mid optimization completion */ |
| 415 | |
| 416 | /* high-band */ |
| 417 | regs[R_EP5] = 0x83; |
| 418 | regs[R_CPD] = 0x98; |
| 419 | regs[R_CD1] = 0x65; |
| 420 | regs[R_CD2] = 0x00; |
| 421 | regs[R_MPD] = 0x99; |
| 422 | regs[R_MD1] = 0x71; |
| 423 | regs[R_MD2] = 0xcd; |
| 424 | |
| 425 | tda18271_write_regs(fe, R_EP3, 11); |
| 426 | msleep(5); /* pll locking */ |
| 427 | |
| 428 | /* launch detector */ |
| 429 | tda18271_write_regs(fe, R_EP1, 1); |
| 430 | msleep(5); /* wanted high measurement */ |
| 431 | |
| 432 | regs[R_EP5] = 0x87; |
| 433 | regs[R_CD1] = 0x65; |
| 434 | regs[R_CD2] = 0x50; |
| 435 | |
| 436 | tda18271_write_regs(fe, R_EP3, 7); |
| 437 | msleep(5); /* pll locking */ |
| 438 | |
| 439 | /* launch optimization algorithm */ |
| 440 | tda18271_write_regs(fe, R_EP2, 1); |
| 441 | msleep(30); /* image high optimization completion */ |
| 442 | |
| 443 | /* return to normal mode */ |
| 444 | regs[R_EP4] = 0x64; |
| 445 | tda18271_write_regs(fe, R_EP4, 1); |
| 446 | |
| 447 | /* synchronize */ |
| 448 | tda18271_write_regs(fe, R_EP1, 1); |
| 449 | |
| 450 | return 0; |
| 451 | } |
| 452 | |
| 453 | /*---------------------------------------------------------------------*/ |
| 454 | |
Michael Krufky | 518d873 | 2008-01-13 17:01:01 -0300 | [diff] [blame^] | 455 | /* |
| 456 | * Standby modes, EP3 [7:5] |
| 457 | * |
| 458 | * | SM || SM_LT || SM_XT || mode description |
| 459 | * |=====\\=======\\=======\\=================================== |
| 460 | * | 0 || 0 || 0 || normal mode |
| 461 | * |-----||-------||-------||----------------------------------- |
| 462 | * | || || || standby mode w/ slave tuner output |
| 463 | * | 1 || 0 || 0 || & loop thru & xtal oscillator on |
| 464 | * |-----||-------||-------||----------------------------------- |
| 465 | * | 1 || 1 || 0 || standby mode w/ xtal oscillator on |
| 466 | * |-----||-------||-------||----------------------------------- |
| 467 | * | 1 || 1 || 1 || power off |
| 468 | * |
| 469 | */ |
| 470 | |
| 471 | int tda18271_set_standby_mode(struct dvb_frontend *fe, |
| 472 | int sm, int sm_lt, int sm_xt) |
| 473 | { |
| 474 | struct tda18271_priv *priv = fe->tuner_priv; |
| 475 | unsigned char *regs = priv->tda18271_regs; |
| 476 | |
| 477 | tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt); |
| 478 | |
| 479 | regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */ |
| 480 | regs[R_EP3] |= sm ? (1 << 7) : 0 | |
| 481 | sm_lt ? (1 << 6) : 0 | |
| 482 | sm_xt ? (1 << 5) : 0; |
| 483 | |
| 484 | tda18271_write_regs(fe, R_EP3, 1); |
| 485 | |
| 486 | return 0; |
| 487 | } |
| 488 | |
| 489 | /*---------------------------------------------------------------------*/ |
| 490 | |
Michael Krufky | 59067f7 | 2008-01-02 01:58:26 -0300 | [diff] [blame] | 491 | int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq) |
| 492 | { |
| 493 | /* sets main post divider & divider bytes, but does not write them */ |
| 494 | struct tda18271_priv *priv = fe->tuner_priv; |
| 495 | unsigned char *regs = priv->tda18271_regs; |
| 496 | u8 d, pd; |
| 497 | u32 div; |
| 498 | |
| 499 | int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d); |
| 500 | if (ret < 0) |
| 501 | goto fail; |
| 502 | |
| 503 | regs[R_MPD] = (0x77 & pd); |
| 504 | |
| 505 | switch (priv->mode) { |
| 506 | case TDA18271_ANALOG: |
| 507 | regs[R_MPD] &= ~0x08; |
| 508 | break; |
| 509 | case TDA18271_DIGITAL: |
| 510 | regs[R_MPD] |= 0x08; |
| 511 | break; |
| 512 | } |
| 513 | |
| 514 | div = ((d * (freq / 1000)) << 7) / 125; |
| 515 | |
| 516 | regs[R_MD1] = 0x7f & (div >> 16); |
| 517 | regs[R_MD2] = 0xff & (div >> 8); |
| 518 | regs[R_MD3] = 0xff & div; |
| 519 | fail: |
| 520 | return ret; |
| 521 | } |
| 522 | |
| 523 | int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq) |
| 524 | { |
| 525 | /* sets cal post divider & divider bytes, but does not write them */ |
| 526 | struct tda18271_priv *priv = fe->tuner_priv; |
| 527 | unsigned char *regs = priv->tda18271_regs; |
| 528 | u8 d, pd; |
| 529 | u32 div; |
| 530 | |
| 531 | int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d); |
| 532 | if (ret < 0) |
| 533 | goto fail; |
| 534 | |
| 535 | regs[R_CPD] = pd; |
| 536 | |
| 537 | div = ((d * (freq / 1000)) << 7) / 125; |
| 538 | |
| 539 | regs[R_CD1] = 0x7f & (div >> 16); |
| 540 | regs[R_CD2] = 0xff & (div >> 8); |
| 541 | regs[R_CD3] = 0xff & div; |
| 542 | fail: |
| 543 | return ret; |
| 544 | } |
| 545 | |
| 546 | /*---------------------------------------------------------------------*/ |
| 547 | |
| 548 | int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq) |
| 549 | { |
| 550 | /* sets bp filter bits, but does not write them */ |
| 551 | struct tda18271_priv *priv = fe->tuner_priv; |
| 552 | unsigned char *regs = priv->tda18271_regs; |
| 553 | u8 val; |
| 554 | |
| 555 | int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val); |
| 556 | if (ret < 0) |
| 557 | goto fail; |
| 558 | |
| 559 | regs[R_EP1] &= ~0x07; /* clear bp filter bits */ |
| 560 | regs[R_EP1] |= (0x07 & val); |
| 561 | fail: |
| 562 | return ret; |
| 563 | } |
| 564 | |
| 565 | int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq) |
| 566 | { |
| 567 | /* sets K & M bits, but does not write them */ |
| 568 | struct tda18271_priv *priv = fe->tuner_priv; |
| 569 | unsigned char *regs = priv->tda18271_regs; |
| 570 | u8 val; |
| 571 | |
| 572 | int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val); |
| 573 | if (ret < 0) |
| 574 | goto fail; |
| 575 | |
| 576 | regs[R_EB13] &= ~0x7c; /* clear k & m bits */ |
| 577 | regs[R_EB13] |= (0x7c & val); |
| 578 | fail: |
| 579 | return ret; |
| 580 | } |
| 581 | |
| 582 | int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq) |
| 583 | { |
| 584 | /* sets rf band bits, but does not write them */ |
| 585 | struct tda18271_priv *priv = fe->tuner_priv; |
| 586 | unsigned char *regs = priv->tda18271_regs; |
| 587 | u8 val; |
| 588 | |
| 589 | int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val); |
| 590 | if (ret < 0) |
| 591 | goto fail; |
| 592 | |
| 593 | regs[R_EP2] &= ~0xe0; /* clear rf band bits */ |
| 594 | regs[R_EP2] |= (0xe0 & (val << 5)); |
| 595 | fail: |
| 596 | return ret; |
| 597 | } |
| 598 | |
| 599 | int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq) |
| 600 | { |
| 601 | /* sets gain taper bits, but does not write them */ |
| 602 | struct tda18271_priv *priv = fe->tuner_priv; |
| 603 | unsigned char *regs = priv->tda18271_regs; |
| 604 | u8 val; |
| 605 | |
| 606 | int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val); |
| 607 | if (ret < 0) |
| 608 | goto fail; |
| 609 | |
| 610 | regs[R_EP2] &= ~0x1f; /* clear gain taper bits */ |
| 611 | regs[R_EP2] |= (0x1f & val); |
| 612 | fail: |
| 613 | return ret; |
| 614 | } |
| 615 | |
| 616 | int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq) |
| 617 | { |
| 618 | /* sets IR Meas bits, but does not write them */ |
| 619 | struct tda18271_priv *priv = fe->tuner_priv; |
| 620 | unsigned char *regs = priv->tda18271_regs; |
| 621 | u8 val; |
| 622 | |
| 623 | int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val); |
| 624 | if (ret < 0) |
| 625 | goto fail; |
| 626 | |
| 627 | regs[R_EP5] &= ~0x07; |
| 628 | regs[R_EP5] |= (0x07 & val); |
| 629 | fail: |
| 630 | return ret; |
| 631 | } |
| 632 | |
| 633 | int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq) |
| 634 | { |
| 635 | /* sets rf cal byte (RFC_Cprog), but does not write it */ |
| 636 | struct tda18271_priv *priv = fe->tuner_priv; |
| 637 | unsigned char *regs = priv->tda18271_regs; |
| 638 | u8 val; |
| 639 | |
Michael Krufky | d2c932a | 2008-01-05 15:42:54 -0300 | [diff] [blame] | 640 | tda18271_lookup_map(fe, RF_CAL, freq, &val); |
Michael Krufky | 59067f7 | 2008-01-02 01:58:26 -0300 | [diff] [blame] | 641 | |
| 642 | regs[R_EB14] = val; |
Michael Krufky | d2c932a | 2008-01-05 15:42:54 -0300 | [diff] [blame] | 643 | |
| 644 | return 0; |
Michael Krufky | 59067f7 | 2008-01-02 01:58:26 -0300 | [diff] [blame] | 645 | } |
| 646 | |
| 647 | /* |
| 648 | * Overrides for Emacs so that we follow Linus's tabbing style. |
| 649 | * --------------------------------------------------------------------------- |
| 650 | * Local variables: |
| 651 | * c-basic-offset: 8 |
| 652 | * End: |
| 653 | */ |