int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user, struct tegra_dc_ext_cursor_image *args) { struct tegra_dc_ext *ext = user->ext; struct tegra_dc *dc = ext->dc; struct nvmap_handle_ref *handle, *old_handle; dma_addr_t phys_addr; u32 size; int ret; if (!user->nvmap) return -EFAULT; size = TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE(args->flags); #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) if (size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64) return -EINVAL; #else if (size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_128x128 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_256x256) return -EINVAL; #endif #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) if (args->flags && TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL) return -EINVAL; #endif mutex_lock(&ext->cursor.lock); if (ext->cursor.user != user) { ret = -EACCES; goto unlock; } if (!ext->enabled) { ret = -ENXIO; goto unlock; } old_handle = ext->cursor.cur_handle; ret = tegra_dc_ext_pin_window(user, args->buff_id, &handle, &phys_addr); if (ret) goto unlock; ext->cursor.cur_handle = handle; mutex_lock(&dc->lock); tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); set_cursor_image_hw(dc, args, phys_addr); tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); tegra_dc_release_dc_out(dc); tegra_dc_io_end(dc); /* XXX sync here? */ mutex_unlock(&dc->lock); mutex_unlock(&ext->cursor.lock); if (old_handle) { nvmap_unpin(ext->nvmap, old_handle); nvmap_free(ext->nvmap, old_handle); } return 0; unlock: mutex_unlock(&ext->cursor.lock); return ret; }
int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user, struct tegra_dc_ext_cursor_image *args) { struct tegra_dc_ext *ext = user->ext; struct tegra_dc *dc = ext->dc; struct nvmap_handle_ref *handle, *old_handle; dma_addr_t phys_addr; u32 size; int ret; if (!user->nvmap) return -EFAULT; size = args->flags & (TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 | TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64); if (size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64) return -EINVAL; mutex_lock(&ext->cursor.lock); if (ext->cursor.user != user) { ret = -EACCES; goto unlock; } if (!ext->enabled) { ret = -ENXIO; goto unlock; } old_handle = ext->cursor.cur_handle; ret = tegra_dc_ext_pin_window(user, args->buff_id, &handle, &phys_addr); if (ret) goto unlock; ext->cursor.cur_handle = handle; mutex_lock(&dc->lock); set_cursor_image_hw(dc, args, phys_addr); tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); /* XXX sync here? */ mutex_unlock(&dc->lock); mutex_unlock(&ext->cursor.lock); if (old_handle) { nvmap_unpin(ext->nvmap, old_handle); nvmap_free(ext->nvmap, old_handle); } return 0; unlock: mutex_unlock(&ext->cursor.lock); return ret; }