linux/drivers/media/radio/si470x/radio-si470x-i2c.c
<<
>>
Prefs
   1/*
   2 * drivers/media/radio/si470x/radio-si470x-i2c.c
   3 *
   4 * I2C driver for radios with Silicon Labs Si470x FM Radio Receivers
   5 *
   6 * Copyright (c) 2009 Samsung Electronics Co.Ltd
   7 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 */
  19
  20
  21/* driver definitions */
  22#define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
  23#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
  24#define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
  25#define DRIVER_VERSION "1.0.2"
  26
  27/* kernel includes */
  28#include <linux/i2c.h>
  29#include <linux/slab.h>
  30#include <linux/delay.h>
  31#include <linux/interrupt.h>
  32
  33#include "radio-si470x.h"
  34
  35
  36/* I2C Device ID List */
  37static const struct i2c_device_id si470x_i2c_id[] = {
  38        /* Generic Entry */
  39        { "si470x", 0 },
  40        /* Terminating entry */
  41        { }
  42};
  43MODULE_DEVICE_TABLE(i2c, si470x_i2c_id);
  44
  45
  46
  47/**************************************************************************
  48 * Module Parameters
  49 **************************************************************************/
  50
  51/* Radio Nr */
  52static int radio_nr = -1;
  53module_param(radio_nr, int, 0444);
  54MODULE_PARM_DESC(radio_nr, "Radio Nr");
  55
  56/* RDS buffer blocks */
  57static unsigned int rds_buf = 100;
  58module_param(rds_buf, uint, 0444);
  59MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
  60
  61/* RDS maximum block errors */
  62static unsigned short max_rds_errors = 1;
  63/* 0 means   0  errors requiring correction */
  64/* 1 means 1-2  errors requiring correction (used by original USBRadio.exe) */
  65/* 2 means 3-5  errors requiring correction */
  66/* 3 means   6+ errors or errors in checkword, correction not possible */
  67module_param(max_rds_errors, ushort, 0644);
  68MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
  69
  70
  71
  72/**************************************************************************
  73 * I2C Definitions
  74 **************************************************************************/
  75
  76/* Write starts with the upper byte of register 0x02 */
  77#define WRITE_REG_NUM           8
  78#define WRITE_INDEX(i)          (i + 0x02)
  79
  80/* Read starts with the upper byte of register 0x0a */
  81#define READ_REG_NUM            RADIO_REGISTER_NUM
  82#define READ_INDEX(i)           ((i + RADIO_REGISTER_NUM - 0x0a) % READ_REG_NUM)
  83
  84
  85
  86/**************************************************************************
  87 * General Driver Functions - REGISTERs
  88 **************************************************************************/
  89
  90/*
  91 * si470x_get_register - read register
  92 */
  93int si470x_get_register(struct si470x_device *radio, int regnr)
  94{
  95        u16 buf[READ_REG_NUM];
  96        struct i2c_msg msgs[1] = {
  97                {
  98                        .addr = radio->client->addr,
  99                        .flags = I2C_M_RD,
 100                        .len = sizeof(u16) * READ_REG_NUM,
 101                        .buf = (void *)buf
 102                },
 103        };
 104
 105        if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
 106                return -EIO;
 107
 108        radio->registers[regnr] = __be16_to_cpu(buf[READ_INDEX(regnr)]);
 109
 110        return 0;
 111}
 112
 113
 114/*
 115 * si470x_set_register - write register
 116 */
 117int si470x_set_register(struct si470x_device *radio, int regnr)
 118{
 119        int i;
 120        u16 buf[WRITE_REG_NUM];
 121        struct i2c_msg msgs[1] = {
 122                {
 123                        .addr = radio->client->addr,
 124                        .len = sizeof(u16) * WRITE_REG_NUM,
 125                        .buf = (void *)buf
 126                },
 127        };
 128
 129        for (i = 0; i < WRITE_REG_NUM; i++)
 130                buf[i] = __cpu_to_be16(radio->registers[WRITE_INDEX(i)]);
 131
 132        if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
 133                return -EIO;
 134
 135        return 0;
 136}
 137
 138
 139
 140/**************************************************************************
 141 * General Driver Functions - ENTIRE REGISTERS
 142 **************************************************************************/
 143
 144/*
 145 * si470x_get_all_registers - read entire registers
 146 */
 147static int si470x_get_all_registers(struct si470x_device *radio)
 148{
 149        int i;
 150        u16 buf[READ_REG_NUM];
 151        struct i2c_msg msgs[1] = {
 152                {
 153                        .addr = radio->client->addr,
 154                        .flags = I2C_M_RD,
 155                        .len = sizeof(u16) * READ_REG_NUM,
 156                        .buf = (void *)buf
 157                },
 158        };
 159
 160        if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
 161                return -EIO;
 162
 163        for (i = 0; i < READ_REG_NUM; i++)
 164                radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]);
 165
 166        return 0;
 167}
 168
 169
 170
 171/**************************************************************************
 172 * File Operations Interface
 173 **************************************************************************/
 174
 175/*
 176 * si470x_fops_open - file open
 177 */
 178int si470x_fops_open(struct file *file)
 179{
 180        struct si470x_device *radio = video_drvdata(file);
 181        int retval = v4l2_fh_open(file);
 182
 183        if (retval)
 184                return retval;
 185
 186        if (v4l2_fh_is_singular_file(file)) {
 187                /* start radio */
 188                retval = si470x_start(radio);
 189                if (retval < 0)
 190                        goto done;
 191
 192                /* enable RDS / STC interrupt */
 193                radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
 194                radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN;
 195                radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
 196                radio->registers[SYSCONFIG1] |= 0x1 << 2;
 197                retval = si470x_set_register(radio, SYSCONFIG1);
 198        }
 199
 200done:
 201        if (retval)
 202                v4l2_fh_release(file);
 203        return retval;
 204}
 205
 206
 207/*
 208 * si470x_fops_release - file release
 209 */
 210int si470x_fops_release(struct file *file)
 211{
 212        struct si470x_device *radio = video_drvdata(file);
 213
 214        if (v4l2_fh_is_singular_file(file))
 215                /* stop radio */
 216                si470x_stop(radio);
 217
 218        return v4l2_fh_release(file);
 219}
 220
 221
 222
 223/**************************************************************************
 224 * Video4Linux Interface
 225 **************************************************************************/
 226
 227/*
 228 * si470x_vidioc_querycap - query device capabilities
 229 */
 230int si470x_vidioc_querycap(struct file *file, void *priv,
 231                struct v4l2_capability *capability)
 232{
 233        strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
 234        strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
 235        capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE |
 236                V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
 237        capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;
 238
 239        return 0;
 240}
 241
 242
 243
 244/**************************************************************************
 245 * I2C Interface
 246 **************************************************************************/
 247
 248/*
 249 * si470x_i2c_interrupt - interrupt handler
 250 */
 251static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
 252{
 253        struct si470x_device *radio = dev_id;
 254        unsigned char regnr;
 255        unsigned char blocknum;
 256        unsigned short bler; /* rds block errors */
 257        unsigned short rds;
 258        unsigned char tmpbuf[3];
 259        int retval = 0;
 260
 261        /* check Seek/Tune Complete */
 262        retval = si470x_get_register(radio, STATUSRSSI);
 263        if (retval < 0)
 264                goto end;
 265
 266        if (radio->registers[STATUSRSSI] & STATUSRSSI_STC)
 267                complete(&radio->completion);
 268
 269        /* safety checks */
 270        if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
 271                goto end;
 272
 273        /* Update RDS registers */
 274        for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) {
 275                retval = si470x_get_register(radio, STATUSRSSI + regnr);
 276                if (retval < 0)
 277                        goto end;
 278        }
 279
 280        /* get rds blocks */
 281        if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0)
 282                /* No RDS group ready, better luck next time */
 283                goto end;
 284
 285        for (blocknum = 0; blocknum < 4; blocknum++) {
 286                switch (blocknum) {
 287                default:
 288                        bler = (radio->registers[STATUSRSSI] &
 289                                        STATUSRSSI_BLERA) >> 9;
 290                        rds = radio->registers[RDSA];
 291                        break;
 292                case 1:
 293                        bler = (radio->registers[READCHAN] &
 294                                        READCHAN_BLERB) >> 14;
 295                        rds = radio->registers[RDSB];
 296                        break;
 297                case 2:
 298                        bler = (radio->registers[READCHAN] &
 299                                        READCHAN_BLERC) >> 12;
 300                        rds = radio->registers[RDSC];
 301                        break;
 302                case 3:
 303                        bler = (radio->registers[READCHAN] &
 304                                        READCHAN_BLERD) >> 10;
 305                        rds = radio->registers[RDSD];
 306                        break;
 307                }
 308
 309                /* Fill the V4L2 RDS buffer */
 310                put_unaligned_le16(rds, &tmpbuf);
 311                tmpbuf[2] = blocknum;           /* offset name */
 312                tmpbuf[2] |= blocknum << 3;     /* received offset */
 313                if (bler > max_rds_errors)
 314                        tmpbuf[2] |= 0x80;      /* uncorrectable errors */
 315                else if (bler > 0)
 316                        tmpbuf[2] |= 0x40;      /* corrected error(s) */
 317
 318                /* copy RDS block to internal buffer */
 319                memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
 320                radio->wr_index += 3;
 321
 322                /* wrap write pointer */
 323                if (radio->wr_index >= radio->buf_size)
 324                        radio->wr_index = 0;
 325
 326                /* check for overflow */
 327                if (radio->wr_index == radio->rd_index) {
 328                        /* increment and wrap read pointer */
 329                        radio->rd_index += 3;
 330                        if (radio->rd_index >= radio->buf_size)
 331                                radio->rd_index = 0;
 332                }
 333        }
 334
 335        if (radio->wr_index != radio->rd_index)
 336                wake_up_interruptible(&radio->read_queue);
 337
 338end:
 339        return IRQ_HANDLED;
 340}
 341
 342
 343/*
 344 * si470x_i2c_probe - probe for the device
 345 */
 346static int si470x_i2c_probe(struct i2c_client *client,
 347                            const struct i2c_device_id *id)
 348{
 349        struct si470x_device *radio;
 350        int retval = 0;
 351        unsigned char version_warning = 0;
 352
 353        /* private data allocation and initialization */
 354        radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
 355        if (!radio) {
 356                retval = -ENOMEM;
 357                goto err_initial;
 358        }
 359
 360        radio->client = client;
 361        radio->band = 1; /* Default to 76 - 108 MHz */
 362        mutex_init(&radio->lock);
 363        init_completion(&radio->completion);
 364
 365        /* video device initialization */
 366        radio->videodev = si470x_viddev_template;
 367        video_set_drvdata(&radio->videodev, radio);
 368
 369        /* power up : need 110ms */
 370        radio->registers[POWERCFG] = POWERCFG_ENABLE;
 371        if (si470x_set_register(radio, POWERCFG) < 0) {
 372                retval = -EIO;
 373                goto err_radio;
 374        }
 375        msleep(110);
 376
 377        /* get device and chip versions */
 378        if (si470x_get_all_registers(radio) < 0) {
 379                retval = -EIO;
 380                goto err_radio;
 381        }
 382        dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
 383                        radio->registers[DEVICEID], radio->registers[SI_CHIPID]);
 384        if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
 385                dev_warn(&client->dev,
 386                        "This driver is known to work with firmware version %hu,\n",
 387                        RADIO_FW_VERSION);
 388                dev_warn(&client->dev,
 389                        "but the device has firmware version %hu.\n",
 390                        radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE);
 391                version_warning = 1;
 392        }
 393
 394        /* give out version warning */
 395        if (version_warning == 1) {
 396                dev_warn(&client->dev,
 397                        "If you have some trouble using this driver,\n");
 398                dev_warn(&client->dev,
 399                        "please report to V4L ML at linux-media@vger.kernel.org\n");
 400        }
 401
 402        /* set initial frequency */
 403        si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
 404
 405        /* rds buffer allocation */
 406        radio->buf_size = rds_buf * 3;
 407        radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
 408        if (!radio->buffer) {
 409                retval = -EIO;
 410                goto err_radio;
 411        }
 412
 413        /* rds buffer configuration */
 414        radio->wr_index = 0;
 415        radio->rd_index = 0;
 416        init_waitqueue_head(&radio->read_queue);
 417
 418        retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt,
 419                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT, DRIVER_NAME,
 420                        radio);
 421        if (retval) {
 422                dev_err(&client->dev, "Failed to register interrupt\n");
 423                goto err_rds;
 424        }
 425
 426        /* register video device */
 427        retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
 428                        radio_nr);
 429        if (retval) {
 430                dev_warn(&client->dev, "Could not register video device\n");
 431                goto err_all;
 432        }
 433        i2c_set_clientdata(client, radio);
 434
 435        return 0;
 436err_all:
 437        free_irq(client->irq, radio);
 438err_rds:
 439        kfree(radio->buffer);
 440err_radio:
 441        kfree(radio);
 442err_initial:
 443        return retval;
 444}
 445
 446
 447/*
 448 * si470x_i2c_remove - remove the device
 449 */
 450static int si470x_i2c_remove(struct i2c_client *client)
 451{
 452        struct si470x_device *radio = i2c_get_clientdata(client);
 453
 454        free_irq(client->irq, radio);
 455        video_unregister_device(&radio->videodev);
 456        kfree(radio);
 457
 458        return 0;
 459}
 460
 461
 462#ifdef CONFIG_PM_SLEEP
 463/*
 464 * si470x_i2c_suspend - suspend the device
 465 */
 466static int si470x_i2c_suspend(struct device *dev)
 467{
 468        struct i2c_client *client = to_i2c_client(dev);
 469        struct si470x_device *radio = i2c_get_clientdata(client);
 470
 471        /* power down */
 472        radio->registers[POWERCFG] |= POWERCFG_DISABLE;
 473        if (si470x_set_register(radio, POWERCFG) < 0)
 474                return -EIO;
 475
 476        return 0;
 477}
 478
 479
 480/*
 481 * si470x_i2c_resume - resume the device
 482 */
 483static int si470x_i2c_resume(struct device *dev)
 484{
 485        struct i2c_client *client = to_i2c_client(dev);
 486        struct si470x_device *radio = i2c_get_clientdata(client);
 487
 488        /* power up : need 110ms */
 489        radio->registers[POWERCFG] |= POWERCFG_ENABLE;
 490        if (si470x_set_register(radio, POWERCFG) < 0)
 491                return -EIO;
 492        msleep(110);
 493
 494        return 0;
 495}
 496
 497static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume);
 498#endif
 499
 500
 501/*
 502 * si470x_i2c_driver - i2c driver interface
 503 */
 504static struct i2c_driver si470x_i2c_driver = {
 505        .driver = {
 506                .name           = "si470x",
 507#ifdef CONFIG_PM_SLEEP
 508                .pm             = &si470x_i2c_pm,
 509#endif
 510        },
 511        .probe                  = si470x_i2c_probe,
 512        .remove                 = si470x_i2c_remove,
 513        .id_table               = si470x_i2c_id,
 514};
 515
 516module_i2c_driver(si470x_i2c_driver);
 517
 518MODULE_LICENSE("GPL");
 519MODULE_AUTHOR(DRIVER_AUTHOR);
 520MODULE_DESCRIPTION(DRIVER_DESC);
 521MODULE_VERSION(DRIVER_VERSION);
 522