int esc_mods_tegra_dc_config_possible(struct file *fp,
				struct MODS_TEGRA_DC_CONFIG_POSSIBLE *args)
{
	int i;
	struct tegra_dc *dc = tegra_dc_get_dc(args->head);
	struct tegra_dc_win *dc_wins[DC_N_WINDOWS];
#ifndef CONFIG_TEGRA_ISOMGR
	struct clk *emc_clk = 0;
	unsigned long max_bandwidth = 0;
	unsigned long current_emc_freq = 0;
	unsigned long max_available_bandwidth = 0;
#else
	int ret = -EINVAL;
#endif

	LOG_ENT();

	BUG_ON(args->win_num > DC_N_WINDOWS);

	if (!dc) {
		LOG_EXT();
		return -EINVAL;
	}

	for (i = 0; i < args->win_num; i++) {
		int idx = args->windows[i].index;

		if (args->windows[i].flags &
			MODS_TEGRA_DC_WINDOW_FLAG_ENABLED) {
			mods_tegra_dc_set_windowattr_basic(&dc->tmp_wins[idx],
							  &args->windows[i]);
		} else {
			dc->tmp_wins[idx].flags = 0;
		}
		dc_wins[i] = &dc->tmp_wins[idx];
		mods_debug_printk(DEBUG_TEGRADC,
			"esc_mods_tegra_dc_config_possible head %u, "
			"using index %d for window %d\n",
			args->head, i, idx);
	}

	mods_debug_printk(DEBUG_TEGRADC,
		"esc_mods_tegra_dc_config_possible head %u, "
		"dc->mode.pclk %u\n",
		args->head, dc->mode.pclk);

#ifndef CONFIG_TEGRA_ISOMGR
	max_bandwidth = tegra_dc_get_bandwidth(dc_wins, args->win_num);

	emc_clk = clk_get_sys("tegra_emc", "emc");
	if (IS_ERR(emc_clk)) {
		mods_debug_printk(DEBUG_TEGRADC,
		"esc_mods_tegra_dc_config_possible "
		"invalid clock specified when fetching EMC clock\n");
	} else {
		current_emc_freq = clk_get_rate(emc_clk);
		current_emc_freq /= 1000;
		max_available_bandwidth =
			8 * tegra_emc_freq_req_to_bw(current_emc_freq);
		max_available_bandwidth = (max_available_bandwidth / 100) * 50;
	}

	mods_debug_printk(DEBUG_TEGRADC,
		"esc_mods_tegra_dc_config_possible bandwidth needed = %lu,"
		" bandwidth available = %lu\n",
		max_bandwidth, max_available_bandwidth);

	args->possible = (max_bandwidth <= max_available_bandwidth);
#else
	ret = tegra_dc_bandwidth_negotiate_bw(dc, dc_wins, args->win_num);
	args->possible = (ret == 0);
#endif
	for (i = 0; i < args->win_num; i++) {
		args->windows[i].bandwidth = dc_wins[i]->new_bandwidth;
		mods_debug_printk(DEBUG_TEGRADC,
			"esc_mods_tegra_dc_config_possible head %u, "
			"window %d bandwidth %d\n",
			args->head, dc_wins[i]->idx, dc_wins[i]->new_bandwidth);
	}

	LOG_EXT();
	return 0;
}
int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode)
{
	unsigned long val;
	unsigned long rate;
	unsigned long div;
	unsigned long pclk;

	unsigned long v_back_porch;
	unsigned long v_front_porch;
	unsigned long v_sync_width;
	unsigned long v_active;

	v_back_porch = mode->v_back_porch;
	v_front_porch = mode->v_front_porch;
	v_sync_width = mode->v_sync_width;
	v_active = mode->v_active;

	if (mode->vmode == FB_VMODE_INTERLACED) {
		v_back_porch /= 2;
		v_front_porch /= 2;
		v_sync_width /= 2;
		v_active /= 2;
	}

	print_mode(dc, mode, __func__);

	/* use default EMC rate when switching modes */
#ifdef CONFIG_TEGRA_ISOMGR
	dc->new_bw_kbps = tegra_dc_calc_min_bandwidth(dc);
#else
	dc->new_bw_kbps = tegra_emc_freq_req_to_bw(
		tegra_dc_get_default_emc_clk_rate(dc) / 1000);
#endif
	tegra_dc_program_bandwidth(dc, true);

	tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
	tegra_dc_writel(dc, mode->h_ref_to_sync | (mode->v_ref_to_sync << 16),
			DC_DISP_REF_TO_SYNC);
	tegra_dc_writel(dc, mode->h_sync_width | (v_sync_width << 16),
			DC_DISP_SYNC_WIDTH);
	if ((dc->out->type == TEGRA_DC_OUT_DP) ||
		(dc->out->type == TEGRA_DC_OUT_LVDS)) {
		tegra_dc_writel(dc, mode->h_back_porch |
			((v_back_porch - mode->v_ref_to_sync) << 16),
			DC_DISP_BACK_PORCH);
		tegra_dc_writel(dc, mode->h_front_porch |
			((v_front_porch + mode->v_ref_to_sync) << 16),
			DC_DISP_FRONT_PORCH);
	} else {
		tegra_dc_writel(dc, mode->h_back_porch |
			(v_back_porch << 16),
			DC_DISP_BACK_PORCH);
		tegra_dc_writel(dc, mode->h_front_porch |
			(v_front_porch << 16),
			DC_DISP_FRONT_PORCH);
	}
	tegra_dc_writel(dc, mode->h_active | (v_active << 16),
			DC_DISP_DISP_ACTIVE);

#if defined(CONFIG_TEGRA_DC_INTERLACE)
	if (mode->vmode == FB_VMODE_INTERLACED)
		tegra_dc_writel(dc, INTERLACE_MODE_ENABLE |
			INTERLACE_START_FIELD_1
			| INTERLACE_STATUS_FIELD_1,
			DC_DISP_INTERLACE_CONTROL);
	else
		tegra_dc_writel(dc, INTERLACE_MODE_DISABLE,
			DC_DISP_INTERLACE_CONTROL);

	if (mode->vmode == FB_VMODE_INTERLACED) {
		tegra_dc_writel(dc, (mode->h_ref_to_sync |
			((mode->h_sync_width + mode->h_back_porch +
			mode->h_active + mode->h_front_porch) >> 1)
			<< 16), DC_DISP_INTERLACE_FIELD2_REF_TO_SYNC);
		tegra_dc_writel(dc, mode->h_sync_width |
			(v_sync_width << 16),
			DC_DISP_INTERLACE_FIELD2_SYNC_WIDTH);
		tegra_dc_writel(dc, mode->h_back_porch |
			((v_back_porch + 1) << 16),
			DC_DISP_INTERLACE_FIELD2_BACK_PORCH);
		tegra_dc_writel(dc, mode->h_active |
			(v_active << 16),
			DC_DISP_INTERLACE_FIELD2_DISP_ACTIVE);
		tegra_dc_writel(dc, mode->h_front_porch |
			(v_front_porch << 16),
			DC_DISP_INTERLACE_FIELD2_FRONT_PORCH);
	}