Merge branch 'master' of git://openpandora.org/openpandora.oe
[openpandora.oe.git] / recipes / linux / omap3-pandora-kernel / mru-improve-pixclock-config.diff
1 From: Mans Rullgard <mans@mansr.com>
2 Date: Fri, 29 Aug 2008 01:34:39 +0000 (+0100)
3 Subject: OMAP: Improve pixel clock configuration
4 X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=01c2d720e59c291de9eb21eb65225f2f215fef84
5
6 OMAP: Improve pixel clock configuration
7
8 This sets the DSS1_ALWON_FCLK clock as close as possible to a
9 multiple of the requested pixel clock, while keeping it below
10 the 173MHz limit.
11
12 Due to of the structure of the clock tree, dss1_alwon_fck cannot
13 be set directly, and we must use dpll4_m4_ck instead.
14
15 Signed-off-by: Mans Rullgard <mans@mansr.com>
16 ---
17
18 diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
19 index 64bf333..888d2c2 100644
20 --- a/drivers/video/omap/dispc.c
21 +++ b/drivers/video/omap/dispc.c
22 @@ -177,6 +177,7 @@ static struct {
23  
24         struct clk      *dss_ick, *dss1_fck;
25         struct clk      *dss_54m_fck;
26 +       struct clk      *dpll4_m4_ck;
27  
28         enum omapfb_update_mode update_mode;
29         struct omapfb_device    *fbdev;
30 @@ -736,19 +737,34 @@ static void setup_color_conv_coef(void)
31         MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range);
32  }
33  
34 +#define MAX_FCK 173000000
35 +
36  static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
37  {
38 +       unsigned long prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
39 +       unsigned long pcd_min = is_tft? 2: 3;
40 +       unsigned long fck_div;
41         unsigned long fck, lck;
42  
43 -       *lck_div = 1;
44         pck = max(1, pck);
45 +
46 +       if (pck * pcd_min > MAX_FCK) {
47 +               dev_warn(dispc.fbdev->dev, "pixclock %d kHz too high.\n",
48 +                        pck / 1000);
49 +               pck = MAX_FCK / pcd_min;
50 +       }
51 +
52 +       fck = pck * 2;
53 +       fck_div = (prate + pck) / fck;
54 +       if (fck_div > 16)
55 +               fck_div /= (fck_div + 15) / 16;
56 +       if (fck_div < 1)
57 +               fck_div = 1;
58 +       clk_set_rate(dispc.dpll4_m4_ck, prate / fck_div);
59         fck = clk_get_rate(dispc.dss1_fck);
60 -       lck = fck;
61 -       *pck_div = (lck + pck - 1) / pck;
62 -       if (is_tft)
63 -               *pck_div = max(2, *pck_div);
64 -       else
65 -               *pck_div = max(3, *pck_div);
66 +
67 +       *lck_div = 1;
68 +       *pck_div = (fck + pck - 1) / pck;
69         if (*pck_div > 255) {
70                 *pck_div = 255;
71                 lck = pck * *pck_div;
72 @@ -909,11 +925,21 @@ static int get_dss_clocks(void)
73                 return PTR_ERR(dispc.dss_54m_fck);
74         }
75  
76 +       if (IS_ERR((dispc.dpll4_m4_ck =
77 +                               clk_get(dispc.fbdev->dev, "dpll4_m4_ck")))) {
78 +               dev_err(dispc.fbdev->dev, "can't get dpll4_m4_ck");
79 +               clk_put(dispc.dss_ick);
80 +               clk_put(dispc.dss1_fck);
81 +               clk_put(dispc.dss_54m_fck);
82 +               return PTR_ERR(dispc.dss_54m_fck);
83 +       }
84 +
85         return 0;
86  }
87  
88  static void put_dss_clocks(void)
89  {
90 +       clk_put(dispc.dpll4_m4_ck);
91         clk_put(dispc.dss_54m_fck);
92         clk_put(dispc.dss1_fck);
93         clk_put(dispc.dss_ick);