diff options
Diffstat (limited to 'vidix/sh_veu_vid.c')
-rw-r--r-- | vidix/sh_veu_vid.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/vidix/sh_veu_vid.c b/vidix/sh_veu_vid.c index 7ce49b4a94..cc45e32d86 100644 --- a/vidix/sh_veu_vid.c +++ b/vidix/sh_veu_vid.c @@ -1,6 +1,6 @@ /* * VIDIX driver for SuperH Mobile VEU hardware block. - * Copyright (C) 2008 Magnus Damm + * Copyright (C) 2008, 2009 Magnus Damm * * Requires a kernel that exposes the VEU hardware block to user space * using UIO. Available in upstream linux-2.6.27 or later. @@ -179,8 +179,7 @@ static int get_fb_info(char *device, struct fb_info *fip) memset(iomem, 0, fip->line_length * fip->height); munmap(iomem, fip->size); - close(fd); - return 0; + return fd; } #define VESTR 0x00 /* start register */ @@ -220,6 +219,8 @@ static int get_fb_info(char *device, struct fb_info *fip) #define VCOFFR 0x224 /* color conversion offset */ #define VCBR 0x228 /* color conversion clip */ +#define VRPBR 0xc8 /* resize passband */ + /* Helper functions for reading registers. */ static unsigned long read_reg(struct uio_map *ump, int reg_offs) @@ -268,6 +269,7 @@ struct sh_veu_plane { static struct sh_veu_plane _src, _dst; static vidix_playback_t my_info; +static int fb_fd; static int sh_veu_probe(int verbose, int force) { @@ -276,6 +278,7 @@ static int sh_veu_probe(int verbose, int force) ret = get_fb_info("/dev/fb0", &fbi); if (ret < 0) return ret; + fb_fd = ret; if (fbi.bpp != 16) { printf("sh_veu: only 16bpp supported\n"); @@ -315,18 +318,26 @@ static void sh_veu_wait_irq(vidix_playback_t *info) read(uio_dev.fd, &n_pending, sizeof(unsigned long)); write_reg(&uio_mmio, 0x100, VEVTR); /* ack int, write 0 to bit 0 */ + + /* flush framebuffer to handle deferred io case */ + fsync(fb_fd); } static int sh_veu_is_veu2h(void) { - return uio_mmio.size > 0xb8; + return uio_mmio.size == 0x27c; +} + +static int sh_veu_is_veu3f(void) +{ + return uio_mmio.size == 0xcc; } static unsigned long sh_veu_do_scale(struct uio_map *ump, int vertical, int size_in, int size_out, int crop_out) { - unsigned long fixpoint, mant, frac, value, rep; + unsigned long fixpoint, mant, frac, value, rep, vb; /* calculate FRAC and MANT */ do { @@ -398,6 +409,34 @@ static unsigned long sh_veu_do_scale(struct uio_map *ump, } write_reg(ump, value, VRFSR); + /* VEU3F needs additional VRPBR register handling */ + if (sh_veu_is_veu3f()) { + if (size_out > size_in) + vb = 64; + else { + if ((mant >= 8) && (mant < 16)) + value = 4; + else if ((mant >= 4) && (mant < 8)) + value = 2; + else + value = 1; + + vb = 64 * 4096 * value; + vb /= 4096 * mant + frac; + } + + /* set resize passband register */ + value = read_reg(ump, VRPBR); + if (vertical) { + value &= ~0xffff0000; + value |= vb << 16; + } else { + value &= ~0xffff; + value |= vb; + } + write_reg(ump, value, VRPBR); + } + return (((size_in * crop_out) / size_out) + 0x03) & ~0x03; } @@ -486,6 +525,7 @@ static int sh_veu_init(void) static void sh_veu_destroy(void) { + close(fb_fd); } static int sh_veu_get_caps(vidix_capability_t *to) |