aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/cx24123.c
diff options
context:
space:
mode:
authorVadim Catana <skystar@moldova.cc>2006-04-13 09:19:52 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-05-12 18:55:02 -0400
commita74b51fca9d9b6774413d700ade1e9ae1f0c0e75 (patch)
treeac02ba7f67f5b51805a4a0dda1d09701c1e3aab8 /drivers/media/dvb/frontends/cx24123.c
parent3a63fc4bfd8579bda1f6a03b3fcb792f59cb15f8 (diff)
V4L/DVB (3795): Fix for CX24123 & low symbol rates
- fixed the reception of channels with low symbol rates. ( The VGA1 and VGA2 offsets recommended by cx24109 docs for symbol rates from 1 to 5 MSps do not work. I changed them to values found experimentally. The charge pump current and FILTUNE voltage are now set to values recommended in the docs. This improves reception for symbol rates < 15 MSps. The values written in the SYSSymbolRate registers are calculated with better precision. ) - fixed the cx24123_get_fec() function. It was returning the values for DCII mode. - removed some unused variables Signed-off-by: Vadim Catana <skystar at moldova.cc> Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/frontends/cx24123.c')
-rw-r--r--drivers/media/dvb/frontends/cx24123.c262
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
32static int debug; 34static 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)
375static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) 342static 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 */
415static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) 381static 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
538static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) 559static 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
627static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, 656static 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
692static 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
636static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) 733static 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};