diff options
author | Rahul Sharma <rahul.sharma@samsung.com> | 2012-10-04 11:18:52 -0400 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2012-10-05 06:15:08 -0400 |
commit | 1b8e5747a9b65928a5a126d128847b29128cae34 (patch) | |
tree | 32c6890d2f595cad9008ed780a934f4007a02dfd /drivers/gpu | |
parent | 1e12344120df6b1959f47382bac02952bee6226c (diff) |
drm: exynos: hdmi: add support to disable video processor in mixer
This patch adds support for disabling the video processor code based
on the platform type. This is done based on a field in the mixer driver
data which changes with the platform variant.
Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 151 |
1 files changed, 98 insertions, 53 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index e312fb1dafdd..167734529229 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -83,6 +83,7 @@ struct mixer_context { | |||
83 | int pipe; | 83 | int pipe; |
84 | bool interlace; | 84 | bool interlace; |
85 | bool powered; | 85 | bool powered; |
86 | bool vp_enabled; | ||
86 | u32 int_en; | 87 | u32 int_en; |
87 | 88 | ||
88 | struct mutex mixer_mutex; | 89 | struct mutex mixer_mutex; |
@@ -93,6 +94,7 @@ struct mixer_context { | |||
93 | 94 | ||
94 | struct mixer_drv_data { | 95 | struct mixer_drv_data { |
95 | enum mixer_version_id version; | 96 | enum mixer_version_id version; |
97 | bool is_vp_enabled; | ||
96 | }; | 98 | }; |
97 | 99 | ||
98 | static const u8 filter_y_horiz_tap8[] = { | 100 | static const u8 filter_y_horiz_tap8[] = { |
@@ -261,7 +263,8 @@ static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) | |||
261 | mixer_reg_writemask(res, MXR_STATUS, enable ? | 263 | mixer_reg_writemask(res, MXR_STATUS, enable ? |
262 | MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); | 264 | MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); |
263 | 265 | ||
264 | vp_reg_write(res, VP_SHADOW_UPDATE, enable ? | 266 | if (ctx->vp_enabled) |
267 | vp_reg_write(res, VP_SHADOW_UPDATE, enable ? | ||
265 | VP_SHADOW_UPDATE_ENABLE : 0); | 268 | VP_SHADOW_UPDATE_ENABLE : 0); |
266 | } | 269 | } |
267 | 270 | ||
@@ -343,8 +346,11 @@ static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable) | |||
343 | mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); | 346 | mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); |
344 | break; | 347 | break; |
345 | case 2: | 348 | case 2: |
346 | vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); | 349 | if (ctx->vp_enabled) { |
347 | mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE); | 350 | vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); |
351 | mixer_reg_writemask(res, MXR_CFG, val, | ||
352 | MXR_CFG_VP_ENABLE); | ||
353 | } | ||
348 | break; | 354 | break; |
349 | } | 355 | } |
350 | } | 356 | } |
@@ -602,7 +608,8 @@ static void mixer_win_reset(struct mixer_context *ctx) | |||
602 | */ | 608 | */ |
603 | val = MXR_LAYER_CFG_GRP1_VAL(3); | 609 | val = MXR_LAYER_CFG_GRP1_VAL(3); |
604 | val |= MXR_LAYER_CFG_GRP0_VAL(2); | 610 | val |= MXR_LAYER_CFG_GRP0_VAL(2); |
605 | val |= MXR_LAYER_CFG_VP_VAL(1); | 611 | if (ctx->vp_enabled) |
612 | val |= MXR_LAYER_CFG_VP_VAL(1); | ||
606 | mixer_reg_write(res, MXR_LAYER_CFG, val); | 613 | mixer_reg_write(res, MXR_LAYER_CFG, val); |
607 | 614 | ||
608 | /* setting background color */ | 615 | /* setting background color */ |
@@ -625,14 +632,17 @@ static void mixer_win_reset(struct mixer_context *ctx) | |||
625 | val = MXR_GRP_CFG_ALPHA_VAL(0); | 632 | val = MXR_GRP_CFG_ALPHA_VAL(0); |
626 | mixer_reg_write(res, MXR_VIDEO_CFG, val); | 633 | mixer_reg_write(res, MXR_VIDEO_CFG, val); |
627 | 634 | ||
628 | /* configuration of Video Processor Registers */ | 635 | if (ctx->vp_enabled) { |
629 | vp_win_reset(ctx); | 636 | /* configuration of Video Processor Registers */ |
630 | vp_default_filter(res); | 637 | vp_win_reset(ctx); |
638 | vp_default_filter(res); | ||
639 | } | ||
631 | 640 | ||
632 | /* disable all layers */ | 641 | /* disable all layers */ |
633 | mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); | 642 | mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); |
634 | mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE); | 643 | mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE); |
635 | mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); | 644 | if (ctx->vp_enabled) |
645 | mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); | ||
636 | 646 | ||
637 | mixer_vsync_set_update(ctx, true); | 647 | mixer_vsync_set_update(ctx, true); |
638 | spin_unlock_irqrestore(&res->reg_slock, flags); | 648 | spin_unlock_irqrestore(&res->reg_slock, flags); |
@@ -655,8 +665,10 @@ static void mixer_poweron(struct mixer_context *ctx) | |||
655 | pm_runtime_get_sync(ctx->dev); | 665 | pm_runtime_get_sync(ctx->dev); |
656 | 666 | ||
657 | clk_enable(res->mixer); | 667 | clk_enable(res->mixer); |
658 | clk_enable(res->vp); | 668 | if (ctx->vp_enabled) { |
659 | clk_enable(res->sclk_mixer); | 669 | clk_enable(res->vp); |
670 | clk_enable(res->sclk_mixer); | ||
671 | } | ||
660 | 672 | ||
661 | mixer_reg_write(res, MXR_INT_EN, ctx->int_en); | 673 | mixer_reg_write(res, MXR_INT_EN, ctx->int_en); |
662 | mixer_win_reset(ctx); | 674 | mixer_win_reset(ctx); |
@@ -676,8 +688,10 @@ static void mixer_poweroff(struct mixer_context *ctx) | |||
676 | ctx->int_en = mixer_reg_read(res, MXR_INT_EN); | 688 | ctx->int_en = mixer_reg_read(res, MXR_INT_EN); |
677 | 689 | ||
678 | clk_disable(res->mixer); | 690 | clk_disable(res->mixer); |
679 | clk_disable(res->vp); | 691 | if (ctx->vp_enabled) { |
680 | clk_disable(res->sclk_mixer); | 692 | clk_disable(res->vp); |
693 | clk_disable(res->sclk_mixer); | ||
694 | } | ||
681 | 695 | ||
682 | pm_runtime_put_sync(ctx->dev); | 696 | pm_runtime_put_sync(ctx->dev); |
683 | 697 | ||
@@ -810,7 +824,7 @@ static void mixer_win_commit(void *ctx, int win) | |||
810 | 824 | ||
811 | DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); | 825 | DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); |
812 | 826 | ||
813 | if (win > 1) | 827 | if (win > 1 && mixer_ctx->vp_enabled) |
814 | vp_video_buffer(mixer_ctx, win); | 828 | vp_video_buffer(mixer_ctx, win); |
815 | else | 829 | else |
816 | mixer_graph_buffer(mixer_ctx, win); | 830 | mixer_graph_buffer(mixer_ctx, win); |
@@ -946,39 +960,20 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, | |||
946 | ret = -ENODEV; | 960 | ret = -ENODEV; |
947 | goto fail; | 961 | goto fail; |
948 | } | 962 | } |
949 | mixer_res->vp = clk_get(dev, "vp"); | 963 | |
950 | if (IS_ERR_OR_NULL(mixer_res->vp)) { | ||
951 | dev_err(dev, "failed to get clock 'vp'\n"); | ||
952 | ret = -ENODEV; | ||
953 | goto fail; | ||
954 | } | ||
955 | mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer"); | ||
956 | if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { | ||
957 | dev_err(dev, "failed to get clock 'sclk_mixer'\n"); | ||
958 | ret = -ENODEV; | ||
959 | goto fail; | ||
960 | } | ||
961 | mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); | 964 | mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); |
962 | if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { | 965 | if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { |
963 | dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); | 966 | dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); |
964 | ret = -ENODEV; | 967 | ret = -ENODEV; |
965 | goto fail; | 968 | goto fail; |
966 | } | 969 | } |
967 | mixer_res->sclk_dac = clk_get(dev, "sclk_dac"); | 970 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
968 | if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { | ||
969 | dev_err(dev, "failed to get clock 'sclk_dac'\n"); | ||
970 | ret = -ENODEV; | ||
971 | goto fail; | ||
972 | } | ||
973 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr"); | ||
974 | if (res == NULL) { | 971 | if (res == NULL) { |
975 | dev_err(dev, "get memory resource failed.\n"); | 972 | dev_err(dev, "get memory resource failed.\n"); |
976 | ret = -ENXIO; | 973 | ret = -ENXIO; |
977 | goto fail; | 974 | goto fail; |
978 | } | 975 | } |
979 | 976 | ||
980 | clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); | ||
981 | |||
982 | mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start, | 977 | mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start, |
983 | resource_size(res)); | 978 | resource_size(res)); |
984 | if (mixer_res->mixer_regs == NULL) { | 979 | if (mixer_res->mixer_regs == NULL) { |
@@ -987,54 +982,92 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, | |||
987 | goto fail; | 982 | goto fail; |
988 | } | 983 | } |
989 | 984 | ||
990 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp"); | 985 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
991 | if (res == NULL) { | 986 | if (res == NULL) { |
992 | dev_err(dev, "get memory resource failed.\n"); | 987 | dev_err(dev, "get interrupt resource failed.\n"); |
993 | ret = -ENXIO; | 988 | ret = -ENXIO; |
994 | goto fail; | 989 | goto fail; |
995 | } | 990 | } |
996 | 991 | ||
997 | mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start, | 992 | ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler, |
998 | resource_size(res)); | 993 | 0, "drm_mixer", ctx); |
999 | if (mixer_res->vp_regs == NULL) { | 994 | if (ret) { |
1000 | dev_err(dev, "register mapping failed.\n"); | 995 | dev_err(dev, "request interrupt failed.\n"); |
1001 | ret = -ENXIO; | ||
1002 | goto fail; | 996 | goto fail; |
1003 | } | 997 | } |
998 | mixer_res->irq = res->start; | ||
1004 | 999 | ||
1005 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq"); | 1000 | return 0; |
1001 | |||
1002 | fail: | ||
1003 | if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) | ||
1004 | clk_put(mixer_res->sclk_hdmi); | ||
1005 | if (!IS_ERR_OR_NULL(mixer_res->mixer)) | ||
1006 | clk_put(mixer_res->mixer); | ||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx, | ||
1011 | struct platform_device *pdev) | ||
1012 | { | ||
1013 | struct mixer_context *mixer_ctx = ctx->ctx; | ||
1014 | struct device *dev = &pdev->dev; | ||
1015 | struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; | ||
1016 | struct resource *res; | ||
1017 | int ret; | ||
1018 | |||
1019 | mixer_res->vp = clk_get(dev, "vp"); | ||
1020 | if (IS_ERR_OR_NULL(mixer_res->vp)) { | ||
1021 | dev_err(dev, "failed to get clock 'vp'\n"); | ||
1022 | ret = -ENODEV; | ||
1023 | goto fail; | ||
1024 | } | ||
1025 | mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer"); | ||
1026 | if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { | ||
1027 | dev_err(dev, "failed to get clock 'sclk_mixer'\n"); | ||
1028 | ret = -ENODEV; | ||
1029 | goto fail; | ||
1030 | } | ||
1031 | mixer_res->sclk_dac = clk_get(dev, "sclk_dac"); | ||
1032 | if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { | ||
1033 | dev_err(dev, "failed to get clock 'sclk_dac'\n"); | ||
1034 | ret = -ENODEV; | ||
1035 | goto fail; | ||
1036 | } | ||
1037 | |||
1038 | if (mixer_res->sclk_hdmi) | ||
1039 | clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); | ||
1040 | |||
1041 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1006 | if (res == NULL) { | 1042 | if (res == NULL) { |
1007 | dev_err(dev, "get interrupt resource failed.\n"); | 1043 | dev_err(dev, "get memory resource failed.\n"); |
1008 | ret = -ENXIO; | 1044 | ret = -ENXIO; |
1009 | goto fail; | 1045 | goto fail; |
1010 | } | 1046 | } |
1011 | 1047 | ||
1012 | ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler, | 1048 | mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start, |
1013 | 0, "drm_mixer", ctx); | 1049 | resource_size(res)); |
1014 | if (ret) { | 1050 | if (mixer_res->vp_regs == NULL) { |
1015 | dev_err(dev, "request interrupt failed.\n"); | 1051 | dev_err(dev, "register mapping failed.\n"); |
1052 | ret = -ENXIO; | ||
1016 | goto fail; | 1053 | goto fail; |
1017 | } | 1054 | } |
1018 | mixer_res->irq = res->start; | ||
1019 | 1055 | ||
1020 | return 0; | 1056 | return 0; |
1021 | 1057 | ||
1022 | fail: | 1058 | fail: |
1023 | if (!IS_ERR_OR_NULL(mixer_res->sclk_dac)) | 1059 | if (!IS_ERR_OR_NULL(mixer_res->sclk_dac)) |
1024 | clk_put(mixer_res->sclk_dac); | 1060 | clk_put(mixer_res->sclk_dac); |
1025 | if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) | ||
1026 | clk_put(mixer_res->sclk_hdmi); | ||
1027 | if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer)) | 1061 | if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer)) |
1028 | clk_put(mixer_res->sclk_mixer); | 1062 | clk_put(mixer_res->sclk_mixer); |
1029 | if (!IS_ERR_OR_NULL(mixer_res->vp)) | 1063 | if (!IS_ERR_OR_NULL(mixer_res->vp)) |
1030 | clk_put(mixer_res->vp); | 1064 | clk_put(mixer_res->vp); |
1031 | if (!IS_ERR_OR_NULL(mixer_res->mixer)) | ||
1032 | clk_put(mixer_res->mixer); | ||
1033 | return ret; | 1065 | return ret; |
1034 | } | 1066 | } |
1035 | 1067 | ||
1036 | static struct mixer_drv_data exynos4_mxr_drv_data = { | 1068 | static struct mixer_drv_data exynos4_mxr_drv_data = { |
1037 | .version = MXR_VER_0_0_0_16, | 1069 | .version = MXR_VER_0_0_0_16, |
1070 | .is_vp_enabled = 1, | ||
1038 | }; | 1071 | }; |
1039 | 1072 | ||
1040 | static struct platform_device_id mixer_driver_types[] = { | 1073 | static struct platform_device_id mixer_driver_types[] = { |
@@ -1075,14 +1108,26 @@ static int __devinit mixer_probe(struct platform_device *pdev) | |||
1075 | pdev)->driver_data; | 1108 | pdev)->driver_data; |
1076 | ctx->dev = &pdev->dev; | 1109 | ctx->dev = &pdev->dev; |
1077 | drm_hdmi_ctx->ctx = (void *)ctx; | 1110 | drm_hdmi_ctx->ctx = (void *)ctx; |
1111 | ctx->vp_enabled = drv->is_vp_enabled; | ||
1078 | ctx->mxr_ver = drv->version; | 1112 | ctx->mxr_ver = drv->version; |
1079 | 1113 | ||
1080 | platform_set_drvdata(pdev, drm_hdmi_ctx); | 1114 | platform_set_drvdata(pdev, drm_hdmi_ctx); |
1081 | 1115 | ||
1082 | /* acquire resources: regs, irqs, clocks */ | 1116 | /* acquire resources: regs, irqs, clocks */ |
1083 | ret = mixer_resources_init(drm_hdmi_ctx, pdev); | 1117 | ret = mixer_resources_init(drm_hdmi_ctx, pdev); |
1084 | if (ret) | 1118 | if (ret) { |
1119 | DRM_ERROR("mixer_resources_init failed\n"); | ||
1085 | goto fail; | 1120 | goto fail; |
1121 | } | ||
1122 | |||
1123 | if (ctx->vp_enabled) { | ||
1124 | /* acquire vp resources: regs, irqs, clocks */ | ||
1125 | ret = vp_resources_init(drm_hdmi_ctx, pdev); | ||
1126 | if (ret) { | ||
1127 | DRM_ERROR("vp_resources_init failed\n"); | ||
1128 | goto fail; | ||
1129 | } | ||
1130 | } | ||
1086 | 1131 | ||
1087 | /* register specific callback point to common hdmi. */ | 1132 | /* register specific callback point to common hdmi. */ |
1088 | exynos_mixer_ops_register(&mixer_ops); | 1133 | exynos_mixer_ops_register(&mixer_ops); |