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