]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: dc: skip over invalid windows
authorJon Mayo <jmayo@nvidia.com>
Fri, 15 Nov 2013 01:06:13 +0000 (17:06 -0800)
committerJon Mayo <jmayo@nvidia.com>
Fri, 15 Nov 2013 22:03:49 +0000 (14:03 -0800)
Use for_each_set_bit and valid_windows to loop through window array,
ignoring non-existant windows.
Use tegra_dc_get_window() instead of directly accessing window array
elements.
Use for_each_set_bit() and tegra_dc_get_window() in lut.c
Clean up window indexing in ext/dev.c
Aggressive checks for valid windows indexs from user space.
Remove unused variable in hdmi.c

Change-Id: Icca964b8a2e27aa947611049b79abd9833aca323
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/328426

arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/bandwidth.c
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_priv_defs.h
drivers/video/tegra/dc/ext/dev.c
drivers/video/tegra/dc/hdmi.c
drivers/video/tegra/dc/lut.c
drivers/video/tegra/dc/window.c

index cd650098ceb761da99acca586e672d0f40500bda..c01f7f631bc83bbfa927c29e538d25f0396ae76f 100644 (file)
@@ -30,9 +30,9 @@
 #define TEGRA_MAX_DC           2
 
 #if defined(CONFIG_ARCH_TEGRA_14x_SOC)
-#define DC_N_WINDOWS           5
+#define DC_N_WINDOWS           6
 #elif defined(CONFIG_ARCH_TEGRA_12x_SOC)
-#define DC_N_WINDOWS           4
+#define DC_N_WINDOWS           5
 #else
 #define DC_N_WINDOWS           3
 #endif
@@ -695,6 +695,7 @@ struct tegra_dc_win {
 #define TEGRA_WIN_FLAG_SCAN_COLUMN     (1 << 9)
 #define TEGRA_WIN_FLAG_INTERLACE       (1 << 10)
 #define TEGRA_WIN_FLAG_FB              (1 << 11)
+#define TEGRA_WIN_FLAG_INVALID         (1 << 31) /* window does not exist. */
 
 #define TEGRA_WIN_BLEND_FLAGS_MASK \
        (TEGRA_WIN_FLAG_BLEND_PREMULT | TEGRA_WIN_FLAG_BLEND_COVERAGE)
index b38099308da5dcead41193530ff4d993d80f62ac..967d973525caea2d33ca1b5a96b90ccd815b049e 100644 (file)
@@ -83,7 +83,7 @@ static unsigned int num_active_internal_wins(struct tegra_dc *dc)
        unsigned int num_active_internal_wins = 0;
        int i = 0;
 
-       for (i = 0; i < DC_N_WINDOWS; i++) {
+       for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                struct tegra_dc_win *curr_win = &dc->windows[i];
                enum tegra_la_id curr_win_la_id =
                                la_id_tab[dc->ndev->id][curr_win->idx];
@@ -103,7 +103,7 @@ static unsigned int num_active_external_wins(struct tegra_dc *dc)
        unsigned int num_active_external_wins = 0;
        int i = 0;
 
-       for (i = 0; i < DC_N_WINDOWS; i++) {
+       for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                struct tegra_dc_win *curr_win = &dc->windows[i];
                enum tegra_la_id curr_win_la_id =
                                la_id_tab[dc->ndev->id][curr_win->idx];
@@ -363,7 +363,8 @@ static void calc_disp_params(struct tegra_dc *dc,
 
        if (is_internal_win(la_id)) {
                int i = 0;
-               for (i = 0; i < DC_N_WINDOWS; i++) {
+
+               for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                        struct tegra_dc_win *curr_win = &dc->windows[i];
                        enum tegra_la_id curr_win_la_id =
                                        la_id_tab[dc->ndev->id][curr_win->idx];
@@ -383,7 +384,8 @@ static void calc_disp_params(struct tegra_dc *dc,
                }
        } else {
                int i = 0;
-               for (i = 0; i < DC_N_WINDOWS; i++) {
+
+               for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                        struct tegra_dc_win *curr_win = &dc->windows[i];
                        enum tegra_la_id curr_win_la_id =
                                        la_id_tab[dc->ndev->id][curr_win->idx];
@@ -727,7 +729,7 @@ void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new)
                dc->bw_kbps = dc->new_bw_kbps;
        }
 
-       for (i = 0; i < DC_N_WINDOWS; i++) {
+       for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                struct tegra_dc_win *w = &dc->windows[i];
 
                if ((use_new || w->bandwidth != w->new_bandwidth) &&
@@ -743,19 +745,23 @@ int tegra_dc_set_dynamic_emc(struct tegra_dc *dc)
        unsigned long new_rate;
        struct tegra_dc_win *windows[DC_N_WINDOWS];
        unsigned i;
+       unsigned len;
 
        if (!use_dynamic_emc)
                return 0;
 
-       for (i = 0; i < DC_N_WINDOWS; i++)
-               windows[i] = &dc->windows[i];
+       for (i = 0, len = 0; i < DC_N_WINDOWS; i++) {
+               struct tegra_dc_win *win = tegra_dc_get_window(dc, i);
+               if (win)
+                       windows[len++] = win;
+       }
 #ifdef CONFIG_TEGRA_ISOMGR
-       new_rate = tegra_dc_get_bandwidth(windows, DC_N_WINDOWS);
+       new_rate = tegra_dc_get_bandwidth(windows, len);
 #else
        if (tegra_dc_has_multiple_dc())
                new_rate = ULONG_MAX;
        else
-               new_rate = tegra_dc_get_bandwidth(windows, DC_N_WINDOWS);
+               new_rate = tegra_dc_get_bandwidth(windows, len);
 #endif
 
        dc->new_bw_kbps = new_rate;
index aa3d6ff137e542c15e9025615b50a29bf0cf8886..a9c541cb509f5c43f1894d4d27d3849d353f04f6 100644 (file)
@@ -978,7 +978,7 @@ 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)
+       if (win >= DC_N_WINDOWS || !test_bit(win, &dc->valid_windows))
                return NULL;
 
        return &dc->windows[win];
@@ -1666,6 +1666,16 @@ static u64 tegra_dc_underflow_count(struct tegra_dc *dc, unsigned reg)
 
 static void tegra_dc_underflow_handler(struct tegra_dc *dc)
 {
+       const u32 masks[] = {
+               WIN_A_UF_INT,
+               WIN_B_UF_INT,
+               WIN_C_UF_INT,
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC) || defined(CONFIG_ARCH_TEGRA_12x_SOC)
+               WIN_D_UF_INT,
+               HC_UF_INT,
+               WIN_T_UF_INT,
+#endif
+       };
        int i;
 
        dc->stats.underflows++;
@@ -1691,18 +1701,7 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc)
 #endif
 
        /* Check for any underflow reset conditions */
-       for (i = 0; i < DC_N_WINDOWS; i++) {
-               u32 masks[] = {
-                       WIN_A_UF_INT,
-                       WIN_B_UF_INT,
-                       WIN_C_UF_INT,
-#if defined(CONFIG_ARCH_TEGRA_14x_SOC) || defined(CONFIG_ARCH_TEGRA_12x_SOC)
-                       WIN_D_UF_INT,
-                       HC_UF_INT,
-                       WIN_T_UF_INT,
-#endif
-               };
-
+       for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                if (WARN_ONCE(i >= ARRAY_SIZE(masks),
                        "underflow stats unsupported"))
                        break; /* bail if the table above is missing entries */
@@ -2118,7 +2117,7 @@ static int tegra_dc_init(struct tegra_dc *dc)
        }
 #endif
        tegra_dc_set_color_control(dc);
-       for (i = 0; i < DC_N_WINDOWS; i++) {
+       for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                struct tegra_dc_win *win = &dc->windows[i];
                tegra_dc_writel(dc, WINDOW_A_SELECT << i,
                                DC_CMD_DISPLAY_WINDOW_HEADER);
@@ -2476,8 +2475,10 @@ void tegra_dc_blank(struct tegra_dc *dc)
        struct tegra_dc_win *dcwins[DC_N_WINDOWS];
        unsigned i;
 
-       for (i = 0; i < DC_N_WINDOWS; i++) {
+       for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                dcwins[i] = tegra_dc_get_window(dc, i);
+               if (!dcwins[i])
+                       continue;
                dcwins[i]->flags &= ~TEGRA_WIN_FLAG_ENABLED;
        }
 
@@ -2790,9 +2791,11 @@ static int tegra_dc_probe(struct platform_device *ndev)
        tegra_dc_init_lut_defaults(&dc->fb_lut);
 
        dc->n_windows = DC_N_WINDOWS;
-       for (i = 0; i < dc->n_windows; i++) {
+       for (i = 0; i < DC_N_WINDOWS; i++) {
                struct tegra_dc_win *win = &dc->windows[i];
                struct tegra_dc_win *tmp_win = &dc->tmp_wins[i];
+               if (!test_bit(i, &dc->valid_windows))
+                       win->flags |= TEGRA_WIN_FLAG_INVALID;
                win->idx = i;
                win->dc = dc;
                tmp_win->idx = i;
index ca8e0c78cd222da11a41c9919e0c85e2aeacbfe9..973f6c249f0c6fbe9fe87bbb9fc1cb05a8f897e5 100644 (file)
@@ -172,7 +172,7 @@ struct tegra_dc {
        u32                             vblank_syncpt;
        u32                             win_syncpt[DC_N_WINDOWS];
 
-       u32                             valid_windows;
+       unsigned long int               valid_windows;
 
        unsigned long                   underflow_mask;
        struct work_struct              reset_work;
index 7b6092f3a98510a28d7baa8c3aa2f676dbd8a7d2..29aa19f47eef8a235227d5bf6aa70fd16e0daf4a 100644 (file)
@@ -120,7 +120,7 @@ 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)
+       if ((n >= DC_N_WINDOWS) || !(ext->dc->valid_windows & BIT(n)))
                return -EINVAL;
 
        win = &ext->win[n];
@@ -422,10 +422,12 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
                s64 head_timestamp = 0;
                int j = 0;
 
-               if (index < 0)
+               if (index < 0 || !test_bit(index, &ext->dc->valid_windows))
                        continue;
 
                win = tegra_dc_get_window(ext->dc, index);
+               if (!win)
+                       continue;
                ext_win = &ext->win[index];
 
                if (!(atomic_dec_and_test(&ext_win->nr_pending_flips)) &&
@@ -500,7 +502,8 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
                        struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
                        int index = flip_win->attr.index;
 
-                       if (index < 0)
+                       if (index < 0 ||
+                               !test_bit(index, &ext->dc->valid_windows))
                                continue;
 
                        tegra_dc_incr_syncpt_min(ext->dc, index,
@@ -533,7 +536,7 @@ static int lock_windows_for_flip(struct tegra_dc_ext_user *user,
        for (i = 0; i < win_num; i++) {
                int index = win[i].index;
 
-               if (index < 0)
+               if (index < 0 || !test_bit(index, &ext->dc->valid_windows))
                        continue;
 
                idx_mask |= BIT(index);
@@ -578,7 +581,7 @@ static void unlock_windows_for_flip(struct tegra_dc_ext_user *user,
        for (i = 0; i < win_num; i++) {
                int index = win[i].index;
 
-               if (index < 0)
+               if (index < 0 || !test_bit(index, &ext->dc->valid_windows))
                        continue;
 
                idx_mask |= BIT(index);
@@ -597,6 +600,7 @@ static int sanitize_flip_args(struct tegra_dc_ext_user *user,
                                int win_num)
 {
        int i, used_windows = 0;
+       struct tegra_dc *dc = user->ext->dc;
 
        if (win_num > DC_N_WINDOWS)
                return -EINVAL;
@@ -607,7 +611,8 @@ static int sanitize_flip_args(struct tegra_dc_ext_user *user,
                if (index < 0)
                        continue;
 
-               if (index >= DC_N_WINDOWS)
+               if (index >= DC_N_WINDOWS ||
+                       !test_bit(index, &dc->valid_windows))
                        return -EINVAL;
 
                if (used_windows & BIT(index))
@@ -629,6 +634,7 @@ static int tegra_dc_ext_pin_windows(struct tegra_dc_ext_user *user,
                                bool *has_timestamp)
 {
        int i, ret;
+       struct tegra_dc *dc = user->ext->dc;
 
        for (i = 0; i < win_num; i++) {
                struct tegra_dc_ext_flip_win *flip_win = &flip_wins[i];
@@ -638,7 +644,7 @@ static int tegra_dc_ext_pin_windows(struct tegra_dc_ext_user *user,
                if (has_timestamp && timespec_to_ns(&flip_win->attr.timestamp))
                        *has_timestamp = true;
 
-               if (index < 0)
+               if (index < 0 || !test_bit(index, &dc->valid_windows))
                        continue;
 
                ret = tegra_dc_ext_pin_window(user, flip_win->attr.buff_id,
@@ -724,7 +730,7 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
                int index = win[i].index;
                struct tegra_dc_ext_win *ext_win;
 
-               if (index < 0)
+               if (index < 0 || !test_bit(index, &ext->dc->valid_windows))
                        continue;
 
                ext_win = &ext->win[index];
@@ -975,6 +981,8 @@ static int tegra_dc_ext_negotiate_bw(struct tegra_dc_ext_user *user,
                return -1;
 
        for (i = 0; i < win_num; i++) {
+               int idx = wins[i].index;
+
                ret = tegra_dc_ext_pin_window(user, wins[i].buff_id,
                                              &handle, &phys_addr);
                if (ret)
@@ -985,13 +993,13 @@ static int tegra_dc_ext_negotiate_bw(struct tegra_dc_ext_user *user,
                                handle->sgt, DMA_TO_DEVICE);
                        dma_buf_put(handle->buf);
                        kfree(handle);
-                       tegra_dc_ext_set_windowattr_basic(&dc->tmp_wins[i],
+                       tegra_dc_ext_set_windowattr_basic(&dc->tmp_wins[idx],
                                                          &wins[i]);
                }
                else {
                        dc->tmp_wins[i].flags = 0;
                }
-               dc_wins[i] = &dc->tmp_wins[i];
+               dc_wins[i] = &dc->tmp_wins[idx];
        }
 
        ret = tegra_dc_bandwidth_negotiate_bw(dc, dc_wins, win_num);
index c259ed2c42fdd23d0334fe64ef726dfd31549ae4..8918ef55dad1eb7458920fb1093ea6410053be2d 100644 (file)
@@ -757,8 +757,6 @@ bool tegra_dc_hdmi_mode_filter(const struct tegra_dc *dc,
 /* used by tegra_dc_probe() to detect hpd/hdmi status at boot */
 static bool tegra_dc_hdmi_detect(struct tegra_dc *dc)
 {
-       int hdmi_state;
-
        hdmi_state_machine_set_pending_hpd();
        /* result isn't used by dc */
 
index cc50c14829198e7c2d8ec015d80ea6035cb86071..4b4a1b5e9f0f70af6ce9e08e7ccc482c74467194 100644 (file)
@@ -83,8 +83,10 @@ void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win *win)
 
 static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
 {
-       struct tegra_dc_win *win = &dc->windows[win_idx];
+       struct tegra_dc_win *win = tegra_dc_get_window(dc, win_idx);
 
+       if (!win)
+               return -EINVAL;
        mutex_lock(&dc->lock);
        tegra_dc_get(dc);
 
@@ -123,7 +125,7 @@ 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 (win_idx = 0; win_idx < DC_N_WINDOWS; win_idx++) {
+       for_each_set_bit(win_idx, &dc->valid_windows, DC_N_WINDOWS) {
                int err = tegra_dc_update_winlut(dc, win_idx, fboveride);
                if (err)
                        return err;
index ad6007cdce36a968d89e8afd42810d34d98b508d..fab178f1f0bdf967a5e12723f85c80fa710bd9c0 100644 (file)
@@ -827,7 +827,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
                if (update_blend_seq)
                        tegra_dc_blend_sequential(dc, &dc->blend);
 
-               for (i = 0; i < DC_N_WINDOWS; i++) {
+               for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                        if (!no_vsync)
                                dc->windows[i].dirty = 1;
                        update_mask |= WIN_A_ACT_REQ << i;
@@ -904,7 +904,7 @@ void tegra_dc_trigger_windows(struct tegra_dc *dc)
 #endif
 
        val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
-       for (i = 0; i < DC_N_WINDOWS; i++) {
+       for_each_set_bit(i, &dc->valid_windows, DC_N_WINDOWS) {
                if (tegra_platform_is_linsim()) {
                        /* FIXME: this is not needed when
                           the simulator clears WIN_x_UPDATE