aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_mixer.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-17 11:26:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-17 11:26:17 -0500
commit3c2e81ef344a90bb0a39d84af6878b4aeff568a2 (patch)
treebd8c8b23466174899d2fe4d35af6e1e838edb068 /drivers/gpu/drm/exynos/exynos_mixer.c
parent221392c3ad0432e39fd74a349364f66cb0ed78f6 (diff)
parent55bde6b1442fed8af67b92d21acce67db454c9f9 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull DRM updates from Dave Airlie: "This is the one and only next pull for 3.8, we had a regression we found last week, so I was waiting for that to resolve itself, and I ended up with some Intel fixes on top as well. Highlights: - new driver: nvidia tegra 20/30/hdmi support - radeon: add support for previously unused DMA engines, more HDMI regs, eviction speeds ups and fixes - i915: HSW support enable, agp removal on GEN6, seqno wrapping - exynos: IPP subsystem support (image post proc), HDMI - nouveau: display class reworking, nv20->40 z compression - ttm: start of locking fixes, rcu usage for lookups, - core: documentation updates, docbook integration, monotonic clock usage, move from connector to object properties" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (590 commits) drm/exynos: add gsc ipp driver drm/exynos: add rotator ipp driver drm/exynos: add fimc ipp driver drm/exynos: add iommu support for ipp drm/exynos: add ipp subsystem drm/exynos: support device tree for fimd radeon: fix regression with eviction since evict caching changes drm/radeon: add more pedantic checks in the CP DMA checker drm/radeon: bump version for CS ioctl support for async DMA drm/radeon: enable the async DMA rings in the CS ioctl drm/radeon: add VM CS parser support for async DMA on cayman/TN/SI drm/radeon/kms: add evergreen/cayman CS parser for async DMA (v2) drm/radeon/kms: add 6xx/7xx CS parser for async DMA (v2) drm/radeon: fix htile buffer size computation for command stream checker drm/radeon: fix fence locking in the pageflip callback drm/radeon: make indirect register access concurrency-safe drm/radeon: add W|RREG32_IDX for MM_INDEX|DATA based mmio accesss drm/exynos: support extended screen coordinate of fimd drm/exynos: fix x, y coordinates for right bottom pixel drm/exynos: fix fb offset calculation for plane ...
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_mixer.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c376
1 files changed, 237 insertions, 139 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index e7fbb823fd8e..21db89530fc7 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -36,14 +36,13 @@
36 36
37#include "exynos_drm_drv.h" 37#include "exynos_drm_drv.h"
38#include "exynos_drm_hdmi.h" 38#include "exynos_drm_hdmi.h"
39#include "exynos_drm_iommu.h"
39 40
40#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev)) 41#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
41 42
42struct hdmi_win_data { 43struct hdmi_win_data {
43 dma_addr_t dma_addr; 44 dma_addr_t dma_addr;
44 void __iomem *vaddr;
45 dma_addr_t chroma_dma_addr; 45 dma_addr_t chroma_dma_addr;
46 void __iomem *chroma_vaddr;
47 uint32_t pixel_format; 46 uint32_t pixel_format;
48 unsigned int bpp; 47 unsigned int bpp;
49 unsigned int crtc_x; 48 unsigned int crtc_x;
@@ -59,6 +58,8 @@ struct hdmi_win_data {
59 unsigned int mode_width; 58 unsigned int mode_width;
60 unsigned int mode_height; 59 unsigned int mode_height;
61 unsigned int scan_flags; 60 unsigned int scan_flags;
61 bool enabled;
62 bool resume;
62}; 63};
63 64
64struct mixer_resources { 65struct mixer_resources {
@@ -80,6 +81,7 @@ enum mixer_version_id {
80 81
81struct mixer_context { 82struct mixer_context {
82 struct device *dev; 83 struct device *dev;
84 struct drm_device *drm_dev;
83 int pipe; 85 int pipe;
84 bool interlace; 86 bool interlace;
85 bool powered; 87 bool powered;
@@ -90,6 +92,9 @@ struct mixer_context {
90 struct mixer_resources mixer_res; 92 struct mixer_resources mixer_res;
91 struct hdmi_win_data win_data[MIXER_WIN_NR]; 93 struct hdmi_win_data win_data[MIXER_WIN_NR];
92 enum mixer_version_id mxr_ver; 94 enum mixer_version_id mxr_ver;
95 void *parent_ctx;
96 wait_queue_head_t wait_vsync_queue;
97 atomic_t wait_vsync_event;
93}; 98};
94 99
95struct mixer_drv_data { 100struct mixer_drv_data {
@@ -665,58 +670,22 @@ static void mixer_win_reset(struct mixer_context *ctx)
665 spin_unlock_irqrestore(&res->reg_slock, flags); 670 spin_unlock_irqrestore(&res->reg_slock, flags);
666} 671}
667 672
668static void mixer_poweron(struct mixer_context *ctx) 673static int mixer_iommu_on(void *ctx, bool enable)
669{
670 struct mixer_resources *res = &ctx->mixer_res;
671
672 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
673
674 mutex_lock(&ctx->mixer_mutex);
675 if (ctx->powered) {
676 mutex_unlock(&ctx->mixer_mutex);
677 return;
678 }
679 ctx->powered = true;
680 mutex_unlock(&ctx->mixer_mutex);
681
682 pm_runtime_get_sync(ctx->dev);
683
684 clk_enable(res->mixer);
685 if (ctx->vp_enabled) {
686 clk_enable(res->vp);
687 clk_enable(res->sclk_mixer);
688 }
689
690 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
691 mixer_win_reset(ctx);
692}
693
694static void mixer_poweroff(struct mixer_context *ctx)
695{ 674{
696 struct mixer_resources *res = &ctx->mixer_res; 675 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
697 676 struct mixer_context *mdata = ctx;
698 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 677 struct drm_device *drm_dev;
699 678
700 mutex_lock(&ctx->mixer_mutex); 679 drm_hdmi_ctx = mdata->parent_ctx;
701 if (!ctx->powered) 680 drm_dev = drm_hdmi_ctx->drm_dev;
702 goto out;
703 mutex_unlock(&ctx->mixer_mutex);
704 681
705 ctx->int_en = mixer_reg_read(res, MXR_INT_EN); 682 if (is_drm_iommu_supported(drm_dev)) {
683 if (enable)
684 return drm_iommu_attach_device(drm_dev, mdata->dev);
706 685
707 clk_disable(res->mixer); 686 drm_iommu_detach_device(drm_dev, mdata->dev);
708 if (ctx->vp_enabled) {
709 clk_disable(res->vp);
710 clk_disable(res->sclk_mixer);
711 } 687 }
712 688 return 0;
713 pm_runtime_put_sync(ctx->dev);
714
715 mutex_lock(&ctx->mixer_mutex);
716 ctx->powered = false;
717
718out:
719 mutex_unlock(&ctx->mixer_mutex);
720} 689}
721 690
722static int mixer_enable_vblank(void *ctx, int pipe) 691static int mixer_enable_vblank(void *ctx, int pipe)
@@ -746,39 +715,6 @@ static void mixer_disable_vblank(void *ctx)
746 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 715 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
747} 716}
748 717
749static void mixer_dpms(void *ctx, int mode)
750{
751 struct mixer_context *mixer_ctx = ctx;
752
753 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
754
755 switch (mode) {
756 case DRM_MODE_DPMS_ON:
757 mixer_poweron(mixer_ctx);
758 break;
759 case DRM_MODE_DPMS_STANDBY:
760 case DRM_MODE_DPMS_SUSPEND:
761 case DRM_MODE_DPMS_OFF:
762 mixer_poweroff(mixer_ctx);
763 break;
764 default:
765 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
766 break;
767 }
768}
769
770static void mixer_wait_for_vblank(void *ctx)
771{
772 struct mixer_context *mixer_ctx = ctx;
773 struct mixer_resources *res = &mixer_ctx->mixer_res;
774 int ret;
775
776 ret = wait_for((mixer_reg_read(res, MXR_INT_STATUS) &
777 MXR_INT_STATUS_VSYNC), 50);
778 if (ret < 0)
779 DRM_DEBUG_KMS("vblank wait timed out.\n");
780}
781
782static void mixer_win_mode_set(void *ctx, 718static void mixer_win_mode_set(void *ctx,
783 struct exynos_drm_overlay *overlay) 719 struct exynos_drm_overlay *overlay)
784{ 720{
@@ -811,9 +747,7 @@ static void mixer_win_mode_set(void *ctx,
811 win_data = &mixer_ctx->win_data[win]; 747 win_data = &mixer_ctx->win_data[win];
812 748
813 win_data->dma_addr = overlay->dma_addr[0]; 749 win_data->dma_addr = overlay->dma_addr[0];
814 win_data->vaddr = overlay->vaddr[0];
815 win_data->chroma_dma_addr = overlay->dma_addr[1]; 750 win_data->chroma_dma_addr = overlay->dma_addr[1];
816 win_data->chroma_vaddr = overlay->vaddr[1];
817 win_data->pixel_format = overlay->pixel_format; 751 win_data->pixel_format = overlay->pixel_format;
818 win_data->bpp = overlay->bpp; 752 win_data->bpp = overlay->bpp;
819 753
@@ -845,6 +779,8 @@ static void mixer_win_commit(void *ctx, int win)
845 vp_video_buffer(mixer_ctx, win); 779 vp_video_buffer(mixer_ctx, win);
846 else 780 else
847 mixer_graph_buffer(mixer_ctx, win); 781 mixer_graph_buffer(mixer_ctx, win);
782
783 mixer_ctx->win_data[win].enabled = true;
848} 784}
849 785
850static void mixer_win_disable(void *ctx, int win) 786static void mixer_win_disable(void *ctx, int win)
@@ -855,6 +791,14 @@ static void mixer_win_disable(void *ctx, int win)
855 791
856 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); 792 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
857 793
794 mutex_lock(&mixer_ctx->mixer_mutex);
795 if (!mixer_ctx->powered) {
796 mutex_unlock(&mixer_ctx->mixer_mutex);
797 mixer_ctx->win_data[win].resume = false;
798 return;
799 }
800 mutex_unlock(&mixer_ctx->mixer_mutex);
801
858 spin_lock_irqsave(&res->reg_slock, flags); 802 spin_lock_irqsave(&res->reg_slock, flags);
859 mixer_vsync_set_update(mixer_ctx, false); 803 mixer_vsync_set_update(mixer_ctx, false);
860 804
@@ -862,16 +806,144 @@ static void mixer_win_disable(void *ctx, int win)
862 806
863 mixer_vsync_set_update(mixer_ctx, true); 807 mixer_vsync_set_update(mixer_ctx, true);
864 spin_unlock_irqrestore(&res->reg_slock, flags); 808 spin_unlock_irqrestore(&res->reg_slock, flags);
809
810 mixer_ctx->win_data[win].enabled = false;
811}
812
813static void mixer_wait_for_vblank(void *ctx)
814{
815 struct mixer_context *mixer_ctx = ctx;
816
817 mutex_lock(&mixer_ctx->mixer_mutex);
818 if (!mixer_ctx->powered) {
819 mutex_unlock(&mixer_ctx->mixer_mutex);
820 return;
821 }
822 mutex_unlock(&mixer_ctx->mixer_mutex);
823
824 atomic_set(&mixer_ctx->wait_vsync_event, 1);
825
826 /*
827 * wait for MIXER to signal VSYNC interrupt or return after
828 * timeout which is set to 50ms (refresh rate of 20).
829 */
830 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
831 !atomic_read(&mixer_ctx->wait_vsync_event),
832 DRM_HZ/20))
833 DRM_DEBUG_KMS("vblank wait timed out.\n");
834}
835
836static void mixer_window_suspend(struct mixer_context *ctx)
837{
838 struct hdmi_win_data *win_data;
839 int i;
840
841 for (i = 0; i < MIXER_WIN_NR; i++) {
842 win_data = &ctx->win_data[i];
843 win_data->resume = win_data->enabled;
844 mixer_win_disable(ctx, i);
845 }
846 mixer_wait_for_vblank(ctx);
847}
848
849static void mixer_window_resume(struct mixer_context *ctx)
850{
851 struct hdmi_win_data *win_data;
852 int i;
853
854 for (i = 0; i < MIXER_WIN_NR; i++) {
855 win_data = &ctx->win_data[i];
856 win_data->enabled = win_data->resume;
857 win_data->resume = false;
858 }
859}
860
861static void mixer_poweron(struct mixer_context *ctx)
862{
863 struct mixer_resources *res = &ctx->mixer_res;
864
865 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
866
867 mutex_lock(&ctx->mixer_mutex);
868 if (ctx->powered) {
869 mutex_unlock(&ctx->mixer_mutex);
870 return;
871 }
872 ctx->powered = true;
873 mutex_unlock(&ctx->mixer_mutex);
874
875 clk_enable(res->mixer);
876 if (ctx->vp_enabled) {
877 clk_enable(res->vp);
878 clk_enable(res->sclk_mixer);
879 }
880
881 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
882 mixer_win_reset(ctx);
883
884 mixer_window_resume(ctx);
885}
886
887static void mixer_poweroff(struct mixer_context *ctx)
888{
889 struct mixer_resources *res = &ctx->mixer_res;
890
891 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
892
893 mutex_lock(&ctx->mixer_mutex);
894 if (!ctx->powered)
895 goto out;
896 mutex_unlock(&ctx->mixer_mutex);
897
898 mixer_window_suspend(ctx);
899
900 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
901
902 clk_disable(res->mixer);
903 if (ctx->vp_enabled) {
904 clk_disable(res->vp);
905 clk_disable(res->sclk_mixer);
906 }
907
908 mutex_lock(&ctx->mixer_mutex);
909 ctx->powered = false;
910
911out:
912 mutex_unlock(&ctx->mixer_mutex);
913}
914
915static void mixer_dpms(void *ctx, int mode)
916{
917 struct mixer_context *mixer_ctx = ctx;
918
919 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
920
921 switch (mode) {
922 case DRM_MODE_DPMS_ON:
923 if (pm_runtime_suspended(mixer_ctx->dev))
924 pm_runtime_get_sync(mixer_ctx->dev);
925 break;
926 case DRM_MODE_DPMS_STANDBY:
927 case DRM_MODE_DPMS_SUSPEND:
928 case DRM_MODE_DPMS_OFF:
929 if (!pm_runtime_suspended(mixer_ctx->dev))
930 pm_runtime_put_sync(mixer_ctx->dev);
931 break;
932 default:
933 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
934 break;
935 }
865} 936}
866 937
867static struct exynos_mixer_ops mixer_ops = { 938static struct exynos_mixer_ops mixer_ops = {
868 /* manager */ 939 /* manager */
940 .iommu_on = mixer_iommu_on,
869 .enable_vblank = mixer_enable_vblank, 941 .enable_vblank = mixer_enable_vblank,
870 .disable_vblank = mixer_disable_vblank, 942 .disable_vblank = mixer_disable_vblank,
943 .wait_for_vblank = mixer_wait_for_vblank,
871 .dpms = mixer_dpms, 944 .dpms = mixer_dpms,
872 945
873 /* overlay */ 946 /* overlay */
874 .wait_for_vblank = mixer_wait_for_vblank,
875 .win_mode_set = mixer_win_mode_set, 947 .win_mode_set = mixer_win_mode_set,
876 .win_commit = mixer_win_commit, 948 .win_commit = mixer_win_commit,
877 .win_disable = mixer_win_disable, 949 .win_disable = mixer_win_disable,
@@ -884,7 +956,6 @@ static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
884 struct drm_pending_vblank_event *e, *t; 956 struct drm_pending_vblank_event *e, *t;
885 struct timeval now; 957 struct timeval now;
886 unsigned long flags; 958 unsigned long flags;
887 bool is_checked = false;
888 959
889 spin_lock_irqsave(&drm_dev->event_lock, flags); 960 spin_lock_irqsave(&drm_dev->event_lock, flags);
890 961
@@ -894,7 +965,6 @@ static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
894 if (crtc != e->pipe) 965 if (crtc != e->pipe)
895 continue; 966 continue;
896 967
897 is_checked = true;
898 do_gettimeofday(&now); 968 do_gettimeofday(&now);
899 e->event.sequence = 0; 969 e->event.sequence = 0;
900 e->event.tv_sec = now.tv_sec; 970 e->event.tv_sec = now.tv_sec;
@@ -902,16 +972,9 @@ static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
902 972
903 list_move_tail(&e->base.link, &e->base.file_priv->event_list); 973 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
904 wake_up_interruptible(&e->base.file_priv->event_wait); 974 wake_up_interruptible(&e->base.file_priv->event_wait);
975 drm_vblank_put(drm_dev, crtc);
905 } 976 }
906 977
907 if (is_checked)
908 /*
909 * call drm_vblank_put only in case that drm_vblank_get was
910 * called.
911 */
912 if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
913 drm_vblank_put(drm_dev, crtc);
914
915 spin_unlock_irqrestore(&drm_dev->event_lock, flags); 978 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
916} 979}
917 980
@@ -944,6 +1007,12 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
944 1007
945 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe); 1008 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
946 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe); 1009 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
1010
1011 /* set wait vsync event to zero and wake up queue. */
1012 if (atomic_read(&ctx->wait_vsync_event)) {
1013 atomic_set(&ctx->wait_vsync_event, 0);
1014 DRM_WAKEUP(&ctx->wait_vsync_queue);
1015 }
947 } 1016 }
948 1017
949out: 1018out:
@@ -971,57 +1040,45 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
971 1040
972 spin_lock_init(&mixer_res->reg_slock); 1041 spin_lock_init(&mixer_res->reg_slock);
973 1042
974 mixer_res->mixer = clk_get(dev, "mixer"); 1043 mixer_res->mixer = devm_clk_get(dev, "mixer");
975 if (IS_ERR_OR_NULL(mixer_res->mixer)) { 1044 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
976 dev_err(dev, "failed to get clock 'mixer'\n"); 1045 dev_err(dev, "failed to get clock 'mixer'\n");
977 ret = -ENODEV; 1046 return -ENODEV;
978 goto fail;
979 } 1047 }
980 1048
981 mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); 1049 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
982 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { 1050 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
983 dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); 1051 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
984 ret = -ENODEV; 1052 return -ENODEV;
985 goto fail;
986 } 1053 }
987 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1054 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
988 if (res == NULL) { 1055 if (res == NULL) {
989 dev_err(dev, "get memory resource failed.\n"); 1056 dev_err(dev, "get memory resource failed.\n");
990 ret = -ENXIO; 1057 return -ENXIO;
991 goto fail;
992 } 1058 }
993 1059
994 mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start, 1060 mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start,
995 resource_size(res)); 1061 resource_size(res));
996 if (mixer_res->mixer_regs == NULL) { 1062 if (mixer_res->mixer_regs == NULL) {
997 dev_err(dev, "register mapping failed.\n"); 1063 dev_err(dev, "register mapping failed.\n");
998 ret = -ENXIO; 1064 return -ENXIO;
999 goto fail;
1000 } 1065 }
1001 1066
1002 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1067 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1003 if (res == NULL) { 1068 if (res == NULL) {
1004 dev_err(dev, "get interrupt resource failed.\n"); 1069 dev_err(dev, "get interrupt resource failed.\n");
1005 ret = -ENXIO; 1070 return -ENXIO;
1006 goto fail;
1007 } 1071 }
1008 1072
1009 ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler, 1073 ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler,
1010 0, "drm_mixer", ctx); 1074 0, "drm_mixer", ctx);
1011 if (ret) { 1075 if (ret) {
1012 dev_err(dev, "request interrupt failed.\n"); 1076 dev_err(dev, "request interrupt failed.\n");
1013 goto fail; 1077 return ret;
1014 } 1078 }
1015 mixer_res->irq = res->start; 1079 mixer_res->irq = res->start;
1016 1080
1017 return 0; 1081 return 0;
1018
1019fail:
1020 if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1021 clk_put(mixer_res->sclk_hdmi);
1022 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1023 clk_put(mixer_res->mixer);
1024 return ret;
1025} 1082}
1026 1083
1027static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx, 1084static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx,
@@ -1031,25 +1088,21 @@ static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx,
1031 struct device *dev = &pdev->dev; 1088 struct device *dev = &pdev->dev;
1032 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; 1089 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1033 struct resource *res; 1090 struct resource *res;
1034 int ret;
1035 1091
1036 mixer_res->vp = clk_get(dev, "vp"); 1092 mixer_res->vp = devm_clk_get(dev, "vp");
1037 if (IS_ERR_OR_NULL(mixer_res->vp)) { 1093 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1038 dev_err(dev, "failed to get clock 'vp'\n"); 1094 dev_err(dev, "failed to get clock 'vp'\n");
1039 ret = -ENODEV; 1095 return -ENODEV;
1040 goto fail;
1041 } 1096 }
1042 mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer"); 1097 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
1043 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { 1098 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1044 dev_err(dev, "failed to get clock 'sclk_mixer'\n"); 1099 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1045 ret = -ENODEV; 1100 return -ENODEV;
1046 goto fail;
1047 } 1101 }
1048 mixer_res->sclk_dac = clk_get(dev, "sclk_dac"); 1102 mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
1049 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { 1103 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1050 dev_err(dev, "failed to get clock 'sclk_dac'\n"); 1104 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1051 ret = -ENODEV; 1105 return -ENODEV;
1052 goto fail;
1053 } 1106 }
1054 1107
1055 if (mixer_res->sclk_hdmi) 1108 if (mixer_res->sclk_hdmi)
@@ -1058,28 +1111,17 @@ static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx,
1058 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1111 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1059 if (res == NULL) { 1112 if (res == NULL) {
1060 dev_err(dev, "get memory resource failed.\n"); 1113 dev_err(dev, "get memory resource failed.\n");
1061 ret = -ENXIO; 1114 return -ENXIO;
1062 goto fail;
1063 } 1115 }
1064 1116
1065 mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start, 1117 mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start,
1066 resource_size(res)); 1118 resource_size(res));
1067 if (mixer_res->vp_regs == NULL) { 1119 if (mixer_res->vp_regs == NULL) {
1068 dev_err(dev, "register mapping failed.\n"); 1120 dev_err(dev, "register mapping failed.\n");
1069 ret = -ENXIO; 1121 return -ENXIO;
1070 goto fail;
1071 } 1122 }
1072 1123
1073 return 0; 1124 return 0;
1074
1075fail:
1076 if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1077 clk_put(mixer_res->sclk_dac);
1078 if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1079 clk_put(mixer_res->sclk_mixer);
1080 if (!IS_ERR_OR_NULL(mixer_res->vp))
1081 clk_put(mixer_res->vp);
1082 return ret;
1083} 1125}
1084 1126
1085static struct mixer_drv_data exynos5_mxr_drv_data = { 1127static struct mixer_drv_data exynos5_mxr_drv_data = {
@@ -1149,9 +1191,12 @@ static int __devinit mixer_probe(struct platform_device *pdev)
1149 } 1191 }
1150 1192
1151 ctx->dev = &pdev->dev; 1193 ctx->dev = &pdev->dev;
1194 ctx->parent_ctx = (void *)drm_hdmi_ctx;
1152 drm_hdmi_ctx->ctx = (void *)ctx; 1195 drm_hdmi_ctx->ctx = (void *)ctx;
1153 ctx->vp_enabled = drv->is_vp_enabled; 1196 ctx->vp_enabled = drv->is_vp_enabled;
1154 ctx->mxr_ver = drv->version; 1197 ctx->mxr_ver = drv->version;
1198 DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
1199 atomic_set(&ctx->wait_vsync_event, 0);
1155 1200
1156 platform_set_drvdata(pdev, drm_hdmi_ctx); 1201 platform_set_drvdata(pdev, drm_hdmi_ctx);
1157 1202
@@ -1202,13 +1247,66 @@ static int mixer_suspend(struct device *dev)
1202 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev); 1247 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1203 struct mixer_context *ctx = drm_hdmi_ctx->ctx; 1248 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1204 1249
1250 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1251
1252 if (pm_runtime_suspended(dev)) {
1253 DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
1254 return 0;
1255 }
1256
1205 mixer_poweroff(ctx); 1257 mixer_poweroff(ctx);
1206 1258
1207 return 0; 1259 return 0;
1208} 1260}
1261
1262static int mixer_resume(struct device *dev)
1263{
1264 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1265 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1266
1267 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1268
1269 if (!pm_runtime_suspended(dev)) {
1270 DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
1271 return 0;
1272 }
1273
1274 mixer_poweron(ctx);
1275
1276 return 0;
1277}
1209#endif 1278#endif
1210 1279
1211static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL); 1280#ifdef CONFIG_PM_RUNTIME
1281static int mixer_runtime_suspend(struct device *dev)
1282{
1283 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1284 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1285
1286 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1287
1288 mixer_poweroff(ctx);
1289
1290 return 0;
1291}
1292
1293static int mixer_runtime_resume(struct device *dev)
1294{
1295 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1296 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1297
1298 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1299
1300 mixer_poweron(ctx);
1301
1302 return 0;
1303}
1304#endif
1305
1306static const struct dev_pm_ops mixer_pm_ops = {
1307 SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
1308 SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
1309};
1212 1310
1213struct platform_driver mixer_driver = { 1311struct platform_driver mixer_driver = {
1214 .driver = { 1312 .driver = {