static inline void wbcir_set_irqmask(struct wbcir_data *data, u8 irqmask) { if (data->irqmask == irqmask) return; wbcir_select_bank(data, WBCIR_BANK_0); outb(irqmask, data->sbase + WBCIR_REG_SP3_IER); data->irqmask = irqmask; }
static int wbcir_set_carrier_report(struct rc_dev *dev, int enable) { struct wbcir_data *data = dev->priv; unsigned long flags; spin_lock_irqsave(&data->spinlock, flags); if (data->carrier_report_enabled == enable) { spin_unlock_irqrestore(&data->spinlock, flags); return 0; } data->pulse_duration = 0; wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R, WBCIR_CNTR_EN | WBCIR_CNTR_R); if (enable && data->dev->idle) wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_EN, WBCIR_CNTR_EN | WBCIR_CNTR_R); /* Set a higher sampling resolution if carrier reports are enabled */ wbcir_select_bank(data, WBCIR_BANK_2); data->dev->rx_resolution = US_TO_NS(enable ? 2 : 10); outb(enable ? 0x03 : 0x0f, data->sbase + WBCIR_REG_SP3_BGDL); outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); /* Enable oversampling if carrier reports are enabled */ wbcir_select_bank(data, WBCIR_BANK_7); wbcir_set_bits(data->sbase + WBCIR_REG_SP3_RCCFG, enable ? WBCIR_RX_T_OV : 0, WBCIR_RX_T_OV); data->carrier_report_enabled = enable; spin_unlock_irqrestore(&data->spinlock, flags); return 0; }
static int wbcir_txcarrier(struct rc_dev *dev, u32 carrier) { struct wbcir_data *data = dev->priv; unsigned long flags; u8 val; u32 freq; freq = DIV_ROUND_CLOSEST(carrier, 1000); if (freq < 30 || freq > 60) return -EINVAL; switch (freq) { case 58: case 59: case 60: val = freq - 58; freq *= 1000; break; case 57: val = freq - 27; freq = 56900; break; default: val = freq - 27; freq *= 1000; break; } spin_lock_irqsave(&data->spinlock, flags); if (data->txstate != WBCIR_TXSTATE_INACTIVE) { spin_unlock_irqrestore(&data->spinlock, flags); return -EBUSY; } if (data->txcarrier != freq) { wbcir_select_bank(data, WBCIR_BANK_7); wbcir_set_bits(data->sbase + WBCIR_REG_SP3_IRTXMC, val, 0x1F); data->txcarrier = freq; } spin_unlock_irqrestore(&data->spinlock, flags); return 0; }
static irqreturn_t wbcir_irq_handler(int irqno, void *cookie) { struct pnp_dev *device = cookie; struct wbcir_data *data = pnp_get_drvdata(device); unsigned long flags; u8 status; spin_lock_irqsave(&data->spinlock, flags); wbcir_select_bank(data, WBCIR_BANK_0); status = inb(data->sbase + WBCIR_REG_SP3_EIR); status &= data->irqmask; if (!status) { spin_unlock_irqrestore(&data->spinlock, flags); return IRQ_NONE; } if (status & WBCIR_IRQ_ERR) { /* RX overflow? (read clears bit) */ if (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_OVERRUN) { data->rxstate = WBCIR_RXSTATE_ERROR; ir_raw_event_reset(data->dev); } /* TX underflow? */ if (inb(data->sbase + WBCIR_REG_SP3_ASCR) & WBCIR_TX_UNDERRUN) data->txstate = WBCIR_TXSTATE_ERROR; } if (status & WBCIR_IRQ_RX) wbcir_irq_rx(data, device); if (status & (WBCIR_IRQ_TX_LOW | WBCIR_IRQ_TX_EMPTY)) wbcir_irq_tx(data); spin_unlock_irqrestore(&data->spinlock, flags); return IRQ_HANDLED; }