fbdev: sm712fb: fix crashes and garbled display during DPMS modesetting
On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), blanking the display or starting the X server will crash and freeze the system, or garble the display. Experiments showed this problem can mostly be solved by adjusting the order of register writes. Also, sm712fb failed to consider the difference of clock frequency when unblanking the display, and programs the clock for SM712 to SM720. Fix them by adjusting the order of register writes, and adding an additional check for SM720 for programming the clock frequency. Signed-off-by: Yifeng Li <tomli@tomli.me> Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Cc: Teddy Wang <teddy.wang@siliconmotion.com> Cc: <stable@vger.kernel.org> # v4.4+ Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
This commit is contained in:
parent
9e0e59993d
commit
f627caf55b
@ -827,67 +827,79 @@ static inline unsigned int chan_to_field(unsigned int chan,
|
|||||||
|
|
||||||
static int smtc_blank(int blank_mode, struct fb_info *info)
|
static int smtc_blank(int blank_mode, struct fb_info *info)
|
||||||
{
|
{
|
||||||
|
struct smtcfb_info *sfb = info->par;
|
||||||
|
|
||||||
/* clear DPMS setting */
|
/* clear DPMS setting */
|
||||||
switch (blank_mode) {
|
switch (blank_mode) {
|
||||||
case FB_BLANK_UNBLANK:
|
case FB_BLANK_UNBLANK:
|
||||||
/* Screen On: HSync: On, VSync : On */
|
/* Screen On: HSync: On, VSync : On */
|
||||||
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
|
|
||||||
|
switch (sfb->chip_id) {
|
||||||
|
case 0x710:
|
||||||
|
case 0x712:
|
||||||
smtc_seqw(0x6a, 0x16);
|
smtc_seqw(0x6a, 0x16);
|
||||||
smtc_seqw(0x6b, 0x02);
|
smtc_seqw(0x6b, 0x02);
|
||||||
|
case 0x720:
|
||||||
|
smtc_seqw(0x6a, 0x0d);
|
||||||
|
smtc_seqw(0x6b, 0x02);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
|
||||||
|
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
|
||||||
smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
|
smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
|
||||||
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
|
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
|
||||||
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
|
|
||||||
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
|
|
||||||
smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
|
smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
|
||||||
|
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
|
||||||
break;
|
break;
|
||||||
case FB_BLANK_NORMAL:
|
case FB_BLANK_NORMAL:
|
||||||
/* Screen Off: HSync: On, VSync : On Soft blank */
|
/* Screen Off: HSync: On, VSync : On Soft blank */
|
||||||
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
|
|
||||||
smtc_seqw(0x6a, 0x16);
|
|
||||||
smtc_seqw(0x6b, 0x02);
|
|
||||||
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
|
|
||||||
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
|
|
||||||
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
|
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
|
||||||
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
||||||
|
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
|
||||||
|
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
|
||||||
|
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
|
||||||
|
smtc_seqw(0x6a, 0x16);
|
||||||
|
smtc_seqw(0x6b, 0x02);
|
||||||
break;
|
break;
|
||||||
case FB_BLANK_VSYNC_SUSPEND:
|
case FB_BLANK_VSYNC_SUSPEND:
|
||||||
/* Screen On: HSync: On, VSync : Off */
|
/* Screen On: HSync: On, VSync : Off */
|
||||||
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
|
||||||
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
|
||||||
smtc_seqw(0x6a, 0x0c);
|
|
||||||
smtc_seqw(0x6b, 0x02);
|
|
||||||
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
|
||||||
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
|
|
||||||
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
|
|
||||||
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
||||||
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
||||||
|
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
|
||||||
|
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
||||||
|
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
||||||
|
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
||||||
|
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
|
||||||
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
||||||
|
smtc_seqw(0x6a, 0x0c);
|
||||||
|
smtc_seqw(0x6b, 0x02);
|
||||||
break;
|
break;
|
||||||
case FB_BLANK_HSYNC_SUSPEND:
|
case FB_BLANK_HSYNC_SUSPEND:
|
||||||
/* Screen On: HSync: Off, VSync : On */
|
/* Screen On: HSync: Off, VSync : On */
|
||||||
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
|
||||||
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
|
||||||
smtc_seqw(0x6a, 0x0c);
|
|
||||||
smtc_seqw(0x6b, 0x02);
|
|
||||||
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
|
||||||
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
|
|
||||||
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
|
|
||||||
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
||||||
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
||||||
|
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
|
||||||
|
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
||||||
|
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
||||||
|
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
||||||
|
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
|
||||||
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
||||||
|
smtc_seqw(0x6a, 0x0c);
|
||||||
|
smtc_seqw(0x6b, 0x02);
|
||||||
break;
|
break;
|
||||||
case FB_BLANK_POWERDOWN:
|
case FB_BLANK_POWERDOWN:
|
||||||
/* Screen On: HSync: Off, VSync : Off */
|
/* Screen On: HSync: Off, VSync : Off */
|
||||||
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
|
||||||
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
|
||||||
smtc_seqw(0x6a, 0x0c);
|
|
||||||
smtc_seqw(0x6b, 0x02);
|
|
||||||
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
|
||||||
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
|
|
||||||
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
|
|
||||||
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
||||||
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
||||||
|
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
|
||||||
|
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
||||||
|
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
||||||
|
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
||||||
|
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
|
||||||
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
||||||
|
smtc_seqw(0x6a, 0x0c);
|
||||||
|
smtc_seqw(0x6b, 0x02);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
Loading…
Reference in New Issue
Block a user