diff options
author | Chanho Park <chanho61.park@samsung.com> | 2013-08-13 01:12:56 -0400 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2013-09-05 00:43:42 -0400 |
commit | 319477f35eef46e3c1eeb155f17c5fb06ef85704 (patch) | |
tree | 0255d4015c206710e8802d04a106e9dd09e62fbe | |
parent | e30655d06179aa91c0c4caa2b7a6c55f8f81a731 (diff) |
drm/exynos: add device tree support for rotator
The exynos4 platform is only dt-based since 3.10, we should convert driver data
and ids to dt-based parsing methods. The rotator driver has a limit table to get
size limit of input picture. Each SoCs has slightly different limit value
compared with any others.
For example, exynos4210's max_size of RGB888 is 16k x 16k. But, others have
8k x 8k. Another example the exynos5250 should have multiple of 2 pixel size
for its X/Y axis. Thus, we should keep different tables for each of them.
This patch also includes desciptions of each nodes for the rotator and specifies
a example how to bind it.
Signed-off-by: Chanho Park <chanho61.park@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r-- | Documentation/devicetree/bindings/gpu/samsung-rotator.txt | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_rotator.c | 108 |
2 files changed, 107 insertions, 28 deletions
diff --git a/Documentation/devicetree/bindings/gpu/samsung-rotator.txt b/Documentation/devicetree/bindings/gpu/samsung-rotator.txt new file mode 100644 index 000000000000..82cd1ed0be93 --- /dev/null +++ b/Documentation/devicetree/bindings/gpu/samsung-rotator.txt | |||
@@ -0,0 +1,27 @@ | |||
1 | * Samsung Image Rotator | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : value should be one of the following: | ||
5 | (a) "samsung,exynos4210-rotator" for Rotator IP in Exynos4210 | ||
6 | (b) "samsung,exynos4212-rotator" for Rotator IP in Exynos4212/4412 | ||
7 | (c) "samsung,exynos5250-rotator" for Rotator IP in Exynos5250 | ||
8 | |||
9 | - reg : Physical base address of the IP registers and length of memory | ||
10 | mapped region. | ||
11 | |||
12 | - interrupts : Interrupt specifier for rotator interrupt, according to format | ||
13 | specific to interrupt parent. | ||
14 | |||
15 | - clocks : Clock specifier for rotator clock, according to generic clock | ||
16 | bindings. (See Documentation/devicetree/bindings/clock/exynos*.txt) | ||
17 | |||
18 | - clock-names : Names of clocks. For exynos rotator, it should be "rotator". | ||
19 | |||
20 | Example: | ||
21 | rotator@12810000 { | ||
22 | compatible = "samsung,exynos4210-rotator"; | ||
23 | reg = <0x12810000 0x1000>; | ||
24 | interrupts = <0 83 0>; | ||
25 | clocks = <&clock 278>; | ||
26 | clock-names = "rotator"; | ||
27 | }; | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index 54b7360bad30..a77cd5bb104c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c | |||
@@ -632,21 +632,98 @@ static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) | |||
632 | return 0; | 632 | return 0; |
633 | } | 633 | } |
634 | 634 | ||
635 | static struct rot_limit_table rot_limit_tbl_4210 = { | ||
636 | .ycbcr420_2p = { | ||
637 | .min_w = 32, | ||
638 | .min_h = 32, | ||
639 | .max_w = SZ_64K, | ||
640 | .max_h = SZ_64K, | ||
641 | .align = 3, | ||
642 | }, | ||
643 | .rgb888 = { | ||
644 | .min_w = 8, | ||
645 | .min_h = 8, | ||
646 | .max_w = SZ_16K, | ||
647 | .max_h = SZ_16K, | ||
648 | .align = 2, | ||
649 | }, | ||
650 | }; | ||
651 | |||
652 | static struct rot_limit_table rot_limit_tbl_4x12 = { | ||
653 | .ycbcr420_2p = { | ||
654 | .min_w = 32, | ||
655 | .min_h = 32, | ||
656 | .max_w = SZ_32K, | ||
657 | .max_h = SZ_32K, | ||
658 | .align = 3, | ||
659 | }, | ||
660 | .rgb888 = { | ||
661 | .min_w = 8, | ||
662 | .min_h = 8, | ||
663 | .max_w = SZ_8K, | ||
664 | .max_h = SZ_8K, | ||
665 | .align = 2, | ||
666 | }, | ||
667 | }; | ||
668 | |||
669 | static struct rot_limit_table rot_limit_tbl_5250 = { | ||
670 | .ycbcr420_2p = { | ||
671 | .min_w = 32, | ||
672 | .min_h = 32, | ||
673 | .max_w = SZ_32K, | ||
674 | .max_h = SZ_32K, | ||
675 | .align = 3, | ||
676 | }, | ||
677 | .rgb888 = { | ||
678 | .min_w = 8, | ||
679 | .min_h = 8, | ||
680 | .max_w = SZ_8K, | ||
681 | .max_h = SZ_8K, | ||
682 | .align = 1, | ||
683 | }, | ||
684 | }; | ||
685 | |||
686 | static const struct of_device_id exynos_rotator_match[] = { | ||
687 | { | ||
688 | .compatible = "samsung,exynos4210-rotator", | ||
689 | .data = &rot_limit_tbl_4210, | ||
690 | }, | ||
691 | { | ||
692 | .compatible = "samsung,exynos4212-rotator", | ||
693 | .data = &rot_limit_tbl_4x12, | ||
694 | }, | ||
695 | { | ||
696 | .compatible = "samsung,exynos5250-rotator", | ||
697 | .data = &rot_limit_tbl_5250, | ||
698 | }, | ||
699 | {}, | ||
700 | }; | ||
701 | |||
635 | static int rotator_probe(struct platform_device *pdev) | 702 | static int rotator_probe(struct platform_device *pdev) |
636 | { | 703 | { |
637 | struct device *dev = &pdev->dev; | 704 | struct device *dev = &pdev->dev; |
638 | struct rot_context *rot; | 705 | struct rot_context *rot; |
639 | struct exynos_drm_ippdrv *ippdrv; | 706 | struct exynos_drm_ippdrv *ippdrv; |
707 | const struct of_device_id *match; | ||
640 | int ret; | 708 | int ret; |
641 | 709 | ||
710 | if (!dev->of_node) { | ||
711 | dev_err(dev, "cannot find of_node.\n"); | ||
712 | return -ENODEV; | ||
713 | } | ||
714 | |||
642 | rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL); | 715 | rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL); |
643 | if (!rot) { | 716 | if (!rot) { |
644 | dev_err(dev, "failed to allocate rot\n"); | 717 | dev_err(dev, "failed to allocate rot\n"); |
645 | return -ENOMEM; | 718 | return -ENOMEM; |
646 | } | 719 | } |
647 | 720 | ||
648 | rot->limit_tbl = (struct rot_limit_table *) | 721 | match = of_match_node(exynos_rotator_match, dev->of_node); |
649 | platform_get_device_id(pdev)->driver_data; | 722 | if (!match) { |
723 | dev_err(dev, "failed to match node\n"); | ||
724 | return -ENODEV; | ||
725 | } | ||
726 | rot->limit_tbl = (struct rot_limit_table *)match->data; | ||
650 | 727 | ||
651 | rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 728 | rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
652 | rot->regs = devm_ioremap_resource(dev, rot->regs_res); | 729 | rot->regs = devm_ioremap_resource(dev, rot->regs_res); |
@@ -718,31 +795,6 @@ static int rotator_remove(struct platform_device *pdev) | |||
718 | return 0; | 795 | return 0; |
719 | } | 796 | } |
720 | 797 | ||
721 | static struct rot_limit_table rot_limit_tbl = { | ||
722 | .ycbcr420_2p = { | ||
723 | .min_w = 32, | ||
724 | .min_h = 32, | ||
725 | .max_w = SZ_32K, | ||
726 | .max_h = SZ_32K, | ||
727 | .align = 3, | ||
728 | }, | ||
729 | .rgb888 = { | ||
730 | .min_w = 8, | ||
731 | .min_h = 8, | ||
732 | .max_w = SZ_8K, | ||
733 | .max_h = SZ_8K, | ||
734 | .align = 2, | ||
735 | }, | ||
736 | }; | ||
737 | |||
738 | static struct platform_device_id rotator_driver_ids[] = { | ||
739 | { | ||
740 | .name = "exynos-rot", | ||
741 | .driver_data = (unsigned long)&rot_limit_tbl, | ||
742 | }, | ||
743 | {}, | ||
744 | }; | ||
745 | |||
746 | static int rotator_clk_crtl(struct rot_context *rot, bool enable) | 798 | static int rotator_clk_crtl(struct rot_context *rot, bool enable) |
747 | { | 799 | { |
748 | if (enable) { | 800 | if (enable) { |
@@ -804,10 +856,10 @@ static const struct dev_pm_ops rotator_pm_ops = { | |||
804 | struct platform_driver rotator_driver = { | 856 | struct platform_driver rotator_driver = { |
805 | .probe = rotator_probe, | 857 | .probe = rotator_probe, |
806 | .remove = rotator_remove, | 858 | .remove = rotator_remove, |
807 | .id_table = rotator_driver_ids, | ||
808 | .driver = { | 859 | .driver = { |
809 | .name = "exynos-rot", | 860 | .name = "exynos-rot", |
810 | .owner = THIS_MODULE, | 861 | .owner = THIS_MODULE, |
811 | .pm = &rotator_pm_ops, | 862 | .pm = &rotator_pm_ops, |
863 | .of_match_table = exynos_rotator_match, | ||
812 | }, | 864 | }, |
813 | }; | 865 | }; |