Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/omap: remove dss compat code

We have removed all the uses of compat code from omapdrm and the
non-compat parts of omapdss, so now we can remove all the compat code
itself.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

-4260
-3
drivers/gpu/drm/omapdrm/dss/Makefile
··· 3 3 # Core DSS files 4 4 omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 5 5 output.o dss-of.o pll.o video-pll.o 6 - # DSS compat layer files 7 - omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ 8 - dispc-compat.o display-sysfs.o 9 6 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 10 7 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 11 8 omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
-1711
drivers/gpu/drm/omapdrm/dss/apply.c
··· 1 - /* 2 - * Copyright (C) 2011 Texas Instruments 3 - * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 4 - * 5 - * This program is free software; you can redistribute it and/or modify it 6 - * under the terms of the GNU General Public License version 2 as published by 7 - * the Free Software Foundation. 8 - * 9 - * This program is distributed in the hope that it will be useful, but WITHOUT 10 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 - * more details. 13 - * 14 - * You should have received a copy of the GNU General Public License along with 15 - * this program. If not, see <http://www.gnu.org/licenses/>. 16 - */ 17 - 18 - #define DSS_SUBSYS_NAME "APPLY" 19 - 20 - #include <linux/kernel.h> 21 - #include <linux/module.h> 22 - #include <linux/slab.h> 23 - #include <linux/spinlock.h> 24 - #include <linux/jiffies.h> 25 - 26 - #include <video/omapdss.h> 27 - 28 - #include "dss.h" 29 - #include "dss_features.h" 30 - #include "dispc-compat.h" 31 - 32 - /* 33 - * We have 4 levels of cache for the dispc settings. First two are in SW and 34 - * the latter two in HW. 35 - * 36 - * set_info() 37 - * v 38 - * +--------------------+ 39 - * | user_info | 40 - * +--------------------+ 41 - * v 42 - * apply() 43 - * v 44 - * +--------------------+ 45 - * | info | 46 - * +--------------------+ 47 - * v 48 - * write_regs() 49 - * v 50 - * +--------------------+ 51 - * | shadow registers | 52 - * +--------------------+ 53 - * v 54 - * VFP or lcd/digit_enable 55 - * v 56 - * +--------------------+ 57 - * | registers | 58 - * +--------------------+ 59 - */ 60 - 61 - struct ovl_priv_data { 62 - 63 - bool user_info_dirty; 64 - struct omap_overlay_info user_info; 65 - 66 - bool info_dirty; 67 - struct omap_overlay_info info; 68 - 69 - bool shadow_info_dirty; 70 - 71 - bool extra_info_dirty; 72 - bool shadow_extra_info_dirty; 73 - 74 - bool enabled; 75 - u32 fifo_low, fifo_high; 76 - 77 - /* 78 - * True if overlay is to be enabled. Used to check and calculate configs 79 - * for the overlay before it is enabled in the HW. 80 - */ 81 - bool enabling; 82 - }; 83 - 84 - struct mgr_priv_data { 85 - 86 - bool user_info_dirty; 87 - struct omap_overlay_manager_info user_info; 88 - 89 - bool info_dirty; 90 - struct omap_overlay_manager_info info; 91 - 92 - bool shadow_info_dirty; 93 - 94 - /* If true, GO bit is up and shadow registers cannot be written. 95 - * Never true for manual update displays */ 96 - bool busy; 97 - 98 - /* If true, dispc output is enabled */ 99 - bool updating; 100 - 101 - /* If true, a display is enabled using this manager */ 102 - bool enabled; 103 - 104 - bool extra_info_dirty; 105 - bool shadow_extra_info_dirty; 106 - 107 - struct omap_video_timings timings; 108 - struct dss_lcd_mgr_config lcd_config; 109 - 110 - void (*framedone_handler)(void *); 111 - void *framedone_handler_data; 112 - }; 113 - 114 - static struct { 115 - struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS]; 116 - struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS]; 117 - 118 - bool irq_enabled; 119 - } dss_data; 120 - 121 - /* protects dss_data */ 122 - static spinlock_t data_lock; 123 - /* lock for blocking functions */ 124 - static DEFINE_MUTEX(apply_lock); 125 - static DECLARE_COMPLETION(extra_updated_completion); 126 - 127 - static void dss_register_vsync_isr(void); 128 - 129 - static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl) 130 - { 131 - return &dss_data.ovl_priv_data_array[ovl->id]; 132 - } 133 - 134 - static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr) 135 - { 136 - return &dss_data.mgr_priv_data_array[mgr->id]; 137 - } 138 - 139 - static void apply_init_priv(void) 140 - { 141 - const int num_ovls = dss_feat_get_num_ovls(); 142 - struct mgr_priv_data *mp; 143 - int i; 144 - 145 - spin_lock_init(&data_lock); 146 - 147 - for (i = 0; i < num_ovls; ++i) { 148 - struct ovl_priv_data *op; 149 - 150 - op = &dss_data.ovl_priv_data_array[i]; 151 - 152 - op->info.color_mode = OMAP_DSS_COLOR_RGB16; 153 - op->info.rotation_type = OMAP_DSS_ROT_DMA; 154 - 155 - op->info.global_alpha = 255; 156 - 157 - switch (i) { 158 - case 0: 159 - op->info.zorder = 0; 160 - break; 161 - case 1: 162 - op->info.zorder = 163 - dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0; 164 - break; 165 - case 2: 166 - op->info.zorder = 167 - dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0; 168 - break; 169 - case 3: 170 - op->info.zorder = 171 - dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0; 172 - break; 173 - } 174 - 175 - op->user_info = op->info; 176 - } 177 - 178 - /* 179 - * Initialize some of the lcd_config fields for TV manager, this lets 180 - * us prevent checking if the manager is LCD or TV at some places 181 - */ 182 - mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT]; 183 - 184 - mp->lcd_config.video_port_width = 24; 185 - mp->lcd_config.clock_info.lck_div = 1; 186 - mp->lcd_config.clock_info.pck_div = 1; 187 - } 188 - 189 - /* 190 - * A LCD manager's stallmode decides whether it is in manual or auto update. TV 191 - * manager is always auto update, stallmode field for TV manager is false by 192 - * default 193 - */ 194 - static bool ovl_manual_update(struct omap_overlay *ovl) 195 - { 196 - struct mgr_priv_data *mp = get_mgr_priv(ovl->manager); 197 - 198 - return mp->lcd_config.stallmode; 199 - } 200 - 201 - static bool mgr_manual_update(struct omap_overlay_manager *mgr) 202 - { 203 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 204 - 205 - return mp->lcd_config.stallmode; 206 - } 207 - 208 - static int dss_check_settings_low(struct omap_overlay_manager *mgr, 209 - bool applying) 210 - { 211 - struct omap_overlay_info *oi; 212 - struct omap_overlay_manager_info *mi; 213 - struct omap_overlay *ovl; 214 - struct omap_overlay_info *ois[MAX_DSS_OVERLAYS]; 215 - struct ovl_priv_data *op; 216 - struct mgr_priv_data *mp; 217 - 218 - mp = get_mgr_priv(mgr); 219 - 220 - if (!mp->enabled) 221 - return 0; 222 - 223 - if (applying && mp->user_info_dirty) 224 - mi = &mp->user_info; 225 - else 226 - mi = &mp->info; 227 - 228 - /* collect the infos to be tested into the array */ 229 - list_for_each_entry(ovl, &mgr->overlays, list) { 230 - op = get_ovl_priv(ovl); 231 - 232 - if (!op->enabled && !op->enabling) 233 - oi = NULL; 234 - else if (applying && op->user_info_dirty) 235 - oi = &op->user_info; 236 - else 237 - oi = &op->info; 238 - 239 - ois[ovl->id] = oi; 240 - } 241 - 242 - return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois); 243 - } 244 - 245 - /* 246 - * check manager and overlay settings using overlay_info from data->info 247 - */ 248 - static int dss_check_settings(struct omap_overlay_manager *mgr) 249 - { 250 - return dss_check_settings_low(mgr, false); 251 - } 252 - 253 - /* 254 - * check manager and overlay settings using overlay_info from ovl->info if 255 - * dirty and from data->info otherwise 256 - */ 257 - static int dss_check_settings_apply(struct omap_overlay_manager *mgr) 258 - { 259 - return dss_check_settings_low(mgr, true); 260 - } 261 - 262 - static bool need_isr(void) 263 - { 264 - const int num_mgrs = dss_feat_get_num_mgrs(); 265 - int i; 266 - 267 - for (i = 0; i < num_mgrs; ++i) { 268 - struct omap_overlay_manager *mgr; 269 - struct mgr_priv_data *mp; 270 - struct omap_overlay *ovl; 271 - 272 - mgr = omap_dss_get_overlay_manager(i); 273 - mp = get_mgr_priv(mgr); 274 - 275 - if (!mp->enabled) 276 - continue; 277 - 278 - if (mgr_manual_update(mgr)) { 279 - /* to catch FRAMEDONE */ 280 - if (mp->updating) 281 - return true; 282 - } else { 283 - /* to catch GO bit going down */ 284 - if (mp->busy) 285 - return true; 286 - 287 - /* to write new values to registers */ 288 - if (mp->info_dirty) 289 - return true; 290 - 291 - /* to set GO bit */ 292 - if (mp->shadow_info_dirty) 293 - return true; 294 - 295 - /* 296 - * NOTE: we don't check extra_info flags for disabled 297 - * managers, once the manager is enabled, the extra_info 298 - * related manager changes will be taken in by HW. 299 - */ 300 - 301 - /* to write new values to registers */ 302 - if (mp->extra_info_dirty) 303 - return true; 304 - 305 - /* to set GO bit */ 306 - if (mp->shadow_extra_info_dirty) 307 - return true; 308 - 309 - list_for_each_entry(ovl, &mgr->overlays, list) { 310 - struct ovl_priv_data *op; 311 - 312 - op = get_ovl_priv(ovl); 313 - 314 - /* 315 - * NOTE: we check extra_info flags even for 316 - * disabled overlays, as extra_infos need to be 317 - * always written. 318 - */ 319 - 320 - /* to write new values to registers */ 321 - if (op->extra_info_dirty) 322 - return true; 323 - 324 - /* to set GO bit */ 325 - if (op->shadow_extra_info_dirty) 326 - return true; 327 - 328 - if (!op->enabled) 329 - continue; 330 - 331 - /* to write new values to registers */ 332 - if (op->info_dirty) 333 - return true; 334 - 335 - /* to set GO bit */ 336 - if (op->shadow_info_dirty) 337 - return true; 338 - } 339 - } 340 - } 341 - 342 - return false; 343 - } 344 - 345 - static bool need_go(struct omap_overlay_manager *mgr) 346 - { 347 - struct omap_overlay *ovl; 348 - struct mgr_priv_data *mp; 349 - struct ovl_priv_data *op; 350 - 351 - mp = get_mgr_priv(mgr); 352 - 353 - if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty) 354 - return true; 355 - 356 - list_for_each_entry(ovl, &mgr->overlays, list) { 357 - op = get_ovl_priv(ovl); 358 - if (op->shadow_info_dirty || op->shadow_extra_info_dirty) 359 - return true; 360 - } 361 - 362 - return false; 363 - } 364 - 365 - /* returns true if an extra_info field is currently being updated */ 366 - static bool extra_info_update_ongoing(void) 367 - { 368 - const int num_mgrs = dss_feat_get_num_mgrs(); 369 - int i; 370 - 371 - for (i = 0; i < num_mgrs; ++i) { 372 - struct omap_overlay_manager *mgr; 373 - struct omap_overlay *ovl; 374 - struct mgr_priv_data *mp; 375 - 376 - mgr = omap_dss_get_overlay_manager(i); 377 - mp = get_mgr_priv(mgr); 378 - 379 - if (!mp->enabled) 380 - continue; 381 - 382 - if (!mp->updating) 383 - continue; 384 - 385 - if (mp->extra_info_dirty || mp->shadow_extra_info_dirty) 386 - return true; 387 - 388 - list_for_each_entry(ovl, &mgr->overlays, list) { 389 - struct ovl_priv_data *op = get_ovl_priv(ovl); 390 - 391 - if (op->extra_info_dirty || op->shadow_extra_info_dirty) 392 - return true; 393 - } 394 - } 395 - 396 - return false; 397 - } 398 - 399 - /* wait until no extra_info updates are pending */ 400 - static void wait_pending_extra_info_updates(void) 401 - { 402 - bool updating; 403 - unsigned long flags; 404 - unsigned long t; 405 - int r; 406 - 407 - spin_lock_irqsave(&data_lock, flags); 408 - 409 - updating = extra_info_update_ongoing(); 410 - 411 - if (!updating) { 412 - spin_unlock_irqrestore(&data_lock, flags); 413 - return; 414 - } 415 - 416 - init_completion(&extra_updated_completion); 417 - 418 - spin_unlock_irqrestore(&data_lock, flags); 419 - 420 - t = msecs_to_jiffies(500); 421 - r = wait_for_completion_timeout(&extra_updated_completion, t); 422 - if (r == 0) 423 - DSSWARN("timeout in wait_pending_extra_info_updates\n"); 424 - } 425 - 426 - static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr) 427 - { 428 - struct omap_dss_device *dssdev; 429 - 430 - dssdev = mgr->output; 431 - if (dssdev == NULL) 432 - return NULL; 433 - 434 - while (dssdev->dst) 435 - dssdev = dssdev->dst; 436 - 437 - if (dssdev->driver) 438 - return dssdev; 439 - else 440 - return NULL; 441 - } 442 - 443 - static struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl) 444 - { 445 - return ovl->manager ? dss_mgr_get_device(ovl->manager) : NULL; 446 - } 447 - 448 - static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) 449 - { 450 - unsigned long timeout = msecs_to_jiffies(500); 451 - u32 irq; 452 - int r; 453 - 454 - if (mgr->output == NULL) 455 - return -ENODEV; 456 - 457 - r = dispc_runtime_get(); 458 - if (r) 459 - return r; 460 - 461 - switch (mgr->output->id) { 462 - case OMAP_DSS_OUTPUT_VENC: 463 - irq = DISPC_IRQ_EVSYNC_ODD; 464 - break; 465 - case OMAP_DSS_OUTPUT_HDMI: 466 - irq = DISPC_IRQ_EVSYNC_EVEN; 467 - break; 468 - default: 469 - irq = dispc_mgr_get_vsync_irq(mgr->id); 470 - break; 471 - } 472 - 473 - r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 474 - 475 - dispc_runtime_put(); 476 - 477 - return r; 478 - } 479 - 480 - static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 481 - { 482 - unsigned long timeout = msecs_to_jiffies(500); 483 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 484 - u32 irq; 485 - unsigned long flags; 486 - int r; 487 - int i; 488 - 489 - spin_lock_irqsave(&data_lock, flags); 490 - 491 - if (mgr_manual_update(mgr)) { 492 - spin_unlock_irqrestore(&data_lock, flags); 493 - return 0; 494 - } 495 - 496 - if (!mp->enabled) { 497 - spin_unlock_irqrestore(&data_lock, flags); 498 - return 0; 499 - } 500 - 501 - spin_unlock_irqrestore(&data_lock, flags); 502 - 503 - r = dispc_runtime_get(); 504 - if (r) 505 - return r; 506 - 507 - irq = dispc_mgr_get_vsync_irq(mgr->id); 508 - 509 - i = 0; 510 - while (1) { 511 - bool shadow_dirty, dirty; 512 - 513 - spin_lock_irqsave(&data_lock, flags); 514 - dirty = mp->info_dirty; 515 - shadow_dirty = mp->shadow_info_dirty; 516 - spin_unlock_irqrestore(&data_lock, flags); 517 - 518 - if (!dirty && !shadow_dirty) { 519 - r = 0; 520 - break; 521 - } 522 - 523 - /* 4 iterations is the worst case: 524 - * 1 - initial iteration, dirty = true (between VFP and VSYNC) 525 - * 2 - first VSYNC, dirty = true 526 - * 3 - dirty = false, shadow_dirty = true 527 - * 4 - shadow_dirty = false */ 528 - if (i++ == 3) { 529 - DSSERR("mgr(%d)->wait_for_go() not finishing\n", 530 - mgr->id); 531 - r = 0; 532 - break; 533 - } 534 - 535 - r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 536 - if (r == -ERESTARTSYS) 537 - break; 538 - 539 - if (r) { 540 - DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id); 541 - break; 542 - } 543 - } 544 - 545 - dispc_runtime_put(); 546 - 547 - return r; 548 - } 549 - 550 - static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) 551 - { 552 - unsigned long timeout = msecs_to_jiffies(500); 553 - struct ovl_priv_data *op; 554 - struct mgr_priv_data *mp; 555 - u32 irq; 556 - unsigned long flags; 557 - int r; 558 - int i; 559 - 560 - if (!ovl->manager) 561 - return 0; 562 - 563 - mp = get_mgr_priv(ovl->manager); 564 - 565 - spin_lock_irqsave(&data_lock, flags); 566 - 567 - if (ovl_manual_update(ovl)) { 568 - spin_unlock_irqrestore(&data_lock, flags); 569 - return 0; 570 - } 571 - 572 - if (!mp->enabled) { 573 - spin_unlock_irqrestore(&data_lock, flags); 574 - return 0; 575 - } 576 - 577 - spin_unlock_irqrestore(&data_lock, flags); 578 - 579 - r = dispc_runtime_get(); 580 - if (r) 581 - return r; 582 - 583 - irq = dispc_mgr_get_vsync_irq(ovl->manager->id); 584 - 585 - op = get_ovl_priv(ovl); 586 - i = 0; 587 - while (1) { 588 - bool shadow_dirty, dirty; 589 - 590 - spin_lock_irqsave(&data_lock, flags); 591 - dirty = op->info_dirty; 592 - shadow_dirty = op->shadow_info_dirty; 593 - spin_unlock_irqrestore(&data_lock, flags); 594 - 595 - if (!dirty && !shadow_dirty) { 596 - r = 0; 597 - break; 598 - } 599 - 600 - /* 4 iterations is the worst case: 601 - * 1 - initial iteration, dirty = true (between VFP and VSYNC) 602 - * 2 - first VSYNC, dirty = true 603 - * 3 - dirty = false, shadow_dirty = true 604 - * 4 - shadow_dirty = false */ 605 - if (i++ == 3) { 606 - DSSERR("ovl(%d)->wait_for_go() not finishing\n", 607 - ovl->id); 608 - r = 0; 609 - break; 610 - } 611 - 612 - r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 613 - if (r == -ERESTARTSYS) 614 - break; 615 - 616 - if (r) { 617 - DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id); 618 - break; 619 - } 620 - } 621 - 622 - dispc_runtime_put(); 623 - 624 - return r; 625 - } 626 - 627 - static void dss_ovl_write_regs(struct omap_overlay *ovl) 628 - { 629 - struct ovl_priv_data *op = get_ovl_priv(ovl); 630 - struct omap_overlay_info *oi; 631 - bool replication; 632 - struct mgr_priv_data *mp; 633 - int r; 634 - 635 - DSSDBG("writing ovl %d regs\n", ovl->id); 636 - 637 - if (!op->enabled || !op->info_dirty) 638 - return; 639 - 640 - oi = &op->info; 641 - 642 - mp = get_mgr_priv(ovl->manager); 643 - 644 - replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); 645 - 646 - r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false); 647 - if (r) { 648 - /* 649 - * We can't do much here, as this function can be called from 650 - * vsync interrupt. 651 - */ 652 - DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id); 653 - 654 - /* This will leave fifo configurations in a nonoptimal state */ 655 - op->enabled = false; 656 - dispc_ovl_enable(ovl->id, false); 657 - return; 658 - } 659 - 660 - op->info_dirty = false; 661 - if (mp->updating) 662 - op->shadow_info_dirty = true; 663 - } 664 - 665 - static void dss_ovl_write_regs_extra(struct omap_overlay *ovl) 666 - { 667 - struct ovl_priv_data *op = get_ovl_priv(ovl); 668 - struct mgr_priv_data *mp; 669 - 670 - DSSDBG("writing ovl %d regs extra\n", ovl->id); 671 - 672 - if (!op->extra_info_dirty) 673 - return; 674 - 675 - /* note: write also when op->enabled == false, so that the ovl gets 676 - * disabled */ 677 - 678 - dispc_ovl_enable(ovl->id, op->enabled); 679 - dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high); 680 - 681 - mp = get_mgr_priv(ovl->manager); 682 - 683 - op->extra_info_dirty = false; 684 - if (mp->updating) 685 - op->shadow_extra_info_dirty = true; 686 - } 687 - 688 - static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) 689 - { 690 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 691 - struct omap_overlay *ovl; 692 - 693 - DSSDBG("writing mgr %d regs\n", mgr->id); 694 - 695 - if (!mp->enabled) 696 - return; 697 - 698 - WARN_ON(mp->busy); 699 - 700 - /* Commit overlay settings */ 701 - list_for_each_entry(ovl, &mgr->overlays, list) { 702 - dss_ovl_write_regs(ovl); 703 - dss_ovl_write_regs_extra(ovl); 704 - } 705 - 706 - if (mp->info_dirty) { 707 - dispc_mgr_setup(mgr->id, &mp->info); 708 - 709 - mp->info_dirty = false; 710 - if (mp->updating) 711 - mp->shadow_info_dirty = true; 712 - } 713 - } 714 - 715 - static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr) 716 - { 717 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 718 - 719 - DSSDBG("writing mgr %d regs extra\n", mgr->id); 720 - 721 - if (!mp->extra_info_dirty) 722 - return; 723 - 724 - dispc_mgr_set_timings(mgr->id, &mp->timings); 725 - 726 - /* lcd_config parameters */ 727 - if (dss_mgr_is_lcd(mgr->id)) 728 - dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config); 729 - 730 - mp->extra_info_dirty = false; 731 - if (mp->updating) 732 - mp->shadow_extra_info_dirty = true; 733 - } 734 - 735 - static void dss_write_regs(void) 736 - { 737 - const int num_mgrs = omap_dss_get_num_overlay_managers(); 738 - int i; 739 - 740 - for (i = 0; i < num_mgrs; ++i) { 741 - struct omap_overlay_manager *mgr; 742 - struct mgr_priv_data *mp; 743 - int r; 744 - 745 - mgr = omap_dss_get_overlay_manager(i); 746 - mp = get_mgr_priv(mgr); 747 - 748 - if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) 749 - continue; 750 - 751 - r = dss_check_settings(mgr); 752 - if (r) { 753 - DSSERR("cannot write registers for manager %s: " 754 - "illegal configuration\n", mgr->name); 755 - continue; 756 - } 757 - 758 - dss_mgr_write_regs(mgr); 759 - dss_mgr_write_regs_extra(mgr); 760 - } 761 - } 762 - 763 - static void dss_set_go_bits(void) 764 - { 765 - const int num_mgrs = omap_dss_get_num_overlay_managers(); 766 - int i; 767 - 768 - for (i = 0; i < num_mgrs; ++i) { 769 - struct omap_overlay_manager *mgr; 770 - struct mgr_priv_data *mp; 771 - 772 - mgr = omap_dss_get_overlay_manager(i); 773 - mp = get_mgr_priv(mgr); 774 - 775 - if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) 776 - continue; 777 - 778 - if (!need_go(mgr)) 779 - continue; 780 - 781 - mp->busy = true; 782 - 783 - if (!dss_data.irq_enabled && need_isr()) 784 - dss_register_vsync_isr(); 785 - 786 - dispc_mgr_go(mgr->id); 787 - } 788 - 789 - } 790 - 791 - static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) 792 - { 793 - struct omap_overlay *ovl; 794 - struct mgr_priv_data *mp; 795 - struct ovl_priv_data *op; 796 - 797 - mp = get_mgr_priv(mgr); 798 - mp->shadow_info_dirty = false; 799 - mp->shadow_extra_info_dirty = false; 800 - 801 - list_for_each_entry(ovl, &mgr->overlays, list) { 802 - op = get_ovl_priv(ovl); 803 - op->shadow_info_dirty = false; 804 - op->shadow_extra_info_dirty = false; 805 - } 806 - } 807 - 808 - static int dss_mgr_connect_compat(enum omap_channel channel, 809 - struct omap_dss_device *dst) 810 - { 811 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 812 - return mgr->set_output(mgr, dst); 813 - } 814 - 815 - static void dss_mgr_disconnect_compat(enum omap_channel channel, 816 - struct omap_dss_device *dst) 817 - { 818 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 819 - mgr->unset_output(mgr); 820 - } 821 - 822 - static void dss_mgr_start_update_compat(enum omap_channel channel) 823 - { 824 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 825 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 826 - unsigned long flags; 827 - int r; 828 - 829 - spin_lock_irqsave(&data_lock, flags); 830 - 831 - WARN_ON(mp->updating); 832 - 833 - r = dss_check_settings(mgr); 834 - if (r) { 835 - DSSERR("cannot start manual update: illegal configuration\n"); 836 - spin_unlock_irqrestore(&data_lock, flags); 837 - return; 838 - } 839 - 840 - dss_mgr_write_regs(mgr); 841 - dss_mgr_write_regs_extra(mgr); 842 - 843 - mp->updating = true; 844 - 845 - if (!dss_data.irq_enabled && need_isr()) 846 - dss_register_vsync_isr(); 847 - 848 - dispc_mgr_enable_sync(mgr->id); 849 - 850 - spin_unlock_irqrestore(&data_lock, flags); 851 - } 852 - 853 - static void dss_apply_irq_handler(void *data, u32 mask); 854 - 855 - static void dss_register_vsync_isr(void) 856 - { 857 - const int num_mgrs = dss_feat_get_num_mgrs(); 858 - u32 mask; 859 - int r, i; 860 - 861 - mask = 0; 862 - for (i = 0; i < num_mgrs; ++i) 863 - mask |= dispc_mgr_get_vsync_irq(i); 864 - 865 - for (i = 0; i < num_mgrs; ++i) 866 - mask |= dispc_mgr_get_framedone_irq(i); 867 - 868 - r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask); 869 - WARN_ON(r); 870 - 871 - dss_data.irq_enabled = true; 872 - } 873 - 874 - static void dss_unregister_vsync_isr(void) 875 - { 876 - const int num_mgrs = dss_feat_get_num_mgrs(); 877 - u32 mask; 878 - int r, i; 879 - 880 - mask = 0; 881 - for (i = 0; i < num_mgrs; ++i) 882 - mask |= dispc_mgr_get_vsync_irq(i); 883 - 884 - for (i = 0; i < num_mgrs; ++i) 885 - mask |= dispc_mgr_get_framedone_irq(i); 886 - 887 - r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask); 888 - WARN_ON(r); 889 - 890 - dss_data.irq_enabled = false; 891 - } 892 - 893 - static void dss_apply_irq_handler(void *data, u32 mask) 894 - { 895 - const int num_mgrs = dss_feat_get_num_mgrs(); 896 - int i; 897 - bool extra_updating; 898 - 899 - spin_lock(&data_lock); 900 - 901 - /* clear busy, updating flags, shadow_dirty flags */ 902 - for (i = 0; i < num_mgrs; i++) { 903 - struct omap_overlay_manager *mgr; 904 - struct mgr_priv_data *mp; 905 - 906 - mgr = omap_dss_get_overlay_manager(i); 907 - mp = get_mgr_priv(mgr); 908 - 909 - if (!mp->enabled) 910 - continue; 911 - 912 - mp->updating = dispc_mgr_is_enabled(i); 913 - 914 - if (!mgr_manual_update(mgr)) { 915 - bool was_busy = mp->busy; 916 - mp->busy = dispc_mgr_go_busy(i); 917 - 918 - if (was_busy && !mp->busy) 919 - mgr_clear_shadow_dirty(mgr); 920 - } 921 - } 922 - 923 - dss_write_regs(); 924 - dss_set_go_bits(); 925 - 926 - extra_updating = extra_info_update_ongoing(); 927 - if (!extra_updating) 928 - complete_all(&extra_updated_completion); 929 - 930 - /* call framedone handlers for manual update displays */ 931 - for (i = 0; i < num_mgrs; i++) { 932 - struct omap_overlay_manager *mgr; 933 - struct mgr_priv_data *mp; 934 - 935 - mgr = omap_dss_get_overlay_manager(i); 936 - mp = get_mgr_priv(mgr); 937 - 938 - if (!mgr_manual_update(mgr) || !mp->framedone_handler) 939 - continue; 940 - 941 - if (mask & dispc_mgr_get_framedone_irq(i)) 942 - mp->framedone_handler(mp->framedone_handler_data); 943 - } 944 - 945 - if (!need_isr()) 946 - dss_unregister_vsync_isr(); 947 - 948 - spin_unlock(&data_lock); 949 - } 950 - 951 - static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl) 952 - { 953 - struct ovl_priv_data *op; 954 - 955 - op = get_ovl_priv(ovl); 956 - 957 - if (!op->user_info_dirty) 958 - return; 959 - 960 - op->user_info_dirty = false; 961 - op->info_dirty = true; 962 - op->info = op->user_info; 963 - } 964 - 965 - static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr) 966 - { 967 - struct mgr_priv_data *mp; 968 - 969 - mp = get_mgr_priv(mgr); 970 - 971 - if (!mp->user_info_dirty) 972 - return; 973 - 974 - mp->user_info_dirty = false; 975 - mp->info_dirty = true; 976 - mp->info = mp->user_info; 977 - } 978 - 979 - static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) 980 - { 981 - unsigned long flags; 982 - struct omap_overlay *ovl; 983 - int r; 984 - 985 - DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); 986 - 987 - spin_lock_irqsave(&data_lock, flags); 988 - 989 - r = dss_check_settings_apply(mgr); 990 - if (r) { 991 - spin_unlock_irqrestore(&data_lock, flags); 992 - DSSERR("failed to apply settings: illegal configuration.\n"); 993 - return r; 994 - } 995 - 996 - /* Configure overlays */ 997 - list_for_each_entry(ovl, &mgr->overlays, list) 998 - omap_dss_mgr_apply_ovl(ovl); 999 - 1000 - /* Configure manager */ 1001 - omap_dss_mgr_apply_mgr(mgr); 1002 - 1003 - dss_write_regs(); 1004 - dss_set_go_bits(); 1005 - 1006 - spin_unlock_irqrestore(&data_lock, flags); 1007 - 1008 - return 0; 1009 - } 1010 - 1011 - static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable) 1012 - { 1013 - struct ovl_priv_data *op; 1014 - 1015 - op = get_ovl_priv(ovl); 1016 - 1017 - if (op->enabled == enable) 1018 - return; 1019 - 1020 - op->enabled = enable; 1021 - op->extra_info_dirty = true; 1022 - } 1023 - 1024 - static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl, 1025 - u32 fifo_low, u32 fifo_high) 1026 - { 1027 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1028 - 1029 - if (op->fifo_low == fifo_low && op->fifo_high == fifo_high) 1030 - return; 1031 - 1032 - op->fifo_low = fifo_low; 1033 - op->fifo_high = fifo_high; 1034 - op->extra_info_dirty = true; 1035 - } 1036 - 1037 - static void dss_ovl_setup_fifo(struct omap_overlay *ovl) 1038 - { 1039 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1040 - u32 fifo_low, fifo_high; 1041 - bool use_fifo_merge = false; 1042 - 1043 - if (!op->enabled && !op->enabling) 1044 - return; 1045 - 1046 - dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, 1047 - use_fifo_merge, ovl_manual_update(ovl)); 1048 - 1049 - dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); 1050 - } 1051 - 1052 - static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr) 1053 - { 1054 - struct omap_overlay *ovl; 1055 - struct mgr_priv_data *mp; 1056 - 1057 - mp = get_mgr_priv(mgr); 1058 - 1059 - if (!mp->enabled) 1060 - return; 1061 - 1062 - list_for_each_entry(ovl, &mgr->overlays, list) 1063 - dss_ovl_setup_fifo(ovl); 1064 - } 1065 - 1066 - static void dss_setup_fifos(void) 1067 - { 1068 - const int num_mgrs = omap_dss_get_num_overlay_managers(); 1069 - struct omap_overlay_manager *mgr; 1070 - int i; 1071 - 1072 - for (i = 0; i < num_mgrs; ++i) { 1073 - mgr = omap_dss_get_overlay_manager(i); 1074 - dss_mgr_setup_fifos(mgr); 1075 - } 1076 - } 1077 - 1078 - static int dss_mgr_enable_compat(enum omap_channel channel) 1079 - { 1080 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 1081 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1082 - unsigned long flags; 1083 - int r; 1084 - 1085 - mutex_lock(&apply_lock); 1086 - 1087 - if (mp->enabled) 1088 - goto out; 1089 - 1090 - spin_lock_irqsave(&data_lock, flags); 1091 - 1092 - mp->enabled = true; 1093 - 1094 - r = dss_check_settings(mgr); 1095 - if (r) { 1096 - DSSERR("failed to enable manager %d: check_settings failed\n", 1097 - mgr->id); 1098 - goto err; 1099 - } 1100 - 1101 - dss_setup_fifos(); 1102 - 1103 - dss_write_regs(); 1104 - dss_set_go_bits(); 1105 - 1106 - if (!mgr_manual_update(mgr)) 1107 - mp->updating = true; 1108 - 1109 - if (!dss_data.irq_enabled && need_isr()) 1110 - dss_register_vsync_isr(); 1111 - 1112 - spin_unlock_irqrestore(&data_lock, flags); 1113 - 1114 - if (!mgr_manual_update(mgr)) 1115 - dispc_mgr_enable_sync(mgr->id); 1116 - 1117 - out: 1118 - mutex_unlock(&apply_lock); 1119 - 1120 - return 0; 1121 - 1122 - err: 1123 - mp->enabled = false; 1124 - spin_unlock_irqrestore(&data_lock, flags); 1125 - mutex_unlock(&apply_lock); 1126 - return r; 1127 - } 1128 - 1129 - static void dss_mgr_disable_compat(enum omap_channel channel) 1130 - { 1131 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 1132 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1133 - unsigned long flags; 1134 - 1135 - mutex_lock(&apply_lock); 1136 - 1137 - if (!mp->enabled) 1138 - goto out; 1139 - 1140 - wait_pending_extra_info_updates(); 1141 - 1142 - if (!mgr_manual_update(mgr)) 1143 - dispc_mgr_disable_sync(mgr->id); 1144 - 1145 - spin_lock_irqsave(&data_lock, flags); 1146 - 1147 - mp->updating = false; 1148 - mp->enabled = false; 1149 - 1150 - spin_unlock_irqrestore(&data_lock, flags); 1151 - 1152 - out: 1153 - mutex_unlock(&apply_lock); 1154 - } 1155 - 1156 - static int dss_mgr_set_info(struct omap_overlay_manager *mgr, 1157 - struct omap_overlay_manager_info *info) 1158 - { 1159 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1160 - unsigned long flags; 1161 - int r; 1162 - 1163 - r = dss_mgr_simple_check(mgr, info); 1164 - if (r) 1165 - return r; 1166 - 1167 - spin_lock_irqsave(&data_lock, flags); 1168 - 1169 - mp->user_info = *info; 1170 - mp->user_info_dirty = true; 1171 - 1172 - spin_unlock_irqrestore(&data_lock, flags); 1173 - 1174 - return 0; 1175 - } 1176 - 1177 - static void dss_mgr_get_info(struct omap_overlay_manager *mgr, 1178 - struct omap_overlay_manager_info *info) 1179 - { 1180 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1181 - unsigned long flags; 1182 - 1183 - spin_lock_irqsave(&data_lock, flags); 1184 - 1185 - *info = mp->user_info; 1186 - 1187 - spin_unlock_irqrestore(&data_lock, flags); 1188 - } 1189 - 1190 - static int dss_mgr_set_output(struct omap_overlay_manager *mgr, 1191 - struct omap_dss_device *output) 1192 - { 1193 - int r; 1194 - 1195 - mutex_lock(&apply_lock); 1196 - 1197 - if (mgr->output) { 1198 - DSSERR("manager %s is already connected to an output\n", 1199 - mgr->name); 1200 - r = -EINVAL; 1201 - goto err; 1202 - } 1203 - 1204 - if ((mgr->supported_outputs & output->id) == 0) { 1205 - DSSERR("output does not support manager %s\n", 1206 - mgr->name); 1207 - r = -EINVAL; 1208 - goto err; 1209 - } 1210 - 1211 - output->manager = mgr; 1212 - mgr->output = output; 1213 - 1214 - mutex_unlock(&apply_lock); 1215 - 1216 - return 0; 1217 - err: 1218 - mutex_unlock(&apply_lock); 1219 - return r; 1220 - } 1221 - 1222 - static int dss_mgr_unset_output(struct omap_overlay_manager *mgr) 1223 - { 1224 - int r; 1225 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1226 - unsigned long flags; 1227 - 1228 - mutex_lock(&apply_lock); 1229 - 1230 - if (!mgr->output) { 1231 - DSSERR("failed to unset output, output not set\n"); 1232 - r = -EINVAL; 1233 - goto err; 1234 - } 1235 - 1236 - spin_lock_irqsave(&data_lock, flags); 1237 - 1238 - if (mp->enabled) { 1239 - DSSERR("output can't be unset when manager is enabled\n"); 1240 - r = -EINVAL; 1241 - goto err1; 1242 - } 1243 - 1244 - spin_unlock_irqrestore(&data_lock, flags); 1245 - 1246 - mgr->output->manager = NULL; 1247 - mgr->output = NULL; 1248 - 1249 - mutex_unlock(&apply_lock); 1250 - 1251 - return 0; 1252 - err1: 1253 - spin_unlock_irqrestore(&data_lock, flags); 1254 - err: 1255 - mutex_unlock(&apply_lock); 1256 - 1257 - return r; 1258 - } 1259 - 1260 - static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, 1261 - const struct omap_video_timings *timings) 1262 - { 1263 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1264 - 1265 - mp->timings = *timings; 1266 - mp->extra_info_dirty = true; 1267 - } 1268 - 1269 - static void dss_mgr_set_timings_compat(enum omap_channel channel, 1270 - const struct omap_video_timings *timings) 1271 - { 1272 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 1273 - unsigned long flags; 1274 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1275 - 1276 - spin_lock_irqsave(&data_lock, flags); 1277 - 1278 - if (mp->updating) { 1279 - DSSERR("cannot set timings for %s: manager needs to be disabled\n", 1280 - mgr->name); 1281 - goto out; 1282 - } 1283 - 1284 - dss_apply_mgr_timings(mgr, timings); 1285 - out: 1286 - spin_unlock_irqrestore(&data_lock, flags); 1287 - } 1288 - 1289 - static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr, 1290 - const struct dss_lcd_mgr_config *config) 1291 - { 1292 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1293 - 1294 - mp->lcd_config = *config; 1295 - mp->extra_info_dirty = true; 1296 - } 1297 - 1298 - static void dss_mgr_set_lcd_config_compat(enum omap_channel channel, 1299 - const struct dss_lcd_mgr_config *config) 1300 - { 1301 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 1302 - unsigned long flags; 1303 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1304 - 1305 - spin_lock_irqsave(&data_lock, flags); 1306 - 1307 - if (mp->enabled) { 1308 - DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n", 1309 - mgr->name); 1310 - goto out; 1311 - } 1312 - 1313 - dss_apply_mgr_lcd_config(mgr, config); 1314 - out: 1315 - spin_unlock_irqrestore(&data_lock, flags); 1316 - } 1317 - 1318 - static int dss_ovl_set_info(struct omap_overlay *ovl, 1319 - struct omap_overlay_info *info) 1320 - { 1321 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1322 - unsigned long flags; 1323 - int r; 1324 - 1325 - r = dss_ovl_simple_check(ovl, info); 1326 - if (r) 1327 - return r; 1328 - 1329 - spin_lock_irqsave(&data_lock, flags); 1330 - 1331 - op->user_info = *info; 1332 - op->user_info_dirty = true; 1333 - 1334 - spin_unlock_irqrestore(&data_lock, flags); 1335 - 1336 - return 0; 1337 - } 1338 - 1339 - static void dss_ovl_get_info(struct omap_overlay *ovl, 1340 - struct omap_overlay_info *info) 1341 - { 1342 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1343 - unsigned long flags; 1344 - 1345 - spin_lock_irqsave(&data_lock, flags); 1346 - 1347 - *info = op->user_info; 1348 - 1349 - spin_unlock_irqrestore(&data_lock, flags); 1350 - } 1351 - 1352 - static int dss_ovl_set_manager(struct omap_overlay *ovl, 1353 - struct omap_overlay_manager *mgr) 1354 - { 1355 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1356 - unsigned long flags; 1357 - int r; 1358 - 1359 - if (!mgr) 1360 - return -EINVAL; 1361 - 1362 - mutex_lock(&apply_lock); 1363 - 1364 - if (ovl->manager) { 1365 - DSSERR("overlay '%s' already has a manager '%s'\n", 1366 - ovl->name, ovl->manager->name); 1367 - r = -EINVAL; 1368 - goto err; 1369 - } 1370 - 1371 - r = dispc_runtime_get(); 1372 - if (r) 1373 - goto err; 1374 - 1375 - spin_lock_irqsave(&data_lock, flags); 1376 - 1377 - if (op->enabled) { 1378 - spin_unlock_irqrestore(&data_lock, flags); 1379 - DSSERR("overlay has to be disabled to change the manager\n"); 1380 - r = -EINVAL; 1381 - goto err1; 1382 - } 1383 - 1384 - dispc_ovl_set_channel_out(ovl->id, mgr->id); 1385 - 1386 - ovl->manager = mgr; 1387 - list_add_tail(&ovl->list, &mgr->overlays); 1388 - 1389 - spin_unlock_irqrestore(&data_lock, flags); 1390 - 1391 - dispc_runtime_put(); 1392 - 1393 - mutex_unlock(&apply_lock); 1394 - 1395 - return 0; 1396 - 1397 - err1: 1398 - dispc_runtime_put(); 1399 - err: 1400 - mutex_unlock(&apply_lock); 1401 - return r; 1402 - } 1403 - 1404 - static int dss_ovl_unset_manager(struct omap_overlay *ovl) 1405 - { 1406 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1407 - unsigned long flags; 1408 - int r; 1409 - 1410 - mutex_lock(&apply_lock); 1411 - 1412 - if (!ovl->manager) { 1413 - DSSERR("failed to detach overlay: manager not set\n"); 1414 - r = -EINVAL; 1415 - goto err; 1416 - } 1417 - 1418 - spin_lock_irqsave(&data_lock, flags); 1419 - 1420 - if (op->enabled) { 1421 - spin_unlock_irqrestore(&data_lock, flags); 1422 - DSSERR("overlay has to be disabled to unset the manager\n"); 1423 - r = -EINVAL; 1424 - goto err; 1425 - } 1426 - 1427 - spin_unlock_irqrestore(&data_lock, flags); 1428 - 1429 - /* wait for pending extra_info updates to ensure the ovl is disabled */ 1430 - wait_pending_extra_info_updates(); 1431 - 1432 - /* 1433 - * For a manual update display, there is no guarantee that the overlay 1434 - * is really disabled in HW, we may need an extra update from this 1435 - * manager before the configurations can go in. Return an error if the 1436 - * overlay needed an update from the manager. 1437 - * 1438 - * TODO: Instead of returning an error, try to do a dummy manager update 1439 - * here to disable the overlay in hardware. Use the *GATED fields in 1440 - * the DISPC_CONFIG registers to do a dummy update. 1441 - */ 1442 - spin_lock_irqsave(&data_lock, flags); 1443 - 1444 - if (ovl_manual_update(ovl) && op->extra_info_dirty) { 1445 - spin_unlock_irqrestore(&data_lock, flags); 1446 - DSSERR("need an update to change the manager\n"); 1447 - r = -EINVAL; 1448 - goto err; 1449 - } 1450 - 1451 - ovl->manager = NULL; 1452 - list_del(&ovl->list); 1453 - 1454 - spin_unlock_irqrestore(&data_lock, flags); 1455 - 1456 - mutex_unlock(&apply_lock); 1457 - 1458 - return 0; 1459 - err: 1460 - mutex_unlock(&apply_lock); 1461 - return r; 1462 - } 1463 - 1464 - static bool dss_ovl_is_enabled(struct omap_overlay *ovl) 1465 - { 1466 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1467 - unsigned long flags; 1468 - bool e; 1469 - 1470 - spin_lock_irqsave(&data_lock, flags); 1471 - 1472 - e = op->enabled; 1473 - 1474 - spin_unlock_irqrestore(&data_lock, flags); 1475 - 1476 - return e; 1477 - } 1478 - 1479 - static int dss_ovl_enable(struct omap_overlay *ovl) 1480 - { 1481 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1482 - unsigned long flags; 1483 - int r; 1484 - 1485 - mutex_lock(&apply_lock); 1486 - 1487 - if (op->enabled) { 1488 - r = 0; 1489 - goto err1; 1490 - } 1491 - 1492 - if (ovl->manager == NULL || ovl->manager->output == NULL) { 1493 - r = -EINVAL; 1494 - goto err1; 1495 - } 1496 - 1497 - spin_lock_irqsave(&data_lock, flags); 1498 - 1499 - op->enabling = true; 1500 - 1501 - r = dss_check_settings(ovl->manager); 1502 - if (r) { 1503 - DSSERR("failed to enable overlay %d: check_settings failed\n", 1504 - ovl->id); 1505 - goto err2; 1506 - } 1507 - 1508 - dss_setup_fifos(); 1509 - 1510 - op->enabling = false; 1511 - dss_apply_ovl_enable(ovl, true); 1512 - 1513 - dss_write_regs(); 1514 - dss_set_go_bits(); 1515 - 1516 - spin_unlock_irqrestore(&data_lock, flags); 1517 - 1518 - mutex_unlock(&apply_lock); 1519 - 1520 - return 0; 1521 - err2: 1522 - op->enabling = false; 1523 - spin_unlock_irqrestore(&data_lock, flags); 1524 - err1: 1525 - mutex_unlock(&apply_lock); 1526 - return r; 1527 - } 1528 - 1529 - static int dss_ovl_disable(struct omap_overlay *ovl) 1530 - { 1531 - struct ovl_priv_data *op = get_ovl_priv(ovl); 1532 - unsigned long flags; 1533 - int r; 1534 - 1535 - mutex_lock(&apply_lock); 1536 - 1537 - if (!op->enabled) { 1538 - r = 0; 1539 - goto err; 1540 - } 1541 - 1542 - if (ovl->manager == NULL || ovl->manager->output == NULL) { 1543 - r = -EINVAL; 1544 - goto err; 1545 - } 1546 - 1547 - spin_lock_irqsave(&data_lock, flags); 1548 - 1549 - dss_apply_ovl_enable(ovl, false); 1550 - dss_write_regs(); 1551 - dss_set_go_bits(); 1552 - 1553 - spin_unlock_irqrestore(&data_lock, flags); 1554 - 1555 - mutex_unlock(&apply_lock); 1556 - 1557 - return 0; 1558 - 1559 - err: 1560 - mutex_unlock(&apply_lock); 1561 - return r; 1562 - } 1563 - 1564 - static int dss_mgr_register_framedone_handler_compat(enum omap_channel channel, 1565 - void (*handler)(void *), void *data) 1566 - { 1567 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 1568 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1569 - 1570 - if (mp->framedone_handler) 1571 - return -EBUSY; 1572 - 1573 - mp->framedone_handler = handler; 1574 - mp->framedone_handler_data = data; 1575 - 1576 - return 0; 1577 - } 1578 - 1579 - static void dss_mgr_unregister_framedone_handler_compat(enum omap_channel channel, 1580 - void (*handler)(void *), void *data) 1581 - { 1582 - struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel); 1583 - struct mgr_priv_data *mp = get_mgr_priv(mgr); 1584 - 1585 - WARN_ON(mp->framedone_handler != handler || 1586 - mp->framedone_handler_data != data); 1587 - 1588 - mp->framedone_handler = NULL; 1589 - mp->framedone_handler_data = NULL; 1590 - } 1591 - 1592 - static const struct dss_mgr_ops apply_mgr_ops = { 1593 - .connect = dss_mgr_connect_compat, 1594 - .disconnect = dss_mgr_disconnect_compat, 1595 - .start_update = dss_mgr_start_update_compat, 1596 - .enable = dss_mgr_enable_compat, 1597 - .disable = dss_mgr_disable_compat, 1598 - .set_timings = dss_mgr_set_timings_compat, 1599 - .set_lcd_config = dss_mgr_set_lcd_config_compat, 1600 - .register_framedone_handler = dss_mgr_register_framedone_handler_compat, 1601 - .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat, 1602 - }; 1603 - 1604 - static int compat_refcnt; 1605 - static DEFINE_MUTEX(compat_init_lock); 1606 - 1607 - int omapdss_compat_init(void) 1608 - { 1609 - struct platform_device *pdev = dss_get_core_pdev(); 1610 - int i, r; 1611 - 1612 - mutex_lock(&compat_init_lock); 1613 - 1614 - if (compat_refcnt++ > 0) 1615 - goto out; 1616 - 1617 - apply_init_priv(); 1618 - 1619 - dss_init_overlay_managers_sysfs(pdev); 1620 - dss_init_overlays(pdev); 1621 - 1622 - for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) { 1623 - struct omap_overlay_manager *mgr; 1624 - 1625 - mgr = omap_dss_get_overlay_manager(i); 1626 - 1627 - mgr->set_output = &dss_mgr_set_output; 1628 - mgr->unset_output = &dss_mgr_unset_output; 1629 - mgr->apply = &omap_dss_mgr_apply; 1630 - mgr->set_manager_info = &dss_mgr_set_info; 1631 - mgr->get_manager_info = &dss_mgr_get_info; 1632 - mgr->wait_for_go = &dss_mgr_wait_for_go; 1633 - mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; 1634 - mgr->get_device = &dss_mgr_get_device; 1635 - } 1636 - 1637 - for (i = 0; i < omap_dss_get_num_overlays(); i++) { 1638 - struct omap_overlay *ovl = omap_dss_get_overlay(i); 1639 - 1640 - ovl->is_enabled = &dss_ovl_is_enabled; 1641 - ovl->enable = &dss_ovl_enable; 1642 - ovl->disable = &dss_ovl_disable; 1643 - ovl->set_manager = &dss_ovl_set_manager; 1644 - ovl->unset_manager = &dss_ovl_unset_manager; 1645 - ovl->set_overlay_info = &dss_ovl_set_info; 1646 - ovl->get_overlay_info = &dss_ovl_get_info; 1647 - ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; 1648 - ovl->get_device = &dss_ovl_get_device; 1649 - } 1650 - 1651 - r = dss_install_mgr_ops(&apply_mgr_ops); 1652 - if (r) 1653 - goto err_mgr_ops; 1654 - 1655 - r = display_init_sysfs(pdev); 1656 - if (r) 1657 - goto err_disp_sysfs; 1658 - 1659 - dispc_runtime_get(); 1660 - 1661 - r = dss_dispc_initialize_irq(); 1662 - if (r) 1663 - goto err_init_irq; 1664 - 1665 - dispc_runtime_put(); 1666 - 1667 - out: 1668 - mutex_unlock(&compat_init_lock); 1669 - 1670 - return 0; 1671 - 1672 - err_init_irq: 1673 - dispc_runtime_put(); 1674 - display_uninit_sysfs(pdev); 1675 - 1676 - err_disp_sysfs: 1677 - dss_uninstall_mgr_ops(); 1678 - 1679 - err_mgr_ops: 1680 - dss_uninit_overlay_managers_sysfs(pdev); 1681 - dss_uninit_overlays(pdev); 1682 - 1683 - compat_refcnt--; 1684 - 1685 - mutex_unlock(&compat_init_lock); 1686 - 1687 - return r; 1688 - } 1689 - EXPORT_SYMBOL(omapdss_compat_init); 1690 - 1691 - void omapdss_compat_uninit(void) 1692 - { 1693 - struct platform_device *pdev = dss_get_core_pdev(); 1694 - 1695 - mutex_lock(&compat_init_lock); 1696 - 1697 - if (--compat_refcnt > 0) 1698 - goto out; 1699 - 1700 - dss_dispc_uninitialize_irq(); 1701 - 1702 - display_uninit_sysfs(pdev); 1703 - 1704 - dss_uninstall_mgr_ops(); 1705 - 1706 - dss_uninit_overlay_managers_sysfs(pdev); 1707 - dss_uninit_overlays(pdev); 1708 - out: 1709 - mutex_unlock(&compat_init_lock); 1710 - } 1711 - EXPORT_SYMBOL(omapdss_compat_uninit);
-667
drivers/gpu/drm/omapdrm/dss/dispc-compat.c
··· 1 - /* 2 - * Copyright (C) 2012 Texas Instruments 3 - * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 4 - * 5 - * This program is free software; you can redistribute it and/or modify it 6 - * under the terms of the GNU General Public License version 2 as published by 7 - * the Free Software Foundation. 8 - * 9 - * This program is distributed in the hope that it will be useful, but WITHOUT 10 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 - * more details. 13 - * 14 - * You should have received a copy of the GNU General Public License along with 15 - * this program. If not, see <http://www.gnu.org/licenses/>. 16 - */ 17 - 18 - #define DSS_SUBSYS_NAME "APPLY" 19 - 20 - #include <linux/kernel.h> 21 - #include <linux/module.h> 22 - #include <linux/slab.h> 23 - #include <linux/spinlock.h> 24 - #include <linux/jiffies.h> 25 - #include <linux/delay.h> 26 - #include <linux/interrupt.h> 27 - #include <linux/seq_file.h> 28 - 29 - #include <video/omapdss.h> 30 - 31 - #include "dss.h" 32 - #include "dss_features.h" 33 - #include "dispc-compat.h" 34 - 35 - #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ 36 - DISPC_IRQ_OCP_ERR | \ 37 - DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ 38 - DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ 39 - DISPC_IRQ_SYNC_LOST | \ 40 - DISPC_IRQ_SYNC_LOST_DIGIT) 41 - 42 - #define DISPC_MAX_NR_ISRS 8 43 - 44 - struct omap_dispc_isr_data { 45 - omap_dispc_isr_t isr; 46 - void *arg; 47 - u32 mask; 48 - }; 49 - 50 - struct dispc_irq_stats { 51 - unsigned long last_reset; 52 - unsigned irq_count; 53 - unsigned irqs[32]; 54 - }; 55 - 56 - static struct { 57 - spinlock_t irq_lock; 58 - u32 irq_error_mask; 59 - struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; 60 - u32 error_irqs; 61 - struct work_struct error_work; 62 - 63 - #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 64 - spinlock_t irq_stats_lock; 65 - struct dispc_irq_stats irq_stats; 66 - #endif 67 - } dispc_compat; 68 - 69 - 70 - #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 71 - static void dispc_dump_irqs(struct seq_file *s) 72 - { 73 - unsigned long flags; 74 - struct dispc_irq_stats stats; 75 - 76 - spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags); 77 - 78 - stats = dispc_compat.irq_stats; 79 - memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats)); 80 - dispc_compat.irq_stats.last_reset = jiffies; 81 - 82 - spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags); 83 - 84 - seq_printf(s, "period %u ms\n", 85 - jiffies_to_msecs(jiffies - stats.last_reset)); 86 - 87 - seq_printf(s, "irqs %d\n", stats.irq_count); 88 - #define PIS(x) \ 89 - seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]); 90 - 91 - PIS(FRAMEDONE); 92 - PIS(VSYNC); 93 - PIS(EVSYNC_EVEN); 94 - PIS(EVSYNC_ODD); 95 - PIS(ACBIAS_COUNT_STAT); 96 - PIS(PROG_LINE_NUM); 97 - PIS(GFX_FIFO_UNDERFLOW); 98 - PIS(GFX_END_WIN); 99 - PIS(PAL_GAMMA_MASK); 100 - PIS(OCP_ERR); 101 - PIS(VID1_FIFO_UNDERFLOW); 102 - PIS(VID1_END_WIN); 103 - PIS(VID2_FIFO_UNDERFLOW); 104 - PIS(VID2_END_WIN); 105 - if (dss_feat_get_num_ovls() > 3) { 106 - PIS(VID3_FIFO_UNDERFLOW); 107 - PIS(VID3_END_WIN); 108 - } 109 - PIS(SYNC_LOST); 110 - PIS(SYNC_LOST_DIGIT); 111 - PIS(WAKEUP); 112 - if (dss_has_feature(FEAT_MGR_LCD2)) { 113 - PIS(FRAMEDONE2); 114 - PIS(VSYNC2); 115 - PIS(ACBIAS_COUNT_STAT2); 116 - PIS(SYNC_LOST2); 117 - } 118 - if (dss_has_feature(FEAT_MGR_LCD3)) { 119 - PIS(FRAMEDONE3); 120 - PIS(VSYNC3); 121 - PIS(ACBIAS_COUNT_STAT3); 122 - PIS(SYNC_LOST3); 123 - } 124 - #undef PIS 125 - } 126 - #endif 127 - 128 - /* dispc.irq_lock has to be locked by the caller */ 129 - static void _omap_dispc_set_irqs(void) 130 - { 131 - u32 mask; 132 - int i; 133 - struct omap_dispc_isr_data *isr_data; 134 - 135 - mask = dispc_compat.irq_error_mask; 136 - 137 - for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 138 - isr_data = &dispc_compat.registered_isr[i]; 139 - 140 - if (isr_data->isr == NULL) 141 - continue; 142 - 143 - mask |= isr_data->mask; 144 - } 145 - 146 - dispc_write_irqenable(mask); 147 - } 148 - 149 - int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) 150 - { 151 - int i; 152 - int ret; 153 - unsigned long flags; 154 - struct omap_dispc_isr_data *isr_data; 155 - 156 - if (isr == NULL) 157 - return -EINVAL; 158 - 159 - spin_lock_irqsave(&dispc_compat.irq_lock, flags); 160 - 161 - /* check for duplicate entry */ 162 - for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 163 - isr_data = &dispc_compat.registered_isr[i]; 164 - if (isr_data->isr == isr && isr_data->arg == arg && 165 - isr_data->mask == mask) { 166 - ret = -EINVAL; 167 - goto err; 168 - } 169 - } 170 - 171 - isr_data = NULL; 172 - ret = -EBUSY; 173 - 174 - for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 175 - isr_data = &dispc_compat.registered_isr[i]; 176 - 177 - if (isr_data->isr != NULL) 178 - continue; 179 - 180 - isr_data->isr = isr; 181 - isr_data->arg = arg; 182 - isr_data->mask = mask; 183 - ret = 0; 184 - 185 - break; 186 - } 187 - 188 - if (ret) 189 - goto err; 190 - 191 - _omap_dispc_set_irqs(); 192 - 193 - spin_unlock_irqrestore(&dispc_compat.irq_lock, flags); 194 - 195 - return 0; 196 - err: 197 - spin_unlock_irqrestore(&dispc_compat.irq_lock, flags); 198 - 199 - return ret; 200 - } 201 - EXPORT_SYMBOL(omap_dispc_register_isr); 202 - 203 - int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask) 204 - { 205 - int i; 206 - unsigned long flags; 207 - int ret = -EINVAL; 208 - struct omap_dispc_isr_data *isr_data; 209 - 210 - spin_lock_irqsave(&dispc_compat.irq_lock, flags); 211 - 212 - for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 213 - isr_data = &dispc_compat.registered_isr[i]; 214 - if (isr_data->isr != isr || isr_data->arg != arg || 215 - isr_data->mask != mask) 216 - continue; 217 - 218 - /* found the correct isr */ 219 - 220 - isr_data->isr = NULL; 221 - isr_data->arg = NULL; 222 - isr_data->mask = 0; 223 - 224 - ret = 0; 225 - break; 226 - } 227 - 228 - if (ret == 0) 229 - _omap_dispc_set_irqs(); 230 - 231 - spin_unlock_irqrestore(&dispc_compat.irq_lock, flags); 232 - 233 - return ret; 234 - } 235 - EXPORT_SYMBOL(omap_dispc_unregister_isr); 236 - 237 - static void print_irq_status(u32 status) 238 - { 239 - if ((status & dispc_compat.irq_error_mask) == 0) 240 - return; 241 - 242 - #define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : "" 243 - 244 - pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n", 245 - status, 246 - PIS(OCP_ERR), 247 - PIS(GFX_FIFO_UNDERFLOW), 248 - PIS(VID1_FIFO_UNDERFLOW), 249 - PIS(VID2_FIFO_UNDERFLOW), 250 - dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "", 251 - PIS(SYNC_LOST), 252 - PIS(SYNC_LOST_DIGIT), 253 - dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "", 254 - dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : ""); 255 - #undef PIS 256 - } 257 - 258 - /* Called from dss.c. Note that we don't touch clocks here, 259 - * but we presume they are on because we got an IRQ. However, 260 - * an irq handler may turn the clocks off, so we may not have 261 - * clock later in the function. */ 262 - static irqreturn_t omap_dispc_irq_handler(int irq, void *arg) 263 - { 264 - int i; 265 - u32 irqstatus, irqenable; 266 - u32 handledirqs = 0; 267 - u32 unhandled_errors; 268 - struct omap_dispc_isr_data *isr_data; 269 - struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; 270 - 271 - spin_lock(&dispc_compat.irq_lock); 272 - 273 - irqstatus = dispc_read_irqstatus(); 274 - irqenable = dispc_read_irqenable(); 275 - 276 - /* IRQ is not for us */ 277 - if (!(irqstatus & irqenable)) { 278 - spin_unlock(&dispc_compat.irq_lock); 279 - return IRQ_NONE; 280 - } 281 - 282 - #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 283 - spin_lock(&dispc_compat.irq_stats_lock); 284 - dispc_compat.irq_stats.irq_count++; 285 - dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs); 286 - spin_unlock(&dispc_compat.irq_stats_lock); 287 - #endif 288 - 289 - print_irq_status(irqstatus); 290 - 291 - /* Ack the interrupt. Do it here before clocks are possibly turned 292 - * off */ 293 - dispc_clear_irqstatus(irqstatus); 294 - /* flush posted write */ 295 - dispc_read_irqstatus(); 296 - 297 - /* make a copy and unlock, so that isrs can unregister 298 - * themselves */ 299 - memcpy(registered_isr, dispc_compat.registered_isr, 300 - sizeof(registered_isr)); 301 - 302 - spin_unlock(&dispc_compat.irq_lock); 303 - 304 - for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 305 - isr_data = &registered_isr[i]; 306 - 307 - if (!isr_data->isr) 308 - continue; 309 - 310 - if (isr_data->mask & irqstatus) { 311 - isr_data->isr(isr_data->arg, irqstatus); 312 - handledirqs |= isr_data->mask; 313 - } 314 - } 315 - 316 - spin_lock(&dispc_compat.irq_lock); 317 - 318 - unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask; 319 - 320 - if (unhandled_errors) { 321 - dispc_compat.error_irqs |= unhandled_errors; 322 - 323 - dispc_compat.irq_error_mask &= ~unhandled_errors; 324 - _omap_dispc_set_irqs(); 325 - 326 - schedule_work(&dispc_compat.error_work); 327 - } 328 - 329 - spin_unlock(&dispc_compat.irq_lock); 330 - 331 - return IRQ_HANDLED; 332 - } 333 - 334 - static void dispc_error_worker(struct work_struct *work) 335 - { 336 - int i; 337 - u32 errors; 338 - unsigned long flags; 339 - static const unsigned fifo_underflow_bits[] = { 340 - DISPC_IRQ_GFX_FIFO_UNDERFLOW, 341 - DISPC_IRQ_VID1_FIFO_UNDERFLOW, 342 - DISPC_IRQ_VID2_FIFO_UNDERFLOW, 343 - DISPC_IRQ_VID3_FIFO_UNDERFLOW, 344 - }; 345 - 346 - spin_lock_irqsave(&dispc_compat.irq_lock, flags); 347 - errors = dispc_compat.error_irqs; 348 - dispc_compat.error_irqs = 0; 349 - spin_unlock_irqrestore(&dispc_compat.irq_lock, flags); 350 - 351 - dispc_runtime_get(); 352 - 353 - for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 354 - struct omap_overlay *ovl; 355 - unsigned bit; 356 - 357 - ovl = omap_dss_get_overlay(i); 358 - bit = fifo_underflow_bits[i]; 359 - 360 - if (bit & errors) { 361 - DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n", 362 - ovl->name); 363 - ovl->disable(ovl); 364 - msleep(50); 365 - } 366 - } 367 - 368 - for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 369 - struct omap_overlay_manager *mgr; 370 - unsigned bit; 371 - 372 - mgr = omap_dss_get_overlay_manager(i); 373 - bit = dispc_mgr_get_sync_lost_irq(i); 374 - 375 - if (bit & errors) { 376 - int j; 377 - 378 - DSSERR("SYNC_LOST on channel %s, restarting the output " 379 - "with video overlays disabled\n", 380 - mgr->name); 381 - 382 - dss_mgr_disable(mgr->id); 383 - 384 - for (j = 0; j < omap_dss_get_num_overlays(); ++j) { 385 - struct omap_overlay *ovl; 386 - ovl = omap_dss_get_overlay(j); 387 - 388 - if (ovl->id != OMAP_DSS_GFX && 389 - ovl->manager == mgr) 390 - ovl->disable(ovl); 391 - } 392 - 393 - dss_mgr_enable(mgr->id); 394 - } 395 - } 396 - 397 - if (errors & DISPC_IRQ_OCP_ERR) { 398 - DSSERR("OCP_ERR\n"); 399 - for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 400 - struct omap_overlay_manager *mgr; 401 - 402 - mgr = omap_dss_get_overlay_manager(i); 403 - dss_mgr_disable(mgr->id); 404 - } 405 - } 406 - 407 - spin_lock_irqsave(&dispc_compat.irq_lock, flags); 408 - dispc_compat.irq_error_mask |= errors; 409 - _omap_dispc_set_irqs(); 410 - spin_unlock_irqrestore(&dispc_compat.irq_lock, flags); 411 - 412 - dispc_runtime_put(); 413 - } 414 - 415 - int dss_dispc_initialize_irq(void) 416 - { 417 - int r; 418 - 419 - #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 420 - spin_lock_init(&dispc_compat.irq_stats_lock); 421 - dispc_compat.irq_stats.last_reset = jiffies; 422 - dss_debugfs_create_file("dispc_irq", dispc_dump_irqs); 423 - #endif 424 - 425 - spin_lock_init(&dispc_compat.irq_lock); 426 - 427 - memset(dispc_compat.registered_isr, 0, 428 - sizeof(dispc_compat.registered_isr)); 429 - 430 - dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR; 431 - if (dss_has_feature(FEAT_MGR_LCD2)) 432 - dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; 433 - if (dss_has_feature(FEAT_MGR_LCD3)) 434 - dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3; 435 - if (dss_feat_get_num_ovls() > 3) 436 - dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW; 437 - 438 - /* 439 - * there's SYNC_LOST_DIGIT waiting after enabling the DSS, 440 - * so clear it 441 - */ 442 - dispc_clear_irqstatus(dispc_read_irqstatus()); 443 - 444 - INIT_WORK(&dispc_compat.error_work, dispc_error_worker); 445 - 446 - _omap_dispc_set_irqs(); 447 - 448 - r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat); 449 - if (r) { 450 - DSSERR("dispc_request_irq failed\n"); 451 - return r; 452 - } 453 - 454 - return 0; 455 - } 456 - 457 - void dss_dispc_uninitialize_irq(void) 458 - { 459 - dispc_free_irq(&dispc_compat); 460 - } 461 - 462 - static void dispc_mgr_disable_isr(void *data, u32 mask) 463 - { 464 - struct completion *compl = data; 465 - complete(compl); 466 - } 467 - 468 - static void dispc_mgr_enable_lcd_out(enum omap_channel channel) 469 - { 470 - dispc_mgr_enable(channel, true); 471 - } 472 - 473 - static void dispc_mgr_disable_lcd_out(enum omap_channel channel) 474 - { 475 - DECLARE_COMPLETION_ONSTACK(framedone_compl); 476 - int r; 477 - u32 irq; 478 - 479 - if (!dispc_mgr_is_enabled(channel)) 480 - return; 481 - 482 - /* 483 - * When we disable LCD output, we need to wait for FRAMEDONE to know 484 - * that DISPC has finished with the LCD output. 485 - */ 486 - 487 - irq = dispc_mgr_get_framedone_irq(channel); 488 - 489 - r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl, 490 - irq); 491 - if (r) 492 - DSSERR("failed to register FRAMEDONE isr\n"); 493 - 494 - dispc_mgr_enable(channel, false); 495 - 496 - /* if we couldn't register for framedone, just sleep and exit */ 497 - if (r) { 498 - msleep(100); 499 - return; 500 - } 501 - 502 - if (!wait_for_completion_timeout(&framedone_compl, 503 - msecs_to_jiffies(100))) 504 - DSSERR("timeout waiting for FRAME DONE\n"); 505 - 506 - r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl, 507 - irq); 508 - if (r) 509 - DSSERR("failed to unregister FRAMEDONE isr\n"); 510 - } 511 - 512 - static void dispc_digit_out_enable_isr(void *data, u32 mask) 513 - { 514 - struct completion *compl = data; 515 - 516 - /* ignore any sync lost interrupts */ 517 - if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD)) 518 - complete(compl); 519 - } 520 - 521 - static void dispc_mgr_enable_digit_out(void) 522 - { 523 - DECLARE_COMPLETION_ONSTACK(vsync_compl); 524 - int r; 525 - u32 irq_mask; 526 - 527 - if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT)) 528 - return; 529 - 530 - /* 531 - * Digit output produces some sync lost interrupts during the first 532 - * frame when enabling. Those need to be ignored, so we register for the 533 - * sync lost irq to prevent the error handler from triggering. 534 - */ 535 - 536 - irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) | 537 - dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT); 538 - 539 - r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl, 540 - irq_mask); 541 - if (r) { 542 - DSSERR("failed to register %x isr\n", irq_mask); 543 - return; 544 - } 545 - 546 - dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true); 547 - 548 - /* wait for the first evsync */ 549 - if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100))) 550 - DSSERR("timeout waiting for digit out to start\n"); 551 - 552 - r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl, 553 - irq_mask); 554 - if (r) 555 - DSSERR("failed to unregister %x isr\n", irq_mask); 556 - } 557 - 558 - static void dispc_mgr_disable_digit_out(void) 559 - { 560 - DECLARE_COMPLETION_ONSTACK(framedone_compl); 561 - int r, i; 562 - u32 irq_mask; 563 - int num_irqs; 564 - 565 - if (!dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT)) 566 - return; 567 - 568 - /* 569 - * When we disable the digit output, we need to wait for FRAMEDONE to 570 - * know that DISPC has finished with the output. 571 - */ 572 - 573 - irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT); 574 - num_irqs = 1; 575 - 576 - if (!irq_mask) { 577 - /* 578 - * omap 2/3 don't have framedone irq for TV, so we need to use 579 - * vsyncs for this. 580 - */ 581 - 582 - irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT); 583 - /* 584 - * We need to wait for both even and odd vsyncs. Note that this 585 - * is not totally reliable, as we could get a vsync interrupt 586 - * before we disable the output, which leads to timeout in the 587 - * wait_for_completion. 588 - */ 589 - num_irqs = 2; 590 - } 591 - 592 - r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl, 593 - irq_mask); 594 - if (r) 595 - DSSERR("failed to register %x isr\n", irq_mask); 596 - 597 - dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false); 598 - 599 - /* if we couldn't register the irq, just sleep and exit */ 600 - if (r) { 601 - msleep(100); 602 - return; 603 - } 604 - 605 - for (i = 0; i < num_irqs; ++i) { 606 - if (!wait_for_completion_timeout(&framedone_compl, 607 - msecs_to_jiffies(100))) 608 - DSSERR("timeout waiting for digit out to stop\n"); 609 - } 610 - 611 - r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl, 612 - irq_mask); 613 - if (r) 614 - DSSERR("failed to unregister %x isr\n", irq_mask); 615 - } 616 - 617 - void dispc_mgr_enable_sync(enum omap_channel channel) 618 - { 619 - if (dss_mgr_is_lcd(channel)) 620 - dispc_mgr_enable_lcd_out(channel); 621 - else if (channel == OMAP_DSS_CHANNEL_DIGIT) 622 - dispc_mgr_enable_digit_out(); 623 - else 624 - WARN_ON(1); 625 - } 626 - 627 - void dispc_mgr_disable_sync(enum omap_channel channel) 628 - { 629 - if (dss_mgr_is_lcd(channel)) 630 - dispc_mgr_disable_lcd_out(channel); 631 - else if (channel == OMAP_DSS_CHANNEL_DIGIT) 632 - dispc_mgr_disable_digit_out(); 633 - else 634 - WARN_ON(1); 635 - } 636 - 637 - static inline void dispc_irq_wait_handler(void *data, u32 mask) 638 - { 639 - complete((struct completion *)data); 640 - } 641 - 642 - int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, 643 - unsigned long timeout) 644 - { 645 - 646 - int r; 647 - DECLARE_COMPLETION_ONSTACK(completion); 648 - 649 - r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, 650 - irqmask); 651 - 652 - if (r) 653 - return r; 654 - 655 - timeout = wait_for_completion_interruptible_timeout(&completion, 656 - timeout); 657 - 658 - omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); 659 - 660 - if (timeout == 0) 661 - return -ETIMEDOUT; 662 - 663 - if (timeout == -ERESTARTSYS) 664 - return -ERESTARTSYS; 665 - 666 - return 0; 667 - }
-30
drivers/gpu/drm/omapdrm/dss/dispc-compat.h
··· 1 - /* 2 - * Copyright (C) 2012 Texas Instruments 3 - * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 4 - * 5 - * This program is free software; you can redistribute it and/or modify it 6 - * under the terms of the GNU General Public License version 2 as published by 7 - * the Free Software Foundation. 8 - * 9 - * This program is distributed in the hope that it will be useful, but WITHOUT 10 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 - * more details. 13 - * 14 - * You should have received a copy of the GNU General Public License along with 15 - * this program. If not, see <http://www.gnu.org/licenses/>. 16 - */ 17 - 18 - #ifndef __OMAP2_DSS_DISPC_COMPAT_H 19 - #define __OMAP2_DSS_DISPC_COMPAT_H 20 - 21 - void dispc_mgr_enable_sync(enum omap_channel channel); 22 - void dispc_mgr_disable_sync(enum omap_channel channel); 23 - 24 - int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, 25 - unsigned long timeout); 26 - 27 - int dss_dispc_initialize_irq(void); 28 - void dss_dispc_uninitialize_irq(void); 29 - 30 - #endif
-4
drivers/gpu/drm/omapdrm/dss/dispc.c
··· 4155 4155 4156 4156 dispc_runtime_put(); 4157 4157 4158 - dss_init_overlay_managers(); 4159 - 4160 4158 dss_debugfs_create_file("dispc", dispc_dump_regs); 4161 4159 4162 4160 return 0; ··· 4168 4170 void *data) 4169 4171 { 4170 4172 pm_runtime_disable(dev); 4171 - 4172 - dss_uninit_overlay_managers(); 4173 4173 } 4174 4174 4175 4175 static const struct component_ops dispc_component_ops = {
-356
drivers/gpu/drm/omapdrm/dss/display-sysfs.c
··· 1 - /* 2 - * Copyright (C) 2009 Nokia Corporation 3 - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 4 - * 5 - * Some code and ideas taken from drivers/video/omap/ driver 6 - * by Imre Deak. 7 - * 8 - * This program is free software; you can redistribute it and/or modify it 9 - * under the terms of the GNU General Public License version 2 as published by 10 - * the Free Software Foundation. 11 - * 12 - * This program is distributed in the hope that it will be useful, but WITHOUT 13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 - * more details. 16 - * 17 - * You should have received a copy of the GNU General Public License along with 18 - * this program. If not, see <http://www.gnu.org/licenses/>. 19 - */ 20 - 21 - #define DSS_SUBSYS_NAME "DISPLAY" 22 - 23 - #include <linux/kernel.h> 24 - #include <linux/module.h> 25 - #include <linux/platform_device.h> 26 - #include <linux/sysfs.h> 27 - 28 - #include <video/omapdss.h> 29 - #include "dss.h" 30 - 31 - static ssize_t display_name_show(struct omap_dss_device *dssdev, char *buf) 32 - { 33 - return snprintf(buf, PAGE_SIZE, "%s\n", 34 - dssdev->name ? 35 - dssdev->name : ""); 36 - } 37 - 38 - static ssize_t display_enabled_show(struct omap_dss_device *dssdev, char *buf) 39 - { 40 - return snprintf(buf, PAGE_SIZE, "%d\n", 41 - omapdss_device_is_enabled(dssdev)); 42 - } 43 - 44 - static ssize_t display_enabled_store(struct omap_dss_device *dssdev, 45 - const char *buf, size_t size) 46 - { 47 - int r; 48 - bool enable; 49 - 50 - r = strtobool(buf, &enable); 51 - if (r) 52 - return r; 53 - 54 - if (enable == omapdss_device_is_enabled(dssdev)) 55 - return size; 56 - 57 - if (omapdss_device_is_connected(dssdev) == false) 58 - return -ENODEV; 59 - 60 - if (enable) { 61 - r = dssdev->driver->enable(dssdev); 62 - if (r) 63 - return r; 64 - } else { 65 - dssdev->driver->disable(dssdev); 66 - } 67 - 68 - return size; 69 - } 70 - 71 - static ssize_t display_tear_show(struct omap_dss_device *dssdev, char *buf) 72 - { 73 - return snprintf(buf, PAGE_SIZE, "%d\n", 74 - dssdev->driver->get_te ? 75 - dssdev->driver->get_te(dssdev) : 0); 76 - } 77 - 78 - static ssize_t display_tear_store(struct omap_dss_device *dssdev, 79 - const char *buf, size_t size) 80 - { 81 - int r; 82 - bool te; 83 - 84 - if (!dssdev->driver->enable_te || !dssdev->driver->get_te) 85 - return -ENOENT; 86 - 87 - r = strtobool(buf, &te); 88 - if (r) 89 - return r; 90 - 91 - r = dssdev->driver->enable_te(dssdev, te); 92 - if (r) 93 - return r; 94 - 95 - return size; 96 - } 97 - 98 - static ssize_t display_timings_show(struct omap_dss_device *dssdev, char *buf) 99 - { 100 - struct omap_video_timings t; 101 - 102 - if (!dssdev->driver->get_timings) 103 - return -ENOENT; 104 - 105 - dssdev->driver->get_timings(dssdev, &t); 106 - 107 - return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n", 108 - t.pixelclock, 109 - t.x_res, t.hfp, t.hbp, t.hsw, 110 - t.y_res, t.vfp, t.vbp, t.vsw); 111 - } 112 - 113 - static ssize_t display_timings_store(struct omap_dss_device *dssdev, 114 - const char *buf, size_t size) 115 - { 116 - struct omap_video_timings t = dssdev->panel.timings; 117 - int r, found; 118 - 119 - if (!dssdev->driver->set_timings || !dssdev->driver->check_timings) 120 - return -ENOENT; 121 - 122 - found = 0; 123 - #ifdef CONFIG_OMAP2_DSS_VENC 124 - if (strncmp("pal", buf, 3) == 0) { 125 - t = omap_dss_pal_timings; 126 - found = 1; 127 - } else if (strncmp("ntsc", buf, 4) == 0) { 128 - t = omap_dss_ntsc_timings; 129 - found = 1; 130 - } 131 - #endif 132 - if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu", 133 - &t.pixelclock, 134 - &t.x_res, &t.hfp, &t.hbp, &t.hsw, 135 - &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9) 136 - return -EINVAL; 137 - 138 - r = dssdev->driver->check_timings(dssdev, &t); 139 - if (r) 140 - return r; 141 - 142 - dssdev->driver->disable(dssdev); 143 - dssdev->driver->set_timings(dssdev, &t); 144 - r = dssdev->driver->enable(dssdev); 145 - if (r) 146 - return r; 147 - 148 - return size; 149 - } 150 - 151 - static ssize_t display_rotate_show(struct omap_dss_device *dssdev, char *buf) 152 - { 153 - int rotate; 154 - if (!dssdev->driver->get_rotate) 155 - return -ENOENT; 156 - rotate = dssdev->driver->get_rotate(dssdev); 157 - return snprintf(buf, PAGE_SIZE, "%u\n", rotate); 158 - } 159 - 160 - static ssize_t display_rotate_store(struct omap_dss_device *dssdev, 161 - const char *buf, size_t size) 162 - { 163 - int rot, r; 164 - 165 - if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) 166 - return -ENOENT; 167 - 168 - r = kstrtoint(buf, 0, &rot); 169 - if (r) 170 - return r; 171 - 172 - r = dssdev->driver->set_rotate(dssdev, rot); 173 - if (r) 174 - return r; 175 - 176 - return size; 177 - } 178 - 179 - static ssize_t display_mirror_show(struct omap_dss_device *dssdev, char *buf) 180 - { 181 - int mirror; 182 - if (!dssdev->driver->get_mirror) 183 - return -ENOENT; 184 - mirror = dssdev->driver->get_mirror(dssdev); 185 - return snprintf(buf, PAGE_SIZE, "%u\n", mirror); 186 - } 187 - 188 - static ssize_t display_mirror_store(struct omap_dss_device *dssdev, 189 - const char *buf, size_t size) 190 - { 191 - int r; 192 - bool mirror; 193 - 194 - if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) 195 - return -ENOENT; 196 - 197 - r = strtobool(buf, &mirror); 198 - if (r) 199 - return r; 200 - 201 - r = dssdev->driver->set_mirror(dssdev, mirror); 202 - if (r) 203 - return r; 204 - 205 - return size; 206 - } 207 - 208 - static ssize_t display_wss_show(struct omap_dss_device *dssdev, char *buf) 209 - { 210 - unsigned int wss; 211 - 212 - if (!dssdev->driver->get_wss) 213 - return -ENOENT; 214 - 215 - wss = dssdev->driver->get_wss(dssdev); 216 - 217 - return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss); 218 - } 219 - 220 - static ssize_t display_wss_store(struct omap_dss_device *dssdev, 221 - const char *buf, size_t size) 222 - { 223 - u32 wss; 224 - int r; 225 - 226 - if (!dssdev->driver->get_wss || !dssdev->driver->set_wss) 227 - return -ENOENT; 228 - 229 - r = kstrtou32(buf, 0, &wss); 230 - if (r) 231 - return r; 232 - 233 - if (wss > 0xfffff) 234 - return -EINVAL; 235 - 236 - r = dssdev->driver->set_wss(dssdev, wss); 237 - if (r) 238 - return r; 239 - 240 - return size; 241 - } 242 - 243 - struct display_attribute { 244 - struct attribute attr; 245 - ssize_t (*show)(struct omap_dss_device *, char *); 246 - ssize_t (*store)(struct omap_dss_device *, const char *, size_t); 247 - }; 248 - 249 - #define DISPLAY_ATTR(_name, _mode, _show, _store) \ 250 - struct display_attribute display_attr_##_name = \ 251 - __ATTR(_name, _mode, _show, _store) 252 - 253 - static DISPLAY_ATTR(name, S_IRUGO, display_name_show, NULL); 254 - static DISPLAY_ATTR(display_name, S_IRUGO, display_name_show, NULL); 255 - static DISPLAY_ATTR(enabled, S_IRUGO|S_IWUSR, 256 - display_enabled_show, display_enabled_store); 257 - static DISPLAY_ATTR(tear_elim, S_IRUGO|S_IWUSR, 258 - display_tear_show, display_tear_store); 259 - static DISPLAY_ATTR(timings, S_IRUGO|S_IWUSR, 260 - display_timings_show, display_timings_store); 261 - static DISPLAY_ATTR(rotate, S_IRUGO|S_IWUSR, 262 - display_rotate_show, display_rotate_store); 263 - static DISPLAY_ATTR(mirror, S_IRUGO|S_IWUSR, 264 - display_mirror_show, display_mirror_store); 265 - static DISPLAY_ATTR(wss, S_IRUGO|S_IWUSR, 266 - display_wss_show, display_wss_store); 267 - 268 - static struct attribute *display_sysfs_attrs[] = { 269 - &display_attr_name.attr, 270 - &display_attr_display_name.attr, 271 - &display_attr_enabled.attr, 272 - &display_attr_tear_elim.attr, 273 - &display_attr_timings.attr, 274 - &display_attr_rotate.attr, 275 - &display_attr_mirror.attr, 276 - &display_attr_wss.attr, 277 - NULL 278 - }; 279 - 280 - static ssize_t display_attr_show(struct kobject *kobj, struct attribute *attr, 281 - char *buf) 282 - { 283 - struct omap_dss_device *dssdev; 284 - struct display_attribute *display_attr; 285 - 286 - dssdev = container_of(kobj, struct omap_dss_device, kobj); 287 - display_attr = container_of(attr, struct display_attribute, attr); 288 - 289 - if (!display_attr->show) 290 - return -ENOENT; 291 - 292 - return display_attr->show(dssdev, buf); 293 - } 294 - 295 - static ssize_t display_attr_store(struct kobject *kobj, struct attribute *attr, 296 - const char *buf, size_t size) 297 - { 298 - struct omap_dss_device *dssdev; 299 - struct display_attribute *display_attr; 300 - 301 - dssdev = container_of(kobj, struct omap_dss_device, kobj); 302 - display_attr = container_of(attr, struct display_attribute, attr); 303 - 304 - if (!display_attr->store) 305 - return -ENOENT; 306 - 307 - return display_attr->store(dssdev, buf, size); 308 - } 309 - 310 - static const struct sysfs_ops display_sysfs_ops = { 311 - .show = display_attr_show, 312 - .store = display_attr_store, 313 - }; 314 - 315 - static struct kobj_type display_ktype = { 316 - .sysfs_ops = &display_sysfs_ops, 317 - .default_attrs = display_sysfs_attrs, 318 - }; 319 - 320 - int display_init_sysfs(struct platform_device *pdev) 321 - { 322 - struct omap_dss_device *dssdev = NULL; 323 - int r; 324 - 325 - for_each_dss_dev(dssdev) { 326 - r = kobject_init_and_add(&dssdev->kobj, &display_ktype, 327 - &pdev->dev.kobj, "%s", dssdev->alias); 328 - if (r) { 329 - DSSERR("failed to create sysfs files\n"); 330 - omap_dss_put_device(dssdev); 331 - goto err; 332 - } 333 - } 334 - 335 - return 0; 336 - 337 - err: 338 - display_uninit_sysfs(pdev); 339 - 340 - return r; 341 - } 342 - 343 - void display_uninit_sysfs(struct platform_device *pdev) 344 - { 345 - struct omap_dss_device *dssdev = NULL; 346 - 347 - for_each_dss_dev(dssdev) { 348 - if (kobject_name(&dssdev->kobj) == NULL) 349 - continue; 350 - 351 - kobject_del(&dssdev->kobj); 352 - kobject_put(&dssdev->kobj); 353 - 354 - memset(&dssdev->kobj, 0, sizeof(dssdev->kobj)); 355 - } 356 - }
-37
drivers/gpu/drm/omapdrm/dss/dss.h
··· 207 207 int dss_set_min_bus_tput(struct device *dev, unsigned long tput); 208 208 int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); 209 209 210 - /* display */ 211 - int display_init_sysfs(struct platform_device *pdev); 212 - void display_uninit_sysfs(struct platform_device *pdev); 213 - 214 - /* manager */ 215 - int dss_init_overlay_managers(void); 216 - void dss_uninit_overlay_managers(void); 217 - int dss_init_overlay_managers_sysfs(struct platform_device *pdev); 218 - void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev); 219 - int dss_mgr_simple_check(struct omap_overlay_manager *mgr, 220 - const struct omap_overlay_manager_info *info); 221 - int dss_mgr_check_timings(struct omap_overlay_manager *mgr, 222 - const struct omap_video_timings *timings); 223 - int dss_mgr_check(struct omap_overlay_manager *mgr, 224 - struct omap_overlay_manager_info *info, 225 - const struct omap_video_timings *mgr_timings, 226 - const struct dss_lcd_mgr_config *config, 227 - struct omap_overlay_info **overlay_infos); 228 - 229 210 static inline bool dss_mgr_is_lcd(enum omap_channel id) 230 211 { 231 212 if (id == OMAP_DSS_CHANNEL_LCD || id == OMAP_DSS_CHANNEL_LCD2 || ··· 215 234 else 216 235 return false; 217 236 } 218 - 219 - int dss_manager_kobj_init(struct omap_overlay_manager *mgr, 220 - struct platform_device *pdev); 221 - void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr); 222 - 223 - /* overlay */ 224 - void dss_init_overlays(struct platform_device *pdev); 225 - void dss_uninit_overlays(struct platform_device *pdev); 226 - void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); 227 - int dss_ovl_simple_check(struct omap_overlay *ovl, 228 - const struct omap_overlay_info *info); 229 - int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, 230 - const struct omap_video_timings *mgr_timings); 231 - bool dss_ovl_use_replication(struct dss_lcd_mgr_config config, 232 - enum omap_color_mode mode); 233 - int dss_overlay_kobj_init(struct omap_overlay *ovl, 234 - struct platform_device *pdev); 235 - void dss_overlay_kobj_uninit(struct omap_overlay *ovl); 236 237 237 238 /* DSS */ 238 239 int dss_init_platform_driver(void) __init;
-531
drivers/gpu/drm/omapdrm/dss/manager-sysfs.c
··· 1 - /* 2 - * Copyright (C) 2009 Nokia Corporation 3 - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 4 - * 5 - * Some code and ideas taken from drivers/video/omap/ driver 6 - * by Imre Deak. 7 - * 8 - * This program is free software; you can redistribute it and/or modify it 9 - * under the terms of the GNU General Public License version 2 as published by 10 - * the Free Software Foundation. 11 - * 12 - * This program is distributed in the hope that it will be useful, but WITHOUT 13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 - * more details. 16 - * 17 - * You should have received a copy of the GNU General Public License along with 18 - * this program. If not, see <http://www.gnu.org/licenses/>. 19 - */ 20 - 21 - #define DSS_SUBSYS_NAME "MANAGER" 22 - 23 - #include <linux/kernel.h> 24 - #include <linux/slab.h> 25 - #include <linux/module.h> 26 - #include <linux/platform_device.h> 27 - #include <linux/jiffies.h> 28 - 29 - #include <video/omapdss.h> 30 - 31 - #include "dss.h" 32 - #include "dss_features.h" 33 - 34 - static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) 35 - { 36 - return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); 37 - } 38 - 39 - static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) 40 - { 41 - struct omap_dss_device *dssdev = mgr->get_device(mgr); 42 - 43 - return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ? 44 - dssdev->name : "<none>"); 45 - } 46 - 47 - static int manager_display_match(struct omap_dss_device *dssdev, void *data) 48 - { 49 - const char *str = data; 50 - 51 - return sysfs_streq(dssdev->name, str); 52 - } 53 - 54 - static ssize_t manager_display_store(struct omap_overlay_manager *mgr, 55 - const char *buf, size_t size) 56 - { 57 - int r = 0; 58 - size_t len = size; 59 - struct omap_dss_device *dssdev = NULL; 60 - struct omap_dss_device *old_dssdev; 61 - 62 - if (buf[size-1] == '\n') 63 - --len; 64 - 65 - if (len > 0) 66 - dssdev = omap_dss_find_device((void *)buf, 67 - manager_display_match); 68 - 69 - if (len > 0 && dssdev == NULL) 70 - return -EINVAL; 71 - 72 - if (dssdev) { 73 - DSSDBG("display %s found\n", dssdev->name); 74 - 75 - if (omapdss_device_is_connected(dssdev)) { 76 - DSSERR("new display is already connected\n"); 77 - r = -EINVAL; 78 - goto put_device; 79 - } 80 - 81 - if (omapdss_device_is_enabled(dssdev)) { 82 - DSSERR("new display is not disabled\n"); 83 - r = -EINVAL; 84 - goto put_device; 85 - } 86 - } 87 - 88 - old_dssdev = mgr->get_device(mgr); 89 - if (old_dssdev) { 90 - if (omapdss_device_is_enabled(old_dssdev)) { 91 - DSSERR("old display is not disabled\n"); 92 - r = -EINVAL; 93 - goto put_device; 94 - } 95 - 96 - old_dssdev->driver->disconnect(old_dssdev); 97 - } 98 - 99 - if (dssdev) { 100 - r = dssdev->driver->connect(dssdev); 101 - if (r) { 102 - DSSERR("failed to connect new device\n"); 103 - goto put_device; 104 - } 105 - 106 - old_dssdev = mgr->get_device(mgr); 107 - if (old_dssdev != dssdev) { 108 - DSSERR("failed to connect device to this manager\n"); 109 - dssdev->driver->disconnect(dssdev); 110 - goto put_device; 111 - } 112 - 113 - r = mgr->apply(mgr); 114 - if (r) { 115 - DSSERR("failed to apply dispc config\n"); 116 - goto put_device; 117 - } 118 - } 119 - 120 - put_device: 121 - if (dssdev) 122 - omap_dss_put_device(dssdev); 123 - 124 - return r ? r : size; 125 - } 126 - 127 - static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, 128 - char *buf) 129 - { 130 - struct omap_overlay_manager_info info; 131 - 132 - mgr->get_manager_info(mgr, &info); 133 - 134 - return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color); 135 - } 136 - 137 - static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, 138 - const char *buf, size_t size) 139 - { 140 - struct omap_overlay_manager_info info; 141 - u32 color; 142 - int r; 143 - 144 - r = kstrtouint(buf, 0, &color); 145 - if (r) 146 - return r; 147 - 148 - mgr->get_manager_info(mgr, &info); 149 - 150 - info.default_color = color; 151 - 152 - r = mgr->set_manager_info(mgr, &info); 153 - if (r) 154 - return r; 155 - 156 - r = mgr->apply(mgr); 157 - if (r) 158 - return r; 159 - 160 - return size; 161 - } 162 - 163 - static const char *trans_key_type_str[] = { 164 - "gfx-destination", 165 - "video-source", 166 - }; 167 - 168 - static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr, 169 - char *buf) 170 - { 171 - enum omap_dss_trans_key_type key_type; 172 - struct omap_overlay_manager_info info; 173 - 174 - mgr->get_manager_info(mgr, &info); 175 - 176 - key_type = info.trans_key_type; 177 - BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); 178 - 179 - return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]); 180 - } 181 - 182 - static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, 183 - const char *buf, size_t size) 184 - { 185 - enum omap_dss_trans_key_type key_type; 186 - struct omap_overlay_manager_info info; 187 - int r; 188 - 189 - for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST; 190 - key_type < ARRAY_SIZE(trans_key_type_str); key_type++) { 191 - if (sysfs_streq(buf, trans_key_type_str[key_type])) 192 - break; 193 - } 194 - 195 - if (key_type == ARRAY_SIZE(trans_key_type_str)) 196 - return -EINVAL; 197 - 198 - mgr->get_manager_info(mgr, &info); 199 - 200 - info.trans_key_type = key_type; 201 - 202 - r = mgr->set_manager_info(mgr, &info); 203 - if (r) 204 - return r; 205 - 206 - r = mgr->apply(mgr); 207 - if (r) 208 - return r; 209 - 210 - return size; 211 - } 212 - 213 - static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, 214 - char *buf) 215 - { 216 - struct omap_overlay_manager_info info; 217 - 218 - mgr->get_manager_info(mgr, &info); 219 - 220 - return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key); 221 - } 222 - 223 - static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, 224 - const char *buf, size_t size) 225 - { 226 - struct omap_overlay_manager_info info; 227 - u32 key_value; 228 - int r; 229 - 230 - r = kstrtouint(buf, 0, &key_value); 231 - if (r) 232 - return r; 233 - 234 - mgr->get_manager_info(mgr, &info); 235 - 236 - info.trans_key = key_value; 237 - 238 - r = mgr->set_manager_info(mgr, &info); 239 - if (r) 240 - return r; 241 - 242 - r = mgr->apply(mgr); 243 - if (r) 244 - return r; 245 - 246 - return size; 247 - } 248 - 249 - static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, 250 - char *buf) 251 - { 252 - struct omap_overlay_manager_info info; 253 - 254 - mgr->get_manager_info(mgr, &info); 255 - 256 - return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled); 257 - } 258 - 259 - static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, 260 - const char *buf, size_t size) 261 - { 262 - struct omap_overlay_manager_info info; 263 - bool enable; 264 - int r; 265 - 266 - r = strtobool(buf, &enable); 267 - if (r) 268 - return r; 269 - 270 - mgr->get_manager_info(mgr, &info); 271 - 272 - info.trans_enabled = enable; 273 - 274 - r = mgr->set_manager_info(mgr, &info); 275 - if (r) 276 - return r; 277 - 278 - r = mgr->apply(mgr); 279 - if (r) 280 - return r; 281 - 282 - return size; 283 - } 284 - 285 - static ssize_t manager_alpha_blending_enabled_show( 286 - struct omap_overlay_manager *mgr, char *buf) 287 - { 288 - struct omap_overlay_manager_info info; 289 - 290 - if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) 291 - return -ENODEV; 292 - 293 - mgr->get_manager_info(mgr, &info); 294 - 295 - return snprintf(buf, PAGE_SIZE, "%d\n", 296 - info.partial_alpha_enabled); 297 - } 298 - 299 - static ssize_t manager_alpha_blending_enabled_store( 300 - struct omap_overlay_manager *mgr, 301 - const char *buf, size_t size) 302 - { 303 - struct omap_overlay_manager_info info; 304 - bool enable; 305 - int r; 306 - 307 - if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) 308 - return -ENODEV; 309 - 310 - r = strtobool(buf, &enable); 311 - if (r) 312 - return r; 313 - 314 - mgr->get_manager_info(mgr, &info); 315 - 316 - info.partial_alpha_enabled = enable; 317 - 318 - r = mgr->set_manager_info(mgr, &info); 319 - if (r) 320 - return r; 321 - 322 - r = mgr->apply(mgr); 323 - if (r) 324 - return r; 325 - 326 - return size; 327 - } 328 - 329 - static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr, 330 - char *buf) 331 - { 332 - struct omap_overlay_manager_info info; 333 - 334 - mgr->get_manager_info(mgr, &info); 335 - 336 - return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable); 337 - } 338 - 339 - static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, 340 - const char *buf, size_t size) 341 - { 342 - struct omap_overlay_manager_info info; 343 - int r; 344 - bool enable; 345 - 346 - if (!dss_has_feature(FEAT_CPR)) 347 - return -ENODEV; 348 - 349 - r = strtobool(buf, &enable); 350 - if (r) 351 - return r; 352 - 353 - mgr->get_manager_info(mgr, &info); 354 - 355 - if (info.cpr_enable == enable) 356 - return size; 357 - 358 - info.cpr_enable = enable; 359 - 360 - r = mgr->set_manager_info(mgr, &info); 361 - if (r) 362 - return r; 363 - 364 - r = mgr->apply(mgr); 365 - if (r) 366 - return r; 367 - 368 - return size; 369 - } 370 - 371 - static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr, 372 - char *buf) 373 - { 374 - struct omap_overlay_manager_info info; 375 - 376 - mgr->get_manager_info(mgr, &info); 377 - 378 - return snprintf(buf, PAGE_SIZE, 379 - "%d %d %d %d %d %d %d %d %d\n", 380 - info.cpr_coefs.rr, 381 - info.cpr_coefs.rg, 382 - info.cpr_coefs.rb, 383 - info.cpr_coefs.gr, 384 - info.cpr_coefs.gg, 385 - info.cpr_coefs.gb, 386 - info.cpr_coefs.br, 387 - info.cpr_coefs.bg, 388 - info.cpr_coefs.bb); 389 - } 390 - 391 - static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr, 392 - const char *buf, size_t size) 393 - { 394 - struct omap_overlay_manager_info info; 395 - struct omap_dss_cpr_coefs coefs; 396 - int r, i; 397 - s16 *arr; 398 - 399 - if (!dss_has_feature(FEAT_CPR)) 400 - return -ENODEV; 401 - 402 - if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd", 403 - &coefs.rr, &coefs.rg, &coefs.rb, 404 - &coefs.gr, &coefs.gg, &coefs.gb, 405 - &coefs.br, &coefs.bg, &coefs.bb) != 9) 406 - return -EINVAL; 407 - 408 - arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb, 409 - coefs.gr, coefs.gg, coefs.gb, 410 - coefs.br, coefs.bg, coefs.bb }; 411 - 412 - for (i = 0; i < 9; ++i) { 413 - if (arr[i] < -512 || arr[i] > 511) 414 - return -EINVAL; 415 - } 416 - 417 - mgr->get_manager_info(mgr, &info); 418 - 419 - info.cpr_coefs = coefs; 420 - 421 - r = mgr->set_manager_info(mgr, &info); 422 - if (r) 423 - return r; 424 - 425 - r = mgr->apply(mgr); 426 - if (r) 427 - return r; 428 - 429 - return size; 430 - } 431 - 432 - struct manager_attribute { 433 - struct attribute attr; 434 - ssize_t (*show)(struct omap_overlay_manager *, char *); 435 - ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t); 436 - }; 437 - 438 - #define MANAGER_ATTR(_name, _mode, _show, _store) \ 439 - struct manager_attribute manager_attr_##_name = \ 440 - __ATTR(_name, _mode, _show, _store) 441 - 442 - static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); 443 - static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, 444 - manager_display_show, manager_display_store); 445 - static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, 446 - manager_default_color_show, manager_default_color_store); 447 - static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, 448 - manager_trans_key_type_show, manager_trans_key_type_store); 449 - static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, 450 - manager_trans_key_value_show, manager_trans_key_value_store); 451 - static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, 452 - manager_trans_key_enabled_show, 453 - manager_trans_key_enabled_store); 454 - static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, 455 - manager_alpha_blending_enabled_show, 456 - manager_alpha_blending_enabled_store); 457 - static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR, 458 - manager_cpr_enable_show, 459 - manager_cpr_enable_store); 460 - static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR, 461 - manager_cpr_coef_show, 462 - manager_cpr_coef_store); 463 - 464 - 465 - static struct attribute *manager_sysfs_attrs[] = { 466 - &manager_attr_name.attr, 467 - &manager_attr_display.attr, 468 - &manager_attr_default_color.attr, 469 - &manager_attr_trans_key_type.attr, 470 - &manager_attr_trans_key_value.attr, 471 - &manager_attr_trans_key_enabled.attr, 472 - &manager_attr_alpha_blending_enabled.attr, 473 - &manager_attr_cpr_enable.attr, 474 - &manager_attr_cpr_coef.attr, 475 - NULL 476 - }; 477 - 478 - static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, 479 - char *buf) 480 - { 481 - struct omap_overlay_manager *manager; 482 - struct manager_attribute *manager_attr; 483 - 484 - manager = container_of(kobj, struct omap_overlay_manager, kobj); 485 - manager_attr = container_of(attr, struct manager_attribute, attr); 486 - 487 - if (!manager_attr->show) 488 - return -ENOENT; 489 - 490 - return manager_attr->show(manager, buf); 491 - } 492 - 493 - static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, 494 - const char *buf, size_t size) 495 - { 496 - struct omap_overlay_manager *manager; 497 - struct manager_attribute *manager_attr; 498 - 499 - manager = container_of(kobj, struct omap_overlay_manager, kobj); 500 - manager_attr = container_of(attr, struct manager_attribute, attr); 501 - 502 - if (!manager_attr->store) 503 - return -ENOENT; 504 - 505 - return manager_attr->store(manager, buf, size); 506 - } 507 - 508 - static const struct sysfs_ops manager_sysfs_ops = { 509 - .show = manager_attr_show, 510 - .store = manager_attr_store, 511 - }; 512 - 513 - static struct kobj_type manager_ktype = { 514 - .sysfs_ops = &manager_sysfs_ops, 515 - .default_attrs = manager_sysfs_attrs, 516 - }; 517 - 518 - int dss_manager_kobj_init(struct omap_overlay_manager *mgr, 519 - struct platform_device *pdev) 520 - { 521 - return kobject_init_and_add(&mgr->kobj, &manager_ktype, 522 - &pdev->dev.kobj, "manager%d", mgr->id); 523 - } 524 - 525 - void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr) 526 - { 527 - kobject_del(&mgr->kobj); 528 - kobject_put(&mgr->kobj); 529 - 530 - memset(&mgr->kobj, 0, sizeof(mgr->kobj)); 531 - }
-263
drivers/gpu/drm/omapdrm/dss/manager.c
··· 1 - /* 2 - * linux/drivers/video/omap2/dss/manager.c 3 - * 4 - * Copyright (C) 2009 Nokia Corporation 5 - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 6 - * 7 - * Some code and ideas taken from drivers/video/omap/ driver 8 - * by Imre Deak. 9 - * 10 - * This program is free software; you can redistribute it and/or modify it 11 - * under the terms of the GNU General Public License version 2 as published by 12 - * the Free Software Foundation. 13 - * 14 - * This program is distributed in the hope that it will be useful, but WITHOUT 15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 - * more details. 18 - * 19 - * You should have received a copy of the GNU General Public License along with 20 - * this program. If not, see <http://www.gnu.org/licenses/>. 21 - */ 22 - 23 - #define DSS_SUBSYS_NAME "MANAGER" 24 - 25 - #include <linux/kernel.h> 26 - #include <linux/slab.h> 27 - #include <linux/module.h> 28 - #include <linux/platform_device.h> 29 - #include <linux/jiffies.h> 30 - 31 - #include <video/omapdss.h> 32 - 33 - #include "dss.h" 34 - #include "dss_features.h" 35 - 36 - static int num_managers; 37 - static struct omap_overlay_manager *managers; 38 - 39 - int dss_init_overlay_managers(void) 40 - { 41 - int i; 42 - 43 - num_managers = dss_feat_get_num_mgrs(); 44 - 45 - managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers, 46 - GFP_KERNEL); 47 - 48 - BUG_ON(managers == NULL); 49 - 50 - for (i = 0; i < num_managers; ++i) { 51 - struct omap_overlay_manager *mgr = &managers[i]; 52 - 53 - switch (i) { 54 - case 0: 55 - mgr->name = "lcd"; 56 - mgr->id = OMAP_DSS_CHANNEL_LCD; 57 - break; 58 - case 1: 59 - mgr->name = "tv"; 60 - mgr->id = OMAP_DSS_CHANNEL_DIGIT; 61 - break; 62 - case 2: 63 - mgr->name = "lcd2"; 64 - mgr->id = OMAP_DSS_CHANNEL_LCD2; 65 - break; 66 - case 3: 67 - mgr->name = "lcd3"; 68 - mgr->id = OMAP_DSS_CHANNEL_LCD3; 69 - break; 70 - } 71 - 72 - mgr->caps = 0; 73 - mgr->supported_displays = 74 - dss_feat_get_supported_displays(mgr->id); 75 - mgr->supported_outputs = 76 - dss_feat_get_supported_outputs(mgr->id); 77 - 78 - INIT_LIST_HEAD(&mgr->overlays); 79 - } 80 - 81 - return 0; 82 - } 83 - 84 - int dss_init_overlay_managers_sysfs(struct platform_device *pdev) 85 - { 86 - int i, r; 87 - 88 - for (i = 0; i < num_managers; ++i) { 89 - struct omap_overlay_manager *mgr = &managers[i]; 90 - 91 - r = dss_manager_kobj_init(mgr, pdev); 92 - if (r) 93 - DSSERR("failed to create sysfs file\n"); 94 - } 95 - 96 - return 0; 97 - } 98 - 99 - void dss_uninit_overlay_managers(void) 100 - { 101 - kfree(managers); 102 - managers = NULL; 103 - num_managers = 0; 104 - } 105 - 106 - void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev) 107 - { 108 - int i; 109 - 110 - for (i = 0; i < num_managers; ++i) { 111 - struct omap_overlay_manager *mgr = &managers[i]; 112 - 113 - dss_manager_kobj_uninit(mgr); 114 - } 115 - } 116 - 117 - int omap_dss_get_num_overlay_managers(void) 118 - { 119 - return num_managers; 120 - } 121 - EXPORT_SYMBOL(omap_dss_get_num_overlay_managers); 122 - 123 - struct omap_overlay_manager *omap_dss_get_overlay_manager(int num) 124 - { 125 - if (num >= num_managers) 126 - return NULL; 127 - 128 - return &managers[num]; 129 - } 130 - EXPORT_SYMBOL(omap_dss_get_overlay_manager); 131 - 132 - int dss_mgr_simple_check(struct omap_overlay_manager *mgr, 133 - const struct omap_overlay_manager_info *info) 134 - { 135 - if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) { 136 - /* 137 - * OMAP3 supports only graphics source transparency color key 138 - * and alpha blending simultaneously. See TRM 15.4.2.4.2.2 139 - * Alpha Mode. 140 - */ 141 - if (info->partial_alpha_enabled && info->trans_enabled 142 - && info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) { 143 - DSSERR("check_manager: illegal transparency key\n"); 144 - return -EINVAL; 145 - } 146 - } 147 - 148 - return 0; 149 - } 150 - 151 - static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr, 152 - struct omap_overlay_info **overlay_infos) 153 - { 154 - struct omap_overlay *ovl1, *ovl2; 155 - struct omap_overlay_info *info1, *info2; 156 - 157 - list_for_each_entry(ovl1, &mgr->overlays, list) { 158 - info1 = overlay_infos[ovl1->id]; 159 - 160 - if (info1 == NULL) 161 - continue; 162 - 163 - list_for_each_entry(ovl2, &mgr->overlays, list) { 164 - if (ovl1 == ovl2) 165 - continue; 166 - 167 - info2 = overlay_infos[ovl2->id]; 168 - 169 - if (info2 == NULL) 170 - continue; 171 - 172 - if (info1->zorder == info2->zorder) { 173 - DSSERR("overlays %d and %d have the same " 174 - "zorder %d\n", 175 - ovl1->id, ovl2->id, info1->zorder); 176 - return -EINVAL; 177 - } 178 - } 179 - } 180 - 181 - return 0; 182 - } 183 - 184 - int dss_mgr_check_timings(struct omap_overlay_manager *mgr, 185 - const struct omap_video_timings *timings) 186 - { 187 - if (!dispc_mgr_timings_ok(mgr->id, timings)) { 188 - DSSERR("check_manager: invalid timings\n"); 189 - return -EINVAL; 190 - } 191 - 192 - return 0; 193 - } 194 - 195 - static int dss_mgr_check_lcd_config(struct omap_overlay_manager *mgr, 196 - const struct dss_lcd_mgr_config *config) 197 - { 198 - struct dispc_clock_info cinfo = config->clock_info; 199 - int dl = config->video_port_width; 200 - bool stallmode = config->stallmode; 201 - bool fifohandcheck = config->fifohandcheck; 202 - 203 - if (cinfo.lck_div < 1 || cinfo.lck_div > 255) 204 - return -EINVAL; 205 - 206 - if (cinfo.pck_div < 1 || cinfo.pck_div > 255) 207 - return -EINVAL; 208 - 209 - if (dl != 12 && dl != 16 && dl != 18 && dl != 24) 210 - return -EINVAL; 211 - 212 - /* fifohandcheck should be used only with stallmode */ 213 - if (!stallmode && fifohandcheck) 214 - return -EINVAL; 215 - 216 - /* 217 - * io pad mode can be only checked by using dssdev connected to the 218 - * manager. Ignore checking these for now, add checks when manager 219 - * is capable of holding information related to the connected interface 220 - */ 221 - 222 - return 0; 223 - } 224 - 225 - int dss_mgr_check(struct omap_overlay_manager *mgr, 226 - struct omap_overlay_manager_info *info, 227 - const struct omap_video_timings *mgr_timings, 228 - const struct dss_lcd_mgr_config *lcd_config, 229 - struct omap_overlay_info **overlay_infos) 230 - { 231 - struct omap_overlay *ovl; 232 - int r; 233 - 234 - if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) { 235 - r = dss_mgr_check_zorder(mgr, overlay_infos); 236 - if (r) 237 - return r; 238 - } 239 - 240 - r = dss_mgr_check_timings(mgr, mgr_timings); 241 - if (r) 242 - return r; 243 - 244 - r = dss_mgr_check_lcd_config(mgr, lcd_config); 245 - if (r) 246 - return r; 247 - 248 - list_for_each_entry(ovl, &mgr->overlays, list) { 249 - struct omap_overlay_info *oi; 250 - int r; 251 - 252 - oi = overlay_infos[ovl->id]; 253 - 254 - if (oi == NULL) 255 - continue; 256 - 257 - r = dss_ovl_check(ovl, oi, mgr_timings); 258 - if (r) 259 - return r; 260 - } 261 - 262 - return 0; 263 - }
-456
drivers/gpu/drm/omapdrm/dss/overlay-sysfs.c
··· 1 - /* 2 - * Copyright (C) 2009 Nokia Corporation 3 - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 4 - * 5 - * Some code and ideas taken from drivers/video/omap/ driver 6 - * by Imre Deak. 7 - * 8 - * This program is free software; you can redistribute it and/or modify it 9 - * under the terms of the GNU General Public License version 2 as published by 10 - * the Free Software Foundation. 11 - * 12 - * This program is distributed in the hope that it will be useful, but WITHOUT 13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 - * more details. 16 - * 17 - * You should have received a copy of the GNU General Public License along with 18 - * this program. If not, see <http://www.gnu.org/licenses/>. 19 - */ 20 - 21 - #define DSS_SUBSYS_NAME "OVERLAY" 22 - 23 - #include <linux/module.h> 24 - #include <linux/err.h> 25 - #include <linux/sysfs.h> 26 - #include <linux/kobject.h> 27 - #include <linux/platform_device.h> 28 - 29 - #include <video/omapdss.h> 30 - 31 - #include "dss.h" 32 - #include "dss_features.h" 33 - 34 - static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) 35 - { 36 - return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); 37 - } 38 - 39 - static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf) 40 - { 41 - return snprintf(buf, PAGE_SIZE, "%s\n", 42 - ovl->manager ? ovl->manager->name : "<none>"); 43 - } 44 - 45 - static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, 46 - size_t size) 47 - { 48 - int i, r; 49 - struct omap_overlay_manager *mgr = NULL; 50 - struct omap_overlay_manager *old_mgr; 51 - int len = size; 52 - 53 - if (buf[size-1] == '\n') 54 - --len; 55 - 56 - if (len > 0) { 57 - for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 58 - mgr = omap_dss_get_overlay_manager(i); 59 - 60 - if (sysfs_streq(buf, mgr->name)) 61 - break; 62 - 63 - mgr = NULL; 64 - } 65 - } 66 - 67 - if (len > 0 && mgr == NULL) 68 - return -EINVAL; 69 - 70 - if (mgr) 71 - DSSDBG("manager %s found\n", mgr->name); 72 - 73 - if (mgr == ovl->manager) 74 - return size; 75 - 76 - old_mgr = ovl->manager; 77 - 78 - r = dispc_runtime_get(); 79 - if (r) 80 - return r; 81 - 82 - /* detach old manager */ 83 - if (old_mgr) { 84 - r = ovl->unset_manager(ovl); 85 - if (r) { 86 - DSSERR("detach failed\n"); 87 - goto err; 88 - } 89 - 90 - r = old_mgr->apply(old_mgr); 91 - if (r) 92 - goto err; 93 - } 94 - 95 - if (mgr) { 96 - r = ovl->set_manager(ovl, mgr); 97 - if (r) { 98 - DSSERR("Failed to attach overlay\n"); 99 - goto err; 100 - } 101 - 102 - r = mgr->apply(mgr); 103 - if (r) 104 - goto err; 105 - } 106 - 107 - dispc_runtime_put(); 108 - 109 - return size; 110 - 111 - err: 112 - dispc_runtime_put(); 113 - return r; 114 - } 115 - 116 - static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) 117 - { 118 - struct omap_overlay_info info; 119 - 120 - ovl->get_overlay_info(ovl, &info); 121 - 122 - return snprintf(buf, PAGE_SIZE, "%d,%d\n", 123 - info.width, info.height); 124 - } 125 - 126 - static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf) 127 - { 128 - struct omap_overlay_info info; 129 - 130 - ovl->get_overlay_info(ovl, &info); 131 - 132 - return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width); 133 - } 134 - 135 - static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf) 136 - { 137 - struct omap_overlay_info info; 138 - 139 - ovl->get_overlay_info(ovl, &info); 140 - 141 - return snprintf(buf, PAGE_SIZE, "%d,%d\n", 142 - info.pos_x, info.pos_y); 143 - } 144 - 145 - static ssize_t overlay_position_store(struct omap_overlay *ovl, 146 - const char *buf, size_t size) 147 - { 148 - int r; 149 - char *last; 150 - struct omap_overlay_info info; 151 - 152 - ovl->get_overlay_info(ovl, &info); 153 - 154 - info.pos_x = simple_strtoul(buf, &last, 10); 155 - ++last; 156 - if (last - buf >= size) 157 - return -EINVAL; 158 - 159 - info.pos_y = simple_strtoul(last, &last, 10); 160 - 161 - r = ovl->set_overlay_info(ovl, &info); 162 - if (r) 163 - return r; 164 - 165 - if (ovl->manager) { 166 - r = ovl->manager->apply(ovl->manager); 167 - if (r) 168 - return r; 169 - } 170 - 171 - return size; 172 - } 173 - 174 - static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf) 175 - { 176 - struct omap_overlay_info info; 177 - 178 - ovl->get_overlay_info(ovl, &info); 179 - 180 - return snprintf(buf, PAGE_SIZE, "%d,%d\n", 181 - info.out_width, info.out_height); 182 - } 183 - 184 - static ssize_t overlay_output_size_store(struct omap_overlay *ovl, 185 - const char *buf, size_t size) 186 - { 187 - int r; 188 - char *last; 189 - struct omap_overlay_info info; 190 - 191 - ovl->get_overlay_info(ovl, &info); 192 - 193 - info.out_width = simple_strtoul(buf, &last, 10); 194 - ++last; 195 - if (last - buf >= size) 196 - return -EINVAL; 197 - 198 - info.out_height = simple_strtoul(last, &last, 10); 199 - 200 - r = ovl->set_overlay_info(ovl, &info); 201 - if (r) 202 - return r; 203 - 204 - if (ovl->manager) { 205 - r = ovl->manager->apply(ovl->manager); 206 - if (r) 207 - return r; 208 - } 209 - 210 - return size; 211 - } 212 - 213 - static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) 214 - { 215 - return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl)); 216 - } 217 - 218 - static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, 219 - size_t size) 220 - { 221 - int r; 222 - bool enable; 223 - 224 - r = strtobool(buf, &enable); 225 - if (r) 226 - return r; 227 - 228 - if (enable) 229 - r = ovl->enable(ovl); 230 - else 231 - r = ovl->disable(ovl); 232 - 233 - if (r) 234 - return r; 235 - 236 - return size; 237 - } 238 - 239 - static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) 240 - { 241 - struct omap_overlay_info info; 242 - 243 - ovl->get_overlay_info(ovl, &info); 244 - 245 - return snprintf(buf, PAGE_SIZE, "%d\n", 246 - info.global_alpha); 247 - } 248 - 249 - static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, 250 - const char *buf, size_t size) 251 - { 252 - int r; 253 - u8 alpha; 254 - struct omap_overlay_info info; 255 - 256 - if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) 257 - return -ENODEV; 258 - 259 - r = kstrtou8(buf, 0, &alpha); 260 - if (r) 261 - return r; 262 - 263 - ovl->get_overlay_info(ovl, &info); 264 - 265 - info.global_alpha = alpha; 266 - 267 - r = ovl->set_overlay_info(ovl, &info); 268 - if (r) 269 - return r; 270 - 271 - if (ovl->manager) { 272 - r = ovl->manager->apply(ovl->manager); 273 - if (r) 274 - return r; 275 - } 276 - 277 - return size; 278 - } 279 - 280 - static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl, 281 - char *buf) 282 - { 283 - struct omap_overlay_info info; 284 - 285 - ovl->get_overlay_info(ovl, &info); 286 - 287 - return snprintf(buf, PAGE_SIZE, "%d\n", 288 - info.pre_mult_alpha); 289 - } 290 - 291 - static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, 292 - const char *buf, size_t size) 293 - { 294 - int r; 295 - u8 alpha; 296 - struct omap_overlay_info info; 297 - 298 - if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) 299 - return -ENODEV; 300 - 301 - r = kstrtou8(buf, 0, &alpha); 302 - if (r) 303 - return r; 304 - 305 - ovl->get_overlay_info(ovl, &info); 306 - 307 - info.pre_mult_alpha = alpha; 308 - 309 - r = ovl->set_overlay_info(ovl, &info); 310 - if (r) 311 - return r; 312 - 313 - if (ovl->manager) { 314 - r = ovl->manager->apply(ovl->manager); 315 - if (r) 316 - return r; 317 - } 318 - 319 - return size; 320 - } 321 - 322 - static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf) 323 - { 324 - struct omap_overlay_info info; 325 - 326 - ovl->get_overlay_info(ovl, &info); 327 - 328 - return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder); 329 - } 330 - 331 - static ssize_t overlay_zorder_store(struct omap_overlay *ovl, 332 - const char *buf, size_t size) 333 - { 334 - int r; 335 - u8 zorder; 336 - struct omap_overlay_info info; 337 - 338 - if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) 339 - return -ENODEV; 340 - 341 - r = kstrtou8(buf, 0, &zorder); 342 - if (r) 343 - return r; 344 - 345 - ovl->get_overlay_info(ovl, &info); 346 - 347 - info.zorder = zorder; 348 - 349 - r = ovl->set_overlay_info(ovl, &info); 350 - if (r) 351 - return r; 352 - 353 - if (ovl->manager) { 354 - r = ovl->manager->apply(ovl->manager); 355 - if (r) 356 - return r; 357 - } 358 - 359 - return size; 360 - } 361 - 362 - struct overlay_attribute { 363 - struct attribute attr; 364 - ssize_t (*show)(struct omap_overlay *, char *); 365 - ssize_t (*store)(struct omap_overlay *, const char *, size_t); 366 - }; 367 - 368 - #define OVERLAY_ATTR(_name, _mode, _show, _store) \ 369 - struct overlay_attribute overlay_attr_##_name = \ 370 - __ATTR(_name, _mode, _show, _store) 371 - 372 - static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); 373 - static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, 374 - overlay_manager_show, overlay_manager_store); 375 - static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); 376 - static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); 377 - static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, 378 - overlay_position_show, overlay_position_store); 379 - static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, 380 - overlay_output_size_show, overlay_output_size_store); 381 - static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, 382 - overlay_enabled_show, overlay_enabled_store); 383 - static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, 384 - overlay_global_alpha_show, overlay_global_alpha_store); 385 - static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, 386 - overlay_pre_mult_alpha_show, 387 - overlay_pre_mult_alpha_store); 388 - static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR, 389 - overlay_zorder_show, overlay_zorder_store); 390 - 391 - static struct attribute *overlay_sysfs_attrs[] = { 392 - &overlay_attr_name.attr, 393 - &overlay_attr_manager.attr, 394 - &overlay_attr_input_size.attr, 395 - &overlay_attr_screen_width.attr, 396 - &overlay_attr_position.attr, 397 - &overlay_attr_output_size.attr, 398 - &overlay_attr_enabled.attr, 399 - &overlay_attr_global_alpha.attr, 400 - &overlay_attr_pre_mult_alpha.attr, 401 - &overlay_attr_zorder.attr, 402 - NULL 403 - }; 404 - 405 - static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, 406 - char *buf) 407 - { 408 - struct omap_overlay *overlay; 409 - struct overlay_attribute *overlay_attr; 410 - 411 - overlay = container_of(kobj, struct omap_overlay, kobj); 412 - overlay_attr = container_of(attr, struct overlay_attribute, attr); 413 - 414 - if (!overlay_attr->show) 415 - return -ENOENT; 416 - 417 - return overlay_attr->show(overlay, buf); 418 - } 419 - 420 - static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, 421 - const char *buf, size_t size) 422 - { 423 - struct omap_overlay *overlay; 424 - struct overlay_attribute *overlay_attr; 425 - 426 - overlay = container_of(kobj, struct omap_overlay, kobj); 427 - overlay_attr = container_of(attr, struct overlay_attribute, attr); 428 - 429 - if (!overlay_attr->store) 430 - return -ENOENT; 431 - 432 - return overlay_attr->store(overlay, buf, size); 433 - } 434 - 435 - static const struct sysfs_ops overlay_sysfs_ops = { 436 - .show = overlay_attr_show, 437 - .store = overlay_attr_store, 438 - }; 439 - 440 - static struct kobj_type overlay_ktype = { 441 - .sysfs_ops = &overlay_sysfs_ops, 442 - .default_attrs = overlay_sysfs_attrs, 443 - }; 444 - 445 - int dss_overlay_kobj_init(struct omap_overlay *ovl, 446 - struct platform_device *pdev) 447 - { 448 - return kobject_init_and_add(&ovl->kobj, &overlay_ktype, 449 - &pdev->dev.kobj, "overlay%d", ovl->id); 450 - } 451 - 452 - void dss_overlay_kobj_uninit(struct omap_overlay *ovl) 453 - { 454 - kobject_del(&ovl->kobj); 455 - kobject_put(&ovl->kobj); 456 - }
-202
drivers/gpu/drm/omapdrm/dss/overlay.c
··· 1 - /* 2 - * linux/drivers/video/omap2/dss/overlay.c 3 - * 4 - * Copyright (C) 2009 Nokia Corporation 5 - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 6 - * 7 - * Some code and ideas taken from drivers/video/omap/ driver 8 - * by Imre Deak. 9 - * 10 - * This program is free software; you can redistribute it and/or modify it 11 - * under the terms of the GNU General Public License version 2 as published by 12 - * the Free Software Foundation. 13 - * 14 - * This program is distributed in the hope that it will be useful, but WITHOUT 15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 - * more details. 18 - * 19 - * You should have received a copy of the GNU General Public License along with 20 - * this program. If not, see <http://www.gnu.org/licenses/>. 21 - */ 22 - 23 - #define DSS_SUBSYS_NAME "OVERLAY" 24 - 25 - #include <linux/kernel.h> 26 - #include <linux/module.h> 27 - #include <linux/err.h> 28 - #include <linux/sysfs.h> 29 - #include <linux/platform_device.h> 30 - #include <linux/delay.h> 31 - #include <linux/slab.h> 32 - 33 - #include <video/omapdss.h> 34 - 35 - #include "dss.h" 36 - #include "dss_features.h" 37 - 38 - static int num_overlays; 39 - static struct omap_overlay *overlays; 40 - 41 - int omap_dss_get_num_overlays(void) 42 - { 43 - return num_overlays; 44 - } 45 - EXPORT_SYMBOL(omap_dss_get_num_overlays); 46 - 47 - struct omap_overlay *omap_dss_get_overlay(int num) 48 - { 49 - if (num >= num_overlays) 50 - return NULL; 51 - 52 - return &overlays[num]; 53 - } 54 - EXPORT_SYMBOL(omap_dss_get_overlay); 55 - 56 - void dss_init_overlays(struct platform_device *pdev) 57 - { 58 - int i, r; 59 - 60 - num_overlays = dss_feat_get_num_ovls(); 61 - 62 - overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays, 63 - GFP_KERNEL); 64 - 65 - BUG_ON(overlays == NULL); 66 - 67 - for (i = 0; i < num_overlays; ++i) { 68 - struct omap_overlay *ovl = &overlays[i]; 69 - 70 - switch (i) { 71 - case 0: 72 - ovl->name = "gfx"; 73 - ovl->id = OMAP_DSS_GFX; 74 - break; 75 - case 1: 76 - ovl->name = "vid1"; 77 - ovl->id = OMAP_DSS_VIDEO1; 78 - break; 79 - case 2: 80 - ovl->name = "vid2"; 81 - ovl->id = OMAP_DSS_VIDEO2; 82 - break; 83 - case 3: 84 - ovl->name = "vid3"; 85 - ovl->id = OMAP_DSS_VIDEO3; 86 - break; 87 - } 88 - 89 - ovl->caps = dss_feat_get_overlay_caps(ovl->id); 90 - ovl->supported_modes = 91 - dss_feat_get_supported_color_modes(ovl->id); 92 - 93 - r = dss_overlay_kobj_init(ovl, pdev); 94 - if (r) 95 - DSSERR("failed to create sysfs file\n"); 96 - } 97 - } 98 - 99 - void dss_uninit_overlays(struct platform_device *pdev) 100 - { 101 - int i; 102 - 103 - for (i = 0; i < num_overlays; ++i) { 104 - struct omap_overlay *ovl = &overlays[i]; 105 - dss_overlay_kobj_uninit(ovl); 106 - } 107 - 108 - kfree(overlays); 109 - overlays = NULL; 110 - num_overlays = 0; 111 - } 112 - 113 - int dss_ovl_simple_check(struct omap_overlay *ovl, 114 - const struct omap_overlay_info *info) 115 - { 116 - if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { 117 - if (info->out_width != 0 && info->width != info->out_width) { 118 - DSSERR("check_overlay: overlay %d doesn't support " 119 - "scaling\n", ovl->id); 120 - return -EINVAL; 121 - } 122 - 123 - if (info->out_height != 0 && info->height != info->out_height) { 124 - DSSERR("check_overlay: overlay %d doesn't support " 125 - "scaling\n", ovl->id); 126 - return -EINVAL; 127 - } 128 - } 129 - 130 - if ((ovl->supported_modes & info->color_mode) == 0) { 131 - DSSERR("check_overlay: overlay %d doesn't support mode %d\n", 132 - ovl->id, info->color_mode); 133 - return -EINVAL; 134 - } 135 - 136 - if (info->zorder >= omap_dss_get_num_overlays()) { 137 - DSSERR("check_overlay: zorder %d too high\n", info->zorder); 138 - return -EINVAL; 139 - } 140 - 141 - if (dss_feat_rotation_type_supported(info->rotation_type) == 0) { 142 - DSSERR("check_overlay: rotation type %d not supported\n", 143 - info->rotation_type); 144 - return -EINVAL; 145 - } 146 - 147 - return 0; 148 - } 149 - 150 - int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, 151 - const struct omap_video_timings *mgr_timings) 152 - { 153 - u16 outw, outh; 154 - u16 dw, dh; 155 - 156 - dw = mgr_timings->x_res; 157 - dh = mgr_timings->y_res; 158 - 159 - if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { 160 - outw = info->width; 161 - outh = info->height; 162 - } else { 163 - if (info->out_width == 0) 164 - outw = info->width; 165 - else 166 - outw = info->out_width; 167 - 168 - if (info->out_height == 0) 169 - outh = info->height; 170 - else 171 - outh = info->out_height; 172 - } 173 - 174 - if (dw < info->pos_x + outw) { 175 - DSSERR("overlay %d horizontally not inside the display area " 176 - "(%d + %d >= %d)\n", 177 - ovl->id, info->pos_x, outw, dw); 178 - return -EINVAL; 179 - } 180 - 181 - if (dh < info->pos_y + outh) { 182 - DSSERR("overlay %d vertically not inside the display area " 183 - "(%d + %d >= %d)\n", 184 - ovl->id, info->pos_y, outh, dh); 185 - return -EINVAL; 186 - } 187 - 188 - return 0; 189 - } 190 - 191 - /* 192 - * Checks if replication logic should be used. Only use when overlay is in 193 - * RGB12U or RGB16 mode, and video port width interface is 18bpp or 24bpp 194 - */ 195 - bool dss_ovl_use_replication(struct dss_lcd_mgr_config config, 196 - enum omap_color_mode mode) 197 - { 198 - if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16) 199 - return false; 200 - 201 - return config.video_port_width > 16; 202 - }