1 /*
2 Copyright (c) 2003 Andreas Robinson, All rights reserved.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8 */
9
10 #include <config.h>
11
12 #include "unichrome.h"
13 #include "uc_overlay.h"
14 #include "vidregs.h"
15 #include "mmio.h"
16
17 #include <direct/messages.h>
18
19 #include <core/system.h>
20
21 #include <misc/conf.h>
22
23 // Forward declaration
24 static DFBResult
25 uc_ovl_remove(CoreLayer *layer,
26 void *driver_data,
27 void *layer_data,
28 void *region_data);
29
30
uc_ovl_datasize(void)31 static int uc_ovl_datasize( void )
32 {
33 return sizeof(UcOverlayData);
34 }
35
36
37 static DFBResult
uc_ovl_init_layer(CoreLayer * layer,void * driver_data,void * layer_data,DFBDisplayLayerDescription * description,DFBDisplayLayerConfig * config,DFBColorAdjustment * adjustment)38 uc_ovl_init_layer( CoreLayer *layer,
39 void *driver_data,
40 void *layer_data,
41 DFBDisplayLayerDescription *description,
42 DFBDisplayLayerConfig *config,
43 DFBColorAdjustment *adjustment )
44 {
45 UcDriverData* ucdrv = (UcDriverData*) driver_data;
46 UcOverlayData* ucovl = (UcOverlayData*) layer_data;
47
48 // Set layer type, capabilities and name
49
50 description->caps = UC_OVL_CAPS;
51 description->type = DLTF_GRAPHICS | DLTF_VIDEO | DLTF_STILL_PICTURE;
52 snprintf(description->name,
53 DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "VIA CLE266 Video");
54
55 adjustment->flags = DCAF_NONE;
56
57 // Fill out the default configuration
58
59 config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
60 DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
61
62 ucovl->v1.win.w = 720;
63 ucovl->v1.win.h = 576;
64 ucovl->v1.win.x = 0;
65 ucovl->v1.win.y = 0;
66
67 config->width = 720;
68 config->height = 576;
69
70 config->pixelformat = DSPF_YV12;
71 config->buffermode = DLBM_FRONTONLY;
72 config->options = DLOP_NONE;
73
74 // Reset overlay
75
76 ucovl->extfifo_on = false;
77 ucovl->hwrev = ucdrv->hwrev;
78 ucovl->scrwidth = ucovl->v1.win.w;
79
80 ucovl->v1.isenabled = false;
81 ucovl->v1.cfg = *config;
82 ucovl->v1.ox = 0;
83 ucovl->v1.oy = 0;
84
85 // adjustment->flags = DCAF_BRIGHTNESS | DCAF_CONTRAST |
86 // DCAF_HUE | DCAF_SATURATION;
87 adjustment->brightness = 0x8000;
88 adjustment->contrast = 0x8000;
89 adjustment->saturation = 0x8000;
90 adjustment->hue = 0x8000;
91 ucovl->v1.adj = *adjustment;
92
93 uc_ovl_remove(layer, driver_data, layer_data, NULL);
94
95 return DFB_OK;
96 }
97
98
99 static DFBResult
uc_ovl_set_region(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags updated,CoreSurface * surface,CorePalette * palette,CoreSurfaceBufferLock * lock)100 uc_ovl_set_region( CoreLayer *layer,
101 void *driver_data,
102 void *layer_data,
103 void *region_data,
104 CoreLayerRegionConfig *config,
105 CoreLayerRegionConfigFlags updated,
106 CoreSurface *surface,
107 CorePalette *palette,
108 CoreSurfaceBufferLock *lock )
109 {
110 UcDriverData* ucdrv = (UcDriverData*) driver_data;
111 UcOverlayData* ucovl = (UcOverlayData*) layer_data;
112
113 /* get new destination rectangle */
114 DFBRectangle win = config->dest;;
115
116 // Bounds checking
117 if ((win.x < -8192) || (win.x > 8192) ||
118 (win.y < -8192) || (win.y > 8192) ||
119 (win.w < 32) || (win.w > 4096) ||
120 (win.h < 32) || (win.h > 4096))
121 {
122 D_DEBUG("Layer size or position is out of bounds.");
123 return DFB_INVAREA;
124 }
125
126 ucovl->v1.isenabled = true;
127 ucovl->v1.win = win;
128
129 ucovl->deinterlace = config->options & DLOP_DEINTERLACING;
130 ucovl->surface = surface;
131 ucovl->lock = lock;
132
133 return uc_ovl_update(ucdrv, ucovl, UC_OVL_CHANGE, surface, lock);
134 }
135
136
137 static DFBResult
uc_ovl_remove(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data)138 uc_ovl_remove(CoreLayer *layer,
139 void *driver_data,
140 void *layer_data,
141 void *region_data)
142 {
143 UcDriverData* ucdrv = (UcDriverData*) driver_data;
144 UcOverlayData* ucovl = (UcOverlayData*) layer_data;
145 volatile u8* vio = ucdrv->hwregs;
146
147 ucovl->v1.isenabled = false;
148
149 uc_ovl_vcmd_wait(vio);
150
151 VIDEO_OUT(vio, V_FIFO_CONTROL, UC_MAP_V1_FIFO_CONTROL(16,12,8));
152 // VIDEO_OUT(vio, ALPHA_V3_FIFO_CONTROL, 0x0407181f);
153
154 if (ucovl->hwrev == 0x10) {
155 VIDEO_OUT(vio, V1_ColorSpaceReg_1, ColorSpaceValue_1_3123C0);
156 VIDEO_OUT(vio, V1_ColorSpaceReg_2, ColorSpaceValue_2_3123C0);
157 }
158 else {
159 VIDEO_OUT(vio, V1_ColorSpaceReg_1, ColorSpaceValue_1);
160 VIDEO_OUT(vio, V1_ColorSpaceReg_2, ColorSpaceValue_2);
161 }
162
163 VIDEO_OUT(vio, HQV_CONTROL, VIDEO_IN(vio, HQV_CONTROL) & ~HQV_ENABLE);
164 VIDEO_OUT(vio, V1_CONTROL, VIDEO_IN(vio, V1_CONTROL) & ~V1_ENABLE);
165 // VIDEO_OUT(vio, V3_CONTROL, VIDEO_IN(vio, V3_CONTROL) & ~V3_ENABLE);
166
167 VIDEO_OUT(vio, V_COMPOSE_MODE,
168 VIDEO_IN(vio, V_COMPOSE_MODE) | V1_COMMAND_FIRE);
169
170 ucovl->surface = NULL;
171
172 return DFB_OK;
173 }
174
175
176 static DFBResult
uc_ovl_test_region(CoreLayer * layer,void * driver_data,void * layer_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags * failed)177 uc_ovl_test_region(CoreLayer *layer,
178 void *driver_data,
179 void *layer_data,
180 CoreLayerRegionConfig *config,
181 CoreLayerRegionConfigFlags *failed)
182 {
183 CoreLayerRegionConfigFlags fail = 0;
184
185 // Check layer options
186
187 if (config->options & ~UC_OVL_OPTIONS)
188 fail |= CLRCF_OPTIONS;
189
190 // Check pixelformats
191
192 switch (config->format) {
193 case DSPF_YUY2:
194 break;
195 case DSPF_UYVY:
196 fail |= CLRCF_FORMAT; // Nope... doesn't work.
197 break;
198 case DSPF_I420:
199 case DSPF_YV12:
200 case DSPF_ARGB1555:
201 case DSPF_RGB16:
202 case DSPF_RGB32:
203 case DSPF_ARGB:
204 break;
205 default:
206 fail |= CLRCF_FORMAT;
207 }
208
209 // Check width and height
210
211 if (config->width > 4096 || config->width < 32)
212 fail |= CLRCF_WIDTH;
213
214 if (config->height > 4096 || config->height < 32)
215 fail |= CLRCF_HEIGHT;
216
217 if (failed) *failed = fail;
218 if (fail) return DFB_UNSUPPORTED;
219
220 return DFB_OK;
221 }
222
223
224 static DFBResult
uc_ovl_flip_region(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreSurface * surface,DFBSurfaceFlipFlags flags,CoreSurfaceBufferLock * lock)225 uc_ovl_flip_region( CoreLayer *layer,
226 void *driver_data,
227 void *layer_data,
228 void *region_data,
229 CoreSurface *surface,
230 DFBSurfaceFlipFlags flags,
231 CoreSurfaceBufferLock *lock)
232 {
233 //printf("Entering %s ... \n", __PRETTY_FUNCTION__);
234
235 UcDriverData* ucdrv = (UcDriverData*) driver_data;
236 UcOverlayData* ucovl = (UcOverlayData*) layer_data;
237 DFBResult ret;
238
239 if (((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) &&
240 !dfb_config->pollvsync_after)
241 dfb_layer_wait_vsync( layer );
242
243 dfb_surface_flip(surface, false);
244
245 ucovl->field = 0;
246 ucovl->lock = lock;
247
248 ret = uc_ovl_update(ucdrv, ucovl, UC_OVL_FLIP, surface, lock);
249 if (ret)
250 return ret;
251
252 if ((flags & DSFLIP_WAIT) &&
253 (dfb_config->pollvsync_after || !(flags & DSFLIP_ONSYNC)))
254 dfb_layer_wait_vsync(layer);
255
256 return DFB_OK;
257 }
258
259 static DFBResult
uc_ovl_get_level(CoreLayer * layer,void * driver_data,void * layer_data,int * level)260 uc_ovl_get_level(CoreLayer *layer,
261 void *driver_data,
262 void *layer_data,
263 int *level)
264 {
265 UcOverlayData* ucovl = (UcOverlayData*) layer_data;
266 *level = ucovl->v1.level;
267 return DFB_OK;
268 }
269
270 static DFBResult
uc_ovl_set_level(CoreLayer * layer,void * driver_data,void * layer_data,int level)271 uc_ovl_set_level(CoreLayer *layer,
272 void *driver_data,
273 void *layer_data,
274 int level)
275 {
276 UcOverlayData* ucovl = (UcOverlayData*) layer_data;
277 UcDriverData* ucdrv = (UcDriverData*) driver_data;
278
279 if (level == 0) return DFB_INVARG;
280 if (level > 0) {
281 // Enable underlay mode.
282 VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(-1));
283 }
284 else {
285 // Enable overlay mode (default)
286 VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL,
287 uc_ovl_map_alpha(ucovl->v1.opacity));
288 }
289
290 ucovl->v1.level = level;
291 return DFB_OK;
292 }
293
294 static DFBResult
uc_ovl_set_input_field(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,int field)295 uc_ovl_set_input_field( CoreLayer *layer,
296 void *driver_data,
297 void *layer_data,
298 void *region_data,
299 int field )
300 {
301 UcOverlayData* ucovl = (UcOverlayData*) layer_data;
302 UcDriverData* ucdrv = (UcDriverData*) driver_data;
303
304 ucovl->field = field;
305
306 return uc_ovl_update(ucdrv, ucovl, UC_OVL_FIELD, ucovl->surface, ucovl->lock);
307 }
308
309 DisplayLayerFuncs ucOverlayFuncs = {
310 .LayerDataSize = uc_ovl_datasize,
311 .InitLayer = uc_ovl_init_layer,
312 .SetRegion = uc_ovl_set_region,
313 .RemoveRegion = uc_ovl_remove,
314 .TestRegion = uc_ovl_test_region,
315 .FlipRegion = uc_ovl_flip_region,
316 .GetLevel = uc_ovl_get_level,
317 .SetLevel = uc_ovl_set_level,
318 .SetInputField = uc_ovl_set_input_field,
319 .SetColorAdjustment = uc_ovl_set_adjustment,
320 };
321