drivers/staging/media/imx/imx-media-fim.c

Source file repositories/reference/linux-study-clean/drivers/staging/media/imx/imx-media-fim.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/media/imx/imx-media-fim.c
Extension
.c
Size
10812 bytes
Lines
432
Domain
Driver Families
Bucket
drivers/staging
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 imx_media_fim {
	/* the owning subdev of this fim instance */
	struct v4l2_subdev *sd;

	/* FIM's control handler */
	struct v4l2_ctrl_handler ctrl_handler;

	/* control clusters */
	struct v4l2_ctrl  *ctrl[FIM_NUM_CONTROLS];
	struct v4l2_ctrl  *icap_ctrl[FIM_NUM_ICAP_CONTROLS];

	spinlock_t        lock; /* protect control values */

	/* current control values */
	bool              enabled;
	int               num_avg;
	int               num_skip;
	unsigned long     tolerance_min; /* usec */
	unsigned long     tolerance_max; /* usec */
	/* input capture method of measuring FI */
	int               icap_channel;
	int               icap_flags;

	int               counter;
	ktime_t		  last_ts;
	unsigned long     sum;       /* usec */
	unsigned long     nominal;   /* usec */

	struct completion icap_first_event;
	bool              stream_on;
};

static bool icap_enabled(struct imx_media_fim *fim)
{
	return fim->icap_flags != IRQ_TYPE_NONE;
}

static void update_fim_nominal(struct imx_media_fim *fim,
			       const struct v4l2_fract *fi)
{
	if (fi->denominator == 0) {
		dev_dbg(fim->sd->dev, "no frame interval, FIM disabled\n");
		fim->enabled = false;
		return;
	}

	fim->nominal = DIV_ROUND_CLOSEST_ULL(1000000ULL * (u64)fi->numerator,
					     fi->denominator);

	dev_dbg(fim->sd->dev, "FI=%lu usec\n", fim->nominal);
}

static void reset_fim(struct imx_media_fim *fim, bool curval)
{
	struct v4l2_ctrl *icap_chan = fim->icap_ctrl[FIM_CL_ICAP_CHANNEL];
	struct v4l2_ctrl *icap_edge = fim->icap_ctrl[FIM_CL_ICAP_EDGE];
	struct v4l2_ctrl *en = fim->ctrl[FIM_CL_ENABLE];
	struct v4l2_ctrl *num = fim->ctrl[FIM_CL_NUM];
	struct v4l2_ctrl *skip = fim->ctrl[FIM_CL_NUM_SKIP];
	struct v4l2_ctrl *tol_min = fim->ctrl[FIM_CL_TOLERANCE_MIN];
	struct v4l2_ctrl *tol_max = fim->ctrl[FIM_CL_TOLERANCE_MAX];

	if (curval) {
		fim->enabled = en->cur.val;
		fim->icap_flags = icap_edge->cur.val;
		fim->icap_channel = icap_chan->cur.val;
		fim->num_avg = num->cur.val;
		fim->num_skip = skip->cur.val;
		fim->tolerance_min = tol_min->cur.val;
		fim->tolerance_max = tol_max->cur.val;
	} else {
		fim->enabled = en->val;
		fim->icap_flags = icap_edge->val;
		fim->icap_channel = icap_chan->val;
		fim->num_avg = num->val;
		fim->num_skip = skip->val;
		fim->tolerance_min = tol_min->val;
		fim->tolerance_max = tol_max->val;
	}

	/* disable tolerance range if max <= min */
	if (fim->tolerance_max <= fim->tolerance_min)
		fim->tolerance_max = 0;

	/* num_skip must be >= 1 if input capture not used */
	if (!icap_enabled(fim))
		fim->num_skip = max_t(int, fim->num_skip, 1);

	fim->counter = -fim->num_skip;
	fim->sum = 0;

Annotation

Implementation Notes