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); }