162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/drivers/video/omap2/omapfb-ioctl.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2008 Nokia Corporation 662306a36Sopenharmony_ci * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Some code and ideas taken from drivers/video/omap/ driver 962306a36Sopenharmony_ci * by Imre Deak. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/fb.h> 1362306a36Sopenharmony_ci#include <linux/device.h> 1462306a36Sopenharmony_ci#include <linux/uaccess.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/mm.h> 1762306a36Sopenharmony_ci#include <linux/omapfb.h> 1862306a36Sopenharmony_ci#include <linux/vmalloc.h> 1962306a36Sopenharmony_ci#include <linux/export.h> 2062306a36Sopenharmony_ci#include <linux/sizes.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <video/omapfb_dss.h> 2362306a36Sopenharmony_ci#include <video/omapvrfb.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "omapfb.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic u8 get_mem_idx(struct omapfb_info *ofbi) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci if (ofbi->id == ofbi->region->id) 3062306a36Sopenharmony_ci return 0; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id; 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi, 3662306a36Sopenharmony_ci u8 mem_idx) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct omapfb2_device *fbdev = ofbi->fbdev; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (mem_idx & OMAPFB_MEM_IDX_ENABLED) 4162306a36Sopenharmony_ci mem_idx &= OMAPFB_MEM_IDX_MASK; 4262306a36Sopenharmony_ci else 4362306a36Sopenharmony_ci mem_idx = ofbi->id; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (mem_idx >= fbdev->num_fbs) 4662306a36Sopenharmony_ci return NULL; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci return &fbdev->regions[mem_idx]; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 5462306a36Sopenharmony_ci struct omapfb2_device *fbdev = ofbi->fbdev; 5562306a36Sopenharmony_ci struct omap_overlay *ovl; 5662306a36Sopenharmony_ci struct omap_overlay_info old_info; 5762306a36Sopenharmony_ci struct omapfb2_mem_region *old_rg, *new_rg; 5862306a36Sopenharmony_ci int r = 0; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci DBG("omapfb_setup_plane\n"); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if (ofbi->num_overlays == 0) { 6362306a36Sopenharmony_ci r = -EINVAL; 6462306a36Sopenharmony_ci goto out; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* XXX uses only the first overlay */ 6862306a36Sopenharmony_ci ovl = ofbi->overlays[0]; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci old_rg = ofbi->region; 7162306a36Sopenharmony_ci new_rg = get_mem_region(ofbi, pi->mem_idx); 7262306a36Sopenharmony_ci if (!new_rg) { 7362306a36Sopenharmony_ci r = -EINVAL; 7462306a36Sopenharmony_ci goto out; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* Take the locks in a specific order to keep lockdep happy */ 7862306a36Sopenharmony_ci if (old_rg->id < new_rg->id) { 7962306a36Sopenharmony_ci omapfb_get_mem_region(old_rg); 8062306a36Sopenharmony_ci omapfb_get_mem_region(new_rg); 8162306a36Sopenharmony_ci } else if (new_rg->id < old_rg->id) { 8262306a36Sopenharmony_ci omapfb_get_mem_region(new_rg); 8362306a36Sopenharmony_ci omapfb_get_mem_region(old_rg); 8462306a36Sopenharmony_ci } else 8562306a36Sopenharmony_ci omapfb_get_mem_region(old_rg); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (pi->enabled && !new_rg->size) { 8862306a36Sopenharmony_ci /* 8962306a36Sopenharmony_ci * This plane's memory was freed, can't enable it 9062306a36Sopenharmony_ci * until it's reallocated. 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_ci r = -EINVAL; 9362306a36Sopenharmony_ci goto put_mem; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci ovl->get_overlay_info(ovl, &old_info); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (old_rg != new_rg) { 9962306a36Sopenharmony_ci ofbi->region = new_rg; 10062306a36Sopenharmony_ci set_fb_fix(fbi); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if (!pi->enabled) { 10462306a36Sopenharmony_ci r = ovl->disable(ovl); 10562306a36Sopenharmony_ci if (r) 10662306a36Sopenharmony_ci goto undo; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (pi->enabled) { 11062306a36Sopenharmony_ci r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y, 11162306a36Sopenharmony_ci pi->out_width, pi->out_height); 11262306a36Sopenharmony_ci if (r) 11362306a36Sopenharmony_ci goto undo; 11462306a36Sopenharmony_ci } else { 11562306a36Sopenharmony_ci struct omap_overlay_info info; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci ovl->get_overlay_info(ovl, &info); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci info.pos_x = pi->pos_x; 12062306a36Sopenharmony_ci info.pos_y = pi->pos_y; 12162306a36Sopenharmony_ci info.out_width = pi->out_width; 12262306a36Sopenharmony_ci info.out_height = pi->out_height; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci r = ovl->set_overlay_info(ovl, &info); 12562306a36Sopenharmony_ci if (r) 12662306a36Sopenharmony_ci goto undo; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (ovl->manager) { 13062306a36Sopenharmony_ci r = ovl->manager->apply(ovl->manager); 13162306a36Sopenharmony_ci if (r) 13262306a36Sopenharmony_ci goto undo; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (pi->enabled) { 13662306a36Sopenharmony_ci r = ovl->enable(ovl); 13762306a36Sopenharmony_ci if (r) 13862306a36Sopenharmony_ci goto undo; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* Release the locks in a specific order to keep lockdep happy */ 14262306a36Sopenharmony_ci if (old_rg->id > new_rg->id) { 14362306a36Sopenharmony_ci omapfb_put_mem_region(old_rg); 14462306a36Sopenharmony_ci omapfb_put_mem_region(new_rg); 14562306a36Sopenharmony_ci } else if (new_rg->id > old_rg->id) { 14662306a36Sopenharmony_ci omapfb_put_mem_region(new_rg); 14762306a36Sopenharmony_ci omapfb_put_mem_region(old_rg); 14862306a36Sopenharmony_ci } else 14962306a36Sopenharmony_ci omapfb_put_mem_region(old_rg); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci return 0; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci undo: 15462306a36Sopenharmony_ci if (old_rg != new_rg) { 15562306a36Sopenharmony_ci ofbi->region = old_rg; 15662306a36Sopenharmony_ci set_fb_fix(fbi); 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci ovl->set_overlay_info(ovl, &old_info); 16062306a36Sopenharmony_ci put_mem: 16162306a36Sopenharmony_ci /* Release the locks in a specific order to keep lockdep happy */ 16262306a36Sopenharmony_ci if (old_rg->id > new_rg->id) { 16362306a36Sopenharmony_ci omapfb_put_mem_region(old_rg); 16462306a36Sopenharmony_ci omapfb_put_mem_region(new_rg); 16562306a36Sopenharmony_ci } else if (new_rg->id > old_rg->id) { 16662306a36Sopenharmony_ci omapfb_put_mem_region(new_rg); 16762306a36Sopenharmony_ci omapfb_put_mem_region(old_rg); 16862306a36Sopenharmony_ci } else 16962306a36Sopenharmony_ci omapfb_put_mem_region(old_rg); 17062306a36Sopenharmony_ci out: 17162306a36Sopenharmony_ci dev_err(fbdev->dev, "setup_plane failed\n"); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci return r; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if (ofbi->num_overlays == 0) { 18162306a36Sopenharmony_ci memset(pi, 0, sizeof(*pi)); 18262306a36Sopenharmony_ci } else { 18362306a36Sopenharmony_ci struct omap_overlay *ovl; 18462306a36Sopenharmony_ci struct omap_overlay_info ovli; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci ovl = ofbi->overlays[0]; 18762306a36Sopenharmony_ci ovl->get_overlay_info(ovl, &ovli); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci pi->pos_x = ovli.pos_x; 19062306a36Sopenharmony_ci pi->pos_y = ovli.pos_y; 19162306a36Sopenharmony_ci pi->enabled = ovl->is_enabled(ovl); 19262306a36Sopenharmony_ci pi->channel_out = 0; /* xxx */ 19362306a36Sopenharmony_ci pi->mirror = 0; 19462306a36Sopenharmony_ci pi->mem_idx = get_mem_idx(ofbi); 19562306a36Sopenharmony_ci pi->out_width = ovli.out_width; 19662306a36Sopenharmony_ci pi->out_height = ovli.out_height; 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci return 0; 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 20562306a36Sopenharmony_ci struct omapfb2_device *fbdev = ofbi->fbdev; 20662306a36Sopenharmony_ci struct omap_dss_device *display = fb2display(fbi); 20762306a36Sopenharmony_ci struct omapfb2_mem_region *rg; 20862306a36Sopenharmony_ci int r = 0, i; 20962306a36Sopenharmony_ci size_t size; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci if (mi->type != OMAPFB_MEMTYPE_SDRAM) 21262306a36Sopenharmony_ci return -EINVAL; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci size = PAGE_ALIGN(mi->size); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (display && display->driver->sync) 21762306a36Sopenharmony_ci display->driver->sync(display); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci rg = ofbi->region; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci down_write_nested(&rg->lock, rg->id); 22262306a36Sopenharmony_ci atomic_inc(&rg->lock_count); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci if (rg->size == size && rg->type == mi->type) 22562306a36Sopenharmony_ci goto out; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (atomic_read(&rg->map_count)) { 22862306a36Sopenharmony_ci r = -EBUSY; 22962306a36Sopenharmony_ci goto out; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci for (i = 0; i < fbdev->num_fbs; i++) { 23362306a36Sopenharmony_ci struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]); 23462306a36Sopenharmony_ci int j; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (ofbi2->region != rg) 23762306a36Sopenharmony_ci continue; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci for (j = 0; j < ofbi2->num_overlays; j++) { 24062306a36Sopenharmony_ci struct omap_overlay *ovl; 24162306a36Sopenharmony_ci ovl = ofbi2->overlays[j]; 24262306a36Sopenharmony_ci if (ovl->is_enabled(ovl)) { 24362306a36Sopenharmony_ci r = -EBUSY; 24462306a36Sopenharmony_ci goto out; 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci r = omapfb_realloc_fbmem(fbi, size, mi->type); 25062306a36Sopenharmony_ci if (r) { 25162306a36Sopenharmony_ci dev_err(fbdev->dev, "realloc fbmem failed\n"); 25262306a36Sopenharmony_ci goto out; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci out: 25662306a36Sopenharmony_ci atomic_dec(&rg->lock_count); 25762306a36Sopenharmony_ci up_write(&rg->lock); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci return r; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 26562306a36Sopenharmony_ci struct omapfb2_mem_region *rg; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci rg = omapfb_get_mem_region(ofbi->region); 26862306a36Sopenharmony_ci memset(mi, 0, sizeof(*mi)); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci mi->size = rg->size; 27162306a36Sopenharmony_ci mi->type = rg->type; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci omapfb_put_mem_region(rg); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci return 0; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic int omapfb_update_window(struct fb_info *fbi, 27962306a36Sopenharmony_ci u32 x, u32 y, u32 w, u32 h) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci struct omap_dss_device *display = fb2display(fbi); 28262306a36Sopenharmony_ci u16 dw, dh; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (!display) 28562306a36Sopenharmony_ci return 0; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (w == 0 || h == 0) 28862306a36Sopenharmony_ci return 0; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci display->driver->get_resolution(display, &dw, &dh); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (x + w > dw || y + h > dh) 29362306a36Sopenharmony_ci return -EINVAL; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci return display->driver->update(display, x, y, w, h); 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ciint omapfb_set_update_mode(struct fb_info *fbi, 29962306a36Sopenharmony_ci enum omapfb_update_mode mode) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct omap_dss_device *display = fb2display(fbi); 30262306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 30362306a36Sopenharmony_ci struct omapfb2_device *fbdev = ofbi->fbdev; 30462306a36Sopenharmony_ci struct omapfb_display_data *d; 30562306a36Sopenharmony_ci int r; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (!display) 30862306a36Sopenharmony_ci return -EINVAL; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE) 31162306a36Sopenharmony_ci return -EINVAL; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci omapfb_lock(fbdev); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci d = get_display_data(fbdev, display); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci if (d->update_mode == mode) { 31862306a36Sopenharmony_ci omapfb_unlock(fbdev); 31962306a36Sopenharmony_ci return 0; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci r = 0; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { 32562306a36Sopenharmony_ci if (mode == OMAPFB_AUTO_UPDATE) 32662306a36Sopenharmony_ci omapfb_start_auto_update(fbdev, display); 32762306a36Sopenharmony_ci else /* MANUAL_UPDATE */ 32862306a36Sopenharmony_ci omapfb_stop_auto_update(fbdev, display); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci d->update_mode = mode; 33162306a36Sopenharmony_ci } else { /* AUTO_UPDATE */ 33262306a36Sopenharmony_ci if (mode == OMAPFB_MANUAL_UPDATE) 33362306a36Sopenharmony_ci r = -EINVAL; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci omapfb_unlock(fbdev); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci return r; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ciint omapfb_get_update_mode(struct fb_info *fbi, 34262306a36Sopenharmony_ci enum omapfb_update_mode *mode) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct omap_dss_device *display = fb2display(fbi); 34562306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 34662306a36Sopenharmony_ci struct omapfb2_device *fbdev = ofbi->fbdev; 34762306a36Sopenharmony_ci struct omapfb_display_data *d; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (!display) 35062306a36Sopenharmony_ci return -EINVAL; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci omapfb_lock(fbdev); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci d = get_display_data(fbdev, display); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci *mode = d->update_mode; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci omapfb_unlock(fbdev); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci return 0; 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci/* XXX this color key handling is a hack... */ 36462306a36Sopenharmony_cistatic struct omapfb_color_key omapfb_color_keys[2]; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic int _omapfb_set_color_key(struct omap_overlay_manager *mgr, 36762306a36Sopenharmony_ci struct omapfb_color_key *ck) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct omap_overlay_manager_info info; 37062306a36Sopenharmony_ci enum omap_dss_trans_key_type kt; 37162306a36Sopenharmony_ci int r; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci mgr->get_manager_info(mgr, &info); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) { 37662306a36Sopenharmony_ci info.trans_enabled = false; 37762306a36Sopenharmony_ci omapfb_color_keys[mgr->id] = *ck; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci r = mgr->set_manager_info(mgr, &info); 38062306a36Sopenharmony_ci if (r) 38162306a36Sopenharmony_ci return r; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci r = mgr->apply(mgr); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci return r; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci switch (ck->key_type) { 38962306a36Sopenharmony_ci case OMAPFB_COLOR_KEY_GFX_DST: 39062306a36Sopenharmony_ci kt = OMAP_DSS_COLOR_KEY_GFX_DST; 39162306a36Sopenharmony_ci break; 39262306a36Sopenharmony_ci case OMAPFB_COLOR_KEY_VID_SRC: 39362306a36Sopenharmony_ci kt = OMAP_DSS_COLOR_KEY_VID_SRC; 39462306a36Sopenharmony_ci break; 39562306a36Sopenharmony_ci default: 39662306a36Sopenharmony_ci return -EINVAL; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci info.default_color = ck->background; 40062306a36Sopenharmony_ci info.trans_key = ck->trans_key; 40162306a36Sopenharmony_ci info.trans_key_type = kt; 40262306a36Sopenharmony_ci info.trans_enabled = true; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci omapfb_color_keys[mgr->id] = *ck; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci r = mgr->set_manager_info(mgr, &info); 40762306a36Sopenharmony_ci if (r) 40862306a36Sopenharmony_ci return r; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci r = mgr->apply(mgr); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci return r; 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic int omapfb_set_color_key(struct fb_info *fbi, 41662306a36Sopenharmony_ci struct omapfb_color_key *ck) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 41962306a36Sopenharmony_ci struct omapfb2_device *fbdev = ofbi->fbdev; 42062306a36Sopenharmony_ci int r; 42162306a36Sopenharmony_ci int i; 42262306a36Sopenharmony_ci struct omap_overlay_manager *mgr = NULL; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci omapfb_lock(fbdev); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci for (i = 0; i < ofbi->num_overlays; i++) { 42762306a36Sopenharmony_ci if (ofbi->overlays[i]->manager) { 42862306a36Sopenharmony_ci mgr = ofbi->overlays[i]->manager; 42962306a36Sopenharmony_ci break; 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci if (!mgr) { 43462306a36Sopenharmony_ci r = -EINVAL; 43562306a36Sopenharmony_ci goto err; 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci r = _omapfb_set_color_key(mgr, ck); 43962306a36Sopenharmony_cierr: 44062306a36Sopenharmony_ci omapfb_unlock(fbdev); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci return r; 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic int omapfb_get_color_key(struct fb_info *fbi, 44662306a36Sopenharmony_ci struct omapfb_color_key *ck) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 44962306a36Sopenharmony_ci struct omapfb2_device *fbdev = ofbi->fbdev; 45062306a36Sopenharmony_ci struct omap_overlay_manager *mgr = NULL; 45162306a36Sopenharmony_ci int r = 0; 45262306a36Sopenharmony_ci int i; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci omapfb_lock(fbdev); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci for (i = 0; i < ofbi->num_overlays; i++) { 45762306a36Sopenharmony_ci if (ofbi->overlays[i]->manager) { 45862306a36Sopenharmony_ci mgr = ofbi->overlays[i]->manager; 45962306a36Sopenharmony_ci break; 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (!mgr) { 46462306a36Sopenharmony_ci r = -EINVAL; 46562306a36Sopenharmony_ci goto err; 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci *ck = omapfb_color_keys[mgr->id]; 46962306a36Sopenharmony_cierr: 47062306a36Sopenharmony_ci omapfb_unlock(fbdev); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci return r; 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic int omapfb_memory_read(struct fb_info *fbi, 47662306a36Sopenharmony_ci struct omapfb_memory_read *mr) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct omap_dss_device *display = fb2display(fbi); 47962306a36Sopenharmony_ci void *buf; 48062306a36Sopenharmony_ci int r; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci if (!display || !display->driver->memory_read) 48362306a36Sopenharmony_ci return -ENOENT; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci if (mr->w > 4096 || mr->h > 4096) 48662306a36Sopenharmony_ci return -EINVAL; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci if (mr->w * mr->h * 3 > mr->buffer_size) 48962306a36Sopenharmony_ci return -EINVAL; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci buf = vmalloc(mr->buffer_size); 49262306a36Sopenharmony_ci if (!buf) { 49362306a36Sopenharmony_ci DBG("vmalloc failed\n"); 49462306a36Sopenharmony_ci return -ENOMEM; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci r = display->driver->memory_read(display, buf, mr->buffer_size, 49862306a36Sopenharmony_ci mr->x, mr->y, mr->w, mr->h); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci if (r > 0) { 50162306a36Sopenharmony_ci if (copy_to_user(mr->buffer, buf, r)) 50262306a36Sopenharmony_ci r = -EFAULT; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci vfree(buf); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci return r; 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cistatic int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev, 51162306a36Sopenharmony_ci struct omapfb_ovl_colormode *mode) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci int ovl_idx = mode->overlay_idx; 51462306a36Sopenharmony_ci int mode_idx = mode->mode_idx; 51562306a36Sopenharmony_ci struct omap_overlay *ovl; 51662306a36Sopenharmony_ci enum omap_color_mode supported_modes; 51762306a36Sopenharmony_ci struct fb_var_screeninfo var; 51862306a36Sopenharmony_ci int i; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci if (ovl_idx >= fbdev->num_overlays) 52162306a36Sopenharmony_ci return -ENODEV; 52262306a36Sopenharmony_ci ovl = fbdev->overlays[ovl_idx]; 52362306a36Sopenharmony_ci supported_modes = ovl->supported_modes; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci mode_idx = mode->mode_idx; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci for (i = 0; i < sizeof(supported_modes) * 8; i++) { 52862306a36Sopenharmony_ci if (!(supported_modes & (1 << i))) 52962306a36Sopenharmony_ci continue; 53062306a36Sopenharmony_ci /* 53162306a36Sopenharmony_ci * It's possible that the FB doesn't support a mode 53262306a36Sopenharmony_ci * that is supported by the overlay, so call the 53362306a36Sopenharmony_ci * following here. 53462306a36Sopenharmony_ci */ 53562306a36Sopenharmony_ci if (dss_mode_to_fb_mode(1 << i, &var) < 0) 53662306a36Sopenharmony_ci continue; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci mode_idx--; 53962306a36Sopenharmony_ci if (mode_idx < 0) 54062306a36Sopenharmony_ci break; 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci if (i == sizeof(supported_modes) * 8) 54462306a36Sopenharmony_ci return -ENOENT; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci mode->bits_per_pixel = var.bits_per_pixel; 54762306a36Sopenharmony_ci mode->nonstd = var.nonstd; 54862306a36Sopenharmony_ci mode->red = var.red; 54962306a36Sopenharmony_ci mode->green = var.green; 55062306a36Sopenharmony_ci mode->blue = var.blue; 55162306a36Sopenharmony_ci mode->transp = var.transp; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci return 0; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_cistatic int omapfb_wait_for_go(struct fb_info *fbi) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 55962306a36Sopenharmony_ci int r = 0; 56062306a36Sopenharmony_ci int i; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci for (i = 0; i < ofbi->num_overlays; ++i) { 56362306a36Sopenharmony_ci struct omap_overlay *ovl = ofbi->overlays[i]; 56462306a36Sopenharmony_ci r = ovl->wait_for_go(ovl); 56562306a36Sopenharmony_ci if (r) 56662306a36Sopenharmony_ci break; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci return r; 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ciint omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) 57362306a36Sopenharmony_ci{ 57462306a36Sopenharmony_ci struct omapfb_info *ofbi = FB2OFB(fbi); 57562306a36Sopenharmony_ci struct omapfb2_device *fbdev = ofbi->fbdev; 57662306a36Sopenharmony_ci struct omap_dss_device *display = fb2display(fbi); 57762306a36Sopenharmony_ci struct omap_overlay_manager *mgr; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci union { 58062306a36Sopenharmony_ci struct omapfb_update_window_old uwnd_o; 58162306a36Sopenharmony_ci struct omapfb_update_window uwnd; 58262306a36Sopenharmony_ci struct omapfb_plane_info plane_info; 58362306a36Sopenharmony_ci struct omapfb_caps caps; 58462306a36Sopenharmony_ci struct omapfb_mem_info mem_info; 58562306a36Sopenharmony_ci struct omapfb_color_key color_key; 58662306a36Sopenharmony_ci struct omapfb_ovl_colormode ovl_colormode; 58762306a36Sopenharmony_ci enum omapfb_update_mode update_mode; 58862306a36Sopenharmony_ci int test_num; 58962306a36Sopenharmony_ci struct omapfb_memory_read memory_read; 59062306a36Sopenharmony_ci struct omapfb_vram_info vram_info; 59162306a36Sopenharmony_ci struct omapfb_tearsync_info tearsync_info; 59262306a36Sopenharmony_ci struct omapfb_display_info display_info; 59362306a36Sopenharmony_ci u32 crt; 59462306a36Sopenharmony_ci } p; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci int r = 0; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci memset(&p, 0, sizeof(p)); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci switch (cmd) { 60162306a36Sopenharmony_ci case OMAPFB_SYNC_GFX: 60262306a36Sopenharmony_ci DBG("ioctl SYNC_GFX\n"); 60362306a36Sopenharmony_ci if (!display || !display->driver->sync) { 60462306a36Sopenharmony_ci /* DSS1 never returns an error here, so we neither */ 60562306a36Sopenharmony_ci /*r = -EINVAL;*/ 60662306a36Sopenharmony_ci break; 60762306a36Sopenharmony_ci } 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci r = display->driver->sync(display); 61062306a36Sopenharmony_ci break; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci case OMAPFB_UPDATE_WINDOW_OLD: 61362306a36Sopenharmony_ci DBG("ioctl UPDATE_WINDOW_OLD\n"); 61462306a36Sopenharmony_ci if (!display || !display->driver->update) { 61562306a36Sopenharmony_ci r = -EINVAL; 61662306a36Sopenharmony_ci break; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (copy_from_user(&p.uwnd_o, 62062306a36Sopenharmony_ci (void __user *)arg, 62162306a36Sopenharmony_ci sizeof(p.uwnd_o))) { 62262306a36Sopenharmony_ci r = -EFAULT; 62362306a36Sopenharmony_ci break; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y, 62762306a36Sopenharmony_ci p.uwnd_o.width, p.uwnd_o.height); 62862306a36Sopenharmony_ci break; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci case OMAPFB_UPDATE_WINDOW: 63162306a36Sopenharmony_ci DBG("ioctl UPDATE_WINDOW\n"); 63262306a36Sopenharmony_ci if (!display || !display->driver->update) { 63362306a36Sopenharmony_ci r = -EINVAL; 63462306a36Sopenharmony_ci break; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci if (copy_from_user(&p.uwnd, (void __user *)arg, 63862306a36Sopenharmony_ci sizeof(p.uwnd))) { 63962306a36Sopenharmony_ci r = -EFAULT; 64062306a36Sopenharmony_ci break; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y, 64462306a36Sopenharmony_ci p.uwnd.width, p.uwnd.height); 64562306a36Sopenharmony_ci break; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci case OMAPFB_SETUP_PLANE: 64862306a36Sopenharmony_ci DBG("ioctl SETUP_PLANE\n"); 64962306a36Sopenharmony_ci if (copy_from_user(&p.plane_info, (void __user *)arg, 65062306a36Sopenharmony_ci sizeof(p.plane_info))) 65162306a36Sopenharmony_ci r = -EFAULT; 65262306a36Sopenharmony_ci else 65362306a36Sopenharmony_ci r = omapfb_setup_plane(fbi, &p.plane_info); 65462306a36Sopenharmony_ci break; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci case OMAPFB_QUERY_PLANE: 65762306a36Sopenharmony_ci DBG("ioctl QUERY_PLANE\n"); 65862306a36Sopenharmony_ci r = omapfb_query_plane(fbi, &p.plane_info); 65962306a36Sopenharmony_ci if (r < 0) 66062306a36Sopenharmony_ci break; 66162306a36Sopenharmony_ci if (copy_to_user((void __user *)arg, &p.plane_info, 66262306a36Sopenharmony_ci sizeof(p.plane_info))) 66362306a36Sopenharmony_ci r = -EFAULT; 66462306a36Sopenharmony_ci break; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci case OMAPFB_SETUP_MEM: 66762306a36Sopenharmony_ci DBG("ioctl SETUP_MEM\n"); 66862306a36Sopenharmony_ci if (copy_from_user(&p.mem_info, (void __user *)arg, 66962306a36Sopenharmony_ci sizeof(p.mem_info))) 67062306a36Sopenharmony_ci r = -EFAULT; 67162306a36Sopenharmony_ci else 67262306a36Sopenharmony_ci r = omapfb_setup_mem(fbi, &p.mem_info); 67362306a36Sopenharmony_ci break; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci case OMAPFB_QUERY_MEM: 67662306a36Sopenharmony_ci DBG("ioctl QUERY_MEM\n"); 67762306a36Sopenharmony_ci r = omapfb_query_mem(fbi, &p.mem_info); 67862306a36Sopenharmony_ci if (r < 0) 67962306a36Sopenharmony_ci break; 68062306a36Sopenharmony_ci if (copy_to_user((void __user *)arg, &p.mem_info, 68162306a36Sopenharmony_ci sizeof(p.mem_info))) 68262306a36Sopenharmony_ci r = -EFAULT; 68362306a36Sopenharmony_ci break; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci case OMAPFB_GET_CAPS: 68662306a36Sopenharmony_ci DBG("ioctl GET_CAPS\n"); 68762306a36Sopenharmony_ci if (!display) { 68862306a36Sopenharmony_ci r = -EINVAL; 68962306a36Sopenharmony_ci break; 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci memset(&p.caps, 0, sizeof(p.caps)); 69362306a36Sopenharmony_ci if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) 69462306a36Sopenharmony_ci p.caps.ctrl |= OMAPFB_CAPS_MANUAL_UPDATE; 69562306a36Sopenharmony_ci if (display->caps & OMAP_DSS_DISPLAY_CAP_TEAR_ELIM) 69662306a36Sopenharmony_ci p.caps.ctrl |= OMAPFB_CAPS_TEARSYNC; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps))) 69962306a36Sopenharmony_ci r = -EFAULT; 70062306a36Sopenharmony_ci break; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci case OMAPFB_GET_OVERLAY_COLORMODE: 70362306a36Sopenharmony_ci DBG("ioctl GET_OVERLAY_COLORMODE\n"); 70462306a36Sopenharmony_ci if (copy_from_user(&p.ovl_colormode, (void __user *)arg, 70562306a36Sopenharmony_ci sizeof(p.ovl_colormode))) { 70662306a36Sopenharmony_ci r = -EFAULT; 70762306a36Sopenharmony_ci break; 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode); 71062306a36Sopenharmony_ci if (r < 0) 71162306a36Sopenharmony_ci break; 71262306a36Sopenharmony_ci if (copy_to_user((void __user *)arg, &p.ovl_colormode, 71362306a36Sopenharmony_ci sizeof(p.ovl_colormode))) 71462306a36Sopenharmony_ci r = -EFAULT; 71562306a36Sopenharmony_ci break; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci case OMAPFB_SET_UPDATE_MODE: 71862306a36Sopenharmony_ci DBG("ioctl SET_UPDATE_MODE\n"); 71962306a36Sopenharmony_ci if (get_user(p.update_mode, (int __user *)arg)) 72062306a36Sopenharmony_ci r = -EFAULT; 72162306a36Sopenharmony_ci else 72262306a36Sopenharmony_ci r = omapfb_set_update_mode(fbi, p.update_mode); 72362306a36Sopenharmony_ci break; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci case OMAPFB_GET_UPDATE_MODE: 72662306a36Sopenharmony_ci DBG("ioctl GET_UPDATE_MODE\n"); 72762306a36Sopenharmony_ci r = omapfb_get_update_mode(fbi, &p.update_mode); 72862306a36Sopenharmony_ci if (r) 72962306a36Sopenharmony_ci break; 73062306a36Sopenharmony_ci if (put_user(p.update_mode, 73162306a36Sopenharmony_ci (enum omapfb_update_mode __user *)arg)) 73262306a36Sopenharmony_ci r = -EFAULT; 73362306a36Sopenharmony_ci break; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci case OMAPFB_SET_COLOR_KEY: 73662306a36Sopenharmony_ci DBG("ioctl SET_COLOR_KEY\n"); 73762306a36Sopenharmony_ci if (copy_from_user(&p.color_key, (void __user *)arg, 73862306a36Sopenharmony_ci sizeof(p.color_key))) 73962306a36Sopenharmony_ci r = -EFAULT; 74062306a36Sopenharmony_ci else 74162306a36Sopenharmony_ci r = omapfb_set_color_key(fbi, &p.color_key); 74262306a36Sopenharmony_ci break; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci case OMAPFB_GET_COLOR_KEY: 74562306a36Sopenharmony_ci DBG("ioctl GET_COLOR_KEY\n"); 74662306a36Sopenharmony_ci r = omapfb_get_color_key(fbi, &p.color_key); 74762306a36Sopenharmony_ci if (r) 74862306a36Sopenharmony_ci break; 74962306a36Sopenharmony_ci if (copy_to_user((void __user *)arg, &p.color_key, 75062306a36Sopenharmony_ci sizeof(p.color_key))) 75162306a36Sopenharmony_ci r = -EFAULT; 75262306a36Sopenharmony_ci break; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci case FBIO_WAITFORVSYNC: 75562306a36Sopenharmony_ci if (get_user(p.crt, (__u32 __user *)arg)) { 75662306a36Sopenharmony_ci r = -EFAULT; 75762306a36Sopenharmony_ci break; 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci if (p.crt != 0) { 76062306a36Sopenharmony_ci r = -ENODEV; 76162306a36Sopenharmony_ci break; 76262306a36Sopenharmony_ci } 76362306a36Sopenharmony_ci fallthrough; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci case OMAPFB_WAITFORVSYNC: 76662306a36Sopenharmony_ci DBG("ioctl WAITFORVSYNC\n"); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci if (!display) { 76962306a36Sopenharmony_ci r = -EINVAL; 77062306a36Sopenharmony_ci break; 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci mgr = omapdss_find_mgr_from_display(display); 77462306a36Sopenharmony_ci if (!mgr) { 77562306a36Sopenharmony_ci r = -EINVAL; 77662306a36Sopenharmony_ci break; 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci r = mgr->wait_for_vsync(mgr); 78062306a36Sopenharmony_ci break; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci case OMAPFB_WAITFORGO: 78362306a36Sopenharmony_ci DBG("ioctl WAITFORGO\n"); 78462306a36Sopenharmony_ci if (!display) { 78562306a36Sopenharmony_ci r = -EINVAL; 78662306a36Sopenharmony_ci break; 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci r = omapfb_wait_for_go(fbi); 79062306a36Sopenharmony_ci break; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci /* LCD and CTRL tests do the same thing for backward 79362306a36Sopenharmony_ci * compatibility */ 79462306a36Sopenharmony_ci case OMAPFB_LCD_TEST: 79562306a36Sopenharmony_ci DBG("ioctl LCD_TEST\n"); 79662306a36Sopenharmony_ci if (get_user(p.test_num, (int __user *)arg)) { 79762306a36Sopenharmony_ci r = -EFAULT; 79862306a36Sopenharmony_ci break; 79962306a36Sopenharmony_ci } 80062306a36Sopenharmony_ci if (!display || !display->driver->run_test) { 80162306a36Sopenharmony_ci r = -EINVAL; 80262306a36Sopenharmony_ci break; 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci r = display->driver->run_test(display, p.test_num); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci break; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci case OMAPFB_CTRL_TEST: 81062306a36Sopenharmony_ci DBG("ioctl CTRL_TEST\n"); 81162306a36Sopenharmony_ci if (get_user(p.test_num, (int __user *)arg)) { 81262306a36Sopenharmony_ci r = -EFAULT; 81362306a36Sopenharmony_ci break; 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci if (!display || !display->driver->run_test) { 81662306a36Sopenharmony_ci r = -EINVAL; 81762306a36Sopenharmony_ci break; 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci r = display->driver->run_test(display, p.test_num); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci break; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci case OMAPFB_MEMORY_READ: 82562306a36Sopenharmony_ci DBG("ioctl MEMORY_READ\n"); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci if (copy_from_user(&p.memory_read, (void __user *)arg, 82862306a36Sopenharmony_ci sizeof(p.memory_read))) { 82962306a36Sopenharmony_ci r = -EFAULT; 83062306a36Sopenharmony_ci break; 83162306a36Sopenharmony_ci } 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci r = omapfb_memory_read(fbi, &p.memory_read); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci break; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci case OMAPFB_GET_VRAM_INFO: { 83862306a36Sopenharmony_ci DBG("ioctl GET_VRAM_INFO\n"); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci /* 84162306a36Sopenharmony_ci * We don't have the ability to get this vram info anymore. 84262306a36Sopenharmony_ci * Fill in something that should keep the applications working. 84362306a36Sopenharmony_ci */ 84462306a36Sopenharmony_ci p.vram_info.total = SZ_1M * 64; 84562306a36Sopenharmony_ci p.vram_info.free = SZ_1M * 64; 84662306a36Sopenharmony_ci p.vram_info.largest_free_block = SZ_1M * 64; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci if (copy_to_user((void __user *)arg, &p.vram_info, 84962306a36Sopenharmony_ci sizeof(p.vram_info))) 85062306a36Sopenharmony_ci r = -EFAULT; 85162306a36Sopenharmony_ci break; 85262306a36Sopenharmony_ci } 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci case OMAPFB_SET_TEARSYNC: { 85562306a36Sopenharmony_ci DBG("ioctl SET_TEARSYNC\n"); 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci if (copy_from_user(&p.tearsync_info, (void __user *)arg, 85862306a36Sopenharmony_ci sizeof(p.tearsync_info))) { 85962306a36Sopenharmony_ci r = -EFAULT; 86062306a36Sopenharmony_ci break; 86162306a36Sopenharmony_ci } 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci if (!display || !display->driver->enable_te) { 86462306a36Sopenharmony_ci r = -ENODEV; 86562306a36Sopenharmony_ci break; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci r = display->driver->enable_te(display, 86962306a36Sopenharmony_ci !!p.tearsync_info.enabled); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci break; 87262306a36Sopenharmony_ci } 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci case OMAPFB_GET_DISPLAY_INFO: { 87562306a36Sopenharmony_ci u16 xres, yres; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci DBG("ioctl GET_DISPLAY_INFO\n"); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci if (display == NULL) { 88062306a36Sopenharmony_ci r = -ENODEV; 88162306a36Sopenharmony_ci break; 88262306a36Sopenharmony_ci } 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci display->driver->get_resolution(display, &xres, &yres); 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci p.display_info.xres = xres; 88762306a36Sopenharmony_ci p.display_info.yres = yres; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci if (display->driver->get_dimensions) { 89062306a36Sopenharmony_ci u32 w, h; 89162306a36Sopenharmony_ci display->driver->get_dimensions(display, &w, &h); 89262306a36Sopenharmony_ci p.display_info.width = w; 89362306a36Sopenharmony_ci p.display_info.height = h; 89462306a36Sopenharmony_ci } else { 89562306a36Sopenharmony_ci p.display_info.width = 0; 89662306a36Sopenharmony_ci p.display_info.height = 0; 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci if (copy_to_user((void __user *)arg, &p.display_info, 90062306a36Sopenharmony_ci sizeof(p.display_info))) 90162306a36Sopenharmony_ci r = -EFAULT; 90262306a36Sopenharmony_ci break; 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci default: 90662306a36Sopenharmony_ci dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd); 90762306a36Sopenharmony_ci r = -EINVAL; 90862306a36Sopenharmony_ci } 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci if (r < 0) 91162306a36Sopenharmony_ci DBG("ioctl failed: %d\n", r); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci return r; 91462306a36Sopenharmony_ci} 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci 917