static int tegra_overlay_flip(struct tegra_overlay_info *overlay, struct tegra_overlay_flip_args *args, struct nvmap_client *user_nvmap) { struct tegra_overlay_flip_data *data; struct tegra_overlay_flip_win *flip_win; u32 syncpt_max; int i, err; if (WARN_ON(!overlay->ndev)) return -EFAULT; data = kzalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) { dev_err(&overlay->ndev->dev, "can't allocate memory for flip\n"); return -ENOMEM; } INIT_WORK(&data->work, tegra_overlay_flip_worker); data->overlay = overlay; for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) { flip_win = &data->win[i]; memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr)); if (flip_win->attr.index == -1) continue; err = tegra_overlay_pin_window(overlay, flip_win, user_nvmap); if (err < 0) { dev_err(&overlay->ndev->dev, "error setting window attributes\n"); goto surf_err; } } syncpt_max = tegra_dc_incr_syncpt_max(overlay->dc); data->syncpt_max = syncpt_max; queue_work(overlay->flip_wq, &data->work); args->post_syncpt_val = syncpt_max; args->post_syncpt_id = tegra_dc_get_syncpt_id(overlay->dc); return 0; surf_err: while (i--) { if (data->win[i].handle) { nvmap_unpin(overlay->overlay_nvmap, data->win[i].handle); nvmap_free(overlay->overlay_nvmap, data->win[i].handle); } } kfree(data); return err; }
static int tegra_overlay_flip(struct tegra_overlay_info *overlay, struct tegra_overlay_flip_args *args, struct nvmap_client *user_nvmap) { struct tegra_overlay_flip_data *data; struct tegra_overlay_flip_win *flip_win; u32 syncpt_max; int i, err; if (WARN_ON(!overlay->ndev)) return -EFAULT; mutex_lock(&tegra_flip_lock); if (!overlay->dc->enabled) { mutex_unlock(&tegra_flip_lock); return -EFAULT; } data = kzalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) { dev_err(&overlay->ndev->dev, "can't allocate memory for flip\n"); mutex_unlock(&tegra_flip_lock); return -ENOMEM; } INIT_WORK(&data->work, tegra_overlay_flip_worker); data->overlay = overlay; data->flags = args->flags; for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) { flip_win = &data->win[i]; memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr)); if (flip_win->attr.index == -1) continue; err = tegra_overlay_pin_window(overlay, flip_win, user_nvmap); if (err < 0) { dev_err(&overlay->ndev->dev, "error setting window attributes\n"); goto surf_err; } } syncpt_max = tegra_dc_incr_syncpt_max(overlay->dc); data->syncpt_max = syncpt_max; queue_work(overlay->flip_wq, &data->work); /* * Before the queued flip_wq get scheduled, we set the EMC clock to the * default value in order to do FLIP without glitch. */ tegra_dc_set_default_emc(overlay->dc); args->post_syncpt_val = syncpt_max; args->post_syncpt_id = tegra_dc_get_syncpt_id(overlay->dc); mutex_unlock(&tegra_flip_lock); return 0; surf_err: while (i--) { if (data->win[i].handle) { nvmap_unpin(overlay->overlay_nvmap, data->win[i].handle); nvmap_free(overlay->overlay_nvmap, data->win[i].handle); } } kfree(data); mutex_unlock(&tegra_flip_lock); return err; }