Commit eca331c2 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: dt282x: introduce struct dt282x_dma_desc

For aesthetics, introduce a struct to hold the DMA descriptor data.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d5702e34
...@@ -300,6 +300,12 @@ static const struct dt282x_board boardtypes[] = { ...@@ -300,6 +300,12 @@ static const struct dt282x_board boardtypes[] = {
}, },
}; };
struct dt282x_dma_desc {
unsigned int chan; /* DMA channel */
unsigned short *virt_addr; /* virtual address of DMA buffer */
unsigned int size; /* transfer size (in bytes) */
};
struct dt282x_private { struct dt282x_private {
unsigned int ad_2scomp:1; unsigned int ad_2scomp:1;
...@@ -312,21 +318,16 @@ struct dt282x_private { ...@@ -312,21 +318,16 @@ struct dt282x_private {
int ntrig; int ntrig;
int nread; int nread;
struct { struct dt282x_dma_desc dma_desc[2];
int chan;
unsigned short *buf; /* DMA buffer */
int size; /* size of current transfer */
} dma[2];
int dma_maxsize; /* max size of DMA transfer (in bytes) */ int dma_maxsize; /* max size of DMA transfer (in bytes) */
int current_dma_index; int cur_dma;
int dma_dir; int dma_dir;
}; };
static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
int dma_chan; struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index];
unsigned long dma_ptr;
unsigned long flags; unsigned long flags;
if (!devpriv->ntrig) if (!devpriv->ntrig)
...@@ -338,18 +339,16 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) ...@@ -338,18 +339,16 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
n = devpriv->ntrig * 2; n = devpriv->ntrig * 2;
devpriv->ntrig -= n / 2; devpriv->ntrig -= n / 2;
devpriv->dma[dma_index].size = n; dma->size = n;
dma_chan = devpriv->dma[dma_index].chan;
dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf);
set_dma_mode(dma_chan, DMA_MODE_READ); set_dma_mode(dma->chan, DMA_MODE_READ);
flags = claim_dma_lock(); flags = claim_dma_lock();
clear_dma_ff(dma_chan); clear_dma_ff(dma->chan);
set_dma_addr(dma_chan, dma_ptr); set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr));
set_dma_count(dma_chan, n); set_dma_count(dma->chan, dma->size);
release_dma_lock(flags); release_dma_lock(flags);
enable_dma(dma_chan); enable_dma(dma->chan);
return n; return n;
} }
...@@ -357,22 +356,19 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) ...@@ -357,22 +356,19 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
int dma_chan; struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index];
unsigned long dma_ptr;
unsigned long flags; unsigned long flags;
devpriv->dma[dma_index].size = n; dma->size = n;
dma_chan = devpriv->dma[dma_index].chan;
dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf);
set_dma_mode(dma_chan, DMA_MODE_WRITE); set_dma_mode(dma->chan, DMA_MODE_WRITE);
flags = claim_dma_lock(); flags = claim_dma_lock();
clear_dma_ff(dma_chan); clear_dma_ff(dma->chan);
set_dma_addr(dma_chan, dma_ptr); set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr));
set_dma_count(dma_chan, n); set_dma_count(dma->chan, dma->size);
release_dma_lock(flags); release_dma_lock(flags);
enable_dma(dma_chan); enable_dma(dma->chan);
return n; return n;
} }
...@@ -381,8 +377,8 @@ static void dt282x_disable_dma(struct comedi_device *dev) ...@@ -381,8 +377,8 @@ static void dt282x_disable_dma(struct comedi_device *dev)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
disable_dma(devpriv->dma[0].chan); disable_dma(devpriv->dma_desc[0].chan);
disable_dma(devpriv->dma[1].chan); disable_dma(devpriv->dma_desc[1].chan);
} }
static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags)
...@@ -444,11 +440,11 @@ static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev, ...@@ -444,11 +440,11 @@ static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev,
int cur_dma) int cur_dma)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
void *ptr = devpriv->dma[cur_dma].buf; struct dt282x_dma_desc *dma = &devpriv->dma_desc[cur_dma];
unsigned int nsamples = comedi_bytes_to_samples(s, devpriv->dma_maxsize); unsigned int nsamples = comedi_bytes_to_samples(s, devpriv->dma_maxsize);
unsigned int nbytes; unsigned int nbytes;
nbytes = comedi_buf_read_samples(s, ptr, nsamples); nbytes = comedi_buf_read_samples(s, dma->virt_addr, nsamples);
if (nbytes) if (nbytes)
dt282x_prep_ao_dma(dev, cur_dma, nbytes); dt282x_prep_ao_dma(dev, cur_dma, nbytes);
else else
...@@ -461,39 +457,35 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev, ...@@ -461,39 +457,35 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s) struct comedi_subdevice *s)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
int cur_dma = devpriv->current_dma_index; struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma];
outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
dev->iobase + DT2821_SUPCSR_REG); dev->iobase + DT2821_SUPCSR_REG);
disable_dma(devpriv->dma[cur_dma].chan); disable_dma(dma->chan);
devpriv->current_dma_index = 1 - cur_dma; if (!dt282x_ao_setup_dma(dev, s, devpriv->cur_dma))
if (!dt282x_ao_setup_dma(dev, s, cur_dma))
s->async->events |= COMEDI_CB_OVERFLOW; s->async->events |= COMEDI_CB_OVERFLOW;
devpriv->cur_dma = 1 - devpriv->cur_dma;
} }
static void dt282x_ai_dma_interrupt(struct comedi_device *dev, static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s) struct comedi_subdevice *s)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
int cur_dma = devpriv->current_dma_index; struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma];
void *ptr = devpriv->dma[cur_dma].buf; unsigned int nsamples = comedi_bytes_to_samples(s, dma->size);
int size = devpriv->dma[cur_dma].size;
unsigned int nsamples = comedi_bytes_to_samples(s, size);
int ret; int ret;
outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
dev->iobase + DT2821_SUPCSR_REG); dev->iobase + DT2821_SUPCSR_REG);
disable_dma(devpriv->dma[cur_dma].chan); disable_dma(dma->chan);
devpriv->current_dma_index = 1 - cur_dma; dt282x_munge(dev, s, dma->virt_addr, dma->size);
ret = comedi_buf_write_samples(s, dma->virt_addr, nsamples);
dt282x_munge(dev, s, ptr, size); if (ret != dma->size)
ret = comedi_buf_write_samples(s, ptr, nsamples);
if (ret != size)
return; return;
devpriv->nread -= nsamples; devpriv->nread -= nsamples;
...@@ -514,7 +506,9 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev, ...@@ -514,7 +506,9 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
} }
#endif #endif
/* restart the channel */ /* restart the channel */
dt282x_prep_ai_dma(dev, cur_dma, 0); dt282x_prep_ai_dma(dev, devpriv->cur_dma, 0);
devpriv->cur_dma = 1 - devpriv->cur_dma;
} }
static irqreturn_t dt282x_interrupt(int irq, void *d) static irqreturn_t dt282x_interrupt(int irq, void *d)
...@@ -769,7 +763,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -769,7 +763,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->nread = devpriv->ntrig; devpriv->nread = devpriv->ntrig;
devpriv->dma_dir = DMA_MODE_READ; devpriv->dma_dir = DMA_MODE_READ;
devpriv->current_dma_index = 0; devpriv->cur_dma = 0;
dt282x_prep_ai_dma(dev, 0, 0); dt282x_prep_ai_dma(dev, 0, 0);
if (devpriv->ntrig) { if (devpriv->ntrig) {
dt282x_prep_ai_dma(dev, 1, 0); dt282x_prep_ai_dma(dev, 1, 0);
...@@ -949,7 +943,7 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -949,7 +943,7 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->nread = devpriv->ntrig; devpriv->nread = devpriv->ntrig;
devpriv->dma_dir = DMA_MODE_WRITE; devpriv->dma_dir = DMA_MODE_WRITE;
devpriv->current_dma_index = 0; devpriv->cur_dma = 0;
outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG); outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
...@@ -1090,10 +1084,11 @@ static int dt282x_alloc_dma(struct comedi_device *dev, ...@@ -1090,10 +1084,11 @@ static int dt282x_alloc_dma(struct comedi_device *dev,
devpriv->dma_maxsize = PAGE_SIZE; devpriv->dma_maxsize = PAGE_SIZE;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
devpriv->dma[i].chan = dma_chan[i]; struct dt282x_dma_desc *dma = &devpriv->dma_desc[i];
devpriv->dma[i].buf =
(void *)__get_free_page(GFP_KERNEL | GFP_DMA); dma->chan = dma_chan[i];
if (!devpriv->dma[i].buf) dma->virt_addr = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
if (!dma->virt_addr)
return -ENOMEM; return -ENOMEM;
} }
...@@ -1103,18 +1098,18 @@ static int dt282x_alloc_dma(struct comedi_device *dev, ...@@ -1103,18 +1098,18 @@ static int dt282x_alloc_dma(struct comedi_device *dev,
static void dt282x_free_dma(struct comedi_device *dev) static void dt282x_free_dma(struct comedi_device *dev)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct dt282x_dma_desc *dma;
int i; int i;
if (!devpriv) if (!devpriv)
return; return;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (devpriv->dma[i].chan) dma = &devpriv->dma_desc[i];
free_dma(devpriv->dma[i].chan); if (dma->chan)
if (devpriv->dma[i].buf) free_dma(dma->chan);
free_page((unsigned long)devpriv->dma[i].buf); if (dma->virt_addr)
devpriv->dma[i].chan = 0; free_page((unsigned long)dma->virt_addr);
devpriv->dma[i].buf = NULL;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment