| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2014 Traphandler |
|---|
| 3 | 4 | * Copyright (C) 2014 Free Electrons |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Author: Jean-Jacques Hiblot <jjhiblot@traphandler.com> |
|---|
| 7 | 8 | * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 10 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 11 | | - * the Free Software Foundation. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 14 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 15 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 16 | | - * more details. |
|---|
| 17 | | - * |
|---|
| 18 | | - * You should have received a copy of the GNU General Public License along with |
|---|
| 19 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 20 | 9 | */ |
|---|
| 21 | 10 | |
|---|
| 22 | 11 | #include <linux/clk.h> |
|---|
| 23 | 12 | #include <linux/irq.h> |
|---|
| 24 | 13 | #include <linux/irqchip.h> |
|---|
| 14 | +#include <linux/mfd/atmel-hlcdc.h> |
|---|
| 25 | 15 | #include <linux/module.h> |
|---|
| 26 | 16 | #include <linux/pm_runtime.h> |
|---|
| 17 | +#include <linux/platform_device.h> |
|---|
| 18 | + |
|---|
| 19 | +#include <drm/drm_atomic.h> |
|---|
| 20 | +#include <drm/drm_atomic_helper.h> |
|---|
| 21 | +#include <drm/drm_drv.h> |
|---|
| 22 | +#include <drm/drm_fb_helper.h> |
|---|
| 23 | +#include <drm/drm_gem_cma_helper.h> |
|---|
| 24 | +#include <drm/drm_gem_framebuffer_helper.h> |
|---|
| 25 | +#include <drm/drm_irq.h> |
|---|
| 26 | +#include <drm/drm_probe_helper.h> |
|---|
| 27 | +#include <drm/drm_vblank.h> |
|---|
| 27 | 28 | |
|---|
| 28 | 29 | #include "atmel_hlcdc_dc.h" |
|---|
| 29 | 30 | |
|---|
| .. | .. |
|---|
| 364 | 365 | .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers), |
|---|
| 365 | 366 | .layers = atmel_hlcdc_sama5d4_layers, |
|---|
| 366 | 367 | }; |
|---|
| 368 | + |
|---|
| 369 | +static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = { |
|---|
| 370 | + { |
|---|
| 371 | + .name = "base", |
|---|
| 372 | + .formats = &atmel_hlcdc_plane_rgb_formats, |
|---|
| 373 | + .regs_offset = 0x60, |
|---|
| 374 | + .id = 0, |
|---|
| 375 | + .type = ATMEL_HLCDC_BASE_LAYER, |
|---|
| 376 | + .cfgs_offset = 0x2c, |
|---|
| 377 | + .layout = { |
|---|
| 378 | + .xstride = { 2 }, |
|---|
| 379 | + .default_color = 3, |
|---|
| 380 | + .general_config = 4, |
|---|
| 381 | + .disc_pos = 5, |
|---|
| 382 | + .disc_size = 6, |
|---|
| 383 | + }, |
|---|
| 384 | + .clut_offset = 0x600, |
|---|
| 385 | + }, |
|---|
| 386 | + { |
|---|
| 387 | + .name = "overlay1", |
|---|
| 388 | + .formats = &atmel_hlcdc_plane_rgb_formats, |
|---|
| 389 | + .regs_offset = 0x160, |
|---|
| 390 | + .id = 1, |
|---|
| 391 | + .type = ATMEL_HLCDC_OVERLAY_LAYER, |
|---|
| 392 | + .cfgs_offset = 0x2c, |
|---|
| 393 | + .layout = { |
|---|
| 394 | + .pos = 2, |
|---|
| 395 | + .size = 3, |
|---|
| 396 | + .xstride = { 4 }, |
|---|
| 397 | + .pstride = { 5 }, |
|---|
| 398 | + .default_color = 6, |
|---|
| 399 | + .chroma_key = 7, |
|---|
| 400 | + .chroma_key_mask = 8, |
|---|
| 401 | + .general_config = 9, |
|---|
| 402 | + }, |
|---|
| 403 | + .clut_offset = 0xa00, |
|---|
| 404 | + }, |
|---|
| 405 | + { |
|---|
| 406 | + .name = "overlay2", |
|---|
| 407 | + .formats = &atmel_hlcdc_plane_rgb_formats, |
|---|
| 408 | + .regs_offset = 0x260, |
|---|
| 409 | + .id = 2, |
|---|
| 410 | + .type = ATMEL_HLCDC_OVERLAY_LAYER, |
|---|
| 411 | + .cfgs_offset = 0x2c, |
|---|
| 412 | + .layout = { |
|---|
| 413 | + .pos = 2, |
|---|
| 414 | + .size = 3, |
|---|
| 415 | + .xstride = { 4 }, |
|---|
| 416 | + .pstride = { 5 }, |
|---|
| 417 | + .default_color = 6, |
|---|
| 418 | + .chroma_key = 7, |
|---|
| 419 | + .chroma_key_mask = 8, |
|---|
| 420 | + .general_config = 9, |
|---|
| 421 | + }, |
|---|
| 422 | + .clut_offset = 0xe00, |
|---|
| 423 | + }, |
|---|
| 424 | + { |
|---|
| 425 | + .name = "high-end-overlay", |
|---|
| 426 | + .formats = &atmel_hlcdc_plane_rgb_and_yuv_formats, |
|---|
| 427 | + .regs_offset = 0x360, |
|---|
| 428 | + .id = 3, |
|---|
| 429 | + .type = ATMEL_HLCDC_OVERLAY_LAYER, |
|---|
| 430 | + .cfgs_offset = 0x4c, |
|---|
| 431 | + .layout = { |
|---|
| 432 | + .pos = 2, |
|---|
| 433 | + .size = 3, |
|---|
| 434 | + .memsize = 4, |
|---|
| 435 | + .xstride = { 5, 7 }, |
|---|
| 436 | + .pstride = { 6, 8 }, |
|---|
| 437 | + .default_color = 9, |
|---|
| 438 | + .chroma_key = 10, |
|---|
| 439 | + .chroma_key_mask = 11, |
|---|
| 440 | + .general_config = 12, |
|---|
| 441 | + .scaler_config = 13, |
|---|
| 442 | + .phicoeffs = { |
|---|
| 443 | + .x = 17, |
|---|
| 444 | + .y = 33, |
|---|
| 445 | + }, |
|---|
| 446 | + .csc = 14, |
|---|
| 447 | + }, |
|---|
| 448 | + .clut_offset = 0x1200, |
|---|
| 449 | + }, |
|---|
| 450 | +}; |
|---|
| 451 | + |
|---|
| 452 | +static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sam9x60 = { |
|---|
| 453 | + .min_width = 0, |
|---|
| 454 | + .min_height = 0, |
|---|
| 455 | + .max_width = 2048, |
|---|
| 456 | + .max_height = 2048, |
|---|
| 457 | + .max_spw = 0xff, |
|---|
| 458 | + .max_vpw = 0xff, |
|---|
| 459 | + .max_hpw = 0x3ff, |
|---|
| 460 | + .fixed_clksrc = true, |
|---|
| 461 | + .nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers), |
|---|
| 462 | + .layers = atmel_hlcdc_sam9x60_layers, |
|---|
| 463 | +}; |
|---|
| 464 | + |
|---|
| 367 | 465 | static const struct of_device_id atmel_hlcdc_of_match[] = { |
|---|
| 368 | 466 | { |
|---|
| 369 | 467 | .compatible = "atmel,at91sam9n12-hlcdc", |
|---|
| .. | .. |
|---|
| 384 | 482 | { |
|---|
| 385 | 483 | .compatible = "atmel,sama5d4-hlcdc", |
|---|
| 386 | 484 | .data = &atmel_hlcdc_dc_sama5d4, |
|---|
| 485 | + }, |
|---|
| 486 | + { |
|---|
| 487 | + .compatible = "microchip,sam9x60-hlcdc", |
|---|
| 488 | + .data = &atmel_hlcdc_dc_sam9x60, |
|---|
| 387 | 489 | }, |
|---|
| 388 | 490 | { /* sentinel */ }, |
|---|
| 389 | 491 | }; |
|---|
| .. | .. |
|---|
| 453 | 555 | } |
|---|
| 454 | 556 | |
|---|
| 455 | 557 | return IRQ_HANDLED; |
|---|
| 456 | | -} |
|---|
| 457 | | - |
|---|
| 458 | | -static struct drm_framebuffer *atmel_hlcdc_fb_create(struct drm_device *dev, |
|---|
| 459 | | - struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) |
|---|
| 460 | | -{ |
|---|
| 461 | | - return drm_gem_fb_create(dev, file_priv, mode_cmd); |
|---|
| 462 | 558 | } |
|---|
| 463 | 559 | |
|---|
| 464 | 560 | struct atmel_hlcdc_dc_commit { |
|---|
| .. | .. |
|---|
| 555 | 651 | } |
|---|
| 556 | 652 | |
|---|
| 557 | 653 | static const struct drm_mode_config_funcs mode_config_funcs = { |
|---|
| 558 | | - .fb_create = atmel_hlcdc_fb_create, |
|---|
| 559 | | - .output_poll_changed = drm_fb_helper_output_poll_changed, |
|---|
| 654 | + .fb_create = drm_gem_fb_create, |
|---|
| 560 | 655 | .atomic_check = drm_atomic_helper_check, |
|---|
| 561 | 656 | .atomic_commit = atmel_hlcdc_dc_atomic_commit, |
|---|
| 562 | 657 | }; |
|---|
| .. | .. |
|---|
| 658 | 753 | |
|---|
| 659 | 754 | platform_set_drvdata(pdev, dev); |
|---|
| 660 | 755 | |
|---|
| 661 | | - drm_fb_cma_fbdev_init(dev, 24, 0); |
|---|
| 662 | | - |
|---|
| 663 | 756 | drm_kms_helper_poll_init(dev); |
|---|
| 664 | 757 | |
|---|
| 665 | 758 | return 0; |
|---|
| .. | .. |
|---|
| 678 | 771 | { |
|---|
| 679 | 772 | struct atmel_hlcdc_dc *dc = dev->dev_private; |
|---|
| 680 | 773 | |
|---|
| 681 | | - drm_fb_cma_fbdev_fini(dev); |
|---|
| 682 | 774 | flush_workqueue(dc->wq); |
|---|
| 683 | 775 | drm_kms_helper_poll_fini(dev); |
|---|
| 684 | 776 | drm_atomic_helper_shutdown(dev); |
|---|
| .. | .. |
|---|
| 724 | 816 | DEFINE_DRM_GEM_CMA_FOPS(fops); |
|---|
| 725 | 817 | |
|---|
| 726 | 818 | static struct drm_driver atmel_hlcdc_dc_driver = { |
|---|
| 727 | | - .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | |
|---|
| 728 | | - DRIVER_MODESET | DRIVER_PRIME | |
|---|
| 729 | | - DRIVER_ATOMIC, |
|---|
| 730 | | - .lastclose = drm_fb_helper_lastclose, |
|---|
| 819 | + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, |
|---|
| 731 | 820 | .irq_handler = atmel_hlcdc_dc_irq_handler, |
|---|
| 732 | 821 | .irq_preinstall = atmel_hlcdc_dc_irq_uninstall, |
|---|
| 733 | 822 | .irq_postinstall = atmel_hlcdc_dc_irq_postinstall, |
|---|
| 734 | 823 | .irq_uninstall = atmel_hlcdc_dc_irq_uninstall, |
|---|
| 735 | | - .gem_free_object_unlocked = drm_gem_cma_free_object, |
|---|
| 736 | | - .gem_vm_ops = &drm_gem_cma_vm_ops, |
|---|
| 737 | | - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, |
|---|
| 738 | | - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, |
|---|
| 739 | | - .gem_prime_import = drm_gem_prime_import, |
|---|
| 740 | | - .gem_prime_export = drm_gem_prime_export, |
|---|
| 741 | | - .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, |
|---|
| 742 | | - .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, |
|---|
| 743 | | - .gem_prime_vmap = drm_gem_cma_prime_vmap, |
|---|
| 744 | | - .gem_prime_vunmap = drm_gem_cma_prime_vunmap, |
|---|
| 745 | | - .gem_prime_mmap = drm_gem_cma_prime_mmap, |
|---|
| 746 | | - .dumb_create = drm_gem_cma_dumb_create, |
|---|
| 824 | + DRM_GEM_CMA_DRIVER_OPS, |
|---|
| 747 | 825 | .fops = &fops, |
|---|
| 748 | 826 | .name = "atmel-hlcdc", |
|---|
| 749 | 827 | .desc = "Atmel HLCD Controller DRM", |
|---|
| .. | .. |
|---|
| 763 | 841 | |
|---|
| 764 | 842 | ret = atmel_hlcdc_dc_load(ddev); |
|---|
| 765 | 843 | if (ret) |
|---|
| 766 | | - goto err_unref; |
|---|
| 844 | + goto err_put; |
|---|
| 767 | 845 | |
|---|
| 768 | 846 | ret = drm_dev_register(ddev, 0); |
|---|
| 769 | 847 | if (ret) |
|---|
| 770 | 848 | goto err_unload; |
|---|
| 849 | + |
|---|
| 850 | + drm_fbdev_generic_setup(ddev, 24); |
|---|
| 771 | 851 | |
|---|
| 772 | 852 | return 0; |
|---|
| 773 | 853 | |
|---|
| 774 | 854 | err_unload: |
|---|
| 775 | 855 | atmel_hlcdc_dc_unload(ddev); |
|---|
| 776 | 856 | |
|---|
| 777 | | -err_unref: |
|---|
| 778 | | - drm_dev_unref(ddev); |
|---|
| 857 | +err_put: |
|---|
| 858 | + drm_dev_put(ddev); |
|---|
| 779 | 859 | |
|---|
| 780 | 860 | return ret; |
|---|
| 781 | 861 | } |
|---|
| .. | .. |
|---|
| 786 | 866 | |
|---|
| 787 | 867 | drm_dev_unregister(ddev); |
|---|
| 788 | 868 | atmel_hlcdc_dc_unload(ddev); |
|---|
| 789 | | - drm_dev_unref(ddev); |
|---|
| 869 | + drm_dev_put(ddev); |
|---|
| 790 | 870 | |
|---|
| 791 | 871 | return 0; |
|---|
| 792 | 872 | } |
|---|