drivers/media/rc/ite-cir.c

Source file repositories/reference/linux-study-clean/drivers/media/rc/ite-cir.c

File Facts

System
Linux kernel
Corpus path
drivers/media/rc/ite-cir.c
Extension
.c
Size
41654 bytes
Lines
1511
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (next_zero < size) {
			next_one = find_next_bit_le(ldata, size, next_zero + 1);
			ev.pulse = true;
			ev.duration = ITE_BITS_TO_US(next_one - next_zero,
						     sample_period);
			ir_raw_event_store_with_filter(dev->rdev, &ev);
		} else
			next_one = size;
	}

	ir_raw_event_handle(dev->rdev);

	dev_dbg(&dev->rdev->dev, "decoded %d bytes\n", length);
}

/* set all the rx/tx carrier parameters; this must be called with the device
 * spinlock held */
static void ite_set_carrier_params(struct ite_dev *dev)
{
	unsigned int freq, low_freq, high_freq;
	int allowance;
	bool use_demodulator;
	bool for_tx = dev->transmitting;

	if (for_tx) {
		/* we don't need no stinking calculations */
		freq = dev->tx_carrier_freq;
		allowance = ITE_RXDCR_DEFAULT;
		use_demodulator = false;
	} else {
		low_freq = dev->rx_low_carrier_freq;
		high_freq = dev->rx_high_carrier_freq;

		if (low_freq == 0) {
			/* don't demodulate */
			freq = ITE_DEFAULT_CARRIER_FREQ;
			allowance = ITE_RXDCR_DEFAULT;
			use_demodulator = false;
		} else {
			/* calculate the middle freq */
			freq = (low_freq + high_freq) / 2;

			/* calculate the allowance */
			allowance =
			    DIV_ROUND_CLOSEST(10000 * (high_freq - low_freq),
					      ITE_RXDCR_PER_10000_STEP
					      * (high_freq + low_freq));

			if (allowance < 1)
				allowance = 1;

			if (allowance > ITE_RXDCR_MAX)
				allowance = ITE_RXDCR_MAX;

			use_demodulator = true;
		}
	}

	/* set the carrier parameters in a device-dependent way */
	dev->params->set_carrier_params(dev, ite_is_high_carrier_freq(freq),
		 use_demodulator, ite_get_carrier_freq_bits(freq), allowance,
		 ite_get_pulse_width_bits(freq, dev->tx_duty_cycle));
}

/* interrupt service routine for incoming and outgoing CIR data */
static irqreturn_t ite_cir_isr(int irq, void *data)
{
	struct ite_dev *dev = data;
	irqreturn_t ret = IRQ_RETVAL(IRQ_NONE);
	u8 rx_buf[ITE_RX_FIFO_LEN];
	int rx_bytes;
	int iflags;

	/* grab the spinlock */
	spin_lock(&dev->lock);

	/* read the interrupt flags */
	iflags = dev->params->get_irq_causes(dev);

	/* Check for RX overflow */
	if (iflags & ITE_IRQ_RX_FIFO_OVERRUN) {
		dev_warn(&dev->rdev->dev, "receive overflow\n");
		ir_raw_event_overflow(dev->rdev);
	}

	/* check for the receive interrupt */
	if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) {
		/* read the FIFO bytes */
		rx_bytes = dev->params->get_rx_bytes(dev, rx_buf,
						    ITE_RX_FIFO_LEN);

Annotation

Implementation Notes