static void tegra_overlay_flip_worker(struct work_struct *work) { struct tegra_overlay_flip_data *data = container_of(work, struct tegra_overlay_flip_data, work); struct tegra_overlay_info *overlay = data->overlay; struct tegra_dc_win *win; struct tegra_dc_win *wins[TEGRA_FB_FLIP_N_WINDOWS]; struct nvmap_handle_ref *unpin_handles[TEGRA_FB_FLIP_N_WINDOWS]; int i, nr_win = 0, nr_unpin = 0; data = container_of(work, struct tegra_overlay_flip_data, work); for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) { struct tegra_overlay_flip_win *flip_win = &data->win[i]; int idx = flip_win->attr.index; if (idx == -1) continue; win = tegra_dc_get_window(overlay->dc, idx); if (!win) continue; if (win->flags && win->cur_handle) unpin_handles[nr_unpin++] = win->cur_handle; tegra_overlay_set_windowattr(overlay, win, &data->win[i]); wins[nr_win++] = win; #if 0 if (flip_win->attr.pre_syncpt_id < 0) continue; printk("%08x %08x\n", flip_win->attr.pre_syncpt_id, flip_win->attr.pre_syncpt_val); nvhost_syncpt_wait_timeout(&overlay->ndev->host->syncpt, flip_win->attr.pre_syncpt_id, flip_win->attr.pre_syncpt_val, msecs_to_jiffies(500)); #endif } tegra_dc_update_windows(wins, nr_win); /* TODO: implement swapinterval here */ tegra_dc_sync_windows(wins, nr_win); tegra_dc_incr_syncpt_min(overlay->dc, data->syncpt_max); /* unpin and deref previous front buffers */ for (i = 0; i < nr_unpin; i++) { nvmap_unpin(overlay->overlay_nvmap, unpin_handles[i]); nvmap_free(overlay->overlay_nvmap, unpin_handles[i]); } kfree(data); }
/* make the screen blank by disabling all windows */ 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++) { dcwins[i] = tegra_dc_get_window(dc, i); dcwins[i]->flags &= ~TEGRA_WIN_FLAG_ENABLED; } tegra_dc_update_windows(dcwins, DC_N_WINDOWS); tegra_dc_sync_windows(dcwins, DC_N_WINDOWS); }
static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr) { struct tegra_dc_win *win = &dc->windows[win_idx]; mutex_lock(&dc->lock); tegra_dc_get(dc); if (!dc->enabled) { tegra_dc_put(dc); mutex_unlock(&dc->lock); return -EFAULT; } if (fbovr > 0) win->ppflags |= TEGRA_WIN_PPFLAG_CP_FBOVERRIDE; else if (fbovr == 0) win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_FBOVERRIDE; if (!tegra_dc_loop_lut(dc, win, tegra_dc_lut_isdefaults_lambda)) win->ppflags |= TEGRA_WIN_PPFLAG_CP_ENABLE; else win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_ENABLE; tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx, DC_CMD_DISPLAY_WINDOW_HEADER); tegra_dc_set_lut(dc, win); mutex_unlock(&dc->lock); tegra_dc_update_windows(&win, 1); tegra_dc_sync_windows(&win, 1); tegra_dc_put(dc); return 0; }
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); struct tegra_dc_ext *ext = data->ext; struct tegra_dc_win *wins[DC_N_WINDOWS]; struct nvmap_handle_ref *unpin_handles[DC_N_WINDOWS * TEGRA_DC_NUM_PLANES]; int i, nr_unpin = 0, nr_win = 0; 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; struct tegra_dc_win *win; struct tegra_dc_ext_win *ext_win; if (index < 0) continue; win = tegra_dc_get_window(ext->dc, index); ext_win = &ext->win[index]; if (win->flags & TEGRA_WIN_FLAG_ENABLED) { int j; for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) { if (!ext_win->cur_handle[j]) continue; unpin_handles[nr_unpin++] = ext_win->cur_handle[j]; } } tegra_dc_ext_set_windowattr(ext, win, &data->win[i]); wins[nr_win++] = win; } tegra_dc_update_windows(wins, nr_win); /* TODO: implement swapinterval here */ tegra_dc_sync_windows(wins, nr_win); 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; if (index < 0) continue; tegra_dc_incr_syncpt_min(ext->dc, index, flip_win->syncpt_max); } /* unpin and deref previous front buffers */ for (i = 0; i < nr_unpin; i++) { nvmap_unpin(ext->nvmap, unpin_handles[i]); nvmap_free(ext->nvmap, unpin_handles[i]); } kfree(data); }
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); struct tegra_dc_ext *ext = data->ext; 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 < DC_N_WINDOWS; i++) { struct tegra_dc_ext_flip_win *flip_win = &data->win[i]; int index = flip_win->attr.index; struct tegra_dc_win *win; struct tegra_dc_ext_win *ext_win; if (index < 0) continue; win = tegra_dc_get_window(ext->dc, index); ext_win = &ext->win[index]; if (!(atomic_dec_and_test(&ext_win->nr_pending_flips)) && (flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_CURSOR)) skip_flip = true; if (skip_flip) old_handle = flip_win->handle[TEGRA_DC_Y]; else old_handle = ext_win->cur_handle[TEGRA_DC_Y]; if (old_handle) { int j; for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) { if (skip_flip) old_handle = flip_win->handle[j]; else old_handle = ext_win->cur_handle[j]; if (!old_handle) continue; unpin_handles[nr_unpin++] = old_handle; } } if (!skip_flip) tegra_dc_ext_set_windowattr(ext, win, &data->win[i]); wins[nr_win++] = win; } if (!skip_flip) { tegra_dc_update_windows(wins, nr_win); /* TODO: implement swapinterval here */ tegra_dc_sync_windows(wins, nr_win); } 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; if (index < 0) continue; tegra_dc_incr_syncpt_min(ext->dc, index, flip_win->syncpt_max); } /* unpin and deref previous front buffers */ for (i = 0; i < nr_unpin; i++) { nvmap_unpin(ext->nvmap, unpin_handles[i]); nvmap_free(ext->nvmap, unpin_handles[i]); } kfree(data); }
static void tegra_overlay_flip_worker(struct work_struct *work) { struct tegra_overlay_flip_data *data = container_of(work, struct tegra_overlay_flip_data, work); struct tegra_overlay_info *overlay = data->overlay; struct tegra_dc_win *win; struct tegra_dc_win *wins[TEGRA_FB_FLIP_N_WINDOWS]; struct nvmap_handle_ref *unpin_handles[TEGRA_FB_FLIP_N_WINDOWS]; int i, nr_win = 0, nr_unpin = 0; data = container_of(work, struct tegra_overlay_flip_data, work); for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) { struct tegra_overlay_flip_win *flip_win = &data->win[i]; int idx = flip_win->attr.index; if (idx == -1) continue; win = tegra_dc_get_window(overlay->dc, idx); if (!win) continue; if (win->flags && win->cur_handle && !data->didim_work) unpin_handles[nr_unpin++] = win->cur_handle; tegra_overlay_set_windowattr(overlay, win, &data->win[i]); wins[nr_win++] = win; #if 0 if (flip_win->attr.pre_syncpt_id < 0) continue; printk("%08x %08x\n", flip_win->attr.pre_syncpt_id, flip_win->attr.pre_syncpt_val); nvhost_syncpt_wait_timeout(&nvhost_get_host(overlay->ndev)->syncpt, flip_win->attr.pre_syncpt_id, flip_win->attr.pre_syncpt_val, msecs_to_jiffies(500)); #endif } if (data->flags & TEGRA_OVERLAY_FLIP_FLAG_BLEND_REORDER) { struct tegra_dc_win *dcwins[DC_N_WINDOWS]; for (i = 0; i < DC_N_WINDOWS; i++) dcwins[i] = tegra_dc_get_window(overlay->dc, i); tegra_overlay_blend_reorder(&overlay->blend, dcwins); tegra_dc_update_windows(dcwins, DC_N_WINDOWS); tegra_dc_sync_windows(dcwins, DC_N_WINDOWS); } else { tegra_dc_update_windows(wins, nr_win); /* TODO: implement swapinterval here */ tegra_dc_sync_windows(wins, nr_win); } if ((overlay->dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) && (overlay->dc->out->flags & TEGRA_DC_OUT_N_SHOT_MODE)) { tegra_overlay_n_shot(data, unpin_handles, &nr_unpin); } else { tegra_dc_incr_syncpt_min(overlay->dc, 0, data->syncpt_max); /* unpin and deref previous front buffers */ for (i = 0; i < nr_unpin; i++) { nvmap_unpin(overlay->overlay_nvmap, unpin_handles[i]); nvmap_free(overlay->overlay_nvmap, unpin_handles[i]); } kfree(data); } }
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); struct tegra_dc_ext *ext = data->ext; struct tegra_dc_win *wins[DC_N_WINDOWS]; struct nvmap_handle_ref *unpin_handles[DC_N_WINDOWS]; int i, nr_unpin = 0, nr_win = 0, nr_disable = 0; 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; struct tegra_dc_win *win; struct tegra_dc_ext_win *ext_win; bool old_ena, new_ena; if (index < 0) continue; win = tegra_dc_get_window(ext->dc, index); ext_win = &ext->win[index]; old_ena = ext->win[index].enabled; new_ena = flip_win->handle != NULL; if (old_ena != new_ena) { if (new_ena) process_window_change(ext, 1); else nr_disable++; } ext->win[index].enabled = new_ena; if (old_ena && ext_win->cur_handle) unpin_handles[nr_unpin++] = ext_win->cur_handle; tegra_dc_ext_set_windowattr(ext, win, &data->win[i]); wins[nr_win++] = win; } tegra_dc_update_windows(wins, nr_win); /* TODO: implement swapinterval here */ tegra_dc_sync_windows(wins, nr_win); 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; if (index < 0) continue; tegra_dc_incr_syncpt_min(ext->dc, index, flip_win->syncpt_max); } /* unpin and deref previous front buffers */ for (i = 0; i < nr_unpin; i++) { nvmap_unpin(ext->nvmap, unpin_handles[i]); nvmap_free(ext->nvmap, unpin_handles[i]); } if (nr_disable) process_window_change(ext, -nr_disable); kfree(data); }