linux/drivers/staging/media/lirc/lirc_bt829.c
<<
>>
Prefs
   1/*
   2 * Remote control driver for the TV-card based on bt829
   3 *
   4 *  by Leonid Froenchenko <lfroen@galileo.co.il>
   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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  22
  23#include <linux/kernel.h>
  24#include <linux/module.h>
  25#include <linux/threads.h>
  26#include <linux/sched.h>
  27#include <linux/ioport.h>
  28#include <linux/pci.h>
  29#include <linux/delay.h>
  30
  31#include <media/lirc_dev.h>
  32
  33static int poll_main(void);
  34static int atir_init_start(void);
  35
  36static void write_index(unsigned char index, unsigned int value);
  37static unsigned int read_index(unsigned char index);
  38
  39static void do_i2c_start(void);
  40static void do_i2c_stop(void);
  41
  42static void seems_wr_byte(unsigned char al);
  43static unsigned char seems_rd_byte(void);
  44
  45static unsigned int read_index(unsigned char al);
  46static void write_index(unsigned char ah, unsigned int edx);
  47
  48static void cycle_delay(int cycle);
  49
  50static void do_set_bits(unsigned char bl);
  51static unsigned char do_get_bits(void);
  52
  53#define DATA_PCI_OFF 0x7FFC00
  54#define WAIT_CYCLE   20
  55
  56#define DRIVER_NAME "lirc_bt829"
  57
  58static bool debug;
  59#define dprintk(fmt, args...)                                            \
  60        do {                                                             \
  61                if (debug)                                               \
  62                        printk(KERN_DEBUG DRIVER_NAME ": "fmt, ## args); \
  63        } while (0)
  64
  65static int atir_minor;
  66static unsigned long pci_addr_phys;
  67static unsigned char *pci_addr_lin;
  68
  69static struct lirc_driver atir_driver;
  70
  71static struct pci_dev *do_pci_probe(void)
  72{
  73        struct pci_dev *my_dev;
  74        my_dev = pci_get_device(PCI_VENDOR_ID_ATI,
  75                                PCI_DEVICE_ID_ATI_264VT, NULL);
  76        if (my_dev) {
  77                pr_err("Using device: %s\n", pci_name(my_dev));
  78                pci_addr_phys = 0;
  79                if (my_dev->resource[0].flags & IORESOURCE_MEM) {
  80                        pci_addr_phys = my_dev->resource[0].start;
  81                        pr_info("memory at 0x%08X\n",
  82                               (unsigned int)pci_addr_phys);
  83                }
  84                if (pci_addr_phys == 0) {
  85                        pr_err("no memory resource ?\n");
  86                        return NULL;
  87                }
  88        } else {
  89                pr_err("pci_probe failed\n");
  90                return NULL;
  91        }
  92        return my_dev;
  93}
  94
  95static int atir_add_to_buf(void *data, struct lirc_buffer *buf)
  96{
  97        unsigned char key;
  98        int status;
  99        status = poll_main();
 100        key = (status >> 8) & 0xFF;
 101        if (status & 0xFF) {
 102                dprintk("reading key %02X\n", key);
 103                lirc_buffer_write(buf, &key);
 104                return 0;
 105        }
 106        return -ENODATA;
 107}
 108
 109static int atir_set_use_inc(void *data)
 110{
 111        dprintk("driver is opened\n");
 112        return 0;
 113}
 114
 115static void atir_set_use_dec(void *data)
 116{
 117        dprintk("driver is closed\n");
 118}
 119
 120int init_module(void)
 121{
 122        struct pci_dev *pdev;
 123
 124        pdev = do_pci_probe();
 125        if (pdev == NULL)
 126                return -ENODEV;
 127
 128        if (!atir_init_start())
 129                return -ENODEV;
 130
 131        strcpy(atir_driver.name, "ATIR");
 132        atir_driver.minor       = -1;
 133        atir_driver.code_length = 8;
 134        atir_driver.sample_rate = 10;
 135        atir_driver.data        = 0;
 136        atir_driver.add_to_buf  = atir_add_to_buf;
 137        atir_driver.set_use_inc = atir_set_use_inc;
 138        atir_driver.set_use_dec = atir_set_use_dec;
 139        atir_driver.dev         = &pdev->dev;
 140        atir_driver.owner       = THIS_MODULE;
 141
 142        atir_minor = lirc_register_driver(&atir_driver);
 143        if (atir_minor < 0) {
 144                pr_err("failed to register driver!\n");
 145                return atir_minor;
 146        }
 147        dprintk("driver is registered on minor %d\n", atir_minor);
 148
 149        return 0;
 150}
 151
 152
 153void cleanup_module(void)
 154{
 155        lirc_unregister_driver(atir_minor);
 156}
 157
 158
 159static int atir_init_start(void)
 160{
 161        pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400);
 162        if (pci_addr_lin == 0) {
 163                pr_info("pci mem must be mapped\n");
 164                return 0;
 165        }
 166        return 1;
 167}
 168
 169static void cycle_delay(int cycle)
 170{
 171        udelay(WAIT_CYCLE*cycle);
 172}
 173
 174
 175static int poll_main(void)
 176{
 177        unsigned char status_high, status_low;
 178
 179        do_i2c_start();
 180
 181        seems_wr_byte(0xAA);
 182        seems_wr_byte(0x01);
 183
 184        do_i2c_start();
 185
 186        seems_wr_byte(0xAB);
 187
 188        status_low = seems_rd_byte();
 189        status_high = seems_rd_byte();
 190
 191        do_i2c_stop();
 192
 193        return (status_high << 8) | status_low;
 194}
 195
 196static void do_i2c_start(void)
 197{
 198        do_set_bits(3);
 199        cycle_delay(4);
 200
 201        do_set_bits(1);
 202        cycle_delay(7);
 203
 204        do_set_bits(0);
 205        cycle_delay(2);
 206}
 207
 208static void do_i2c_stop(void)
 209{
 210        unsigned char bits;
 211        bits =  do_get_bits() & 0xFD;
 212        do_set_bits(bits);
 213        cycle_delay(1);
 214
 215        bits |= 1;
 216        do_set_bits(bits);
 217        cycle_delay(2);
 218
 219        bits |= 2;
 220        do_set_bits(bits);
 221        bits = 3;
 222        do_set_bits(bits);
 223        cycle_delay(2);
 224}
 225
 226static void seems_wr_byte(unsigned char value)
 227{
 228        int i;
 229        unsigned char reg;
 230
 231        reg = do_get_bits();
 232        for (i = 0; i < 8; i++) {
 233                if (value & 0x80)
 234                        reg |= 0x02;
 235                else
 236                        reg &= 0xFD;
 237
 238                do_set_bits(reg);
 239                cycle_delay(1);
 240
 241                reg |= 1;
 242                do_set_bits(reg);
 243                cycle_delay(1);
 244
 245                reg &= 0xFE;
 246                do_set_bits(reg);
 247                cycle_delay(1);
 248                value <<= 1;
 249        }
 250        cycle_delay(2);
 251
 252        reg |= 2;
 253        do_set_bits(reg);
 254
 255        reg |= 1;
 256        do_set_bits(reg);
 257
 258        cycle_delay(1);
 259        do_get_bits();
 260
 261        reg &= 0xFE;
 262        do_set_bits(reg);
 263        cycle_delay(3);
 264}
 265
 266static unsigned char seems_rd_byte(void)
 267{
 268        int i;
 269        int rd_byte;
 270        unsigned char bits_2, bits_1;
 271
 272        bits_1 = do_get_bits() | 2;
 273        do_set_bits(bits_1);
 274
 275        rd_byte = 0;
 276        for (i = 0; i < 8; i++) {
 277                bits_1 &= 0xFE;
 278                do_set_bits(bits_1);
 279                cycle_delay(2);
 280
 281                bits_1 |= 1;
 282                do_set_bits(bits_1);
 283                cycle_delay(1);
 284
 285                bits_2 = do_get_bits();
 286                if (bits_2 & 2)
 287                        rd_byte |= 1;
 288
 289                rd_byte <<= 1;
 290        }
 291
 292        bits_1 = 0;
 293        if (bits_2 == 0)
 294                bits_1 |= 2;
 295
 296        do_set_bits(bits_1);
 297        cycle_delay(2);
 298
 299        bits_1 |= 1;
 300        do_set_bits(bits_1);
 301        cycle_delay(3);
 302
 303        bits_1 &= 0xFE;
 304        do_set_bits(bits_1);
 305        cycle_delay(2);
 306
 307        rd_byte >>= 1;
 308        rd_byte &= 0xFF;
 309        return rd_byte;
 310}
 311
 312static void do_set_bits(unsigned char new_bits)
 313{
 314        int reg_val;
 315        reg_val = read_index(0x34);
 316        if (new_bits & 2) {
 317                reg_val &= 0xFFFFFFDF;
 318                reg_val |= 1;
 319        } else {
 320                reg_val &= 0xFFFFFFFE;
 321                reg_val |= 0x20;
 322        }
 323        reg_val |= 0x10;
 324        write_index(0x34, reg_val);
 325
 326        reg_val = read_index(0x31);
 327        if (new_bits & 1)
 328                reg_val |= 0x1000000;
 329        else
 330                reg_val &= 0xFEFFFFFF;
 331
 332        reg_val |= 0x8000000;
 333        write_index(0x31, reg_val);
 334}
 335
 336static unsigned char do_get_bits(void)
 337{
 338        unsigned char bits;
 339        int reg_val;
 340
 341        reg_val = read_index(0x34);
 342        reg_val |= 0x10;
 343        reg_val &= 0xFFFFFFDF;
 344        write_index(0x34, reg_val);
 345
 346        reg_val = read_index(0x34);
 347        bits = 0;
 348        if (reg_val & 8)
 349                bits |= 2;
 350        else
 351                bits &= 0xFD;
 352
 353        reg_val = read_index(0x31);
 354        if (reg_val & 0x1000000)
 355                bits |= 1;
 356        else
 357                bits &= 0xFE;
 358
 359        return bits;
 360}
 361
 362static unsigned int read_index(unsigned char index)
 363{
 364        unsigned char *addr;
 365        unsigned int value;
 366        /*  addr = pci_addr_lin + DATA_PCI_OFF + ((index & 0xFF) << 2); */
 367        addr = pci_addr_lin + ((index & 0xFF) << 2);
 368        value = readl(addr);
 369        return value;
 370}
 371
 372static void write_index(unsigned char index, unsigned int reg_val)
 373{
 374        unsigned char *addr;
 375        addr = pci_addr_lin + ((index & 0xFF) << 2);
 376        writel(reg_val, addr);
 377}
 378
 379MODULE_AUTHOR("Froenchenko Leonid");
 380MODULE_DESCRIPTION("IR remote driver for bt829 based TV cards");
 381MODULE_LICENSE("GPL");
 382
 383module_param(debug, bool, S_IRUGO | S_IWUSR);
 384MODULE_PARM_DESC(debug, "Debug enabled or not");
 385