1 From f627caf55b8e735dcec8fa6538e9668632b55276 Mon Sep 17 00:00:00 2001
2 From: Yifeng Li <tomli@tomli.me>
3 Date: Mon, 1 Apr 2019 17:46:59 +0200
4 Subject: fbdev: sm712fb: fix crashes and garbled display during DPMS modesetting
6 From: Yifeng Li <tomli@tomli.me>
8 commit f627caf55b8e735dcec8fa6538e9668632b55276 upstream.
10 On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), blanking the display
11 or starting the X server will crash and freeze the system, or garble the
14 Experiments showed this problem can mostly be solved by adjusting the
15 order of register writes. Also, sm712fb failed to consider the difference
16 of clock frequency when unblanking the display, and programs the clock for
19 Fix them by adjusting the order of register writes, and adding an
20 additional check for SM720 for programming the clock frequency.
22 Signed-off-by: Yifeng Li <tomli@tomli.me>
23 Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
24 Cc: Teddy Wang <teddy.wang@siliconmotion.com>
25 Cc: <stable@vger.kernel.org> # v4.4+
26 Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
27 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
30 drivers/video/fbdev/sm712fb.c | 64 ++++++++++++++++++++++++------------------
31 1 file changed, 38 insertions(+), 26 deletions(-)
33 --- a/drivers/video/fbdev/sm712fb.c
34 +++ b/drivers/video/fbdev/sm712fb.c
35 @@ -886,67 +886,79 @@ static inline unsigned int chan_to_field
37 static int smtc_blank(int blank_mode, struct fb_info *info)
39 + struct smtcfb_info *sfb = info->par;
41 /* clear DPMS setting */
43 case FB_BLANK_UNBLANK:
44 /* Screen On: HSync: On, VSync : On */
46 + switch (sfb->chip_id) {
49 + smtc_seqw(0x6a, 0x16);
50 + smtc_seqw(0x6b, 0x02);
52 + smtc_seqw(0x6a, 0x0d);
53 + smtc_seqw(0x6b, 0x02);
57 + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
58 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
59 - smtc_seqw(0x6a, 0x16);
60 - smtc_seqw(0x6b, 0x02);
61 smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
62 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
63 - smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
64 - smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
65 smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
66 + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
69 /* Screen Off: HSync: On, VSync : On Soft blank */
70 + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
71 + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
72 + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
73 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
74 + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
75 smtc_seqw(0x6a, 0x16);
76 smtc_seqw(0x6b, 0x02);
77 - smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
78 - smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
79 - smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
80 - smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
82 case FB_BLANK_VSYNC_SUSPEND:
83 /* Screen On: HSync: On, VSync : Off */
84 + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
85 + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
86 + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
87 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
88 - smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
89 - smtc_seqw(0x6a, 0x0c);
90 - smtc_seqw(0x6b, 0x02);
91 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
92 + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
93 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
94 - smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
95 - smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
96 - smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
97 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
98 + smtc_seqw(0x6a, 0x0c);
99 + smtc_seqw(0x6b, 0x02);
101 case FB_BLANK_HSYNC_SUSPEND:
102 /* Screen On: HSync: Off, VSync : On */
103 + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
104 + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
105 + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
106 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
107 - smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
108 - smtc_seqw(0x6a, 0x0c);
109 - smtc_seqw(0x6b, 0x02);
110 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
111 + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
112 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
113 - smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
114 - smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
115 - smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
116 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
117 + smtc_seqw(0x6a, 0x0c);
118 + smtc_seqw(0x6b, 0x02);
120 case FB_BLANK_POWERDOWN:
121 /* Screen On: HSync: Off, VSync : Off */
122 + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
123 + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
124 + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
125 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
126 - smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
127 - smtc_seqw(0x6a, 0x0c);
128 - smtc_seqw(0x6b, 0x02);
129 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
130 + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
131 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
132 - smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
133 - smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
134 - smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
135 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
136 + smtc_seqw(0x6a, 0x0c);
137 + smtc_seqw(0x6b, 0x02);