0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/fb.h>
0013 #include <linux/device.h>
0014 #include <linux/uaccess.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/mm.h>
0017 #include <linux/omapfb.h>
0018 #include <linux/vmalloc.h>
0019 #include <linux/export.h>
0020 #include <linux/sizes.h>
0021
0022 #include <video/omapfb_dss.h>
0023 #include <video/omapvrfb.h>
0024
0025 #include "omapfb.h"
0026
0027 static u8 get_mem_idx(struct omapfb_info *ofbi)
0028 {
0029 if (ofbi->id == ofbi->region->id)
0030 return 0;
0031
0032 return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
0033 }
0034
0035 static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
0036 u8 mem_idx)
0037 {
0038 struct omapfb2_device *fbdev = ofbi->fbdev;
0039
0040 if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
0041 mem_idx &= OMAPFB_MEM_IDX_MASK;
0042 else
0043 mem_idx = ofbi->id;
0044
0045 if (mem_idx >= fbdev->num_fbs)
0046 return NULL;
0047
0048 return &fbdev->regions[mem_idx];
0049 }
0050
0051 static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
0052 {
0053 struct omapfb_info *ofbi = FB2OFB(fbi);
0054 struct omapfb2_device *fbdev = ofbi->fbdev;
0055 struct omap_overlay *ovl;
0056 struct omap_overlay_info old_info;
0057 struct omapfb2_mem_region *old_rg, *new_rg;
0058 int r = 0;
0059
0060 DBG("omapfb_setup_plane\n");
0061
0062 if (ofbi->num_overlays == 0) {
0063 r = -EINVAL;
0064 goto out;
0065 }
0066
0067
0068 ovl = ofbi->overlays[0];
0069
0070 old_rg = ofbi->region;
0071 new_rg = get_mem_region(ofbi, pi->mem_idx);
0072 if (!new_rg) {
0073 r = -EINVAL;
0074 goto out;
0075 }
0076
0077
0078 if (old_rg->id < new_rg->id) {
0079 omapfb_get_mem_region(old_rg);
0080 omapfb_get_mem_region(new_rg);
0081 } else if (new_rg->id < old_rg->id) {
0082 omapfb_get_mem_region(new_rg);
0083 omapfb_get_mem_region(old_rg);
0084 } else
0085 omapfb_get_mem_region(old_rg);
0086
0087 if (pi->enabled && !new_rg->size) {
0088
0089
0090
0091
0092 r = -EINVAL;
0093 goto put_mem;
0094 }
0095
0096 ovl->get_overlay_info(ovl, &old_info);
0097
0098 if (old_rg != new_rg) {
0099 ofbi->region = new_rg;
0100 set_fb_fix(fbi);
0101 }
0102
0103 if (!pi->enabled) {
0104 r = ovl->disable(ovl);
0105 if (r)
0106 goto undo;
0107 }
0108
0109 if (pi->enabled) {
0110 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
0111 pi->out_width, pi->out_height);
0112 if (r)
0113 goto undo;
0114 } else {
0115 struct omap_overlay_info info;
0116
0117 ovl->get_overlay_info(ovl, &info);
0118
0119 info.pos_x = pi->pos_x;
0120 info.pos_y = pi->pos_y;
0121 info.out_width = pi->out_width;
0122 info.out_height = pi->out_height;
0123
0124 r = ovl->set_overlay_info(ovl, &info);
0125 if (r)
0126 goto undo;
0127 }
0128
0129 if (ovl->manager) {
0130 r = ovl->manager->apply(ovl->manager);
0131 if (r)
0132 goto undo;
0133 }
0134
0135 if (pi->enabled) {
0136 r = ovl->enable(ovl);
0137 if (r)
0138 goto undo;
0139 }
0140
0141
0142 if (old_rg->id > new_rg->id) {
0143 omapfb_put_mem_region(old_rg);
0144 omapfb_put_mem_region(new_rg);
0145 } else if (new_rg->id > old_rg->id) {
0146 omapfb_put_mem_region(new_rg);
0147 omapfb_put_mem_region(old_rg);
0148 } else
0149 omapfb_put_mem_region(old_rg);
0150
0151 return 0;
0152
0153 undo:
0154 if (old_rg != new_rg) {
0155 ofbi->region = old_rg;
0156 set_fb_fix(fbi);
0157 }
0158
0159 ovl->set_overlay_info(ovl, &old_info);
0160 put_mem:
0161
0162 if (old_rg->id > new_rg->id) {
0163 omapfb_put_mem_region(old_rg);
0164 omapfb_put_mem_region(new_rg);
0165 } else if (new_rg->id > old_rg->id) {
0166 omapfb_put_mem_region(new_rg);
0167 omapfb_put_mem_region(old_rg);
0168 } else
0169 omapfb_put_mem_region(old_rg);
0170 out:
0171 dev_err(fbdev->dev, "setup_plane failed\n");
0172
0173 return r;
0174 }
0175
0176 static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
0177 {
0178 struct omapfb_info *ofbi = FB2OFB(fbi);
0179
0180 if (ofbi->num_overlays == 0) {
0181 memset(pi, 0, sizeof(*pi));
0182 } else {
0183 struct omap_overlay *ovl;
0184 struct omap_overlay_info ovli;
0185
0186 ovl = ofbi->overlays[0];
0187 ovl->get_overlay_info(ovl, &ovli);
0188
0189 pi->pos_x = ovli.pos_x;
0190 pi->pos_y = ovli.pos_y;
0191 pi->enabled = ovl->is_enabled(ovl);
0192 pi->channel_out = 0;
0193 pi->mirror = 0;
0194 pi->mem_idx = get_mem_idx(ofbi);
0195 pi->out_width = ovli.out_width;
0196 pi->out_height = ovli.out_height;
0197 }
0198
0199 return 0;
0200 }
0201
0202 static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
0203 {
0204 struct omapfb_info *ofbi = FB2OFB(fbi);
0205 struct omapfb2_device *fbdev = ofbi->fbdev;
0206 struct omap_dss_device *display = fb2display(fbi);
0207 struct omapfb2_mem_region *rg;
0208 int r = 0, i;
0209 size_t size;
0210
0211 if (mi->type != OMAPFB_MEMTYPE_SDRAM)
0212 return -EINVAL;
0213
0214 size = PAGE_ALIGN(mi->size);
0215
0216 if (display && display->driver->sync)
0217 display->driver->sync(display);
0218
0219 rg = ofbi->region;
0220
0221 down_write_nested(&rg->lock, rg->id);
0222 atomic_inc(&rg->lock_count);
0223
0224 if (rg->size == size && rg->type == mi->type)
0225 goto out;
0226
0227 if (atomic_read(&rg->map_count)) {
0228 r = -EBUSY;
0229 goto out;
0230 }
0231
0232 for (i = 0; i < fbdev->num_fbs; i++) {
0233 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
0234 int j;
0235
0236 if (ofbi2->region != rg)
0237 continue;
0238
0239 for (j = 0; j < ofbi2->num_overlays; j++) {
0240 struct omap_overlay *ovl;
0241 ovl = ofbi2->overlays[j];
0242 if (ovl->is_enabled(ovl)) {
0243 r = -EBUSY;
0244 goto out;
0245 }
0246 }
0247 }
0248
0249 r = omapfb_realloc_fbmem(fbi, size, mi->type);
0250 if (r) {
0251 dev_err(fbdev->dev, "realloc fbmem failed\n");
0252 goto out;
0253 }
0254
0255 out:
0256 atomic_dec(&rg->lock_count);
0257 up_write(&rg->lock);
0258
0259 return r;
0260 }
0261
0262 static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
0263 {
0264 struct omapfb_info *ofbi = FB2OFB(fbi);
0265 struct omapfb2_mem_region *rg;
0266
0267 rg = omapfb_get_mem_region(ofbi->region);
0268 memset(mi, 0, sizeof(*mi));
0269
0270 mi->size = rg->size;
0271 mi->type = rg->type;
0272
0273 omapfb_put_mem_region(rg);
0274
0275 return 0;
0276 }
0277
0278 static int omapfb_update_window(struct fb_info *fbi,
0279 u32 x, u32 y, u32 w, u32 h)
0280 {
0281 struct omap_dss_device *display = fb2display(fbi);
0282 u16 dw, dh;
0283
0284 if (!display)
0285 return 0;
0286
0287 if (w == 0 || h == 0)
0288 return 0;
0289
0290 display->driver->get_resolution(display, &dw, &dh);
0291
0292 if (x + w > dw || y + h > dh)
0293 return -EINVAL;
0294
0295 return display->driver->update(display, x, y, w, h);
0296 }
0297
0298 int omapfb_set_update_mode(struct fb_info *fbi,
0299 enum omapfb_update_mode mode)
0300 {
0301 struct omap_dss_device *display = fb2display(fbi);
0302 struct omapfb_info *ofbi = FB2OFB(fbi);
0303 struct omapfb2_device *fbdev = ofbi->fbdev;
0304 struct omapfb_display_data *d;
0305 int r;
0306
0307 if (!display)
0308 return -EINVAL;
0309
0310 if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
0311 return -EINVAL;
0312
0313 omapfb_lock(fbdev);
0314
0315 d = get_display_data(fbdev, display);
0316
0317 if (d->update_mode == mode) {
0318 omapfb_unlock(fbdev);
0319 return 0;
0320 }
0321
0322 r = 0;
0323
0324 if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
0325 if (mode == OMAPFB_AUTO_UPDATE)
0326 omapfb_start_auto_update(fbdev, display);
0327 else
0328 omapfb_stop_auto_update(fbdev, display);
0329
0330 d->update_mode = mode;
0331 } else {
0332 if (mode == OMAPFB_MANUAL_UPDATE)
0333 r = -EINVAL;
0334 }
0335
0336 omapfb_unlock(fbdev);
0337
0338 return r;
0339 }
0340
0341 int omapfb_get_update_mode(struct fb_info *fbi,
0342 enum omapfb_update_mode *mode)
0343 {
0344 struct omap_dss_device *display = fb2display(fbi);
0345 struct omapfb_info *ofbi = FB2OFB(fbi);
0346 struct omapfb2_device *fbdev = ofbi->fbdev;
0347 struct omapfb_display_data *d;
0348
0349 if (!display)
0350 return -EINVAL;
0351
0352 omapfb_lock(fbdev);
0353
0354 d = get_display_data(fbdev, display);
0355
0356 *mode = d->update_mode;
0357
0358 omapfb_unlock(fbdev);
0359
0360 return 0;
0361 }
0362
0363
0364 static struct omapfb_color_key omapfb_color_keys[2];
0365
0366 static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
0367 struct omapfb_color_key *ck)
0368 {
0369 struct omap_overlay_manager_info info;
0370 enum omap_dss_trans_key_type kt;
0371 int r;
0372
0373 mgr->get_manager_info(mgr, &info);
0374
0375 if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
0376 info.trans_enabled = false;
0377 omapfb_color_keys[mgr->id] = *ck;
0378
0379 r = mgr->set_manager_info(mgr, &info);
0380 if (r)
0381 return r;
0382
0383 r = mgr->apply(mgr);
0384
0385 return r;
0386 }
0387
0388 switch (ck->key_type) {
0389 case OMAPFB_COLOR_KEY_GFX_DST:
0390 kt = OMAP_DSS_COLOR_KEY_GFX_DST;
0391 break;
0392 case OMAPFB_COLOR_KEY_VID_SRC:
0393 kt = OMAP_DSS_COLOR_KEY_VID_SRC;
0394 break;
0395 default:
0396 return -EINVAL;
0397 }
0398
0399 info.default_color = ck->background;
0400 info.trans_key = ck->trans_key;
0401 info.trans_key_type = kt;
0402 info.trans_enabled = true;
0403
0404 omapfb_color_keys[mgr->id] = *ck;
0405
0406 r = mgr->set_manager_info(mgr, &info);
0407 if (r)
0408 return r;
0409
0410 r = mgr->apply(mgr);
0411
0412 return r;
0413 }
0414
0415 static int omapfb_set_color_key(struct fb_info *fbi,
0416 struct omapfb_color_key *ck)
0417 {
0418 struct omapfb_info *ofbi = FB2OFB(fbi);
0419 struct omapfb2_device *fbdev = ofbi->fbdev;
0420 int r;
0421 int i;
0422 struct omap_overlay_manager *mgr = NULL;
0423
0424 omapfb_lock(fbdev);
0425
0426 for (i = 0; i < ofbi->num_overlays; i++) {
0427 if (ofbi->overlays[i]->manager) {
0428 mgr = ofbi->overlays[i]->manager;
0429 break;
0430 }
0431 }
0432
0433 if (!mgr) {
0434 r = -EINVAL;
0435 goto err;
0436 }
0437
0438 r = _omapfb_set_color_key(mgr, ck);
0439 err:
0440 omapfb_unlock(fbdev);
0441
0442 return r;
0443 }
0444
0445 static int omapfb_get_color_key(struct fb_info *fbi,
0446 struct omapfb_color_key *ck)
0447 {
0448 struct omapfb_info *ofbi = FB2OFB(fbi);
0449 struct omapfb2_device *fbdev = ofbi->fbdev;
0450 struct omap_overlay_manager *mgr = NULL;
0451 int r = 0;
0452 int i;
0453
0454 omapfb_lock(fbdev);
0455
0456 for (i = 0; i < ofbi->num_overlays; i++) {
0457 if (ofbi->overlays[i]->manager) {
0458 mgr = ofbi->overlays[i]->manager;
0459 break;
0460 }
0461 }
0462
0463 if (!mgr) {
0464 r = -EINVAL;
0465 goto err;
0466 }
0467
0468 *ck = omapfb_color_keys[mgr->id];
0469 err:
0470 omapfb_unlock(fbdev);
0471
0472 return r;
0473 }
0474
0475 static int omapfb_memory_read(struct fb_info *fbi,
0476 struct omapfb_memory_read *mr)
0477 {
0478 struct omap_dss_device *display = fb2display(fbi);
0479 void *buf;
0480 int r;
0481
0482 if (!display || !display->driver->memory_read)
0483 return -ENOENT;
0484
0485 if (mr->w > 4096 || mr->h > 4096)
0486 return -EINVAL;
0487
0488 if (mr->w * mr->h * 3 > mr->buffer_size)
0489 return -EINVAL;
0490
0491 buf = vmalloc(mr->buffer_size);
0492 if (!buf) {
0493 DBG("vmalloc failed\n");
0494 return -ENOMEM;
0495 }
0496
0497 r = display->driver->memory_read(display, buf, mr->buffer_size,
0498 mr->x, mr->y, mr->w, mr->h);
0499
0500 if (r > 0) {
0501 if (copy_to_user(mr->buffer, buf, r))
0502 r = -EFAULT;
0503 }
0504
0505 vfree(buf);
0506
0507 return r;
0508 }
0509
0510 static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
0511 struct omapfb_ovl_colormode *mode)
0512 {
0513 int ovl_idx = mode->overlay_idx;
0514 int mode_idx = mode->mode_idx;
0515 struct omap_overlay *ovl;
0516 enum omap_color_mode supported_modes;
0517 struct fb_var_screeninfo var;
0518 int i;
0519
0520 if (ovl_idx >= fbdev->num_overlays)
0521 return -ENODEV;
0522 ovl = fbdev->overlays[ovl_idx];
0523 supported_modes = ovl->supported_modes;
0524
0525 mode_idx = mode->mode_idx;
0526
0527 for (i = 0; i < sizeof(supported_modes) * 8; i++) {
0528 if (!(supported_modes & (1 << i)))
0529 continue;
0530
0531
0532
0533
0534
0535 if (dss_mode_to_fb_mode(1 << i, &var) < 0)
0536 continue;
0537
0538 mode_idx--;
0539 if (mode_idx < 0)
0540 break;
0541 }
0542
0543 if (i == sizeof(supported_modes) * 8)
0544 return -ENOENT;
0545
0546 mode->bits_per_pixel = var.bits_per_pixel;
0547 mode->nonstd = var.nonstd;
0548 mode->red = var.red;
0549 mode->green = var.green;
0550 mode->blue = var.blue;
0551 mode->transp = var.transp;
0552
0553 return 0;
0554 }
0555
0556 static int omapfb_wait_for_go(struct fb_info *fbi)
0557 {
0558 struct omapfb_info *ofbi = FB2OFB(fbi);
0559 int r = 0;
0560 int i;
0561
0562 for (i = 0; i < ofbi->num_overlays; ++i) {
0563 struct omap_overlay *ovl = ofbi->overlays[i];
0564 r = ovl->wait_for_go(ovl);
0565 if (r)
0566 break;
0567 }
0568
0569 return r;
0570 }
0571
0572 int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
0573 {
0574 struct omapfb_info *ofbi = FB2OFB(fbi);
0575 struct omapfb2_device *fbdev = ofbi->fbdev;
0576 struct omap_dss_device *display = fb2display(fbi);
0577 struct omap_overlay_manager *mgr;
0578
0579 union {
0580 struct omapfb_update_window_old uwnd_o;
0581 struct omapfb_update_window uwnd;
0582 struct omapfb_plane_info plane_info;
0583 struct omapfb_caps caps;
0584 struct omapfb_mem_info mem_info;
0585 struct omapfb_color_key color_key;
0586 struct omapfb_ovl_colormode ovl_colormode;
0587 enum omapfb_update_mode update_mode;
0588 int test_num;
0589 struct omapfb_memory_read memory_read;
0590 struct omapfb_vram_info vram_info;
0591 struct omapfb_tearsync_info tearsync_info;
0592 struct omapfb_display_info display_info;
0593 u32 crt;
0594 } p;
0595
0596 int r = 0;
0597
0598 memset(&p, 0, sizeof(p));
0599
0600 switch (cmd) {
0601 case OMAPFB_SYNC_GFX:
0602 DBG("ioctl SYNC_GFX\n");
0603 if (!display || !display->driver->sync) {
0604
0605
0606 break;
0607 }
0608
0609 r = display->driver->sync(display);
0610 break;
0611
0612 case OMAPFB_UPDATE_WINDOW_OLD:
0613 DBG("ioctl UPDATE_WINDOW_OLD\n");
0614 if (!display || !display->driver->update) {
0615 r = -EINVAL;
0616 break;
0617 }
0618
0619 if (copy_from_user(&p.uwnd_o,
0620 (void __user *)arg,
0621 sizeof(p.uwnd_o))) {
0622 r = -EFAULT;
0623 break;
0624 }
0625
0626 r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
0627 p.uwnd_o.width, p.uwnd_o.height);
0628 break;
0629
0630 case OMAPFB_UPDATE_WINDOW:
0631 DBG("ioctl UPDATE_WINDOW\n");
0632 if (!display || !display->driver->update) {
0633 r = -EINVAL;
0634 break;
0635 }
0636
0637 if (copy_from_user(&p.uwnd, (void __user *)arg,
0638 sizeof(p.uwnd))) {
0639 r = -EFAULT;
0640 break;
0641 }
0642
0643 r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
0644 p.uwnd.width, p.uwnd.height);
0645 break;
0646
0647 case OMAPFB_SETUP_PLANE:
0648 DBG("ioctl SETUP_PLANE\n");
0649 if (copy_from_user(&p.plane_info, (void __user *)arg,
0650 sizeof(p.plane_info)))
0651 r = -EFAULT;
0652 else
0653 r = omapfb_setup_plane(fbi, &p.plane_info);
0654 break;
0655
0656 case OMAPFB_QUERY_PLANE:
0657 DBG("ioctl QUERY_PLANE\n");
0658 r = omapfb_query_plane(fbi, &p.plane_info);
0659 if (r < 0)
0660 break;
0661 if (copy_to_user((void __user *)arg, &p.plane_info,
0662 sizeof(p.plane_info)))
0663 r = -EFAULT;
0664 break;
0665
0666 case OMAPFB_SETUP_MEM:
0667 DBG("ioctl SETUP_MEM\n");
0668 if (copy_from_user(&p.mem_info, (void __user *)arg,
0669 sizeof(p.mem_info)))
0670 r = -EFAULT;
0671 else
0672 r = omapfb_setup_mem(fbi, &p.mem_info);
0673 break;
0674
0675 case OMAPFB_QUERY_MEM:
0676 DBG("ioctl QUERY_MEM\n");
0677 r = omapfb_query_mem(fbi, &p.mem_info);
0678 if (r < 0)
0679 break;
0680 if (copy_to_user((void __user *)arg, &p.mem_info,
0681 sizeof(p.mem_info)))
0682 r = -EFAULT;
0683 break;
0684
0685 case OMAPFB_GET_CAPS:
0686 DBG("ioctl GET_CAPS\n");
0687 if (!display) {
0688 r = -EINVAL;
0689 break;
0690 }
0691
0692 memset(&p.caps, 0, sizeof(p.caps));
0693 if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
0694 p.caps.ctrl |= OMAPFB_CAPS_MANUAL_UPDATE;
0695 if (display->caps & OMAP_DSS_DISPLAY_CAP_TEAR_ELIM)
0696 p.caps.ctrl |= OMAPFB_CAPS_TEARSYNC;
0697
0698 if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
0699 r = -EFAULT;
0700 break;
0701
0702 case OMAPFB_GET_OVERLAY_COLORMODE:
0703 DBG("ioctl GET_OVERLAY_COLORMODE\n");
0704 if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
0705 sizeof(p.ovl_colormode))) {
0706 r = -EFAULT;
0707 break;
0708 }
0709 r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
0710 if (r < 0)
0711 break;
0712 if (copy_to_user((void __user *)arg, &p.ovl_colormode,
0713 sizeof(p.ovl_colormode)))
0714 r = -EFAULT;
0715 break;
0716
0717 case OMAPFB_SET_UPDATE_MODE:
0718 DBG("ioctl SET_UPDATE_MODE\n");
0719 if (get_user(p.update_mode, (int __user *)arg))
0720 r = -EFAULT;
0721 else
0722 r = omapfb_set_update_mode(fbi, p.update_mode);
0723 break;
0724
0725 case OMAPFB_GET_UPDATE_MODE:
0726 DBG("ioctl GET_UPDATE_MODE\n");
0727 r = omapfb_get_update_mode(fbi, &p.update_mode);
0728 if (r)
0729 break;
0730 if (put_user(p.update_mode,
0731 (enum omapfb_update_mode __user *)arg))
0732 r = -EFAULT;
0733 break;
0734
0735 case OMAPFB_SET_COLOR_KEY:
0736 DBG("ioctl SET_COLOR_KEY\n");
0737 if (copy_from_user(&p.color_key, (void __user *)arg,
0738 sizeof(p.color_key)))
0739 r = -EFAULT;
0740 else
0741 r = omapfb_set_color_key(fbi, &p.color_key);
0742 break;
0743
0744 case OMAPFB_GET_COLOR_KEY:
0745 DBG("ioctl GET_COLOR_KEY\n");
0746 r = omapfb_get_color_key(fbi, &p.color_key);
0747 if (r)
0748 break;
0749 if (copy_to_user((void __user *)arg, &p.color_key,
0750 sizeof(p.color_key)))
0751 r = -EFAULT;
0752 break;
0753
0754 case FBIO_WAITFORVSYNC:
0755 if (get_user(p.crt, (__u32 __user *)arg)) {
0756 r = -EFAULT;
0757 break;
0758 }
0759 if (p.crt != 0) {
0760 r = -ENODEV;
0761 break;
0762 }
0763 fallthrough;
0764
0765 case OMAPFB_WAITFORVSYNC:
0766 DBG("ioctl WAITFORVSYNC\n");
0767
0768 if (!display) {
0769 r = -EINVAL;
0770 break;
0771 }
0772
0773 mgr = omapdss_find_mgr_from_display(display);
0774 if (!mgr) {
0775 r = -EINVAL;
0776 break;
0777 }
0778
0779 r = mgr->wait_for_vsync(mgr);
0780 break;
0781
0782 case OMAPFB_WAITFORGO:
0783 DBG("ioctl WAITFORGO\n");
0784 if (!display) {
0785 r = -EINVAL;
0786 break;
0787 }
0788
0789 r = omapfb_wait_for_go(fbi);
0790 break;
0791
0792
0793
0794 case OMAPFB_LCD_TEST:
0795 DBG("ioctl LCD_TEST\n");
0796 if (get_user(p.test_num, (int __user *)arg)) {
0797 r = -EFAULT;
0798 break;
0799 }
0800 if (!display || !display->driver->run_test) {
0801 r = -EINVAL;
0802 break;
0803 }
0804
0805 r = display->driver->run_test(display, p.test_num);
0806
0807 break;
0808
0809 case OMAPFB_CTRL_TEST:
0810 DBG("ioctl CTRL_TEST\n");
0811 if (get_user(p.test_num, (int __user *)arg)) {
0812 r = -EFAULT;
0813 break;
0814 }
0815 if (!display || !display->driver->run_test) {
0816 r = -EINVAL;
0817 break;
0818 }
0819
0820 r = display->driver->run_test(display, p.test_num);
0821
0822 break;
0823
0824 case OMAPFB_MEMORY_READ:
0825 DBG("ioctl MEMORY_READ\n");
0826
0827 if (copy_from_user(&p.memory_read, (void __user *)arg,
0828 sizeof(p.memory_read))) {
0829 r = -EFAULT;
0830 break;
0831 }
0832
0833 r = omapfb_memory_read(fbi, &p.memory_read);
0834
0835 break;
0836
0837 case OMAPFB_GET_VRAM_INFO: {
0838 DBG("ioctl GET_VRAM_INFO\n");
0839
0840
0841
0842
0843
0844 p.vram_info.total = SZ_1M * 64;
0845 p.vram_info.free = SZ_1M * 64;
0846 p.vram_info.largest_free_block = SZ_1M * 64;
0847
0848 if (copy_to_user((void __user *)arg, &p.vram_info,
0849 sizeof(p.vram_info)))
0850 r = -EFAULT;
0851 break;
0852 }
0853
0854 case OMAPFB_SET_TEARSYNC: {
0855 DBG("ioctl SET_TEARSYNC\n");
0856
0857 if (copy_from_user(&p.tearsync_info, (void __user *)arg,
0858 sizeof(p.tearsync_info))) {
0859 r = -EFAULT;
0860 break;
0861 }
0862
0863 if (!display || !display->driver->enable_te) {
0864 r = -ENODEV;
0865 break;
0866 }
0867
0868 r = display->driver->enable_te(display,
0869 !!p.tearsync_info.enabled);
0870
0871 break;
0872 }
0873
0874 case OMAPFB_GET_DISPLAY_INFO: {
0875 u16 xres, yres;
0876
0877 DBG("ioctl GET_DISPLAY_INFO\n");
0878
0879 if (display == NULL) {
0880 r = -ENODEV;
0881 break;
0882 }
0883
0884 display->driver->get_resolution(display, &xres, &yres);
0885
0886 p.display_info.xres = xres;
0887 p.display_info.yres = yres;
0888
0889 if (display->driver->get_dimensions) {
0890 u32 w, h;
0891 display->driver->get_dimensions(display, &w, &h);
0892 p.display_info.width = w;
0893 p.display_info.height = h;
0894 } else {
0895 p.display_info.width = 0;
0896 p.display_info.height = 0;
0897 }
0898
0899 if (copy_to_user((void __user *)arg, &p.display_info,
0900 sizeof(p.display_info)))
0901 r = -EFAULT;
0902 break;
0903 }
0904
0905 default:
0906 dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
0907 r = -EINVAL;
0908 }
0909
0910 if (r < 0)
0911 DBG("ioctl failed: %d\n", r);
0912
0913 return r;
0914 }
0915
0916