// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar * * Based on original driver by Krzysztof Ha?asa: * Copyright (C) 2015 Industrial Research Institute for Automation * and Measurements PIAP * * Notes * ----- * * 1. Under stress-testing, it has been observed that the PCIe link * goes down, without reason. Therefore, the driver takes special care * to allow device hot-unplugging. * * 2. TW686X devices are capable of setting a few different DMA modes, * including: scatter-gather, field and frame modes. However, * under stress testings it has been found that the machine can * freeze completely if DMA registers are programmed while streaming * is active. * * Therefore, driver implements a dma_mode called 'memcpy' which * avoids cycling the DMA buffers, and insteads allocates extra DMA buffers * and then copies into vmalloc'ed user buffers. * * In addition to this, when streaming is on, the driver tries to access * hardware registers as infrequently as possible. This is done by using * a timer to limit the rate at which DMA is reset on DMA channels error. */ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci_ids.h> #include <linux/slab.h> #include <linux/timer.h> #include "tw686x.h" #include "tw686x-regs.h" /* * This module parameter allows to control the DMA_TIMER_INTERVAL value. * The DMA_TIMER_INTERVAL register controls the minimum DMA interrupt * time span (iow, the maximum DMA interrupt rate) thus allowing for * IRQ coalescing. * * The chip datasheet does not mention a time unit for this value, so * users wanting fine-grain control over the interrupt rate should * determine the desired value through testing. */ static u32 dma_interval = …; module_param(dma_interval, int, 0444); MODULE_PARM_DESC(…) …; static unsigned int dma_mode = …; static const char *dma_mode_name(unsigned int mode) { … } static int tw686x_dma_mode_get(char *buffer, const struct kernel_param *kp) { … } static int tw686x_dma_mode_set(const char *val, const struct kernel_param *kp) { … } module_param_call(…); MODULE_PARM_DESC(…) …; void tw686x_disable_channel(struct tw686x_dev *dev, unsigned int channel) { … } void tw686x_enable_channel(struct tw686x_dev *dev, unsigned int channel) { … } /* * The purpose of this awful hack is to avoid enabling the DMA * channels "too fast" which makes some TW686x devices very * angry and freeze the CPU (see note 1). */ static void tw686x_dma_delay(struct timer_list *t) { … } static void tw686x_reset_channels(struct tw686x_dev *dev, unsigned int ch_mask) { … } static irqreturn_t tw686x_irq(int irq, void *dev_id) { … } static void tw686x_dev_release(struct v4l2_device *v4l2_dev) { … } static int tw686x_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { … } static void tw686x_remove(struct pci_dev *pci_dev) { … } /* * On TW6864 and TW6868, all channels share the pair of video DMA SG tables, * with 10-bit start_idx and end_idx determining start and end of frame buffer * for particular channel. * TW6868 with all its 8 channels would be problematic (only 127 SG entries per * channel) but we support only 4 channels on this chip anyway (the first * 4 channels are driven with internal video decoder, the other 4 would require * an external TW286x part). * * On TW6865 and TW6869, each channel has its own DMA SG table, with indexes * starting with 0. Both chips have complete sets of internal video decoders * (respectively 4 or 8-channel). * * All chips have separate SG tables for two video frames. */ /* driver_data is number of A/V channels */ static const struct pci_device_id tw686x_pci_tbl[] = …; MODULE_DEVICE_TABLE(pci, tw686x_pci_tbl); static struct pci_driver tw686x_pci_driver = …; module_pci_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …;