linux/drivers/media/radio/radio-tea5764.c
<<
>>
Prefs
   1/*
   2 * driver/media/radio/radio-tea5764.c
   3 *
   4 * Driver for TEA5764 radio chip for linux 2.6.
   5 * This driver is for TEA5764 chip from NXP, used in EZX phones from Motorola.
   6 * The I2C protocol is used for communicate with chip.
   7 *
   8 * Based in radio-tea5761.c Copyright (C) 2005 Nokia Corporation
   9 *
  10 *  Copyright (c) 2008 Fabio Belavenuto <belavenuto@gmail.com>
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25 *
  26 * History:
  27 * 2008-12-06   Fabio Belavenuto <belavenuto@gmail.com>
  28 *              initial code
  29 *
  30 * TODO:
  31 *  add platform_data support for IRQs platform dependencies
  32 *  add RDS support
  33 */
  34#include <linux/kernel.h>
  35#include <linux/slab.h>
  36#include <linux/module.h>
  37#include <linux/init.h>                 /* Initdata                     */
  38#include <linux/videodev2.h>            /* kernel radio structs         */
  39#include <linux/i2c.h>                  /* I2C                          */
  40#include <media/v4l2-common.h>
  41#include <media/v4l2-ioctl.h>
  42#include <linux/version.h>              /* for KERNEL_VERSION MACRO     */
  43
  44#define DRIVER_VERSION  "v0.01"
  45#define RADIO_VERSION   KERNEL_VERSION(0, 0, 1)
  46
  47#define DRIVER_AUTHOR   "Fabio Belavenuto <belavenuto@gmail.com>"
  48#define DRIVER_DESC     "A driver for the TEA5764 radio chip for EZX Phones."
  49
  50#define PINFO(format, ...)\
  51        printk(KERN_INFO KBUILD_MODNAME ": "\
  52                DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
  53#define PWARN(format, ...)\
  54        printk(KERN_WARNING KBUILD_MODNAME ": "\
  55                DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
  56# define PDEBUG(format, ...)\
  57        printk(KERN_DEBUG KBUILD_MODNAME ": "\
  58                DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
  59
  60/* Frequency limits in MHz -- these are European values.  For Japanese
  61devices, that would be 76000 and 91000.  */
  62#define FREQ_MIN  87500
  63#define FREQ_MAX 108000
  64#define FREQ_MUL 16
  65
  66/* TEA5764 registers */
  67#define TEA5764_MANID           0x002b
  68#define TEA5764_CHIPID          0x5764
  69
  70#define TEA5764_INTREG_BLMSK    0x0001
  71#define TEA5764_INTREG_FRRMSK   0x0002
  72#define TEA5764_INTREG_LEVMSK   0x0008
  73#define TEA5764_INTREG_IFMSK    0x0010
  74#define TEA5764_INTREG_BLMFLAG  0x0100
  75#define TEA5764_INTREG_FRRFLAG  0x0200
  76#define TEA5764_INTREG_LEVFLAG  0x0800
  77#define TEA5764_INTREG_IFFLAG   0x1000
  78
  79#define TEA5764_FRQSET_SUD      0x8000
  80#define TEA5764_FRQSET_SM       0x4000
  81
  82#define TEA5764_TNCTRL_PUPD1    0x8000
  83#define TEA5764_TNCTRL_PUPD0    0x4000
  84#define TEA5764_TNCTRL_BLIM     0x2000
  85#define TEA5764_TNCTRL_SWPM     0x1000
  86#define TEA5764_TNCTRL_IFCTC    0x0800
  87#define TEA5764_TNCTRL_AFM      0x0400
  88#define TEA5764_TNCTRL_SMUTE    0x0200
  89#define TEA5764_TNCTRL_SNC      0x0100
  90#define TEA5764_TNCTRL_MU       0x0080
  91#define TEA5764_TNCTRL_SSL1     0x0040
  92#define TEA5764_TNCTRL_SSL0     0x0020
  93#define TEA5764_TNCTRL_HLSI     0x0010
  94#define TEA5764_TNCTRL_MST      0x0008
  95#define TEA5764_TNCTRL_SWP      0x0004
  96#define TEA5764_TNCTRL_DTC      0x0002
  97#define TEA5764_TNCTRL_AHLSI    0x0001
  98
  99#define TEA5764_TUNCHK_LEVEL(x) (((x) & 0x00F0) >> 4)
 100#define TEA5764_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9)
 101#define TEA5764_TUNCHK_TUNTO    0x0100
 102#define TEA5764_TUNCHK_LD       0x0008
 103#define TEA5764_TUNCHK_STEREO   0x0004
 104
 105#define TEA5764_TESTREG_TRIGFR  0x0800
 106
 107struct tea5764_regs {
 108        u16 intreg;                             /* INTFLAG & INTMSK */
 109        u16 frqset;                             /* FRQSETMSB & FRQSETLSB */
 110        u16 tnctrl;                             /* TNCTRL1 & TNCTRL2 */
 111        u16 frqchk;                             /* FRQCHKMSB & FRQCHKLSB */
 112        u16 tunchk;                             /* IFCHK & LEVCHK */
 113        u16 testreg;                            /* TESTBITS & TESTMODE */
 114        u16 rdsstat;                            /* RDSSTAT1 & RDSSTAT2 */
 115        u16 rdslb;                              /* RDSLBMSB & RDSLBLSB */
 116        u16 rdspb;                              /* RDSPBMSB & RDSPBLSB */
 117        u16 rdsbc;                              /* RDSBBC & RDSGBC */
 118        u16 rdsctrl;                            /* RDSCTRL1 & RDSCTRL2 */
 119        u16 rdsbbl;                             /* PAUSEDET & RDSBBL */
 120        u16 manid;                              /* MANID1 & MANID2 */
 121        u16 chipid;                             /* CHIPID1 & CHIPID2 */
 122} __attribute__ ((packed));
 123
 124struct tea5764_write_regs {
 125        u8 intreg;                              /* INTMSK */
 126        u16 frqset;                             /* FRQSETMSB & FRQSETLSB */
 127        u16 tnctrl;                             /* TNCTRL1 & TNCTRL2 */
 128        u16 testreg;                            /* TESTBITS & TESTMODE */
 129        u16 rdsctrl;                            /* RDSCTRL1 & RDSCTRL2 */
 130        u16 rdsbbl;                             /* PAUSEDET & RDSBBL */
 131} __attribute__ ((packed));
 132
 133#ifndef RADIO_TEA5764_XTAL
 134#define RADIO_TEA5764_XTAL 1
 135#endif
 136
 137static int radio_nr = -1;
 138static int use_xtal = RADIO_TEA5764_XTAL;
 139
 140struct tea5764_device {
 141        struct i2c_client               *i2c_client;
 142        struct video_device             *videodev;
 143        struct tea5764_regs             regs;
 144        struct mutex                    mutex;
 145};
 146
 147/* I2C code related */
 148int tea5764_i2c_read(struct tea5764_device *radio)
 149{
 150        int i;
 151        u16 *p = (u16 *) &radio->regs;
 152
 153        struct i2c_msg msgs[1] = {
 154                { radio->i2c_client->addr, I2C_M_RD, sizeof(radio->regs),
 155                        (void *)&radio->regs },
 156        };
 157        if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
 158                return -EIO;
 159        for (i = 0; i < sizeof(struct tea5764_regs) / sizeof(u16); i++)
 160                p[i] = __be16_to_cpu(p[i]);
 161
 162        return 0;
 163}
 164
 165int tea5764_i2c_write(struct tea5764_device *radio)
 166{
 167        struct tea5764_write_regs wr;
 168        struct tea5764_regs *r = &radio->regs;
 169        struct i2c_msg msgs[1] = {
 170                { radio->i2c_client->addr, 0, sizeof(wr), (void *) &wr },
 171        };
 172        wr.intreg  = r->intreg & 0xff;
 173        wr.frqset  = __cpu_to_be16(r->frqset);
 174        wr.tnctrl  = __cpu_to_be16(r->tnctrl);
 175        wr.testreg = __cpu_to_be16(r->testreg);
 176        wr.rdsctrl = __cpu_to_be16(r->rdsctrl);
 177        wr.rdsbbl  = __cpu_to_be16(r->rdsbbl);
 178        if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
 179                return -EIO;
 180        return 0;
 181}
 182
 183/* V4L2 code related */
 184static struct v4l2_queryctrl radio_qctrl[] = {
 185        {
 186                .id            = V4L2_CID_AUDIO_MUTE,
 187                .name          = "Mute",
 188                .minimum       = 0,
 189                .maximum       = 1,
 190                .default_value = 1,
 191                .type          = V4L2_CTRL_TYPE_BOOLEAN,
 192        }
 193};
 194
 195static void tea5764_power_up(struct tea5764_device *radio)
 196{
 197        struct tea5764_regs *r = &radio->regs;
 198
 199        if (!(r->tnctrl & TEA5764_TNCTRL_PUPD0)) {
 200                r->tnctrl &= ~(TEA5764_TNCTRL_AFM | TEA5764_TNCTRL_MU |
 201                               TEA5764_TNCTRL_HLSI);
 202                if (!use_xtal)
 203                        r->testreg |= TEA5764_TESTREG_TRIGFR;
 204                else
 205                        r->testreg &= ~TEA5764_TESTREG_TRIGFR;
 206
 207                r->tnctrl |= TEA5764_TNCTRL_PUPD0;
 208                tea5764_i2c_write(radio);
 209        }
 210}
 211
 212static void tea5764_power_down(struct tea5764_device *radio)
 213{
 214        struct tea5764_regs *r = &radio->regs;
 215
 216        if (r->tnctrl & TEA5764_TNCTRL_PUPD0) {
 217                r->tnctrl &= ~TEA5764_TNCTRL_PUPD0;
 218                tea5764_i2c_write(radio);
 219        }
 220}
 221
 222static void tea5764_set_freq(struct tea5764_device *radio, int freq)
 223{
 224        struct tea5764_regs *r = &radio->regs;
 225
 226        /* formula: (freq [+ or -] 225000) / 8192 */
 227        if (r->tnctrl & TEA5764_TNCTRL_HLSI)
 228                r->frqset = (freq + 225000) / 8192;
 229        else
 230                r->frqset = (freq - 225000) / 8192;
 231}
 232
 233static int tea5764_get_freq(struct tea5764_device *radio)
 234{
 235        struct tea5764_regs *r = &radio->regs;
 236
 237        if (r->tnctrl & TEA5764_TNCTRL_HLSI)
 238                return (r->frqchk * 8192) - 225000;
 239        else
 240                return (r->frqchk * 8192) + 225000;
 241}
 242
 243/* tune an frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
 244static void tea5764_tune(struct tea5764_device *radio, int freq)
 245{
 246        tea5764_set_freq(radio, freq);
 247        if (tea5764_i2c_write(radio))
 248                PWARN("Could not set frequency!");
 249}
 250
 251static void tea5764_set_audout_mode(struct tea5764_device *radio, int audmode)
 252{
 253        struct tea5764_regs *r = &radio->regs;
 254        int tnctrl = r->tnctrl;
 255
 256        if (audmode == V4L2_TUNER_MODE_MONO)
 257                r->tnctrl |= TEA5764_TNCTRL_MST;
 258        else
 259                r->tnctrl &= ~TEA5764_TNCTRL_MST;
 260        if (tnctrl != r->tnctrl)
 261                tea5764_i2c_write(radio);
 262}
 263
 264static int tea5764_get_audout_mode(struct tea5764_device *radio)
 265{
 266        struct tea5764_regs *r = &radio->regs;
 267
 268        if (r->tnctrl & TEA5764_TNCTRL_MST)
 269                return V4L2_TUNER_MODE_MONO;
 270        else
 271                return V4L2_TUNER_MODE_STEREO;
 272}
 273
 274static void tea5764_mute(struct tea5764_device *radio, int on)
 275{
 276        struct tea5764_regs *r = &radio->regs;
 277        int tnctrl = r->tnctrl;
 278
 279        if (on)
 280                r->tnctrl |= TEA5764_TNCTRL_MU;
 281        else
 282                r->tnctrl &= ~TEA5764_TNCTRL_MU;
 283        if (tnctrl != r->tnctrl)
 284                tea5764_i2c_write(radio);
 285}
 286
 287static int tea5764_is_muted(struct tea5764_device *radio)
 288{
 289        return radio->regs.tnctrl & TEA5764_TNCTRL_MU;
 290}
 291
 292/* V4L2 vidioc */
 293static int vidioc_querycap(struct file *file, void  *priv,
 294                                        struct v4l2_capability *v)
 295{
 296        struct tea5764_device *radio = video_drvdata(file);
 297        struct video_device *dev = radio->videodev;
 298
 299        strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
 300        strlcpy(v->card, dev->name, sizeof(v->card));
 301        snprintf(v->bus_info, sizeof(v->bus_info),
 302                 "I2C:%s", dev_name(&dev->dev));
 303        v->version = RADIO_VERSION;
 304        v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 305        return 0;
 306}
 307
 308static int vidioc_g_tuner(struct file *file, void *priv,
 309                                struct v4l2_tuner *v)
 310{
 311        struct tea5764_device *radio = video_drvdata(file);
 312        struct tea5764_regs *r = &radio->regs;
 313
 314        if (v->index > 0)
 315                return -EINVAL;
 316
 317        memset(v, 0, sizeof(*v));
 318        strcpy(v->name, "FM");
 319        v->type = V4L2_TUNER_RADIO;
 320        tea5764_i2c_read(radio);
 321        v->rangelow   = FREQ_MIN * FREQ_MUL;
 322        v->rangehigh  = FREQ_MAX * FREQ_MUL;
 323        v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
 324        if (r->tunchk & TEA5764_TUNCHK_STEREO)
 325                v->rxsubchans = V4L2_TUNER_SUB_STEREO;
 326        else
 327                v->rxsubchans = V4L2_TUNER_SUB_MONO;
 328        v->audmode = tea5764_get_audout_mode(radio);
 329        v->signal = TEA5764_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf;
 330        v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk);
 331
 332        return 0;
 333}
 334
 335static int vidioc_s_tuner(struct file *file, void *priv,
 336                                struct v4l2_tuner *v)
 337{
 338        struct tea5764_device *radio = video_drvdata(file);
 339
 340        if (v->index > 0)
 341                return -EINVAL;
 342
 343        tea5764_set_audout_mode(radio, v->audmode);
 344        return 0;
 345}
 346
 347static int vidioc_s_frequency(struct file *file, void *priv,
 348                                struct v4l2_frequency *f)
 349{
 350        struct tea5764_device *radio = video_drvdata(file);
 351
 352        if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
 353                return -EINVAL;
 354        if (f->frequency == 0) {
 355                /* We special case this as a power down control. */
 356                tea5764_power_down(radio);
 357        }
 358        if (f->frequency < (FREQ_MIN * FREQ_MUL))
 359                return -EINVAL;
 360        if (f->frequency > (FREQ_MAX * FREQ_MUL))
 361                return -EINVAL;
 362        tea5764_power_up(radio);
 363        tea5764_tune(radio, (f->frequency * 125) / 2);
 364        return 0;
 365}
 366
 367static int vidioc_g_frequency(struct file *file, void *priv,
 368                                struct v4l2_frequency *f)
 369{
 370        struct tea5764_device *radio = video_drvdata(file);
 371        struct tea5764_regs *r = &radio->regs;
 372
 373        if (f->tuner != 0)
 374                return -EINVAL;
 375        tea5764_i2c_read(radio);
 376        memset(f, 0, sizeof(*f));
 377        f->type = V4L2_TUNER_RADIO;
 378        if (r->tnctrl & TEA5764_TNCTRL_PUPD0)
 379                f->frequency = (tea5764_get_freq(radio) * 2) / 125;
 380        else
 381                f->frequency = 0;
 382
 383        return 0;
 384}
 385
 386static int vidioc_queryctrl(struct file *file, void *priv,
 387                            struct v4l2_queryctrl *qc)
 388{
 389        int i;
 390
 391        for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
 392                if (qc->id && qc->id == radio_qctrl[i].id) {
 393                        memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
 394                        return 0;
 395                }
 396        }
 397        return -EINVAL;
 398}
 399
 400static int vidioc_g_ctrl(struct file *file, void *priv,
 401                            struct v4l2_control *ctrl)
 402{
 403        struct tea5764_device *radio = video_drvdata(file);
 404
 405        switch (ctrl->id) {
 406        case V4L2_CID_AUDIO_MUTE:
 407                tea5764_i2c_read(radio);
 408                ctrl->value = tea5764_is_muted(radio) ? 1 : 0;
 409                return 0;
 410        }
 411        return -EINVAL;
 412}
 413
 414static int vidioc_s_ctrl(struct file *file, void *priv,
 415                            struct v4l2_control *ctrl)
 416{
 417        struct tea5764_device *radio = video_drvdata(file);
 418
 419        switch (ctrl->id) {
 420        case V4L2_CID_AUDIO_MUTE:
 421                tea5764_mute(radio, ctrl->value);
 422                return 0;
 423        }
 424        return -EINVAL;
 425}
 426
 427static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 428{
 429        *i = 0;
 430        return 0;
 431}
 432
 433static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 434{
 435        if (i != 0)
 436                return -EINVAL;
 437        return 0;
 438}
 439
 440static int vidioc_g_audio(struct file *file, void *priv,
 441                           struct v4l2_audio *a)
 442{
 443        if (a->index > 1)
 444                return -EINVAL;
 445
 446        strcpy(a->name, "Radio");
 447        a->capability = V4L2_AUDCAP_STEREO;
 448        return 0;
 449}
 450
 451static int vidioc_s_audio(struct file *file, void *priv,
 452                           struct v4l2_audio *a)
 453{
 454        if (a->index != 0)
 455                return -EINVAL;
 456
 457        return 0;
 458}
 459
 460/* File system interface */
 461static const struct v4l2_file_operations tea5764_fops = {
 462        .owner          = THIS_MODULE,
 463        .unlocked_ioctl = video_ioctl2,
 464};
 465
 466static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
 467        .vidioc_querycap    = vidioc_querycap,
 468        .vidioc_g_tuner     = vidioc_g_tuner,
 469        .vidioc_s_tuner     = vidioc_s_tuner,
 470        .vidioc_g_audio     = vidioc_g_audio,
 471        .vidioc_s_audio     = vidioc_s_audio,
 472        .vidioc_g_input     = vidioc_g_input,
 473        .vidioc_s_input     = vidioc_s_input,
 474        .vidioc_g_frequency = vidioc_g_frequency,
 475        .vidioc_s_frequency = vidioc_s_frequency,
 476        .vidioc_queryctrl   = vidioc_queryctrl,
 477        .vidioc_g_ctrl      = vidioc_g_ctrl,
 478        .vidioc_s_ctrl      = vidioc_s_ctrl,
 479};
 480
 481/* V4L2 interface */
 482static struct video_device tea5764_radio_template = {
 483        .name           = "TEA5764 FM-Radio",
 484        .fops           = &tea5764_fops,
 485        .ioctl_ops      = &tea5764_ioctl_ops,
 486        .release        = video_device_release,
 487};
 488
 489/* I2C probe: check if the device exists and register with v4l if it is */
 490static int __devinit tea5764_i2c_probe(struct i2c_client *client,
 491                                        const struct i2c_device_id *id)
 492{
 493        struct tea5764_device *radio;
 494        struct tea5764_regs *r;
 495        int ret;
 496
 497        PDEBUG("probe");
 498        radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL);
 499        if (!radio)
 500                return -ENOMEM;
 501
 502        mutex_init(&radio->mutex);
 503        radio->i2c_client = client;
 504        ret = tea5764_i2c_read(radio);
 505        if (ret)
 506                goto errfr;
 507        r = &radio->regs;
 508        PDEBUG("chipid = %04X, manid = %04X", r->chipid, r->manid);
 509        if (r->chipid != TEA5764_CHIPID ||
 510                (r->manid & 0x0fff) != TEA5764_MANID) {
 511                PWARN("This chip is not a TEA5764!");
 512                ret = -EINVAL;
 513                goto errfr;
 514        }
 515
 516        radio->videodev = video_device_alloc();
 517        if (!(radio->videodev)) {
 518                ret = -ENOMEM;
 519                goto errfr;
 520        }
 521        memcpy(radio->videodev, &tea5764_radio_template,
 522                sizeof(tea5764_radio_template));
 523
 524        i2c_set_clientdata(client, radio);
 525        video_set_drvdata(radio->videodev, radio);
 526        radio->videodev->lock = &radio->mutex;
 527
 528        /* initialize and power off the chip */
 529        tea5764_i2c_read(radio);
 530        tea5764_set_audout_mode(radio, V4L2_TUNER_MODE_STEREO);
 531        tea5764_mute(radio, 1);
 532        tea5764_power_down(radio);
 533
 534        ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
 535        if (ret < 0) {
 536                PWARN("Could not register video device!");
 537                goto errrel;
 538        }
 539
 540        PINFO("registered.");
 541        return 0;
 542errrel:
 543        video_device_release(radio->videodev);
 544errfr:
 545        kfree(radio);
 546        return ret;
 547}
 548
 549static int __devexit tea5764_i2c_remove(struct i2c_client *client)
 550{
 551        struct tea5764_device *radio = i2c_get_clientdata(client);
 552
 553        PDEBUG("remove");
 554        if (radio) {
 555                tea5764_power_down(radio);
 556                video_unregister_device(radio->videodev);
 557                kfree(radio);
 558        }
 559        return 0;
 560}
 561
 562/* I2C subsystem interface */
 563static const struct i2c_device_id tea5764_id[] = {
 564        { "radio-tea5764", 0 },
 565        { }                                     /* Terminating entry */
 566};
 567MODULE_DEVICE_TABLE(i2c, tea5764_id);
 568
 569static struct i2c_driver tea5764_i2c_driver = {
 570        .driver = {
 571                .name = "radio-tea5764",
 572                .owner = THIS_MODULE,
 573        },
 574        .probe = tea5764_i2c_probe,
 575        .remove = __devexit_p(tea5764_i2c_remove),
 576        .id_table = tea5764_id,
 577};
 578
 579/* init the driver */
 580static int __init tea5764_init(void)
 581{
 582        int ret = i2c_add_driver(&tea5764_i2c_driver);
 583
 584        printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": "
 585                DRIVER_DESC "\n");
 586        return ret;
 587}
 588
 589/* cleanup the driver */
 590static void __exit tea5764_exit(void)
 591{
 592        i2c_del_driver(&tea5764_i2c_driver);
 593}
 594
 595MODULE_AUTHOR(DRIVER_AUTHOR);
 596MODULE_DESCRIPTION(DRIVER_DESC);
 597MODULE_LICENSE("GPL");
 598
 599module_param(use_xtal, int, 1);
 600MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board");
 601module_param(radio_nr, int, 0);
 602MODULE_PARM_DESC(radio_nr, "video4linux device number to use");
 603
 604module_init(tea5764_init);
 605module_exit(tea5764_exit);
 606