Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-fixes

This pull-request fixes hdmi power-off order issue, mixer issues
related to power on/off, and includes trivial fixups.

* 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
drm/exynos: enable vsync interrupt while waiting for vblank
drm/exynos: soft reset mixer before reconfigure after power-on
drm/exynos: allow multiple layer updates per vsync for mixer
drm/exynos: stop mixer before gating clocks during poweroff
drm/exynos: set power state variable after enabling clocks and power
drm/exynos: disable unused windows on apply
drm/exynos: Fix de-registration ordering
drm/exynos: change zero to NULL for sparse
drm/exynos: dpi: Fix NULL pointer dereference with legacy bindings
drm/exynos: hdmi: fix power order issue

+63 -21
+1 -1
drivers/gpu/drm/exynos/exynos_drm_dpi.c
··· 40 40 { 41 41 struct exynos_dpi *ctx = connector_to_dpi(connector); 42 42 43 - if (!ctx->panel->connector) 43 + if (ctx->panel && !ctx->panel->connector) 44 44 drm_panel_attach(ctx->panel, &ctx->connector); 45 45 46 46 return connector_status_connected;
+4 -4
drivers/gpu/drm/exynos/exynos_drm_drv.c
··· 765 765 766 766 return 0; 767 767 768 - err_unregister_pd: 769 - platform_device_unregister(exynos_drm_pdev); 770 - 771 768 err_remove_vidi: 772 769 #ifdef CONFIG_DRM_EXYNOS_VIDI 773 770 exynos_drm_remove_vidi(); 771 + 772 + err_unregister_pd: 774 773 #endif 774 + platform_device_unregister(exynos_drm_pdev); 775 775 776 776 return ret; 777 777 } 778 778 779 779 static void exynos_drm_exit(void) 780 780 { 781 + platform_driver_unregister(&exynos_drm_platform_driver); 781 782 #ifdef CONFIG_DRM_EXYNOS_VIDI 782 783 exynos_drm_remove_vidi(); 783 784 #endif 784 785 platform_device_unregister(exynos_drm_pdev); 785 - platform_driver_unregister(&exynos_drm_platform_driver); 786 786 } 787 787 788 788 module_init(exynos_drm_init);
+1 -1
drivers/gpu/drm/exynos/exynos_drm_drv.h
··· 343 343 int exynos_dpi_remove(struct device *dev); 344 344 #else 345 345 static inline struct exynos_drm_display * 346 - exynos_dpi_probe(struct device *dev) { return 0; } 346 + exynos_dpi_probe(struct device *dev) { return NULL; } 347 347 static inline int exynos_dpi_remove(struct device *dev) { return 0; } 348 348 #endif 349 349
+2
drivers/gpu/drm/exynos/exynos_drm_fimd.c
··· 741 741 win_data = &ctx->win_data[i]; 742 742 if (win_data->enabled) 743 743 fimd_win_commit(mgr, i); 744 + else 745 + fimd_win_disable(mgr, i); 744 746 } 745 747 746 748 fimd_commit(mgr);
+19
drivers/gpu/drm/exynos/exynos_hdmi.c
··· 2090 2090 2091 2091 static void hdmi_dpms(struct exynos_drm_display *display, int mode) 2092 2092 { 2093 + struct hdmi_context *hdata = display->ctx; 2094 + struct drm_encoder *encoder = hdata->encoder; 2095 + struct drm_crtc *crtc = encoder->crtc; 2096 + struct drm_crtc_helper_funcs *funcs = NULL; 2097 + 2093 2098 DRM_DEBUG_KMS("mode %d\n", mode); 2094 2099 2095 2100 switch (mode) { ··· 2104 2099 case DRM_MODE_DPMS_STANDBY: 2105 2100 case DRM_MODE_DPMS_SUSPEND: 2106 2101 case DRM_MODE_DPMS_OFF: 2102 + /* 2103 + * The SFRs of VP and Mixer are updated by Vertical Sync of 2104 + * Timing generator which is a part of HDMI so the sequence 2105 + * to disable TV Subsystem should be as following, 2106 + * VP -> Mixer -> HDMI 2107 + * 2108 + * Below codes will try to disable Mixer and VP(if used) 2109 + * prior to disabling HDMI. 2110 + */ 2111 + if (crtc) 2112 + funcs = crtc->helper_private; 2113 + if (funcs && funcs->dpms) 2114 + (*funcs->dpms)(crtc, mode); 2115 + 2107 2116 hdmi_poweroff(display); 2108 2117 break; 2109 2118 default:
+35 -15
drivers/gpu/drm/exynos/exynos_mixer.c
··· 377 377 mixer_regs_dump(ctx); 378 378 } 379 379 380 + static void mixer_stop(struct mixer_context *ctx) 381 + { 382 + struct mixer_resources *res = &ctx->mixer_res; 383 + int timeout = 20; 384 + 385 + mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN); 386 + 387 + while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) && 388 + --timeout) 389 + usleep_range(10000, 12000); 390 + 391 + mixer_regs_dump(ctx); 392 + } 393 + 380 394 static void vp_video_buffer(struct mixer_context *ctx, int win) 381 395 { 382 396 struct mixer_resources *res = &ctx->mixer_res; ··· 511 497 static void mixer_layer_update(struct mixer_context *ctx) 512 498 { 513 499 struct mixer_resources *res = &ctx->mixer_res; 514 - u32 val; 515 500 516 - val = mixer_reg_read(res, MXR_CFG); 517 - 518 - /* allow one update per vsync only */ 519 - if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK)) 520 - mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); 501 + mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); 521 502 } 522 503 523 504 static void mixer_graph_buffer(struct mixer_context *ctx, int win) ··· 1019 1010 } 1020 1011 mutex_unlock(&mixer_ctx->mixer_mutex); 1021 1012 1013 + drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); 1014 + 1022 1015 atomic_set(&mixer_ctx->wait_vsync_event, 1); 1023 1016 1024 1017 /* ··· 1031 1020 !atomic_read(&mixer_ctx->wait_vsync_event), 1032 1021 HZ/20)) 1033 1022 DRM_DEBUG_KMS("vblank wait timed out.\n"); 1023 + 1024 + drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe); 1034 1025 } 1035 1026 1036 1027 static void mixer_window_suspend(struct exynos_drm_manager *mgr) ··· 1074 1061 mutex_unlock(&ctx->mixer_mutex); 1075 1062 return; 1076 1063 } 1077 - ctx->powered = true; 1064 + 1078 1065 mutex_unlock(&ctx->mixer_mutex); 1079 1066 1080 1067 pm_runtime_get_sync(ctx->dev); ··· 1084 1071 clk_prepare_enable(res->vp); 1085 1072 clk_prepare_enable(res->sclk_mixer); 1086 1073 } 1074 + 1075 + mutex_lock(&ctx->mixer_mutex); 1076 + ctx->powered = true; 1077 + mutex_unlock(&ctx->mixer_mutex); 1078 + 1079 + mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); 1087 1080 1088 1081 mixer_reg_write(res, MXR_INT_EN, ctx->int_en); 1089 1082 mixer_win_reset(ctx); ··· 1103 1084 struct mixer_resources *res = &ctx->mixer_res; 1104 1085 1105 1086 mutex_lock(&ctx->mixer_mutex); 1106 - if (!ctx->powered) 1107 - goto out; 1087 + if (!ctx->powered) { 1088 + mutex_unlock(&ctx->mixer_mutex); 1089 + return; 1090 + } 1108 1091 mutex_unlock(&ctx->mixer_mutex); 1109 1092 1093 + mixer_stop(ctx); 1110 1094 mixer_window_suspend(mgr); 1111 1095 1112 1096 ctx->int_en = mixer_reg_read(res, MXR_INT_EN); 1097 + 1098 + mutex_lock(&ctx->mixer_mutex); 1099 + ctx->powered = false; 1100 + mutex_unlock(&ctx->mixer_mutex); 1113 1101 1114 1102 clk_disable_unprepare(res->mixer); 1115 1103 if (ctx->vp_enabled) { ··· 1125 1099 } 1126 1100 1127 1101 pm_runtime_put_sync(ctx->dev); 1128 - 1129 - mutex_lock(&ctx->mixer_mutex); 1130 - ctx->powered = false; 1131 - 1132 - out: 1133 - mutex_unlock(&ctx->mixer_mutex); 1134 1102 } 1135 1103 1136 1104 static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
+1
drivers/gpu/drm/exynos/regs-mixer.h
··· 78 78 #define MXR_STATUS_BIG_ENDIAN (1 << 3) 79 79 #define MXR_STATUS_ENDIAN_MASK (1 << 3) 80 80 #define MXR_STATUS_SYNC_ENABLE (1 << 2) 81 + #define MXR_STATUS_REG_IDLE (1 << 1) 81 82 #define MXR_STATUS_REG_RUN (1 << 0) 82 83 83 84 /* bits for MXR_CFG */