drivers/media/platform/microchip/microchip-isc-scaler.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/microchip/microchip-isc-scaler.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/microchip/microchip-isc-scaler.c
Extension
.c
Size
7776 bytes
Lines
272
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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-only
/*
 * Microchip Image Sensor Controller (ISC) Scaler entity support
 *
 * Copyright (C) 2022 Microchip Technology, Inc.
 *
 * Author: Eugen Hristev <eugen.hristev@microchip.com>
 *
 */

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

#include "microchip-isc-regs.h"
#include "microchip-isc.h"

static void isc_scaler_prepare_fmt(struct v4l2_mbus_framefmt *framefmt)
{
	framefmt->colorspace = V4L2_COLORSPACE_SRGB;
	framefmt->field = V4L2_FIELD_NONE;
	framefmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
	framefmt->quantization = V4L2_QUANTIZATION_DEFAULT;
	framefmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
};

static int isc_scaler_get_fmt(struct v4l2_subdev *sd,
			      struct v4l2_subdev_state *sd_state,
			      struct v4l2_subdev_format *format)
{
	struct isc_device *isc = container_of(sd, struct isc_device, scaler_sd);
	struct v4l2_mbus_framefmt *v4l2_try_fmt;

	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
		v4l2_try_fmt = v4l2_subdev_state_get_format(sd_state,
							    format->pad);
		format->format = *v4l2_try_fmt;

		return 0;
	}

	format->format = isc->scaler_format[format->pad];

	return 0;
}

static int isc_scaler_set_fmt(struct v4l2_subdev *sd,
			      struct v4l2_subdev_state *sd_state,
			      struct v4l2_subdev_format *req_fmt)
{
	struct isc_device *isc = container_of(sd, struct isc_device, scaler_sd);
	struct v4l2_mbus_framefmt *v4l2_try_fmt;
	struct isc_format *fmt;
	unsigned int i;

	/* Source format is fixed, we cannot change it */
	if (req_fmt->pad == ISC_SCALER_PAD_SOURCE) {
		req_fmt->format = isc->scaler_format[ISC_SCALER_PAD_SOURCE];
		return 0;
	}

	/* There is no limit on the frame size on the sink pad */
	v4l_bound_align_image(&req_fmt->format.width, 16, UINT_MAX, 0,
			      &req_fmt->format.height, 16, UINT_MAX, 0, 0);

	isc_scaler_prepare_fmt(&req_fmt->format);

	fmt = isc_find_format_by_code(isc, req_fmt->format.code, &i);

	if (!fmt)
		fmt = &isc->formats_list[0];

	req_fmt->format.code = fmt->mbus_code;

	if (req_fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
		v4l2_try_fmt = v4l2_subdev_state_get_format(sd_state,
							    req_fmt->pad);
		*v4l2_try_fmt = req_fmt->format;
		/* Trying on the sink pad makes the source pad change too */
		v4l2_try_fmt = v4l2_subdev_state_get_format(sd_state,
							    ISC_SCALER_PAD_SOURCE);
		*v4l2_try_fmt = req_fmt->format;

		v4l_bound_align_image(&v4l2_try_fmt->width,
				      16, isc->max_width, 0,
				      &v4l2_try_fmt->height,
				      16, isc->max_height, 0, 0);
		/* if we are just trying, we are done */
		return 0;

Annotation

Implementation Notes