Skip to content

Commit

Permalink
[media] tw686x: Introduce an interface to support multiple DMA modes
Browse files Browse the repository at this point in the history
Let's set the corner stone to support all the DMA modes
available on this device.

For stability reasons, the driver is currently setting DMA frame
mode, and using single DMA buffers to get the P and B buffers.
Each frame is then memcpy'ed into the user buffer.

However, other platforms might be interested in avoiding this
memcpy, or in taking advantage of the chip's DMA scatter-gather
capabilities.

To achieve this, this commit introduces a "dma_mode" module parameter,
and a tw686x_dma_ops struct. This will allow to define functions to
alloc/free DMA buffers, and to return the frames to userspace.

The memcpy-based method described above is named as dma_mode="memcpy".
Current alloc/free functions are renamed as tw686x_memcpy_xxx,
and are now used through a memcpy_dma_ops.

Tested-by: Tim Harvey <[email protected]>
Signed-off-by: Ezequiel Garcia <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
ezequielgarcia authored and mchehab committed Jun 28, 2016
1 parent 068adc4 commit f8afaa8
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 121 deletions.
48 changes: 40 additions & 8 deletions drivers/media/pci/tw686x/tw686x-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
* under stress testings it has been found that the machine can
* freeze completely if DMA registers are programmed while streaming
* is active.
* This driver tries to access hardware registers as infrequently
* as possible by:
* i. allocating fixed DMA buffers and memcpy'ing into
* vmalloc'ed buffers
* ii. using a timer to mitigate the rate of DMA reset operations,
* on DMA channels error.
*
* 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>
Expand Down Expand Up @@ -55,6 +57,34 @@ static u32 dma_interval = 0x00098968;
module_param(dma_interval, int, 0444);
MODULE_PARM_DESC(dma_interval, "Minimum time span for DMA interrupting host");

static unsigned int dma_mode = TW686X_DMA_MODE_MEMCPY;
static const char *dma_mode_name(unsigned int mode)
{
switch (mode) {
case TW686X_DMA_MODE_MEMCPY:
return "memcpy";
default:
return "unknown";
}
}

static int tw686x_dma_mode_get(char *buffer, struct kernel_param *kp)
{
return sprintf(buffer, dma_mode_name(dma_mode));
}

static int tw686x_dma_mode_set(const char *val, struct kernel_param *kp)
{
if (!strcasecmp(val, dma_mode_name(TW686X_DMA_MODE_MEMCPY)))
dma_mode = TW686X_DMA_MODE_MEMCPY;
else
return -EINVAL;
return 0;
}
module_param_call(dma_mode, tw686x_dma_mode_set, tw686x_dma_mode_get,
&dma_mode, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(dma_mode, "DMA operation mode");

void tw686x_disable_channel(struct tw686x_dev *dev, unsigned int channel)
{
u32 dma_en = reg_read(dev, DMA_CHANNEL_ENABLE);
Expand Down Expand Up @@ -212,6 +242,7 @@ static int tw686x_probe(struct pci_dev *pci_dev,
if (!dev)
return -ENOMEM;
dev->type = pci_id->driver_data;
dev->dma_mode = dma_mode;
sprintf(dev->name, "tw%04X", pci_dev->device);

dev->video_channels = kcalloc(max_channels(dev),
Expand All @@ -228,9 +259,10 @@ static int tw686x_probe(struct pci_dev *pci_dev,
goto free_video;
}

pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx\n", dev->name,
pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx (%s mode)\n", dev->name,
pci_name(pci_dev), pci_dev->irq,
(unsigned long)pci_resource_start(pci_dev, 0));
(unsigned long)pci_resource_start(pci_dev, 0),
dma_mode_name(dma_mode));

dev->pci_dev = pci_dev;
if (pci_enable_device(pci_dev)) {
Expand Down
5 changes: 5 additions & 0 deletions drivers/media/pci/tw686x/tw686x-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,9 @@
#define TW686X_STD_PAL_CN 5
#define TW686X_STD_PAL_60 6

#define TW686X_FIELD_MODE 0x3
#define TW686X_FRAME_MODE 0x2
/* 0x1 is reserved */
#define TW686X_SG_MODE 0x0

#define TW686X_FIFO_ERROR(x) (x & ~(0xff))
Loading

0 comments on commit f8afaa8

Please sign in to comment.