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: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7152f7d4b1
commit
3ec2e20274
1 changed files with 20 additions and 21 deletions
|
|
@ -331,6 +331,8 @@ struct dt282x_private {
|
|||
unsigned int da0_2scomp:1;
|
||||
unsigned int da1_2scomp:1;
|
||||
|
||||
unsigned int divisor;
|
||||
|
||||
unsigned short ao_readback[2];
|
||||
|
||||
int dacsr; /* software copies of registers */
|
||||
|
|
@ -413,34 +415,34 @@ static void dt282x_disable_dma(struct comedi_device *dev)
|
|||
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++) {
|
||||
if (prescale == 1)
|
||||
continue;
|
||||
base = 250 * (1 << prescale);
|
||||
switch (round_mode) {
|
||||
switch (flags & TRIG_ROUND_MASK) {
|
||||
case TRIG_ROUND_NEAREST:
|
||||
default:
|
||||
divider = (*nanosec + base / 2) / base;
|
||||
divider = (*ns + base / 2) / base;
|
||||
break;
|
||||
case TRIG_ROUND_DOWN:
|
||||
divider = (*nanosec) / base;
|
||||
divider = (*ns) / base;
|
||||
break;
|
||||
case TRIG_ROUND_UP:
|
||||
divider = (*nanosec + base - 1) / base;
|
||||
divider = (*ns + base - 1) / base;
|
||||
break;
|
||||
}
|
||||
if (divider < 256) {
|
||||
*nanosec = divider * base;
|
||||
*ns = divider * base;
|
||||
return (prescale << 8) | (255 - divider);
|
||||
}
|
||||
}
|
||||
base = 250 * (1 << 15);
|
||||
divider = 255;
|
||||
*nanosec = divider * base;
|
||||
*ns = divider * base;
|
||||
return (15 << 8) | (255 - divider);
|
||||
}
|
||||
|
||||
|
|
@ -688,9 +690,11 @@ static int dt282x_ai_insn_read(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);
|
||||
struct dt282x_private *devpriv = dev->private;
|
||||
int err = 0;
|
||||
unsigned int arg;
|
||||
|
||||
|
|
@ -748,7 +752,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
|
|||
/* step 4: fix up any arguments */
|
||||
|
||||
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);
|
||||
|
||||
if (err)
|
||||
|
|
@ -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)
|
||||
{
|
||||
const struct dt282x_board *board = comedi_board(dev);
|
||||
struct dt282x_private *devpriv = dev->private;
|
||||
struct comedi_cmd *cmd = &s->async->cmd;
|
||||
int timer;
|
||||
int ret;
|
||||
|
||||
dt282x_disable_dma(dev);
|
||||
|
||||
if (cmd->convert_arg < board->ai_speed)
|
||||
cmd->convert_arg = board->ai_speed;
|
||||
timer = dt282x_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST);
|
||||
outw(timer, dev->iobase + DT2821_TMRCTR);
|
||||
outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR);
|
||||
|
||||
if (cmd->scan_begin_src == TRIG_FOLLOW) {
|
||||
/* internal trigger */
|
||||
|
|
@ -889,8 +888,10 @@ static int dt282x_ao_insn_write(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;
|
||||
unsigned int arg;
|
||||
|
||||
|
|
@ -933,7 +934,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
|
|||
/* step 4: fix up any arguments */
|
||||
|
||||
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);
|
||||
|
||||
if (err)
|
||||
|
|
@ -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)
|
||||
{
|
||||
struct dt282x_private *devpriv = dev->private;
|
||||
int timer;
|
||||
struct comedi_cmd *cmd = &s->async->cmd;
|
||||
|
||||
dt282x_disable_dma(dev);
|
||||
|
|
@ -994,8 +994,7 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
|
|||
devpriv->dma_dir = DMA_MODE_WRITE;
|
||||
devpriv->current_dma_index = 0;
|
||||
|
||||
timer = dt282x_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST);
|
||||
outw(timer, dev->iobase + DT2821_TMRCTR);
|
||||
outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR);
|
||||
|
||||
devpriv->dacsr = DT2821_SSEL | DT2821_DACLK | DT2821_IDARDY;
|
||||
outw(devpriv->dacsr, dev->iobase + DT2821_DACSR);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue