Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  tw68-core.c
0004  *  Core functions for the Techwell 68xx driver
0005  *
0006  *  Much of this code is derived from the cx88 and sa7134 drivers, which
0007  *  were in turn derived from the bt87x driver.  The original work was by
0008  *  Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab,
0009  *  Hans Verkuil, Andy Walls and many others.  Their work is gratefully
0010  *  acknowledged.  Full credit goes to them - any problems within this code
0011  *  are mine.
0012  *
0013  *  Copyright (C) 2009  William M. Brack
0014  *
0015  *  Refactored and updated to the latest v4l core frameworks:
0016  *
0017  *  Copyright (C) 2014 Hans Verkuil <hverkuil@xs4all.nl>
0018  */
0019 
0020 #include <linux/init.h>
0021 #include <linux/list.h>
0022 #include <linux/module.h>
0023 #include <linux/kernel.h>
0024 #include <linux/slab.h>
0025 #include <linux/kmod.h>
0026 #include <linux/sound.h>
0027 #include <linux/interrupt.h>
0028 #include <linux/delay.h>
0029 #include <linux/mutex.h>
0030 #include <linux/dma-mapping.h>
0031 #include <linux/pci_ids.h>
0032 #include <linux/pm.h>
0033 
0034 #include <media/v4l2-dev.h>
0035 #include "tw68.h"
0036 #include "tw68-reg.h"
0037 
0038 MODULE_DESCRIPTION("v4l2 driver module for tw6800 based video capture cards");
0039 MODULE_AUTHOR("William M. Brack");
0040 MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
0041 MODULE_LICENSE("GPL");
0042 
0043 static unsigned int latency = UNSET;
0044 module_param(latency, int, 0444);
0045 MODULE_PARM_DESC(latency, "pci latency timer");
0046 
0047 static unsigned int video_nr[] = {[0 ... (TW68_MAXBOARDS - 1)] = UNSET };
0048 module_param_array(video_nr, int, NULL, 0444);
0049 MODULE_PARM_DESC(video_nr, "video device number");
0050 
0051 static unsigned int card[] = {[0 ... (TW68_MAXBOARDS - 1)] = UNSET };
0052 module_param_array(card, int, NULL, 0444);
0053 MODULE_PARM_DESC(card, "card type");
0054 
0055 static atomic_t tw68_instance = ATOMIC_INIT(0);
0056 
0057 /* ------------------------------------------------------------------ */
0058 
0059 /*
0060  * Please add any new PCI IDs to: https://pci-ids.ucw.cz.  This keeps
0061  * the PCI ID database up to date.  Note that the entries must be
0062  * added under vendor 0x1797 (Techwell Inc.) as subsystem IDs.
0063  */
0064 static const struct pci_device_id tw68_pci_tbl[] = {
0065     {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6800)},
0066     {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6801)},
0067     {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6804)},
0068     {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_1)},
0069     {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_2)},
0070     {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_3)},
0071     {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_4)},
0072     {0,}
0073 };
0074 
0075 /* ------------------------------------------------------------------ */
0076 
0077 
0078 /*
0079  * The device is given a "soft reset". According to the specifications,
0080  * after this "all register content remain unchanged", so we also write
0081  * to all specified registers manually as well (mostly to manufacturer's
0082  * specified reset values)
0083  */
0084 static int tw68_hw_init1(struct tw68_dev *dev)
0085 {
0086     /* Assure all interrupts are disabled */
0087     tw_writel(TW68_INTMASK, 0);     /* 020 */
0088     /* Clear any pending interrupts */
0089     tw_writel(TW68_INTSTAT, 0xffffffff);    /* 01C */
0090     /* Stop risc processor, set default buffer level */
0091     tw_writel(TW68_DMAC, 0x1600);
0092 
0093     tw_writeb(TW68_ACNTL, 0x80);    /* 218  soft reset */
0094     msleep(100);
0095 
0096     tw_writeb(TW68_INFORM, 0x40);   /* 208  mux0, 27mhz xtal */
0097     tw_writeb(TW68_OPFORM, 0x04);   /* 20C  analog line-lock */
0098     tw_writeb(TW68_HSYNC, 0);   /* 210  color-killer high sens */
0099     tw_writeb(TW68_ACNTL, 0x42);    /* 218  int vref #2, chroma adc off */
0100 
0101     tw_writeb(TW68_CROP_HI, 0x02);  /* 21C  Hactive m.s. bits */
0102     tw_writeb(TW68_VDELAY_LO, 0x12);/* 220  Mfg specified reset value */
0103     tw_writeb(TW68_VACTIVE_LO, 0xf0);
0104     tw_writeb(TW68_HDELAY_LO, 0x0f);
0105     tw_writeb(TW68_HACTIVE_LO, 0xd0);
0106 
0107     tw_writeb(TW68_CNTRL1, 0xcd);   /* 230  Wide Chroma BPF B/W
0108                      *  Secam reduction, Adap comb for
0109                      *  NTSC, Op Mode 1 */
0110 
0111     tw_writeb(TW68_VSCALE_LO, 0);   /* 234 */
0112     tw_writeb(TW68_SCALE_HI, 0x11); /* 238 */
0113     tw_writeb(TW68_HSCALE_LO, 0);   /* 23c */
0114     tw_writeb(TW68_BRIGHT, 0);  /* 240 */
0115     tw_writeb(TW68_CONTRAST, 0x5c); /* 244 */
0116     tw_writeb(TW68_SHARPNESS, 0x51);/* 248 */
0117     tw_writeb(TW68_SAT_U, 0x80);    /* 24C */
0118     tw_writeb(TW68_SAT_V, 0x80);    /* 250 */
0119     tw_writeb(TW68_HUE, 0x00);  /* 254 */
0120 
0121     /* TODO - Check that none of these are set by control defaults */
0122     tw_writeb(TW68_SHARP2, 0x53);   /* 258  Mfg specified reset val */
0123     tw_writeb(TW68_VSHARP, 0x80);   /* 25C  Sharpness Coring val 8 */
0124     tw_writeb(TW68_CORING, 0x44);   /* 260  CTI and Vert Peak coring */
0125     tw_writeb(TW68_CNTRL2, 0x00);   /* 268  No power saving enabled */
0126     tw_writeb(TW68_SDT, 0x07);  /* 270  Enable shadow reg, auto-det */
0127     tw_writeb(TW68_SDTR, 0x7f); /* 274  All stds recog, don't start */
0128     tw_writeb(TW68_CLMPG, 0x50);    /* 280  Clamp end at 40 sys clocks */
0129     tw_writeb(TW68_IAGC, 0x22); /* 284  Mfg specified reset val */
0130     tw_writeb(TW68_AGCGAIN, 0xf0);  /* 288  AGC gain when loop disabled */
0131     tw_writeb(TW68_PEAKWT, 0xd8);   /* 28C  White peak threshold */
0132     tw_writeb(TW68_CLMPL, 0x3c);    /* 290  Y channel clamp level */
0133 /*  tw_writeb(TW68_SYNCT, 0x38);*/  /* 294  Sync amplitude */
0134     tw_writeb(TW68_SYNCT, 0x30);    /* 294  Sync amplitude */
0135     tw_writeb(TW68_MISSCNT, 0x44);  /* 298  Horiz sync, VCR detect sens */
0136     tw_writeb(TW68_PCLAMP, 0x28);   /* 29C  Clamp pos from PLL sync */
0137     /* Bit DETV of VCNTL1 helps sync multi cams/chip board */
0138     tw_writeb(TW68_VCNTL1, 0x04);   /* 2A0 */
0139     tw_writeb(TW68_VCNTL2, 0);  /* 2A4 */
0140     tw_writeb(TW68_CKILL, 0x68);    /* 2A8  Mfg specified reset val */
0141     tw_writeb(TW68_COMB, 0x44); /* 2AC  Mfg specified reset val */
0142     tw_writeb(TW68_LDLY, 0x30); /* 2B0  Max positive luma delay */
0143     tw_writeb(TW68_MISC1, 0x14);    /* 2B4  Mfg specified reset val */
0144     tw_writeb(TW68_LOOP, 0xa5); /* 2B8  Mfg specified reset val */
0145     tw_writeb(TW68_MISC2, 0xe0);    /* 2BC  Enable colour killer */
0146     tw_writeb(TW68_MVSN, 0);    /* 2C0 */
0147     tw_writeb(TW68_CLMD, 0x05); /* 2CC  slice level auto, clamp med. */
0148     tw_writeb(TW68_IDCNTL, 0);  /* 2D0  Writing zero to this register
0149                      *  selects NTSC ID detection,
0150                      *  but doesn't change the
0151                      *  sensitivity (which has a reset
0152                      *  value of 1E).  Since we are
0153                      *  not doing auto-detection, it
0154                      *  has no real effect */
0155     tw_writeb(TW68_CLCNTL1, 0); /* 2D4 */
0156     tw_writel(TW68_VBIC, 0x03); /* 010 */
0157     tw_writel(TW68_CAP_CTL, 0x03);  /* 040  Enable both even & odd flds */
0158     tw_writel(TW68_DMAC, 0x2000);   /* patch set had 0x2080 */
0159     tw_writel(TW68_TESTREG, 0); /* 02C */
0160 
0161     /*
0162      * Some common boards, especially inexpensive single-chip models,
0163      * use the GPIO bits 0-3 to control an on-board video-output mux.
0164      * For these boards, we need to set up the GPIO register into
0165      * "normal" mode, set bits 0-3 as output, and then set those bits
0166      * zero.
0167      *
0168      * Eventually, it would be nice if we could identify these boards
0169      * uniquely, and only do this initialisation if the board has been
0170      * identify.  For the moment, however, it shouldn't hurt anything
0171      * to do these steps.
0172      */
0173     tw_writel(TW68_GPIOC, 0);   /* Set the GPIO to "normal", no ints */
0174     tw_writel(TW68_GPOE, 0x0f); /* Set bits 0-3 to "output" */
0175     tw_writel(TW68_GPDATA, 0);  /* Set all bits to low state */
0176 
0177     /* Initialize the device control structures */
0178     mutex_init(&dev->lock);
0179     spin_lock_init(&dev->slock);
0180 
0181     /* Initialize any subsystems */
0182     tw68_video_init1(dev);
0183     return 0;
0184 }
0185 
0186 static irqreturn_t tw68_irq(int irq, void *dev_id)
0187 {
0188     struct tw68_dev *dev = dev_id;
0189     u32 status, orig;
0190     int loop;
0191 
0192     status = orig = tw_readl(TW68_INTSTAT) & dev->pci_irqmask;
0193     /* Check if anything to do */
0194     if (0 == status)
0195         return IRQ_NONE;    /* Nope - return */
0196     for (loop = 0; loop < 10; loop++) {
0197         if (status & dev->board_virqmask)   /* video interrupt */
0198             tw68_irq_video_done(dev, status);
0199         status = tw_readl(TW68_INTSTAT) & dev->pci_irqmask;
0200         if (0 == status)
0201             return IRQ_HANDLED;
0202     }
0203     dev_dbg(&dev->pci->dev, "%s: **** INTERRUPT NOT HANDLED - clearing mask (orig 0x%08x, cur 0x%08x)",
0204             dev->name, orig, tw_readl(TW68_INTSTAT));
0205     dev_dbg(&dev->pci->dev, "%s: pci_irqmask 0x%08x; board_virqmask 0x%08x ****\n",
0206             dev->name, dev->pci_irqmask, dev->board_virqmask);
0207     tw_clearl(TW68_INTMASK, dev->pci_irqmask);
0208     return IRQ_HANDLED;
0209 }
0210 
0211 static int tw68_initdev(struct pci_dev *pci_dev,
0212                      const struct pci_device_id *pci_id)
0213 {
0214     struct tw68_dev *dev;
0215     int vidnr = -1;
0216     int err;
0217 
0218     dev = devm_kzalloc(&pci_dev->dev, sizeof(*dev), GFP_KERNEL);
0219     if (NULL == dev)
0220         return -ENOMEM;
0221 
0222     dev->instance = v4l2_device_set_name(&dev->v4l2_dev, "tw68",
0223                         &tw68_instance);
0224 
0225     err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
0226     if (err)
0227         return err;
0228 
0229     /* pci init */
0230     dev->pci = pci_dev;
0231     if (pci_enable_device(pci_dev)) {
0232         err = -EIO;
0233         goto fail1;
0234     }
0235 
0236     dev->name = dev->v4l2_dev.name;
0237 
0238     if (UNSET != latency) {
0239         pr_info("%s: setting pci latency timer to %d\n",
0240                dev->name, latency);
0241         pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
0242     }
0243 
0244     /* print pci info */
0245     pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
0246     pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
0247     pr_info("%s: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",
0248         dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
0249         dev->pci_lat, (u64)pci_resource_start(pci_dev, 0));
0250     pci_set_master(pci_dev);
0251     err = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32));
0252     if (err) {
0253         pr_info("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
0254         goto fail1;
0255     }
0256 
0257     switch (pci_id->device) {
0258     case PCI_DEVICE_ID_TECHWELL_6800:   /* TW6800 */
0259         dev->vdecoder = TW6800;
0260         dev->board_virqmask = TW68_VID_INTS;
0261         break;
0262     case PCI_DEVICE_ID_TECHWELL_6801:   /* Video decoder for TW6802 */
0263         dev->vdecoder = TW6801;
0264         dev->board_virqmask = TW68_VID_INTS | TW68_VID_INTSX;
0265         break;
0266     case PCI_DEVICE_ID_TECHWELL_6804:   /* Video decoder for TW6804 */
0267         dev->vdecoder = TW6804;
0268         dev->board_virqmask = TW68_VID_INTS | TW68_VID_INTSX;
0269         break;
0270     default:
0271         dev->vdecoder = TWXXXX; /* To be announced */
0272         dev->board_virqmask = TW68_VID_INTS | TW68_VID_INTSX;
0273         break;
0274     }
0275 
0276     /* get mmio */
0277     if (!request_mem_region(pci_resource_start(pci_dev, 0),
0278                 pci_resource_len(pci_dev, 0),
0279                 dev->name)) {
0280         err = -EBUSY;
0281         pr_err("%s: can't get MMIO memory @ 0x%llx\n",
0282             dev->name,
0283             (unsigned long long)pci_resource_start(pci_dev, 0));
0284         goto fail1;
0285     }
0286     dev->lmmio = ioremap(pci_resource_start(pci_dev, 0),
0287                  pci_resource_len(pci_dev, 0));
0288     dev->bmmio = (__u8 __iomem *)dev->lmmio;
0289     if (NULL == dev->lmmio) {
0290         err = -EIO;
0291         pr_err("%s: can't ioremap() MMIO memory\n",
0292                dev->name);
0293         goto fail2;
0294     }
0295     /* initialize hardware #1 */
0296     /* Then do any initialisation wanted before interrupts are on */
0297     tw68_hw_init1(dev);
0298 
0299     /* get irq */
0300     err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw68_irq,
0301               IRQF_SHARED, dev->name, dev);
0302     if (err < 0) {
0303         pr_err("%s: can't get IRQ %d\n",
0304                dev->name, pci_dev->irq);
0305         goto fail3;
0306     }
0307 
0308     /*
0309      *  Now do remainder of initialisation, first for
0310      *  things unique for this card, then for general board
0311      */
0312     if (dev->instance < TW68_MAXBOARDS)
0313         vidnr = video_nr[dev->instance];
0314     /* initialise video function first */
0315     err = tw68_video_init2(dev, vidnr);
0316     if (err < 0) {
0317         pr_err("%s: can't register video device\n",
0318                dev->name);
0319         goto fail4;
0320     }
0321     tw_setl(TW68_INTMASK, dev->pci_irqmask);
0322 
0323     pr_info("%s: registered device %s\n",
0324            dev->name, video_device_node_name(&dev->vdev));
0325 
0326     return 0;
0327 
0328 fail4:
0329     video_unregister_device(&dev->vdev);
0330 fail3:
0331     iounmap(dev->lmmio);
0332 fail2:
0333     release_mem_region(pci_resource_start(pci_dev, 0),
0334                pci_resource_len(pci_dev, 0));
0335 fail1:
0336     v4l2_device_unregister(&dev->v4l2_dev);
0337     return err;
0338 }
0339 
0340 static void tw68_finidev(struct pci_dev *pci_dev)
0341 {
0342     struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
0343     struct tw68_dev *dev =
0344         container_of(v4l2_dev, struct tw68_dev, v4l2_dev);
0345 
0346     /* shutdown subsystems */
0347     tw_clearl(TW68_DMAC, TW68_DMAP_EN | TW68_FIFO_EN);
0348     tw_writel(TW68_INTMASK, 0);
0349 
0350     /* unregister */
0351     video_unregister_device(&dev->vdev);
0352     v4l2_ctrl_handler_free(&dev->hdl);
0353 
0354     /* release resources */
0355     iounmap(dev->lmmio);
0356     release_mem_region(pci_resource_start(pci_dev, 0),
0357                pci_resource_len(pci_dev, 0));
0358 
0359     v4l2_device_unregister(&dev->v4l2_dev);
0360 }
0361 
0362 static int __maybe_unused tw68_suspend(struct device *dev_d)
0363 {
0364     struct pci_dev *pci_dev = to_pci_dev(dev_d);
0365     struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
0366     struct tw68_dev *dev = container_of(v4l2_dev,
0367                 struct tw68_dev, v4l2_dev);
0368 
0369     tw_clearl(TW68_DMAC, TW68_DMAP_EN | TW68_FIFO_EN);
0370     dev->pci_irqmask &= ~TW68_VID_INTS;
0371     tw_writel(TW68_INTMASK, 0);
0372 
0373     synchronize_irq(pci_dev->irq);
0374 
0375     vb2_discard_done(&dev->vidq);
0376 
0377     return 0;
0378 }
0379 
0380 static int __maybe_unused tw68_resume(struct device *dev_d)
0381 {
0382     struct v4l2_device *v4l2_dev = dev_get_drvdata(dev_d);
0383     struct tw68_dev *dev = container_of(v4l2_dev,
0384                         struct tw68_dev, v4l2_dev);
0385     struct tw68_buf *buf;
0386     unsigned long flags;
0387 
0388     /* Do things that are done in tw68_initdev ,
0389         except of initializing memory structures.*/
0390 
0391     msleep(100);
0392 
0393     tw68_set_tvnorm_hw(dev);
0394 
0395     /*resume unfinished buffer(s)*/
0396     spin_lock_irqsave(&dev->slock, flags);
0397     buf = container_of(dev->active.next, struct tw68_buf, list);
0398 
0399     tw68_video_start_dma(dev, buf);
0400 
0401     spin_unlock_irqrestore(&dev->slock, flags);
0402 
0403     return 0;
0404 }
0405 
0406 /* ----------------------------------------------------------- */
0407 
0408 static SIMPLE_DEV_PM_OPS(tw68_pm_ops, tw68_suspend, tw68_resume);
0409 
0410 static struct pci_driver tw68_pci_driver = {
0411     .name      = "tw68",
0412     .id_table  = tw68_pci_tbl,
0413     .probe     = tw68_initdev,
0414     .remove    = tw68_finidev,
0415     .driver.pm = &tw68_pm_ops,
0416 };
0417 
0418 module_pci_driver(tw68_pci_driver);