diff options
Diffstat (limited to 'libvo/vo_s3fb.c')
-rw-r--r-- | libvo/vo_s3fb.c | 560 |
1 files changed, 0 insertions, 560 deletions
diff --git a/libvo/vo_s3fb.c b/libvo/vo_s3fb.c deleted file mode 100644 index bd04ea29a7..0000000000 --- a/libvo/vo_s3fb.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * copyright (C) 2006 Mark Sanderson <mmp@kiora.ath.cx> - * - * 30-Mar-2006 Modified from tdfxfb.c by Mark Zealey - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* Hints and tricks: - * - Use -dr to get direct rendering - * - Use -vf yuy2 to get yuy2 rendering, *MUCH* faster than yv12 - */ - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <linux/fb.h> -#include <sys/io.h> - -#include "config.h" -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#include "mp_msg.h" -#include "fastmemcpy.h" -#include "video_out.h" -#include "video_out_internal.h" -#include "aspect.h" -#include "sub/sub.h" - -static const vo_info_t info = - { - "S3 Virge over fbdev", - "s3fb", - "Mark Sanderson <mmp@kiora.ath.cx>", - "" - }; - -const LIBVO_EXTERN(s3fb) - -typedef struct vga_type { - int cr38, cr39, cr53; - unsigned char *mmio; -} vga_t; - -static vga_t *v = NULL; -static int fd = -1; -static struct fb_fix_screeninfo fb_finfo; -static struct fb_var_screeninfo fb_vinfo; -static uint32_t in_width, in_height, in_format, in_depth, in_s3_format, - screenwidth, screenheight, screendepth, screenstride, - vidwidth, vidheight, vidx, vidy, page, offset, sreg; -static char *inpage, *inpage0, *smem = NULL; -static void (*alpha_func)(); - -static void clear_screen(void); - -/* streams registers */ -#define PSTREAM_CONTROL_REG 0x8180 -#define COL_CHROMA_KEY_CONTROL_REG 0x8184 -#define SSTREAM_CONTROL_REG 0x8190 -#define CHROMA_KEY_UPPER_BOUND_REG 0x8194 -#define SSTREAM_STRETCH_REG 0x8198 -#define BLEND_CONTROL_REG 0x81A0 -#define PSTREAM_FBADDR0_REG 0x81C0 -#define PSTREAM_FBADDR1_REG 0x81C4 -#define PSTREAM_STRIDE_REG 0x81C8 -#define DOUBLE_BUFFER_REG 0x81CC -#define SSTREAM_FBADDR0_REG 0x81D0 -#define SSTREAM_FBADDR1_REG 0x81D4 -#define SSTREAM_STRIDE_REG 0x81D8 -#define OPAQUE_OVERLAY_CONTROL_REG 0x81DC -#define K1_VSCALE_REG 0x81E0 -#define K2_VSCALE_REG 0x81E4 -#define DDA_VERT_REG 0x81E8 -#define STREAMS_FIFO_REG 0x81EC -#define PSTREAM_START_REG 0x81F0 -#define PSTREAM_WINDOW_SIZE_REG 0x81F4 -#define SSTREAM_START_REG 0x81F8 -#define SSTREAM_WINDOW_SIZE_REG 0x81FC - -#define S3_MEMBASE sreg -#define S3_NEWMMIO_REGBASE 0x1000000 /* 16MB */ -#define S3_NEWMMIO_REGSIZE 0x10000 /* 64KB */ -#define S3V_MMIO_REGSIZE 0x8000 /* 32KB */ -#define S3_NEWMMIO_VGABASE (S3_NEWMMIO_REGBASE + 0x8000) - -#define OUTREG(mmreg, value) *(unsigned int *)(&v->mmio[mmreg]) = value - -static int readcrtc(int reg) -{ - outb(reg, 0x3d4); - return inb(0x3d5); -} - -static void writecrtc(int reg, int value) -{ - outb(reg, 0x3d4); - outb(value, 0x3d5); -} - -// enable S3 registers -static int enable(void) -{ - int fd; - - if (v) - return 1; - errno = 0; - v = malloc(sizeof(vga_t)); - if (v) { - if (ioperm(0x3d4, 2, 1) == 0) { - fd = open("/dev/mem", O_RDWR); - if (fd != -1) { - v->mmio = mmap(0, S3_NEWMMIO_REGSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, - S3_MEMBASE + S3_NEWMMIO_REGBASE); - close(fd); - if (v->mmio != MAP_FAILED) { - v->cr38 = readcrtc(0x38); - v->cr39 = readcrtc(0x39); - v->cr53 = readcrtc(0x53); - writecrtc(0x38, 0x48); - writecrtc(0x39, 0xa5); - writecrtc(0x53, 0x08); - return 1; - } - } - iopl(0); - } - free(v); - v = NULL; - } - return 0; -} - -static void disable(void) -{ - if (v) { - writecrtc(0x53, v->cr53); - writecrtc(0x39, v->cr39); - writecrtc(0x38, v->cr38); - ioperm(0x3d4, 2, 0); - munmap(v->mmio, S3_NEWMMIO_REGSIZE); - free(v); - v = NULL; - } -} - -static int yuv_on(int format, int src_w, int src_h, int dst_x, int dst_y, - int dst_w, int dst_h, int crop, int xres, int yres, - int line_length, int offset) -{ - int tmp, pitch, start, src_wc, src_hc, bpp; - - if (format == 0 || format == 7) - bpp = 4; - else if (format == 6) - bpp = 3; - else - bpp = 2; - - src_wc = src_w - crop * 2; - src_hc = src_h - crop * 2; - pitch = src_w * bpp; - - // video card memory layout: - // 0-n: visible screen memory, n = width * height * bytes per pixel - // n-m: scaler source memory, n is aligned to a page boundary - // m+: scaler source memory for multiple buffers - - // offset is the first aligned byte after the screen memory, where the scaler input buffer is - tmp = (yres * line_length + 4095) & ~4095; - offset += tmp; - - // start is the top left viewable scaler input pixel - start = offset + crop * pitch + crop * bpp; - - OUTREG(COL_CHROMA_KEY_CONTROL_REG, 0x47000000); - OUTREG(CHROMA_KEY_UPPER_BOUND_REG, 0x0); - OUTREG(BLEND_CONTROL_REG, 0x00000020); - OUTREG(DOUBLE_BUFFER_REG, 0x0); /* Choose fbaddr0 as stream source. */ - OUTREG(OPAQUE_OVERLAY_CONTROL_REG, 0x0); - - OUTREG(PSTREAM_CONTROL_REG, 0x06000000); - OUTREG(PSTREAM_FBADDR0_REG, 0x0); - OUTREG(PSTREAM_FBADDR1_REG, 0x0); - OUTREG(PSTREAM_STRIDE_REG, line_length); - OUTREG(PSTREAM_START_REG, 0x00010001); - OUTREG(PSTREAM_WINDOW_SIZE_REG, 0x00010001); - //OUTREG(SSTREAM_WINDOW_SIZE_REG, ( ((xres-1) << 16) | yres) & 0x7ff07ff); - - if (dst_w == src_w) - tmp = 0; - else - tmp = 2; - /* format 1=YCbCr-16 2=YUV-16 3=BGR15 4=YUV-16/32(mixed 2/4byte stride) 5=BGR16 6=BGR24 0,7=BGR32 */ - /* The YUV format pixel has a range of value from 0 to 255, while the YCbCr format pixel values are in the range of 16 to 240. */ - OUTREG(SSTREAM_CONTROL_REG, tmp << 28 | (format << 24) | - ((((src_wc-1)<<1)-(dst_w-1)) & 0xfff)); - OUTREG(SSTREAM_STRETCH_REG, - ((src_wc - 1) & 0x7ff) | (((src_wc - dst_w-1) & 0x7ff) << 16)); - OUTREG(SSTREAM_FBADDR0_REG, start & 0x3fffff ); - OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff ); - OUTREG(SSTREAM_START_REG, ((dst_x + 1) << 16) | (dst_y + 1)); - OUTREG(SSTREAM_WINDOW_SIZE_REG, ( ((dst_w-1) << 16) | (dst_h ) ) & 0x7ff07ff); - OUTREG(K1_VSCALE_REG, src_hc - 1 ); - OUTREG(K2_VSCALE_REG, (src_hc - dst_h) & 0x7ff ); - /* 0xc000 = bw & vert interp */ - /* 0x8000 = no bw save */ - OUTREG(DDA_VERT_REG, (((~dst_h)-1) & 0xfff ) | 0xc000); - writecrtc(0x92, (((pitch + 7) / 8) >> 8) | 0x80); - writecrtc(0x93, (pitch + 7) / 8); - - writecrtc(0x67, readcrtc(0x67) | 0x4); - - return offset; -} - -static void yuv_off(void) -{ - writecrtc(0x67, readcrtc(0x67) & ~0xc); - memset(v->mmio + 0x8180, 0, 0x80); - OUTREG(0x81b8, 0x900); - OUTREG(0x81bc, 0x900); - OUTREG(0x81c8, 0x900); - OUTREG(0x81cc, 0x900); - OUTREG(0x81d8, 0x1); - OUTREG(0x81f8, 0x07ff07ff); - OUTREG(0x81fc, 0x00010001); - writecrtc(0x92, 0); - writecrtc(0x93, 0); -} - -static int preinit(const char *arg) -{ - char *name; - - if(arg) - name = (char*)arg; - else if(!(name = getenv("FRAMEBUFFER"))) - name = "/dev/fb0"; - - if((fd = open(name, O_RDWR)) == -1) { - mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: can't open %s: %s\n", name, strerror(errno)); - return -1; - } - - if(ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo)) { - mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: problem with FBITGET_FSCREENINFO ioctl: %s\n", - strerror(errno)); - close(fd); - fd = -1; - return -1; - } - - if(ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo)) { - mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: problem with FBITGET_VSCREENINFO ioctl: %s\n", - strerror(errno)); - close(fd); - fd = -1; - return -1; - } - - // Check the depth now as config() musn't fail - switch(fb_vinfo.bits_per_pixel) { - case 16: - case 24: - case 32: - break; // Ok - default: - mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: %d bpp output is not supported\n", fb_vinfo.bits_per_pixel); - close(fd); - fd = -1; - return -1; - } - - /* Open up a window to the hardware */ - smem = mmap(0, fb_finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - sreg = fb_finfo.smem_start; - - if(smem == (void *)-1) { - mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: Couldn't map memory areas: %s\n", strerror(errno)); - smem = NULL; - close(fd); - fd = -1; - return -1; - } - - if (!enable()) { - mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: Couldn't map S3 registers: %s\n", strerror(errno)); - close(fd); - fd = -1; - return -1; - } - - return 0; // Success -} - -/* And close our mess */ -static void uninit(void) -{ - if (inpage0) { - clear_screen(); - yuv_off(); - inpage0 = NULL; - } - - if(smem) { - munmap(smem, fb_finfo.smem_len); - smem = NULL; - } - - disable(); - - if(fd != -1) { - close(fd); - fd = -1; - } -} - -static void clear_screen(void) -{ - if (inpage0) { - int n; - - memset(smem, 0, screenheight * screenstride); - - if (in_format == IMGFMT_YUY2) { - unsigned short *ptr; - int i; - - ptr = (unsigned short *)inpage0; - n = in_width * in_height; - if (vo_doublebuffering) - n *= 2; - for(i=0; i<n; i++) - *ptr++ = 0x8000; - - } else { - n = in_depth * in_width * in_height; - if (vo_doublebuffering) - n *= 2; - memset(inpage0, 0, n); - } - } -} - -/* Setup output screen dimensions etc */ -static void setup_screen(uint32_t full) -{ - int inpageoffset; - - aspect(&vidwidth, &vidheight, full ? A_ZOOM : A_NOZOOM); - - // center picture - vidx = (screenwidth - vidwidth) / 2; - vidy = (screenheight - vidheight) / 2; - - geometry(&vidx, &vidy, &vidwidth, &vidheight, screenwidth, screenheight); - vo_fs = full; - - inpageoffset = yuv_on(in_s3_format, in_width, in_height, vidx, vidy, vidwidth, vidheight, 0, screenwidth, screenheight, screenstride, 0); - inpage0 = smem + inpageoffset; - inpage = inpage0; - mp_msg(MSGT_VO, MSGL_INFO, "s3fb: output is at %dx%d +%dx%d\n", vidx, vidy, vidwidth, vidheight); - - clear_screen(); -} - -static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, - uint32_t flags, char *title, uint32_t format) -{ - screenwidth = fb_vinfo.xres; - screenheight = fb_vinfo.yres; - screenstride = fb_finfo.line_length; - aspect_save_screenres(fb_vinfo.xres,fb_vinfo.yres); - - in_width = width; - in_height = height; - in_format = format; - aspect_save_orig(width,height); - - aspect_save_prescale(d_width,d_height); - - /* Setup the screen for rendering to */ - screendepth = fb_vinfo.bits_per_pixel / 8; - - switch(in_format) { - - case IMGFMT_YUY2: - in_depth = 2; - in_s3_format = 1; - alpha_func = vo_draw_alpha_yuy2; - break; - - case IMGFMT_BGR15: - in_depth = 2; - in_s3_format = 3; - alpha_func = vo_draw_alpha_rgb16; - break; - - case IMGFMT_BGR16: - in_depth = 2; - in_s3_format = 5; - alpha_func = vo_draw_alpha_rgb16; - break; - - case IMGFMT_BGR24: - in_depth = 3; - in_s3_format = 6; - alpha_func = vo_draw_alpha_rgb24; - break; - - case IMGFMT_BGR32: - in_depth = 4; - in_s3_format = 7; - alpha_func = vo_draw_alpha_rgb32; - break; - - default: - mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: Eik! Something's wrong with control().\n"); - return -1; - } - - offset = in_width * in_depth * in_height; - if (vo_doublebuffering) - page = offset; - else - page = 0; - - if(screenheight * screenstride + page + offset > fb_finfo.smem_len) { - mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: Not enough video memory to play this movie. Try at a lower resolution\n"); - return -1; - } - - setup_screen(flags & VOFLAG_FULLSCREEN); - if (vo_doublebuffering) - inpage = inpage0 + page; - - mp_msg(MSGT_VO, MSGL_INFO, "s3fb: screen is %dx%d at %d bpp, in is %dx%d at %d bpp, norm is %dx%d\n", - screenwidth, screenheight, screendepth * 8, - in_width, in_height, in_depth * 8, - d_width, d_height); - - return 0; -} - -static void draw_alpha(int x, int y, int w, int h, unsigned char *src, - unsigned char *srca, int stride) -{ - char *dst = inpage + (y * in_width + x) * in_depth; - alpha_func(w, h, src, srca, stride, dst, in_width * in_depth); -} - -static void draw_osd(void) -{ - if (!vo_doublebuffering) - vo_draw_text(in_width, in_height, draw_alpha); -} - -/* Render onto the screen */ -static void flip_page(void) -{ - if(vo_doublebuffering) { - vo_draw_text(in_width, in_height, draw_alpha); - yuv_on(in_s3_format, in_width, in_height, vidx, vidy, vidwidth, vidheight, 0, screenwidth, screenheight, screenstride, page); - page ^= offset; - inpage = inpage0 + page; - } -} - -static int draw_frame(uint8_t *src[]) -{ - mem2agpcpy(inpage, src[0], in_width * in_depth * in_height); - return 0; -} - -static int draw_slice(uint8_t *i[], int s[], int w, int h, int x, int y) -{ - return 1; -} - -/* Attempt to start doing DR */ -static uint32_t get_image(mp_image_t *mpi) -{ - - if(mpi->flags & MP_IMGFLAG_READABLE) - return VO_FALSE; - if(mpi->type == MP_IMGTYPE_STATIC && vo_doublebuffering) - return VO_FALSE; - if(mpi->type > MP_IMGTYPE_TEMP) - return VO_FALSE; // TODO ?? - - switch(in_format) { - case IMGFMT_BGR15: - case IMGFMT_BGR16: - case IMGFMT_BGR24: - case IMGFMT_BGR32: - case IMGFMT_YUY2: - mpi->planes[0] = inpage; - mpi->stride[0] = in_width * in_depth; - break; - - default: - return VO_FALSE; - } - - mpi->width = in_width; - mpi->flags |= MP_IMGFLAG_DIRECT; - - return VO_TRUE; -} - -static int control(uint32_t request, void *data) -{ - switch(request) { - case VOCTRL_GET_IMAGE: - return get_image(data); - - case VOCTRL_QUERY_FORMAT: - switch(*((uint32_t*)data)) { - case IMGFMT_BGR15: - case IMGFMT_BGR16: - case IMGFMT_BGR24: - case IMGFMT_BGR32: - case IMGFMT_YUY2: - return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | - VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN; - } - - return 0; /* Not supported */ - - case VOCTRL_FULLSCREEN: - setup_screen(!vo_fs); - return 0; - } - - return VO_NOTIMPL; -} - -/* Dummy funcs */ -static void check_events(void) {} |