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