drivers/media/rc/pwm-ir-tx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/rc/pwm-ir-tx.c
Extension
.c
Size
4577 bytes
Lines
201
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 pwm_ir {
	struct pwm_device *pwm;
	struct hrtimer timer;
	struct completion tx_done;
	struct pwm_state *state;
	u32 carrier;
	u32 duty_cycle;
	const unsigned int *txbuf;
	unsigned int txbuf_len;
	unsigned int txbuf_index;
};

static const struct of_device_id pwm_ir_of_match[] = {
	{ .compatible = "pwm-ir-tx", },
	{ .compatible = "nokia,n900-ir" },
	{ },
};
MODULE_DEVICE_TABLE(of, pwm_ir_of_match);

static int pwm_ir_set_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
{
	struct pwm_ir *pwm_ir = dev->priv;

	pwm_ir->duty_cycle = duty_cycle;

	return 0;
}

static int pwm_ir_set_carrier(struct rc_dev *dev, u32 carrier)
{
	struct pwm_ir *pwm_ir = dev->priv;

	if (!carrier)
		return -EINVAL;

	pwm_ir->carrier = carrier;

	return 0;
}

static int pwm_ir_tx_sleep(struct rc_dev *dev, unsigned int *txbuf,
			   unsigned int count)
{
	struct pwm_ir *pwm_ir = dev->priv;
	struct pwm_device *pwm = pwm_ir->pwm;
	struct pwm_state state;
	int i;
	ktime_t edge;
	long delta;

	pwm_init_state(pwm, &state);

	state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier);
	pwm_set_relative_duty_cycle(&state, pwm_ir->duty_cycle, 100);

	edge = ktime_get();

	for (i = 0; i < count; i++) {
		state.enabled = !(i % 2);
		pwm_apply_might_sleep(pwm, &state);

		edge = ktime_add_us(edge, txbuf[i]);
		delta = ktime_us_delta(edge, ktime_get());
		if (delta > 0)
			usleep_range(delta, delta + 10);
	}

	state.enabled = false;
	pwm_apply_might_sleep(pwm, &state);

	return count;
}

static int pwm_ir_tx_atomic(struct rc_dev *dev, unsigned int *txbuf,
			    unsigned int count)
{
	struct pwm_ir *pwm_ir = dev->priv;
	struct pwm_device *pwm = pwm_ir->pwm;
	struct pwm_state state;

	pwm_init_state(pwm, &state);

	state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier);
	pwm_set_relative_duty_cycle(&state, pwm_ir->duty_cycle, 100);

	pwm_ir->txbuf = txbuf;
	pwm_ir->txbuf_len = count;
	pwm_ir->txbuf_index = 0;
	pwm_ir->state = &state;

Annotation

Implementation Notes