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