Mercurial > mplayer.hg
annotate vidix/sh_veu_vid.c @ 31366:0bf908d29807
SIGPIPE is not really a crash, try to exit cleanly in case we receive one.
Particularly in the network code it would be better to ignore it, but
some window managers use it to indicate a close request.
author | reimar |
---|---|
date | Wed, 16 Jun 2010 17:33:17 +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 }; |