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

staging: comedi: dt282x: avoid calculating the timer divisor multiple times

A common timer is used for analog input and output async commands. The
(*do_cmdtest) for both subdevices calculates the divisor as part of
Step 4 when validating the trigger arguments. The divisor is calculated
again in the (*do_cmd) for both subdevices in order to set the timer.

The comedi core only calls the (*do_cmd) is called after a successful
(*do_cmdtest). Save the divisor from the (*do_cmdtest) in the private
data and use that value in the (*do_cmd).

The extra check of the cmd->convert_arg in dt282x_ai_cmd() is not necessary.
The convert_arg was already checked in the (*do_cmdtest), and it's not used
in the (*do_cmd).

Tidy up dt282x_ns_to_timer(), the parameters are all unsigned int's and the
mask of the 'flags' can be moved here to simplify the callers.
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 7152f7d4
...@@ -331,6 +331,8 @@ struct dt282x_private { ...@@ -331,6 +331,8 @@ struct dt282x_private {
unsigned int da0_2scomp:1; unsigned int da0_2scomp:1;
unsigned int da1_2scomp:1; unsigned int da1_2scomp:1;
unsigned int divisor;
unsigned short ao_readback[2]; unsigned short ao_readback[2];
int dacsr; /* software copies of registers */ int dacsr; /* software copies of registers */
...@@ -413,34 +415,34 @@ static void dt282x_disable_dma(struct comedi_device *dev) ...@@ -413,34 +415,34 @@ static void dt282x_disable_dma(struct comedi_device *dev)
disable_dma(devpriv->dma[1].chan); disable_dma(devpriv->dma[1].chan);
} }
static int dt282x_ns_to_timer(int *nanosec, int round_mode) static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags)
{ {
int prescale, base, divider; unsigned int prescale, base, divider;
for (prescale = 0; prescale < 16; prescale++) { for (prescale = 0; prescale < 16; prescale++) {
if (prescale == 1) if (prescale == 1)
continue; continue;
base = 250 * (1 << prescale); base = 250 * (1 << prescale);
switch (round_mode) { switch (flags & TRIG_ROUND_MASK) {
case TRIG_ROUND_NEAREST: case TRIG_ROUND_NEAREST:
default: default:
divider = (*nanosec + base / 2) / base; divider = (*ns + base / 2) / base;
break; break;
case TRIG_ROUND_DOWN: case TRIG_ROUND_DOWN:
divider = (*nanosec) / base; divider = (*ns) / base;
break; break;
case TRIG_ROUND_UP: case TRIG_ROUND_UP:
divider = (*nanosec + base - 1) / base; divider = (*ns + base - 1) / base;
break; break;
} }
if (divider < 256) { if (divider < 256) {
*nanosec = divider * base; *ns = divider * base;
return (prescale << 8) | (255 - divider); return (prescale << 8) | (255 - divider);
} }
} }
base = 250 * (1 << 15); base = 250 * (1 << 15);
divider = 255; divider = 255;
*nanosec = divider * base; *ns = divider * base;
return (15 << 8) | (255 - divider); return (15 << 8) | (255 - divider);
} }
...@@ -688,9 +690,11 @@ static int dt282x_ai_insn_read(struct comedi_device *dev, ...@@ -688,9 +690,11 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
} }
static int dt282x_ai_cmdtest(struct comedi_device *dev, static int dt282x_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd) struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ {
const struct dt282x_board *board = comedi_board(dev); const struct dt282x_board *board = comedi_board(dev);
struct dt282x_private *devpriv = dev->private;
int err = 0; int err = 0;
unsigned int arg; unsigned int arg;
...@@ -748,7 +752,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, ...@@ -748,7 +752,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
/* step 4: fix up any arguments */ /* step 4: fix up any arguments */
arg = cmd->convert_arg; arg = cmd->convert_arg;
dt282x_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
if (err) if (err)
...@@ -759,18 +763,13 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, ...@@ -759,18 +763,13 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ {
const struct dt282x_board *board = comedi_board(dev);
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd; struct comedi_cmd *cmd = &s->async->cmd;
int timer;
int ret; int ret;
dt282x_disable_dma(dev); dt282x_disable_dma(dev);
if (cmd->convert_arg < board->ai_speed) outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR);
cmd->convert_arg = board->ai_speed;
timer = dt282x_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST);
outw(timer, dev->iobase + DT2821_TMRCTR);
if (cmd->scan_begin_src == TRIG_FOLLOW) { if (cmd->scan_begin_src == TRIG_FOLLOW) {
/* internal trigger */ /* internal trigger */
...@@ -889,8 +888,10 @@ static int dt282x_ao_insn_write(struct comedi_device *dev, ...@@ -889,8 +888,10 @@ static int dt282x_ao_insn_write(struct comedi_device *dev,
} }
static int dt282x_ao_cmdtest(struct comedi_device *dev, static int dt282x_ao_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd) struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ {
struct dt282x_private *devpriv = dev->private;
int err = 0; int err = 0;
unsigned int arg; unsigned int arg;
...@@ -933,7 +934,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev, ...@@ -933,7 +934,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
/* step 4: fix up any arguments */ /* step 4: fix up any arguments */
arg = cmd->scan_begin_arg; arg = cmd->scan_begin_arg;
dt282x_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
if (err) if (err)
...@@ -979,7 +980,6 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, ...@@ -979,7 +980,6 @@ static int dt282x_ao_inttrig(struct comedi_device *dev,
static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
int timer;
struct comedi_cmd *cmd = &s->async->cmd; struct comedi_cmd *cmd = &s->async->cmd;
dt282x_disable_dma(dev); dt282x_disable_dma(dev);
...@@ -994,8 +994,7 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -994,8 +994,7 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->dma_dir = DMA_MODE_WRITE; devpriv->dma_dir = DMA_MODE_WRITE;
devpriv->current_dma_index = 0; devpriv->current_dma_index = 0;
timer = dt282x_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST); outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR);
outw(timer, dev->iobase + DT2821_TMRCTR);
devpriv->dacsr = DT2821_SSEL | DT2821_DACLK | DT2821_IDARDY; devpriv->dacsr = DT2821_SSEL | DT2821_DACLK | DT2821_IDARDY;
outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); outw(devpriv->dacsr, dev->iobase + DT2821_DACSR);
......
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