linux/drivers/media/video/tea5767.c
<<
>>
Prefs
   1/*
   2 * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
   3 * I2C address is allways 0xC0.
   4 *
   5 *
   6 * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org)
   7 * This code is placed under the terms of the GNU General Public License
   8 *
   9 * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
  10 * from their contributions on DScaler.
  11 */
  12
  13#include <linux/i2c.h>
  14#include <linux/delay.h>
  15#include <linux/videodev.h>
  16#include "tuner-i2c.h"
  17#include "tea5767.h"
  18
  19static int debug = 0;
  20module_param(debug, int, 0644);
  21MODULE_PARM_DESC(debug, "enable verbose debug messages");
  22
  23#define PREFIX "tea5767 "
  24
  25struct tea5767_priv {
  26        struct tuner_i2c_props i2c_props;
  27
  28        u32 frequency;
  29};
  30
  31/*****************************************************************************/
  32
  33/******************************
  34 * Write mode register values *
  35 ******************************/
  36
  37/* First register */
  38#define TEA5767_MUTE            0x80    /* Mutes output */
  39#define TEA5767_SEARCH          0x40    /* Activates station search */
  40/* Bits 0-5 for divider MSB */
  41
  42/* Second register */
  43/* Bits 0-7 for divider LSB */
  44
  45/* Third register */
  46
  47/* Station search from botton to up */
  48#define TEA5767_SEARCH_UP       0x80
  49
  50/* Searches with ADC output = 10 */
  51#define TEA5767_SRCH_HIGH_LVL   0x60
  52
  53/* Searches with ADC output = 10 */
  54#define TEA5767_SRCH_MID_LVL    0x40
  55
  56/* Searches with ADC output = 5 */
  57#define TEA5767_SRCH_LOW_LVL    0x20
  58
  59/* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */
  60#define TEA5767_HIGH_LO_INJECT  0x10
  61
  62/* Disable stereo */
  63#define TEA5767_MONO            0x08
  64
  65/* Disable right channel and turns to mono */
  66#define TEA5767_MUTE_RIGHT      0x04
  67
  68/* Disable left channel and turns to mono */
  69#define TEA5767_MUTE_LEFT       0x02
  70
  71#define TEA5767_PORT1_HIGH      0x01
  72
  73/* Fourth register */
  74#define TEA5767_PORT2_HIGH      0x80
  75/* Chips stops working. Only I2C bus remains on */
  76#define TEA5767_STDBY           0x40
  77
  78/* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */
  79#define TEA5767_JAPAN_BAND      0x20
  80
  81/* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */
  82#define TEA5767_XTAL_32768      0x10
  83
  84/* Cuts weak signals */
  85#define TEA5767_SOFT_MUTE       0x08
  86
  87/* Activates high cut control */
  88#define TEA5767_HIGH_CUT_CTRL   0x04
  89
  90/* Activates stereo noise control */
  91#define TEA5767_ST_NOISE_CTL    0x02
  92
  93/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
  94#define TEA5767_SRCH_IND        0x01
  95
  96/* Fifth register */
  97
  98/* By activating, it will use Xtal at 13 MHz as reference for divider */
  99#define TEA5767_PLLREF_ENABLE   0x80
 100
 101/* By activating, deemphasis=50, or else, deemphasis of 50us */
 102#define TEA5767_DEEMPH_75       0X40
 103
 104/*****************************
 105 * Read mode register values *
 106 *****************************/
 107
 108/* First register */
 109#define TEA5767_READY_FLAG_MASK 0x80
 110#define TEA5767_BAND_LIMIT_MASK 0X40
 111/* Bits 0-5 for divider MSB after search or preset */
 112
 113/* Second register */
 114/* Bits 0-7 for divider LSB after search or preset */
 115
 116/* Third register */
 117#define TEA5767_STEREO_MASK     0x80
 118#define TEA5767_IF_CNTR_MASK    0x7f
 119
 120/* Fourth register */
 121#define TEA5767_ADC_LEVEL_MASK  0xf0
 122
 123/* should be 0 */
 124#define TEA5767_CHIP_ID_MASK    0x0f
 125
 126/* Fifth register */
 127/* Reserved for future extensions */
 128#define TEA5767_RESERVED_MASK   0xff
 129
 130enum 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/*****************************************************************************/
 139
 140static void tea5767_status_dump(unsigned char *buffer)
 141{
 142        unsigned int div, frq;
 143
 144        if (TEA5767_READY_FLAG_MASK & buffer[0])
 145                printk(PREFIX "Ready Flag ON\n");
 146        else
 147                printk(PREFIX "Ready Flag OFF\n");
 148
 149        if (TEA5767_BAND_LIMIT_MASK & buffer[0])
 150                printk(PREFIX "Tuner at band limit\n");
 151        else
 152                printk(PREFIX "Tuner not at band limit\n");
 153
 154        div = ((buffer[0] & 0x3f) << 8) | buffer[1];
 155
 156        switch (TEA5767_HIGH_LO_32768) {
 157        case TEA5767_HIGH_LO_13MHz:
 158                frq = (div * 50000 - 700000 - 225000) / 4;      /* Freq in KHz */
 159                break;
 160        case TEA5767_LOW_LO_13MHz:
 161                frq = (div * 50000 + 700000 + 225000) / 4;      /* Freq in KHz */
 162                break;
 163        case TEA5767_LOW_LO_32768:
 164                frq = (div * 32768 + 700000 + 225000) / 4;      /* Freq in KHz */
 165                break;
 166        case TEA5767_HIGH_LO_32768:
 167        default:
 168                frq = (div * 32768 - 700000 - 225000) / 4;      /* Freq in KHz */
 169                break;
 170        }
 171        buffer[0] = (div >> 8) & 0x3f;
 172        buffer[1] = div & 0xff;
 173
 174        printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
 175               frq / 1000, frq % 1000, div);
 176
 177        if (TEA5767_STEREO_MASK & buffer[2])
 178                printk(PREFIX "Stereo\n");
 179        else
 180                printk(PREFIX "Mono\n");
 181
 182        printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
 183
 184        printk(PREFIX "ADC Level = %d\n",
 185               (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
 186
 187        printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
 188
 189        printk(PREFIX "Reserved = 0x%02x\n",
 190               (buffer[4] & TEA5767_RESERVED_MASK));
 191}
 192
 193/* Freq should be specifyed at 62.5 Hz */
 194static int set_radio_freq(struct dvb_frontend *fe,
 195                          struct analog_parameters *params)
 196{
 197        struct tea5767_priv *priv = fe->tuner_priv;
 198        unsigned int frq = params->frequency;
 199        unsigned char buffer[5];
 200        unsigned div;
 201        int rc;
 202
 203        tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
 204
 205        /* Rounds freq to next decimal value - for 62.5 KHz step */
 206        /* frq = 20*(frq/16)+radio_frq[frq%16]; */
 207
 208        buffer[2] = TEA5767_PORT1_HIGH;
 209        buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
 210                    TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND;
 211        buffer[4] = 0;
 212
 213        if (params->audmode == V4L2_TUNER_MODE_MONO) {
 214                tuner_dbg("TEA5767 set to mono\n");
 215                buffer[2] |= TEA5767_MONO;
 216        } else {
 217                tuner_dbg("TEA5767 set to stereo\n");
 218        }
 219
 220        /* Should be replaced */
 221        switch (TEA5767_HIGH_LO_32768) {
 222        case TEA5767_HIGH_LO_13MHz:
 223                tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n");
 224                buffer[2] |= TEA5767_HIGH_LO_INJECT;
 225                buffer[4] |= TEA5767_PLLREF_ENABLE;
 226                div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
 227                break;
 228        case TEA5767_LOW_LO_13MHz:
 229                tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n");
 230
 231                buffer[4] |= TEA5767_PLLREF_ENABLE;
 232                div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
 233                break;
 234        case TEA5767_LOW_LO_32768:
 235                tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n");
 236                buffer[3] |= TEA5767_XTAL_32768;
 237                /* const 700=4000*175 Khz - to adjust freq to right value */
 238                div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
 239                break;
 240        case TEA5767_HIGH_LO_32768:
 241        default:
 242                tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n");
 243
 244                buffer[2] |= TEA5767_HIGH_LO_INJECT;
 245                buffer[3] |= TEA5767_XTAL_32768;
 246                div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
 247                break;
 248        }
 249        buffer[0] = (div >> 8) & 0x3f;
 250        buffer[1] = div & 0xff;
 251
 252        if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
 253                tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
 254
 255        if (debug) {
 256                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);
 258                else
 259                        tea5767_status_dump(buffer);
 260        }
 261
 262        priv->frequency = frq * 125 / 2;
 263
 264        return 0;
 265}
 266
 267static int tea5767_read_status(struct dvb_frontend *fe, char *buffer)
 268{
 269        struct tea5767_priv *priv = fe->tuner_priv;
 270        int rc;
 271
 272        memset(buffer, 0, 5);
 273        if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) {
 274                tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
 275                return -EREMOTEIO;
 276        }
 277
 278        return 0;
 279}
 280
 281static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer)
 282{
 283        struct tea5767_priv *priv = fe->tuner_priv;
 284
 285        int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
 286
 287        tuner_dbg("Signal strength: %d\n", signal);
 288
 289        return signal;
 290}
 291
 292static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer)
 293{
 294        struct tea5767_priv *priv = fe->tuner_priv;
 295
 296        int stereo = buffer[2] & TEA5767_STEREO_MASK;
 297
 298        tuner_dbg("Radio ST GET = %02x\n", stereo);
 299
 300        return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
 301}
 302
 303static int tea5767_get_status(struct dvb_frontend *fe, u32 *status)
 304{
 305        unsigned char buffer[5];
 306
 307        *status = 0;
 308
 309        if (0 == tea5767_read_status(fe, buffer)) {
 310                if (tea5767_signal(fe, buffer))
 311                        *status = TUNER_STATUS_LOCKED;
 312                if (tea5767_stereo(fe, buffer))
 313                        *status |= TUNER_STATUS_STEREO;
 314        }
 315
 316        return 0;
 317}
 318
 319static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
 320{
 321        unsigned char buffer[5];
 322
 323        *strength = 0;
 324
 325        if (0 == tea5767_read_status(fe, buffer))
 326                *strength = tea5767_signal(fe, buffer);
 327
 328        return 0;
 329}
 330
 331static int tea5767_standby(struct dvb_frontend *fe)
 332{
 333        unsigned char buffer[5];
 334        struct tea5767_priv *priv = fe->tuner_priv;
 335        unsigned div, rc;
 336
 337        div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
 338        buffer[0] = (div >> 8) & 0x3f;
 339        buffer[1] = div & 0xff;
 340        buffer[2] = TEA5767_PORT1_HIGH;
 341        buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
 342                    TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
 343        buffer[4] = 0;
 344
 345        if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
 346                tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
 347
 348        return 0;
 349}
 350
 351int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
 352{
 353        struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
 354        unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 355        int rc;
 356
 357        if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) {
 358                printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
 359                return EINVAL;
 360        }
 361
 362        /* If all bytes are the same then it's a TV tuner and not a tea5767 */
 363        if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
 364            buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
 365                printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n");
 366                return EINVAL;
 367        }
 368
 369        /*  Status bytes:
 370         *  Byte 4: bit 3:1 : CI (Chip Identification) == 0
 371         *          bit 0   : internally set to 0
 372         *  Byte 5: bit 7:0 : == 0
 373         */
 374        if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
 375                printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n");
 376                return EINVAL;
 377        }
 378
 379        /* It seems that tea5767 returns 0xff after the 5th byte */
 380        if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
 381                printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
 382                return EINVAL;
 383        }
 384
 385        printk(KERN_WARNING "TEA5767 detected.\n");
 386        return 0;
 387}
 388
 389static int tea5767_release(struct dvb_frontend *fe)
 390{
 391        kfree(fe->tuner_priv);
 392        fe->tuner_priv = NULL;
 393
 394        return 0;
 395}
 396
 397static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 398{
 399        struct tea5767_priv *priv = fe->tuner_priv;
 400        *frequency = priv->frequency;
 401        return 0;
 402}
 403
 404static struct dvb_tuner_ops tea5767_tuner_ops = {
 405        .info = {
 406                .name           = "tea5767", // Philips TEA5767HN FM Radio
 407        },
 408
 409        .set_analog_params = set_radio_freq,
 410        .sleep             = tea5767_standby,
 411        .release           = tea5767_release,
 412        .get_frequency     = tea5767_get_frequency,
 413        .get_status        = tea5767_get_status,
 414        .get_rf_strength   = tea5767_get_rf_strength,
 415};
 416
 417struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
 418                                    struct i2c_adapter* i2c_adap,
 419                                    u8 i2c_addr)
 420{
 421        struct tea5767_priv *priv = NULL;
 422
 423        priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
 424        if (priv == NULL)
 425                return NULL;
 426        fe->tuner_priv = priv;
 427
 428        priv->i2c_props.addr = i2c_addr;
 429        priv->i2c_props.adap = i2c_adap;
 430
 431        memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops,
 432               sizeof(struct dvb_tuner_ops));
 433
 434        tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio");
 435
 436        return fe;
 437}
 438
 439
 440EXPORT_SYMBOL_GPL(tea5767_attach);
 441EXPORT_SYMBOL_GPL(tea5767_autodetection);
 442
 443MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver");
 444MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
 445MODULE_LICENSE("GPL");
 446