aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_fimd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fimd.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c121
1 files changed, 58 insertions, 63 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index f67f11c702ca..9acd6890a3d6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -157,9 +157,9 @@ struct fimd_win_data {
157}; 157};
158 158
159struct fimd_context { 159struct fimd_context {
160 struct exynos_drm_manager manager;
161 struct device *dev; 160 struct device *dev;
162 struct drm_device *drm_dev; 161 struct drm_device *drm_dev;
162 struct exynos_drm_crtc *crtc;
163 struct clk *bus_clk; 163 struct clk *bus_clk;
164 struct clk *lcd_clk; 164 struct clk *lcd_clk;
165 void __iomem *regs; 165 void __iomem *regs;
@@ -185,11 +185,6 @@ struct fimd_context {
185 struct exynos_drm_display *display; 185 struct exynos_drm_display *display;
186}; 186};
187 187
188static inline struct fimd_context *mgr_to_fimd(struct exynos_drm_manager *mgr)
189{
190 return container_of(mgr, struct fimd_context, manager);
191}
192
193static const struct of_device_id fimd_driver_dt_match[] = { 188static const struct of_device_id fimd_driver_dt_match[] = {
194 { .compatible = "samsung,s3c6400-fimd", 189 { .compatible = "samsung,s3c6400-fimd",
195 .data = &s3c64xx_fimd_driver_data }, 190 .data = &s3c64xx_fimd_driver_data },
@@ -214,9 +209,9 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
214 return (struct fimd_driver_data *)of_id->data; 209 return (struct fimd_driver_data *)of_id->data;
215} 210}
216 211
217static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr) 212static void fimd_wait_for_vblank(struct exynos_drm_crtc *crtc)
218{ 213{
219 struct fimd_context *ctx = mgr_to_fimd(mgr); 214 struct fimd_context *ctx = crtc->ctx;
220 215
221 if (ctx->suspended) 216 if (ctx->suspended)
222 return; 217 return;
@@ -259,9 +254,9 @@ static void fimd_enable_shadow_channel_path(struct fimd_context *ctx, int win,
259 writel(val, ctx->regs + SHADOWCON); 254 writel(val, ctx->regs + SHADOWCON);
260} 255}
261 256
262static void fimd_clear_channel(struct exynos_drm_manager *mgr) 257static void fimd_clear_channel(struct exynos_drm_crtc *crtc)
263{ 258{
264 struct fimd_context *ctx = mgr_to_fimd(mgr); 259 struct fimd_context *ctx = crtc->ctx;
265 int win, ch_enabled = 0; 260 int win, ch_enabled = 0;
266 261
267 DRM_DEBUG_KMS("%s\n", __FILE__); 262 DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -286,15 +281,14 @@ static void fimd_clear_channel(struct exynos_drm_manager *mgr)
286 unsigned int state = ctx->suspended; 281 unsigned int state = ctx->suspended;
287 282
288 ctx->suspended = 0; 283 ctx->suspended = 0;
289 fimd_wait_for_vblank(mgr); 284 fimd_wait_for_vblank(crtc);
290 ctx->suspended = state; 285 ctx->suspended = state;
291 } 286 }
292} 287}
293 288
294static int fimd_mgr_initialize(struct exynos_drm_manager *mgr, 289static int fimd_ctx_initialize(struct fimd_context *ctx,
295 struct drm_device *drm_dev) 290 struct drm_device *drm_dev)
296{ 291{
297 struct fimd_context *ctx = mgr_to_fimd(mgr);
298 struct exynos_drm_private *priv; 292 struct exynos_drm_private *priv;
299 priv = drm_dev->dev_private; 293 priv = drm_dev->dev_private;
300 294
@@ -307,17 +301,15 @@ static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
307 * If any channel is already active, iommu will throw 301 * If any channel is already active, iommu will throw
308 * a PAGE FAULT when enabled. So clear any channel if enabled. 302 * a PAGE FAULT when enabled. So clear any channel if enabled.
309 */ 303 */
310 fimd_clear_channel(mgr); 304 fimd_clear_channel(ctx->crtc);
311 drm_iommu_attach_device(ctx->drm_dev, ctx->dev); 305 drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
312 } 306 }
313 307
314 return 0; 308 return 0;
315} 309}
316 310
317static void fimd_mgr_remove(struct exynos_drm_manager *mgr) 311static void fimd_ctx_remove(struct fimd_context *ctx)
318{ 312{
319 struct fimd_context *ctx = mgr_to_fimd(mgr);
320
321 /* detach this sub driver from iommu mapping if supported. */ 313 /* detach this sub driver from iommu mapping if supported. */
322 if (is_drm_iommu_supported(ctx->drm_dev)) 314 if (is_drm_iommu_supported(ctx->drm_dev))
323 drm_iommu_detach_device(ctx->drm_dev, ctx->dev); 315 drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
@@ -343,7 +335,7 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
343 return (clkdiv < 0x100) ? clkdiv : 0xff; 335 return (clkdiv < 0x100) ? clkdiv : 0xff;
344} 336}
345 337
346static bool fimd_mode_fixup(struct exynos_drm_manager *mgr, 338static bool fimd_mode_fixup(struct exynos_drm_crtc *crtc,
347 const struct drm_display_mode *mode, 339 const struct drm_display_mode *mode,
348 struct drm_display_mode *adjusted_mode) 340 struct drm_display_mode *adjusted_mode)
349{ 341{
@@ -353,17 +345,17 @@ static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
353 return true; 345 return true;
354} 346}
355 347
356static void fimd_mode_set(struct exynos_drm_manager *mgr, 348static void fimd_mode_set(struct exynos_drm_crtc *crtc,
357 const struct drm_display_mode *in_mode) 349 const struct drm_display_mode *in_mode)
358{ 350{
359 struct fimd_context *ctx = mgr_to_fimd(mgr); 351 struct fimd_context *ctx = crtc->ctx;
360 352
361 drm_mode_copy(&ctx->mode, in_mode); 353 drm_mode_copy(&ctx->mode, in_mode);
362} 354}
363 355
364static void fimd_commit(struct exynos_drm_manager *mgr) 356static void fimd_commit(struct exynos_drm_crtc *crtc)
365{ 357{
366 struct fimd_context *ctx = mgr_to_fimd(mgr); 358 struct fimd_context *ctx = crtc->ctx;
367 struct drm_display_mode *mode = &ctx->mode; 359 struct drm_display_mode *mode = &ctx->mode;
368 struct fimd_driver_data *driver_data = ctx->driver_data; 360 struct fimd_driver_data *driver_data = ctx->driver_data;
369 void *timing_base = ctx->regs + driver_data->timing_base; 361 void *timing_base = ctx->regs + driver_data->timing_base;
@@ -461,9 +453,9 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
461 writel(val, ctx->regs + VIDCON0); 453 writel(val, ctx->regs + VIDCON0);
462} 454}
463 455
464static int fimd_enable_vblank(struct exynos_drm_manager *mgr) 456static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
465{ 457{
466 struct fimd_context *ctx = mgr_to_fimd(mgr); 458 struct fimd_context *ctx = crtc->ctx;
467 u32 val; 459 u32 val;
468 460
469 if (ctx->suspended) 461 if (ctx->suspended)
@@ -493,9 +485,9 @@ static int fimd_enable_vblank(struct exynos_drm_manager *mgr)
493 return 0; 485 return 0;
494} 486}
495 487
496static void fimd_disable_vblank(struct exynos_drm_manager *mgr) 488static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
497{ 489{
498 struct fimd_context *ctx = mgr_to_fimd(mgr); 490 struct fimd_context *ctx = crtc->ctx;
499 u32 val; 491 u32 val;
500 492
501 if (ctx->suspended) 493 if (ctx->suspended)
@@ -517,10 +509,10 @@ static void fimd_disable_vblank(struct exynos_drm_manager *mgr)
517 } 509 }
518} 510}
519 511
520static void fimd_win_mode_set(struct exynos_drm_manager *mgr, 512static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
521 struct exynos_drm_plane *plane) 513 struct exynos_drm_plane *plane)
522{ 514{
523 struct fimd_context *ctx = mgr_to_fimd(mgr); 515 struct fimd_context *ctx = crtc->ctx;
524 struct fimd_win_data *win_data; 516 struct fimd_win_data *win_data;
525 int win; 517 int win;
526 unsigned long offset; 518 unsigned long offset;
@@ -676,9 +668,9 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
676 writel(val, ctx->regs + reg); 668 writel(val, ctx->regs + reg);
677} 669}
678 670
679static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos) 671static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
680{ 672{
681 struct fimd_context *ctx = mgr_to_fimd(mgr); 673 struct fimd_context *ctx = crtc->ctx;
682 struct fimd_win_data *win_data; 674 struct fimd_win_data *win_data;
683 int win = zpos; 675 int win = zpos;
684 unsigned long val, alpha, size; 676 unsigned long val, alpha, size;
@@ -799,9 +791,9 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
799 atomic_set(&ctx->win_updated, 1); 791 atomic_set(&ctx->win_updated, 1);
800} 792}
801 793
802static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos) 794static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
803{ 795{
804 struct fimd_context *ctx = mgr_to_fimd(mgr); 796 struct fimd_context *ctx = crtc->ctx;
805 struct fimd_win_data *win_data; 797 struct fimd_win_data *win_data;
806 int win = zpos; 798 int win = zpos;
807 799
@@ -833,9 +825,9 @@ static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
833 win_data->enabled = false; 825 win_data->enabled = false;
834} 826}
835 827
836static void fimd_window_suspend(struct exynos_drm_manager *mgr) 828static void fimd_window_suspend(struct exynos_drm_crtc *crtc)
837{ 829{
838 struct fimd_context *ctx = mgr_to_fimd(mgr); 830 struct fimd_context *ctx = crtc->ctx;
839 struct fimd_win_data *win_data; 831 struct fimd_win_data *win_data;
840 int i; 832 int i;
841 833
@@ -843,13 +835,13 @@ static void fimd_window_suspend(struct exynos_drm_manager *mgr)
843 win_data = &ctx->win_data[i]; 835 win_data = &ctx->win_data[i];
844 win_data->resume = win_data->enabled; 836 win_data->resume = win_data->enabled;
845 if (win_data->enabled) 837 if (win_data->enabled)
846 fimd_win_disable(mgr, i); 838 fimd_win_disable(crtc, i);
847 } 839 }
848} 840}
849 841
850static void fimd_window_resume(struct exynos_drm_manager *mgr) 842static void fimd_window_resume(struct exynos_drm_crtc *crtc)
851{ 843{
852 struct fimd_context *ctx = mgr_to_fimd(mgr); 844 struct fimd_context *ctx = crtc->ctx;
853 struct fimd_win_data *win_data; 845 struct fimd_win_data *win_data;
854 int i; 846 int i;
855 847
@@ -860,26 +852,26 @@ static void fimd_window_resume(struct exynos_drm_manager *mgr)
860 } 852 }
861} 853}
862 854
863static void fimd_apply(struct exynos_drm_manager *mgr) 855static void fimd_apply(struct exynos_drm_crtc *crtc)
864{ 856{
865 struct fimd_context *ctx = mgr_to_fimd(mgr); 857 struct fimd_context *ctx = crtc->ctx;
866 struct fimd_win_data *win_data; 858 struct fimd_win_data *win_data;
867 int i; 859 int i;
868 860
869 for (i = 0; i < WINDOWS_NR; i++) { 861 for (i = 0; i < WINDOWS_NR; i++) {
870 win_data = &ctx->win_data[i]; 862 win_data = &ctx->win_data[i];
871 if (win_data->enabled) 863 if (win_data->enabled)
872 fimd_win_commit(mgr, i); 864 fimd_win_commit(crtc, i);
873 else 865 else
874 fimd_win_disable(mgr, i); 866 fimd_win_disable(crtc, i);
875 } 867 }
876 868
877 fimd_commit(mgr); 869 fimd_commit(crtc);
878} 870}
879 871
880static int fimd_poweron(struct exynos_drm_manager *mgr) 872static int fimd_poweron(struct exynos_drm_crtc *crtc)
881{ 873{
882 struct fimd_context *ctx = mgr_to_fimd(mgr); 874 struct fimd_context *ctx = crtc->ctx;
883 int ret; 875 int ret;
884 876
885 if (!ctx->suspended) 877 if (!ctx->suspended)
@@ -903,16 +895,16 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
903 895
904 /* if vblank was enabled status, enable it again. */ 896 /* if vblank was enabled status, enable it again. */
905 if (test_and_clear_bit(0, &ctx->irq_flags)) { 897 if (test_and_clear_bit(0, &ctx->irq_flags)) {
906 ret = fimd_enable_vblank(mgr); 898 ret = fimd_enable_vblank(crtc);
907 if (ret) { 899 if (ret) {
908 DRM_ERROR("Failed to re-enable vblank [%d]\n", ret); 900 DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
909 goto enable_vblank_err; 901 goto enable_vblank_err;
910 } 902 }
911 } 903 }
912 904
913 fimd_window_resume(mgr); 905 fimd_window_resume(crtc);
914 906
915 fimd_apply(mgr); 907 fimd_apply(crtc);
916 908
917 return 0; 909 return 0;
918 910
@@ -925,9 +917,9 @@ bus_clk_err:
925 return ret; 917 return ret;
926} 918}
927 919
928static int fimd_poweroff(struct exynos_drm_manager *mgr) 920static int fimd_poweroff(struct exynos_drm_crtc *crtc)
929{ 921{
930 struct fimd_context *ctx = mgr_to_fimd(mgr); 922 struct fimd_context *ctx = crtc->ctx;
931 923
932 if (ctx->suspended) 924 if (ctx->suspended)
933 return 0; 925 return 0;
@@ -937,7 +929,7 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
937 * suspend that connector. Otherwise we might try to scan from 929 * suspend that connector. Otherwise we might try to scan from
938 * a destroyed buffer later. 930 * a destroyed buffer later.
939 */ 931 */
940 fimd_window_suspend(mgr); 932 fimd_window_suspend(crtc);
941 933
942 clk_disable_unprepare(ctx->lcd_clk); 934 clk_disable_unprepare(ctx->lcd_clk);
943 clk_disable_unprepare(ctx->bus_clk); 935 clk_disable_unprepare(ctx->bus_clk);
@@ -948,18 +940,18 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
948 return 0; 940 return 0;
949} 941}
950 942
951static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) 943static void fimd_dpms(struct exynos_drm_crtc *crtc, int mode)
952{ 944{
953 DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode); 945 DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
954 946
955 switch (mode) { 947 switch (mode) {
956 case DRM_MODE_DPMS_ON: 948 case DRM_MODE_DPMS_ON:
957 fimd_poweron(mgr); 949 fimd_poweron(crtc);
958 break; 950 break;
959 case DRM_MODE_DPMS_STANDBY: 951 case DRM_MODE_DPMS_STANDBY:
960 case DRM_MODE_DPMS_SUSPEND: 952 case DRM_MODE_DPMS_SUSPEND:
961 case DRM_MODE_DPMS_OFF: 953 case DRM_MODE_DPMS_OFF:
962 fimd_poweroff(mgr); 954 fimd_poweroff(crtc);
963 break; 955 break;
964 default: 956 default:
965 DRM_DEBUG_KMS("unspecified mode %d\n", mode); 957 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -996,9 +988,9 @@ static void fimd_trigger(struct device *dev)
996 atomic_set(&ctx->triggering, 0); 988 atomic_set(&ctx->triggering, 0);
997} 989}
998 990
999static void fimd_te_handler(struct exynos_drm_manager *mgr) 991static void fimd_te_handler(struct exynos_drm_crtc *crtc)
1000{ 992{
1001 struct fimd_context *ctx = mgr_to_fimd(mgr); 993 struct fimd_context *ctx = crtc->ctx;
1002 994
1003 /* Checks the crtc is detached already from encoder */ 995 /* Checks the crtc is detached already from encoder */
1004 if (ctx->pipe < 0 || !ctx->drm_dev) 996 if (ctx->pipe < 0 || !ctx->drm_dev)
@@ -1021,7 +1013,7 @@ static void fimd_te_handler(struct exynos_drm_manager *mgr)
1021 drm_handle_vblank(ctx->drm_dev, ctx->pipe); 1013 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
1022} 1014}
1023 1015
1024static struct exynos_drm_manager_ops fimd_manager_ops = { 1016static struct exynos_drm_crtc_ops fimd_crtc_ops = {
1025 .dpms = fimd_dpms, 1017 .dpms = fimd_dpms,
1026 .mode_fixup = fimd_mode_fixup, 1018 .mode_fixup = fimd_mode_fixup,
1027 .mode_set = fimd_mode_set, 1019 .mode_set = fimd_mode_set,
@@ -1075,9 +1067,14 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
1075 struct fimd_context *ctx = dev_get_drvdata(dev); 1067 struct fimd_context *ctx = dev_get_drvdata(dev);
1076 struct drm_device *drm_dev = data; 1068 struct drm_device *drm_dev = data;
1077 1069
1078 fimd_mgr_initialize(&ctx->manager, drm_dev); 1070 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
1079 exynos_drm_crtc_create(&ctx->manager, drm_dev, ctx->pipe, 1071 EXYNOS_DISPLAY_TYPE_LCD,
1080 EXYNOS_DISPLAY_TYPE_LCD); 1072 &fimd_crtc_ops, ctx);
1073 if (IS_ERR(ctx->crtc))
1074 return PTR_ERR(ctx->crtc);
1075
1076 fimd_ctx_initialize(ctx, drm_dev);
1077
1081 if (ctx->display) 1078 if (ctx->display)
1082 exynos_drm_create_enc_conn(drm_dev, ctx->display); 1079 exynos_drm_create_enc_conn(drm_dev, ctx->display);
1083 1080
@@ -1090,12 +1087,12 @@ static void fimd_unbind(struct device *dev, struct device *master,
1090{ 1087{
1091 struct fimd_context *ctx = dev_get_drvdata(dev); 1088 struct fimd_context *ctx = dev_get_drvdata(dev);
1092 1089
1093 fimd_dpms(&ctx->manager, DRM_MODE_DPMS_OFF); 1090 fimd_dpms(ctx->crtc, DRM_MODE_DPMS_OFF);
1094 1091
1095 if (ctx->display) 1092 if (ctx->display)
1096 exynos_dpi_remove(ctx->display); 1093 exynos_dpi_remove(ctx->display);
1097 1094
1098 fimd_mgr_remove(&ctx->manager); 1095 fimd_ctx_remove(ctx);
1099} 1096}
1100 1097
1101static const struct component_ops fimd_component_ops = { 1098static const struct component_ops fimd_component_ops = {
@@ -1118,8 +1115,6 @@ static int fimd_probe(struct platform_device *pdev)
1118 if (!ctx) 1115 if (!ctx)
1119 return -ENOMEM; 1116 return -ENOMEM;
1120 1117
1121 ctx->manager.ops = &fimd_manager_ops;
1122
1123 ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CRTC, 1118 ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CRTC,
1124 EXYNOS_DISPLAY_TYPE_LCD); 1119 EXYNOS_DISPLAY_TYPE_LCD);
1125 if (ret) 1120 if (ret)