aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-omap-2.6.27/0001-Implement-downsampling-with-debugs.patch
blob: d3608df9cb99e439221e8524638c5d62651ac24b (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
From 1ef94095e9399a9a387b7b457b48f6c5de7013d8 Mon Sep 17 00:00:00 2001
From: Tuomas Kulve <tuomas.kulve@movial.com>
Date: Fri, 31 Oct 2008 14:23:57 +0200
Subject: [PATCH] Implement downsampling (with debugs).

---
 drivers/video/omap/dispc.c |   75 +++++++++++++++++++++++++++++++++++++-------
 1 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index 68bc887..3640dbe 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -18,6 +18,8 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
+#define DEBUG
+#define VERBOSE_DEBUG
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
@@ -545,6 +547,17 @@ static void write_firhv_reg(int plane, int reg, u32 value)
 	dispc_write_reg(base + reg * 8,	value);
 }
 
+static void write_firv_reg(int plane, int reg, u32 value)
+{
+	u32 base;
+
+	if (plane == 1)
+		base = 0x1E0;
+	else
+		base = 0x1E0 + 0x20;
+	dispc_write_reg(base + reg * 4,	value);
+}
+
 static void set_upsampling_coef_table(int plane)
 {
 	const u32 coef[][2] = {
@@ -565,6 +578,27 @@ static void set_upsampling_coef_table(int plane)
 	}
 }
 
+static void set_downsampling_coef_table(int plane)
+{
+	const u32 coef[][3] = {
+                { 0x24382400, 0x24382400, 0x00000000 },
+                { 0x28371FFE, 0x28391F04, 0x000004FE },
+                { 0x2C361BFB, 0x2D381B08, 0x000008FB },
+                { 0x303516F9, 0x3237170C, 0x00000CF9 },
+                { 0x11343311, 0x123737F7, 0x0000F711 },
+                { 0x1635300C, 0x173732F9, 0x0000F90C },
+                { 0x1B362C08, 0x1B382DFB, 0x0000FB08 },
+                { 0x1F372804, 0x1F3928FE, 0x0000FE04 },
+	};
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		write_firh_reg(plane, i, coef[i][0]);
+		write_firhv_reg(plane, i, coef[i][1]);
+		write_firv_reg(plane, i, coef[i][2]);
+	}
+}
+
 static int omap_dispc_set_scale(int plane,
 				int orig_width, int orig_height,
 				int out_width, int out_height)
@@ -592,25 +626,47 @@ static int omap_dispc_set_scale(int plane,
 		if (orig_height > out_height ||
 		    orig_width * 8 < out_width ||
 		    orig_height * 8 < out_height) {
+                        dev_dbg(dispc.fbdev->dev, 
+                                "Max upsampling is 8x, "
+                                "tried: %dx%d -> %dx%d\n",
+                                orig_width, orig_height,
+                                out_width, out_height);
 			enable_lcd_clocks(0);
 			return -EINVAL;
 		}
 		set_upsampling_coef_table(plane);
 	} else if (orig_width > out_width) {
-		/* Downsampling not yet supported
-		*/
-
-		enable_lcd_clocks(0);
-		return -EINVAL;
+		/*
+		 * Downsampling.
+		 * Currently you can only scale both dimensions in one way.
+		 */
+		if (orig_height < out_height ||
+		    orig_width > out_width * 4||
+		    orig_height > out_height * 4) {
+                        dev_dbg(dispc.fbdev->dev, 
+                                "Max downsampling is 4x, "
+                                "tried: %dx%d -> %dx%d\n",
+                                orig_width, orig_height,
+                                out_width, out_height);
+			enable_lcd_clocks(0);
+			return -EINVAL;
+		}
+		set_downsampling_coef_table(plane);
 	}
 	if (!orig_width || orig_width == out_width)
 		fir_hinc = 0;
 	else
-		fir_hinc = 1024 * orig_width / out_width;
+		fir_hinc = 1024 * (orig_width -1)/ (out_width -1);
 	if (!orig_height || orig_height == out_height)
 		fir_vinc = 0;
 	else
-		fir_vinc = 1024 * orig_height / out_height;
+		fir_vinc = 1024 * (orig_height-1) / (out_height -1 );
+
+	dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
+		"orig_height %d fir_hinc  %d fir_vinc %d\n",
+		out_width, out_height, orig_width, orig_height,
+		fir_hinc, fir_vinc);
+
 	dispc.fir_hinc[plane] = fir_hinc;
 	dispc.fir_vinc[plane] = fir_vinc;
 
@@ -619,11 +675,6 @@ static int omap_dispc_set_scale(int plane,
 		    ((fir_vinc & 4095) << 16) |
 		    (fir_hinc & 4095));
 
-	dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
-		"orig_height %d fir_hinc  %d fir_vinc %d\n",
-		out_width, out_height, orig_width, orig_height,
-		fir_hinc, fir_vinc);
-
 	MOD_REG_FLD(vs_reg[plane],
 		    FLD_MASK(16, 11) | FLD_MASK(0, 11),
 		    ((out_height - 1) << 16) | (out_width - 1));
-- 
1.5.6.5