summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-omap-pm/dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch
blob: daa95ca50d8f0efb8b7351b9af837ca14b268662 (plain)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
From 67f3fc050ab4e2006d5b7ec6ec341896627181ab Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Mon, 6 Apr 2009 17:32:04 +0200
Subject: [PATCH] DSS2: Check fclk limits when configuring video planes
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Check that the currect functional clock is fast enough to support
the requested scaling ratios. Also check if 5-tap filtering can be
used even though the downscaling ratio is less than 1:2 since the
functional clock rate required for 5-tap filtering can be less than
the requirement for 3-tap filtering, and 5-tap filtering should look
better.

Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
---
 drivers/video/omap2/dss/dispc.c |  104 ++++++++++++++++++++++++++++++++++++---
 1 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 41734f3..61861d8 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1026,11 +1026,11 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
 static void _dispc_set_scaling(enum omap_plane plane,
 		u16 orig_width, u16 orig_height,
 		u16 out_width, u16 out_height,
-		bool ilace)
+		bool ilace, bool five_taps)
 {
 	int fir_hinc;
 	int fir_vinc;
-	int hscaleup, vscaleup, five_taps;
+	int hscaleup, vscaleup;
 	int fieldmode = 0;
 	int accu0 = 0;
 	int accu1 = 0;
@@ -1040,7 +1040,6 @@ static void _dispc_set_scaling(enum omap_plane plane,
 
 	hscaleup = orig_width <= out_width;
 	vscaleup = orig_height <= out_height;
-	five_taps = orig_height > out_height * 2;
 
 	_dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
 
@@ -1283,6 +1282,73 @@ static void calc_rotation_offset(u8 rotation, bool mirror,
 	}
 }
 
+static unsigned long calc_fclk_five_taps(u16 width, u16 height,
+		u16 out_width, u16 out_height, enum omap_color_mode color_mode)
+{
+	u32 fclk = 0;
+	/* FIXME venc pclk? */
+	u64 tmp, pclk = dispc_pclk_rate();
+
+	if (height > out_height) {
+		/* FIXME get real display PPL */
+		unsigned int ppl = 800;
+
+		tmp = pclk * height * out_width;
+		do_div(tmp, 2 * out_height * ppl);
+		fclk = tmp;
+
+		if (height > 2 * out_height) {
+			tmp = pclk * (height - 2 * out_height) * out_width;
+			do_div(tmp, 2 * out_height * (ppl - out_width));
+			fclk = max(fclk, (u32) tmp);
+		}
+	}
+
+	if (width > out_width) {
+		tmp = pclk * width;
+		do_div(tmp, out_width);
+		fclk = max(fclk, (u32) tmp);
+
+		if (color_mode == OMAP_DSS_COLOR_RGB24U)
+			fclk <<= 1;
+	}
+
+	return fclk;
+}
+
+static unsigned long calc_fclk(u16 width, u16 height,
+		u16 out_width, u16 out_height,
+		enum omap_color_mode color_mode, bool five_taps)
+{
+	unsigned int hf, vf;
+
+	if (five_taps)
+		return calc_fclk_five_taps(width, height,
+				out_width, out_height, color_mode);
+
+	/*
+	 * FIXME how to determine the 'A' factor
+	 * for the no downscaling case ?
+	 */
+
+	if (width > 3 * out_width)
+		hf = 4;
+	else if (width > 2 * out_width)
+		hf = 3;
+	else if (width > out_width)
+		hf = 2;
+	else
+		hf = 1;
+
+	if (height > out_height)
+		vf = 2;
+	else
+		vf = 1;
+
+	/* FIXME venc pclk? */
+	return dispc_pclk_rate() * vf * hf;
+}
+
 static int _dispc_setup_plane(enum omap_plane plane,
 		enum omap_channel channel_out,
 		u32 paddr, u16 screen_width,
@@ -1294,7 +1360,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
 		u8 rotation, int mirror)
 {
 	const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
-	bool five_taps = height > out_height * 2;
+	bool five_taps = 0;
 	bool fieldmode = 0;
 	int cconv = 0;
 	unsigned offset0, offset1;
@@ -1323,8 +1389,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
 		}
 	} else {
 		/* video plane */
-		if (width > (2048 >> five_taps))
-			return -EINVAL;
+
+		unsigned long fclk;
 
 		if (out_width < width / maxdownscale ||
 		   out_width > width * 8)
@@ -1356,6 +1422,30 @@ static int _dispc_setup_plane(enum omap_plane plane,
 		default:
 			return -EINVAL;
 		}
+
+		/* Must use 5-tap filter? */
+		five_taps = height > out_height * 2;
+
+		/* Try to use 5-tap filter whenever possible. */
+		if (cpu_is_omap34xx() && !five_taps &&
+		    height > out_height && width <= 1024) {
+			fclk = calc_fclk_five_taps(width, height,
+					out_width, out_height, color_mode);
+			if (fclk <= dispc_fclk_rate())
+				five_taps = true;
+		}
+
+		if (width > (2048 >> five_taps))
+			return -EINVAL;
+
+		fclk = calc_fclk(width, height, out_width, out_height,
+				color_mode, five_taps);
+
+		DSSDBG("required fclk rate = %lu Hz\n", fclk);
+		DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
+
+		if (fclk > dispc_fclk_rate())
+			return -EINVAL;
 	}
 
 	if (ilace && height >= out_height)
@@ -1399,7 +1489,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
 	if (plane != OMAP_DSS_GFX) {
 		_dispc_set_scaling(plane, width, height,
 				   out_width, out_height,
-				   ilace);
+				   ilace, five_taps);
 		_dispc_set_vid_size(plane, out_width, out_height);
 		_dispc_set_vid_color_conv(plane, cconv);
 	}
-- 
1.5.6.5