diff options
Diffstat (limited to 'drivers/media/dvb/frontends/cx24123.c')
-rw-r--r-- | drivers/media/dvb/frontends/cx24123.c | 565 |
1 files changed, 396 insertions, 169 deletions
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index d661c6f9cbe5..691dc840dcc0 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c | |||
@@ -29,6 +29,9 @@ | |||
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 | |||
34 | static int force_band; | ||
32 | static int debug; | 35 | static int debug; |
33 | #define dprintk(args...) \ | 36 | #define dprintk(args...) \ |
34 | do { \ | 37 | do { \ |
@@ -52,6 +55,7 @@ struct cx24123_state | |||
52 | u32 VGAarg; | 55 | u32 VGAarg; |
53 | u32 bandselectarg; | 56 | u32 bandselectarg; |
54 | u32 pllarg; | 57 | u32 pllarg; |
58 | u32 FILTune; | ||
55 | 59 | ||
56 | /* The Demod/Tuner can't easily provide these, we cache them */ | 60 | /* The Demod/Tuner can't easily provide these, we cache them */ |
57 | u32 currentfreq; | 61 | u32 currentfreq; |
@@ -63,43 +67,33 @@ static struct | |||
63 | { | 67 | { |
64 | u32 symbolrate_low; | 68 | u32 symbolrate_low; |
65 | u32 symbolrate_high; | 69 | u32 symbolrate_high; |
66 | u32 VCAslope; | ||
67 | u32 VCAoffset; | ||
68 | u32 VGA1offset; | ||
69 | u32 VGA2offset; | ||
70 | u32 VCAprogdata; | 70 | u32 VCAprogdata; |
71 | u32 VGAprogdata; | 71 | u32 VGAprogdata; |
72 | u32 FILTune; | ||
72 | } cx24123_AGC_vals[] = | 73 | } cx24123_AGC_vals[] = |
73 | { | 74 | { |
74 | { | 75 | { |
75 | .symbolrate_low = 1000000, | 76 | .symbolrate_low = 1000000, |
76 | .symbolrate_high = 4999999, | 77 | .symbolrate_high = 4999999, |
77 | .VCAslope = 0x07, | 78 | /* the specs recommend other values for VGA offsets, |
78 | .VCAoffset = 0x0f, | 79 | but tests show they are wrong */ |
79 | .VGA1offset = 0x1f8, | 80 | .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0, |
80 | .VGA2offset = 0x1f8, | 81 | .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x07, |
81 | .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8, | 82 | .FILTune = 0x27f /* 0.41 V */ |
82 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07, | ||
83 | }, | 83 | }, |
84 | { | 84 | { |
85 | .symbolrate_low = 5000000, | 85 | .symbolrate_low = 5000000, |
86 | .symbolrate_high = 14999999, | 86 | .symbolrate_high = 14999999, |
87 | .VCAslope = 0x1f, | 87 | .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0, |
88 | .VCAoffset = 0x1f, | 88 | .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x1f, |
89 | .VGA1offset = 0x1e0, | 89 | .FILTune = 0x317 /* 0.90 V */ |
90 | .VGA2offset = 0x180, | ||
91 | .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, | ||
92 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f, | ||
93 | }, | 90 | }, |
94 | { | 91 | { |
95 | .symbolrate_low = 15000000, | 92 | .symbolrate_low = 15000000, |
96 | .symbolrate_high = 45000000, | 93 | .symbolrate_high = 45000000, |
97 | .VCAslope = 0x3f, | 94 | .VGAprogdata = (1 << 19) | (0x100 << 9) | 0x180, |
98 | .VCAoffset = 0x3f, | 95 | .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x3f, |
99 | .VGA1offset = 0x180, | 96 | .FILTune = 0x145 /* 2.70 V */ |
100 | .VGA2offset = 0x100, | ||
101 | .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180, | ||
102 | .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f, | ||
103 | }, | 97 | }, |
104 | }; | 98 | }; |
105 | 99 | ||
@@ -112,91 +106,80 @@ static struct | |||
112 | { | 106 | { |
113 | u32 freq_low; | 107 | u32 freq_low; |
114 | u32 freq_high; | 108 | u32 freq_high; |
115 | u32 bandselect; | ||
116 | u32 VCOdivider; | 109 | u32 VCOdivider; |
117 | u32 VCOnumber; | ||
118 | u32 progdata; | 110 | u32 progdata; |
119 | } cx24123_bandselect_vals[] = | 111 | } cx24123_bandselect_vals[] = |
120 | { | 112 | { |
113 | /* band 1 */ | ||
121 | { | 114 | { |
122 | .freq_low = 950000, | 115 | .freq_low = 950000, |
123 | .freq_high = 1018999, | ||
124 | .bandselect = 0x40, | ||
125 | .VCOdivider = 4, | ||
126 | .VCOnumber = 7, | ||
127 | .progdata = (0 << 18) | (0 << 9) | 0x40, | ||
128 | }, | ||
129 | { | ||
130 | .freq_low = 1019000, | ||
131 | .freq_high = 1074999, | 116 | .freq_high = 1074999, |
132 | .bandselect = 0x80, | ||
133 | .VCOdivider = 4, | 117 | .VCOdivider = 4, |
134 | .VCOnumber = 8, | 118 | .progdata = (0 << 19) | (0 << 9) | 0x40, |
135 | .progdata = (0 << 18) | (0 << 9) | 0x80, | ||
136 | }, | 119 | }, |
120 | |||
121 | /* band 2 */ | ||
137 | { | 122 | { |
138 | .freq_low = 1075000, | 123 | .freq_low = 1075000, |
139 | .freq_high = 1227999, | 124 | .freq_high = 1177999, |
140 | .bandselect = 0x01, | 125 | .VCOdivider = 4, |
141 | .VCOdivider = 2, | 126 | .progdata = (0 << 19) | (0 << 9) | 0x80, |
142 | .VCOnumber = 1, | ||
143 | .progdata = (0 << 18) | (1 << 9) | 0x01, | ||
144 | }, | 127 | }, |
128 | |||
129 | /* band 3 */ | ||
145 | { | 130 | { |
146 | .freq_low = 1228000, | 131 | .freq_low = 1178000, |
147 | .freq_high = 1349999, | 132 | .freq_high = 1295999, |
148 | .bandselect = 0x02, | ||
149 | .VCOdivider = 2, | 133 | .VCOdivider = 2, |
150 | .VCOnumber = 2, | 134 | .progdata = (0 << 19) | (1 << 9) | 0x01, |
151 | .progdata = (0 << 18) | (1 << 9) | 0x02, | ||
152 | }, | 135 | }, |
136 | |||
137 | /* band 4 */ | ||
153 | { | 138 | { |
154 | .freq_low = 1350000, | 139 | .freq_low = 1296000, |
155 | .freq_high = 1481999, | 140 | .freq_high = 1431999, |
156 | .bandselect = 0x04, | ||
157 | .VCOdivider = 2, | 141 | .VCOdivider = 2, |
158 | .VCOnumber = 3, | 142 | .progdata = (0 << 19) | (1 << 9) | 0x02, |
159 | .progdata = (0 << 18) | (1 << 9) | 0x04, | ||
160 | }, | 143 | }, |
144 | |||
145 | /* band 5 */ | ||
161 | { | 146 | { |
162 | .freq_low = 1482000, | 147 | .freq_low = 1432000, |
163 | .freq_high = 1595999, | 148 | .freq_high = 1575999, |
164 | .bandselect = 0x08, | ||
165 | .VCOdivider = 2, | 149 | .VCOdivider = 2, |
166 | .VCOnumber = 4, | 150 | .progdata = (0 << 19) | (1 << 9) | 0x04, |
167 | .progdata = (0 << 18) | (1 << 9) | 0x08, | ||
168 | }, | 151 | }, |
152 | |||
153 | /* band 6 */ | ||
169 | { | 154 | { |
170 | .freq_low = 1596000, | 155 | .freq_low = 1576000, |
171 | .freq_high = 1717999, | 156 | .freq_high = 1717999, |
172 | .bandselect = 0x10, | ||
173 | .VCOdivider = 2, | 157 | .VCOdivider = 2, |
174 | .VCOnumber = 5, | 158 | .progdata = (0 << 19) | (1 << 9) | 0x08, |
175 | .progdata = (0 << 18) | (1 << 9) | 0x10, | ||
176 | }, | 159 | }, |
160 | |||
161 | /* band 7 */ | ||
177 | { | 162 | { |
178 | .freq_low = 1718000, | 163 | .freq_low = 1718000, |
179 | .freq_high = 1855999, | 164 | .freq_high = 1855999, |
180 | .bandselect = 0x20, | ||
181 | .VCOdivider = 2, | 165 | .VCOdivider = 2, |
182 | .VCOnumber = 6, | 166 | .progdata = (0 << 19) | (1 << 9) | 0x10, |
183 | .progdata = (0 << 18) | (1 << 9) | 0x20, | ||
184 | }, | 167 | }, |
168 | |||
169 | /* band 8 */ | ||
185 | { | 170 | { |
186 | .freq_low = 1856000, | 171 | .freq_low = 1856000, |
187 | .freq_high = 2035999, | 172 | .freq_high = 2035999, |
188 | .bandselect = 0x40, | ||
189 | .VCOdivider = 2, | 173 | .VCOdivider = 2, |
190 | .VCOnumber = 7, | 174 | .progdata = (0 << 19) | (1 << 9) | 0x20, |
191 | .progdata = (0 << 18) | (1 << 9) | 0x40, | ||
192 | }, | 175 | }, |
176 | |||
177 | /* band 9 */ | ||
193 | { | 178 | { |
194 | .freq_low = 2036000, | 179 | .freq_low = 2036000, |
195 | .freq_high = 2149999, | 180 | .freq_high = 2150000, |
196 | .bandselect = 0x80, | ||
197 | .VCOdivider = 2, | 181 | .VCOdivider = 2, |
198 | .VCOnumber = 8, | 182 | .progdata = (0 << 19) | (1 << 9) | 0x40, |
199 | .progdata = (0 << 18) | (1 << 9) | 0x80, | ||
200 | }, | 183 | }, |
201 | }; | 184 | }; |
202 | 185 | ||
@@ -207,49 +190,44 @@ static struct { | |||
207 | { | 190 | { |
208 | {0x00, 0x03}, /* Reset system */ | 191 | {0x00, 0x03}, /* Reset system */ |
209 | {0x00, 0x00}, /* Clear reset */ | 192 | {0x00, 0x00}, /* Clear reset */ |
210 | {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */ | 193 | {0x03, 0x07}, /* QPSK, DVB, Auto Acquisition (default) */ |
211 | {0x03, 0x07}, | 194 | {0x04, 0x10}, /* MPEG */ |
212 | {0x04, 0x10}, | 195 | {0x05, 0x04}, /* MPEG */ |
213 | {0x05, 0x04}, | 196 | {0x06, 0x31}, /* MPEG (default) */ |
214 | {0x06, 0x31}, | 197 | {0x0b, 0x00}, /* Freq search start point (default) */ |
215 | {0x0d, 0x02}, | 198 | {0x0c, 0x00}, /* Demodulator sample gain (default) */ |
216 | {0x0e, 0x03}, | 199 | {0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */ |
217 | {0x0f, 0xfe}, | 200 | {0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */ |
218 | {0x10, 0x01}, | 201 | {0x0f, 0xfe}, /* FEC search mask (all supported codes) */ |
219 | {0x14, 0x01}, | 202 | {0x10, 0x01}, /* Default search inversion, no repeat (default) */ |
220 | {0x15, 0x98}, | 203 | {0x16, 0x00}, /* Enable reading of frequency */ |
221 | {0x16, 0x00}, | 204 | {0x17, 0x01}, /* Enable EsNO Ready Counter */ |
222 | {0x17, 0x01}, | 205 | {0x1c, 0x80}, /* Enable error counter */ |
223 | {0x1b, 0x05}, | 206 | {0x20, 0x00}, /* Tuner burst clock rate = 500KHz */ |
224 | {0x1c, 0x80}, | 207 | {0x21, 0x15}, /* Tuner burst mode, word length = 0x15 */ |
225 | {0x1d, 0x00}, | 208 | {0x28, 0x00}, /* Enable FILTERV with positive pol., DiSEqC 2.x off */ |
226 | {0x1e, 0x00}, | 209 | {0x29, 0x00}, /* DiSEqC LNB_DC off */ |
227 | {0x20, 0x41}, | 210 | {0x2a, 0xb0}, /* DiSEqC Parameters (default) */ |
228 | {0x21, 0x15}, | 211 | {0x2b, 0x73}, /* DiSEqC Tone Frequency (default) */ |
229 | {0x27, 0x14}, | 212 | {0x2c, 0x00}, /* DiSEqC Message (0x2c - 0x31) */ |
230 | {0x28, 0x46}, | ||
231 | {0x29, 0x00}, | ||
232 | {0x2a, 0xb0}, | ||
233 | {0x2b, 0x73}, | ||
234 | {0x2c, 0x00}, | ||
235 | {0x2d, 0x00}, | 213 | {0x2d, 0x00}, |
236 | {0x2e, 0x00}, | 214 | {0x2e, 0x00}, |
237 | {0x2f, 0x00}, | 215 | {0x2f, 0x00}, |
238 | {0x30, 0x00}, | 216 | {0x30, 0x00}, |
239 | {0x31, 0x00}, | 217 | {0x31, 0x00}, |
240 | {0x32, 0x8c}, | 218 | {0x32, 0x8c}, /* DiSEqC Parameters (default) */ |
241 | {0x33, 0x00}, | 219 | {0x33, 0x00}, /* Interrupts off (0x33 - 0x34) */ |
242 | {0x34, 0x00}, | 220 | {0x34, 0x00}, |
243 | {0x35, 0x03}, | 221 | {0x35, 0x03}, /* DiSEqC Tone Amplitude (default) */ |
244 | {0x36, 0x02}, | 222 | {0x36, 0x02}, /* DiSEqC Parameters (default) */ |
245 | {0x37, 0x3a}, | 223 | {0x37, 0x3a}, /* DiSEqC Parameters (default) */ |
246 | {0x3a, 0x00}, /* Enable AGC accumulator */ | 224 | {0x3a, 0x00}, /* Enable AGC accumulator (for signal strength) */ |
247 | {0x44, 0x00}, | 225 | {0x44, 0x00}, /* Constellation (default) */ |
248 | {0x45, 0x00}, | 226 | {0x45, 0x00}, /* Symbol count (default) */ |
249 | {0x46, 0x05}, | 227 | {0x46, 0x0d}, /* Symbol rate estimator on (default) */ |
250 | {0x56, 0x41}, | 228 | {0x56, 0x41}, /* Various (default) */ |
251 | {0x57, 0xff}, | 229 | {0x57, 0xff}, /* Error Counter Window (default) */ |
252 | {0x67, 0x83}, | 230 | {0x67, 0x83}, /* Non-DCII symbol clock */ |
253 | }; | 231 | }; |
254 | 232 | ||
255 | static int cx24123_writereg(struct cx24123_state* state, int reg, int data) | 233 | static int cx24123_writereg(struct cx24123_state* state, int reg, int data) |
@@ -258,6 +236,10 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data) | |||
258 | struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; | 236 | struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; |
259 | int err; | 237 | int err; |
260 | 238 | ||
239 | if (debug>1) | ||
240 | printk("cx24123: %s: write reg 0x%02x, value 0x%02x\n", | ||
241 | __FUNCTION__,reg, data); | ||
242 | |||
261 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { | 243 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { |
262 | printk("%s: writereg error(err == %i, reg == 0x%02x," | 244 | printk("%s: writereg error(err == %i, reg == 0x%02x," |
263 | " data == 0x%02x)\n", __FUNCTION__, err, reg, data); | 245 | " data == 0x%02x)\n", __FUNCTION__, err, reg, data); |
@@ -274,6 +256,10 @@ static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data) | |||
274 | struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 }; | 256 | struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 }; |
275 | int err; | 257 | int err; |
276 | 258 | ||
259 | if (debug>1) | ||
260 | printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n", | ||
261 | __FUNCTION__,reg, data); | ||
262 | |||
277 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { | 263 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { |
278 | printk("%s: writelnbreg error (err == %i, reg == 0x%02x," | 264 | printk("%s: writelnbreg error (err == %i, reg == 0x%02x," |
279 | " data == 0x%02x)\n", __FUNCTION__, err, reg, data); | 265 | " data == 0x%02x)\n", __FUNCTION__, err, reg, data); |
@@ -303,6 +289,9 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg) | |||
303 | return ret; | 289 | return ret; |
304 | } | 290 | } |
305 | 291 | ||
292 | if (debug>1) | ||
293 | printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret); | ||
294 | |||
306 | return b1[0]; | 295 | return b1[0]; |
307 | } | 296 | } |
308 | 297 | ||
@@ -313,17 +302,23 @@ static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg) | |||
313 | 302 | ||
314 | static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) | 303 | static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) |
315 | { | 304 | { |
305 | u8 nom_reg = cx24123_readreg(state, 0x0e); | ||
306 | u8 auto_reg = cx24123_readreg(state, 0x10); | ||
307 | |||
316 | switch (inversion) { | 308 | switch (inversion) { |
317 | case INVERSION_OFF: | 309 | case INVERSION_OFF: |
318 | cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f); | 310 | dprintk("%s: inversion off\n",__FUNCTION__); |
319 | cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); | 311 | cx24123_writereg(state, 0x0e, nom_reg & ~0x80); |
312 | cx24123_writereg(state, 0x10, auto_reg | 0x80); | ||
320 | break; | 313 | break; |
321 | case INVERSION_ON: | 314 | case INVERSION_ON: |
322 | cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80); | 315 | dprintk("%s: inversion on\n",__FUNCTION__); |
323 | cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); | 316 | cx24123_writereg(state, 0x0e, nom_reg | 0x80); |
317 | cx24123_writereg(state, 0x10, auto_reg | 0x80); | ||
324 | break; | 318 | break; |
325 | case INVERSION_AUTO: | 319 | case INVERSION_AUTO: |
326 | cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f); | 320 | dprintk("%s: inversion auto\n",__FUNCTION__); |
321 | cx24123_writereg(state, 0x10, auto_reg & ~0x80); | ||
327 | break; | 322 | break; |
328 | default: | 323 | default: |
329 | return -EINVAL; | 324 | return -EINVAL; |
@@ -338,92 +333,191 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers | |||
338 | 333 | ||
339 | val = cx24123_readreg(state, 0x1b) >> 7; | 334 | val = cx24123_readreg(state, 0x1b) >> 7; |
340 | 335 | ||
341 | if (val == 0) | 336 | if (val == 0) { |
337 | dprintk("%s: read inversion off\n",__FUNCTION__); | ||
342 | *inversion = INVERSION_OFF; | 338 | *inversion = INVERSION_OFF; |
343 | else | 339 | } else { |
340 | dprintk("%s: read inversion on\n",__FUNCTION__); | ||
344 | *inversion = INVERSION_ON; | 341 | *inversion = INVERSION_ON; |
342 | } | ||
345 | 343 | ||
346 | return 0; | 344 | return 0; |
347 | } | 345 | } |
348 | 346 | ||
349 | static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) | 347 | static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) |
350 | { | 348 | { |
349 | u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07; | ||
350 | |||
351 | if ( (fec < FEC_NONE) || (fec > FEC_AUTO) ) | 351 | if ( (fec < FEC_NONE) || (fec > FEC_AUTO) ) |
352 | fec = FEC_AUTO; | 352 | fec = FEC_AUTO; |
353 | 353 | ||
354 | /* Hardware has 5/11 and 3/5 but are never unused */ | ||
355 | switch (fec) { | 354 | switch (fec) { |
356 | case FEC_NONE: | ||
357 | return cx24123_writereg(state, 0x0f, 0x01); | ||
358 | case FEC_1_2: | 355 | case FEC_1_2: |
359 | return cx24123_writereg(state, 0x0f, 0x02); | 356 | dprintk("%s: set FEC to 1/2\n",__FUNCTION__); |
357 | cx24123_writereg(state, 0x0e, nom_reg | 0x01); | ||
358 | cx24123_writereg(state, 0x0f, 0x02); | ||
359 | break; | ||
360 | case FEC_2_3: | 360 | case FEC_2_3: |
361 | return cx24123_writereg(state, 0x0f, 0x04); | 361 | dprintk("%s: set FEC to 2/3\n",__FUNCTION__); |
362 | cx24123_writereg(state, 0x0e, nom_reg | 0x02); | ||
363 | cx24123_writereg(state, 0x0f, 0x04); | ||
364 | break; | ||
362 | case FEC_3_4: | 365 | case FEC_3_4: |
363 | return cx24123_writereg(state, 0x0f, 0x08); | 366 | dprintk("%s: set FEC to 3/4\n",__FUNCTION__); |
367 | cx24123_writereg(state, 0x0e, nom_reg | 0x03); | ||
368 | cx24123_writereg(state, 0x0f, 0x08); | ||
369 | break; | ||
370 | case FEC_4_5: | ||
371 | dprintk("%s: set FEC to 4/5\n",__FUNCTION__); | ||
372 | cx24123_writereg(state, 0x0e, nom_reg | 0x04); | ||
373 | cx24123_writereg(state, 0x0f, 0x10); | ||
374 | break; | ||
364 | case FEC_5_6: | 375 | case FEC_5_6: |
365 | return cx24123_writereg(state, 0x0f, 0x20); | 376 | dprintk("%s: set FEC to 5/6\n",__FUNCTION__); |
377 | cx24123_writereg(state, 0x0e, nom_reg | 0x05); | ||
378 | cx24123_writereg(state, 0x0f, 0x20); | ||
379 | break; | ||
380 | case FEC_6_7: | ||
381 | dprintk("%s: set FEC to 6/7\n",__FUNCTION__); | ||
382 | cx24123_writereg(state, 0x0e, nom_reg | 0x06); | ||
383 | cx24123_writereg(state, 0x0f, 0x40); | ||
384 | break; | ||
366 | case FEC_7_8: | 385 | case FEC_7_8: |
367 | return cx24123_writereg(state, 0x0f, 0x80); | 386 | dprintk("%s: set FEC to 7/8\n",__FUNCTION__); |
387 | cx24123_writereg(state, 0x0e, nom_reg | 0x07); | ||
388 | cx24123_writereg(state, 0x0f, 0x80); | ||
389 | break; | ||
368 | case FEC_AUTO: | 390 | case FEC_AUTO: |
369 | return cx24123_writereg(state, 0x0f, 0xae); | 391 | dprintk("%s: set FEC to auto\n",__FUNCTION__); |
392 | cx24123_writereg(state, 0x0f, 0xfe); | ||
393 | break; | ||
370 | default: | 394 | default: |
371 | return -EOPNOTSUPP; | 395 | return -EOPNOTSUPP; |
372 | } | 396 | } |
397 | |||
398 | return 0; | ||
373 | } | 399 | } |
374 | 400 | ||
375 | static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) | 401 | static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) |
376 | { | 402 | { |
377 | int ret; | 403 | int ret; |
378 | u8 val; | ||
379 | 404 | ||
380 | ret = cx24123_readreg (state, 0x1b); | 405 | ret = cx24123_readreg (state, 0x1b); |
381 | if (ret < 0) | 406 | if (ret < 0) |
382 | return ret; | 407 | return ret; |
383 | val = ret & 0x07; | 408 | ret = ret & 0x07; |
384 | switch (val) { | 409 | |
410 | switch (ret) { | ||
385 | case 1: | 411 | case 1: |
386 | *fec = FEC_1_2; | 412 | *fec = FEC_1_2; |
387 | break; | 413 | break; |
388 | case 3: | 414 | case 2: |
389 | *fec = FEC_2_3; | 415 | *fec = FEC_2_3; |
390 | break; | 416 | break; |
391 | case 4: | 417 | case 3: |
392 | *fec = FEC_3_4; | 418 | *fec = FEC_3_4; |
393 | break; | 419 | break; |
394 | case 5: | 420 | case 4: |
395 | *fec = FEC_4_5; | 421 | *fec = FEC_4_5; |
396 | break; | 422 | break; |
397 | case 6: | 423 | case 5: |
398 | *fec = FEC_5_6; | 424 | *fec = FEC_5_6; |
399 | break; | 425 | break; |
426 | case 6: | ||
427 | *fec = FEC_6_7; | ||
428 | break; | ||
400 | case 7: | 429 | case 7: |
401 | *fec = FEC_7_8; | 430 | *fec = FEC_7_8; |
402 | break; | 431 | 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: | 432 | default: |
408 | *fec = FEC_NONE; // can't happen | 433 | /* this can happen when there's no lock */ |
434 | *fec = FEC_NONE; | ||
409 | } | 435 | } |
410 | 436 | ||
411 | return 0; | 437 | return 0; |
412 | } | 438 | } |
413 | 439 | ||
414 | /* fixme: Symbol rates < 3MSps may not work because of precision loss */ | 440 | /* Approximation of closest integer of log2(a/b). It actually gives the |
441 | lowest integer i such that 2^i >= round(a/b) */ | ||
442 | static u32 cx24123_int_log2(u32 a, u32 b) | ||
443 | { | ||
444 | u32 exp, nearest = 0; | ||
445 | u32 div = a / b; | ||
446 | if(a % b >= b / 2) ++div; | ||
447 | if(div < (1 << 31)) | ||
448 | { | ||
449 | for(exp = 1; div > exp; nearest++) | ||
450 | exp += exp; | ||
451 | } | ||
452 | return nearest; | ||
453 | } | ||
454 | |||
415 | static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) | 455 | static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) |
416 | { | 456 | { |
417 | u32 val; | 457 | u32 tmp, sample_rate, ratio, sample_gain; |
458 | u8 pll_mult; | ||
459 | |||
460 | /* check if symbol rate is within limits */ | ||
461 | if ((srate > state->ops.info.symbol_rate_max) || | ||
462 | (srate < state->ops.info.symbol_rate_min)) | ||
463 | return -EOPNOTSUPP;; | ||
464 | |||
465 | /* choose the sampling rate high enough for the required operation, | ||
466 | while optimizing the power consumed by the demodulator */ | ||
467 | if (srate < (XTAL*2)/2) | ||
468 | pll_mult = 2; | ||
469 | else if (srate < (XTAL*3)/2) | ||
470 | pll_mult = 3; | ||
471 | else if (srate < (XTAL*4)/2) | ||
472 | pll_mult = 4; | ||
473 | else if (srate < (XTAL*5)/2) | ||
474 | pll_mult = 5; | ||
475 | else if (srate < (XTAL*6)/2) | ||
476 | pll_mult = 6; | ||
477 | else if (srate < (XTAL*7)/2) | ||
478 | pll_mult = 7; | ||
479 | else if (srate < (XTAL*8)/2) | ||
480 | pll_mult = 8; | ||
481 | else | ||
482 | pll_mult = 9; | ||
483 | |||
484 | |||
485 | sample_rate = pll_mult * XTAL; | ||
486 | |||
487 | /* | ||
488 | SYSSymbolRate[21:0] = (srate << 23) / sample_rate | ||
489 | |||
490 | We have to use 32 bit unsigned arithmetic without precision loss. | ||
491 | The maximum srate is 45000000 or 0x02AEA540. This number has | ||
492 | only 6 clear bits on top, hence we can shift it left only 6 bits | ||
493 | at a time. Borrowed from cx24110.c | ||
494 | */ | ||
495 | |||
496 | tmp = srate << 6; | ||
497 | ratio = tmp / sample_rate; | ||
498 | |||
499 | tmp = (tmp % sample_rate) << 6; | ||
500 | ratio = (ratio << 6) + (tmp / sample_rate); | ||
501 | |||
502 | tmp = (tmp % sample_rate) << 6; | ||
503 | ratio = (ratio << 6) + (tmp / sample_rate); | ||
504 | |||
505 | tmp = (tmp % sample_rate) << 5; | ||
506 | ratio = (ratio << 5) + (tmp / sample_rate); | ||
507 | |||
508 | |||
509 | cx24123_writereg(state, 0x01, pll_mult * 6); | ||
418 | 510 | ||
419 | val = (srate / 1185) * 100; | 511 | cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f ); |
512 | cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff ); | ||
513 | cx24123_writereg(state, 0x0a, (ratio ) & 0xff ); | ||
420 | 514 | ||
421 | /* Compensate for scaling up, by removing 17 symbols per 1Msps */ | 515 | /* also set the demodulator sample gain */ |
422 | val = val - (17 * (srate / 1000000)); | 516 | sample_gain = cx24123_int_log2(sample_rate, srate); |
517 | tmp = cx24123_readreg(state, 0x0c) & ~0xe0; | ||
518 | cx24123_writereg(state, 0x0c, tmp | sample_gain << 5); | ||
423 | 519 | ||
424 | cx24123_writereg(state, 0x08, (val >> 16) & 0xff ); | 520 | dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain); |
425 | cx24123_writereg(state, 0x09, (val >> 8) & 0xff ); | ||
426 | cx24123_writereg(state, 0x0a, (val ) & 0xff ); | ||
427 | 521 | ||
428 | return 0; | 522 | return 0; |
429 | } | 523 | } |
@@ -437,6 +531,9 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa | |||
437 | struct cx24123_state *state = fe->demodulator_priv; | 531 | struct cx24123_state *state = fe->demodulator_priv; |
438 | u32 ndiv = 0, adiv = 0, vco_div = 0; | 532 | u32 ndiv = 0, adiv = 0, vco_div = 0; |
439 | int i = 0; | 533 | int i = 0; |
534 | int pump = 2; | ||
535 | int band = 0; | ||
536 | int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); | ||
440 | 537 | ||
441 | /* Defaults for low freq, low rate */ | 538 | /* Defaults for low freq, low rate */ |
442 | state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; | 539 | state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; |
@@ -444,38 +541,49 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa | |||
444 | state->bandselectarg = cx24123_bandselect_vals[0].progdata; | 541 | state->bandselectarg = cx24123_bandselect_vals[0].progdata; |
445 | vco_div = cx24123_bandselect_vals[0].VCOdivider; | 542 | vco_div = cx24123_bandselect_vals[0].VCOdivider; |
446 | 543 | ||
447 | /* For the given symbolerate, determine the VCA and VGA programming bits */ | 544 | /* 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++) | 545 | for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++) |
449 | { | 546 | { |
450 | if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && | 547 | if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && |
451 | (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { | 548 | (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { |
452 | state->VCAarg = cx24123_AGC_vals[i].VCAprogdata; | 549 | state->VCAarg = cx24123_AGC_vals[i].VCAprogdata; |
453 | state->VGAarg = cx24123_AGC_vals[i].VGAprogdata; | 550 | state->VGAarg = cx24123_AGC_vals[i].VGAprogdata; |
551 | state->FILTune = cx24123_AGC_vals[i].FILTune; | ||
454 | } | 552 | } |
455 | } | 553 | } |
456 | 554 | ||
457 | /* For the given frequency, determine the bandselect programming bits */ | 555 | /* determine the band to use */ |
458 | for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++) | 556 | if(force_band < 1 || force_band > num_bands) |
459 | { | 557 | { |
460 | if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && | 558 | for (i = 0; i < num_bands; i++) |
461 | (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) { | 559 | { |
462 | state->bandselectarg = cx24123_bandselect_vals[i].progdata; | 560 | if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && |
463 | vco_div = cx24123_bandselect_vals[i].VCOdivider; | 561 | (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) |
562 | band = i; | ||
464 | } | 563 | } |
465 | } | 564 | } |
565 | else | ||
566 | band = force_band - 1; | ||
567 | |||
568 | state->bandselectarg = cx24123_bandselect_vals[band].progdata; | ||
569 | vco_div = cx24123_bandselect_vals[band].VCOdivider; | ||
570 | |||
571 | /* determine the charge pump current */ | ||
572 | if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 ) | ||
573 | pump = 0x01; | ||
574 | else | ||
575 | pump = 0x02; | ||
466 | 576 | ||
467 | /* Determine the N/A dividers for the requested lband freq (in kHz). */ | 577 | /* Determine the N/A dividers for the requested lband freq (in kHz). */ |
468 | /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */ | 578 | /* 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; | 579 | ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff; |
470 | adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f; | 580 | adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f; |
471 | 581 | ||
472 | if (adiv == 0) | 582 | if (adiv == 0) |
473 | adiv++; | 583 | ndiv++; |
474 | 584 | ||
475 | /* determine the correct pll frequency values. */ | 585 | /* 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. */ | 586 | 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 | 587 | ||
480 | return 0; | 588 | return 0; |
481 | } | 589 | } |
@@ -489,6 +597,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par | |||
489 | struct cx24123_state *state = fe->demodulator_priv; | 597 | struct cx24123_state *state = fe->demodulator_priv; |
490 | unsigned long timeout; | 598 | unsigned long timeout; |
491 | 599 | ||
600 | dprintk("%s: pll writereg called, data=0x%08x\n",__FUNCTION__,data); | ||
601 | |||
492 | /* align the 21 bytes into to bit23 boundary */ | 602 | /* align the 21 bytes into to bit23 boundary */ |
493 | data = data << 3; | 603 | data = data << 3; |
494 | 604 | ||
@@ -538,6 +648,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) | 648 | static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) |
539 | { | 649 | { |
540 | struct cx24123_state *state = fe->demodulator_priv; | 650 | struct cx24123_state *state = fe->demodulator_priv; |
651 | u8 val; | ||
652 | |||
653 | dprintk("frequency=%i\n", p->frequency); | ||
541 | 654 | ||
542 | if (cx24123_pll_calculate(fe, p) != 0) { | 655 | if (cx24123_pll_calculate(fe, p) != 0) { |
543 | printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); | 656 | printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); |
@@ -552,6 +665,14 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet | |||
552 | cx24123_pll_writereg(fe, p, state->bandselectarg); | 665 | cx24123_pll_writereg(fe, p, state->bandselectarg); |
553 | cx24123_pll_writereg(fe, p, state->pllarg); | 666 | cx24123_pll_writereg(fe, p, state->pllarg); |
554 | 667 | ||
668 | /* set the FILTUNE voltage */ | ||
669 | val = cx24123_readreg(state, 0x28) & ~0x3; | ||
670 | cx24123_writereg(state, 0x27, state->FILTune >> 2); | ||
671 | cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3)); | ||
672 | |||
673 | dprintk("%s: pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg, | ||
674 | state->bandselectarg,state->pllarg); | ||
675 | |||
555 | return 0; | 676 | return 0; |
556 | } | 677 | } |
557 | 678 | ||
@@ -560,6 +681,8 @@ static int cx24123_initfe(struct dvb_frontend* fe) | |||
560 | struct cx24123_state *state = fe->demodulator_priv; | 681 | struct cx24123_state *state = fe->demodulator_priv; |
561 | int i; | 682 | int i; |
562 | 683 | ||
684 | dprintk("%s: init frontend\n",__FUNCTION__); | ||
685 | |||
563 | /* Configure the demod to a good set of defaults */ | 686 | /* Configure the demod to a good set of defaults */ |
564 | for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) | 687 | for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) |
565 | cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); | 688 | cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); |
@@ -587,10 +710,13 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage | |||
587 | 710 | ||
588 | switch (voltage) { | 711 | switch (voltage) { |
589 | case SEC_VOLTAGE_13: | 712 | case SEC_VOLTAGE_13: |
713 | dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__); | ||
590 | return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */ | 714 | return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */ |
591 | case SEC_VOLTAGE_18: | 715 | case SEC_VOLTAGE_18: |
716 | dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__); | ||
592 | return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */ | 717 | return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */ |
593 | case SEC_VOLTAGE_OFF: | 718 | case SEC_VOLTAGE_OFF: |
719 | dprintk("%s: isl5421 voltage off\n",__FUNCTION__); | ||
594 | return cx24123_writelnbreg(state, 0x0, val & 0x30); | 720 | return cx24123_writelnbreg(state, 0x0, val & 0x30); |
595 | default: | 721 | default: |
596 | return -EINVAL; | 722 | return -EINVAL; |
@@ -624,13 +750,93 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage | |||
624 | return 0; | 750 | return 0; |
625 | } | 751 | } |
626 | 752 | ||
627 | static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, | 753 | /* wait for diseqc queue to become ready (or timeout) */ |
628 | struct dvb_diseqc_master_cmd *cmd) | 754 | static void cx24123_wait_for_diseqc(struct cx24123_state *state) |
755 | { | ||
756 | unsigned long timeout = jiffies + msecs_to_jiffies(200); | ||
757 | while (!(cx24123_readreg(state, 0x29) & 0x40)) { | ||
758 | if(time_after(jiffies, timeout)) { | ||
759 | printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__); | ||
760 | break; | ||
761 | } | ||
762 | msleep(10); | ||
763 | } | ||
764 | } | ||
765 | |||
766 | static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) | ||
629 | { | 767 | { |
630 | /* fixme: Implement diseqc */ | 768 | struct cx24123_state *state = fe->demodulator_priv; |
631 | printk("%s: No support yet\n",__FUNCTION__); | 769 | int i, val; |
770 | |||
771 | dprintk("%s:\n",__FUNCTION__); | ||
772 | |||
773 | /* check if continuous tone has been stopped */ | ||
774 | if (state->config->use_isl6421) | ||
775 | val = cx24123_readlnbreg(state, 0x00) & 0x10; | ||
776 | else | ||
777 | val = cx24123_readreg(state, 0x29) & 0x10; | ||
632 | 778 | ||
633 | return -ENOTSUPP; | 779 | |
780 | if (val) { | ||
781 | printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); | ||
782 | return -ENOTSUPP; | ||
783 | } | ||
784 | |||
785 | /* wait for diseqc queue ready */ | ||
786 | cx24123_wait_for_diseqc(state); | ||
787 | |||
788 | /* select tone mode */ | ||
789 | cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8); | ||
790 | |||
791 | for (i = 0; i < cmd->msg_len; i++) | ||
792 | cx24123_writereg(state, 0x2C + i, cmd->msg[i]); | ||
793 | |||
794 | val = cx24123_readreg(state, 0x29); | ||
795 | cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); | ||
796 | |||
797 | /* wait for diseqc message to finish sending */ | ||
798 | cx24123_wait_for_diseqc(state); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) | ||
804 | { | ||
805 | struct cx24123_state *state = fe->demodulator_priv; | ||
806 | int val; | ||
807 | |||
808 | dprintk("%s:\n", __FUNCTION__); | ||
809 | |||
810 | /* check if continuous tone has been stoped */ | ||
811 | if (state->config->use_isl6421) | ||
812 | val = cx24123_readlnbreg(state, 0x00) & 0x10; | ||
813 | else | ||
814 | val = cx24123_readreg(state, 0x29) & 0x10; | ||
815 | |||
816 | |||
817 | if (val) { | ||
818 | printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); | ||
819 | return -ENOTSUPP; | ||
820 | } | ||
821 | |||
822 | cx24123_wait_for_diseqc(state); | ||
823 | |||
824 | /* select tone mode */ | ||
825 | val = cx24123_readreg(state, 0x2a) & 0xf8; | ||
826 | cx24123_writereg(state, 0x2a, val | 0x04); | ||
827 | |||
828 | val = cx24123_readreg(state, 0x29); | ||
829 | |||
830 | if (burst == SEC_MINI_A) | ||
831 | cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00)); | ||
832 | else if (burst == SEC_MINI_B) | ||
833 | cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x08)); | ||
834 | else | ||
835 | return -EINVAL; | ||
836 | |||
837 | cx24123_wait_for_diseqc(state); | ||
838 | |||
839 | return 0; | ||
634 | } | 840 | } |
635 | 841 | ||
636 | static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) | 842 | static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) |
@@ -642,13 +848,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
642 | 848 | ||
643 | *status = 0; | 849 | *status = 0; |
644 | if (lock & 0x01) | 850 | if (lock & 0x01) |
645 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | 851 | *status |= FE_HAS_SIGNAL; |
852 | if (sync & 0x02) | ||
853 | *status |= FE_HAS_CARRIER; | ||
646 | if (sync & 0x04) | 854 | if (sync & 0x04) |
647 | *status |= FE_HAS_VITERBI; | 855 | *status |= FE_HAS_VITERBI; |
648 | if (sync & 0x08) | 856 | if (sync & 0x08) |
649 | *status |= FE_HAS_CARRIER; | 857 | *status |= FE_HAS_SYNC; |
650 | if (sync & 0x80) | 858 | if (sync & 0x80) |
651 | *status |= FE_HAS_SYNC | FE_HAS_LOCK; | 859 | *status |= FE_HAS_LOCK; |
652 | 860 | ||
653 | return 0; | 861 | return 0; |
654 | } | 862 | } |
@@ -681,6 +889,8 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber) | |||
681 | else | 889 | else |
682 | state->snr = 0; | 890 | state->snr = 0; |
683 | 891 | ||
892 | dprintk("%s: BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr); | ||
893 | |||
684 | *ber = state->lastber; | 894 | *ber = state->lastber; |
685 | 895 | ||
686 | return 0; | 896 | return 0; |
@@ -691,6 +901,8 @@ static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_str | |||
691 | struct cx24123_state *state = fe->demodulator_priv; | 901 | struct cx24123_state *state = fe->demodulator_priv; |
692 | *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */ | 902 | *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */ |
693 | 903 | ||
904 | dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength); | ||
905 | |||
694 | return 0; | 906 | return 0; |
695 | } | 907 | } |
696 | 908 | ||
@@ -699,6 +911,8 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr) | |||
699 | struct cx24123_state *state = fe->demodulator_priv; | 911 | struct cx24123_state *state = fe->demodulator_priv; |
700 | *snr = state->snr; | 912 | *snr = state->snr; |
701 | 913 | ||
914 | dprintk("%s: read S/N index = %d\n",__FUNCTION__,*snr); | ||
915 | |||
702 | return 0; | 916 | return 0; |
703 | } | 917 | } |
704 | 918 | ||
@@ -707,6 +921,8 @@ static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | |||
707 | struct cx24123_state *state = fe->demodulator_priv; | 921 | struct cx24123_state *state = fe->demodulator_priv; |
708 | *ucblocks = state->lastber; | 922 | *ucblocks = state->lastber; |
709 | 923 | ||
924 | dprintk("%s: ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks); | ||
925 | |||
710 | return 0; | 926 | return 0; |
711 | } | 927 | } |
712 | 928 | ||
@@ -714,6 +930,8 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
714 | { | 930 | { |
715 | struct cx24123_state *state = fe->demodulator_priv; | 931 | struct cx24123_state *state = fe->demodulator_priv; |
716 | 932 | ||
933 | dprintk("%s: set_frontend\n",__FUNCTION__); | ||
934 | |||
717 | if (state->config->set_ts_params) | 935 | if (state->config->set_ts_params) |
718 | state->config->set_ts_params(fe, 0); | 936 | state->config->set_ts_params(fe, 0); |
719 | 937 | ||
@@ -737,6 +955,8 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
737 | { | 955 | { |
738 | struct cx24123_state *state = fe->demodulator_priv; | 956 | struct cx24123_state *state = fe->demodulator_priv; |
739 | 957 | ||
958 | dprintk("%s: get_frontend\n",__FUNCTION__); | ||
959 | |||
740 | if (cx24123_get_inversion(state, &p->inversion) != 0) { | 960 | if (cx24123_get_inversion(state, &p->inversion) != 0) { |
741 | printk("%s: Failed to get inversion status\n",__FUNCTION__); | 961 | printk("%s: Failed to get inversion status\n",__FUNCTION__); |
742 | return -EREMOTEIO; | 962 | return -EREMOTEIO; |
@@ -763,8 +983,10 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | |||
763 | 983 | ||
764 | switch (tone) { | 984 | switch (tone) { |
765 | case SEC_TONE_ON: | 985 | case SEC_TONE_ON: |
986 | dprintk("%s: isl6421 sec tone on\n",__FUNCTION__); | ||
766 | return cx24123_writelnbreg(state, 0x0, val | 0x10); | 987 | return cx24123_writelnbreg(state, 0x0, val | 0x10); |
767 | case SEC_TONE_OFF: | 988 | case SEC_TONE_OFF: |
989 | dprintk("%s: isl6421 sec tone off\n",__FUNCTION__); | ||
768 | return cx24123_writelnbreg(state, 0x0, val & 0x2f); | 990 | return cx24123_writelnbreg(state, 0x0, val & 0x2f); |
769 | default: | 991 | default: |
770 | printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); | 992 | printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); |
@@ -855,12 +1077,13 @@ static struct dvb_frontend_ops cx24123_ops = { | |||
855 | .frequency_min = 950000, | 1077 | .frequency_min = 950000, |
856 | .frequency_max = 2150000, | 1078 | .frequency_max = 2150000, |
857 | .frequency_stepsize = 1011, /* kHz for QPSK frontends */ | 1079 | .frequency_stepsize = 1011, /* kHz for QPSK frontends */ |
858 | .frequency_tolerance = 29500, | 1080 | .frequency_tolerance = 5000, |
859 | .symbol_rate_min = 1000000, | 1081 | .symbol_rate_min = 1000000, |
860 | .symbol_rate_max = 45000000, | 1082 | .symbol_rate_max = 45000000, |
861 | .caps = FE_CAN_INVERSION_AUTO | | 1083 | .caps = FE_CAN_INVERSION_AUTO | |
862 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | 1084 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | |
863 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | 1085 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | |
1086 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
864 | FE_CAN_QPSK | FE_CAN_RECOVER | 1087 | FE_CAN_QPSK | FE_CAN_RECOVER |
865 | }, | 1088 | }, |
866 | 1089 | ||
@@ -875,12 +1098,16 @@ static struct dvb_frontend_ops cx24123_ops = { | |||
875 | .read_snr = cx24123_read_snr, | 1098 | .read_snr = cx24123_read_snr, |
876 | .read_ucblocks = cx24123_read_ucblocks, | 1099 | .read_ucblocks = cx24123_read_ucblocks, |
877 | .diseqc_send_master_cmd = cx24123_send_diseqc_msg, | 1100 | .diseqc_send_master_cmd = cx24123_send_diseqc_msg, |
1101 | .diseqc_send_burst = cx24123_diseqc_send_burst, | ||
878 | .set_tone = cx24123_set_tone, | 1102 | .set_tone = cx24123_set_tone, |
879 | .set_voltage = cx24123_set_voltage, | 1103 | .set_voltage = cx24123_set_voltage, |
880 | }; | 1104 | }; |
881 | 1105 | ||
882 | module_param(debug, int, 0644); | 1106 | module_param(debug, int, 0644); |
883 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | 1107 | MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); |
1108 | |||
1109 | module_param(force_band, int, 0644); | ||
1110 | MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off)."); | ||
884 | 1111 | ||
885 | MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware"); | 1112 | MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware"); |
886 | MODULE_AUTHOR("Steven Toth"); | 1113 | MODULE_AUTHOR("Steven Toth"); |