drivers/staging/media/ipu3/ipu3-css-params.c

Source file repositories/reference/linux-study-clean/drivers/staging/media/ipu3/ipu3-css-params.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/media/ipu3/ipu3-css-params.c
Extension
.c
Size
95458 bytes
Lines
2964
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 imgu_css_scaler_info {
	unsigned int phase_step;	/* Same for luma/chroma */
	int exp_shift;

	unsigned int phase_init;	/* luma/chroma dependent */
	int pad_left;
	int pad_right;
	int crop_left;
	int crop_top;
};

static unsigned int imgu_css_scaler_get_exp(unsigned int counter,
					    unsigned int divider)
{
	int i = fls(divider) - fls(counter);

	if (i <= 0)
		return 0;

	if (divider >> i < counter)
		i = i - 1;

	return i;
}

/* Set up the CSS scaler look up table */
static void
imgu_css_scaler_setup_lut(unsigned int taps, unsigned int input_width,
			  unsigned int output_width, int phase_step_correction,
			  const int *coeffs, unsigned int coeffs_size,
			  s8 coeff_lut[], struct imgu_css_scaler_info *info)
{
	int tap, phase, phase_sum_left, phase_sum_right;
	int exponent = imgu_css_scaler_get_exp(output_width, input_width);
	int mantissa = (1 << exponent) * output_width;
	unsigned int phase_step, phase_taps;

	if (input_width == output_width) {
		for (phase = 0; phase < IMGU_SCALER_PHASES; phase++) {
			phase_taps = phase * IMGU_SCALER_FILTER_TAPS;
			for (tap = 0; tap < taps; tap++)
				coeff_lut[phase_taps + tap] = 0;
		}

		info->phase_step = IMGU_SCALER_PHASES *
			(1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF);
		info->exp_shift = 0;
		info->pad_left = 0;
		info->pad_right = 0;
		info->phase_init = 0;
		info->crop_left = 0;
		info->crop_top = 0;
		return;
	}

	for (phase = 0; phase < IMGU_SCALER_PHASES; phase++) {
		phase_taps = phase * IMGU_SCALER_FILTER_TAPS;
		for (tap = 0; tap < taps; tap++) {
			/* flip table to for convolution reverse indexing */
			s64 coeff = coeffs[coeffs_size -
				((tap * (coeffs_size / taps)) + phase) - 1];
			coeff *= mantissa;
			coeff = div64_long(coeff, input_width);

			/* Add +"0.5" */
			coeff += 1 << (IMGU_SCALER_COEFF_BITS - 1);
			coeff >>= IMGU_SCALER_COEFF_BITS;
			coeff_lut[phase_taps + tap] = coeff;
		}
	}

	phase_step = IMGU_SCALER_PHASES *
			(1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF) *
			output_width / input_width;
	phase_step += phase_step_correction;
	phase_sum_left = (taps / 2 * IMGU_SCALER_PHASES *
			(1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF)) -
			(1 << (IMGU_SCALER_PHASE_COUNTER_PREC_REF - 1));
	phase_sum_right = (taps / 2 * IMGU_SCALER_PHASES *
			(1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF)) +
			(1 << (IMGU_SCALER_PHASE_COUNTER_PREC_REF - 1));

	info->exp_shift = IMGU_SCALER_MAX_EXPONENT_SHIFT - exponent;
	info->pad_left = (phase_sum_left % phase_step == 0) ?
		phase_sum_left / phase_step - 1 : phase_sum_left / phase_step;
	info->pad_right = (phase_sum_right % phase_step == 0) ?
		phase_sum_right / phase_step - 1 : phase_sum_right / phase_step;
	info->phase_init = phase_sum_left - phase_step * info->pad_left;
	info->phase_step = phase_step;
	info->crop_left = taps - 1;

Annotation

Implementation Notes