drivers/media/platform/arm/mali-c55/mali-c55-tpg.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/arm/mali-c55/mali-c55-tpg.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/arm/mali-c55/mali-c55-tpg.c
Extension
.c
Size
12783 bytes
Lines
439
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
/*
 * ARM Mali-C55 ISP Driver - Test pattern generator
 *
 * Copyright (C) 2025 Ideas on Board Oy
 */

#include <linux/minmax.h>
#include <linux/pm_runtime.h>
#include <linux/string.h>

#include <media/media-entity.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-subdev.h>

#include "mali-c55-common.h"
#include "mali-c55-registers.h"

#define MALI_C55_TPG_SRC_PAD			0
#define MALI_C55_TPG_FIXED_HBLANK		0x20
#define MALI_C55_TPG_DEFAULT_MIN_VBLANK		66
#define MALI_C55_TPG_DEFAULT_DEF_VBLANK		626
#define MALI_C55_TPG_MAX_VBLANK			0xffff
#define MALI_C55_TPG_PIXEL_RATE			100000000

static const char * const mali_c55_tpg_test_pattern_menu[] = {
	"Flat field",
	"Horizontal gradient",
	"Vertical gradient",
	"Vertical bars",
	"Arbitrary rectangle",
	"White frame on black field"
};

static const u32 mali_c55_tpg_mbus_codes[] = {
	MEDIA_BUS_FMT_SRGGB20_1X20,
	MEDIA_BUS_FMT_RGB202020_1X60,
};

static void mali_c55_tpg_update_vblank(struct mali_c55_tpg *tpg,
				       struct v4l2_mbus_framefmt *format)
{
	unsigned int def_vblank;
	unsigned int min_vblank;
	unsigned int hts;
	int tgt_fps;

	hts = format->width + MALI_C55_TPG_FIXED_HBLANK;

	/*
	 * The ISP has minimum vertical blanking requirements that must be
	 * adhered to by the TPG. The minimum is a function of the Iridix blocks
	 * clocking requirements and the width of the image and horizontal
	 * blanking, but if we assume the worst case iVariance and sVariance
	 * values then it boils down to the below (plus one to the numerator to
	 * ensure the answer is rounded up).
	 */
	min_vblank = 15 + (120501 / hts);

	/*
	 * We need to set a sensible default vblank for whatever format height
	 * we happen to be given from set_fmt(). This function just targets
	 * an even multiple of 15fps. If we can't get 15fps, let's target 5fps.
	 * If we can't get 5fps we'll take whatever the minimum vblank gives us.
	 */
	tgt_fps = MALI_C55_TPG_PIXEL_RATE / hts / (format->height + min_vblank);

	if (tgt_fps < 5)
		def_vblank = min_vblank;
	else
		def_vblank = (MALI_C55_TPG_PIXEL_RATE / hts
			   / max(rounddown(tgt_fps, 15), 5)) - format->height;

	def_vblank = ALIGN_DOWN(def_vblank, 2);

	__v4l2_ctrl_modify_range(tpg->ctrls.vblank, min_vblank,
				 MALI_C55_TPG_MAX_VBLANK, 1, def_vblank);
	__v4l2_ctrl_s_ctrl(tpg->ctrls.vblank, def_vblank);
}

static int mali_c55_tpg_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct mali_c55_tpg *tpg = container_of(ctrl->handler,
						struct mali_c55_tpg,
						ctrls.handler);
	struct mali_c55 *mali_c55 = container_of(tpg, struct mali_c55, tpg);
	int ret = 0;

	if (!pm_runtime_get_if_in_use(mali_c55->dev))

Annotation

Implementation Notes