diff options
author | Xue Dong <xdong@nvidia.com> | 2013-01-24 13:34:06 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 01:29:26 -0700 |
commit | 46faf97bfd50b576a277c1ecbb29be6aa45f7af8 (patch) | |
tree | a63a077a6863df9d1ae56a8ceb01e01b94eb55bb /drivers/video | |
parent | 49f52b7e3f79c19650ea75f71d3eb508ce6cc464 (diff) |
video: tegra: dc: flip API for more than 3 windows
add new ioctl that supports flip of an arbitrary number of windows.
Change-Id: I6368129092921c665db5a8063f714d9f8fc14e63
Signed-off-by: Xue Dong <xdong@nvidia.com>
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/193929
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Kevin Huang (Eng-SW) <kevinh@nvidia.com>
Reviewed-by: Tuomas Kulve <tkulve@nvidia.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/tegra/dc/bandwidth.c | 4 | ||||
-rw-r--r-- | drivers/video/tegra/dc/ext/dev.c | 135 |
2 files changed, 87 insertions, 52 deletions
diff --git a/drivers/video/tegra/dc/bandwidth.c b/drivers/video/tegra/dc/bandwidth.c index a494e71495f0..8d389aa85b23 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-2012, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2013, 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 @@ -38,6 +38,7 @@ module_param_named(use_dynamic_emc, use_dynamic_emc, int, S_IRUGO | S_IWUSR); static void tegra_dc_set_latency_allowance(struct tegra_dc *dc, struct tegra_dc_win *w) { + unsigned long bw; /* windows A, B, C for first and second display */ static const enum tegra_la_id la_id_tab[2][DC_N_WINDOWS] = { /* first display */ @@ -67,7 +68,6 @@ static void tegra_dc_set_latency_allowance(struct tegra_dc *dc, TEGRA_LA_DISPLAY_1B, TEGRA_LA_DISPLAY_1BB, }; #endif - unsigned long bw; BUG_ON(dc->ndev->id >= ARRAY_SIZE(la_id_tab)); #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c index df45bed651a8..a859221a3bb9 100644 --- a/drivers/video/tegra/dc/ext/dev.c +++ b/drivers/video/tegra/dc/ext/dev.c @@ -1,7 +1,7 @@ /* * drivers/video/tegra/dc/dev.c * - * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2011-2013, NVIDIA CORPORATION, All rights reserved. * * Author: Robert Morell <rmorell@nvidia.com> * Some code based on fbdev extensions written by: @@ -56,8 +56,9 @@ struct tegra_dc_ext_flip_win { struct tegra_dc_ext_flip_data { struct tegra_dc_ext *ext; struct work_struct work; - struct tegra_dc_ext_flip_win win[TEGRA_DC_EXT_FLIP_N_WINDOWS]; + struct tegra_dc_ext_flip_win win[DC_N_WINDOWS]; struct list_head timestamp_node; + int act_window_num; }; int tegra_dc_ext_get_num_outputs(void) @@ -340,15 +341,16 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work) { struct tegra_dc_ext_flip_data *data = container_of(work, struct tegra_dc_ext_flip_data, work); + int win_num = data->act_window_num; struct tegra_dc_ext *ext = data->ext; - struct tegra_dc_win *wins[TEGRA_DC_EXT_FLIP_N_WINDOWS]; - struct nvmap_handle_ref *unpin_handles[TEGRA_DC_EXT_FLIP_N_WINDOWS * + struct tegra_dc_win *wins[DC_N_WINDOWS]; + struct nvmap_handle_ref *unpin_handles[DC_N_WINDOWS * TEGRA_DC_NUM_PLANES]; struct nvmap_handle_ref *old_handle; int i, nr_unpin = 0, nr_win = 0; bool skip_flip = false; - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { + for (i = 0; i < win_num; i++) { struct tegra_dc_ext_flip_win *flip_win = &data->win[i]; int index = flip_win->attr.index; struct tegra_dc_win *win; @@ -435,7 +437,7 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work) spin_unlock(&flip_callback_lock); } - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { + for (i = 0; i < DC_N_WINDOWS; i++) { struct tegra_dc_ext_flip_win *flip_win = &data->win[i]; int index = flip_win->attr.index; @@ -457,14 +459,15 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work) } static int lock_windows_for_flip(struct tegra_dc_ext_user *user, - struct tegra_dc_ext_flip *args) + struct tegra_dc_ext_flip_windowattr *win, + int win_num) { struct tegra_dc_ext *ext = user->ext; u8 idx_mask = 0; int i; - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { - int index = args->win[i].index; + for (i = 0; i < win_num; i++) { + int index = win[i].index; if (index < 0) continue; @@ -472,7 +475,7 @@ static int lock_windows_for_flip(struct tegra_dc_ext_user *user, idx_mask |= BIT(index); } - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { + for (i = 0; i < win_num; i++) { struct tegra_dc_ext_win *win; if (!(idx_mask & BIT(i))) @@ -500,14 +503,16 @@ fail_unlock: } static void unlock_windows_for_flip(struct tegra_dc_ext_user *user, - struct tegra_dc_ext_flip *args) + struct tegra_dc_ext_flip_windowattr *win, + int win_num) { struct tegra_dc_ext *ext = user->ext; u8 idx_mask = 0; int i; - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { - int index = args->win[i].index; + + for (i = 0; i < win_num; i++) { + int index = win[i].index; if (index < 0) continue; @@ -515,7 +520,7 @@ static void unlock_windows_for_flip(struct tegra_dc_ext_user *user, idx_mask |= BIT(index); } - for (i = TEGRA_DC_EXT_FLIP_N_WINDOWS - 1; i >= 0; i--) { + for (i = win_num - 1; i >= 0; i--) { if (!(idx_mask & BIT(i))) continue; @@ -524,12 +529,13 @@ static void unlock_windows_for_flip(struct tegra_dc_ext_user *user, } static int sanitize_flip_args(struct tegra_dc_ext_user *user, - struct tegra_dc_ext_flip *args) + struct tegra_dc_ext_flip_windowattr *win, + int win_num) { int i, used_windows = 0; - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { - int index = args->win[i].index; + for (i = 0; i < win_num; i++) { + int index = win[i].index; if (index < 0) continue; @@ -550,7 +556,9 @@ static int sanitize_flip_args(struct tegra_dc_ext_user *user, } static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, - struct tegra_dc_ext_flip *args) + struct tegra_dc_ext_flip_windowattr *win, + int win_num, + __u32 *syncpt_id, __u32 *syncpt_val) { struct tegra_dc_ext *ext = user->ext; struct tegra_dc_ext_flip_data *data; @@ -558,15 +566,11 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, int i, ret = 0; bool has_timestamp = false; -#ifdef CONFIG_ANDROID - int index_check[TEGRA_DC_EXT_FLIP_N_WINDOWS] = {0, }; - int zero_index_id = 0; -#endif if (!user->nvmap) return -EFAULT; - ret = sanitize_flip_args(user, args); + ret = sanitize_flip_args(user, win, win_num); if (ret) return ret; @@ -576,28 +580,14 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, INIT_WORK(&data->work, tegra_dc_ext_flip_worker); data->ext = ext; + data->act_window_num = win_num; -#ifdef CONFIG_ANDROID - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { - index_check[i] = args->win[i].index; - if (index_check[i] == 0) - zero_index_id = i; - } - - if (index_check[TEGRA_DC_EXT_FLIP_N_WINDOWS - 1] != 0) { - struct tegra_dc_ext_flip_windowattr win_temp; - win_temp = args->win[TEGRA_DC_EXT_FLIP_N_WINDOWS - 1]; - args->win[TEGRA_DC_EXT_FLIP_N_WINDOWS - 1] = - args->win[zero_index_id]; - args->win[zero_index_id] = win_temp; - } -#endif - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { + for (i = 0; i < win_num; i++) { struct tegra_dc_ext_flip_win *flip_win = &data->win[i]; - int index = args->win[i].index; + int index = win[i].index; - memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr)); + memcpy(&flip_win->attr, &win[i], sizeof(flip_win->attr)); if (timespec_to_ns(&flip_win->attr.timestamp)) has_timestamp = true; @@ -635,7 +625,7 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, } } - ret = lock_windows_for_flip(user, args); + ret = lock_windows_for_flip(user, win, win_num); if (ret) goto fail_pin; @@ -644,9 +634,10 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, goto unlock; } - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { + + for (i = 0; i < win_num; i++) { u32 syncpt_max; - int index = args->win[i].index; + int index = win[i].index; struct tegra_dc_ext_win *ext_win; if (index < 0) @@ -662,8 +653,8 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, * Any of these windows' syncpoints should be equivalent for * the client, so we just send back an arbitrary one of them */ - args->post_syncpt_val = syncpt_max; - args->post_syncpt_id = tegra_dc_get_syncpt_id(ext->dc, index); + *syncpt_val = syncpt_max; + *syncpt_id = tegra_dc_get_syncpt_id(ext->dc, index); work_index = index; atomic_inc(&ext->win[work_index].nr_pending_flips); @@ -677,17 +668,21 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, list_add_tail(&data->timestamp_node, &ext->win[work_index].timestamp_queue); mutex_unlock(&ext->win[work_index].queue_lock); } +#ifdef CONFIG_ANDROID + work_index = 0; +#endif queue_work(ext->win[work_index].flip_wq, &data->work); - unlock_windows_for_flip(user, args); + unlock_windows_for_flip(user, win, win_num); return 0; unlock: - unlock_windows_for_flip(user, args); + unlock_windows_for_flip(user, win, win_num); fail_pin: - for (i = 0; i < TEGRA_DC_EXT_FLIP_N_WINDOWS; i++) { + + for (i = 0; i < win_num; i++) { int j; for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) { if (!data->win[i].handle[j]) @@ -882,6 +877,7 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd, { void __user *user_arg = (void __user *)arg; struct tegra_dc_ext_user *user = filp->private_data; + struct tegra_dc_ext_flip_2 args_new; switch (cmd) { case TEGRA_DC_EXT_SET_NVMAP_FD: @@ -900,7 +896,10 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&args, user_arg, sizeof(args))) return -EFAULT; - ret = tegra_dc_ext_flip(user, &args); + ret = tegra_dc_ext_flip(user, args.win, + DC_N_WINDOWS, + &args.post_syncpt_id, + &args.post_syncpt_val); if (copy_to_user(user_arg, &args, sizeof(args))) return -EFAULT; @@ -908,6 +907,42 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd, return ret; } + case TEGRA_DC_EXT_FLIP2: + { + int ret; + int num; + struct tegra_dc_ext_flip_windowattr *start; + struct tegra_dc_ext_flip_windowattr *temp; + + if (copy_from_user(&args_new, user_arg, sizeof(args_new))) + return -EFAULT; + + num = args_new.win_num; + start = args_new.win; + + temp = kzalloc(sizeof(*start) * num, GFP_KERNEL); + + if (copy_from_user(temp, start, sizeof(*start) * num)) + return -EFAULT; + + args_new.win = temp; + + ret = tegra_dc_ext_flip(user, args_new.win, + args_new.win_num, + &args_new.post_syncpt_id, + &args_new.post_syncpt_val); + + if (copy_to_user(start, temp, sizeof(*start) * num)) + return -EFAULT; + + args_new.win = start; + + if (copy_to_user(user_arg, &args_new, sizeof(args_new))) + return -EFAULT; + kfree(temp); + return ret; + } + case TEGRA_DC_EXT_GET_CURSOR: return tegra_dc_ext_get_cursor(user); case TEGRA_DC_EXT_PUT_CURSOR: |