drivers/media/rc/img-ir/img-ir-raw.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/rc/img-ir/img-ir-raw.c
Extension
.c
Size
3951 bytes
Lines
153
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

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * ImgTec IR Raw Decoder found in PowerDown Controller.
 *
 * Copyright 2010-2014 Imagination Technologies Ltd.
 *
 * This ties into the input subsystem using the RC-core in raw mode. Raw IR
 * signal edges are reported and decoded by generic software decoders.
 */

#include <linux/spinlock.h>
#include <media/rc-core.h>
#include "img-ir.h"

#define ECHO_TIMEOUT_MS 150	/* ms between echos */

/* must be called with priv->lock held */
static void img_ir_refresh_raw(struct img_ir_priv *priv, u32 irq_status)
{
	struct img_ir_priv_raw *raw = &priv->raw;
	struct rc_dev *rc_dev = priv->raw.rdev;
	int multiple;
	u32 ir_status;

	/* find whether both rise and fall was detected */
	multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE);
	/*
	 * If so, we need to see if the level has actually changed.
	 * If it's just noise that we didn't have time to process,
	 * there's no point reporting it.
	 */
	ir_status = img_ir_read(priv, IMG_IR_STATUS) & IMG_IR_IRRXD;
	if (multiple && ir_status == raw->last_status)
		return;
	raw->last_status = ir_status;

	/* report the edge to the IR raw decoders */
	if (ir_status) /* low */
		ir_raw_event_store_edge(rc_dev, false);
	else /* high */
		ir_raw_event_store_edge(rc_dev, true);
	ir_raw_event_handle(rc_dev);
}

/* called with priv->lock held */
void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
{
	struct img_ir_priv_raw *raw = &priv->raw;

	/* check not removing */
	if (!raw->rdev)
		return;

	img_ir_refresh_raw(priv, irq_status);

	/* start / push back the echo timer */
	mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS));
}

/*
 * Echo timer callback function.
 * The raw decoders expect to get a final sample even if there are no edges, in
 * order to be assured of the final space. If there are no edges for a certain
 * time we use this timer to emit a final sample to satisfy them.
 */
static void img_ir_echo_timer(struct timer_list *t)
{
	struct img_ir_priv *priv = timer_container_of(priv, t, raw.timer);

	spin_lock_irq(&priv->lock);

	/* check not removing */
	if (priv->raw.rdev)
		/*
		 * It's safe to pass irq_status=0 since it's only used to check
		 * for double edges.
		 */
		img_ir_refresh_raw(priv, 0);

	spin_unlock_irq(&priv->lock);
}

void img_ir_setup_raw(struct img_ir_priv *priv)
{
	u32 irq_en;

	if (!priv->raw.rdev)
		return;

	/* clear and enable edge interrupts */

Annotation

Implementation Notes