]>
Commit | Line | Data |
---|---|---|
53722911 GKH |
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 | |
5 | ||
6 | From: Yifeng Li <tomli@tomli.me> | |
7 | ||
8 | commit f627caf55b8e735dcec8fa6538e9668632b55276 upstream. | |
9 | ||
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 | |
12 | display. | |
13 | ||
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 | |
17 | SM712 to SM720. | |
18 | ||
19 | Fix them by adjusting the order of register writes, and adding an | |
20 | additional check for SM720 for programming the clock frequency. | |
21 | ||
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> | |
28 | ||
29 | --- | |
30 | drivers/video/fbdev/sm712fb.c | 64 ++++++++++++++++++++++++------------------ | |
31 | 1 file changed, 38 insertions(+), 26 deletions(-) | |
32 | ||
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 | |
36 | ||
37 | static int smtc_blank(int blank_mode, struct fb_info *info) | |
38 | { | |
39 | + struct smtcfb_info *sfb = info->par; | |
40 | + | |
41 | /* clear DPMS setting */ | |
42 | switch (blank_mode) { | |
43 | case FB_BLANK_UNBLANK: | |
44 | /* Screen On: HSync: On, VSync : On */ | |
45 | + | |
46 | + switch (sfb->chip_id) { | |
47 | + case 0x710: | |
48 | + case 0x712: | |
49 | + smtc_seqw(0x6a, 0x16); | |
50 | + smtc_seqw(0x6b, 0x02); | |
51 | + case 0x720: | |
52 | + smtc_seqw(0x6a, 0x0d); | |
53 | + smtc_seqw(0x6b, 0x02); | |
54 | + break; | |
55 | + } | |
56 | + | |
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)); | |
67 | break; | |
68 | case FB_BLANK_NORMAL: | |
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)); | |
81 | break; | |
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); | |
100 | break; | |
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); | |
119 | break; | |
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); | |
138 | break; | |
139 | default: | |
140 | return -EINVAL; |