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

drm/msm/mdp5: restore cursor state when enabling crtc

Since we enabled runtime PM, we cannot count on cursor registers to
retain their values. This can result in situations where we think the
cursor is enabled when we enable the CRTC but it is trying to scan out
null (and the rest of cursor position/size is lost), resulting in faults
and generally angering the hw when coming out of DPMS with a cursor
enabled.

stable backport note: reverting 774e39ee3572 is also a suitable fix

Fixes: 774e39ee3572 drm/msm/mdp5: Set up runtime PM for MDSS
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Archit Taneja <architt@codeaurora.org>

+68 -32
+68 -32
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
··· 61 61 62 62 /* current cursor being scanned out: */ 63 63 struct drm_gem_object *scanout_bo; 64 + uint64_t iova; 64 65 uint32_t width, height; 65 66 uint32_t x, y; 66 67 } cursor; 67 68 }; 68 69 #define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base) 70 + 71 + static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc); 69 72 70 73 static struct mdp5_kms *get_kms(struct drm_crtc *crtc) 71 74 { ··· 457 454 458 455 pm_runtime_get_sync(dev); 459 456 457 + /* Restore cursor state, as it might have been lost with suspend: */ 458 + if (mdp5_crtc->cursor.iova) { 459 + unsigned long flags; 460 + 461 + spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); 462 + mdp5_crtc_restore_cursor(crtc); 463 + spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); 464 + 465 + mdp5_ctl_set_cursor(mdp5_cstate->ctl, 466 + &mdp5_cstate->pipeline, 0, true); 467 + } else { 468 + mdp5_ctl_set_cursor(mdp5_cstate->ctl, 469 + &mdp5_cstate->pipeline, 0, false); 470 + } 471 + 460 472 /* Restore vblank irq handling after power is enabled */ 461 473 drm_crtc_vblank_on(crtc); 462 474 ··· 755 737 mdp5_crtc->cursor.y); 756 738 } 757 739 740 + static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc) 741 + { 742 + struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); 743 + struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); 744 + struct mdp5_kms *mdp5_kms = get_kms(crtc); 745 + const enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; 746 + uint32_t blendcfg, stride; 747 + uint32_t x, y, width, height; 748 + uint32_t roi_w, roi_h; 749 + int lm; 750 + 751 + assert_spin_locked(&mdp5_crtc->cursor.lock); 752 + 753 + lm = mdp5_cstate->pipeline.mixer->lm; 754 + 755 + x = mdp5_crtc->cursor.x; 756 + y = mdp5_crtc->cursor.y; 757 + width = mdp5_crtc->cursor.width; 758 + height = mdp5_crtc->cursor.height; 759 + 760 + stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0); 761 + 762 + get_roi(crtc, &roi_w, &roi_h); 763 + 764 + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride); 765 + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm), 766 + MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888)); 767 + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_IMG_SIZE(lm), 768 + MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) | 769 + MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width)); 770 + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), 771 + MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) | 772 + MDP5_LM_CURSOR_SIZE_ROI_W(roi_w)); 773 + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(lm), 774 + MDP5_LM_CURSOR_START_XY_Y_START(y) | 775 + MDP5_LM_CURSOR_START_XY_X_START(x)); 776 + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), 777 + mdp5_crtc->cursor.iova); 778 + 779 + blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN; 780 + blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha); 781 + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg); 782 + } 783 + 758 784 static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, 759 785 struct drm_file *file, uint32_t handle, 760 786 uint32_t width, uint32_t height) ··· 811 749 struct platform_device *pdev = mdp5_kms->pdev; 812 750 struct msm_kms *kms = &mdp5_kms->base.base; 813 751 struct drm_gem_object *cursor_bo, *old_bo = NULL; 814 - uint32_t blendcfg, stride; 815 - uint64_t cursor_addr; 816 752 struct mdp5_ctl *ctl; 817 - int ret, lm; 818 - enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; 753 + int ret; 819 754 uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); 820 - uint32_t roi_w, roi_h; 821 755 bool cursor_enable = true; 822 756 unsigned long flags; 823 757 ··· 833 775 if (!handle) { 834 776 DBG("Cursor off"); 835 777 cursor_enable = false; 778 + mdp5_crtc->cursor.iova = 0; 836 779 pm_runtime_get_sync(&pdev->dev); 837 780 goto set_cursor; 838 781 } ··· 842 783 if (!cursor_bo) 843 784 return -ENOENT; 844 785 845 - ret = msm_gem_get_iova(cursor_bo, kms->aspace, &cursor_addr); 786 + ret = msm_gem_get_iova(cursor_bo, kms->aspace, 787 + &mdp5_crtc->cursor.iova); 846 788 if (ret) 847 789 return -EINVAL; 848 - 849 - lm = mdp5_cstate->pipeline.mixer->lm; 850 - stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0); 851 790 852 791 pm_runtime_get_sync(&pdev->dev); 853 792 ··· 856 799 mdp5_crtc->cursor.width = width; 857 800 mdp5_crtc->cursor.height = height; 858 801 859 - get_roi(crtc, &roi_w, &roi_h); 860 - 861 - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride); 862 - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm), 863 - MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888)); 864 - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_IMG_SIZE(lm), 865 - MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) | 866 - MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width)); 867 - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), 868 - MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) | 869 - MDP5_LM_CURSOR_SIZE_ROI_W(roi_w)); 870 - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr); 871 - 872 - blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN; 873 - blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha); 874 - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg); 802 + mdp5_crtc_restore_cursor(crtc); 875 803 876 804 spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); 877 805 ··· 887 845 struct mdp5_kms *mdp5_kms = get_kms(crtc); 888 846 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); 889 847 struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); 890 - uint32_t lm = mdp5_cstate->pipeline.mixer->lm; 891 848 uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); 892 849 uint32_t roi_w; 893 850 uint32_t roi_h; ··· 908 867 pm_runtime_get_sync(&mdp5_kms->pdev->dev); 909 868 910 869 spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); 911 - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), 912 - MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) | 913 - MDP5_LM_CURSOR_SIZE_ROI_W(roi_w)); 914 - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(lm), 915 - MDP5_LM_CURSOR_START_XY_Y_START(y) | 916 - MDP5_LM_CURSOR_START_XY_X_START(x)); 870 + mdp5_crtc_restore_cursor(crtc); 917 871 spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); 918 872 919 873 crtc_flush(crtc, flush_mask);