Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f778dad3 authored by Tomi Valkeinen's avatar Tomi Valkeinen
Browse files

Merge omapdss scaling fixes

parents a9bd32a8 a9fad688
Loading
Loading
Loading
Loading
+99 −15
Original line number Diff line number Diff line
@@ -96,6 +96,9 @@ struct dispc_features {
	bool mstandby_workaround:1;

	bool set_max_preload:1;

	/* PIXEL_INC is not added to the last pixel of a line */
	bool last_pixel_inc_missing:1;
};

#define DISPC_MAX_NR_FIFOS 5
@@ -1742,6 +1745,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
			row_repeat = false;
	}

	/*
	 * OMAP4/5 Errata i631:
	 * NV12 in 1D mode must use ROTATION=1. Otherwise DSS will fetch extra
	 * rows beyond the framebuffer, which may cause OCP error.
	 */
	if (color_mode == OMAP_DSS_COLOR_NV12 &&
			rotation_type != OMAP_DSS_ROT_TILER)
		vidrot = 1;

	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
	if (dss_has_feature(FEAT_ROWREPEATENABLE))
		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
@@ -2155,7 +2167,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk,
	if (height > out_height) {
		unsigned int ppl = mgr_timings->x_res;

		tmp = pclk * height * out_width;
		tmp = (u64)pclk * height * out_width;
		do_div(tmp, 2 * out_height * ppl);
		core_clk = tmp;

@@ -2163,14 +2175,14 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk,
			if (ppl == out_width)
				return 0;

			tmp = pclk * (height - 2 * out_height) * out_width;
			tmp = (u64)pclk * (height - 2 * out_height) * out_width;
			do_div(tmp, 2 * out_height * (ppl - out_width));
			core_clk = max_t(u32, core_clk, tmp);
		}
	}

	if (width > out_width) {
		tmp = pclk * width;
		tmp = (u64)pclk * width;
		do_div(tmp, out_width);
		core_clk = max_t(u32, core_clk, tmp);

@@ -2268,6 +2280,11 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
		}
	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);

	if (error) {
		DSSERR("failed to find scaling settings\n");
		return -EINVAL;
	}

	if (in_width > maxsinglelinewidth) {
		DSSERR("Cannot scale max input width exceeded");
		return -EINVAL;
@@ -2284,7 +2301,6 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
{
	int error;
	u16 in_width, in_height;
	int min_factor = min(*decim_x, *decim_y);
	const int maxsinglelinewidth =
			dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);

@@ -2318,20 +2334,32 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
		error = (error || in_width > maxsinglelinewidth * 2 ||
			(in_width > maxsinglelinewidth && *five_taps) ||
			!*core_clk || *core_clk > dispc_core_clk_rate());
		if (error) {
			if (*decim_x == *decim_y) {
				*decim_x = min_factor;
				++*decim_y;

		if (!error) {
			/* verify that we're inside the limits of scaler */
			if (in_width / 4 > out_width)
					error = 1;

			if (*five_taps) {
				if (in_height / 4 > out_height)
					error = 1;
			} else {
				swap(*decim_x, *decim_y);
				if (*decim_x < *decim_y)
					++*decim_x;
				if (in_height / 2 > out_height)
					error = 1;
			}
		}

		if (error)
			++*decim_y;
	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);

	if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
				height, out_width, out_height, *five_taps)) {
	if (error) {
		DSSERR("failed to find scaling settings\n");
		return -EINVAL;
	}

	if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width,
				in_height, out_width, out_height, *five_taps)) {
			DSSERR("horizontal timing too tight\n");
			return -EINVAL;
	}
@@ -2391,6 +2419,9 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
	return 0;
}

#define DIV_FRAC(dividend, divisor) \
	((dividend) * 100 / (divisor) - ((dividend) / (divisor) * 100))

static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
		enum omap_overlay_caps caps,
		const struct omap_video_timings *mgr_timings,
@@ -2450,8 +2481,19 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
	if (ret)
		return ret;

	DSSDBG("required core clk rate = %lu Hz\n", core_clk);
	DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
	DSSDBG("%dx%d -> %dx%d (%d.%02d x %d.%02d), decim %dx%d %dx%d (%d.%02d x %d.%02d), taps %d, req clk %lu, cur clk %lu\n",
		width, height,
		out_width, out_height,
		out_width / width, DIV_FRAC(out_width, width),
		out_height / height, DIV_FRAC(out_height, height),

		decim_x, decim_y,
		width / decim_x, height / decim_y,
		out_width / (width / decim_x), DIV_FRAC(out_width, width / decim_x),
		out_height / (height / decim_y), DIV_FRAC(out_height, height / decim_y),

		*five_taps ? 5 : 3,
		core_clk, dispc_core_clk_rate());

	if (!core_clk || core_clk > dispc_core_clk_rate()) {
		DSSERR("failed to set up scaling, "
@@ -2534,6 +2576,21 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
	if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER)
		return -EINVAL;

	switch (color_mode) {
	case OMAP_DSS_COLOR_YUV2:
	case OMAP_DSS_COLOR_UYVY:
	case OMAP_DSS_COLOR_NV12:
		if (in_width & 1) {
			DSSERR("input width %d is not even for YUV format\n",
				in_width);
			return -EINVAL;
		}
		break;

	default:
		break;
	}

	out_width = out_width == 0 ? width : out_width;
	out_height = out_height == 0 ? height : out_height;

@@ -2564,6 +2621,27 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
	in_width = in_width / x_predecim;
	in_height = in_height / y_predecim;

	if (x_predecim > 1 || y_predecim > 1)
		DSSDBG("predecimation %d x %x, new input size %d x %d\n",
			x_predecim, y_predecim, in_width, in_height);

	switch (color_mode) {
	case OMAP_DSS_COLOR_YUV2:
	case OMAP_DSS_COLOR_UYVY:
	case OMAP_DSS_COLOR_NV12:
		if (in_width & 1) {
			DSSDBG("predecimated input width is not even for YUV format\n");
			DSSDBG("adjusting input width %d -> %d\n",
				in_width, in_width & ~1);

			in_width &= ~1;
		}
		break;

	default:
		break;
	}

	if (color_mode == OMAP_DSS_COLOR_YUV2 ||
			color_mode == OMAP_DSS_COLOR_UYVY ||
			color_mode == OMAP_DSS_COLOR_NV12)
@@ -2633,6 +2711,9 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
		dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
	}

	if (dispc.feat->last_pixel_inc_missing)
		row_inc += pix_inc - 1;

	dispc_ovl_set_row_inc(plane, row_inc);
	dispc_ovl_set_pix_inc(plane, pix_inc);

@@ -3710,6 +3791,7 @@ static const struct dispc_features omap24xx_dispc_feats = {
	.num_fifos		=	3,
	.no_framedone_tv	=	true,
	.set_max_preload	=	false,
	.last_pixel_inc_missing	=	true,
};

static const struct dispc_features omap34xx_rev1_0_dispc_feats = {
@@ -3730,6 +3812,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = {
	.num_fifos		=	3,
	.no_framedone_tv	=	true,
	.set_max_preload	=	false,
	.last_pixel_inc_missing	=	true,
};

static const struct dispc_features omap34xx_rev3_0_dispc_feats = {
@@ -3750,6 +3833,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = {
	.num_fifos		=	3,
	.no_framedone_tv	=	true,
	.set_max_preload	=	false,
	.last_pixel_inc_missing	=	true,
};

static const struct dispc_features omap44xx_dispc_feats = {
+1 −1
Original line number Diff line number Diff line
@@ -230,9 +230,9 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
err_mgr_enable:
	hdmi_wp_video_stop(&hdmi.wp);
err_vid_enable:
err_phy_cfg:
	hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
err_phy_pwr:
err_phy_cfg:
err_pll_cfg:
	dss_pll_disable(&hdmi.pll.pll);
err_pll_enable:
+16 −0
Original line number Diff line number Diff line
@@ -110,7 +110,23 @@ int hdmi_wp_video_start(struct hdmi_wp_data *wp)

void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
{
	int i;

	hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE);

	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);

	for (i = 0; i < 50; ++i) {
		u32 v;

		msleep(20);

		v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW);
		if (v & HDMI_IRQ_VIDEO_FRAME_DONE)
			return;
	}

	DSSERR("no HDMI FRAMEDONE when disabling output\n");
}

void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,