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

Commit 5e360978 authored by Tomi Valkeinen's avatar Tomi Valkeinen
Browse files

Merge branch 'work/fifomerge'

parents 6e2a14d2 e0e405b9
Loading
Loading
Loading
Loading
+191 −30
Original line number Original line Diff line number Diff line
@@ -105,6 +105,9 @@ static struct {
	struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
	struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
	struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
	struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];


	bool fifo_merge_dirty;
	bool fifo_merge;

	bool irq_enabled;
	bool irq_enabled;
} dss_data;
} dss_data;


@@ -585,11 +588,40 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
	}
	}
}
}


static void dss_write_regs_common(void)
{
	const int num_mgrs = omap_dss_get_num_overlay_managers();
	int i;

	if (!dss_data.fifo_merge_dirty)
		return;

	for (i = 0; i < num_mgrs; ++i) {
		struct omap_overlay_manager *mgr;
		struct mgr_priv_data *mp;

		mgr = omap_dss_get_overlay_manager(i);
		mp = get_mgr_priv(mgr);

		if (mp->enabled) {
			if (dss_data.fifo_merge_dirty) {
				dispc_enable_fifomerge(dss_data.fifo_merge);
				dss_data.fifo_merge_dirty = false;
			}

			if (mp->updating)
				mp->shadow_info_dirty = true;
		}
	}
}

static void dss_write_regs(void)
static void dss_write_regs(void)
{
{
	const int num_mgrs = omap_dss_get_num_overlay_managers();
	const int num_mgrs = omap_dss_get_num_overlay_managers();
	int i;
	int i;


	dss_write_regs_common();

	for (i = 0; i < num_mgrs; ++i) {
	for (i = 0; i < num_mgrs; ++i) {
		struct omap_overlay_manager *mgr;
		struct omap_overlay_manager *mgr;
		struct mgr_priv_data *mp;
		struct mgr_priv_data *mp;
@@ -659,6 +691,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)


	dss_mgr_write_regs(mgr);
	dss_mgr_write_regs(mgr);


	dss_write_regs_common();

	mp->updating = true;
	mp->updating = true;


	if (!dss_data.irq_enabled && need_isr())
	if (!dss_data.irq_enabled && need_isr())
@@ -859,11 +893,20 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
	op->extra_info_dirty = true;
	op->extra_info_dirty = true;
}
}


static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
static void dss_apply_fifo_merge(bool use_fifo_merge)
{
	if (dss_data.fifo_merge == use_fifo_merge)
		return;

	dss_data.fifo_merge = use_fifo_merge;
	dss_data.fifo_merge_dirty = true;
}

static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
		bool use_fifo_merge)
{
{
	struct ovl_priv_data *op = get_ovl_priv(ovl);
	struct ovl_priv_data *op = get_ovl_priv(ovl);
	struct omap_dss_device *dssdev;
	struct omap_dss_device *dssdev;
	u32 size, burst_size;
	u32 fifo_low, fifo_high;
	u32 fifo_low, fifo_high;


	if (!op->enabled && !op->enabling)
	if (!op->enabled && !op->enabling)
@@ -871,33 +914,14 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)


	dssdev = ovl->manager->device;
	dssdev = ovl->manager->device;


	size = dispc_ovl_get_fifo_size(ovl->id);
	dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,

			use_fifo_merge);
	burst_size = dispc_ovl_get_burst_size(ovl->id);

	switch (dssdev->type) {
	case OMAP_DISPLAY_TYPE_DPI:
	case OMAP_DISPLAY_TYPE_DBI:
	case OMAP_DISPLAY_TYPE_SDI:
	case OMAP_DISPLAY_TYPE_VENC:
	case OMAP_DISPLAY_TYPE_HDMI:
		default_get_overlay_fifo_thresholds(ovl->id, size,
				burst_size, &fifo_low, &fifo_high);
		break;
#ifdef CONFIG_OMAP2_DSS_DSI
	case OMAP_DISPLAY_TYPE_DSI:
		dsi_get_overlay_fifo_thresholds(ovl->id, size,
				burst_size, &fifo_low, &fifo_high);
		break;
#endif
	default:
		BUG();
	}


	dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
	dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
}
}


static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
		bool use_fifo_merge)
{
{
	struct omap_overlay *ovl;
	struct omap_overlay *ovl;
	struct mgr_priv_data *mp;
	struct mgr_priv_data *mp;
@@ -908,10 +932,10 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
		return;
		return;


	list_for_each_entry(ovl, &mgr->overlays, list)
	list_for_each_entry(ovl, &mgr->overlays, list)
		dss_ovl_setup_fifo(ovl);
		dss_ovl_setup_fifo(ovl, use_fifo_merge);
}
}


static void dss_setup_fifos(void)
static void dss_setup_fifos(bool use_fifo_merge)
{
{
	const int num_mgrs = omap_dss_get_num_overlay_managers();
	const int num_mgrs = omap_dss_get_num_overlay_managers();
	struct omap_overlay_manager *mgr;
	struct omap_overlay_manager *mgr;
@@ -919,15 +943,91 @@ static void dss_setup_fifos(void)


	for (i = 0; i < num_mgrs; ++i) {
	for (i = 0; i < num_mgrs; ++i) {
		mgr = omap_dss_get_overlay_manager(i);
		mgr = omap_dss_get_overlay_manager(i);
		dss_mgr_setup_fifos(mgr);
		dss_mgr_setup_fifos(mgr, use_fifo_merge);
	}
	}
}
}


static int get_num_used_managers(void)
{
	const int num_mgrs = omap_dss_get_num_overlay_managers();
	struct omap_overlay_manager *mgr;
	struct mgr_priv_data *mp;
	int i;
	int enabled_mgrs;

	enabled_mgrs = 0;

	for (i = 0; i < num_mgrs; ++i) {
		mgr = omap_dss_get_overlay_manager(i);
		mp = get_mgr_priv(mgr);

		if (!mp->enabled)
			continue;

		enabled_mgrs++;
	}

	return enabled_mgrs;
}

static int get_num_used_overlays(void)
{
	const int num_ovls = omap_dss_get_num_overlays();
	struct omap_overlay *ovl;
	struct ovl_priv_data *op;
	struct mgr_priv_data *mp;
	int i;
	int enabled_ovls;

	enabled_ovls = 0;

	for (i = 0; i < num_ovls; ++i) {
		ovl = omap_dss_get_overlay(i);
		op = get_ovl_priv(ovl);

		if (!op->enabled && !op->enabling)
			continue;

		mp = get_mgr_priv(ovl->manager);

		if (!mp->enabled)
			continue;

		enabled_ovls++;
	}

	return enabled_ovls;
}

static bool get_use_fifo_merge(void)
{
	int enabled_mgrs = get_num_used_managers();
	int enabled_ovls = get_num_used_overlays();

	if (!dss_has_feature(FEAT_FIFO_MERGE))
		return false;

	/*
	 * In theory the only requirement for fifomerge is enabled_ovls <= 1.
	 * However, if we have two managers enabled and set/unset the fifomerge,
	 * we need to set the GO bits in particular sequence for the managers,
	 * and wait in between.
	 *
	 * This is rather difficult as new apply calls can happen at any time,
	 * so we simplify the problem by requiring also that enabled_mgrs <= 1.
	 * In practice this shouldn't matter, because when only one overlay is
	 * enabled, most likely only one output is enabled.
	 */

	return enabled_mgrs <= 1 && enabled_ovls <= 1;
}

int dss_mgr_enable(struct omap_overlay_manager *mgr)
int dss_mgr_enable(struct omap_overlay_manager *mgr)
{
{
	struct mgr_priv_data *mp = get_mgr_priv(mgr);
	struct mgr_priv_data *mp = get_mgr_priv(mgr);
	unsigned long flags;
	unsigned long flags;
	int r;
	int r;
	bool fifo_merge;


	mutex_lock(&apply_lock);
	mutex_lock(&apply_lock);


@@ -945,11 +1045,23 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
		goto err;
		goto err;
	}
	}


	dss_setup_fifos();
	/* step 1: setup fifos/fifomerge before enabling the manager */

	fifo_merge = get_use_fifo_merge();
	dss_setup_fifos(fifo_merge);
	dss_apply_fifo_merge(fifo_merge);


	dss_write_regs();
	dss_write_regs();
	dss_set_go_bits();
	dss_set_go_bits();


	spin_unlock_irqrestore(&data_lock, flags);

	/* wait until fifo config is in */
	wait_pending_extra_info_updates();

	/* step 2: enable the manager */
	spin_lock_irqsave(&data_lock, flags);

	if (!mgr_manual_update(mgr))
	if (!mgr_manual_update(mgr))
		mp->updating = true;
		mp->updating = true;


@@ -974,6 +1086,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
{
{
	struct mgr_priv_data *mp = get_mgr_priv(mgr);
	struct mgr_priv_data *mp = get_mgr_priv(mgr);
	unsigned long flags;
	unsigned long flags;
	bool fifo_merge;


	mutex_lock(&apply_lock);
	mutex_lock(&apply_lock);


@@ -988,8 +1101,16 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
	mp->updating = false;
	mp->updating = false;
	mp->enabled = false;
	mp->enabled = false;


	fifo_merge = get_use_fifo_merge();
	dss_setup_fifos(fifo_merge);
	dss_apply_fifo_merge(fifo_merge);

	dss_write_regs();
	dss_set_go_bits();

	spin_unlock_irqrestore(&data_lock, flags);
	spin_unlock_irqrestore(&data_lock, flags);


	wait_pending_extra_info_updates();
out:
out:
	mutex_unlock(&apply_lock);
	mutex_unlock(&apply_lock);
}
}
@@ -1241,6 +1362,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
{
{
	struct ovl_priv_data *op = get_ovl_priv(ovl);
	struct ovl_priv_data *op = get_ovl_priv(ovl);
	unsigned long flags;
	unsigned long flags;
	bool fifo_merge;
	int r;
	int r;


	mutex_lock(&apply_lock);
	mutex_lock(&apply_lock);
@@ -1266,7 +1388,22 @@ int dss_ovl_enable(struct omap_overlay *ovl)
		goto err2;
		goto err2;
	}
	}


	dss_setup_fifos();
	/* step 1: configure fifos/fifomerge for currently enabled ovls */

	fifo_merge = get_use_fifo_merge();
	dss_setup_fifos(fifo_merge);
	dss_apply_fifo_merge(fifo_merge);

	dss_write_regs();
	dss_set_go_bits();

	spin_unlock_irqrestore(&data_lock, flags);

	/* wait for fifo configs to go in */
	wait_pending_extra_info_updates();

	/* step 2: enable the overlay */
	spin_lock_irqsave(&data_lock, flags);


	op->enabling = false;
	op->enabling = false;
	dss_apply_ovl_enable(ovl, true);
	dss_apply_ovl_enable(ovl, true);
@@ -1276,6 +1413,9 @@ int dss_ovl_enable(struct omap_overlay *ovl)


	spin_unlock_irqrestore(&data_lock, flags);
	spin_unlock_irqrestore(&data_lock, flags);


	/* wait for overlay to be enabled */
	wait_pending_extra_info_updates();

	mutex_unlock(&apply_lock);
	mutex_unlock(&apply_lock);


	return 0;
	return 0;
@@ -1291,6 +1431,7 @@ int dss_ovl_disable(struct omap_overlay *ovl)
{
{
	struct ovl_priv_data *op = get_ovl_priv(ovl);
	struct ovl_priv_data *op = get_ovl_priv(ovl);
	unsigned long flags;
	unsigned long flags;
	bool fifo_merge;
	int r;
	int r;


	mutex_lock(&apply_lock);
	mutex_lock(&apply_lock);
@@ -1305,14 +1446,34 @@ int dss_ovl_disable(struct omap_overlay *ovl)
		goto err;
		goto err;
	}
	}


	/* step 1: disable the overlay */
	spin_lock_irqsave(&data_lock, flags);
	spin_lock_irqsave(&data_lock, flags);


	dss_apply_ovl_enable(ovl, false);
	dss_apply_ovl_enable(ovl, false);

	dss_write_regs();
	dss_set_go_bits();

	spin_unlock_irqrestore(&data_lock, flags);

	/* wait for the overlay to be disabled */
	wait_pending_extra_info_updates();

	/* step 2: configure fifos/fifomerge */
	spin_lock_irqsave(&data_lock, flags);

	fifo_merge = get_use_fifo_merge();
	dss_setup_fifos(fifo_merge);
	dss_apply_fifo_merge(fifo_merge);

	dss_write_regs();
	dss_write_regs();
	dss_set_go_bits();
	dss_set_go_bits();


	spin_unlock_irqrestore(&data_lock, flags);
	spin_unlock_irqrestore(&data_lock, flags);


	/* wait for fifo config to go in */
	wait_pending_extra_info_updates();

	mutex_unlock(&apply_lock);
	mutex_unlock(&apply_lock);


	return 0;
	return 0;
+49 −6
Original line number Original line Diff line number Diff line
@@ -909,7 +909,7 @@ static void dispc_configure_burst_sizes(void)
		dispc_ovl_set_burst_size(i, burst_size);
		dispc_ovl_set_burst_size(i, burst_size);
}
}


u32 dispc_ovl_get_burst_size(enum omap_plane plane)
static u32 dispc_ovl_get_burst_size(enum omap_plane plane)
{
{
	unsigned unit = dss_feat_get_burst_size_unit();
	unsigned unit = dss_feat_get_burst_size_unit();
	/* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
	/* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
@@ -1018,7 +1018,7 @@ static void dispc_read_plane_fifo_sizes(void)
	}
	}
}
}


u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
{
{
	return dispc.fifo_size[plane];
	return dispc.fifo_size[plane];
}
}
@@ -1039,13 +1039,13 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);


	DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
	DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n",
			plane,
			plane,
			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
				lo_start, lo_end),
				lo_start, lo_end) * unit,
			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
				hi_start, hi_end),
				hi_start, hi_end) * unit,
			low, high);
			low * unit, high * unit);


	dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
	dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
			FLD_VAL(high, hi_start, hi_end) |
			FLD_VAL(high, hi_start, hi_end) |
@@ -1054,10 +1054,53 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)


void dispc_enable_fifomerge(bool enable)
void dispc_enable_fifomerge(bool enable)
{
{
	if (!dss_has_feature(FEAT_FIFO_MERGE)) {
		WARN_ON(enable);
		return;
	}

	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
}
}


void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge)
{
	/*
	 * All sizes are in bytes. Both the buffer and burst are made of
	 * buffer_units, and the fifo thresholds must be buffer_unit aligned.
	 */

	unsigned buf_unit = dss_feat_get_buffer_size_unit();
	unsigned ovl_fifo_size, total_fifo_size, burst_size;
	int i;

	burst_size = dispc_ovl_get_burst_size(plane);
	ovl_fifo_size = dispc_ovl_get_fifo_size(plane);

	if (use_fifomerge) {
		total_fifo_size = 0;
		for (i = 0; i < omap_dss_get_num_overlays(); ++i)
			total_fifo_size += dispc_ovl_get_fifo_size(i);
	} else {
		total_fifo_size = ovl_fifo_size;
	}

	/*
	 * We use the same low threshold for both fifomerge and non-fifomerge
	 * cases, but for fifomerge we calculate the high threshold using the
	 * combined fifo size
	 */

	if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
		*fifo_low = ovl_fifo_size - burst_size * 2;
		*fifo_high = total_fifo_size - burst_size;
	} else {
		*fifo_low = ovl_fifo_size - burst_size;
		*fifo_high = total_fifo_size - buf_unit;
	}
}

static void dispc_ovl_set_fir(enum omap_plane plane,
static void dispc_ovl_set_fir(enum omap_plane plane,
				int hinc, int vinc,
				int hinc, int vinc,
				enum omap_color_component color_comp)
				enum omap_color_component color_comp)
+0 −10
Original line number Original line Diff line number Diff line
@@ -279,16 +279,6 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
}
}
EXPORT_SYMBOL(omapdss_default_get_resolution);
EXPORT_SYMBOL(omapdss_default_get_resolution);


void default_get_overlay_fifo_thresholds(enum omap_plane plane,
		u32 fifo_size, u32 burst_size,
		u32 *fifo_low, u32 *fifo_high)
{
	unsigned buf_unit = dss_feat_get_buffer_size_unit();

	*fifo_high = fifo_size - buf_unit;
	*fifo_low = fifo_size - burst_size;
}

int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
{
{
	switch (dssdev->type) {
	switch (dssdev->type) {
+0 −8
Original line number Original line Diff line number Diff line
@@ -4524,14 +4524,6 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
}
}
EXPORT_SYMBOL(omapdss_dsi_enable_te);
EXPORT_SYMBOL(omapdss_dsi_enable_te);


void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
		u32 fifo_size, u32 burst_size,
		u32 *fifo_low, u32 *fifo_high)
{
	*fifo_high = fifo_size - burst_size;
	*fifo_low = fifo_size - burst_size * 2;
}

int dsi_init_display(struct omap_dss_device *dssdev)
int dsi_init_display(struct omap_dss_device *dssdev)
{
{
	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+2 −8
Original line number Original line Diff line number Diff line
@@ -202,9 +202,6 @@ void dss_uninit_device(struct platform_device *pdev,
		struct omap_dss_device *dssdev);
		struct omap_dss_device *dssdev);
bool dss_use_replication(struct omap_dss_device *dssdev,
bool dss_use_replication(struct omap_dss_device *dssdev,
		enum omap_color_mode mode);
		enum omap_color_mode mode);
void default_get_overlay_fifo_thresholds(enum omap_plane plane,
		u32 fifo_size, u32 burst_size,
		u32 *fifo_low, u32 *fifo_high);


/* manager */
/* manager */
int dss_init_overlay_managers(struct platform_device *pdev);
int dss_init_overlay_managers(struct platform_device *pdev);
@@ -313,9 +310,6 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
		bool enable_hsdiv);
		bool enable_hsdiv);
void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
		u32 fifo_size, u32 burst_size,
		u32 *fifo_low, u32 *fifo_high);
void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
struct platform_device *dsi_get_dsidev_from_id(int module);
struct platform_device *dsi_get_dsidev_from_id(int module);
@@ -429,8 +423,8 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,




void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
u32 dispc_ovl_get_burst_size(enum omap_plane plane);
		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge);
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
		bool ilace, bool replication);
		bool ilace, bool replication);
int dispc_ovl_enable(enum omap_plane plane, bool enable);
int dispc_ovl_enable(enum omap_plane plane, bool enable);
Loading