diff options
author | Igor M. Liplianin <liplianin@me.by> | 2012-12-28 17:40:33 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-12-28 18:37:36 -0500 |
commit | b858c331cdf402853be2c48c8f4f77173ef04da8 (patch) | |
tree | 456fdd9581b3416fa17b359b3e417af4cf4dd73e /drivers/media/dvb-frontends | |
parent | 43385c8a645a25ddef7a45df8786ff26806f7e5d (diff) |
[media] m88rs2000: make use ts2020
Tuner part of Montage rs2000 chip is similar to ts2020 tuner.
Patch to use ts2020 code.
[mchehab@redhat.com: a few CodingStyle fixes]
Signed-off-by: Igor M. Liplianin <liplianin@me.by>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb-frontends')
-rw-r--r-- | drivers/media/dvb-frontends/m88rs2000.c | 408 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88rs2000.h | 6 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ts2020.c | 381 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ts2020.h | 1 |
4 files changed, 318 insertions, 478 deletions
diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c index df9e7dd6fe74..283c90fee374 100644 --- a/drivers/media/dvb-frontends/m88rs2000.c +++ b/drivers/media/dvb-frontends/m88rs2000.c | |||
@@ -60,15 +60,13 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); | |||
60 | #define info(format, arg...) \ | 60 | #define info(format, arg...) \ |
61 | printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg) | 61 | printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg) |
62 | 62 | ||
63 | static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner, | 63 | static int m88rs2000_writereg(struct m88rs2000_state *state, |
64 | u8 reg, u8 data) | 64 | u8 reg, u8 data) |
65 | { | 65 | { |
66 | int ret; | 66 | int ret; |
67 | u8 addr = (tuner == 0) ? state->config->tuner_addr : | ||
68 | state->config->demod_addr; | ||
69 | u8 buf[] = { reg, data }; | 67 | u8 buf[] = { reg, data }; |
70 | struct i2c_msg msg = { | 68 | struct i2c_msg msg = { |
71 | .addr = addr, | 69 | .addr = state->config->demod_addr, |
72 | .flags = 0, | 70 | .flags = 0, |
73 | .buf = buf, | 71 | .buf = buf, |
74 | .len = 2 | 72 | .len = 2 |
@@ -83,44 +81,20 @@ static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner, | |||
83 | return (ret != 1) ? -EREMOTEIO : 0; | 81 | return (ret != 1) ? -EREMOTEIO : 0; |
84 | } | 82 | } |
85 | 83 | ||
86 | static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data) | 84 | static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 reg) |
87 | { | ||
88 | return m88rs2000_writereg(state, 1, reg, data); | ||
89 | } | ||
90 | |||
91 | static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data) | ||
92 | { | ||
93 | m88rs2000_demod_write(state, 0x81, 0x84); | ||
94 | udelay(10); | ||
95 | return m88rs2000_writereg(state, 0, reg, data); | ||
96 | |||
97 | } | ||
98 | |||
99 | static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len) | ||
100 | { | ||
101 | struct m88rs2000_state *state = fe->demodulator_priv; | ||
102 | |||
103 | if (len != 2) | ||
104 | return -EINVAL; | ||
105 | |||
106 | return m88rs2000_writereg(state, 1, buf[0], buf[1]); | ||
107 | } | ||
108 | |||
109 | static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg) | ||
110 | { | 85 | { |
111 | int ret; | 86 | int ret; |
112 | u8 b0[] = { reg }; | 87 | u8 b0[] = { reg }; |
113 | u8 b1[] = { 0 }; | 88 | u8 b1[] = { 0 }; |
114 | u8 addr = (tuner == 0) ? state->config->tuner_addr : | 89 | |
115 | state->config->demod_addr; | ||
116 | struct i2c_msg msg[] = { | 90 | struct i2c_msg msg[] = { |
117 | { | 91 | { |
118 | .addr = addr, | 92 | .addr = state->config->demod_addr, |
119 | .flags = 0, | 93 | .flags = 0, |
120 | .buf = b0, | 94 | .buf = b0, |
121 | .len = 1 | 95 | .len = 1 |
122 | }, { | 96 | }, { |
123 | .addr = addr, | 97 | .addr = state->config->demod_addr, |
124 | .flags = I2C_M_RD, | 98 | .flags = I2C_M_RD, |
125 | .buf = b1, | 99 | .buf = b1, |
126 | .len = 1 | 100 | .len = 1 |
@@ -136,18 +110,6 @@ static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg) | |||
136 | return b1[0]; | 110 | return b1[0]; |
137 | } | 111 | } |
138 | 112 | ||
139 | static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg) | ||
140 | { | ||
141 | return m88rs2000_readreg(state, 1, reg); | ||
142 | } | ||
143 | |||
144 | static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg) | ||
145 | { | ||
146 | m88rs2000_demod_write(state, 0x81, 0x85); | ||
147 | udelay(10); | ||
148 | return m88rs2000_readreg(state, 0, reg); | ||
149 | } | ||
150 | |||
151 | static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) | 113 | static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) |
152 | { | 114 | { |
153 | struct m88rs2000_state *state = fe->demodulator_priv; | 115 | struct m88rs2000_state *state = fe->demodulator_priv; |
@@ -166,9 +128,9 @@ static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) | |||
166 | b[0] = (u8) (temp >> 16) & 0xff; | 128 | b[0] = (u8) (temp >> 16) & 0xff; |
167 | b[1] = (u8) (temp >> 8) & 0xff; | 129 | b[1] = (u8) (temp >> 8) & 0xff; |
168 | b[2] = (u8) temp & 0xff; | 130 | b[2] = (u8) temp & 0xff; |
169 | ret = m88rs2000_demod_write(state, 0x93, b[2]); | 131 | ret = m88rs2000_writereg(state, 0x93, b[2]); |
170 | ret |= m88rs2000_demod_write(state, 0x94, b[1]); | 132 | ret |= m88rs2000_writereg(state, 0x94, b[1]); |
171 | ret |= m88rs2000_demod_write(state, 0x95, b[0]); | 133 | ret |= m88rs2000_writereg(state, 0x95, b[0]); |
172 | 134 | ||
173 | deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); | 135 | deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); |
174 | return ret; | 136 | return ret; |
@@ -182,37 +144,37 @@ static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe, | |||
182 | int i; | 144 | int i; |
183 | u8 reg; | 145 | u8 reg; |
184 | deb_info("%s\n", __func__); | 146 | deb_info("%s\n", __func__); |
185 | m88rs2000_demod_write(state, 0x9a, 0x30); | 147 | m88rs2000_writereg(state, 0x9a, 0x30); |
186 | reg = m88rs2000_demod_read(state, 0xb2); | 148 | reg = m88rs2000_readreg(state, 0xb2); |
187 | reg &= 0x3f; | 149 | reg &= 0x3f; |
188 | m88rs2000_demod_write(state, 0xb2, reg); | 150 | m88rs2000_writereg(state, 0xb2, reg); |
189 | for (i = 0; i < m->msg_len; i++) | 151 | for (i = 0; i < m->msg_len; i++) |
190 | m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]); | 152 | m88rs2000_writereg(state, 0xb3 + i, m->msg[i]); |
191 | 153 | ||
192 | reg = m88rs2000_demod_read(state, 0xb1); | 154 | reg = m88rs2000_readreg(state, 0xb1); |
193 | reg &= 0x87; | 155 | reg &= 0x87; |
194 | reg |= ((m->msg_len - 1) << 3) | 0x07; | 156 | reg |= ((m->msg_len - 1) << 3) | 0x07; |
195 | reg &= 0x7f; | 157 | reg &= 0x7f; |
196 | m88rs2000_demod_write(state, 0xb1, reg); | 158 | m88rs2000_writereg(state, 0xb1, reg); |
197 | 159 | ||
198 | for (i = 0; i < 15; i++) { | 160 | for (i = 0; i < 15; i++) { |
199 | if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0) | 161 | if ((m88rs2000_readreg(state, 0xb1) & 0x40) == 0x0) |
200 | break; | 162 | break; |
201 | msleep(20); | 163 | msleep(20); |
202 | } | 164 | } |
203 | 165 | ||
204 | reg = m88rs2000_demod_read(state, 0xb1); | 166 | reg = m88rs2000_readreg(state, 0xb1); |
205 | if ((reg & 0x40) > 0x0) { | 167 | if ((reg & 0x40) > 0x0) { |
206 | reg &= 0x7f; | 168 | reg &= 0x7f; |
207 | reg |= 0x40; | 169 | reg |= 0x40; |
208 | m88rs2000_demod_write(state, 0xb1, reg); | 170 | m88rs2000_writereg(state, 0xb1, reg); |
209 | } | 171 | } |
210 | 172 | ||
211 | reg = m88rs2000_demod_read(state, 0xb2); | 173 | reg = m88rs2000_readreg(state, 0xb2); |
212 | reg &= 0x3f; | 174 | reg &= 0x3f; |
213 | reg |= 0x80; | 175 | reg |= 0x80; |
214 | m88rs2000_demod_write(state, 0xb2, reg); | 176 | m88rs2000_writereg(state, 0xb2, reg); |
215 | m88rs2000_demod_write(state, 0x9a, 0xb0); | 177 | m88rs2000_writereg(state, 0x9a, 0xb0); |
216 | 178 | ||
217 | 179 | ||
218 | return 0; | 180 | return 0; |
@@ -224,14 +186,14 @@ static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe, | |||
224 | struct m88rs2000_state *state = fe->demodulator_priv; | 186 | struct m88rs2000_state *state = fe->demodulator_priv; |
225 | u8 reg0, reg1; | 187 | u8 reg0, reg1; |
226 | deb_info("%s\n", __func__); | 188 | deb_info("%s\n", __func__); |
227 | m88rs2000_demod_write(state, 0x9a, 0x30); | 189 | m88rs2000_writereg(state, 0x9a, 0x30); |
228 | msleep(50); | 190 | msleep(50); |
229 | reg0 = m88rs2000_demod_read(state, 0xb1); | 191 | reg0 = m88rs2000_readreg(state, 0xb1); |
230 | reg1 = m88rs2000_demod_read(state, 0xb2); | 192 | reg1 = m88rs2000_readreg(state, 0xb2); |
231 | /* TODO complete this section */ | 193 | /* TODO complete this section */ |
232 | m88rs2000_demod_write(state, 0xb2, reg1); | 194 | m88rs2000_writereg(state, 0xb2, reg1); |
233 | m88rs2000_demod_write(state, 0xb1, reg0); | 195 | m88rs2000_writereg(state, 0xb1, reg0); |
234 | m88rs2000_demod_write(state, 0x9a, 0xb0); | 196 | m88rs2000_writereg(state, 0x9a, 0xb0); |
235 | 197 | ||
236 | return 0; | 198 | return 0; |
237 | } | 199 | } |
@@ -240,9 +202,9 @@ static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | |||
240 | { | 202 | { |
241 | struct m88rs2000_state *state = fe->demodulator_priv; | 203 | struct m88rs2000_state *state = fe->demodulator_priv; |
242 | u8 reg0, reg1; | 204 | u8 reg0, reg1; |
243 | m88rs2000_demod_write(state, 0x9a, 0x30); | 205 | m88rs2000_writereg(state, 0x9a, 0x30); |
244 | reg0 = m88rs2000_demod_read(state, 0xb1); | 206 | reg0 = m88rs2000_readreg(state, 0xb1); |
245 | reg1 = m88rs2000_demod_read(state, 0xb2); | 207 | reg1 = m88rs2000_readreg(state, 0xb2); |
246 | 208 | ||
247 | reg1 &= 0x3f; | 209 | reg1 &= 0x3f; |
248 | 210 | ||
@@ -257,9 +219,9 @@ static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | |||
257 | default: | 219 | default: |
258 | break; | 220 | break; |
259 | } | 221 | } |
260 | m88rs2000_demod_write(state, 0xb2, reg1); | 222 | m88rs2000_writereg(state, 0xb2, reg1); |
261 | m88rs2000_demod_write(state, 0xb1, reg0); | 223 | m88rs2000_writereg(state, 0xb1, reg0); |
262 | m88rs2000_demod_write(state, 0x9a, 0xb0); | 224 | m88rs2000_writereg(state, 0x9a, 0xb0); |
263 | return 0; | 225 | return 0; |
264 | } | 226 | } |
265 | 227 | ||
@@ -276,14 +238,6 @@ struct inittab m88rs2000_setup[] = { | |||
276 | {DEMOD_WRITE, 0x00, 0x00}, | 238 | {DEMOD_WRITE, 0x00, 0x00}, |
277 | {DEMOD_WRITE, 0x9a, 0xb0}, | 239 | {DEMOD_WRITE, 0x9a, 0xb0}, |
278 | {DEMOD_WRITE, 0x81, 0xc1}, | 240 | {DEMOD_WRITE, 0x81, 0xc1}, |
279 | {TUNER_WRITE, 0x42, 0x73}, | ||
280 | {TUNER_WRITE, 0x05, 0x07}, | ||
281 | {TUNER_WRITE, 0x20, 0x27}, | ||
282 | {TUNER_WRITE, 0x07, 0x02}, | ||
283 | {TUNER_WRITE, 0x11, 0xff}, | ||
284 | {TUNER_WRITE, 0x60, 0xf9}, | ||
285 | {TUNER_WRITE, 0x08, 0x01}, | ||
286 | {TUNER_WRITE, 0x00, 0x41}, | ||
287 | {DEMOD_WRITE, 0x81, 0x81}, | 241 | {DEMOD_WRITE, 0x81, 0x81}, |
288 | {DEMOD_WRITE, 0x86, 0xc6}, | 242 | {DEMOD_WRITE, 0x86, 0xc6}, |
289 | {DEMOD_WRITE, 0x9a, 0x30}, | 243 | {DEMOD_WRITE, 0x9a, 0x30}, |
@@ -301,23 +255,10 @@ struct inittab m88rs2000_shutdown[] = { | |||
301 | {DEMOD_WRITE, 0xf1, 0x89}, | 255 | {DEMOD_WRITE, 0xf1, 0x89}, |
302 | {DEMOD_WRITE, 0x00, 0x01}, | 256 | {DEMOD_WRITE, 0x00, 0x01}, |
303 | {DEMOD_WRITE, 0x9a, 0xb0}, | 257 | {DEMOD_WRITE, 0x9a, 0xb0}, |
304 | {TUNER_WRITE, 0x00, 0x40}, | ||
305 | {DEMOD_WRITE, 0x81, 0x81}, | 258 | {DEMOD_WRITE, 0x81, 0x81}, |
306 | {0xff, 0xaa, 0xff} | 259 | {0xff, 0xaa, 0xff} |
307 | }; | 260 | }; |
308 | 261 | ||
309 | struct inittab tuner_reset[] = { | ||
310 | {TUNER_WRITE, 0x42, 0x73}, | ||
311 | {TUNER_WRITE, 0x05, 0x07}, | ||
312 | {TUNER_WRITE, 0x20, 0x27}, | ||
313 | {TUNER_WRITE, 0x07, 0x02}, | ||
314 | {TUNER_WRITE, 0x11, 0xff}, | ||
315 | {TUNER_WRITE, 0x60, 0xf9}, | ||
316 | {TUNER_WRITE, 0x08, 0x01}, | ||
317 | {TUNER_WRITE, 0x00, 0x41}, | ||
318 | {0xff, 0xaa, 0xff} | ||
319 | }; | ||
320 | |||
321 | struct inittab fe_reset[] = { | 262 | struct inittab fe_reset[] = { |
322 | {DEMOD_WRITE, 0x00, 0x01}, | 263 | {DEMOD_WRITE, 0x00, 0x01}, |
323 | {DEMOD_WRITE, 0xf1, 0xbf}, | 264 | {DEMOD_WRITE, 0xf1, 0xbf}, |
@@ -389,11 +330,7 @@ static int m88rs2000_tab_set(struct m88rs2000_state *state, | |||
389 | for (i = 0; i < 255; i++) { | 330 | for (i = 0; i < 255; i++) { |
390 | switch (tab[i].cmd) { | 331 | switch (tab[i].cmd) { |
391 | case 0x01: | 332 | case 0x01: |
392 | ret = m88rs2000_demod_write(state, tab[i].reg, | 333 | ret = m88rs2000_writereg(state, tab[i].reg, |
393 | tab[i].val); | ||
394 | break; | ||
395 | case 0x02: | ||
396 | ret = m88rs2000_tuner_write(state, tab[i].reg, | ||
397 | tab[i].val); | 334 | tab[i].val); |
398 | break; | 335 | break; |
399 | case 0x10: | 336 | case 0x10: |
@@ -419,7 +356,7 @@ static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) | |||
419 | struct m88rs2000_state *state = fe->demodulator_priv; | 356 | struct m88rs2000_state *state = fe->demodulator_priv; |
420 | u8 data; | 357 | u8 data; |
421 | 358 | ||
422 | data = m88rs2000_demod_read(state, 0xb2); | 359 | data = m88rs2000_readreg(state, 0xb2); |
423 | data |= 0x03; /* bit0 V/H, bit1 off/on */ | 360 | data |= 0x03; /* bit0 V/H, bit1 off/on */ |
424 | 361 | ||
425 | switch (volt) { | 362 | switch (volt) { |
@@ -434,23 +371,11 @@ static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) | |||
434 | break; | 371 | break; |
435 | } | 372 | } |
436 | 373 | ||
437 | m88rs2000_demod_write(state, 0xb2, data); | 374 | m88rs2000_writereg(state, 0xb2, data); |
438 | 375 | ||
439 | return 0; | 376 | return 0; |
440 | } | 377 | } |
441 | 378 | ||
442 | static int m88rs2000_startup(struct m88rs2000_state *state) | ||
443 | { | ||
444 | int ret = 0; | ||
445 | u8 reg; | ||
446 | |||
447 | reg = m88rs2000_tuner_read(state, 0x00); | ||
448 | if ((reg & 0x40) == 0) | ||
449 | ret = -ENODEV; | ||
450 | |||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | static int m88rs2000_init(struct dvb_frontend *fe) | 379 | static int m88rs2000_init(struct dvb_frontend *fe) |
455 | { | 380 | { |
456 | struct m88rs2000_state *state = fe->demodulator_priv; | 381 | struct m88rs2000_state *state = fe->demodulator_priv; |
@@ -479,7 +404,7 @@ static int m88rs2000_sleep(struct dvb_frontend *fe) | |||
479 | static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status) | 404 | static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status) |
480 | { | 405 | { |
481 | struct m88rs2000_state *state = fe->demodulator_priv; | 406 | struct m88rs2000_state *state = fe->demodulator_priv; |
482 | u8 reg = m88rs2000_demod_read(state, 0x8c); | 407 | u8 reg = m88rs2000_readreg(state, 0x8c); |
483 | 408 | ||
484 | *status = 0; | 409 | *status = 0; |
485 | 410 | ||
@@ -497,23 +422,23 @@ static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber) | |||
497 | struct m88rs2000_state *state = fe->demodulator_priv; | 422 | struct m88rs2000_state *state = fe->demodulator_priv; |
498 | u8 tmp0, tmp1; | 423 | u8 tmp0, tmp1; |
499 | 424 | ||
500 | m88rs2000_demod_write(state, 0x9a, 0x30); | 425 | m88rs2000_writereg(state, 0x9a, 0x30); |
501 | tmp0 = m88rs2000_demod_read(state, 0xd8); | 426 | tmp0 = m88rs2000_readreg(state, 0xd8); |
502 | if ((tmp0 & 0x10) != 0) { | 427 | if ((tmp0 & 0x10) != 0) { |
503 | m88rs2000_demod_write(state, 0x9a, 0xb0); | 428 | m88rs2000_writereg(state, 0x9a, 0xb0); |
504 | *ber = 0xffffffff; | 429 | *ber = 0xffffffff; |
505 | return 0; | 430 | return 0; |
506 | } | 431 | } |
507 | 432 | ||
508 | *ber = (m88rs2000_demod_read(state, 0xd7) << 8) | | 433 | *ber = (m88rs2000_readreg(state, 0xd7) << 8) | |
509 | m88rs2000_demod_read(state, 0xd6); | 434 | m88rs2000_readreg(state, 0xd6); |
510 | 435 | ||
511 | tmp1 = m88rs2000_demod_read(state, 0xd9); | 436 | tmp1 = m88rs2000_readreg(state, 0xd9); |
512 | m88rs2000_demod_write(state, 0xd9, (tmp1 & ~7) | 4); | 437 | m88rs2000_writereg(state, 0xd9, (tmp1 & ~7) | 4); |
513 | /* needs twice */ | 438 | /* needs twice */ |
514 | m88rs2000_demod_write(state, 0xd8, (tmp0 & ~8) | 0x30); | 439 | m88rs2000_writereg(state, 0xd8, (tmp0 & ~8) | 0x30); |
515 | m88rs2000_demod_write(state, 0xd8, (tmp0 & ~8) | 0x30); | 440 | m88rs2000_writereg(state, 0xd8, (tmp0 & ~8) | 0x30); |
516 | m88rs2000_demod_write(state, 0x9a, 0xb0); | 441 | m88rs2000_writereg(state, 0x9a, 0xb0); |
517 | 442 | ||
518 | return 0; | 443 | return 0; |
519 | } | 444 | } |
@@ -529,7 +454,7 @@ static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) | |||
529 | { | 454 | { |
530 | struct m88rs2000_state *state = fe->demodulator_priv; | 455 | struct m88rs2000_state *state = fe->demodulator_priv; |
531 | 456 | ||
532 | *snr = 512 * m88rs2000_demod_read(state, 0x65); | 457 | *snr = 512 * m88rs2000_readreg(state, 0x65); |
533 | 458 | ||
534 | return 0; | 459 | return 0; |
535 | } | 460 | } |
@@ -539,166 +464,17 @@ static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | |||
539 | struct m88rs2000_state *state = fe->demodulator_priv; | 464 | struct m88rs2000_state *state = fe->demodulator_priv; |
540 | u8 tmp; | 465 | u8 tmp; |
541 | 466 | ||
542 | *ucblocks = (m88rs2000_demod_read(state, 0xd5) << 8) | | 467 | *ucblocks = (m88rs2000_readreg(state, 0xd5) << 8) | |
543 | m88rs2000_demod_read(state, 0xd4); | 468 | m88rs2000_readreg(state, 0xd4); |
544 | tmp = m88rs2000_demod_read(state, 0xd8); | 469 | tmp = m88rs2000_readreg(state, 0xd8); |
545 | m88rs2000_demod_write(state, 0xd8, tmp & ~0x20); | 470 | m88rs2000_writereg(state, 0xd8, tmp & ~0x20); |
546 | /* needs two times */ | 471 | /* needs two times */ |
547 | m88rs2000_demod_write(state, 0xd8, tmp | 0x20); | 472 | m88rs2000_writereg(state, 0xd8, tmp | 0x20); |
548 | m88rs2000_demod_write(state, 0xd8, tmp | 0x20); | 473 | m88rs2000_writereg(state, 0xd8, tmp | 0x20); |
549 | 474 | ||
550 | return 0; | 475 | return 0; |
551 | } | 476 | } |
552 | 477 | ||
553 | static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset) | ||
554 | { | ||
555 | int ret; | ||
556 | ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset); | ||
557 | ret |= m88rs2000_tuner_write(state, 0x51, 0x1f); | ||
558 | ret |= m88rs2000_tuner_write(state, 0x50, offset); | ||
559 | ret |= m88rs2000_tuner_write(state, 0x50, 0x00); | ||
560 | msleep(20); | ||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe) | ||
565 | { | ||
566 | struct m88rs2000_state *state = fe->demodulator_priv; | ||
567 | int reg; | ||
568 | reg = m88rs2000_tuner_read(state, 0x3d); | ||
569 | reg &= 0x7f; | ||
570 | if (reg < 0x16) | ||
571 | reg = 0xa1; | ||
572 | else if (reg == 0x16) | ||
573 | reg = 0x99; | ||
574 | else | ||
575 | reg = 0xf9; | ||
576 | |||
577 | m88rs2000_tuner_write(state, 0x60, reg); | ||
578 | reg = m88rs2000_tuner_gate_ctrl(state, 0x08); | ||
579 | |||
580 | if (fe->ops.i2c_gate_ctrl) | ||
581 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
582 | return reg; | ||
583 | } | ||
584 | |||
585 | static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset) | ||
586 | { | ||
587 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
588 | struct m88rs2000_state *state = fe->demodulator_priv; | ||
589 | int ret; | ||
590 | u32 frequency = c->frequency; | ||
591 | s32 offset_khz; | ||
592 | s32 tmp; | ||
593 | u32 symbol_rate = (c->symbol_rate / 1000); | ||
594 | u32 f3db, gdiv28; | ||
595 | u16 value, ndiv, lpf_coeff; | ||
596 | u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf; | ||
597 | u8 lo = 0x01, div4 = 0x0; | ||
598 | |||
599 | /* Reset Tuner */ | ||
600 | ret = m88rs2000_tab_set(state, tuner_reset); | ||
601 | |||
602 | /* Calculate frequency divider */ | ||
603 | if (frequency < 1060000) { | ||
604 | lo |= 0x10; | ||
605 | div4 = 0x1; | ||
606 | ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ; | ||
607 | } else | ||
608 | ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ; | ||
609 | ndiv = ndiv + ndiv % 2; | ||
610 | ndiv = ndiv - 1024; | ||
611 | |||
612 | ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo); | ||
613 | |||
614 | /* Set frequency divider */ | ||
615 | ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf); | ||
616 | ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff); | ||
617 | |||
618 | ret |= m88rs2000_tuner_write(state, 0x03, 0x06); | ||
619 | ret |= m88rs2000_tuner_gate_ctrl(state, 0x10); | ||
620 | if (ret < 0) | ||
621 | return -ENODEV; | ||
622 | |||
623 | /* Tuner Frequency Range */ | ||
624 | ret = m88rs2000_tuner_write(state, 0x10, lo); | ||
625 | |||
626 | ret |= m88rs2000_tuner_gate_ctrl(state, 0x08); | ||
627 | |||
628 | /* Tuner RF */ | ||
629 | ret |= m88rs2000_set_tuner_rf(fe); | ||
630 | |||
631 | gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000; | ||
632 | ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff); | ||
633 | ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); | ||
634 | if (ret < 0) | ||
635 | return -ENODEV; | ||
636 | |||
637 | value = m88rs2000_tuner_read(state, 0x26); | ||
638 | |||
639 | f3db = (symbol_rate * 135) / 200 + 2000; | ||
640 | f3db += FREQ_OFFSET_LOW_SYM_RATE; | ||
641 | if (f3db < 7000) | ||
642 | f3db = 7000; | ||
643 | if (f3db > 40000) | ||
644 | f3db = 40000; | ||
645 | |||
646 | gdiv28 = gdiv28 * 207 / (value * 2 + 151); | ||
647 | mlpf_max = gdiv28 * 135 / 100; | ||
648 | mlpf_min = gdiv28 * 78 / 100; | ||
649 | if (mlpf_max > 63) | ||
650 | mlpf_max = 63; | ||
651 | |||
652 | lpf_coeff = 2766; | ||
653 | |||
654 | nlpf = (f3db * gdiv28 * 2 / lpf_coeff / | ||
655 | (FE_CRYSTAL_KHZ / 1000) + 1) / 2; | ||
656 | if (nlpf > 23) | ||
657 | nlpf = 23; | ||
658 | if (nlpf < 1) | ||
659 | nlpf = 1; | ||
660 | |||
661 | lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) | ||
662 | * lpf_coeff * 2 / f3db + 1) / 2; | ||
663 | |||
664 | if (lpf_mxdiv < mlpf_min) { | ||
665 | nlpf++; | ||
666 | lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) | ||
667 | * lpf_coeff * 2 / f3db + 1) / 2; | ||
668 | } | ||
669 | |||
670 | if (lpf_mxdiv > mlpf_max) | ||
671 | lpf_mxdiv = mlpf_max; | ||
672 | |||
673 | ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv); | ||
674 | ret |= m88rs2000_tuner_write(state, 0x06, nlpf); | ||
675 | |||
676 | ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); | ||
677 | |||
678 | ret |= m88rs2000_tuner_gate_ctrl(state, 0x01); | ||
679 | |||
680 | msleep(80); | ||
681 | /* calculate offset assuming 96000kHz*/ | ||
682 | offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ | ||
683 | / 14 / (div4 + 1) / 2; | ||
684 | |||
685 | offset_khz -= frequency; | ||
686 | |||
687 | tmp = offset_khz; | ||
688 | tmp *= 65536; | ||
689 | |||
690 | tmp = (2 * tmp + 96000) / (2 * 96000); | ||
691 | if (tmp < 0) | ||
692 | tmp += 65536; | ||
693 | |||
694 | *offset = tmp & 0xffff; | ||
695 | |||
696 | if (fe->ops.i2c_gate_ctrl) | ||
697 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
698 | |||
699 | return (ret < 0) ? -EINVAL : 0; | ||
700 | } | ||
701 | |||
702 | static int m88rs2000_set_fec(struct m88rs2000_state *state, | 478 | static int m88rs2000_set_fec(struct m88rs2000_state *state, |
703 | fe_code_rate_t fec) | 479 | fe_code_rate_t fec) |
704 | { | 480 | { |
@@ -724,7 +500,7 @@ static int m88rs2000_set_fec(struct m88rs2000_state *state, | |||
724 | default: | 500 | default: |
725 | fec_set = 0x08; | 501 | fec_set = 0x08; |
726 | } | 502 | } |
727 | m88rs2000_demod_write(state, 0x76, fec_set); | 503 | m88rs2000_writereg(state, 0x76, fec_set); |
728 | 504 | ||
729 | return 0; | 505 | return 0; |
730 | } | 506 | } |
@@ -733,9 +509,9 @@ static int m88rs2000_set_fec(struct m88rs2000_state *state, | |||
733 | static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) | 509 | static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) |
734 | { | 510 | { |
735 | u8 reg; | 511 | u8 reg; |
736 | m88rs2000_demod_write(state, 0x9a, 0x30); | 512 | m88rs2000_writereg(state, 0x9a, 0x30); |
737 | reg = m88rs2000_demod_read(state, 0x76); | 513 | reg = m88rs2000_readreg(state, 0x76); |
738 | m88rs2000_demod_write(state, 0x9a, 0xb0); | 514 | m88rs2000_writereg(state, 0x9a, 0xb0); |
739 | 515 | ||
740 | switch (reg) { | 516 | switch (reg) { |
741 | case 0x88: | 517 | case 0x88: |
@@ -761,7 +537,9 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
761 | struct m88rs2000_state *state = fe->demodulator_priv; | 537 | struct m88rs2000_state *state = fe->demodulator_priv; |
762 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 538 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
763 | fe_status_t status; | 539 | fe_status_t status; |
764 | int i, ret; | 540 | int i, ret = 0; |
541 | s32 tmp; | ||
542 | u32 tuner_freq; | ||
765 | u16 offset = 0; | 543 | u16 offset = 0; |
766 | u8 reg; | 544 | u8 reg; |
767 | 545 | ||
@@ -775,17 +553,37 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
775 | } | 553 | } |
776 | 554 | ||
777 | /* Set Tuner */ | 555 | /* Set Tuner */ |
778 | ret = m88rs2000_set_tuner(fe, &offset); | 556 | if (fe->ops.tuner_ops.set_params) |
557 | ret = fe->ops.tuner_ops.set_params(fe); | ||
558 | |||
559 | if (ret < 0) | ||
560 | return -ENODEV; | ||
561 | |||
562 | if (fe->ops.tuner_ops.get_frequency) | ||
563 | ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_freq); | ||
564 | |||
779 | if (ret < 0) | 565 | if (ret < 0) |
780 | return -ENODEV; | 566 | return -ENODEV; |
781 | 567 | ||
782 | ret = m88rs2000_demod_write(state, 0x9a, 0x30); | 568 | offset = tuner_freq - c->frequency; |
569 | |||
570 | /* calculate offset assuming 96000kHz*/ | ||
571 | tmp = offset; | ||
572 | tmp *= 65536; | ||
573 | |||
574 | tmp = (2 * tmp + 96000) / (2 * 96000); | ||
575 | if (tmp < 0) | ||
576 | tmp += 65536; | ||
577 | |||
578 | offset = tmp & 0xffff; | ||
579 | |||
580 | ret = m88rs2000_writereg(state, 0x9a, 0x30); | ||
783 | /* Unknown usually 0xc6 sometimes 0xc1 */ | 581 | /* Unknown usually 0xc6 sometimes 0xc1 */ |
784 | reg = m88rs2000_demod_read(state, 0x86); | 582 | reg = m88rs2000_readreg(state, 0x86); |
785 | ret |= m88rs2000_demod_write(state, 0x86, reg); | 583 | ret |= m88rs2000_writereg(state, 0x86, reg); |
786 | /* Offset lower nibble always 0 */ | 584 | /* Offset lower nibble always 0 */ |
787 | ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8)); | 585 | ret |= m88rs2000_writereg(state, 0x9c, (offset >> 8)); |
788 | ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0); | 586 | ret |= m88rs2000_writereg(state, 0x9d, offset & 0xf0); |
789 | 587 | ||
790 | 588 | ||
791 | /* Reset Demod */ | 589 | /* Reset Demod */ |
@@ -794,16 +592,16 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
794 | return -ENODEV; | 592 | return -ENODEV; |
795 | 593 | ||
796 | /* Unknown */ | 594 | /* Unknown */ |
797 | reg = m88rs2000_demod_read(state, 0x70); | 595 | reg = m88rs2000_readreg(state, 0x70); |
798 | ret = m88rs2000_demod_write(state, 0x70, reg); | 596 | ret = m88rs2000_writereg(state, 0x70, reg); |
799 | 597 | ||
800 | /* Set FEC */ | 598 | /* Set FEC */ |
801 | ret |= m88rs2000_set_fec(state, c->fec_inner); | 599 | ret |= m88rs2000_set_fec(state, c->fec_inner); |
802 | ret |= m88rs2000_demod_write(state, 0x85, 0x1); | 600 | ret |= m88rs2000_writereg(state, 0x85, 0x1); |
803 | ret |= m88rs2000_demod_write(state, 0x8a, 0xbf); | 601 | ret |= m88rs2000_writereg(state, 0x8a, 0xbf); |
804 | ret |= m88rs2000_demod_write(state, 0x8d, 0x1e); | 602 | ret |= m88rs2000_writereg(state, 0x8d, 0x1e); |
805 | ret |= m88rs2000_demod_write(state, 0x90, 0xf1); | 603 | ret |= m88rs2000_writereg(state, 0x90, 0xf1); |
806 | ret |= m88rs2000_demod_write(state, 0x91, 0x08); | 604 | ret |= m88rs2000_writereg(state, 0x91, 0x08); |
807 | 605 | ||
808 | if (ret < 0) | 606 | if (ret < 0) |
809 | return -ENODEV; | 607 | return -ENODEV; |
@@ -819,27 +617,25 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
819 | return -ENODEV; | 617 | return -ENODEV; |
820 | 618 | ||
821 | for (i = 0; i < 25; i++) { | 619 | for (i = 0; i < 25; i++) { |
822 | reg = m88rs2000_demod_read(state, 0x8c); | 620 | reg = m88rs2000_readreg(state, 0x8c); |
823 | if ((reg & 0x7) == 0x7) { | 621 | if ((reg & 0x7) == 0x7) { |
824 | status = FE_HAS_LOCK; | 622 | status = FE_HAS_LOCK; |
825 | break; | 623 | break; |
826 | } | 624 | } |
827 | state->no_lock_count++; | 625 | state->no_lock_count++; |
828 | if (state->no_lock_count == 15) { | 626 | if (state->no_lock_count == 15) { |
829 | reg = m88rs2000_demod_read(state, 0x70); | 627 | reg = m88rs2000_readreg(state, 0x70); |
830 | reg ^= 0x4; | 628 | reg ^= 0x4; |
831 | m88rs2000_demod_write(state, 0x70, reg); | 629 | m88rs2000_writereg(state, 0x70, reg); |
832 | state->no_lock_count = 0; | 630 | state->no_lock_count = 0; |
833 | } | 631 | } |
834 | if (state->no_lock_count == 20) | ||
835 | m88rs2000_set_tuner_rf(fe); | ||
836 | msleep(20); | 632 | msleep(20); |
837 | } | 633 | } |
838 | 634 | ||
839 | if (status & FE_HAS_LOCK) { | 635 | if (status & FE_HAS_LOCK) { |
840 | state->fec_inner = m88rs2000_get_fec(state); | 636 | state->fec_inner = m88rs2000_get_fec(state); |
841 | /* Uknown suspect SNR level */ | 637 | /* Uknown suspect SNR level */ |
842 | reg = m88rs2000_demod_read(state, 0x65); | 638 | reg = m88rs2000_readreg(state, 0x65); |
843 | } | 639 | } |
844 | 640 | ||
845 | state->tuner_frequency = c->frequency; | 641 | state->tuner_frequency = c->frequency; |
@@ -862,9 +658,9 @@ static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | |||
862 | struct m88rs2000_state *state = fe->demodulator_priv; | 658 | struct m88rs2000_state *state = fe->demodulator_priv; |
863 | 659 | ||
864 | if (enable) | 660 | if (enable) |
865 | m88rs2000_demod_write(state, 0x81, 0x84); | 661 | m88rs2000_writereg(state, 0x81, 0x84); |
866 | else | 662 | else |
867 | m88rs2000_demod_write(state, 0x81, 0x81); | 663 | m88rs2000_writereg(state, 0x81, 0x81); |
868 | udelay(10); | 664 | udelay(10); |
869 | return 0; | 665 | return 0; |
870 | } | 666 | } |
@@ -895,7 +691,6 @@ static struct dvb_frontend_ops m88rs2000_ops = { | |||
895 | .release = m88rs2000_release, | 691 | .release = m88rs2000_release, |
896 | .init = m88rs2000_init, | 692 | .init = m88rs2000_init, |
897 | .sleep = m88rs2000_sleep, | 693 | .sleep = m88rs2000_sleep, |
898 | .write = m88rs2000_write, | ||
899 | .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl, | 694 | .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl, |
900 | .read_status = m88rs2000_read_status, | 695 | .read_status = m88rs2000_read_status, |
901 | .read_ber = m88rs2000_read_ber, | 696 | .read_ber = m88rs2000_read_ber, |
@@ -928,9 +723,6 @@ struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config, | |||
928 | state->symbol_rate = 0; | 723 | state->symbol_rate = 0; |
929 | state->fec_inner = 0; | 724 | state->fec_inner = 0; |
930 | 725 | ||
931 | if (m88rs2000_startup(state) < 0) | ||
932 | goto error; | ||
933 | |||
934 | /* create dvb_frontend */ | 726 | /* create dvb_frontend */ |
935 | memcpy(&state->frontend.ops, &m88rs2000_ops, | 727 | memcpy(&state->frontend.ops, &m88rs2000_ops, |
936 | sizeof(struct dvb_frontend_ops)); | 728 | sizeof(struct dvb_frontend_ops)); |
diff --git a/drivers/media/dvb-frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h index 59acdb696873..5a8023e5a4b8 100644 --- a/drivers/media/dvb-frontends/m88rs2000.h +++ b/drivers/media/dvb-frontends/m88rs2000.h | |||
@@ -26,8 +26,6 @@ | |||
26 | struct m88rs2000_config { | 26 | struct m88rs2000_config { |
27 | /* Demodulator i2c address */ | 27 | /* Demodulator i2c address */ |
28 | u8 demod_addr; | 28 | u8 demod_addr; |
29 | /* Tuner address */ | ||
30 | u8 tuner_addr; | ||
31 | 29 | ||
32 | u8 *inittab; | 30 | u8 *inittab; |
33 | 31 | ||
@@ -55,12 +53,8 @@ static inline struct dvb_frontend *m88rs2000_attach( | |||
55 | } | 53 | } |
56 | #endif /* CONFIG_DVB_M88RS2000 */ | 54 | #endif /* CONFIG_DVB_M88RS2000 */ |
57 | 55 | ||
58 | #define FE_CRYSTAL_KHZ 27000 | ||
59 | #define FREQ_OFFSET_LOW_SYM_RATE 3000 | ||
60 | |||
61 | enum { | 56 | enum { |
62 | DEMOD_WRITE = 0x1, | 57 | DEMOD_WRITE = 0x1, |
63 | TUNER_WRITE, | ||
64 | WRITE_DELAY = 0x10, | 58 | WRITE_DELAY = 0x10, |
65 | }; | 59 | }; |
66 | #endif /* M88RS2000_H */ | 60 | #endif /* M88RS2000_H */ |
diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c index 73010ecb9866..94e3fe21eefb 100644 --- a/drivers/media/dvb-frontends/ts2020.c +++ b/drivers/media/dvb-frontends/ts2020.c | |||
@@ -23,27 +23,68 @@ | |||
23 | #include "ts2020.h" | 23 | #include "ts2020.h" |
24 | 24 | ||
25 | #define TS2020_XTAL_FREQ 27000 /* in kHz */ | 25 | #define TS2020_XTAL_FREQ 27000 /* in kHz */ |
26 | #define FREQ_OFFSET_LOW_SYM_RATE 3000 | ||
26 | 27 | ||
27 | struct ts2020_state { | 28 | struct ts2020_priv { |
28 | u8 tuner_address; | 29 | /* i2c details */ |
30 | int i2c_address; | ||
29 | struct i2c_adapter *i2c; | 31 | struct i2c_adapter *i2c; |
32 | u8 clk_out_div; | ||
33 | u32 frequency; | ||
30 | }; | 34 | }; |
31 | 35 | ||
32 | static int ts2020_readreg(struct dvb_frontend *fe, u8 reg) | 36 | static int ts2020_release(struct dvb_frontend *fe) |
33 | { | 37 | { |
34 | struct ts2020_state *state = fe->tuner_priv; | 38 | kfree(fe->tuner_priv); |
39 | fe->tuner_priv = NULL; | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static int ts2020_writereg(struct dvb_frontend *fe, int reg, int data) | ||
44 | { | ||
45 | struct ts2020_priv *priv = fe->tuner_priv; | ||
46 | u8 buf[] = { reg, data }; | ||
47 | struct i2c_msg msg[] = { | ||
48 | { | ||
49 | .addr = priv->i2c_address, | ||
50 | .flags = 0, | ||
51 | .buf = buf, | ||
52 | .len = 2 | ||
53 | } | ||
54 | }; | ||
55 | int err; | ||
56 | |||
57 | if (fe->ops.i2c_gate_ctrl) | ||
58 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
59 | |||
60 | err = i2c_transfer(priv->i2c, msg, 1); | ||
61 | if (err != 1) { | ||
62 | printk(KERN_ERR | ||
63 | "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n", | ||
64 | __func__, err, reg, data); | ||
65 | return -EREMOTEIO; | ||
66 | } | ||
35 | 67 | ||
68 | if (fe->ops.i2c_gate_ctrl) | ||
69 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int ts2020_readreg(struct dvb_frontend *fe, u8 reg) | ||
75 | { | ||
76 | struct ts2020_priv *priv = fe->tuner_priv; | ||
36 | int ret; | 77 | int ret; |
37 | u8 b0[] = { reg }; | 78 | u8 b0[] = { reg }; |
38 | u8 b1[] = { 0 }; | 79 | u8 b1[] = { 0 }; |
39 | struct i2c_msg msg[] = { | 80 | struct i2c_msg msg[] = { |
40 | { | 81 | { |
41 | .addr = state->tuner_address, | 82 | .addr = priv->i2c_address, |
42 | .flags = 0, | 83 | .flags = 0, |
43 | .buf = b0, | 84 | .buf = b0, |
44 | .len = 1 | 85 | .len = 1 |
45 | }, { | 86 | }, { |
46 | .addr = state->tuner_address, | 87 | .addr = priv->i2c_address, |
47 | .flags = I2C_M_RD, | 88 | .flags = I2C_M_RD, |
48 | .buf = b1, | 89 | .buf = b1, |
49 | .len = 1 | 90 | .len = 1 |
@@ -53,212 +94,202 @@ static int ts2020_readreg(struct dvb_frontend *fe, u8 reg) | |||
53 | if (fe->ops.i2c_gate_ctrl) | 94 | if (fe->ops.i2c_gate_ctrl) |
54 | fe->ops.i2c_gate_ctrl(fe, 1); | 95 | fe->ops.i2c_gate_ctrl(fe, 1); |
55 | 96 | ||
56 | ret = i2c_transfer(state->i2c, msg, 2); | 97 | ret = i2c_transfer(priv->i2c, msg, 2); |
57 | |||
58 | if (fe->ops.i2c_gate_ctrl) | ||
59 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
60 | 98 | ||
61 | if (ret != 2) { | 99 | if (ret != 2) { |
62 | printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret); | 100 | printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", |
101 | __func__, reg, ret); | ||
63 | return ret; | 102 | return ret; |
64 | } | 103 | } |
65 | 104 | ||
105 | if (fe->ops.i2c_gate_ctrl) | ||
106 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
107 | |||
66 | return b1[0]; | 108 | return b1[0]; |
67 | } | 109 | } |
68 | 110 | ||
69 | static int ts2020_writereg(struct dvb_frontend *fe, int reg, int data) | 111 | static int ts2020_sleep(struct dvb_frontend *fe) |
70 | { | 112 | { |
71 | struct ts2020_state *state = fe->tuner_priv; | 113 | struct ts2020_priv *priv = fe->tuner_priv; |
72 | 114 | int ret; | |
73 | u8 buf[] = { reg, data }; | 115 | u8 buf[] = { 10, 0 }; |
74 | struct i2c_msg msg = { .addr = state->tuner_address, | 116 | struct i2c_msg msg = { |
75 | .flags = 0, .buf = buf, .len = 2 }; | 117 | .addr = priv->i2c_address, |
76 | int err; | 118 | .flags = 0, |
77 | 119 | .buf = buf, | |
120 | .len = 2 | ||
121 | }; | ||
78 | 122 | ||
79 | if (fe->ops.i2c_gate_ctrl) | 123 | if (fe->ops.i2c_gate_ctrl) |
80 | fe->ops.i2c_gate_ctrl(fe, 1); | 124 | fe->ops.i2c_gate_ctrl(fe, 1); |
81 | 125 | ||
82 | err = i2c_transfer(state->i2c, &msg, 1); | 126 | ret = i2c_transfer(priv->i2c, &msg, 1); |
127 | if (ret != 1) | ||
128 | printk(KERN_ERR "%s: i2c error\n", __func__); | ||
83 | 129 | ||
84 | if (fe->ops.i2c_gate_ctrl) | 130 | if (fe->ops.i2c_gate_ctrl) |
85 | fe->ops.i2c_gate_ctrl(fe, 0); | 131 | fe->ops.i2c_gate_ctrl(fe, 0); |
86 | 132 | ||
87 | if (err != 1) { | 133 | return (ret == 1) ? 0 : ret; |
88 | printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x," | ||
89 | " value == 0x%02x)\n", __func__, err, reg, data); | ||
90 | return -EREMOTEIO; | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | 134 | } |
95 | 135 | ||
96 | static int ts2020_init(struct dvb_frontend *fe) | 136 | static int ts2020_init(struct dvb_frontend *fe) |
97 | { | 137 | { |
138 | struct ts2020_priv *priv = fe->tuner_priv; | ||
139 | |||
98 | ts2020_writereg(fe, 0x42, 0x73); | 140 | ts2020_writereg(fe, 0x42, 0x73); |
99 | ts2020_writereg(fe, 0x05, 0x01); | 141 | ts2020_writereg(fe, 0x05, priv->clk_out_div); |
100 | ts2020_writereg(fe, 0x62, 0xf5); | 142 | ts2020_writereg(fe, 0x20, 0x27); |
143 | ts2020_writereg(fe, 0x07, 0x02); | ||
144 | ts2020_writereg(fe, 0x11, 0xff); | ||
145 | ts2020_writereg(fe, 0x60, 0xf9); | ||
146 | ts2020_writereg(fe, 0x08, 0x01); | ||
147 | ts2020_writereg(fe, 0x00, 0x41); | ||
148 | |||
101 | return 0; | 149 | return 0; |
102 | } | 150 | } |
103 | 151 | ||
104 | static int ts2020_get_frequency(struct dvb_frontend *fe, u32 *frequency) | 152 | static int ts2020_tuner_gate_ctrl(struct dvb_frontend *fe, u8 offset) |
105 | { | 153 | { |
106 | u16 ndiv, div4; | 154 | int ret; |
155 | ret = ts2020_writereg(fe, 0x51, 0x1f - offset); | ||
156 | ret |= ts2020_writereg(fe, 0x51, 0x1f); | ||
157 | ret |= ts2020_writereg(fe, 0x50, offset); | ||
158 | ret |= ts2020_writereg(fe, 0x50, 0x00); | ||
159 | msleep(20); | ||
160 | return ret; | ||
161 | } | ||
107 | 162 | ||
108 | div4 = (ts2020_readreg(fe, 0x10) & 0x10) >> 4; | 163 | static int ts2020_set_tuner_rf(struct dvb_frontend *fe) |
164 | { | ||
165 | int reg; | ||
109 | 166 | ||
110 | ndiv = ts2020_readreg(fe, 0x01); | 167 | reg = ts2020_readreg(fe, 0x3d); |
111 | ndiv &= 0x0f; | 168 | reg &= 0x7f; |
112 | ndiv <<= 8; | 169 | if (reg < 0x16) |
113 | ndiv |= ts2020_readreg(fe, 0x02); | 170 | reg = 0xa1; |
171 | else if (reg == 0x16) | ||
172 | reg = 0x99; | ||
173 | else | ||
174 | reg = 0xf9; | ||
114 | 175 | ||
115 | /* actual tuned frequency, i.e. including the offset */ | 176 | ts2020_writereg(fe, 0x60, reg); |
116 | *frequency = (ndiv - ndiv % 2 + 1024) * TS2020_XTAL_FREQ | 177 | reg = ts2020_tuner_gate_ctrl(fe, 0x08); |
117 | / (6 + 8) / (div4 + 1) / 2; | ||
118 | 178 | ||
119 | return 0; | 179 | return reg; |
120 | } | 180 | } |
121 | 181 | ||
122 | static int ts2020_set_params(struct dvb_frontend *fe) | 182 | static int ts2020_set_params(struct dvb_frontend *fe) |
123 | { | 183 | { |
124 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 184 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
185 | struct ts2020_priv *priv = fe->demodulator_priv; | ||
186 | int ret; | ||
187 | u32 frequency = c->frequency; | ||
188 | s32 offset_khz; | ||
189 | u32 symbol_rate = (c->symbol_rate / 1000); | ||
190 | u32 f3db, gdiv28; | ||
191 | u16 value, ndiv, lpf_coeff; | ||
192 | u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf; | ||
193 | u8 lo = 0x01, div4 = 0x0; | ||
194 | |||
195 | /* Calculate frequency divider */ | ||
196 | if (frequency < 1060000) { | ||
197 | lo |= 0x10; | ||
198 | div4 = 0x1; | ||
199 | ndiv = (frequency * 14 * 4) / TS2020_XTAL_FREQ; | ||
200 | } else | ||
201 | ndiv = (frequency * 14 * 2) / TS2020_XTAL_FREQ; | ||
202 | ndiv = ndiv + ndiv % 2; | ||
203 | ndiv = ndiv - 1024; | ||
204 | |||
205 | ret = ts2020_writereg(fe, 0x10, 0x80 | lo); | ||
206 | |||
207 | /* Set frequency divider */ | ||
208 | ret |= ts2020_writereg(fe, 0x01, (ndiv >> 8) & 0xf); | ||
209 | ret |= ts2020_writereg(fe, 0x02, ndiv & 0xff); | ||
210 | |||
211 | ret |= ts2020_writereg(fe, 0x03, 0x06); | ||
212 | ret |= ts2020_tuner_gate_ctrl(fe, 0x10); | ||
213 | if (ret < 0) | ||
214 | return -ENODEV; | ||
215 | |||
216 | /* Tuner Frequency Range */ | ||
217 | ret = ts2020_writereg(fe, 0x10, lo); | ||
218 | |||
219 | ret |= ts2020_tuner_gate_ctrl(fe, 0x08); | ||
220 | |||
221 | /* Tuner RF */ | ||
222 | ret |= ts2020_set_tuner_rf(fe); | ||
223 | |||
224 | gdiv28 = (TS2020_XTAL_FREQ / 1000 * 1694 + 500) / 1000; | ||
225 | ret |= ts2020_writereg(fe, 0x04, gdiv28 & 0xff); | ||
226 | ret |= ts2020_tuner_gate_ctrl(fe, 0x04); | ||
227 | if (ret < 0) | ||
228 | return -ENODEV; | ||
125 | 229 | ||
126 | u8 mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf; | 230 | value = ts2020_readreg(fe, 0x26); |
127 | u16 value, ndiv; | ||
128 | u32 srate = 0, f3db; | ||
129 | |||
130 | ts2020_init(fe); | ||
131 | |||
132 | /* unknown */ | ||
133 | ts2020_writereg(fe, 0x07, 0x02); | ||
134 | ts2020_writereg(fe, 0x10, 0x00); | ||
135 | ts2020_writereg(fe, 0x60, 0x79); | ||
136 | ts2020_writereg(fe, 0x08, 0x01); | ||
137 | ts2020_writereg(fe, 0x00, 0x01); | ||
138 | |||
139 | /* calculate and set freq divider */ | ||
140 | if (c->frequency < 1146000) { | ||
141 | ts2020_writereg(fe, 0x10, 0x11); | ||
142 | ndiv = ((c->frequency * (6 + 8) * 4) + | ||
143 | (TS2020_XTAL_FREQ / 2)) / | ||
144 | TS2020_XTAL_FREQ - 1024; | ||
145 | } else { | ||
146 | ts2020_writereg(fe, 0x10, 0x01); | ||
147 | ndiv = ((c->frequency * (6 + 8) * 2) + | ||
148 | (TS2020_XTAL_FREQ / 2)) / | ||
149 | TS2020_XTAL_FREQ - 1024; | ||
150 | } | ||
151 | |||
152 | ts2020_writereg(fe, 0x01, (ndiv & 0x0f00) >> 8); | ||
153 | ts2020_writereg(fe, 0x02, ndiv & 0x00ff); | ||
154 | |||
155 | /* set pll */ | ||
156 | ts2020_writereg(fe, 0x03, 0x06); | ||
157 | ts2020_writereg(fe, 0x51, 0x0f); | ||
158 | ts2020_writereg(fe, 0x51, 0x1f); | ||
159 | ts2020_writereg(fe, 0x50, 0x10); | ||
160 | ts2020_writereg(fe, 0x50, 0x00); | ||
161 | msleep(5); | ||
162 | |||
163 | /* unknown */ | ||
164 | ts2020_writereg(fe, 0x51, 0x17); | ||
165 | ts2020_writereg(fe, 0x51, 0x1f); | ||
166 | ts2020_writereg(fe, 0x50, 0x08); | ||
167 | ts2020_writereg(fe, 0x50, 0x00); | ||
168 | msleep(5); | ||
169 | |||
170 | value = ts2020_readreg(fe, 0x3d); | ||
171 | value &= 0x0f; | ||
172 | if ((value > 4) && (value < 15)) { | ||
173 | value -= 3; | ||
174 | if (value < 4) | ||
175 | value = 4; | ||
176 | value = ((value << 3) | 0x01) & 0x79; | ||
177 | } | ||
178 | 231 | ||
179 | ts2020_writereg(fe, 0x60, value); | 232 | f3db = (symbol_rate * 135) / 200 + 2000; |
180 | ts2020_writereg(fe, 0x51, 0x17); | 233 | f3db += FREQ_OFFSET_LOW_SYM_RATE; |
181 | ts2020_writereg(fe, 0x51, 0x1f); | ||
182 | ts2020_writereg(fe, 0x50, 0x08); | ||
183 | ts2020_writereg(fe, 0x50, 0x00); | ||
184 | |||
185 | /* set low-pass filter period */ | ||
186 | ts2020_writereg(fe, 0x04, 0x2e); | ||
187 | ts2020_writereg(fe, 0x51, 0x1b); | ||
188 | ts2020_writereg(fe, 0x51, 0x1f); | ||
189 | ts2020_writereg(fe, 0x50, 0x04); | ||
190 | ts2020_writereg(fe, 0x50, 0x00); | ||
191 | msleep(5); | ||
192 | |||
193 | srate = c->symbol_rate / 1000; | ||
194 | |||
195 | f3db = (srate << 2) / 5 + 2000; | ||
196 | if (srate < 5000) | ||
197 | f3db += 3000; | ||
198 | if (f3db < 7000) | 234 | if (f3db < 7000) |
199 | f3db = 7000; | 235 | f3db = 7000; |
200 | if (f3db > 40000) | 236 | if (f3db > 40000) |
201 | f3db = 40000; | 237 | f3db = 40000; |
202 | 238 | ||
203 | /* set low-pass filter baseband */ | 239 | gdiv28 = gdiv28 * 207 / (value * 2 + 151); |
204 | value = ts2020_readreg(fe, 0x26); | 240 | mlpf_max = gdiv28 * 135 / 100; |
205 | mlpf = 0x2e * 207 / ((value << 1) + 151); | 241 | mlpf_min = gdiv28 * 78 / 100; |
206 | mlpf_max = mlpf * 135 / 100; | ||
207 | mlpf_min = mlpf * 78 / 100; | ||
208 | if (mlpf_max > 63) | 242 | if (mlpf_max > 63) |
209 | mlpf_max = 63; | 243 | mlpf_max = 63; |
210 | 244 | ||
211 | /* rounded to the closest integer */ | 245 | lpf_coeff = 2766; |
212 | nlpf = ((mlpf * f3db * 1000) + (2766 * TS2020_XTAL_FREQ / 2)) | 246 | |
213 | / (2766 * TS2020_XTAL_FREQ); | 247 | nlpf = (f3db * gdiv28 * 2 / lpf_coeff / |
248 | (TS2020_XTAL_FREQ / 1000) + 1) / 2; | ||
214 | if (nlpf > 23) | 249 | if (nlpf > 23) |
215 | nlpf = 23; | 250 | nlpf = 23; |
216 | if (nlpf < 1) | 251 | if (nlpf < 1) |
217 | nlpf = 1; | 252 | nlpf = 1; |
218 | 253 | ||
219 | /* rounded to the closest integer */ | 254 | lpf_mxdiv = (nlpf * (TS2020_XTAL_FREQ / 1000) |
220 | mlpf_new = ((TS2020_XTAL_FREQ * nlpf * 2766) + | 255 | * lpf_coeff * 2 / f3db + 1) / 2; |
221 | (1000 * f3db / 2)) / (1000 * f3db); | ||
222 | 256 | ||
223 | if (mlpf_new < mlpf_min) { | 257 | if (lpf_mxdiv < mlpf_min) { |
224 | nlpf++; | 258 | nlpf++; |
225 | mlpf_new = ((TS2020_XTAL_FREQ * nlpf * 2766) + | 259 | lpf_mxdiv = (nlpf * (TS2020_XTAL_FREQ / 1000) |
226 | (1000 * f3db / 2)) / (1000 * f3db); | 260 | * lpf_coeff * 2 / f3db + 1) / 2; |
227 | } | 261 | } |
228 | 262 | ||
229 | if (mlpf_new > mlpf_max) | 263 | if (lpf_mxdiv > mlpf_max) |
230 | mlpf_new = mlpf_max; | 264 | lpf_mxdiv = mlpf_max; |
231 | 265 | ||
232 | ts2020_writereg(fe, 0x04, mlpf_new); | 266 | ret = ts2020_writereg(fe, 0x04, lpf_mxdiv); |
233 | ts2020_writereg(fe, 0x06, nlpf); | 267 | ret |= ts2020_writereg(fe, 0x06, nlpf); |
234 | ts2020_writereg(fe, 0x51, 0x1b); | ||
235 | ts2020_writereg(fe, 0x51, 0x1f); | ||
236 | ts2020_writereg(fe, 0x50, 0x04); | ||
237 | ts2020_writereg(fe, 0x50, 0x00); | ||
238 | msleep(5); | ||
239 | 268 | ||
240 | /* unknown */ | 269 | ret |= ts2020_tuner_gate_ctrl(fe, 0x04); |
241 | ts2020_writereg(fe, 0x51, 0x1e); | ||
242 | ts2020_writereg(fe, 0x51, 0x1f); | ||
243 | ts2020_writereg(fe, 0x50, 0x01); | ||
244 | ts2020_writereg(fe, 0x50, 0x00); | ||
245 | msleep(60); | ||
246 | 270 | ||
247 | return 0; | 271 | ret |= ts2020_tuner_gate_ctrl(fe, 0x01); |
248 | } | ||
249 | 272 | ||
250 | static int ts2020_release(struct dvb_frontend *fe) | 273 | msleep(80); |
251 | { | 274 | /* calculate offset assuming 96000kHz*/ |
252 | struct ts2020_state *state = fe->tuner_priv; | 275 | offset_khz = (ndiv - ndiv % 2 + 1024) * TS2020_XTAL_FREQ |
276 | / (6 + 8) / (div4 + 1) / 2; | ||
253 | 277 | ||
254 | fe->tuner_priv = NULL; | 278 | priv->frequency = offset_khz; |
255 | kfree(state); | 279 | |
280 | return (ret < 0) ? -EINVAL : 0; | ||
281 | } | ||
256 | 282 | ||
283 | static int ts2020_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
284 | { | ||
285 | struct ts2020_priv *priv = fe->tuner_priv; | ||
286 | *frequency = priv->frequency; | ||
257 | return 0; | 287 | return 0; |
258 | } | 288 | } |
259 | 289 | ||
260 | static int ts2020_get_signal_strength(struct dvb_frontend *fe, | 290 | /* read TS2020 signal strength */ |
261 | u16 *signal_strength) | 291 | static int ts2020_read_signal_strength(struct dvb_frontend *fe, |
292 | u16 *signal_strength) | ||
262 | { | 293 | { |
263 | u16 sig_reading, sig_strength; | 294 | u16 sig_reading, sig_strength; |
264 | u8 rfgain, bbgain; | 295 | u8 rfgain, bbgain; |
@@ -281,35 +312,57 @@ static int ts2020_get_signal_strength(struct dvb_frontend *fe, | |||
281 | return 0; | 312 | return 0; |
282 | } | 313 | } |
283 | 314 | ||
284 | static struct dvb_tuner_ops ts2020_ops = { | 315 | static struct dvb_tuner_ops ts2020_tuner_ops = { |
285 | .info = { | 316 | .info = { |
286 | .name = "Montage Technology TS2020 Silicon Tuner", | 317 | .name = "TS2020", |
287 | .frequency_min = 950000, | 318 | .frequency_min = 950000, |
288 | .frequency_max = 2150000, | 319 | .frequency_max = 2150000 |
289 | }, | 320 | }, |
290 | |||
291 | .init = ts2020_init, | 321 | .init = ts2020_init, |
292 | .release = ts2020_release, | 322 | .release = ts2020_release, |
323 | .sleep = ts2020_sleep, | ||
293 | .set_params = ts2020_set_params, | 324 | .set_params = ts2020_set_params, |
294 | .get_frequency = ts2020_get_frequency, | 325 | .get_frequency = ts2020_get_frequency, |
295 | .get_rf_strength = ts2020_get_signal_strength | 326 | .get_rf_strength = ts2020_read_signal_strength, |
296 | }; | 327 | }; |
297 | 328 | ||
298 | struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe, | 329 | struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe, |
299 | const struct ts2020_config *config, struct i2c_adapter *i2c) | 330 | const struct ts2020_config *config, |
331 | struct i2c_adapter *i2c) | ||
300 | { | 332 | { |
301 | struct ts2020_state *state = NULL; | 333 | struct ts2020_priv *priv = NULL; |
334 | u8 buf; | ||
335 | |||
336 | priv = kzalloc(sizeof(struct ts2020_priv), GFP_KERNEL); | ||
337 | if (priv == NULL) | ||
338 | return NULL; | ||
302 | 339 | ||
303 | /* allocate memory for the internal state */ | 340 | priv->i2c_address = config->tuner_address; |
304 | state = kzalloc(sizeof(struct ts2020_state), GFP_KERNEL); | 341 | priv->i2c = i2c; |
305 | if (!state) | 342 | priv->clk_out_div = config->clk_out_div; |
343 | fe->tuner_priv = priv; | ||
344 | |||
345 | /* Wake Up the tuner */ | ||
346 | if ((0x03 & ts2020_readreg(fe, 0x00)) == 0x00) { | ||
347 | ts2020_writereg(fe, 0x00, 0x01); | ||
348 | msleep(2); | ||
349 | } | ||
350 | |||
351 | ts2020_writereg(fe, 0x00, 0x03); | ||
352 | msleep(2); | ||
353 | |||
354 | /* Check the tuner version */ | ||
355 | buf = ts2020_readreg(fe, 0x00); | ||
356 | if ((buf == 0x01) || (buf == 0x41) || (buf == 0x81)) | ||
357 | printk(KERN_INFO "%s: Find tuner TS2020!\n", __func__); | ||
358 | else { | ||
359 | printk(KERN_ERR "%s: Read tuner reg[0] = %d\n", __func__, buf); | ||
360 | kfree(priv); | ||
306 | return NULL; | 361 | return NULL; |
362 | } | ||
307 | 363 | ||
308 | /* setup the state */ | 364 | memcpy(&fe->ops.tuner_ops, &ts2020_tuner_ops, |
309 | state->tuner_address = config->tuner_address; | 365 | sizeof(struct dvb_tuner_ops)); |
310 | state->i2c = i2c; | ||
311 | fe->tuner_priv = state; | ||
312 | fe->ops.tuner_ops = ts2020_ops; | ||
313 | fe->ops.read_signal_strength = fe->ops.tuner_ops.get_rf_strength; | 366 | fe->ops.read_signal_strength = fe->ops.tuner_ops.get_rf_strength; |
314 | 367 | ||
315 | return fe; | 368 | return fe; |
diff --git a/drivers/media/dvb-frontends/ts2020.h b/drivers/media/dvb-frontends/ts2020.h index 13a172dfd582..c7e64afa614a 100644 --- a/drivers/media/dvb-frontends/ts2020.h +++ b/drivers/media/dvb-frontends/ts2020.h | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | struct ts2020_config { | 27 | struct ts2020_config { |
28 | u8 tuner_address; | 28 | u8 tuner_address; |
29 | u8 clk_out_div; | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | #if defined(CONFIG_DVB_TS2020) || \ | 32 | #if defined(CONFIG_DVB_TS2020) || \ |