@@ -100,12 +100,76 @@ int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused)
100
100
}
101
101
#endif
102
102
103
+ /* The filter kernel is composed of dwords each containing 3 9-bit
104
+ * signed integers packed next to each other.
105
+ */
106
+ #define VC4_INT_TO_COEFF (coeff ) (coeff & 0x1ff)
107
+ #define VC4_PPF_FILTER_WORD (c0 , c1 , c2 ) \
108
+ ((((c0) & 0x1ff) << 0) | \
109
+ (((c1) & 0x1ff) << 9) | \
110
+ (((c2) & 0x1ff) << 18))
111
+
112
+ /* The whole filter kernel is arranged as the coefficients 0-16 going
113
+ * up, then a pad, then 17-31 going down and reversed within the
114
+ * dwords. This means that a linear phase kernel (where it's
115
+ * symmetrical at the boundary between 15 and 16) has the last 5
116
+ * dwords matching the first 5, but reversed.
117
+ */
118
+ #define VC4_LINEAR_PHASE_KERNEL (c0 , c1 , c2 , c3 , c4 , c5 , c6 , c7 , c8 , \
119
+ c9 , c10 , c11 , c12 , c13 , c14 , c15 ) \
120
+ {VC4_PPF_FILTER_WORD(c0, c1, c2), \
121
+ VC4_PPF_FILTER_WORD(c3, c4, c5), \
122
+ VC4_PPF_FILTER_WORD(c6, c7, c8), \
123
+ VC4_PPF_FILTER_WORD(c9, c10, c11), \
124
+ VC4_PPF_FILTER_WORD(c12, c13, c14), \
125
+ VC4_PPF_FILTER_WORD(c15, c15, 0)}
126
+
127
+ #define VC4_LINEAR_PHASE_KERNEL_DWORDS 6
128
+ #define VC4_KERNEL_DWORDS (VC4_LINEAR_PHASE_KERNEL_DWORDS * 2 - 1)
129
+
130
+ /* Recommended B=1/3, C=1/3 filter choice from Mitchell/Netravali.
131
+ * http://www.cs.utexas.edu/~fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
132
+ */
133
+ static const u32 mitchell_netravali_1_3_1_3_kernel [] =
134
+ VC4_LINEAR_PHASE_KERNEL (0 , -2 , -6 , -8 , -10 , -8 , -3 , 2 , 18 ,
135
+ 50 , 82 , 119 , 155 , 187 , 213 , 227 );
136
+
137
+ static int vc4_hvs_upload_linear_kernel (struct vc4_hvs * hvs ,
138
+ struct drm_mm_node * space ,
139
+ const u32 * kernel )
140
+ {
141
+ int ret , i ;
142
+ u32 __iomem * dst_kernel ;
143
+
144
+ ret = drm_mm_insert_node (& hvs -> dlist_mm , space , VC4_KERNEL_DWORDS , 1 ,
145
+ 0 );
146
+ if (ret ) {
147
+ DRM_ERROR ("Failed to allocate space for filter kernel: %d\n" ,
148
+ ret );
149
+ return ret ;
150
+ }
151
+
152
+ dst_kernel = hvs -> dlist + space -> start ;
153
+
154
+ for (i = 0 ; i < VC4_KERNEL_DWORDS ; i ++ ) {
155
+ if (i < VC4_LINEAR_PHASE_KERNEL_DWORDS )
156
+ writel (kernel [i ], & dst_kernel [i ]);
157
+ else {
158
+ writel (kernel [VC4_KERNEL_DWORDS - i - 1 ],
159
+ & dst_kernel [i ]);
160
+ }
161
+ }
162
+
163
+ return 0 ;
164
+ }
165
+
103
166
static int vc4_hvs_bind (struct device * dev , struct device * master , void * data )
104
167
{
105
168
struct platform_device * pdev = to_platform_device (dev );
106
169
struct drm_device * drm = dev_get_drvdata (master );
107
170
struct vc4_dev * vc4 = drm -> dev_private ;
108
171
struct vc4_hvs * hvs = NULL ;
172
+ int ret ;
109
173
110
174
hvs = devm_kzalloc (& pdev -> dev , sizeof (* hvs ), GFP_KERNEL );
111
175
if (!hvs )
@@ -130,6 +194,22 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
130
194
HVS_BOOTLOADER_DLIST_END ,
131
195
(SCALER_DLIST_SIZE >> 2 ) - HVS_BOOTLOADER_DLIST_END );
132
196
197
+ /* Set up the HVS LBM memory manager. We could have some more
198
+ * complicated data structure that allowed reuse of LBM areas
199
+ * between planes when they don't overlap on the screen, but
200
+ * for now we just allocate globally.
201
+ */
202
+ drm_mm_init (& hvs -> lbm_mm , 0 , 96 * 1024 );
203
+
204
+ /* Upload filter kernels. We only have the one for now, so we
205
+ * keep it around for the lifetime of the driver.
206
+ */
207
+ ret = vc4_hvs_upload_linear_kernel (hvs ,
208
+ & hvs -> mitchell_netravali_filter ,
209
+ mitchell_netravali_1_3_1_3_kernel );
210
+ if (ret )
211
+ return ret ;
212
+
133
213
vc4 -> hvs = hvs ;
134
214
return 0 ;
135
215
}
@@ -140,7 +220,11 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
140
220
struct drm_device * drm = dev_get_drvdata (master );
141
221
struct vc4_dev * vc4 = drm -> dev_private ;
142
222
223
+ if (vc4 -> hvs -> mitchell_netravali_filter .allocated )
224
+ drm_mm_remove_node (& vc4 -> hvs -> mitchell_netravali_filter );
225
+
143
226
drm_mm_takedown (& vc4 -> hvs -> dlist_mm );
227
+ drm_mm_takedown (& vc4 -> hvs -> lbm_mm );
144
228
145
229
vc4 -> hvs = NULL ;
146
230
}
0 commit comments