]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.4.162/mach64-detect-the-dot-clock-divider-correctly-on-sparc.patch
Linux 4.4.162
[thirdparty/kernel/stable-queue.git] / releases / 4.4.162 / mach64-detect-the-dot-clock-divider-correctly-on-sparc.patch
1 From 76ebebd2464c5c8a4453c98b6dbf9c95a599e810 Mon Sep 17 00:00:00 2001
2 From: Mikulas Patocka <mpatocka@redhat.com>
3 Date: Fri, 17 Aug 2018 15:19:37 -0400
4 Subject: mach64: detect the dot clock divider correctly on sparc
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 From: Mikulas Patocka <mpatocka@redhat.com>
10
11 commit 76ebebd2464c5c8a4453c98b6dbf9c95a599e810 upstream.
12
13 On Sun Ultra 5, it happens that the dot clock is not set up properly for
14 some videomodes. For example, if we set the videomode "r1024x768x60" in
15 the firmware, Linux would incorrectly set a videomode with refresh rate
16 180Hz when booting (suprisingly, my LCD monitor can display it, although
17 display quality is very low).
18
19 The reason is this: Older mach64 cards set the divider in the register
20 VCLK_POST_DIV. The register has four 2-bit fields (the field that is
21 actually used is specified in the lowest two bits of the register
22 CLOCK_CNTL). The 2 bits select divider "1, 2, 4, 8". On newer mach64 cards,
23 there's another bit added - the top four bits of PLL_EXT_CNTL extend the
24 divider selection, so we have possible dividers "1, 2, 4, 8, 3, 5, 6, 12".
25 The Linux driver clears the top four bits of PLL_EXT_CNTL and never sets
26 them, so it can work regardless if the card supports them. However, the
27 sparc64 firmware may set these extended dividers during boot - and the
28 mach64 driver detects incorrect dot clock in this case.
29
30 This patch makes the driver read the additional divider bit from
31 PLL_EXT_CNTL and calculate the initial refresh rate properly.
32
33 Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
34 Cc: stable@vger.kernel.org
35 Acked-by: David S. Miller <davem@davemloft.net>
36 Reviewed-by: Ville Syrjälä <syrjala@sci.fi>
37 Signed-off-by: David S. Miller <davem@davemloft.net>
38 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
39
40 ---
41 drivers/video/fbdev/aty/atyfb.h | 3 ++-
42 drivers/video/fbdev/aty/atyfb_base.c | 7 ++++---
43 drivers/video/fbdev/aty/mach64_ct.c | 10 +++++-----
44 3 files changed, 11 insertions(+), 9 deletions(-)
45
46 --- a/drivers/video/fbdev/aty/atyfb.h
47 +++ b/drivers/video/fbdev/aty/atyfb.h
48 @@ -332,6 +332,8 @@ extern const struct aty_pll_ops aty_pll_
49 extern void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll);
50 extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
51
52 +extern const u8 aty_postdividers[8];
53 +
54
55 /*
56 * Hardware cursor support
57 @@ -358,7 +360,6 @@ static inline void wait_for_idle(struct
58
59 extern void aty_reset_engine(const struct atyfb_par *par);
60 extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
61 -extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
62
63 void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
64 void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
65 --- a/drivers/video/fbdev/aty/atyfb_base.c
66 +++ b/drivers/video/fbdev/aty/atyfb_base.c
67 @@ -3093,17 +3093,18 @@ static int atyfb_setup_sparc(struct pci_
68 /*
69 * PLL Reference Divider M:
70 */
71 - M = pll_regs[2];
72 + M = pll_regs[PLL_REF_DIV];
73
74 /*
75 * PLL Feedback Divider N (Dependent on CLOCK_CNTL):
76 */
77 - N = pll_regs[7 + (clock_cntl & 3)];
78 + N = pll_regs[VCLK0_FB_DIV + (clock_cntl & 3)];
79
80 /*
81 * PLL Post Divider P (Dependent on CLOCK_CNTL):
82 */
83 - P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
84 + P = aty_postdividers[((pll_regs[VCLK_POST_DIV] >> ((clock_cntl & 3) << 1)) & 3) |
85 + ((pll_regs[PLL_EXT_CNTL] >> (2 + (clock_cntl & 3))) & 4)];
86
87 /*
88 * PLL Divider Q:
89 --- a/drivers/video/fbdev/aty/mach64_ct.c
90 +++ b/drivers/video/fbdev/aty/mach64_ct.c
91 @@ -114,7 +114,7 @@ static void aty_st_pll_ct(int offset, u8
92 */
93
94 #define Maximum_DSP_PRECISION 7
95 -static u8 postdividers[] = {1,2,4,8,3};
96 +const u8 aty_postdividers[8] = {1,2,4,8,3,5,6,12};
97
98 static int aty_dsp_gt(const struct fb_info *info, u32 bpp, struct pll_ct *pll)
99 {
100 @@ -221,7 +221,7 @@ static int aty_valid_pll_ct(const struct
101 pll->vclk_post_div += (q < 64*8);
102 pll->vclk_post_div += (q < 32*8);
103 }
104 - pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
105 + pll->vclk_post_div_real = aty_postdividers[pll->vclk_post_div];
106 // pll->vclk_post_div <<= 6;
107 pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
108 pllvclk = (1000000 * 2 * pll->vclk_fb_div) /
109 @@ -512,7 +512,7 @@ static int aty_init_pll_ct(const struct
110 u8 mclk_fb_div, pll_ext_cntl;
111 pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
112 pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
113 - pll->ct.xclk_post_div_real = postdividers[pll_ext_cntl & 0x07];
114 + pll->ct.xclk_post_div_real = aty_postdividers[pll_ext_cntl & 0x07];
115 mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
116 if (pll_ext_cntl & PLL_MFB_TIMES_4_2B)
117 mclk_fb_div <<= 1;
118 @@ -534,7 +534,7 @@ static int aty_init_pll_ct(const struct
119 xpost_div += (q < 64*8);
120 xpost_div += (q < 32*8);
121 }
122 - pll->ct.xclk_post_div_real = postdividers[xpost_div];
123 + pll->ct.xclk_post_div_real = aty_postdividers[xpost_div];
124 pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8;
125
126 #ifdef CONFIG_PPC
127 @@ -583,7 +583,7 @@ static int aty_init_pll_ct(const struct
128 mpost_div += (q < 64*8);
129 mpost_div += (q < 32*8);
130 }
131 - sclk_post_div_real = postdividers[mpost_div];
132 + sclk_post_div_real = aty_postdividers[mpost_div];
133 pll->ct.sclk_fb_div = q * sclk_post_div_real / 8;
134 pll->ct.spll_cntl2 = mpost_div << 4;
135 #ifdef DEBUG