/* initialize the hardware */ static void it8709_init_hardware(struct ite_dev *dev) { ite_dbg("%s called", __func__); /* disable all the interrupts */ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), IT85_C0IER); /* program the baud rate divisor */ it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR); it8709_wr(dev, (ITE_BAUDRATE_DIVISOR >> 8) & 0xff, IT85_C0BDHR); /* program the C0MSTCR register defaults */ it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL | IT85_FIFOCLR | IT85_RESET)) | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR); /* program the C0RCR register defaults */ it8709_wr(dev, (it8709_rr(dev, IT85_C0RCR) & ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | IT85_RXACT | IT85_RXDCR)) | ITE_RXDCR_DEFAULT, IT85_C0RCR); /* program the C0TCR register defaults */ it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR) & ~(IT85_TXMPM | IT85_TXMPW)) | IT85_TXRLE | IT85_TXENDF | IT85_TXMPM_DEFAULT | IT85_TXMPW_DEFAULT, IT85_C0TCR); /* program the carrier parameters */ ite_set_carrier_params(dev); }
/* initialize the hardware */ static void it87_init_hardware(struct ite_dev *dev) { ite_dbg("%s called", __func__); /* enable just the baud rate divisor register, disabling all the interrupts at the same time */ outb((inb(dev->cir_addr + IT87_IER) & ~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE)) | IT87_BR, dev->cir_addr + IT87_IER); /* write out the baud rate divisor */ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT87_BDLR); outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT87_BDHR); /* disable the baud rate divisor register again */ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_BR, dev->cir_addr + IT87_IER); /* program the RCR register defaults */ outb(ITE_RXDCR_DEFAULT, dev->cir_addr + IT87_RCR); /* program the TCR1 register */ outb(IT87_TXMPM_DEFAULT | IT87_TXENDF | IT87_TXRLE | IT87_FIFOTL_DEFAULT | IT87_FIFOCLR, dev->cir_addr + IT87_TCR1); /* program the carrier parameters */ ite_set_carrier_params(dev); }
static void it87_init_hardware(struct ite_dev *dev) { ite_dbg("%s called", __func__); outb((inb(dev->cir_addr + IT87_IER) & ~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE)) | IT87_BR, dev->cir_addr + IT87_IER); outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT87_BDLR); outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT87_BDHR); outb(inb(dev->cir_addr + IT87_IER) & ~IT87_BR, dev->cir_addr + IT87_IER); outb(ITE_RXDCR_DEFAULT, dev->cir_addr + IT87_RCR); outb(IT87_TXMPM_DEFAULT | IT87_TXENDF | IT87_TXRLE | IT87_FIFOTL_DEFAULT | IT87_FIFOCLR, dev->cir_addr + IT87_TCR1); ite_set_carrier_params(dev); }
static void it8709_init_hardware(struct ite_dev *dev) { ite_dbg("%s called", __func__); it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), IT85_C0IER); it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR); it8709_wr(dev, (ITE_BAUDRATE_DIVISOR >> 8) & 0xff, IT85_C0BDHR); it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL | IT85_FIFOCLR | IT85_RESET)) | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR); it8709_wr(dev, (it8709_rr(dev, IT85_C0RCR) & ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | IT85_RXACT | IT85_RXDCR)) | ITE_RXDCR_DEFAULT, IT85_C0RCR); it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR) & ~(IT85_TXMPM | IT85_TXMPW)) | IT85_TXRLE | IT85_TXENDF | IT85_TXMPM_DEFAULT | IT85_TXMPW_DEFAULT, IT85_C0TCR); ite_set_carrier_params(dev); }
/* set the tx duty cycle by controlling the pulse width */ static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle) { unsigned long flags; struct ite_dev *dev = rcdev->priv; spin_lock_irqsave(&dev->lock, flags); dev->params.tx_duty_cycle = duty_cycle; ite_set_carrier_params(dev); spin_unlock_irqrestore(&dev->lock, flags); return 0; }
/* set the rx carrier freq range, guess it's in Hz... */ static int ite_set_rx_carrier_range(struct rc_dev *rcdev, u32 carrier_low, u32 carrier_high) { unsigned long flags; struct ite_dev *dev = rcdev->priv; spin_lock_irqsave(&dev->lock, flags); dev->params.rx_low_carrier_freq = carrier_low; dev->params.rx_high_carrier_freq = carrier_high; ite_set_carrier_params(dev); spin_unlock_irqrestore(&dev->lock, flags); return 0; }
static void it8708_init_hardware(struct ite_dev *dev) { ite_dbg("%s called", __func__); outb(inb(dev->cir_addr + IT8708_C0IER) & ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), dev->cir_addr + IT8708_C0IER); outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE, dev->cir_addr + IT8708_BANKSEL); outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT8708_C0BDLR); outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT8708_C0BDHR); outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE, dev->cir_addr + IT8708_BANKSEL); outb((inb(dev->cir_addr + IT8708_C0MSTCR) & ~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL | IT85_FIFOCLR | IT85_RESET)) | IT85_FIFOTL_DEFAULT, dev->cir_addr + IT8708_C0MSTCR); outb((inb(dev->cir_addr + IT8708_C0RCR) & ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | IT85_RXACT | IT85_RXDCR)) | ITE_RXDCR_DEFAULT, dev->cir_addr + IT8708_C0RCR); outb((inb(dev->cir_addr + IT8708_C0TCR) & ~(IT85_TXMPM | IT85_TXMPW)) |IT85_TXRLE | IT85_TXENDF | IT85_TXMPM_DEFAULT | IT85_TXMPW_DEFAULT, dev->cir_addr + IT8708_C0TCR); ite_set_carrier_params(dev); }
/* transmit out IR pulses; what you get here is a batch of alternating * pulse/space/pulse/space lengths that we should write out completely through * the FIFO, blocking on a full FIFO */ static int ite_tx_ir(struct rc_dev *rcdev, unsigned *txbuf, unsigned n) { unsigned long flags; struct ite_dev *dev = rcdev->priv; bool is_pulse = false; int remaining_us, fifo_avail, fifo_remaining, last_idx = 0; int max_rle_us, next_rle_us; int ret = n; u8 last_sent[ITE_TX_FIFO_LEN]; u8 val; ite_dbg("%s called", __func__); /* clear the array just in case */ memset(last_sent, 0, ARRAY_SIZE(last_sent)); spin_lock_irqsave(&dev->lock, flags); /* let everybody know we're now transmitting */ dev->transmitting = true; /* and set the carrier values for transmission */ ite_set_carrier_params(dev); /* calculate how much time we can send in one byte */ max_rle_us = (ITE_BAUDRATE_DIVISOR * dev->params.sample_period * ITE_TX_MAX_RLE) / 1000; /* disable the receiver */ dev->params.disable_rx(dev); /* this is where we'll begin filling in the FIFO, until it's full. * then we'll just activate the interrupt, wait for it to wake us up * again, disable it, continue filling the FIFO... until everything * has been pushed out */ fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); while (n > 0 && dev->in_use) { /* transmit the next sample */ is_pulse = !is_pulse; remaining_us = *(txbuf++); n--; ite_dbg("%s: %ld", ((is_pulse) ? "pulse" : "space"), (long int) remaining_us); /* repeat while the pulse is non-zero length */ while (remaining_us > 0 && dev->in_use) { if (remaining_us > max_rle_us) next_rle_us = max_rle_us; else next_rle_us = remaining_us; remaining_us -= next_rle_us; /* check what's the length we have to pump out */ val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us; /* put it into the sent buffer */ last_sent[last_idx++] = val; last_idx &= (ITE_TX_FIFO_LEN); /* encode it for 7 bits */ val = (val - 1) & ITE_TX_RLE_MASK; /* take into account pulse/space prefix */ if (is_pulse) val |= ITE_TX_PULSE; else val |= ITE_TX_SPACE; /* * if we get to 0 available, read again, just in case * some other slot got freed */ if (fifo_avail <= 0) fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); /* if it's still full */ if (fifo_avail <= 0) { /* enable the tx interrupt */ dev->params. enable_tx_interrupt(dev); /* drop the spinlock */ spin_unlock_irqrestore(&dev->lock, flags); /* wait for the FIFO to empty enough */ wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8); /* get the spinlock again */ spin_lock_irqsave(&dev->lock, flags); /* disable the tx interrupt again. */ dev->params. disable_tx_interrupt(dev); } /* now send the byte through the FIFO */ dev->params.put_tx_byte(dev, val); fifo_avail--; } } /* wait and don't return until the whole FIFO has been sent out; * otherwise we could configure the RX carrier params instead of the * TX ones while the transmission is still being performed! */ fifo_remaining = dev->params.get_tx_used_slots(dev); remaining_us = 0; while (fifo_remaining > 0) { fifo_remaining--; last_idx--; last_idx &= (ITE_TX_FIFO_LEN - 1); remaining_us += last_sent[last_idx]; } remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE); /* drop the spinlock while we sleep */ spin_unlock_irqrestore(&dev->lock, flags); /* sleep remaining_us microseconds */ mdelay(DIV_ROUND_UP(remaining_us, 1000)); /* reacquire the spinlock */ spin_lock_irqsave(&dev->lock, flags); /* now we're not transmitting anymore */ dev->transmitting = false; /* and set the carrier values for reception */ ite_set_carrier_params(dev); /* reenable the receiver */ if (dev->in_use) dev->params.enable_rx(dev); /* notify transmission end */ wake_up_interruptible(&dev->tx_ended); spin_unlock_irqrestore(&dev->lock, flags); return ret; }
static int ite_tx_ir(struct rc_dev *rcdev, unsigned *txbuf, unsigned n) { unsigned long flags; struct ite_dev *dev = rcdev->priv; bool is_pulse = false; int remaining_us, fifo_avail, fifo_remaining, last_idx = 0; int max_rle_us, next_rle_us; int ret = n; u8 last_sent[ITE_TX_FIFO_LEN]; u8 val; ite_dbg("%s called", __func__); memset(last_sent, 0, ARRAY_SIZE(last_sent)); spin_lock_irqsave(&dev->lock, flags); dev->transmitting = true; ite_set_carrier_params(dev); max_rle_us = (ITE_BAUDRATE_DIVISOR * dev->params.sample_period * ITE_TX_MAX_RLE) / 1000; dev->params.disable_rx(dev); fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); while (n > 0 && dev->in_use) { is_pulse = !is_pulse; remaining_us = *(txbuf++); n--; ite_dbg("%s: %ld", ((is_pulse) ? "pulse" : "space"), (long int) remaining_us); while (remaining_us > 0 && dev->in_use) { if (remaining_us > max_rle_us) next_rle_us = max_rle_us; else next_rle_us = remaining_us; remaining_us -= next_rle_us; val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us; last_sent[last_idx++] = val; last_idx &= (ITE_TX_FIFO_LEN); val = (val - 1) & ITE_TX_RLE_MASK; if (is_pulse) val |= ITE_TX_PULSE; else val |= ITE_TX_SPACE; if (fifo_avail <= 0) fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); if (fifo_avail <= 0) { dev->params. enable_tx_interrupt(dev); spin_unlock_irqrestore(&dev->lock, flags); wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8); spin_lock_irqsave(&dev->lock, flags); dev->params. disable_tx_interrupt(dev); } dev->params.put_tx_byte(dev, val); fifo_avail--; } } fifo_remaining = dev->params.get_tx_used_slots(dev); remaining_us = 0; while (fifo_remaining > 0) { fifo_remaining--; last_idx--; last_idx &= (ITE_TX_FIFO_LEN - 1); remaining_us += last_sent[last_idx]; } remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE); spin_unlock_irqrestore(&dev->lock, flags); mdelay(DIV_ROUND_UP(remaining_us, 1000)); spin_lock_irqsave(&dev->lock, flags); dev->transmitting = false; ite_set_carrier_params(dev); if (dev->in_use) dev->params.enable_rx(dev); wake_up_interruptible(&dev->tx_ended); spin_unlock_irqrestore(&dev->lock, flags); return ret; }