in 104-quad-8.c [240:300]
static int quad8_function_write(struct counter_device *counter,
struct counter_count *count,
enum counter_function function)
{
struct quad8 *const priv = counter_priv(counter);
const int id = count->id;
unsigned int *const quadrature_mode = priv->quadrature_mode + id;
unsigned int *const scale = priv->quadrature_scale + id;
unsigned int *const synchronous_mode = priv->synchronous_mode + id;
const int base_offset = priv->base + 2 * id + 1;
unsigned long irqflags;
unsigned int mode_cfg;
unsigned int idr_cfg;
spin_lock_irqsave(&priv->lock, irqflags);
mode_cfg = priv->count_mode[id] << 1;
idr_cfg = priv->index_polarity[id] << 1;
if (function == COUNTER_FUNCTION_PULSE_DIRECTION) {
*quadrature_mode = 0;
/* Quadrature scaling only available in quadrature mode */
*scale = 0;
/* Synchronous function not supported in non-quadrature mode */
if (*synchronous_mode) {
*synchronous_mode = 0;
/* Disable synchronous function mode */
outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
}
} else {
*quadrature_mode = 1;
switch (function) {
case COUNTER_FUNCTION_QUADRATURE_X1_A:
*scale = 0;
mode_cfg |= QUAD8_CMR_QUADRATURE_X1;
break;
case COUNTER_FUNCTION_QUADRATURE_X2_A:
*scale = 1;
mode_cfg |= QUAD8_CMR_QUADRATURE_X2;
break;
case COUNTER_FUNCTION_QUADRATURE_X4:
*scale = 2;
mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
break;
default:
/* should never reach this path */
spin_unlock_irqrestore(&priv->lock, irqflags);
return -EINVAL;
}
}
/* Load mode configuration to Counter Mode Register */
outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
spin_unlock_irqrestore(&priv->lock, irqflags);
return 0;
}