linux/drivers/media/rc/ir-rx51.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2008 Nokia Corporation
   3 *
   4 *  Based on lirc_serial.c
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 *
  20 */
  21
  22#include <linux/module.h>
  23#include <linux/interrupt.h>
  24#include <linux/uaccess.h>
  25#include <linux/platform_device.h>
  26#include <linux/sched.h>
  27#include <linux/wait.h>
  28
  29#include <plat/dmtimer.h>
  30#include <plat/clock.h>
  31
  32#include <media/lirc.h>
  33#include <media/lirc_dev.h>
  34#include <media/ir-rx51.h>
  35
  36#define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE |       \
  37                                   LIRC_CAN_SET_SEND_CARRIER |          \
  38                                   LIRC_CAN_SEND_PULSE)
  39
  40#define DRIVER_NAME "lirc_rx51"
  41
  42#define WBUF_LEN 256
  43
  44#define TIMER_MAX_VALUE 0xffffffff
  45
  46struct lirc_rx51 {
  47        struct omap_dm_timer *pwm_timer;
  48        struct omap_dm_timer *pulse_timer;
  49        struct device        *dev;
  50        struct lirc_rx51_platform_data *pdata;
  51        wait_queue_head_t     wqueue;
  52
  53        unsigned long   fclk_khz;
  54        unsigned int    freq;           /* carrier frequency */
  55        unsigned int    duty_cycle;     /* carrier duty cycle */
  56        unsigned int    irq_num;
  57        unsigned int    match;
  58        int             wbuf[WBUF_LEN];
  59        int             wbuf_index;
  60        unsigned long   device_is_open;
  61        int             pwm_timer_num;
  62};
  63
  64static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
  65{
  66        omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
  67                              OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
  68}
  69
  70static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
  71{
  72        omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
  73                              OMAP_TIMER_TRIGGER_NONE);
  74}
  75
  76static int init_timing_params(struct lirc_rx51 *lirc_rx51)
  77{
  78        u32 load, match;
  79
  80        load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq);
  81        match = -(lirc_rx51->duty_cycle * -load / 100);
  82        omap_dm_timer_set_load(lirc_rx51->pwm_timer, 1, load);
  83        omap_dm_timer_set_match(lirc_rx51->pwm_timer, 1, match);
  84        omap_dm_timer_write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
  85        omap_dm_timer_start(lirc_rx51->pwm_timer);
  86        omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
  87        omap_dm_timer_start(lirc_rx51->pulse_timer);
  88
  89        lirc_rx51->match = 0;
  90
  91        return 0;
  92}
  93
  94#define tics_after(a, b) ((long)(b) - (long)(a) < 0)
  95
  96static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec)
  97{
  98        int counter;
  99
 100        BUG_ON(usec < 0);
 101
 102        if (lirc_rx51->match == 0)
 103                counter = omap_dm_timer_read_counter(lirc_rx51->pulse_timer);
 104        else
 105                counter = lirc_rx51->match;
 106
 107        counter += (u32)(lirc_rx51->fclk_khz * usec / (1000));
 108        omap_dm_timer_set_match(lirc_rx51->pulse_timer, 1, counter);
 109        omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer,
 110                                     OMAP_TIMER_INT_MATCH);
 111        if (tics_after(omap_dm_timer_read_counter(lirc_rx51->pulse_timer),
 112                       counter)) {
 113                return 1;
 114        }
 115        return 0;
 116}
 117
 118static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
 119{
 120        unsigned int retval;
 121        struct lirc_rx51 *lirc_rx51 = ptr;
 122
 123        retval = omap_dm_timer_read_status(lirc_rx51->pulse_timer);
 124        if (!retval)
 125                return IRQ_NONE;
 126
 127        if (retval & ~OMAP_TIMER_INT_MATCH)
 128                dev_err_ratelimited(lirc_rx51->dev,
 129                                ": Unexpected interrupt source: %x\n", retval);
 130
 131        omap_dm_timer_write_status(lirc_rx51->pulse_timer,
 132                                OMAP_TIMER_INT_MATCH    |
 133                                OMAP_TIMER_INT_OVERFLOW |
 134                                OMAP_TIMER_INT_CAPTURE);
 135        if (lirc_rx51->wbuf_index < 0) {
 136                dev_err_ratelimited(lirc_rx51->dev,
 137                                ": BUG wbuf_index has value of %i\n",
 138                                lirc_rx51->wbuf_index);
 139                goto end;
 140        }
 141
 142        /*
 143         * If we happen to hit an odd latency spike, loop through the
 144         * pulses until we catch up.
 145         */
 146        do {
 147                if (lirc_rx51->wbuf_index >= WBUF_LEN)
 148                        goto end;
 149                if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1)
 150                        goto end;
 151
 152                if (lirc_rx51->wbuf_index % 2)
 153                        lirc_rx51_off(lirc_rx51);
 154                else
 155                        lirc_rx51_on(lirc_rx51);
 156
 157                retval = pulse_timer_set_timeout(lirc_rx51,
 158                                        lirc_rx51->wbuf[lirc_rx51->wbuf_index]);
 159                lirc_rx51->wbuf_index++;
 160
 161        } while (retval);
 162
 163        return IRQ_HANDLED;
 164end:
 165        /* Stop TX here */
 166        lirc_rx51_off(lirc_rx51);
 167        lirc_rx51->wbuf_index = -1;
 168        omap_dm_timer_stop(lirc_rx51->pwm_timer);
 169        omap_dm_timer_stop(lirc_rx51->pulse_timer);
 170        omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
 171        wake_up_interruptible(&lirc_rx51->wqueue);
 172
 173        return IRQ_HANDLED;
 174}
 175
 176static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 177{
 178        struct clk *clk_fclk;
 179        int retval, pwm_timer = lirc_rx51->pwm_timer_num;
 180
 181        lirc_rx51->pwm_timer = omap_dm_timer_request_specific(pwm_timer);
 182        if (lirc_rx51->pwm_timer == NULL) {
 183                dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n",
 184                        pwm_timer);
 185                return -EBUSY;
 186        }
 187
 188        lirc_rx51->pulse_timer = omap_dm_timer_request();
 189        if (lirc_rx51->pulse_timer == NULL) {
 190                dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n");
 191                retval = -EBUSY;
 192                goto err1;
 193        }
 194
 195        omap_dm_timer_set_source(lirc_rx51->pwm_timer, OMAP_TIMER_SRC_SYS_CLK);
 196        omap_dm_timer_set_source(lirc_rx51->pulse_timer,
 197                                OMAP_TIMER_SRC_SYS_CLK);
 198
 199        omap_dm_timer_enable(lirc_rx51->pwm_timer);
 200        omap_dm_timer_enable(lirc_rx51->pulse_timer);
 201
 202        lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer);
 203        retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
 204                             IRQF_DISABLED | IRQF_SHARED,
 205                             "lirc_pulse_timer", lirc_rx51);
 206        if (retval) {
 207                dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n");
 208                goto err2;
 209        }
 210
 211        clk_fclk = omap_dm_timer_get_fclk(lirc_rx51->pwm_timer);
 212        lirc_rx51->fclk_khz = clk_fclk->rate / 1000;
 213
 214        return 0;
 215
 216err2:
 217        omap_dm_timer_free(lirc_rx51->pulse_timer);
 218err1:
 219        omap_dm_timer_free(lirc_rx51->pwm_timer);
 220
 221        return retval;
 222}
 223
 224static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
 225{
 226        omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
 227        free_irq(lirc_rx51->irq_num, lirc_rx51);
 228        lirc_rx51_off(lirc_rx51);
 229        omap_dm_timer_disable(lirc_rx51->pwm_timer);
 230        omap_dm_timer_disable(lirc_rx51->pulse_timer);
 231        omap_dm_timer_free(lirc_rx51->pwm_timer);
 232        omap_dm_timer_free(lirc_rx51->pulse_timer);
 233        lirc_rx51->wbuf_index = -1;
 234
 235        return 0;
 236}
 237
 238static ssize_t lirc_rx51_write(struct file *file, const char *buf,
 239                          size_t n, loff_t *ppos)
 240{
 241        int count, i;
 242        struct lirc_rx51 *lirc_rx51 = file->private_data;
 243
 244        if (n % sizeof(int))
 245                return -EINVAL;
 246
 247        count = n / sizeof(int);
 248        if ((count > WBUF_LEN) || (count % 2 == 0))
 249                return -EINVAL;
 250
 251        /* Wait any pending transfers to finish */
 252        wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0);
 253
 254        if (copy_from_user(lirc_rx51->wbuf, buf, n))
 255                return -EFAULT;
 256
 257        /* Sanity check the input pulses */
 258        for (i = 0; i < count; i++)
 259                if (lirc_rx51->wbuf[i] < 0)
 260                        return -EINVAL;
 261
 262        init_timing_params(lirc_rx51);
 263        if (count < WBUF_LEN)
 264                lirc_rx51->wbuf[count] = -1; /* Insert termination mark */
 265
 266        /*
 267         * Adjust latency requirements so the device doesn't go in too
 268         * deep sleep states
 269         */
 270        lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, 50);
 271
 272        lirc_rx51_on(lirc_rx51);
 273        lirc_rx51->wbuf_index = 1;
 274        pulse_timer_set_timeout(lirc_rx51, lirc_rx51->wbuf[0]);
 275
 276        /*
 277         * Don't return back to the userspace until the transfer has
 278         * finished
 279         */
 280        wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0);
 281
 282        /* We can sleep again */
 283        lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, -1);
 284
 285        return n;
 286}
 287
 288static long lirc_rx51_ioctl(struct file *filep,
 289                        unsigned int cmd, unsigned long arg)
 290{
 291        int result;
 292        unsigned long value;
 293        unsigned int ivalue;
 294        struct lirc_rx51 *lirc_rx51 = filep->private_data;
 295
 296        switch (cmd) {
 297        case LIRC_GET_SEND_MODE:
 298                result = put_user(LIRC_MODE_PULSE, (unsigned long *)arg);
 299                if (result)
 300                        return result;
 301                break;
 302
 303        case LIRC_SET_SEND_MODE:
 304                result = get_user(value, (unsigned long *)arg);
 305                if (result)
 306                        return result;
 307
 308                /* only LIRC_MODE_PULSE supported */
 309                if (value != LIRC_MODE_PULSE)
 310                        return -ENOSYS;
 311                break;
 312
 313        case LIRC_GET_REC_MODE:
 314                result = put_user(0, (unsigned long *) arg);
 315                if (result)
 316                        return result;
 317                break;
 318
 319        case LIRC_GET_LENGTH:
 320                return -ENOSYS;
 321                break;
 322
 323        case LIRC_SET_SEND_DUTY_CYCLE:
 324                result = get_user(ivalue, (unsigned int *) arg);
 325                if (result)
 326                        return result;
 327
 328                if (ivalue <= 0 || ivalue > 100) {
 329                        dev_err(lirc_rx51->dev, ": invalid duty cycle %d\n",
 330                                ivalue);
 331                        return -EINVAL;
 332                }
 333
 334                lirc_rx51->duty_cycle = ivalue;
 335                break;
 336
 337        case LIRC_SET_SEND_CARRIER:
 338                result = get_user(ivalue, (unsigned int *) arg);
 339                if (result)
 340                        return result;
 341
 342                if (ivalue > 500000 || ivalue < 20000) {
 343                        dev_err(lirc_rx51->dev, ": invalid carrier freq %d\n",
 344                                ivalue);
 345                        return -EINVAL;
 346                }
 347
 348                lirc_rx51->freq = ivalue;
 349                break;
 350
 351        case LIRC_GET_FEATURES:
 352                result = put_user(LIRC_RX51_DRIVER_FEATURES,
 353                                  (unsigned long *) arg);
 354                if (result)
 355                        return result;
 356                break;
 357
 358        default:
 359                return -ENOIOCTLCMD;
 360        }
 361
 362        return 0;
 363}
 364
 365static int lirc_rx51_open(struct inode *inode, struct file *file)
 366{
 367        struct lirc_rx51 *lirc_rx51 = lirc_get_pdata(file);
 368        BUG_ON(!lirc_rx51);
 369
 370        file->private_data = lirc_rx51;
 371
 372        if (test_and_set_bit(1, &lirc_rx51->device_is_open))
 373                return -EBUSY;
 374
 375        return lirc_rx51_init_port(lirc_rx51);
 376}
 377
 378static int lirc_rx51_release(struct inode *inode, struct file *file)
 379{
 380        struct lirc_rx51 *lirc_rx51 = file->private_data;
 381
 382        lirc_rx51_free_port(lirc_rx51);
 383
 384        clear_bit(1, &lirc_rx51->device_is_open);
 385
 386        return 0;
 387}
 388
 389static struct lirc_rx51 lirc_rx51 = {
 390        .freq           = 38000,
 391        .duty_cycle     = 50,
 392        .wbuf_index     = -1,
 393};
 394
 395static const struct file_operations lirc_fops = {
 396        .owner          = THIS_MODULE,
 397        .write          = lirc_rx51_write,
 398        .unlocked_ioctl = lirc_rx51_ioctl,
 399        .read           = lirc_dev_fop_read,
 400        .poll           = lirc_dev_fop_poll,
 401        .open           = lirc_rx51_open,
 402        .release        = lirc_rx51_release,
 403};
 404
 405static struct lirc_driver lirc_rx51_driver = {
 406        .name           = DRIVER_NAME,
 407        .minor          = -1,
 408        .code_length    = 1,
 409        .data           = &lirc_rx51,
 410        .fops           = &lirc_fops,
 411        .owner          = THIS_MODULE,
 412};
 413
 414#ifdef CONFIG_PM
 415
 416static int lirc_rx51_suspend(struct platform_device *dev, pm_message_t state)
 417{
 418        /*
 419         * In case the device is still open, do not suspend. Normally
 420         * this should not be a problem as lircd only keeps the device
 421         * open only for short periods of time. We also don't want to
 422         * get involved with race conditions that might happen if we
 423         * were in a middle of a transmit. Thus, we defer any suspend
 424         * actions until transmit has completed.
 425         */
 426        if (test_and_set_bit(1, &lirc_rx51.device_is_open))
 427                return -EAGAIN;
 428
 429        clear_bit(1, &lirc_rx51.device_is_open);
 430
 431        return 0;
 432}
 433
 434static int lirc_rx51_resume(struct platform_device *dev)
 435{
 436        return 0;
 437}
 438
 439#else
 440
 441#define lirc_rx51_suspend       NULL
 442#define lirc_rx51_resume        NULL
 443
 444#endif /* CONFIG_PM */
 445
 446static int lirc_rx51_probe(struct platform_device *dev)
 447{
 448        lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
 449        lirc_rx51.pdata = dev->dev.platform_data;
 450        lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer;
 451        lirc_rx51.dev = &dev->dev;
 452        lirc_rx51_driver.dev = &dev->dev;
 453        lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
 454        init_waitqueue_head(&lirc_rx51.wqueue);
 455
 456        if (lirc_rx51_driver.minor < 0) {
 457                dev_err(lirc_rx51.dev, ": lirc_register_driver failed: %d\n",
 458                       lirc_rx51_driver.minor);
 459                return lirc_rx51_driver.minor;
 460        }
 461        dev_info(lirc_rx51.dev, "registration ok, minor: %d, pwm: %d\n",
 462                 lirc_rx51_driver.minor, lirc_rx51.pwm_timer_num);
 463
 464        return 0;
 465}
 466
 467static int __exit lirc_rx51_remove(struct platform_device *dev)
 468{
 469        return lirc_unregister_driver(lirc_rx51_driver.minor);
 470}
 471
 472struct platform_driver lirc_rx51_platform_driver = {
 473        .probe          = lirc_rx51_probe,
 474        .remove         = __exit_p(lirc_rx51_remove),
 475        .suspend        = lirc_rx51_suspend,
 476        .resume         = lirc_rx51_resume,
 477        .driver         = {
 478                .name   = DRIVER_NAME,
 479                .owner  = THIS_MODULE,
 480        },
 481};
 482module_platform_driver(lirc_rx51_platform_driver);
 483
 484MODULE_DESCRIPTION("LIRC TX driver for Nokia RX51");
 485MODULE_AUTHOR("Nokia Corporation");
 486MODULE_LICENSE("GPL");
 487