diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-10-18 19:10:07 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:00:54 -0500 |
commit | 0e1165e8d05ef4a530001ea4ac5ff0df78129dd2 (patch) | |
tree | c018261ded3131c6e4cd0957d5434110efa6dd68 /drivers/media/video/tea5767.c | |
parent | 7f1711234e6a21c153e892758d9d82c333ab37ac (diff) |
V4L/DVB (6385): Adds the capability of configuring tea5767 support
tea5767 has several possible configurations. Before the patch, the
driver were assuming the more common configuration. However, some newer
cards, like MSI @nyware Master requires other configurations, like
de-activating a gpio port and changing chip Xtal.
This patch adds the capability of altering device configuration at
runtime. This may also be used later to activate some features like
auto-mute when signal is weak.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/tea5767.c')
-rw-r--r-- | drivers/media/video/tea5767.c | 89 |
1 files changed, 62 insertions, 27 deletions
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 71df419df7bc..2d2acbdd24ac 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c | |||
@@ -22,10 +22,12 @@ MODULE_PARM_DESC(debug, "enable verbose debug messages"); | |||
22 | 22 | ||
23 | #define PREFIX "tea5767 " | 23 | #define PREFIX "tea5767 " |
24 | 24 | ||
25 | struct tea5767_priv { | 25 | /*****************************************************************************/ |
26 | struct tuner_i2c_props i2c_props; | ||
27 | 26 | ||
28 | u32 frequency; | 27 | struct tea5767_priv { |
28 | struct tuner_i2c_props i2c_props; | ||
29 | u32 frequency; | ||
30 | struct tea5767_ctrl ctrl; | ||
29 | }; | 31 | }; |
30 | 32 | ||
31 | /*****************************************************************************/ | 33 | /*****************************************************************************/ |
@@ -127,17 +129,10 @@ struct tea5767_priv { | |||
127 | /* Reserved for future extensions */ | 129 | /* Reserved for future extensions */ |
128 | #define TEA5767_RESERVED_MASK 0xff | 130 | #define TEA5767_RESERVED_MASK 0xff |
129 | 131 | ||
130 | enum tea5767_xtal_freq { | ||
131 | TEA5767_LOW_LO_32768 = 0, | ||
132 | TEA5767_HIGH_LO_32768 = 1, | ||
133 | TEA5767_LOW_LO_13MHz = 2, | ||
134 | TEA5767_HIGH_LO_13MHz = 3, | ||
135 | }; | ||
136 | |||
137 | |||
138 | /*****************************************************************************/ | 132 | /*****************************************************************************/ |
139 | 133 | ||
140 | static void tea5767_status_dump(unsigned char *buffer) | 134 | static void tea5767_status_dump(struct tea5767_priv *priv, |
135 | unsigned char *buffer) | ||
141 | { | 136 | { |
142 | unsigned int div, frq; | 137 | unsigned int div, frq; |
143 | 138 | ||
@@ -153,7 +148,7 @@ static void tea5767_status_dump(unsigned char *buffer) | |||
153 | 148 | ||
154 | div = ((buffer[0] & 0x3f) << 8) | buffer[1]; | 149 | div = ((buffer[0] & 0x3f) << 8) | buffer[1]; |
155 | 150 | ||
156 | switch (TEA5767_HIGH_LO_32768) { | 151 | switch (priv->ctrl.xtal_freq) { |
157 | case TEA5767_HIGH_LO_13MHz: | 152 | case TEA5767_HIGH_LO_13MHz: |
158 | frq = (div * 50000 - 700000 - 225000) / 4; /* Freq in KHz */ | 153 | frq = (div * 50000 - 700000 - 225000) / 4; /* Freq in KHz */ |
159 | break; | 154 | break; |
@@ -202,13 +197,10 @@ static int set_radio_freq(struct dvb_frontend *fe, | |||
202 | 197 | ||
203 | tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000); | 198 | tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000); |
204 | 199 | ||
205 | /* Rounds freq to next decimal value - for 62.5 KHz step */ | 200 | buffer[2] = 0; |
206 | /* frq = 20*(frq/16)+radio_frq[frq%16]; */ | ||
207 | 201 | ||
208 | buffer[2] = TEA5767_PORT1_HIGH; | 202 | if (priv->ctrl.port1) |
209 | buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL | | 203 | buffer[2] |= TEA5767_PORT1_HIGH; |
210 | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND; | ||
211 | buffer[4] = 0; | ||
212 | 204 | ||
213 | if (params->audmode == V4L2_TUNER_MODE_MONO) { | 205 | if (params->audmode == V4L2_TUNER_MODE_MONO) { |
214 | tuner_dbg("TEA5767 set to mono\n"); | 206 | tuner_dbg("TEA5767 set to mono\n"); |
@@ -217,18 +209,45 @@ static int set_radio_freq(struct dvb_frontend *fe, | |||
217 | tuner_dbg("TEA5767 set to stereo\n"); | 209 | tuner_dbg("TEA5767 set to stereo\n"); |
218 | } | 210 | } |
219 | 211 | ||
220 | /* Should be replaced */ | 212 | |
221 | switch (TEA5767_HIGH_LO_32768) { | 213 | buffer[3] = 0; |
214 | |||
215 | if (priv->ctrl.port2) | ||
216 | buffer[3] |= TEA5767_PORT2_HIGH; | ||
217 | |||
218 | if (priv->ctrl.high_cut) | ||
219 | buffer[3] |= TEA5767_HIGH_CUT_CTRL; | ||
220 | |||
221 | if (priv->ctrl.st_noise) | ||
222 | buffer[3] |= TEA5767_ST_NOISE_CTL; | ||
223 | |||
224 | if (priv->ctrl.soft_mute) | ||
225 | buffer[3] |= TEA5767_SOFT_MUTE; | ||
226 | |||
227 | if (priv->ctrl.japan_band) | ||
228 | buffer[3] |= TEA5767_JAPAN_BAND; | ||
229 | |||
230 | buffer[4] = 0; | ||
231 | |||
232 | if (priv->ctrl.deemph_75) | ||
233 | buffer[4] |= TEA5767_DEEMPH_75; | ||
234 | |||
235 | if (priv->ctrl.pllref) | ||
236 | buffer[4] |= TEA5767_PLLREF_ENABLE; | ||
237 | |||
238 | |||
239 | /* Rounds freq to next decimal value - for 62.5 KHz step */ | ||
240 | /* frq = 20*(frq/16)+radio_frq[frq%16]; */ | ||
241 | |||
242 | switch (priv->ctrl.xtal_freq) { | ||
222 | case TEA5767_HIGH_LO_13MHz: | 243 | case TEA5767_HIGH_LO_13MHz: |
223 | tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n"); | 244 | tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n"); |
224 | buffer[2] |= TEA5767_HIGH_LO_INJECT; | 245 | buffer[2] |= TEA5767_HIGH_LO_INJECT; |
225 | buffer[4] |= TEA5767_PLLREF_ENABLE; | ||
226 | div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000; | 246 | div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000; |
227 | break; | 247 | break; |
228 | case TEA5767_LOW_LO_13MHz: | 248 | case TEA5767_LOW_LO_13MHz: |
229 | tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n"); | 249 | tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n"); |
230 | 250 | ||
231 | buffer[4] |= TEA5767_PLLREF_ENABLE; | ||
232 | div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000; | 251 | div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000; |
233 | break; | 252 | break; |
234 | case TEA5767_LOW_LO_32768: | 253 | case TEA5767_LOW_LO_32768: |
@@ -256,7 +275,7 @@ static int set_radio_freq(struct dvb_frontend *fe, | |||
256 | if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) | 275 | if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) |
257 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | 276 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); |
258 | else | 277 | else |
259 | tea5767_status_dump(buffer); | 278 | tea5767_status_dump(priv, buffer); |
260 | } | 279 | } |
261 | 280 | ||
262 | priv->frequency = frq * 125 / 2; | 281 | priv->frequency = frq * 125 / 2; |
@@ -398,6 +417,16 @@ static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency) | |||
398 | { | 417 | { |
399 | struct tea5767_priv *priv = fe->tuner_priv; | 418 | struct tea5767_priv *priv = fe->tuner_priv; |
400 | *frequency = priv->frequency; | 419 | *frequency = priv->frequency; |
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int tea5767_set_config (struct dvb_frontend *fe, void *priv_cfg) | ||
425 | { | ||
426 | struct tea5767_priv *priv = fe->tuner_priv; | ||
427 | |||
428 | memcpy(&priv->ctrl, priv_cfg, sizeof(priv->ctrl)); | ||
429 | |||
401 | return 0; | 430 | return 0; |
402 | } | 431 | } |
403 | 432 | ||
@@ -407,6 +436,7 @@ static struct dvb_tuner_ops tea5767_tuner_ops = { | |||
407 | }, | 436 | }, |
408 | 437 | ||
409 | .set_analog_params = set_radio_freq, | 438 | .set_analog_params = set_radio_freq, |
439 | .set_config = tea5767_set_config, | ||
410 | .sleep = tea5767_standby, | 440 | .sleep = tea5767_standby, |
411 | .release = tea5767_release, | 441 | .release = tea5767_release, |
412 | .get_frequency = tea5767_get_frequency, | 442 | .get_frequency = tea5767_get_frequency, |
@@ -425,8 +455,14 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, | |||
425 | return NULL; | 455 | return NULL; |
426 | fe->tuner_priv = priv; | 456 | fe->tuner_priv = priv; |
427 | 457 | ||
428 | priv->i2c_props.addr = i2c_addr; | 458 | priv->i2c_props.addr = i2c_addr; |
429 | priv->i2c_props.adap = i2c_adap; | 459 | priv->i2c_props.adap = i2c_adap; |
460 | priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768; | ||
461 | priv->ctrl.port1 = 1; | ||
462 | priv->ctrl.port2 = 1; | ||
463 | priv->ctrl.high_cut = 1; | ||
464 | priv->ctrl.st_noise = 1; | ||
465 | priv->ctrl.japan_band = 1; | ||
430 | 466 | ||
431 | memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops, | 467 | memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops, |
432 | sizeof(struct dvb_tuner_ops)); | 468 | sizeof(struct dvb_tuner_ops)); |
@@ -436,7 +472,6 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, | |||
436 | return fe; | 472 | return fe; |
437 | } | 473 | } |
438 | 474 | ||
439 | |||
440 | EXPORT_SYMBOL_GPL(tea5767_attach); | 475 | EXPORT_SYMBOL_GPL(tea5767_attach); |
441 | EXPORT_SYMBOL_GPL(tea5767_autodetection); | 476 | EXPORT_SYMBOL_GPL(tea5767_autodetection); |
442 | 477 | ||