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