Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13-rc2 547 lines 14 kB view raw
1/* 2 saa7146.o - driver for generic saa7146-based hardware 3 4 Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> 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., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include <media/saa7146.h> 22 23LIST_HEAD(saa7146_devices); 24DECLARE_MUTEX(saa7146_devices_lock); 25 26static int saa7146_num; 27 28unsigned int saa7146_debug; 29 30module_param(saa7146_debug, int, 0644); 31MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)"); 32 33#if 0 34static void dump_registers(struct saa7146_dev* dev) 35{ 36 int i = 0; 37 38 INFO((" @ %li jiffies:\n",jiffies)); 39 for(i = 0; i <= 0x148; i+=4) { 40 printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i)); 41 } 42} 43#endif 44 45/**************************************************************************** 46 * gpio and debi helper functions 47 ****************************************************************************/ 48 49void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) 50{ 51 u32 value = 0; 52 53 BUG_ON(port > 3); 54 55 value = saa7146_read(dev, GPIO_CTRL); 56 value &= ~(0xff << (8*port)); 57 value |= (data << (8*port)); 58 saa7146_write(dev, GPIO_CTRL, value); 59} 60 61/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */ 62int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) 63{ 64 unsigned long start; 65 66 /* wait for registers to be programmed */ 67 start = jiffies; 68 while (1) { 69 if (saa7146_read(dev, MC2) & 2) 70 break; 71 if (time_after(jiffies, start + HZ/20)) { 72 DEB_S(("timed out while waiting for registers getting programmed\n")); 73 return -ETIMEDOUT; 74 } 75 if (nobusyloop) 76 msleep(1); 77 } 78 79 /* wait for transfer to complete */ 80 start = jiffies; 81 while (1) { 82 if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) 83 break; 84 saa7146_read(dev, MC2); 85 if (time_after(jiffies, start + HZ/4)) { 86 DEB_S(("timed out while waiting for transfer completion\n")); 87 return -ETIMEDOUT; 88 } 89 if (nobusyloop) 90 msleep(1); 91 } 92 93 return 0; 94} 95 96/**************************************************************************** 97 * general helper functions 98 ****************************************************************************/ 99 100/* this is videobuf_vmalloc_to_sg() from video-buf.c 101 make sure virt has been allocated with vmalloc_32(), otherwise the BUG() 102 may be triggered on highmem machines */ 103static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) 104{ 105 struct scatterlist *sglist; 106 struct page *pg; 107 int i; 108 109 sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL); 110 if (NULL == sglist) 111 return NULL; 112 memset(sglist,0,sizeof(struct scatterlist)*nr_pages); 113 for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { 114 pg = vmalloc_to_page(virt); 115 if (NULL == pg) 116 goto err; 117 if (PageHighMem(pg)) 118 BUG(); 119 sglist[i].page = pg; 120 sglist[i].length = PAGE_SIZE; 121 } 122 return sglist; 123 124 err: 125 kfree(sglist); 126 return NULL; 127} 128 129/********************************************************************************/ 130/* common page table functions */ 131 132char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt) 133{ 134 int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; 135 char *mem = vmalloc_32(length); 136 int slen = 0; 137 138 if (NULL == mem) { 139 return NULL; 140 } 141 142 if (!(pt->slist = vmalloc_to_sg(mem, pages))) { 143 vfree(mem); 144 return NULL; 145 } 146 147 if (saa7146_pgtable_alloc(pci, pt)) { 148 kfree(pt->slist); 149 pt->slist = NULL; 150 vfree(mem); 151 return NULL; 152 } 153 154 slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE); 155 if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) { 156 return NULL; 157 } 158 159 return mem; 160} 161 162void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) 163{ 164 if (NULL == pt->cpu) 165 return; 166 pci_free_consistent(pci, pt->size, pt->cpu, pt->dma); 167 pt->cpu = NULL; 168 if (NULL != pt->slist) { 169 kfree(pt->slist); 170 pt->slist = NULL; 171 } 172} 173 174int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) 175{ 176 u32 *cpu; 177 dma_addr_t dma_addr; 178 179 cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr); 180 if (NULL == cpu) { 181 return -ENOMEM; 182 } 183 pt->size = PAGE_SIZE; 184 pt->cpu = cpu; 185 pt->dma = dma_addr; 186 187 return 0; 188} 189 190int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, 191 struct scatterlist *list, int sglen ) 192{ 193 u32 *ptr, fill; 194 int nr_pages = 0; 195 int i,p; 196 197 BUG_ON(0 == sglen); 198 BUG_ON(list->offset > PAGE_SIZE); 199 200 /* if we have a user buffer, the first page may not be 201 aligned to a page boundary. */ 202 pt->offset = list->offset; 203 204 ptr = pt->cpu; 205 for (i = 0; i < sglen; i++, list++) { 206/* 207 printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset); 208*/ 209 for (p = 0; p * 4096 < list->length; p++, ptr++) { 210 *ptr = cpu_to_le32(sg_dma_address(list) + p * 4096); 211 nr_pages++; 212 } 213 } 214 215 216 /* safety; fill the page table up with the last valid page */ 217 fill = *(ptr-1); 218 for(i=nr_pages;i<1024;i++) { 219 *ptr++ = fill; 220 } 221 222/* 223 ptr = pt->cpu; 224 printk("offset: %d\n",pt->offset); 225 for(i=0;i<5;i++) { 226 printk("ptr1 %d: 0x%08x\n",i,ptr[i]); 227 } 228*/ 229 return 0; 230} 231 232/********************************************************************************/ 233/* interrupt handler */ 234static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) 235{ 236 struct saa7146_dev *dev = dev_id; 237 u32 isr = 0; 238 239 /* read out the interrupt status register */ 240 isr = saa7146_read(dev, ISR); 241 242 /* is this our interrupt? */ 243 if ( 0 == isr ) { 244 /* nope, some other device */ 245 return IRQ_NONE; 246 } 247 248 saa7146_write(dev, ISR, isr); 249 250 if( 0 != (dev->ext)) { 251 if( 0 != (dev->ext->irq_mask & isr )) { 252 if( 0 != dev->ext->irq_func ) { 253 dev->ext->irq_func(dev, &isr); 254 } 255 isr &= ~dev->ext->irq_mask; 256 } 257 } 258 if (0 != (isr & (MASK_27))) { 259 DEB_INT(("irq: RPS0 (0x%08x).\n",isr)); 260 if( 0 != dev->vv_data && 0 != dev->vv_callback) { 261 dev->vv_callback(dev,isr); 262 } 263 isr &= ~MASK_27; 264 } 265 if (0 != (isr & (MASK_28))) { 266 if( 0 != dev->vv_data && 0 != dev->vv_callback) { 267 dev->vv_callback(dev,isr); 268 } 269 isr &= ~MASK_28; 270 } 271 if (0 != (isr & (MASK_16|MASK_17))) { 272 u32 status = saa7146_read(dev, I2C_STATUS); 273 if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { 274 SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); 275 /* only wake up if we expect something */ 276 if( 0 != dev->i2c_op ) { 277 u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2; 278 u32 ssr = (saa7146_read(dev, SSR) >> 17) & 0x1f; 279 DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr)); 280 dev->i2c_op = 0; 281 wake_up(&dev->i2c_wq); 282 } else { 283 DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); 284 } 285 } else { 286 DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); 287 } 288 isr &= ~(MASK_16|MASK_17); 289 } 290 if( 0 != isr ) { 291 ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr)); 292 ERR(("disabling interrupt source(s)!\n")); 293 SAA7146_IER_DISABLE(dev,isr); 294 } 295 return IRQ_HANDLED; 296} 297 298/*********************************************************************************/ 299/* configuration-functions */ 300 301static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent) 302{ 303 struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data; 304 struct saa7146_extension *ext = pci_ext->ext; 305 struct saa7146_dev *dev; 306 int err = -ENOMEM; 307 308 dev = kmalloc(sizeof(struct saa7146_dev), GFP_KERNEL); 309 if (!dev) { 310 ERR(("out of memory.\n")); 311 goto out; 312 } 313 314 /* clear out mem for sure */ 315 memset(dev, 0x0, sizeof(struct saa7146_dev)); 316 317 DEB_EE(("pci:%p\n",pci)); 318 319 err = pci_enable_device(pci); 320 if (err < 0) { 321 ERR(("pci_enable_device() failed.\n")); 322 goto err_free; 323 } 324 325 /* enable bus-mastering */ 326 pci_set_master(pci); 327 328 dev->pci = pci; 329 330 /* get chip-revision; this is needed to enable bug-fixes */ 331 err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision); 332 if (err < 0) { 333 ERR(("pci_read_config_dword() failed.\n")); 334 goto err_disable; 335 } 336 dev->revision &= 0xf; 337 338 /* remap the memory from virtual to physical adress */ 339 340 err = pci_request_region(pci, 0, "saa7146"); 341 if (err < 0) 342 goto err_disable; 343 344 dev->mem = ioremap(pci_resource_start(pci, 0), 345 pci_resource_len(pci, 0)); 346 if (!dev->mem) { 347 ERR(("ioremap() failed.\n")); 348 err = -ENODEV; 349 goto err_release; 350 } 351 352 /* we don't do a master reset here anymore, it screws up 353 some boards that don't have an i2c-eeprom for configuration 354 values */ 355/* 356 saa7146_write(dev, MC1, MASK_31); 357*/ 358 359 /* disable all irqs */ 360 saa7146_write(dev, IER, 0); 361 362 /* shut down all dma transfers and rps tasks */ 363 saa7146_write(dev, MC1, 0x30ff0000); 364 365 /* clear out any rps-signals pending */ 366 saa7146_write(dev, MC2, 0xf8000000); 367 368 /* request an interrupt for the saa7146 */ 369 err = request_irq(pci->irq, interrupt_hw, SA_SHIRQ | SA_INTERRUPT, 370 dev->name, dev); 371 if (err < 0) { 372 ERR(("request_irq() failed.\n")); 373 goto err_unmap; 374 } 375 376 err = -ENOMEM; 377 378 /* get memory for various stuff */ 379 dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, 380 &dev->d_rps0.dma_handle); 381 if (!dev->d_rps0.cpu_addr) 382 goto err_free_irq; 383 memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM); 384 385 dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, 386 &dev->d_rps1.dma_handle); 387 if (!dev->d_rps1.cpu_addr) 388 goto err_free_rps0; 389 memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM); 390 391 dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, 392 &dev->d_i2c.dma_handle); 393 if (!dev->d_i2c.cpu_addr) 394 goto err_free_rps1; 395 memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM); 396 397 /* the rest + print status message */ 398 399 /* create a nice device name */ 400 sprintf(dev->name, "saa7146 (%d)", saa7146_num); 401 402 INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device)); 403 dev->ext = ext; 404 405 pci_set_drvdata(pci, dev); 406 407 init_MUTEX(&dev->lock); 408 spin_lock_init(&dev->int_slock); 409 spin_lock_init(&dev->slock); 410 411 init_MUTEX(&dev->i2c_lock); 412 413 dev->module = THIS_MODULE; 414 init_waitqueue_head(&dev->i2c_wq); 415 416 /* set some sane pci arbitrition values */ 417 saa7146_write(dev, PCI_BT_V1, 0x1c00101f); 418 419 /* TODO: use the status code of the callback */ 420 421 err = -ENODEV; 422 423 if (ext->probe && ext->probe(dev)) { 424 DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); 425 goto err_free_i2c; 426 } 427 428 if (ext->attach(dev, pci_ext)) { 429 DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); 430 goto err_unprobe; 431 } 432 433 INIT_LIST_HEAD(&dev->item); 434 list_add_tail(&dev->item,&saa7146_devices); 435 saa7146_num++; 436 437 err = 0; 438out: 439 return err; 440 441err_unprobe: 442 pci_set_drvdata(pci, NULL); 443err_free_i2c: 444 pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, 445 dev->d_i2c.dma_handle); 446err_free_rps1: 447 pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, 448 dev->d_rps1.dma_handle); 449err_free_rps0: 450 pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, 451 dev->d_rps0.dma_handle); 452err_free_irq: 453 free_irq(pci->irq, (void *)dev); 454err_unmap: 455 iounmap(dev->mem); 456err_release: 457 pci_release_region(pci, 0); 458err_disable: 459 pci_disable_device(pci); 460err_free: 461 kfree(dev); 462 goto out; 463} 464 465static void saa7146_remove_one(struct pci_dev *pdev) 466{ 467 struct saa7146_dev* dev = pci_get_drvdata(pdev); 468 struct { 469 void *addr; 470 dma_addr_t dma; 471 } dev_map[] = { 472 { dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle }, 473 { dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle }, 474 { dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle }, 475 { NULL, 0 } 476 }, *p; 477 478 DEB_EE(("dev:%p\n",dev)); 479 480 dev->ext->detach(dev); 481 482 /* shut down all video dma transfers */ 483 saa7146_write(dev, MC1, 0x00ff0000); 484 485 /* disable all irqs, release irq-routine */ 486 saa7146_write(dev, IER, 0); 487 488 free_irq(pdev->irq, dev); 489 490 for (p = dev_map; p->addr; p++) 491 pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma); 492 493 iounmap(dev->mem); 494 pci_release_region(pdev, 0); 495 list_del(&dev->item); 496 pci_disable_device(pdev); 497 kfree(dev); 498 499 saa7146_num--; 500} 501 502/*********************************************************************************/ 503/* extension handling functions */ 504 505int saa7146_register_extension(struct saa7146_extension* ext) 506{ 507 DEB_EE(("ext:%p\n",ext)); 508 509 ext->driver.name = ext->name; 510 ext->driver.id_table = ext->pci_tbl; 511 ext->driver.probe = saa7146_init_one; 512 ext->driver.remove = saa7146_remove_one; 513 514 printk("saa7146: register extension '%s'.\n",ext->name); 515 return pci_module_init(&ext->driver); 516} 517 518int saa7146_unregister_extension(struct saa7146_extension* ext) 519{ 520 DEB_EE(("ext:%p\n",ext)); 521 printk("saa7146: unregister extension '%s'.\n",ext->name); 522 pci_unregister_driver(&ext->driver); 523 return 0; 524} 525 526EXPORT_SYMBOL_GPL(saa7146_register_extension); 527EXPORT_SYMBOL_GPL(saa7146_unregister_extension); 528 529/* misc functions used by extension modules */ 530EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc); 531EXPORT_SYMBOL_GPL(saa7146_pgtable_free); 532EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); 533EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable); 534EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done); 535 536EXPORT_SYMBOL_GPL(saa7146_setgpio); 537 538EXPORT_SYMBOL_GPL(saa7146_i2c_transfer); 539EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare); 540 541EXPORT_SYMBOL_GPL(saa7146_debug); 542EXPORT_SYMBOL_GPL(saa7146_devices); 543EXPORT_SYMBOL_GPL(saa7146_devices_lock); 544 545MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); 546MODULE_DESCRIPTION("driver for generic saa7146-based hardware"); 547MODULE_LICENSE("GPL");