drivers/media/rc/ir-spi.c

Source file repositories/reference/linux-study-clean/drivers/media/rc/ir-spi.c

File Facts

System
Linux kernel
Corpus path
drivers/media/rc/ir-spi.c
Extension
.c
Size
4379 bytes
Lines
196
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

struct ir_spi_data {
	u32 freq;
	bool negated;

	u16 pulse;
	u16 space;

	struct rc_dev *rc;
	struct spi_device *spi;
	struct regulator *regulator;
};

static int ir_spi_tx(struct rc_dev *dev, unsigned int *buffer, unsigned int count)
{
	int i;
	int ret;
	unsigned int len = 0;
	struct ir_spi_data *idata = dev->priv;
	struct spi_transfer xfer;
	u16 *tx_buf;

	/* convert the pulse/space signal to raw binary signal */
	for (i = 0; i < count; i++) {
		buffer[i] = DIV_ROUND_CLOSEST_ULL((u64)buffer[i] * idata->freq,
						  1000000);
		len += buffer[i];
	}

	tx_buf = kmalloc_array(len, sizeof(*tx_buf), GFP_KERNEL);
	if (!tx_buf)
		return -ENOMEM;

	len = 0;
	for (i = 0; i < count; i++) {
		int j;
		u16 val;

		/*
		 * The first value in buffer is a pulse, so that 0, 2, 4, ...
		 * contain a pulse duration. On the contrary, 1, 3, 5, ...
		 * contain a space duration.
		 */
		val = (i % 2) ? idata->space : idata->pulse;
		for (j = 0; j < buffer[i]; j++)
			tx_buf[len++] = val;
	}

	memset(&xfer, 0, sizeof(xfer));

	xfer.speed_hz = idata->freq * IR_SPI_BITS_PER_PULSE;
	xfer.len = len * sizeof(*tx_buf);
	xfer.tx_buf = tx_buf;

	ret = regulator_enable(idata->regulator);
	if (ret)
		goto err_free_tx_buf;

	ret = spi_sync_transfer(idata->spi, &xfer, 1);
	if (ret)
		dev_err(&idata->spi->dev, "unable to deliver the signal\n");

	regulator_disable(idata->regulator);

err_free_tx_buf:

	kfree(tx_buf);

	return ret ? ret : count;
}

static int ir_spi_set_tx_carrier(struct rc_dev *dev, u32 carrier)
{
	struct ir_spi_data *idata = dev->priv;

	if (!carrier)
		return -EINVAL;

	if (carrier > idata->spi->max_speed_hz / IR_SPI_BITS_PER_PULSE)
		return -EINVAL;

	idata->freq = carrier;

	return 0;
}

static int ir_spi_set_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
{
	struct ir_spi_data *idata = dev->priv;
	int bits = (duty_cycle * 15) / 100;

Annotation

Implementation Notes