From 1df65fce9afbcfb7f7d9b10b237b76ac1146b762 Mon Sep 17 00:00:00 2001 From: Santosh Reddy Galma Date: Wed, 5 Oct 2016 08:57:05 +0530 Subject: video: tegra: read and use display hw data runtime currently, TEGRA_MAX_DC and DC_N_WINDOWS macros are used to represent number of display heads, windows based on chip config. This change does following to support multiple SOCs on a single binary. - use tegra_dc_hw_data data structure and populate it based on the chip compatible field. - expose API's to read number of display heads, windows for other modules. - use the above data structure fields or API's in place of macros in display drivers and other modules like fb,ext,screen capture. - remove TEGRA_MAX_DC macro usage completely. - make runtime alloc for data structures which were using static alloc previously based on macros at compile time. - code re-organization and cleanup with above change. TDS-1305 TDS-1301 TDS-1408 TDS-1307 Change-Id: Ief70aa7fdac420a7a8375fe91dfae58116d3eb6e Signed-off-by: Santosh Reddy Galma Reviewed-on: http://git-master/r/1231688 Reviewed-by: Ujwal Patel Tested-by: Ujwal Patel Reviewed-by: svccoveritychecker --- drivers/video/tegra/dc/bandwidth.c | 37 ++++++---- drivers/video/tegra/dc/dc.c | 124 +++++++++++++++++++--------------- drivers/video/tegra/dc/dc_priv_defs.h | 7 +- drivers/video/tegra/dc/ext/dev.c | 49 ++++++++------ drivers/video/tegra/dc/ext/scrncapt.c | 53 ++++++++++----- drivers/video/tegra/dc/lut.c | 5 +- drivers/video/tegra/dc/sor.c | 8 ++- drivers/video/tegra/dc/window.c | 12 ++-- drivers/video/tegra/fb.c | 4 +- include/video/tegra_dc_ext.h | 2 - include/video/tegra_dc_ext_kernel.h | 8 +-- 11 files changed, 179 insertions(+), 130 deletions(-) diff --git a/drivers/video/tegra/dc/bandwidth.c b/drivers/video/tegra/dc/bandwidth.c index 6b3aa0242..a33c2cd60 100644 --- a/drivers/video/tegra/dc/bandwidth.c +++ b/drivers/video/tegra/dc/bandwidth.c @@ -1,7 +1,7 @@ /* * drivers/video/tegra/dc/bandwidth.c * - * Copyright (c) 2010-2016, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2017, NVIDIA CORPORATION, All rights reserved. * * Author: Jon Mayo * @@ -40,7 +40,6 @@ static int use_dynamic_emc = 1; module_param_named(use_dynamic_emc, use_dynamic_emc, int, S_IRUGO | S_IWUSR); -static unsigned int tegra_dcs_total_bw[TEGRA_MAX_DC] = {0}; DEFINE_MUTEX(tegra_dcs_total_bw_lock); /* windows A, B, C for first and second display */ @@ -73,7 +72,8 @@ static unsigned int num_active_internal_wins(struct tegra_dc *dc) unsigned int num_active_internal_wins = 0; int i = 0; - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *curr_win = tegra_dc_get_window(dc, i); enum tegra_la_id curr_win_la_id = la_id_tab[dc->ctrl_num][curr_win->idx]; @@ -93,7 +93,8 @@ static unsigned int num_active_external_wins(struct tegra_dc *dc) unsigned int num_active_external_wins = 0; int i = 0; - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *curr_win = tegra_dc_get_window(dc, i); enum tegra_la_id curr_win_la_id = la_id_tab[dc->ctrl_num][curr_win->idx]; @@ -379,7 +380,8 @@ static void calc_disp_params(struct tegra_dc *dc, if (is_internal_win(la_id)) { int i = 0; - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *curr_win = tegra_dc_get_window(dc, i); enum tegra_la_id curr_win_la_id = @@ -401,7 +403,8 @@ static void calc_disp_params(struct tegra_dc *dc, } else { int i = 0; - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *curr_win = tegra_dc_get_window(dc, i); enum tegra_la_id curr_win_la_id = @@ -482,9 +485,12 @@ static void calc_disp_params(struct tegra_dc *dc, * round up bandwidth to next 1MBps */ if (curr_dc_head_bw != ULONG_MAX) curr_dc_head_bw = curr_dc_head_bw / 1000 + 1; - tegra_dcs_total_bw[dc->ctrl_num] = curr_dc_head_bw; - disp_params->total_dc0_bw = tegra_dcs_total_bw[0]; - disp_params->total_dc1_bw = tegra_dcs_total_bw[1]; + + if (dc->ctrl_num) + disp_params->total_dc1_bw = curr_dc_head_bw; + else + disp_params->total_dc0_bw = curr_dc_head_bw; + mutex_unlock(&tegra_dcs_total_bw_lock); } @@ -703,7 +709,7 @@ unsigned long tegra_dc_get_bandwidth( { int i; - BUG_ON(n > DC_N_WINDOWS); + BUG_ON(n > tegra_dc_get_numof_dispwindows()); /* emc rate and latency allowance both need to know per window * bandwidths */ @@ -821,7 +827,8 @@ void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new) dc->bw_kbps = dc->new_bw_kbps; } - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *w = tegra_dc_get_window(dc, i); if ((use_new || w->bandwidth != w->new_bandwidth) && @@ -835,14 +842,15 @@ void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new) int tegra_dc_set_dynamic_emc(struct tegra_dc *dc) { unsigned long new_rate; - struct tegra_dc_win *windows[DC_N_WINDOWS]; + int nwins = tegra_dc_get_numof_dispwindows(); + struct tegra_dc_win *windows[nwins]; unsigned i; unsigned len; if (!use_dynamic_emc) return 0; - for (i = 0, len = 0; i < DC_N_WINDOWS; i++) { + for (i = 0, len = 0; i < tegra_dc_get_numof_dispwindows(); i++) { struct tegra_dc_win *win = tegra_dc_get_window(dc, i); if (win) windows[len++] = win; @@ -945,7 +953,8 @@ int tegra_dc_bandwidth_negotiate_bw(struct tegra_dc *dc, dc->bw_kbps = bw; } - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *w = tegra_dc_get_window(dc, i); if ((w->bandwidth != w->new_bandwidth) && w->new_bandwidth != 0) { diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 0bc098639..9b0483e5a 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +94,17 @@ EXPORT_TRACEPOINT_SYMBOL(display_readl); #define MAX_VRR_V_FRONT_PORCH 0x1000 +static struct tegra_dc_hw_data *hw_data; +static struct tegra_dc_hw_data t21x_hw_data; +static struct tegra_dc_hw_data t18x_hw_data; + +static const struct of_device_id tegra_display_of_match[] = { + {.compatible = "nvidia,tegra210-dc", .data = &t21x_hw_data }, + {.compatible = "nvidia,tegra186-dc", .data = &t18x_hw_data }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra_display_of_match); + #ifndef CONFIG_TEGRA_NVDISPLAY static struct of_device_id tegra_disa_pd[] = { { .compatible = "nvidia,tegra210-disa-pd", }, @@ -134,8 +146,7 @@ static int tegra_dc_suspend(struct platform_device *ndev, pm_message_t state); static int tegra_dc_resume(struct platform_device *ndev); #endif -static struct tegra_dc *tegra_dcs[TEGRA_MAX_DC]; - +static struct tegra_dc **tegra_dcs; #ifdef CONFIG_TEGRA_NVDISPLAY static struct tegra_dc_win tegra_dc_windows[DC_N_WINDOWS]; #endif @@ -864,7 +875,8 @@ void reg_dump(struct tegra_dc *dc, void *data, DUMP_REG(DC_COM_CMU_CSC_KBB); #endif - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { print(data, "\n"); snprintf(buff, sizeof(buff), "WINDOW %c:\n", winname[i]); print(data, buff); @@ -1253,7 +1265,8 @@ static ssize_t dbg_dc_out_type_set(struct file *file, return -EINVAL; } - WARN_ON((sizeof(boot_out_type) / sizeof(int)) != TEGRA_MAX_DC); + WARN_ON((sizeof(boot_out_type) / sizeof(int)) != + tegra_dc_get_numof_dispheads()); if (boot_out_type[dc->ndev->id] == -1) boot_out_type[dc->ndev->id] = dc->pdata->default_out->type; @@ -1971,7 +1984,7 @@ static ssize_t dbg_window_toggle_write(struct file *file, /* limit the request only to valid windows */ windows &= dc->valid_windows; - for_each_set_bit(i, &windows, DC_N_WINDOWS) { + for_each_set_bit(i, &windows, tegra_dc_get_numof_dispwindows()) { u32 val; /* select the assembly registers for window i */ tegra_dc_writel(dc, WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY, @@ -2016,7 +2029,8 @@ static int dbg_window_toggle_show(struct seq_file *m, void *unused) tegra_dc_get(dc); /* limit the request only to valid windows */ windows = 0; - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { u32 val; /* select the active registers for window i */ @@ -2564,7 +2578,7 @@ static void tegra_dc_create_debugfs(struct tegra_dc *dc) NULL); if (!dc->debug_common_dir) goto remove_out; - for (i = 0; i < DC_N_WINDOWS; i++) { + for (i = 0; i < tegra_dc_get_numof_dispwindows(); i++) { struct tegra_dc_win *win = &tegra_dc_windows[i]; snprintf(winname, sizeof(winname), "tegra_win.%d", i); @@ -2741,7 +2755,7 @@ static int tegra_dc_set_next(struct tegra_dc *dc) mutex_lock(&tegra_dc_lock); - for (i = 0; i < TEGRA_MAX_DC; i++) { + for (i = 0; i < tegra_dc_get_numof_dispheads(); i++) { if (tegra_dcs[i] == NULL) { tegra_dcs[i] = dc; ret = i; @@ -2759,7 +2773,8 @@ static int tegra_dc_set_idx(struct tegra_dc *dc, int index) int ret = 0; mutex_lock(&tegra_dc_lock); - if (index >= TEGRA_MAX_DC) { + + if (index >= tegra_dc_get_numof_dispheads()) { ret = -EINVAL; goto out; } @@ -2797,7 +2812,7 @@ unsigned int tegra_dc_has_multiple_dc(void) struct tegra_dc *dc; mutex_lock(&tegra_dc_lock); - for (idx = 0; idx < TEGRA_MAX_DC; idx++) + for (idx = 0; idx < tegra_dc_get_numof_dispheads(); idx++) cnt += ((dc = tegra_dcs[idx]) != NULL && dc->enabled) ? 1 : 0; mutex_unlock(&tegra_dc_lock); @@ -2812,7 +2827,7 @@ int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win) if (!dc->enabled) return 0; - BUG_ON(win > DC_N_WINDOWS); + WARN_ON(win > tegra_dc_get_numof_dispwindows()); mutex_lock(&dc->lock); tegra_dc_get(dc); #ifdef CONFIG_TEGRA_NVDISPLAY @@ -2831,7 +2846,7 @@ EXPORT_SYMBOL(tegra_dc_get_stride); struct tegra_dc *tegra_dc_get_dc(unsigned idx) { - if (idx < TEGRA_MAX_DC) + if (idx < tegra_dc_get_numof_dispheads()) return tegra_dcs[idx]; else return NULL; @@ -2840,7 +2855,8 @@ EXPORT_SYMBOL(tegra_dc_get_dc); struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win) { - if (win >= DC_N_WINDOWS || !test_bit(win, &dc->valid_windows)) + if (win >= tegra_dc_get_numof_dispwindows() || + !test_bit(win, &dc->valid_windows)) return NULL; #ifdef CONFIG_TEGRA_NVDISPLAY @@ -4830,7 +4846,8 @@ static int tegra_dc_init(struct tegra_dc *dc) dc->is_cmu_set_bl = false; #endif tegra_dc_set_color_control(dc); - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *win = tegra_dc_get_window(dc, i); tegra_dc_writel(dc, WINDOW_A_SELECT << i, DC_CMD_DISPLAY_WINDOW_HEADER); @@ -4839,7 +4856,9 @@ static int tegra_dc_init(struct tegra_dc *dc) tegra_dc_set_scaling_filter(dc); } - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *win = tegra_dc_get_window(dc, i); BUG_ON(!win); @@ -4939,7 +4958,7 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc) dc->out_ops->enable(dc); /* force a full blending update */ - for (i = 0; i < DC_N_WINDOWS; i++) + for (i = 0; i < tegra_dc_get_numof_dispwindows(); i++) dc->blend.z[i] = -1; tegra_dc_ext_enable(dc->ext); @@ -5136,7 +5155,8 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc) if (dc->out && dc->out->disable) dc->out->disable(&dc->ndev->dev); - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { tegra_dc_disable_window(dc, i); } trace_display_disable(dc); @@ -5188,7 +5208,8 @@ bool tegra_dc_stats_get(struct tegra_dc *dc) /* blank selected windows by disabling them */ void tegra_dc_blank_wins(struct tegra_dc *dc, unsigned windows) { - struct tegra_dc_win *dcwins[DC_N_WINDOWS]; + int nwins = tegra_dc_get_numof_dispwindows(); + struct tegra_dc_win *dcwins[nwins]; struct tegra_dc_win blank_win; unsigned i; unsigned long int blank_windows; @@ -5234,7 +5255,7 @@ void tegra_dc_blank_wins(struct tegra_dc *dc, unsigned windows) if (!blank_windows) return; - for_each_set_bit(i, &blank_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &blank_windows, tegra_dc_get_numof_dispwindows()) { dcwins[nr_win] = tegra_dc_get_window(dc, i); if (!dcwins[nr_win]) continue; @@ -5263,7 +5284,7 @@ void tegra_dc_blank_wins(struct tegra_dc *dc, unsigned windows) * of all windows. In case the statically created 420 10bpc * is also present in blank_windows, only advance syncpoints. */ - for_each_set_bit(i, &blank_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &blank_windows, tegra_dc_get_numof_dispwindows()) { if (fb_win_pos == i) { tegra_dc_flush_syncpts_window(dc, i); continue; @@ -5485,7 +5506,7 @@ int tegra_dc_update_winmask(struct tegra_dc *dc, unsigned long winmask) #endif /* CONFIG_TEGRA_NVDISPLAY */ /* check that dc is not NULL and do range check */ - if (!dc || (winmask >= (1 << DC_N_WINDOWS))) + if (!dc || (winmask >= (1 << tegra_dc_get_numof_dispwindows()))) return -EINVAL; mutex_lock(&dc->lock); @@ -5495,14 +5516,14 @@ int tegra_dc_update_winmask(struct tegra_dc *dc, unsigned long winmask) } /* check requested=enabled windows NOT owned by other dcs */ - for_each_set_bit(i, &winmask, DC_N_WINDOWS) { + for_each_set_bit(i, &winmask, tegra_dc_get_numof_dispwindows()) { j = dc->ndev->id; win = tegra_dc_get_window(dc, i); /* is window already owned by this dc? */ if (win && win->dc && (win->dc == dc)) continue; /* is window already owned by other dc? */ - for (j = 0; j < TEGRA_MAX_DC; j++) { + for (j = 0; j < tegra_dc_get_numof_dispheads(); j++) { dc_other = tegra_dc_get_dc(j); if (!dc_other) continue; @@ -5705,7 +5726,7 @@ static int tegra_dc_probe(struct platform_device *ndev) } #ifndef CONFIG_TEGRA_NVDISPLAY - for (i = 0; i < DC_N_WINDOWS; i++) + for (i = 0; i < tegra_dc_get_numof_dispwindows(); i++) dc->windows[i].syncpt.id = NVSYNCPT_INVALID; if (TEGRA_DISPLAY_BASE == res->start) { @@ -5839,8 +5860,8 @@ static int tegra_dc_probe(struct platform_device *ndev) #endif tegra_dc_init_lut_defaults(&dc->fb_lut); - dc->n_windows = DC_N_WINDOWS; - for (i = 0; i < DC_N_WINDOWS; i++) { + dc->n_windows = tegra_dc_get_numof_dispwindows(); + for (i = 0; i < tegra_dc_get_numof_dispwindows(); i++) { struct tegra_dc_win *tmp_win = &dc->tmp_wins[i]; #ifdef CONFIG_TEGRA_NVDISPLAY struct tegra_dc_win *win = &tegra_dc_windows[i]; @@ -6453,7 +6474,7 @@ static struct tegra_dc *tegra_dc_hwidx2dc(int dcid) struct tegra_dc *dc; int i; - for (i = 0; i < TEGRA_MAX_DC; i++) { + for (i = 0; i < tegra_dc_get_numof_dispheads(); i++) { dc = tegra_dc_get_dc(i); if (dc && (dcid == dc->ctrl_num)) return dc; @@ -6462,24 +6483,10 @@ static struct tegra_dc *tegra_dc_hwidx2dc(int dcid) return NULL; } - -/* - * get number of Tegra display heads - * o inputs: none - * o outputs: - * - return: number of Tegra display heads - */ -int tegra_dc_get_numof_dispheads(void) -{ - return TEGRA_MAX_DC; -} -EXPORT_SYMBOL(tegra_dc_get_numof_dispheads); - - /* * get Tegra display head status * o inputs: - * - dcid: display head HW index (0 to TEGRA_MAX_DC-1) + * - dcid: display head HW index (0 to max_dc_heads-1) * - pSts: pointer to the head status structure to be returned * o outputs: * - return: error number @@ -6505,11 +6512,10 @@ int tegra_dc_get_disphead_sts(int dcid, struct tegra_dc_head_status *pSts) } EXPORT_SYMBOL(tegra_dc_get_disphead_sts); - /* * to register the Tegra display ISR user call-back routine * o inputs: - * - dcid: display head HW index (0 to TEGRA_MAX_DC-1) + * - dcid: display head HW index (0 to max_dc_heads-1) * - usr_isr_cb: function pointer to the user call-back routine * - usr_isr_pdt: user call-back private data * o outputs: @@ -6551,7 +6557,7 @@ EXPORT_SYMBOL(tegra_dc_register_isr_usr_cb); /* * to unregister the Tegra display ISR user call-back routine * o inputs: - * - dcid: display head HW index (0 to TEGRA_MAX_DC-1) + * - dcid: display head HW index (0 to max_dc_heads-1) * - usr_isr_cb: registered user call-back. ignored. * - usr_isr_pdt: registered user call-back private data. ignored. * o outputs: @@ -6583,23 +6589,23 @@ EXPORT_SYMBOL(tegra_dc_unregister_isr_usr_cb); #endif /* TEGRA_DC_USR_SHARED_IRQ */ -static struct tegra_dc_hw_data *hw_data; -static struct tegra_dc_hw_data t21x_hw_data; -static struct tegra_dc_hw_data t18x_hw_data; - -static const struct of_device_id tegra_display_of_match[] = { - {.compatible = "nvidia,tegra210-dc", .data = &t21x_hw_data }, - {.compatible = "nvidia,tegra186-dc", .data = &t18x_hw_data }, - { }, -}; - -inline int tegra_dc_get_max_heads(void) +int tegra_dc_get_numof_dispheads(void) { if (!hw_data || !hw_data->valid) return -ENODEV; return hw_data->nheads; } +EXPORT_SYMBOL(tegra_dc_get_numof_dispheads); + +int tegra_dc_get_numof_dispwindows(void) +{ + if (!hw_data || !hw_data->valid) + return DC_N_WINDOWS; + + return hw_data->nwins; +} +EXPORT_SYMBOL(tegra_dc_get_numof_dispwindows); static int tegra_dc_assign_hw_data(void) { @@ -6665,6 +6671,11 @@ static int __init tegra_dc_module_init(void) if (ret) return ret; + tegra_dcs = kzalloc( + (hw_data->nheads) * sizeof(struct tegra_dc *), GFP_KERNEL); + if (!tegra_dcs) + return -ENOMEM; + ret = tegra_dc_ext_module_init(); if (ret) return ret; @@ -6674,6 +6685,7 @@ static int __init tegra_dc_module_init(void) static void __exit tegra_dc_module_exit(void) { + kfree(tegra_dcs); platform_driver_unregister(&tegra_dc_driver); tegra_dc_ext_module_exit(); } diff --git a/drivers/video/tegra/dc/dc_priv_defs.h b/drivers/video/tegra/dc/dc_priv_defs.h index 2d7032979..8f5a8cdf6 100644 --- a/drivers/video/tegra/dc/dc_priv_defs.h +++ b/drivers/video/tegra/dc/dc_priv_defs.h @@ -175,8 +175,10 @@ struct tegra_dc_pool_allocation { struct tegra_dc_imp_settings { struct tegra_dc_ext_imp_settings ext_settings; - struct tegra_dc_pool_allocation decreasing_pool[TEGRA_MAX_DC]; - struct tegra_dc_pool_allocation increasing_pool[TEGRA_MAX_DC]; + struct tegra_dc_pool_allocation + decreasing_pool[TEGRA_DC_EXT_N_HEADS]; + struct tegra_dc_pool_allocation + increasing_pool[TEGRA_DC_EXT_N_HEADS]; struct list_head imp_node; u64 session_id; u32 owner; @@ -255,6 +257,7 @@ struct tegra_dc { bool common_channel_reserved; bool common_channel_pending; bool common_channel_intr_enabled; + bool comp_clk_inuse; #endif bool imp_dirty; u64 imp_session_id_cntr; diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c index f7b9fc019..329134f53 100644 --- a/drivers/video/tegra/dc/ext/dev.c +++ b/drivers/video/tegra/dc/ext/dev.c @@ -167,7 +167,8 @@ static int tegra_dc_ext_get_window(struct tegra_dc_ext_user *user, struct tegra_dc_ext_win *win; int ret = 0; - if ((n >= DC_N_WINDOWS) || !(ext->dc->valid_windows & BIT(n))) + if ((n >= tegra_dc_get_numof_dispwindows()) || + !(ext->dc->valid_windows & BIT(n))) return -EINVAL; win = &ext->win[n]; @@ -193,7 +194,8 @@ static int tegra_dc_ext_put_window(struct tegra_dc_ext_user *user, struct tegra_dc_ext_win *win; int ret = 0; - if ((n >= DC_N_WINDOWS) || !(ext->dc->valid_windows & BIT(n))) + if ((n >= tegra_dc_get_numof_dispwindows()) || + !(ext->dc->valid_windows & BIT(n))) return -EINVAL; win = &ext->win[n]; @@ -229,10 +231,12 @@ static int tegra_dc_ext_set_winmask(struct tegra_dc_ext_user *user, int tegra_dc_ext_restore(struct tegra_dc_ext *ext) { - struct tegra_dc_win *wins[DC_N_WINDOWS]; + int nwins = tegra_dc_get_numof_dispwindows(); + struct tegra_dc_win *wins[nwins]; int i, nr_win = 0; - for_each_set_bit(i, &ext->dc->valid_windows, DC_N_WINDOWS) + for_each_set_bit(i, &ext->dc->valid_windows, + tegra_dc_get_numof_dispwindows()) if (ext->win[i].enabled) { wins[nr_win] = tegra_dc_get_window(ext->dc, i); wins[nr_win++]->flags |= TEGRA_WIN_FLAG_ENABLED; @@ -298,14 +302,15 @@ int tegra_dc_ext_disable(struct tegra_dc_ext *ext) * removed from screen, and advance syncpt. */ if (ext->dc->enabled) { - for (i = 0; i < DC_N_WINDOWS; i++) { + for (i = 0; i < tegra_dc_get_numof_dispwindows(); i++) { if (ext->win[i].user) windows |= BIT(i); } tegra_dc_blank_wins(ext->dc, windows); if (!IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE)) { - for_each_set_bit(i, &windows, DC_N_WINDOWS) { + for_each_set_bit(i, &windows, + tegra_dc_get_numof_dispwindows()) { tegra_dc_ext_unpin_window(&ext->win[i]); } } @@ -846,7 +851,7 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work) tegra_dc_scrncapt_disp_pause_lock(dc); - BUG_ON(win_num > DC_N_WINDOWS); + BUG_ON(win_num > tegra_dc_get_numof_dispwindows()); for (i = 0; i < win_num; i++) { struct tegra_dc_ext_flip_win *flip_win = &data->win[i]; int index = flip_win->attr.index; @@ -1081,7 +1086,7 @@ static int lock_windows_for_flip(struct tegra_dc_ext_user *user, u8 idx_mask = 0; int i; - BUG_ON(win_num > DC_N_WINDOWS); + BUG_ON(win_num > tegra_dc_get_numof_dispwindows()); for (i = 0; i < win_num; i++) { int index = win_attr[i].index; @@ -1126,7 +1131,7 @@ static void unlock_windows_for_flip(struct tegra_dc_ext_user *user, u8 idx_mask = 0; int i; - BUG_ON(win_num > DC_N_WINDOWS); + BUG_ON(win_num > tegra_dc_get_numof_dispwindows()); for (i = 0; i < win_num; i++) { int index = win[i].index; @@ -1150,7 +1155,7 @@ static int sanitize_flip_args(struct tegra_dc_ext_user *user, int i, used_windows = 0; struct tegra_dc *dc = user->ext->dc; - if (win_num > DC_N_WINDOWS) + if (win_num > tegra_dc_get_numof_dispwindows()) return -EINVAL; for (i = 0; i < win_num; i++) { @@ -1159,7 +1164,7 @@ static int sanitize_flip_args(struct tegra_dc_ext_user *user, if (index < 0) continue; - if (index >= DC_N_WINDOWS || + if (index >= tegra_dc_get_numof_dispwindows() || !test_bit(index, &dc->valid_windows)) return -EINVAL; @@ -1409,7 +1414,7 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, data->dirty_rect_valid = true; } - BUG_ON(win_num > DC_N_WINDOWS); + BUG_ON(win_num > tegra_dc_get_numof_dispwindows()); ret = tegra_dc_ext_pin_windows(user, win, win_num, data->win, &has_timestamp, @@ -1444,7 +1449,7 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, goto unlock; } - BUG_ON(win_num > DC_N_WINDOWS); + BUG_ON(win_num > tegra_dc_get_numof_dispwindows()); for (i = 0; i < win_num; i++) { u32 syncpt_max; int index = win[i].index; @@ -3072,7 +3077,7 @@ static int tegra_dc_release(struct inode *inode, struct file *filp) unsigned int i; unsigned long int windows = 0; - for (i = 0; i < DC_N_WINDOWS; i++) { + for (i = 0; i < tegra_dc_get_numof_dispwindows(); i++) { if (ext->win[i].user == user) { tegra_dc_ext_put_window(user, i); windows |= BIT(i); @@ -3081,7 +3086,8 @@ static int tegra_dc_release(struct inode *inode, struct file *filp) if (ext->dc->enabled) { tegra_dc_blank_wins(ext->dc, windows); - for_each_set_bit(i, &windows, DC_N_WINDOWS) { + for_each_set_bit(i, &windows, + tegra_dc_get_numof_dispwindows()) { tegra_dc_ext_unpin_window(&ext->win[i]); tegra_dc_disable_window(ext->dc, i); } @@ -3241,11 +3247,11 @@ void tegra_dc_ext_unregister(struct tegra_dc_ext *ext) int __init tegra_dc_ext_module_init(void) { - int ret, heads = tegra_dc_get_max_heads(); + int ret, nheads = tegra_dc_get_numof_dispheads(); - if (heads <= 0) { + if (nheads <= 0) { pr_err("%s: max heads:%d cannot be negative or zero\n", - __func__, heads); + __func__, nheads); return -EINVAL; } @@ -3257,7 +3263,7 @@ int __init tegra_dc_ext_module_init(void) /* Reserve one character device per head, plus the control device */ ret = alloc_chrdev_region(&tegra_dc_ext_devno, - 0, heads + 1, + 0, nheads + 1, "tegra_dc_ext"); if (ret) goto cleanup_class; @@ -3271,7 +3277,7 @@ int __init tegra_dc_ext_module_init(void) return 0; cleanup_region: - unregister_chrdev_region(tegra_dc_ext_devno, heads); + unregister_chrdev_region(tegra_dc_ext_devno, nheads); cleanup_class: class_destroy(tegra_dc_ext_class); @@ -3282,6 +3288,7 @@ cleanup_class: void __exit tegra_dc_ext_module_exit(void) { tegra_dc_scrncapt_exit(); - unregister_chrdev_region(tegra_dc_ext_devno, tegra_dc_get_max_heads()); + unregister_chrdev_region(tegra_dc_ext_devno, + tegra_dc_get_numof_dispheads()); class_destroy(tegra_dc_ext_class); } diff --git a/drivers/video/tegra/dc/ext/scrncapt.c b/drivers/video/tegra/dc/ext/scrncapt.c index ae502f799..c8557d620 100644 --- a/drivers/video/tegra/dc/ext/scrncapt.c +++ b/drivers/video/tegra/dc/ext/scrncapt.c @@ -45,12 +45,11 @@ static struct tegra_dc_scrncapt_private { int holder_pid; u32 magic; u32 pause_heads; - struct rw_semaphore rwsema_head[TEGRA_MAX_DC]; + struct rw_semaphore *rwsema_head; struct timer_list tmr_resume; unsigned long tm_resume; } scrncapt; - /* * Interface with Tegra DC Driver * @@ -238,7 +237,7 @@ static int scrncapt_get_info_wins(struct tegra_dc *dc, void __user *ptr) pwinattr = (struct tegra_dc_ext_flip_windowattr_v2 __user *)info.wins; num_wins = 0; - for (i = 0; i < DC_N_WINDOWS; i++) { + for (i = 0; i < tegra_dc_get_numof_dispwindows(); i++) { struct tegra_dc_ext_flip_windowattr_v2 winattr; if (!(info.flag_wins & dc->valid_windows & (1 << i))) @@ -417,7 +416,7 @@ int tegra_dc_scrncapt_get_info(struct tegra_dc_ext_user *user, if ((args->ver ^ scrncapt.magic) & ~0xff) return -EFAULT; - if (TEGRA_MAX_DC <= (unsigned)args->head) + if (tegra_dc_get_numof_dispheads() <= (unsigned)args->head) return -EFAULT; /* check disp paused */ @@ -484,8 +483,8 @@ int tegra_dc_scrncapt_dup_fbuf(struct tegra_dc_ext_user *user, if ((args->ver ^ scrncapt.magic) & ~0xff) return -EFAULT; - if (TEGRA_MAX_DC <= (unsigned)args->head - || DC_N_WINDOWS <= (unsigned)args->win) + if ((tegra_dc_get_numof_dispheads() <= (unsigned)args->head) || + (tegra_dc_get_numof_dispwindows() <= (unsigned)args->win)) return -EINVAL; if (!access_ok(VERIFY_WRITE, args->buffer, args->buffer_max)) @@ -539,13 +538,14 @@ int tegra_dc_scrncapt_pause(struct tegra_dc_ext_control_user *ctlusr, struct tegra_dc_ext_control_scrncapt_pause *args) { int err = 0; - int i; + int i, nheads; u32 heads; unsigned long tm; if (TEGRA_DC_EXT_CONTROL_SCRNCAPT_MAGIC != args->magic) return -EFAULT; + nheads = tegra_dc_get_numof_dispheads(); heads = 1 << 31; /* default to pausing all heads */ if ((1 << 31) & heads) heads |= -1; @@ -557,7 +557,7 @@ int tegra_dc_scrncapt_pause(struct tegra_dc_ext_control_user *ctlusr, if (scrncapt.pause_heads) { err = -EBUSY; } else { - for (i = 0; i < TEGRA_MAX_DC; i++) { + for (i = 0; i < nheads; i++) { if ((1 << i) & heads) down_write(&scrncapt.rwsema_head[i]); } @@ -578,8 +578,8 @@ int tegra_dc_scrncapt_pause(struct tegra_dc_ext_control_user *ctlusr, args->magic = scrncapt.magic; args->tm_resume_msec = tm ? : -1; - args->num_heads = TEGRA_MAX_DC; - args->num_wins = DC_N_WINDOWS; + args->num_heads = nheads; + args->num_wins = tegra_dc_get_numof_dispwindows(); return err; } @@ -596,6 +596,7 @@ int tegra_dc_scrncapt_resume(struct tegra_dc_ext_control_user *ctlusr, return -EFAULT; mutex_lock(&scrncapt.lock); + if (!scrncapt.pause_heads) { err = -EINVAL; } else { @@ -606,7 +607,7 @@ int tegra_dc_scrncapt_resume(struct tegra_dc_ext_control_user *ctlusr, scrncapt.holder_pid = 0x0; if ((1 << 31) & heads) heads |= -1; - for (i = 0; i < TEGRA_MAX_DC; i++) { + for (i = 0; i < tegra_dc_get_numof_dispheads(); i++) { if ((1 << i) & heads) up_write(&scrncapt.rwsema_head[i]); } @@ -632,7 +633,7 @@ static void tegra_dc_scrncapt_timer_cb(unsigned long arg) scrncapt.holder_pid = 0x0; if ((1 << 31) & heads) heads |= -1; - for (i = 0; i < TEGRA_MAX_DC; i++) { + for (i = 0; i < tegra_dc_get_numof_dispheads(); i++) { if ((1 << i) & heads) up_write(&scrncapt.rwsema_head[i]); } @@ -642,13 +643,31 @@ static void tegra_dc_scrncapt_timer_cb(unsigned long arg) int tegra_dc_scrncapt_init(void) { - int i, heads = tegra_dc_get_max_heads(); + int i, nheads, nwins; + + nheads = tegra_dc_get_numof_dispheads(); + nwins = tegra_dc_get_numof_dispwindows(); + + if (nheads <= 0 || nwins <= 0) { + pr_err("%s: heads:%d windows:%d cannot be negative or zero\n", + __func__, nheads, nwins); + return -EINVAL; + } - pr_info("scrncapt: init (heads:%d wins:%d planes:%d)\n", - heads, DC_N_WINDOWS, TEGRA_DC_NUM_PLANES); memset(&scrncapt, 0, sizeof(scrncapt)); mutex_init(&scrncapt.lock); - for (i = 0; i < heads; i++) + scrncapt.rwsema_head = kzalloc(nheads * + sizeof(struct rw_semaphore), GFP_KERNEL); + + if (IS_ERR_OR_NULL(scrncapt.rwsema_head)) { + pr_err("%s: Insufficient memory\n", __func__); + return -ENOMEM; + } + + pr_info("scrncapt: init (heads:%d wins:%d planes:%d)\n", + nheads, nwins, TEGRA_DC_NUM_PLANES); + + for (i = 0; i < nheads; i++) init_rwsem(&scrncapt.rwsema_head[i]); init_timer(&scrncapt.tmr_resume); scrncapt.tmr_resume.function = &tegra_dc_scrncapt_timer_cb; @@ -662,6 +681,6 @@ int tegra_dc_scrncapt_init(void) int tegra_dc_scrncapt_exit(void) { pr_info("scrncapt: exit\n"); - + kfree(scrncapt.rwsema_head); return 0; } diff --git a/drivers/video/tegra/dc/lut.c b/drivers/video/tegra/dc/lut.c index 2fd479a9b..fbfbfe30f 100644 --- a/drivers/video/tegra/dc/lut.c +++ b/drivers/video/tegra/dc/lut.c @@ -1,7 +1,7 @@ /* * drivers/video/tegra/dc/lut.c * - * Copyright (c) 2010-2016, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2017, NVIDIA CORPORATION, All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -125,7 +125,8 @@ int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int fboveride) if (win_idx > -1) return tegra_dc_update_winlut(dc, win_idx, fboveride); - for_each_set_bit(win_idx, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(win_idx, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { int err = tegra_dc_update_winlut(dc, win_idx, fboveride); if (err) return err; diff --git a/drivers/video/tegra/dc/sor.c b/drivers/video/tegra/dc/sor.c index f98d65df9..f46fcdaee 100644 --- a/drivers/video/tegra/dc/sor.c +++ b/drivers/video/tegra/dc/sor.c @@ -1,7 +1,7 @@ /* * drivers/video/tegra/dc/sor.c * - * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -1807,7 +1807,8 @@ tegra_dc_sor_disable_win_short_raster(struct tegra_dc *dc, int *dc_reg_ctx) selected_windows = tegra_dc_readl(dc, DC_CMD_DISPLAY_WINDOW_HEADER); /* Store and clear window options */ - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { tegra_dc_writel(dc, WINDOW_A_SELECT << i, DC_CMD_DISPLAY_WINDOW_HEADER); dc_reg_ctx[i] = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); @@ -1854,7 +1855,8 @@ tegra_dc_sor_restore_win_and_raster(struct tegra_dc *dc, int *dc_reg_ctx) selected_windows = tegra_dc_readl(dc, DC_CMD_DISPLAY_WINDOW_HEADER); - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { tegra_dc_writel(dc, WINDOW_A_SELECT << i, DC_CMD_DISPLAY_WINDOW_HEADER); tegra_dc_writel(dc, dc_reg_ctx[i], DC_WIN_WIN_OPTIONS); diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c index 572b700ef..2d7b14020 100644 --- a/drivers/video/tegra/dc/window.c +++ b/drivers/video/tegra/dc/window.c @@ -3,7 +3,7 @@ * * Copyright (C) 2010 Google, Inc. * - * Copyright (c) 2010-2016, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2017, NVIDIA CORPORATION, All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -175,7 +175,7 @@ static void tegra_dc_blend_sequential(struct tegra_dc *dc, unsigned long mask = dc->valid_windows; tegra_dc_io_start(dc); - for_each_set_bit(idx, &mask, DC_N_WINDOWS) { + for_each_set_bit(idx, &mask, tegra_dc_get_numof_dispwindows()) { if (!tegra_dc_feature_is_gen2_blender(dc, idx)) continue; @@ -276,7 +276,7 @@ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n) if (dc == NULL) return -EFAULT; - if (n < 1 || n > DC_N_WINDOWS) + if (n < 1 || n > tegra_dc_get_numof_dispwindows()) return -EINVAL; if (!dc->enabled) @@ -964,7 +964,8 @@ static int _tegra_dc_program_windows(struct tegra_dc *dc, if (update_blend_seq) tegra_dc_blend_sequential(dc, &dc->blend); - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *win = tegra_dc_get_window(dc, i); win->dirty = 1; @@ -1127,7 +1128,8 @@ void tegra_dc_trigger_windows(struct tegra_dc *dc) #endif val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); - for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) { + for_each_set_bit(i, &dc->valid_windows, + tegra_dc_get_numof_dispwindows()) { struct tegra_dc_win *win = tegra_dc_get_window(dc, i); if (tegra_platform_is_linsim()) { diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index 8acfc9068..2251e9272 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -6,7 +6,7 @@ * Colin Cross * Travis Geiselbrecht * - * Copyright (c) 2010-2016, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2017, NVIDIA CORPORATION, All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -988,7 +988,7 @@ int tegra_fb_set_win_index(struct tegra_dc *dc, unsigned long win_mask) if (win_mask) { /* Set the first valid bit as fb win index */ - for (i = 0; i < DC_N_WINDOWS; i++) { + for (i = 0; i < tegra_dc_get_numof_dispwindows(); i++) { if (test_bit(i, &mask)) break; } diff --git a/include/video/tegra_dc_ext.h b/include/video/tegra_dc_ext.h index 8e57d77fa..7099ea4b8 100644 --- a/include/video/tegra_dc_ext.h +++ b/include/video/tegra_dc_ext.h @@ -408,8 +408,6 @@ struct tegra_dc_ext_imp_settings { __u64 __user session_id_ptr; /* out - ptr to unsigned 64-bit val */ __u64 reserved[4]; /* reserved - must be 0 */ }; -#undef TEGRA_DC_EXT_N_WINDOWS -#undef TEGRA_DC_EXT_N_HEADS /* * Variable settings is a pointer to tegra_dc_ext_imp_settings. diff --git a/include/video/tegra_dc_ext_kernel.h b/include/video/tegra_dc_ext_kernel.h index 44ab3a232..5d8cebe28 100644 --- a/include/video/tegra_dc_ext_kernel.h +++ b/include/video/tegra_dc_ext_kernel.h @@ -20,12 +20,6 @@ #include #include -#if defined(CONFIG_TEGRA_NVDISPLAY) -#define TEGRA_MAX_DC 3 -#else -#define TEGRA_MAX_DC 2 -#endif - #if defined(CONFIG_ARCH_TEGRA_14x_SOC) #define DC_N_WINDOWS 6 #elif defined(CONFIG_ARCH_TEGRA_12x_SOC) || defined(CONFIG_ARCH_TEGRA_21x_SOC) @@ -190,6 +184,8 @@ struct tegra_dc *tegra_dc_get_dc(unsigned idx); int tegra_dc_bandwidth_negotiate_bw(struct tegra_dc *dc, struct tegra_dc_win *windows[], int n); #endif +int tegra_dc_get_numof_dispheads(void); +int tegra_dc_get_numof_dispwindows(void); /* needed by tegra-throughput */ int tegra_dc_set_flip_callback(void (*callback)(void)); -- cgit v1.2.2