Mercurial > mplayer.hg
annotate vidix/sh_veu_vid.c @ 33696:24d919fb6778
Don't let MPlayer directly call user interface functions.
Provide the necessary actions for MPlayer commands by guiGetEvent type
guiRunCommand instead. That way, access is possible through the official
interface function.
author | ib |
---|---|
date | Wed, 29 Jun 2011 15:22:22 +0000 |
parents | 20da977f0f3e |
children | 0989cbea18b4 |
rev | line source |
---|---|
27420 | 1 /* |
2 * VIDIX driver for SuperH Mobile VEU hardware block. | |
29946
54bacf6a38ca
Update the SuperH VEU vidix driver with code that calls fsync() after each
cehoyos
parents:
28019
diff
changeset
|
3 * Copyright (C) 2008, 2009 Magnus Damm |
27420 | 4 * |
5 * Requires a kernel that exposes the VEU hardware block to user space | |
6 * using UIO. Available in upstream linux-2.6.27 or later. | |
7 * | |
8 * Tested using WVGA and QVGA panels with sh7722 VEU and sh7723 VEU2H. | |
9 * | |
10 * This file is part of MPlayer. | |
11 * | |
12 * MPlayer is free software; you can redistribute it and/or modify | |
13 * it under the terms of the GNU General Public License as published by | |
14 * the Free Software Foundation; either version 2 of the License, or | |
15 * (at your option) any later version. | |
16 * | |
17 * MPlayer is distributed in the hope that it will be useful, | |
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 * GNU General Public License for more details. | |
21 * | |
22 * You should have received a copy of the GNU General Public License | |
23 * along with MPlayer; if not, write to the Free Software | |
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
25 */ | |
26 | |
27 #include <stdio.h> | |
28 #include <unistd.h> | |
29 #include <string.h> | |
30 #include <stdlib.h> | |
31 #include <sys/mman.h> | |
32 #include <sys/time.h> | |
33 #include <sys/ioctl.h> | |
34 #include <fcntl.h> | |
35 #include <linux/fb.h> | |
36 #include <inttypes.h> | |
37 #include <unistd.h> | |
38 #include <errno.h> | |
39 | |
40 #include "config.h" | |
41 #include "vidix.h" | |
42 #include "fourcc.h" | |
43 | |
44 #include "dha.h" | |
45 | |
46 static int fgets_with_openclose(char *fname, char *buf, size_t maxlen) | |
47 { | |
48 FILE *fp; | |
49 | |
50 fp = fopen(fname, "r"); | |
51 if (!fp) | |
52 return -1; | |
53 | |
54 fgets(buf, maxlen, fp); | |
55 fclose(fp); | |
56 return strlen(buf); | |
57 } | |
58 | |
59 struct uio_device { | |
60 char *name; | |
61 char *path; | |
62 int fd; | |
63 }; | |
64 | |
65 #define MAXNAMELEN 256 | |
66 | |
67 static int locate_uio_device(char *name, struct uio_device *udp) | |
68 { | |
69 char fname[MAXNAMELEN], buf[MAXNAMELEN]; | |
70 char *tmp; | |
71 int uio_id; | |
72 | |
73 uio_id = -1; | |
74 do { | |
75 uio_id++; | |
76 snprintf(fname, MAXNAMELEN, "/sys/class/uio/uio%d/name", uio_id); | |
77 if (fgets_with_openclose(fname, buf, MAXNAMELEN) < 0) | |
78 return -1; | |
79 | |
80 } while (strncmp(name, buf, strlen(name))); | |
81 | |
82 tmp = strchr(buf, '\n'); | |
83 if (tmp) | |
84 *tmp = '\0'; | |
85 | |
86 udp->name = strdup(buf); | |
87 udp->path = strdup(fname); | |
88 udp->path[strlen(udp->path) - 5] = '\0'; | |
89 | |
90 snprintf(buf, MAXNAMELEN, "/dev/uio%d", uio_id); | |
91 udp->fd = open(buf, O_RDWR | O_SYNC); | |
92 | |
93 if (udp->fd < 0) | |
94 return -1; | |
95 | |
96 return 0; | |
97 } | |
98 | |
99 struct uio_map { | |
100 unsigned long address; | |
101 unsigned long size; | |
102 void *iomem; | |
103 }; | |
104 | |
105 static int setup_uio_map(struct uio_device *udp, int nr, struct uio_map *ump) | |
106 { | |
107 char fname[MAXNAMELEN], buf[MAXNAMELEN]; | |
108 | |
109 snprintf(fname, MAXNAMELEN, "%s/maps/map%d/addr", udp->path, nr); | |
110 if (fgets_with_openclose(fname, buf, MAXNAMELEN) <= 0) | |
111 return -1; | |
112 | |
113 ump->address = strtoul(buf, NULL, 0); | |
114 | |
115 snprintf(fname, MAXNAMELEN, "%s/maps/map%d/size", udp->path, nr); | |
116 if (fgets_with_openclose(fname, buf, MAXNAMELEN) <= 0) | |
117 return -1; | |
118 | |
119 ump->size = strtoul(buf, NULL, 0); | |
120 ump->iomem = mmap(0, ump->size, | |
121 PROT_READ|PROT_WRITE, MAP_SHARED, | |
122 udp->fd, nr * getpagesize()); | |
123 | |
124 if (ump->iomem == MAP_FAILED) | |
125 return -1; | |
126 | |
127 return 0; | |
128 } | |
129 | |
130 struct fb_info { | |
131 unsigned long width; | |
132 unsigned long height; | |
133 unsigned long bpp; | |
134 unsigned long line_length; | |
135 | |
136 unsigned long address; | |
137 unsigned long size; | |
138 }; | |
139 | |
140 static int get_fb_info(char *device, struct fb_info *fip) | |
141 { | |
142 struct fb_var_screeninfo vinfo; | |
143 struct fb_fix_screeninfo finfo; | |
144 void *iomem; | |
145 int fd; | |
146 | |
147 fd = open(device, O_RDWR); | |
148 if (fd < 0) { | |
149 perror("open"); | |
150 return -1; | |
151 } | |
152 | |
153 if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) { | |
154 perror("ioctl(FBIOGET_VSCREENINFO)"); | |
155 return -1; | |
156 } | |
157 | |
158 fip->width = vinfo.xres; | |
159 fip->height = vinfo.yres; | |
160 fip->bpp = vinfo.bits_per_pixel; | |
161 | |
162 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { | |
163 perror("ioctl(FBIOGET_FSCREENINFO)"); | |
164 return -1; | |
165 } | |
166 | |
167 fip->address = finfo.smem_start; | |
168 fip->size = finfo.smem_len; | |
169 fip->line_length = finfo.line_length; | |
170 | |
171 iomem = mmap(0, fip->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | |
172 | |
173 if (iomem == MAP_FAILED) { | |
174 perror("mmap"); | |
175 return -1; | |
176 } | |
177 | |
178 /* clear framebuffer */ | |
179 memset(iomem, 0, fip->line_length * fip->height); | |
180 munmap(iomem, fip->size); | |
181 | |
29946
54bacf6a38ca
Update the SuperH VEU vidix driver with code that calls fsync() after each
cehoyos
parents:
28019
diff
changeset
|
182 return fd; |
27420 | 183 } |
184 | |
185 #define VESTR 0x00 /* start register */ | |
186 #define VESWR 0x10 /* src: line length */ | |
187 #define VESSR 0x14 /* src: image size */ | |
188 #define VSAYR 0x18 /* src: y/rgb plane address */ | |
189 #define VSACR 0x1c /* src: c plane address */ | |
190 #define VBSSR 0x20 /* bundle mode register */ | |
191 #define VEDWR 0x30 /* dst: line length */ | |
192 #define VDAYR 0x34 /* dst: y/rgb plane address */ | |
193 #define VDACR 0x38 /* dst: c plane address */ | |
194 #define VTRCR 0x50 /* transform control */ | |
195 #define VRFCR 0x54 /* resize scale */ | |
196 #define VRFSR 0x58 /* resize clip */ | |
197 #define VENHR 0x5c /* enhance */ | |
198 #define VFMCR 0x70 /* filter mode */ | |
199 #define VVTCR 0x74 /* lowpass vertical */ | |
200 #define VHTCR 0x78 /* lowpass horizontal */ | |
201 #define VAPCR 0x80 /* color match */ | |
202 #define VECCR 0x84 /* color replace */ | |
203 #define VAFXR 0x90 /* fixed mode */ | |
204 #define VSWPR 0x94 /* swap */ | |
205 #define VEIER 0xa0 /* interrupt mask */ | |
206 #define VEVTR 0xa4 /* interrupt event */ | |
207 #define VSTAR 0xb0 /* status */ | |
208 #define VBSRR 0xb4 /* reset */ | |
209 | |
210 #define VMCR00 0x200 /* color conversion matrix coefficient 00 */ | |
211 #define VMCR01 0x204 /* color conversion matrix coefficient 01 */ | |
212 #define VMCR02 0x208 /* color conversion matrix coefficient 02 */ | |
213 #define VMCR10 0x20c /* color conversion matrix coefficient 10 */ | |
214 #define VMCR11 0x210 /* color conversion matrix coefficient 11 */ | |
215 #define VMCR12 0x214 /* color conversion matrix coefficient 12 */ | |
216 #define VMCR20 0x218 /* color conversion matrix coefficient 20 */ | |
217 #define VMCR21 0x21c /* color conversion matrix coefficient 21 */ | |
218 #define VMCR22 0x220 /* color conversion matrix coefficient 22 */ | |
219 #define VCOFFR 0x224 /* color conversion offset */ | |
220 #define VCBR 0x228 /* color conversion clip */ | |
221 | |
29948
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
222 #define VRPBR 0xc8 /* resize passband */ |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
223 |
27420 | 224 /* Helper functions for reading registers. */ |
225 | |
226 static unsigned long read_reg(struct uio_map *ump, int reg_offs) | |
227 { | |
228 volatile unsigned long *reg = ump->iomem; | |
229 | |
230 return reg[reg_offs / 4]; | |
231 } | |
232 | |
233 static void write_reg(struct uio_map *ump, unsigned long value, int reg_offs) | |
234 { | |
235 volatile unsigned long *reg = ump->iomem; | |
236 | |
237 reg[reg_offs / 4] = value; | |
238 } | |
239 | |
240 static vidix_capability_t sh_veu_cap = { | |
241 "SuperH VEU driver", | |
242 "Magnus Damm", | |
243 TYPE_OUTPUT, | |
244 { 0, 0, 0, 0 }, | |
245 2560, | |
246 1920, | |
247 16, | |
248 16, | |
249 -1, | |
250 FLAG_UPSCALER|FLAG_DOWNSCALER, | |
251 -1, | |
252 -1, | |
253 { 0, 0, 0, 0 } | |
254 }; | |
255 | |
256 /* global variables yuck */ | |
257 | |
258 static struct fb_info fbi; | |
259 static struct uio_device uio_dev; | |
260 static struct uio_map uio_mmio, uio_mem; | |
261 | |
262 struct sh_veu_plane { | |
263 unsigned long width; | |
264 unsigned long height; | |
265 unsigned long stride; | |
266 unsigned long pos_x; | |
267 unsigned long pos_y; | |
268 }; | |
269 | |
270 static struct sh_veu_plane _src, _dst; | |
271 static vidix_playback_t my_info; | |
29946
54bacf6a38ca
Update the SuperH VEU vidix driver with code that calls fsync() after each
cehoyos
parents:
28019
diff
changeset
|
272 static int fb_fd; |
27420 | 273 |
274 static int sh_veu_probe(int verbose, int force) | |
275 { | |
276 int ret; | |
277 | |
278 ret = get_fb_info("/dev/fb0", &fbi); | |
279 if (ret < 0) | |
280 return ret; | |
29946
54bacf6a38ca
Update the SuperH VEU vidix driver with code that calls fsync() after each
cehoyos
parents:
28019
diff
changeset
|
281 fb_fd = ret; |
27420 | 282 |
283 if (fbi.bpp != 16) { | |
284 printf("sh_veu: only 16bpp supported\n"); | |
285 return -1; | |
286 } | |
287 | |
288 ret = locate_uio_device("VEU", &uio_dev); | |
289 if (ret < 0) { | |
290 printf("sh_veu: unable to locate matching UIO device\n"); | |
291 return ret; | |
292 } | |
293 | |
294 ret = setup_uio_map(&uio_dev, 0, &uio_mmio); | |
295 if (ret < 0) { | |
296 printf("sh_veu: cannot setup MMIO\n"); | |
297 return ret; | |
298 } | |
299 | |
300 ret = setup_uio_map(&uio_dev, 1, &uio_mem); | |
301 if (ret < 0) { | |
302 printf("sh_veu: cannot setup contiguous memory\n"); | |
303 return ret; | |
304 } | |
305 | |
306 printf("sh_veu: Using %s at %s on %lux%lu %ldbpp /dev/fb0\n", | |
307 uio_dev.name, uio_dev.path, | |
308 fbi.width, fbi.height, fbi.bpp); | |
309 | |
310 return ret; | |
311 } | |
312 | |
313 static void sh_veu_wait_irq(vidix_playback_t *info) | |
314 { | |
315 unsigned long n_pending; | |
316 | |
317 /* Wait for an interrupt */ | |
28019 | 318 read(uio_dev.fd, &n_pending, sizeof(unsigned long)); |
27420 | 319 |
320 write_reg(&uio_mmio, 0x100, VEVTR); /* ack int, write 0 to bit 0 */ | |
29946
54bacf6a38ca
Update the SuperH VEU vidix driver with code that calls fsync() after each
cehoyos
parents:
28019
diff
changeset
|
321 |
54bacf6a38ca
Update the SuperH VEU vidix driver with code that calls fsync() after each
cehoyos
parents:
28019
diff
changeset
|
322 /* flush framebuffer to handle deferred io case */ |
54bacf6a38ca
Update the SuperH VEU vidix driver with code that calls fsync() after each
cehoyos
parents:
28019
diff
changeset
|
323 fsync(fb_fd); |
27420 | 324 } |
325 | |
326 static int sh_veu_is_veu2h(void) | |
327 { | |
29948
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
328 return uio_mmio.size == 0x27c; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
329 } |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
330 |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
331 static int sh_veu_is_veu3f(void) |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
332 { |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
333 return uio_mmio.size == 0xcc; |
27420 | 334 } |
335 | |
336 static unsigned long sh_veu_do_scale(struct uio_map *ump, | |
337 int vertical, int size_in, | |
338 int size_out, int crop_out) | |
339 { | |
29948
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
340 unsigned long fixpoint, mant, frac, value, rep, vb; |
27420 | 341 |
342 /* calculate FRAC and MANT */ | |
343 do { | |
344 rep = mant = frac = 0; | |
345 | |
346 if (size_in == size_out) { | |
347 if (crop_out != size_out) | |
348 mant = 1; /* needed for cropping */ | |
349 break; | |
350 } | |
351 | |
352 /* VEU2H special upscale */ | |
353 if (sh_veu_is_veu2h() && size_out > size_in) { | |
354 fixpoint = (4096 * size_in) / size_out; | |
355 | |
356 mant = fixpoint / 4096; | |
357 frac = fixpoint - (mant * 4096); | |
358 frac &= ~0x07; | |
359 | |
360 switch (frac) { | |
361 case 0x800: | |
362 rep = 1; | |
363 break; | |
364 case 0x400: | |
365 rep = 3; | |
366 break; | |
367 case 0x200: | |
368 rep = 7; | |
369 break; | |
370 } | |
371 | |
372 if (rep) | |
373 break; | |
374 } | |
375 | |
376 fixpoint = (4096 * (size_in - 1)) / (size_out + 1); | |
377 mant = fixpoint / 4096; | |
378 frac = fixpoint - (mant * 4096); | |
379 | |
380 if (frac & 0x07) { | |
381 frac &= ~0x07; | |
382 if (size_out > size_in) | |
383 frac -= 8; /* round down if scaling up */ | |
384 else | |
385 frac += 8; /* round up if scaling down */ | |
386 } | |
387 | |
388 } while (0); | |
389 | |
390 /* set scale */ | |
391 value = read_reg(ump, VRFCR); | |
392 if (vertical) { | |
393 value &= ~0xffff0000; | |
394 value |= ((mant << 12) | frac) << 16; | |
395 } else { | |
396 value &= ~0xffff; | |
397 value |= (mant << 12) | frac; | |
398 } | |
399 write_reg(ump, value, VRFCR); | |
400 | |
401 /* set clip */ | |
402 value = read_reg(ump, VRFSR); | |
403 if (vertical) { | |
404 value &= ~0xffff0000; | |
405 value |= ((rep << 12) | crop_out) << 16; | |
406 } else { | |
407 value &= ~0xffff; | |
408 value |= (rep << 12) | crop_out; | |
409 } | |
410 write_reg(ump, value, VRFSR); | |
411 | |
29948
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
412 /* VEU3F needs additional VRPBR register handling */ |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
413 if (sh_veu_is_veu3f()) { |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
414 if (size_out > size_in) |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
415 vb = 64; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
416 else { |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
417 if ((mant >= 8) && (mant < 16)) |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
418 value = 4; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
419 else if ((mant >= 4) && (mant < 8)) |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
420 value = 2; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
421 else |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
422 value = 1; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
423 |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
424 vb = 64 * 4096 * value; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
425 vb /= 4096 * mant + frac; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
426 } |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
427 |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
428 /* set resize passband register */ |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
429 value = read_reg(ump, VRPBR); |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
430 if (vertical) { |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
431 value &= ~0xffff0000; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
432 value |= vb << 16; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
433 } else { |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
434 value &= ~0xffff; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
435 value |= vb; |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
436 } |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
437 write_reg(ump, value, VRPBR); |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
438 } |
20da977f0f3e
Update the SuperH VEU vidix driver with experimental support for VEU3F.
cehoyos
parents:
29946
diff
changeset
|
439 |
27420 | 440 return (((size_in * crop_out) / size_out) + 0x03) & ~0x03; |
441 } | |
442 | |
443 static void sh_veu_setup_planes(vidix_playback_t *info, | |
444 struct sh_veu_plane *src, | |
445 struct sh_veu_plane *dst) | |
446 { | |
447 unsigned long addr, real_w, real_h; | |
448 | |
449 src->width = info->src.w; | |
450 src->height = info->src.h; | |
451 src->stride = (info->src.w+15) & ~15; | |
452 | |
453 dst->width = real_w = info->dest.w; | |
454 dst->height = real_h = info->dest.h; | |
455 dst->stride = fbi.line_length; | |
456 dst->pos_x = info->dest.x & ~0x03; | |
457 dst->pos_y = info->dest.y; | |
458 | |
459 if ((dst->width + dst->pos_x) > fbi.width) | |
460 dst->width = fbi.width - dst->pos_x; | |
461 | |
462 if ((dst->height + dst->pos_y) > fbi.height) | |
463 dst->height = fbi.height - dst->pos_y; | |
464 | |
465 addr = fbi.address; | |
466 addr += dst->pos_x * (fbi.bpp / 8); | |
467 addr += dst->pos_y * dst->stride; | |
468 | |
469 src->width = sh_veu_do_scale(&uio_mmio, 0, src->width, | |
470 real_w, dst->width); | |
471 src->height = sh_veu_do_scale(&uio_mmio, 1, src->height, | |
472 real_h, dst->height); | |
473 | |
474 write_reg(&uio_mmio, src->stride, VESWR); | |
475 write_reg(&uio_mmio, src->width | (src->height << 16), VESSR); | |
476 write_reg(&uio_mmio, 0, VBSSR); /* not using bundle mode */ | |
477 | |
478 write_reg(&uio_mmio, dst->stride, VEDWR); | |
479 write_reg(&uio_mmio, addr, VDAYR); | |
480 write_reg(&uio_mmio, 0, VDACR); /* unused for RGB */ | |
481 | |
482 write_reg(&uio_mmio, 0x67, VSWPR); | |
483 write_reg(&uio_mmio, (6 << 16) | (0 << 14) | 2 | 4, VTRCR); | |
484 | |
485 if (sh_veu_is_veu2h()) { | |
486 write_reg(&uio_mmio, 0x0cc5, VMCR00); | |
487 write_reg(&uio_mmio, 0x0950, VMCR01); | |
488 write_reg(&uio_mmio, 0x0000, VMCR02); | |
489 | |
490 write_reg(&uio_mmio, 0x397f, VMCR10); | |
491 write_reg(&uio_mmio, 0x0950, VMCR11); | |
492 write_reg(&uio_mmio, 0x3ccd, VMCR12); | |
493 | |
494 write_reg(&uio_mmio, 0x0000, VMCR20); | |
495 write_reg(&uio_mmio, 0x0950, VMCR21); | |
496 write_reg(&uio_mmio, 0x1023, VMCR22); | |
497 | |
498 write_reg(&uio_mmio, 0x00800010, VCOFFR); | |
499 } | |
500 | |
501 write_reg(&uio_mmio, 1, VEIER); /* enable interrupt in VEU */ | |
502 } | |
503 | |
504 static void sh_veu_blit(vidix_playback_t *info, int frame) | |
505 { | |
506 unsigned long enable = 1; | |
507 unsigned long addr; | |
508 | |
509 addr = uio_mem.address + info->offsets[frame]; | |
510 | |
511 write_reg(&uio_mmio, addr + info->offset.y, VSAYR); | |
512 write_reg(&uio_mmio, addr + info->offset.u, VSACR); | |
513 | |
514 /* Enable interrupt in UIO driver */ | |
28019 | 515 write(uio_dev.fd, &enable, sizeof(unsigned long)); |
27420 | 516 |
517 write_reg(&uio_mmio, 1, VESTR); /* start operation */ | |
518 } | |
519 | |
520 static int sh_veu_init(void) | |
521 { | |
522 write_reg(&uio_mmio, 0x100, VBSRR); /* reset VEU */ | |
523 return 0; | |
524 } | |
525 | |
526 static void sh_veu_destroy(void) | |
527 { | |
29946
54bacf6a38ca
Update the SuperH VEU vidix driver with code that calls fsync() after each
cehoyos
parents:
28019
diff
changeset
|
528 close(fb_fd); |
27420 | 529 } |
530 | |
531 static int sh_veu_get_caps(vidix_capability_t *to) | |
532 { | |
533 memcpy(to, &sh_veu_cap, sizeof(vidix_capability_t)); | |
534 return 0; | |
535 } | |
536 | |
537 static int sh_veu_query_fourcc(vidix_fourcc_t *to) | |
538 { | |
539 if (to->fourcc == IMGFMT_NV12) { | |
540 to->depth = VID_DEPTH_ALL; | |
541 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK; | |
542 return 0; | |
543 } | |
544 to->depth = to->flags = 0; | |
545 return ENOSYS; | |
546 } | |
547 | |
548 | |
549 static int sh_veu_config_playback(vidix_playback_t *info) | |
550 { | |
551 unsigned int i, y_pitch; | |
552 | |
553 switch (info->fourcc) { | |
554 case IMGFMT_NV12: | |
555 y_pitch = (info->src.w + 15) & ~15; | |
556 | |
557 info->offset.y = 0; | |
558 info->offset.u = y_pitch * info->src.h; | |
559 info->frame_size = info->offset.u + info->offset.u / 2; | |
560 break; | |
561 default: | |
562 return ENOTSUP; | |
563 } | |
564 | |
565 info->num_frames = uio_mem.size / info->frame_size; | |
566 if (info->num_frames > VID_PLAY_MAXFRAMES) | |
567 info->num_frames = VID_PLAY_MAXFRAMES; | |
568 | |
569 if (!info->num_frames) { | |
570 printf("sh_veu: %d is not enough memory for %d bytes frame\n", | |
571 (int)uio_mem.size, (int)info->frame_size); | |
572 return ENOMEM; | |
573 } | |
574 | |
575 info->dga_addr = uio_mem.iomem; | |
576 info->dest.pitch.y = info->dest.pitch.u = info->dest.pitch.v = 16; | |
577 | |
578 for (i = 0; i < info->num_frames; i++) | |
579 info->offsets[i] = info->frame_size * i; | |
580 | |
581 my_info = *info; | |
582 | |
583 printf("sh_veu: %d frames * %d bytes, total size = %d\n", | |
584 (int)info->num_frames, (int)info->frame_size, | |
585 (int)uio_mem.size); | |
586 | |
587 sh_veu_setup_planes(info, &_src, &_dst); | |
588 | |
589 printf("sh_veu: %dx%d->%dx%d@%dx%d -> %dx%d->%dx%d@%dx%d \n", | |
590 (int)info->src.w, (int)info->src.h, | |
591 (int)info->dest.w, (int)info->dest.h, | |
592 (int)info->dest.x, (int)info->dest.y, | |
593 (int)_src.width, (int)_src.height, | |
594 (int)_dst.width, (int)_dst.height, | |
595 (int)_dst.pos_x, (int)_dst.pos_y); | |
596 return 0; | |
597 } | |
598 | |
599 | |
600 static int sh_veu_playback_on(void) | |
601 { | |
602 return 0; | |
603 } | |
604 | |
605 static int sh_veu_playback_off(void) | |
606 { | |
607 return 0; | |
608 } | |
609 | |
610 static int sh_veu_first_frame = 1; | |
611 | |
612 static int sh_veu_frame_sel(unsigned int frame) | |
613 { | |
614 if (!sh_veu_first_frame) | |
615 sh_veu_wait_irq(&my_info); | |
616 | |
617 sh_veu_blit(&my_info, frame); | |
618 sh_veu_first_frame = 0; | |
619 return 0; | |
620 } | |
621 | |
622 VDXDriver sh_veu_drv = { | |
623 "sh_veu", | |
624 NULL, | |
625 .probe = sh_veu_probe, | |
626 .get_caps = sh_veu_get_caps, | |
627 .query_fourcc = sh_veu_query_fourcc, | |
628 .init = sh_veu_init, | |
629 .destroy = sh_veu_destroy, | |
630 .config_playback = sh_veu_config_playback, | |
631 .playback_on = sh_veu_playback_on, | |
632 .playback_off = sh_veu_playback_off, | |
633 .frame_sel = sh_veu_frame_sel, | |
634 }; |