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