diff options
| -rw-r--r-- | drivers/media/dvb/frontends/cx24123.c | 262 |
1 files changed, 181 insertions, 81 deletions
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index d661c6f9cbe5..e430e6a50831 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include "dvb_frontend.h" | 29 | #include "dvb_frontend.h" |
| 30 | #include "cx24123.h" | 30 | #include "cx24123.h" |
| 31 | 31 | ||
| 32 | #define XTAL 10111000 | ||
| 33 | |||
| 32 | static int debug; | 34 | static int debug; |
| 33 | #define dprintk(args...) \ | 35 | #define dprintk(args...) \ |
| 34 | do { \ | 36 | do { \ |
| @@ -52,6 +54,7 @@ struct cx24123_state | |||
| 52 | u32 VGAarg; | 54 | u32 VGAarg; |
| 53 | u32 bandselectarg; | 55 | u32 bandselectarg; |
| 54 | u32 pllarg; | 56 | u32 pllarg; |
| 57 | u32 FILTune; | ||
| 55 | 58 | ||
| 56 | /* The Demod/Tuner can't easily provide these, we cache them */ | 59 | /* The Demod/Tuner can't easily provide these, we cache them */ |
| 57 | u32 currentfreq; | 60 | u32 currentfreq; |
| @@ -63,43 +66,33 @@ static struct | |||
| 63 | { | 66 | { |
| 64 | u32 symbolrate_low; | 67 | u32 symbolrate_low; |
| 65 | u32 symbolrate_high; | 68 | u32 symbolrate_high; |
| 66 | u32 VCAslope; | ||
| 67 | u32 VCAoffset; | ||
| 68 | u32 VGA1offset; | ||
| 69 | u32 VGA2offset; | ||
| 70 | u32 VCAprogdata; | 69 | u32 VCAprogdata; |
| 71 | u32 VGAprogdata; | 70 | u32 VGAprogdata; |
| 71 | u32 FILTune; | ||
| 72 | } cx24123_AGC_vals[] = | 72 | } cx24123_AGC_vals[] = |
| 73 | { | 73 | { |
| 74 | { | 74 | { |
| 75 | .symbolrate_low = 1000000, | 75 | .symbolrate_low = 1000000, |
| 76 | .symbolrate_high = 4999999, | 76 | .symbolrate_high = 4999999, |
| 77 | .VCAslope = 0x07, | 77 | /* the specs recommend other values for VGA offsets, |
| 78 | .VCAoffset = 0x0f, | 78 | but tests show they are wrong */ |
| 79 | .VGA1offset = 0x1f8, | 79 | .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, |
| 80 | .VGA2offset = 0x1f8, | ||
| 81 | .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8, | ||
| 82 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07, | 80 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07, |
| 81 | .FILTune = 0x280 /* 0.41 V */ | ||
| 83 | }, | 82 | }, |
| 84 | { | 83 | { |
| 85 | .symbolrate_low = 5000000, | 84 | .symbolrate_low = 5000000, |
| 86 | .symbolrate_high = 14999999, | 85 | .symbolrate_high = 14999999, |
| 87 | .VCAslope = 0x1f, | ||
| 88 | .VCAoffset = 0x1f, | ||
| 89 | .VGA1offset = 0x1e0, | ||
| 90 | .VGA2offset = 0x180, | ||
| 91 | .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, | 86 | .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, |
| 92 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f, | 87 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f, |
| 88 | .FILTune = 0x317 /* 0.90 V */ | ||
| 93 | }, | 89 | }, |
| 94 | { | 90 | { |
| 95 | .symbolrate_low = 15000000, | 91 | .symbolrate_low = 15000000, |
| 96 | .symbolrate_high = 45000000, | 92 | .symbolrate_high = 45000000, |
| 97 | .VCAslope = 0x3f, | ||
| 98 | .VCAoffset = 0x3f, | ||
| 99 | .VGA1offset = 0x180, | ||
| 100 | .VGA2offset = 0x100, | ||
| 101 | .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180, | 93 | .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180, |
| 102 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f, | 94 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f, |
| 95 | .FILTune = 0x146 /* 2.70 V */ | ||
| 103 | }, | 96 | }, |
| 104 | }; | 97 | }; |
| 105 | 98 | ||
| @@ -112,90 +105,68 @@ static struct | |||
| 112 | { | 105 | { |
| 113 | u32 freq_low; | 106 | u32 freq_low; |
| 114 | u32 freq_high; | 107 | u32 freq_high; |
| 115 | u32 bandselect; | ||
| 116 | u32 VCOdivider; | 108 | u32 VCOdivider; |
| 117 | u32 VCOnumber; | ||
| 118 | u32 progdata; | 109 | u32 progdata; |
| 119 | } cx24123_bandselect_vals[] = | 110 | } cx24123_bandselect_vals[] = |
| 120 | { | 111 | { |
| 121 | { | 112 | { |
| 122 | .freq_low = 950000, | 113 | .freq_low = 950000, |
| 123 | .freq_high = 1018999, | 114 | .freq_high = 1018999, |
| 124 | .bandselect = 0x40, | ||
| 125 | .VCOdivider = 4, | 115 | .VCOdivider = 4, |
| 126 | .VCOnumber = 7, | ||
| 127 | .progdata = (0 << 18) | (0 << 9) | 0x40, | 116 | .progdata = (0 << 18) | (0 << 9) | 0x40, |
| 128 | }, | 117 | }, |
| 129 | { | 118 | { |
| 130 | .freq_low = 1019000, | 119 | .freq_low = 1019000, |
| 131 | .freq_high = 1074999, | 120 | .freq_high = 1074999, |
| 132 | .bandselect = 0x80, | ||
| 133 | .VCOdivider = 4, | 121 | .VCOdivider = 4, |
| 134 | .VCOnumber = 8, | ||
| 135 | .progdata = (0 << 18) | (0 << 9) | 0x80, | 122 | .progdata = (0 << 18) | (0 << 9) | 0x80, |
| 136 | }, | 123 | }, |
| 137 | { | 124 | { |
| 138 | .freq_low = 1075000, | 125 | .freq_low = 1075000, |
| 139 | .freq_high = 1227999, | 126 | .freq_high = 1227999, |
| 140 | .bandselect = 0x01, | ||
| 141 | .VCOdivider = 2, | 127 | .VCOdivider = 2, |
| 142 | .VCOnumber = 1, | ||
| 143 | .progdata = (0 << 18) | (1 << 9) | 0x01, | 128 | .progdata = (0 << 18) | (1 << 9) | 0x01, |
| 144 | }, | 129 | }, |
| 145 | { | 130 | { |
| 146 | .freq_low = 1228000, | 131 | .freq_low = 1228000, |
| 147 | .freq_high = 1349999, | 132 | .freq_high = 1349999, |
| 148 | .bandselect = 0x02, | ||
| 149 | .VCOdivider = 2, | 133 | .VCOdivider = 2, |
| 150 | .VCOnumber = 2, | ||
| 151 | .progdata = (0 << 18) | (1 << 9) | 0x02, | 134 | .progdata = (0 << 18) | (1 << 9) | 0x02, |
| 152 | }, | 135 | }, |
| 153 | { | 136 | { |
| 154 | .freq_low = 1350000, | 137 | .freq_low = 1350000, |
| 155 | .freq_high = 1481999, | 138 | .freq_high = 1481999, |
| 156 | .bandselect = 0x04, | ||
| 157 | .VCOdivider = 2, | 139 | .VCOdivider = 2, |
| 158 | .VCOnumber = 3, | ||
| 159 | .progdata = (0 << 18) | (1 << 9) | 0x04, | 140 | .progdata = (0 << 18) | (1 << 9) | 0x04, |
| 160 | }, | 141 | }, |
| 161 | { | 142 | { |
| 162 | .freq_low = 1482000, | 143 | .freq_low = 1482000, |
| 163 | .freq_high = 1595999, | 144 | .freq_high = 1595999, |
| 164 | .bandselect = 0x08, | ||
| 165 | .VCOdivider = 2, | 145 | .VCOdivider = 2, |
| 166 | .VCOnumber = 4, | ||
| 167 | .progdata = (0 << 18) | (1 << 9) | 0x08, | 146 | .progdata = (0 << 18) | (1 << 9) | 0x08, |
| 168 | }, | 147 | }, |
| 169 | { | 148 | { |
| 170 | .freq_low = 1596000, | 149 | .freq_low = 1596000, |
| 171 | .freq_high = 1717999, | 150 | .freq_high = 1717999, |
| 172 | .bandselect = 0x10, | ||
| 173 | .VCOdivider = 2, | 151 | .VCOdivider = 2, |
| 174 | .VCOnumber = 5, | ||
| 175 | .progdata = (0 << 18) | (1 << 9) | 0x10, | 152 | .progdata = (0 << 18) | (1 << 9) | 0x10, |
| 176 | }, | 153 | }, |
| 177 | { | 154 | { |
| 178 | .freq_low = 1718000, | 155 | .freq_low = 1718000, |
| 179 | .freq_high = 1855999, | 156 | .freq_high = 1855999, |
| 180 | .bandselect = 0x20, | ||
| 181 | .VCOdivider = 2, | 157 | .VCOdivider = 2, |
| 182 | .VCOnumber = 6, | ||
| 183 | .progdata = (0 << 18) | (1 << 9) | 0x20, | 158 | .progdata = (0 << 18) | (1 << 9) | 0x20, |
| 184 | }, | 159 | }, |
| 185 | { | 160 | { |
| 186 | .freq_low = 1856000, | 161 | .freq_low = 1856000, |
| 187 | .freq_high = 2035999, | 162 | .freq_high = 2035999, |
| 188 | .bandselect = 0x40, | ||
| 189 | .VCOdivider = 2, | 163 | .VCOdivider = 2, |
| 190 | .VCOnumber = 7, | ||
| 191 | .progdata = (0 << 18) | (1 << 9) | 0x40, | 164 | .progdata = (0 << 18) | (1 << 9) | 0x40, |
| 192 | }, | 165 | }, |
| 193 | { | 166 | { |
| 194 | .freq_low = 2036000, | 167 | .freq_low = 2036000, |
| 195 | .freq_high = 2149999, | 168 | .freq_high = 2149999, |
| 196 | .bandselect = 0x80, | ||
| 197 | .VCOdivider = 2, | 169 | .VCOdivider = 2, |
| 198 | .VCOnumber = 8, | ||
| 199 | .progdata = (0 << 18) | (1 << 9) | 0x80, | 170 | .progdata = (0 << 18) | (1 << 9) | 0x80, |
| 200 | }, | 171 | }, |
| 201 | }; | 172 | }; |
| @@ -207,7 +178,6 @@ static struct { | |||
| 207 | { | 178 | { |
| 208 | {0x00, 0x03}, /* Reset system */ | 179 | {0x00, 0x03}, /* Reset system */ |
| 209 | {0x00, 0x00}, /* Clear reset */ | 180 | {0x00, 0x00}, /* Clear reset */ |
| 210 | {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */ | ||
| 211 | {0x03, 0x07}, | 181 | {0x03, 0x07}, |
| 212 | {0x04, 0x10}, | 182 | {0x04, 0x10}, |
| 213 | {0x05, 0x04}, | 183 | {0x05, 0x04}, |
| @@ -217,7 +187,6 @@ static struct { | |||
| 217 | {0x0f, 0xfe}, | 187 | {0x0f, 0xfe}, |
| 218 | {0x10, 0x01}, | 188 | {0x10, 0x01}, |
| 219 | {0x14, 0x01}, | 189 | {0x14, 0x01}, |
| 220 | {0x15, 0x98}, | ||
| 221 | {0x16, 0x00}, | 190 | {0x16, 0x00}, |
| 222 | {0x17, 0x01}, | 191 | {0x17, 0x01}, |
| 223 | {0x1b, 0x05}, | 192 | {0x1b, 0x05}, |
| @@ -226,8 +195,6 @@ static struct { | |||
| 226 | {0x1e, 0x00}, | 195 | {0x1e, 0x00}, |
| 227 | {0x20, 0x41}, | 196 | {0x20, 0x41}, |
| 228 | {0x21, 0x15}, | 197 | {0x21, 0x15}, |
| 229 | {0x27, 0x14}, | ||
| 230 | {0x28, 0x46}, | ||
| 231 | {0x29, 0x00}, | 198 | {0x29, 0x00}, |
| 232 | {0x2a, 0xb0}, | 199 | {0x2a, 0xb0}, |
| 233 | {0x2b, 0x73}, | 200 | {0x2b, 0x73}, |
| @@ -375,55 +342,103 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) | |||
| 375 | static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) | 342 | static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) |
| 376 | { | 343 | { |
| 377 | int ret; | 344 | int ret; |
| 378 | u8 val; | ||
| 379 | 345 | ||
| 380 | ret = cx24123_readreg (state, 0x1b); | 346 | ret = cx24123_readreg (state, 0x1b); |
| 381 | if (ret < 0) | 347 | if (ret < 0) |
| 382 | return ret; | 348 | return ret; |
| 383 | val = ret & 0x07; | 349 | ret = ret & 0x07; |
| 384 | switch (val) { | 350 | |
| 351 | switch (ret) { | ||
| 385 | case 1: | 352 | case 1: |
| 386 | *fec = FEC_1_2; | 353 | *fec = FEC_1_2; |
| 387 | break; | 354 | break; |
| 388 | case 3: | 355 | case 2: |
| 389 | *fec = FEC_2_3; | 356 | *fec = FEC_2_3; |
| 390 | break; | 357 | break; |
| 391 | case 4: | 358 | case 3: |
| 392 | *fec = FEC_3_4; | 359 | *fec = FEC_3_4; |
| 393 | break; | 360 | break; |
| 394 | case 5: | 361 | case 4: |
| 395 | *fec = FEC_4_5; | 362 | *fec = FEC_4_5; |
| 396 | break; | 363 | break; |
| 397 | case 6: | 364 | case 5: |
| 398 | *fec = FEC_5_6; | 365 | *fec = FEC_5_6; |
| 399 | break; | 366 | break; |
| 367 | case 6: | ||
| 368 | *fec = FEC_6_7; | ||
| 369 | break; | ||
| 400 | case 7: | 370 | case 7: |
| 401 | *fec = FEC_7_8; | 371 | *fec = FEC_7_8; |
| 402 | break; | 372 | break; |
| 403 | case 2: /* *fec = FEC_3_5; break; */ | ||
| 404 | case 0: /* *fec = FEC_5_11; break; */ | ||
| 405 | *fec = FEC_AUTO; | ||
| 406 | break; | ||
| 407 | default: | 373 | default: |
| 408 | *fec = FEC_NONE; // can't happen | 374 | *fec = FEC_NONE; // can't happen |
| 375 | printk("FEC_NONE ?\n"); | ||
| 409 | } | 376 | } |
| 410 | 377 | ||
| 411 | return 0; | 378 | return 0; |
| 412 | } | 379 | } |
| 413 | 380 | ||
| 414 | /* fixme: Symbol rates < 3MSps may not work because of precision loss */ | ||
| 415 | static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) | 381 | static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) |
| 416 | { | 382 | { |
| 417 | u32 val; | 383 | u32 tmp, sample_rate, ratio; |
| 384 | u8 pll_mult; | ||
| 385 | |||
| 386 | /* check if symbol rate is within limits */ | ||
| 387 | if ((srate > state->ops.info.symbol_rate_max) || | ||
| 388 | (srate < state->ops.info.symbol_rate_min)) | ||
| 389 | return -EOPNOTSUPP;; | ||
| 390 | |||
| 391 | /* choose the sampling rate high enough for the required operation, | ||
| 392 | while optimizing the power consumed by the demodulator */ | ||
| 393 | if (srate < (XTAL*2)/2) | ||
| 394 | pll_mult = 2; | ||
| 395 | else if (srate < (XTAL*3)/2) | ||
| 396 | pll_mult = 3; | ||
| 397 | else if (srate < (XTAL*4)/2) | ||
| 398 | pll_mult = 4; | ||
| 399 | else if (srate < (XTAL*5)/2) | ||
| 400 | pll_mult = 5; | ||
| 401 | else if (srate < (XTAL*6)/2) | ||
| 402 | pll_mult = 6; | ||
| 403 | else if (srate < (XTAL*7)/2) | ||
| 404 | pll_mult = 7; | ||
| 405 | else if (srate < (XTAL*8)/2) | ||
| 406 | pll_mult = 8; | ||
| 407 | else | ||
| 408 | pll_mult = 9; | ||
| 409 | |||
| 410 | |||
| 411 | sample_rate = pll_mult * XTAL; | ||
| 418 | 412 | ||
| 419 | val = (srate / 1185) * 100; | 413 | /* |
| 414 | SYSSymbolRate[21:0] = (srate << 23) / sample_rate | ||
| 420 | 415 | ||
| 421 | /* Compensate for scaling up, by removing 17 symbols per 1Msps */ | 416 | We have to use 32 bit unsigned arithmetic without precision loss. |
| 422 | val = val - (17 * (srate / 1000000)); | 417 | The maximum srate is 45000000 or 0x02AEA540. This number has |
| 418 | only 6 clear bits on top, hence we can shift it left only 6 bits | ||
| 419 | at a time. Borrowed from cx24110.c | ||
| 420 | */ | ||
| 423 | 421 | ||
| 424 | cx24123_writereg(state, 0x08, (val >> 16) & 0xff ); | 422 | tmp = srate << 6; |
| 425 | cx24123_writereg(state, 0x09, (val >> 8) & 0xff ); | 423 | ratio = tmp / sample_rate; |
| 426 | cx24123_writereg(state, 0x0a, (val ) & 0xff ); | 424 | |
| 425 | tmp = (tmp % sample_rate) << 6; | ||
| 426 | ratio = (ratio << 6) + (tmp / sample_rate); | ||
| 427 | |||
| 428 | tmp = (tmp % sample_rate) << 6; | ||
| 429 | ratio = (ratio << 6) + (tmp / sample_rate); | ||
| 430 | |||
| 431 | tmp = (tmp % sample_rate) << 5; | ||
| 432 | ratio = (ratio << 5) + (tmp / sample_rate); | ||
| 433 | |||
| 434 | |||
| 435 | cx24123_writereg(state, 0x01, pll_mult * 6); | ||
| 436 | |||
| 437 | cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f ); | ||
| 438 | cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff ); | ||
| 439 | cx24123_writereg(state, 0x0a, (ratio ) & 0xff ); | ||
| 440 | |||
| 441 | dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i\n", __FUNCTION__, srate, ratio, sample_rate); | ||
| 427 | 442 | ||
| 428 | return 0; | 443 | return 0; |
| 429 | } | 444 | } |
| @@ -437,6 +452,7 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa | |||
| 437 | struct cx24123_state *state = fe->demodulator_priv; | 452 | struct cx24123_state *state = fe->demodulator_priv; |
| 438 | u32 ndiv = 0, adiv = 0, vco_div = 0; | 453 | u32 ndiv = 0, adiv = 0, vco_div = 0; |
| 439 | int i = 0; | 454 | int i = 0; |
| 455 | int pump = 2; | ||
| 440 | 456 | ||
| 441 | /* Defaults for low freq, low rate */ | 457 | /* Defaults for low freq, low rate */ |
| 442 | state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; | 458 | state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; |
| @@ -444,13 +460,14 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa | |||
| 444 | state->bandselectarg = cx24123_bandselect_vals[0].progdata; | 460 | state->bandselectarg = cx24123_bandselect_vals[0].progdata; |
| 445 | vco_div = cx24123_bandselect_vals[0].VCOdivider; | 461 | vco_div = cx24123_bandselect_vals[0].VCOdivider; |
| 446 | 462 | ||
| 447 | /* For the given symbolerate, determine the VCA and VGA programming bits */ | 463 | /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */ |
| 448 | for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++) | 464 | for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++) |
| 449 | { | 465 | { |
| 450 | if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && | 466 | if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && |
| 451 | (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { | 467 | (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { |
| 452 | state->VCAarg = cx24123_AGC_vals[i].VCAprogdata; | 468 | state->VCAarg = cx24123_AGC_vals[i].VCAprogdata; |
| 453 | state->VGAarg = cx24123_AGC_vals[i].VGAprogdata; | 469 | state->VGAarg = cx24123_AGC_vals[i].VGAprogdata; |
| 470 | state->FILTune = cx24123_AGC_vals[i].FILTune; | ||
| 454 | } | 471 | } |
| 455 | } | 472 | } |
| 456 | 473 | ||
| @@ -458,24 +475,28 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa | |||
| 458 | for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++) | 475 | for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++) |
| 459 | { | 476 | { |
| 460 | if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && | 477 | if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && |
| 461 | (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) { | 478 | (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) { |
| 462 | state->bandselectarg = cx24123_bandselect_vals[i].progdata; | 479 | state->bandselectarg = cx24123_bandselect_vals[i].progdata; |
| 463 | vco_div = cx24123_bandselect_vals[i].VCOdivider; | 480 | vco_div = cx24123_bandselect_vals[i].VCOdivider; |
| 481 | |||
| 482 | /* determine the charge pump current */ | ||
| 483 | if ( p->frequency < (cx24123_bandselect_vals[i].freq_low + cx24123_bandselect_vals[i].freq_high)/2 ) | ||
| 484 | pump = 0x01; | ||
| 485 | else | ||
| 486 | pump = 0x02; | ||
| 464 | } | 487 | } |
| 465 | } | 488 | } |
| 466 | 489 | ||
| 467 | /* Determine the N/A dividers for the requested lband freq (in kHz). */ | 490 | /* Determine the N/A dividers for the requested lband freq (in kHz). */ |
| 468 | /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */ | 491 | /* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */ |
| 469 | ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff; | 492 | ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff; |
| 470 | adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f; | 493 | adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f; |
| 471 | 494 | ||
| 472 | if (adiv == 0) | 495 | if (adiv == 0) |
| 473 | adiv++; | 496 | ndiv++; |
| 474 | 497 | ||
| 475 | /* determine the correct pll frequency values. */ | 498 | /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */ |
| 476 | /* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */ | 499 | state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv; |
| 477 | state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14); | ||
| 478 | state->pllarg |= (ndiv << 5) | adiv; | ||
| 479 | 500 | ||
| 480 | return 0; | 501 | return 0; |
| 481 | } | 502 | } |
| @@ -538,6 +559,9 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par | |||
| 538 | static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | 559 | static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) |
| 539 | { | 560 | { |
| 540 | struct cx24123_state *state = fe->demodulator_priv; | 561 | struct cx24123_state *state = fe->demodulator_priv; |
| 562 | u8 val; | ||
| 563 | |||
| 564 | dprintk("frequency=%i\n", p->frequency); | ||
| 541 | 565 | ||
| 542 | if (cx24123_pll_calculate(fe, p) != 0) { | 566 | if (cx24123_pll_calculate(fe, p) != 0) { |
| 543 | printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); | 567 | printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); |
| @@ -552,6 +576,11 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet | |||
| 552 | cx24123_pll_writereg(fe, p, state->bandselectarg); | 576 | cx24123_pll_writereg(fe, p, state->bandselectarg); |
| 553 | cx24123_pll_writereg(fe, p, state->pllarg); | 577 | cx24123_pll_writereg(fe, p, state->pllarg); |
| 554 | 578 | ||
| 579 | /* set the FILTUNE voltage */ | ||
| 580 | val = cx24123_readreg(state, 0x28) & ~0x3; | ||
| 581 | cx24123_writereg(state, 0x27, state->FILTune >> 2); | ||
| 582 | cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3)); | ||
| 583 | |||
| 555 | return 0; | 584 | return 0; |
| 556 | } | 585 | } |
| 557 | 586 | ||
| @@ -624,13 +653,81 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage | |||
| 624 | return 0; | 653 | return 0; |
| 625 | } | 654 | } |
| 626 | 655 | ||
| 627 | static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, | 656 | static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) |
| 628 | struct dvb_diseqc_master_cmd *cmd) | ||
| 629 | { | 657 | { |
| 630 | /* fixme: Implement diseqc */ | 658 | struct cx24123_state *state = fe->demodulator_priv; |
| 631 | printk("%s: No support yet\n",__FUNCTION__); | 659 | int i, val; |
| 660 | unsigned long timeout; | ||
| 661 | |||
| 662 | dprintk("%s:\n",__FUNCTION__); | ||
| 632 | 663 | ||
| 633 | return -ENOTSUPP; | 664 | /* check if continuous tone has been stoped */ |
| 665 | if (state->config->use_isl6421) | ||
| 666 | val = cx24123_readlnbreg(state, 0x00) & 0x10; | ||
| 667 | else | ||
| 668 | val = cx24123_readreg(state, 0x29) & 0x10; | ||
| 669 | |||
| 670 | |||
| 671 | if (val) { | ||
| 672 | printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); | ||
| 673 | return -ENOTSUPP; | ||
| 674 | } | ||
| 675 | |||
| 676 | /* select tone mode */ | ||
| 677 | cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8); | ||
| 678 | |||
| 679 | for (i = 0; i < cmd->msg_len; i++) | ||
| 680 | cx24123_writereg(state, 0x2C + i, cmd->msg[i]); | ||
| 681 | |||
| 682 | val = cx24123_readreg(state, 0x29); | ||
| 683 | cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); | ||
| 684 | |||
| 685 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 686 | while (!time_after(jiffies, timeout) && !(cx24123_readreg(state, 0x29) & 0x40)) | ||
| 687 | ; // wait for LNB ready | ||
| 688 | |||
| 689 | return 0; | ||
| 690 | } | ||
| 691 | |||
| 692 | static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) | ||
| 693 | { | ||
| 694 | struct cx24123_state *state = fe->demodulator_priv; | ||
| 695 | int val; | ||
| 696 | unsigned long timeout; | ||
| 697 | |||
| 698 | dprintk("%s:\n", __FUNCTION__); | ||
| 699 | |||
| 700 | /* check if continuous tone has been stoped */ | ||
| 701 | if (state->config->use_isl6421) | ||
| 702 | val = cx24123_readlnbreg(state, 0x00) & 0x10; | ||
| 703 | else | ||
| 704 | val = cx24123_readreg(state, 0x29) & 0x10; | ||
| 705 | |||
| 706 | |||
| 707 | if (val) { | ||
| 708 | printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); | ||
| 709 | return -ENOTSUPP; | ||
| 710 | } | ||
| 711 | |||
| 712 | /* select tone mode */ | ||
| 713 | val = cx24123_readreg(state, 0x2a) & 0xf8; | ||
| 714 | cx24123_writereg(state, 0x2a, val | 0x04); | ||
| 715 | |||
| 716 | val = cx24123_readreg(state, 0x29); | ||
| 717 | |||
| 718 | if (burst == SEC_MINI_A) | ||
| 719 | cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00)); | ||
| 720 | else if (burst == SEC_MINI_B) | ||
| 721 | cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x08)); | ||
| 722 | else | ||
| 723 | return -EINVAL; | ||
| 724 | |||
| 725 | |||
| 726 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 727 | while (!time_after(jiffies, timeout) && !(cx24123_readreg(state, 0x29) & 0x40)) | ||
| 728 | ; // wait for LNB ready | ||
| 729 | |||
| 730 | return 0; | ||
| 634 | } | 731 | } |
| 635 | 732 | ||
| 636 | static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) | 733 | static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) |
| @@ -642,13 +739,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
| 642 | 739 | ||
| 643 | *status = 0; | 740 | *status = 0; |
| 644 | if (lock & 0x01) | 741 | if (lock & 0x01) |
| 645 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | 742 | *status |= FE_HAS_SIGNAL; |
| 743 | if (sync & 0x02) | ||
| 744 | *status |= FE_HAS_CARRIER; | ||
| 646 | if (sync & 0x04) | 745 | if (sync & 0x04) |
| 647 | *status |= FE_HAS_VITERBI; | 746 | *status |= FE_HAS_VITERBI; |
| 648 | if (sync & 0x08) | 747 | if (sync & 0x08) |
| 649 | *status |= FE_HAS_CARRIER; | 748 | *status |= FE_HAS_SYNC; |
| 650 | if (sync & 0x80) | 749 | if (sync & 0x80) |
| 651 | *status |= FE_HAS_SYNC | FE_HAS_LOCK; | 750 | *status |= FE_HAS_LOCK; |
| 652 | 751 | ||
| 653 | return 0; | 752 | return 0; |
| 654 | } | 753 | } |
| @@ -875,6 +974,7 @@ static struct dvb_frontend_ops cx24123_ops = { | |||
| 875 | .read_snr = cx24123_read_snr, | 974 | .read_snr = cx24123_read_snr, |
| 876 | .read_ucblocks = cx24123_read_ucblocks, | 975 | .read_ucblocks = cx24123_read_ucblocks, |
| 877 | .diseqc_send_master_cmd = cx24123_send_diseqc_msg, | 976 | .diseqc_send_master_cmd = cx24123_send_diseqc_msg, |
| 977 | .diseqc_send_burst = cx24123_diseqc_send_burst, | ||
| 878 | .set_tone = cx24123_set_tone, | 978 | .set_tone = cx24123_set_tone, |
| 879 | .set_voltage = cx24123_set_voltage, | 979 | .set_voltage = cx24123_set_voltage, |
| 880 | }; | 980 | }; |
