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