summaryrefslogtreecommitdiff
path: root/src/video_out/vidix/drivers/pm3_vid.c
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-01-13 23:36:01 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-01-13 23:36:01 +0000
commit9baa6d2f372d3e09280e1103d7bfcf048f6457ec (patch)
treecf3bfc3fb392fe58ed612a5a09c11d176eb17e99 /src/video_out/vidix/drivers/pm3_vid.c
parent989188f25474868841d8a5148873a5995be58c6f (diff)
downloadxine-lib-9baa6d2f372d3e09280e1103d7bfcf048f6457ec.tar.gz
xine-lib-9baa6d2f372d3e09280e1103d7bfcf048f6457ec.tar.bz2
big vidix driver update by James Stembridge
CVS patchset: 3907 CVS date: 2003/01/13 23:36:01
Diffstat (limited to 'src/video_out/vidix/drivers/pm3_vid.c')
-rw-r--r--src/video_out/vidix/drivers/pm3_vid.c367
1 files changed, 254 insertions, 113 deletions
diff --git a/src/video_out/vidix/drivers/pm3_vid.c b/src/video_out/vidix/drivers/pm3_vid.c
index c5b97782c..20b35a14a 100644
--- a/src/video_out/vidix/drivers/pm3_vid.c
+++ b/src/video_out/vidix/drivers/pm3_vid.c
@@ -24,16 +24,20 @@
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
+#include <sys/mman.h>
#include "vidix.h"
#include "fourcc.h"
#include "libdha.h"
#include "pci_ids.h"
#include "pci_names.h"
-#include "config.h"
#include "pm3_regs.h"
+#define PM3_MSG "pm3_vid:"
+
+#define VIDIX_STATIC pm3_
+
/* MBytes of video memory to use */
#define PM3_VIDMEM 24
@@ -45,12 +49,16 @@
#define TRACE_EXIT()
#endif
-pciinfo_t pci_info;
+static pciinfo_t pci_info;
-void *pm3_reg_base;
-void *pm3_mem;
+static void *pm3_reg_base;
+static void *pm3_mem;
-int pm3_vidmem = PM3_VIDMEM;
+static int pm3_vidmem = PM3_VIDMEM;
+static int pm3_blank = 0;
+static int pm3_dma = 0;
+
+static u_int page_size;
static vidix_capability_t pm3_cap =
{
@@ -63,14 +71,14 @@ static vidix_capability_t pm3_cap =
4,
4,
-1,
- FLAG_UPSCALER|FLAG_DOWNSCALER,
+ FLAG_UPSCALER | FLAG_DOWNSCALER,
VENDOR_3DLABS,
-1,
{ 0, 0, 0, 0 }
};
-unsigned int vixGetVersion(void)
+unsigned int VIDIX_NAME(vixGetVersion)(void)
{
return(VIDIX_VERSION);
}
@@ -90,7 +98,7 @@ static int find_chip(unsigned chip_id)
return -1;
}
-int vixProbe(int verbose, int force)
+int VIDIX_NAME(vixProbe)(int verbose, int force)
{
pciinfo_t lst[MAX_PCI_DEVICES];
unsigned i,num_pci;
@@ -99,7 +107,7 @@ int vixProbe(int verbose, int force)
err = pci_scan(lst,&num_pci);
if(err)
{
- printf("[pm3] Error occured during pci scan: %s\n",strerror(err));
+ printf(PM3_MSG" Error occured during pci scan: %s\n",strerror(err));
return err;
}
else
@@ -116,7 +124,8 @@ int vixProbe(int verbose, int force)
continue;
dname = pci_device_name(VENDOR_3DLABS, lst[i].device);
dname = dname ? dname : "Unknown chip";
- printf("[pm3] Found chip: %s\n", dname);
+ printf(PM3_MSG" Found chip: %s with IRQ %i\n",
+ dname, lst[i].irq);
pm3_cap.device_id = lst[i].device;
err = 0;
memcpy(&pci_info, &lst[i], sizeof(pciinfo_t));
@@ -124,34 +133,62 @@ int vixProbe(int verbose, int force)
}
}
}
- if(err && verbose) printf("[pm3] Can't find chip\n");
+ if(err && verbose) printf(PM3_MSG" Can't find chip\n");
return err;
}
#define PRINT_REG(reg) \
{ \
long _foo = READ_REG(reg); \
- printf("[pm3] " #reg " (%x) = %#lx (%li)\n", reg, _foo, _foo); \
+ printf(PM3_MSG" " #reg " (%x) = %#lx (%li)\n", reg, _foo, _foo); \
}
-int vixInit(void)
+int VIDIX_NAME(vixInit)(const char *args)
{
- char *vm;
+ char *ac = strdup(args), *s, *opt;
+
+ opt = strtok_r(ac, ",", &s);
+ while(opt){
+ char *a = strchr(opt, '=');
+
+ if(a)
+ *a++ = 0;
+ if(!strcmp(opt, "mem")){
+ if(a)
+ pm3_vidmem = strtol(a, NULL, 0);
+ } else if(!strcmp(opt, "blank")){
+ pm3_blank = a? strtol(a, NULL, 0): 1;
+ }
+
+ opt = strtok_r(NULL, ",", &s);
+ }
+
+ free(ac);
+
pm3_reg_base = map_phys_mem(pci_info.base0, 0x20000);
pm3_mem = map_phys_mem(pci_info.base1, 0x2000000);
- if((vm = getenv("PM3_VIDMEM"))){
- pm3_vidmem = strtol(vm, NULL, 0);
+
+ if(bm_open() == 0){
+ printf(PM3_MSG" Using DMA.\n");
+ pm3_cap.flags |= FLAG_DMA;
+ page_size = sysconf(_SC_PAGESIZE);
+ hwirq_install(pci_info.bus, pci_info.card, pci_info.func,
+ 0, PM3IntFlags, -1);
+ pm3_dma = 1;
}
+
return 0;
}
-void vixDestroy(void)
+void VIDIX_NAME(vixDestroy)(void)
{
unmap_phys_mem(pm3_reg_base, 0x20000);
unmap_phys_mem(pm3_mem, 0x2000000);
+ hwirq_uninstall(pci_info.bus, pci_info.card, pci_info.func);
+ bm_close();
}
-int vixGetCapability(vidix_capability_t *to)
+int VIDIX_NAME(vixGetCapability)(vidix_capability_t *to)
{
memcpy(to, &pm3_cap, sizeof(vidix_capability_t));
return 0;
@@ -168,7 +205,7 @@ static int is_supported_fourcc(uint32_t fourcc)
}
}
-int vixQueryFourcc(vidix_fourcc_t *to)
+int VIDIX_NAME(vixQueryFourcc)(vidix_fourcc_t *to)
{
if(is_supported_fourcc(to->fourcc))
{
@@ -184,6 +221,12 @@ int vixQueryFourcc(vidix_fourcc_t *to)
return ENOSYS;
}
+static int frames[VID_PLAY_MAXFRAMES], vid_base;
+static long overlay_mode, overlay_control, video_control, int_enable;
+static int src_w, drw_w;
+static int src_h, drw_h;
+static int drw_x, drw_y;
+
#define FORMAT_RGB8888 PM3VideoOverlayMode_COLORFORMAT_RGB8888
#define FORMAT_RGB4444 PM3VideoOverlayMode_COLORFORMAT_RGB4444
#define FORMAT_RGB5551 PM3VideoOverlayMode_COLORFORMAT_RGB5551
@@ -202,9 +245,8 @@ int vixQueryFourcc(vidix_fourcc_t *to)
/* Notice, have to check that we dont overflow the deltas here ... */
static void
-compute_scale_factor(
- short* src_w, short* dst_w,
- unsigned int* shrink_delta, unsigned int* zoom_delta)
+compute_scale_factor(int* src_w, int* dst_w,
+ u_int* shrink_delta, u_int* zoom_delta)
{
/* NOTE: If we don't return reasonable values here then the video
* unit can potential shut off and won't display an image until re-enabled.
@@ -228,21 +270,13 @@ compute_scale_factor(
}
}
-static int frames[VID_PLAY_MAXFRAMES];
-
-static long overlay_mode, overlay_control;
-
-int vixConfigPlayback(vidix_playback_t *info)
+static void
+pm3_setup_overlay(vidix_playback_t *info)
{
int shrink, zoom;
- short src_w, drw_w;
- short src_h, drw_h;
- long base0;
- int pitch;
- int format;
- unsigned int i;
-
- TRACE_ENTER();
+ int format = 0;
+ int filter = 0;
+ int sw = src_w;
switch(info->fourcc){
case IMGFMT_YUY2:
@@ -251,97 +285,46 @@ int vixConfigPlayback(vidix_playback_t *info)
case IMGFMT_UYVY:
format = FORMAT_VUY422;
break;
- default:
- return -1;
}
- src_w = info->src.w;
- src_h = info->src.h;
+ compute_scale_factor(&sw, &drw_w, &shrink, &zoom);
- drw_w = info->dest.w;
- drw_h = info->dest.h;
-
- pitch = src_w;
-
- info->num_frames = pm3_vidmem*1024*1024 / (pitch * src_h * 2);
- if(info->num_frames > VID_PLAY_MAXFRAMES)
- info->num_frames = VID_PLAY_MAXFRAMES;
-
- /* Use end of video memory. Assume the card has 32 MB */
- base0 = (32-pm3_vidmem)*1024*1024;
- info->dga_addr = pm3_mem + base0;
-
- if(info->fourcc == IMGFMT_YV12){
- info->dest.pitch.y = 2;
- info->dest.pitch.u = 2;
- info->dest.pitch.y = 2;
- info->offset.y = 0;
- info->offset.v = src_w * src_h;
- info->offset.u = src_w * src_h * 3/2;
- } else {
- info->dest.pitch.y = 2;
- info->dest.pitch.u = 0;
- info->dest.pitch.v = 0;
- info->offset.y = 0;
- info->offset.v = 0;
- info->offset.u = 0;
- }
- info->frame_size = pitch * src_h * 2;
-
- for(i = 0; i < info->num_frames; i++){
- info->offsets[i] = info->frame_size * i;
- frames[i] = (base0 + info->offsets[i]) >> 1;
- }
-
- compute_scale_factor(&src_w, &drw_w, &shrink, &zoom);
-
-#if 0
- aperture_mode = READ_REG(PM3ByAperture1Mode);
- if(info->fourcc == IMGFMT_YV12){
-/* WRITE_REG(PM3Aperture0, base0 >> 1); */
- WRITE_REG(PM3ByAperture1Mode,
- PM3ByApertureMode_FORMAT_YUYV |
- PM3ByApertureMode_PIXELSIZE_32BIT);
- WRITE_REG(PM3Aperture1Stride, pitch);
- WRITE_REG(PM3Aperture1YStart, base0 / 16);
- WRITE_REG(PM3Aperture1VStart, (base0 + info->offset.v) / 16);
- WRITE_REG(PM3Aperture1UStart, (base0 + info->offset.u) / 16);
- }
-#endif
-
- WRITE_REG(PM3VideoOverlayBase0, base0 >> 1);
- WRITE_REG(PM3VideoOverlayStride, PM3VideoOverlayStride_STRIDE(pitch));
- WRITE_REG(PM3VideoOverlayWidth, PM3VideoOverlayWidth_WIDTH(src_w));
+ WRITE_REG(PM3VideoOverlayBase0, vid_base >> 1);
+ WRITE_REG(PM3VideoOverlayStride, PM3VideoOverlayStride_STRIDE(src_w));
+ WRITE_REG(PM3VideoOverlayWidth, PM3VideoOverlayWidth_WIDTH(sw));
WRITE_REG(PM3VideoOverlayHeight, PM3VideoOverlayHeight_HEIGHT(src_h));
WRITE_REG(PM3VideoOverlayOrigin, 0);
/* Scale the source to the destinationsize */
- if (src_h == drw_h) {
- WRITE_REG(PM3VideoOverlayYDelta, PM3VideoOverlayYDelta_NONE);
- } else {
- WRITE_REG(PM3VideoOverlayYDelta,
- PM3VideoOverlayYDelta_DELTA(src_h, drw_h));
- }
if (src_w == drw_w) {
WRITE_REG(PM3VideoOverlayShrinkXDelta, 1<<16);
WRITE_REG(PM3VideoOverlayZoomXDelta, 1<<16);
} else {
WRITE_REG(PM3VideoOverlayShrinkXDelta, shrink);
WRITE_REG(PM3VideoOverlayZoomXDelta, zoom);
+ filter = PM3VideoOverlayMode_FILTER_PARTIAL;
}
+ if (src_h == drw_h) {
+ WRITE_REG(PM3VideoOverlayYDelta, PM3VideoOverlayYDelta_NONE);
+ } else {
+ WRITE_REG(PM3VideoOverlayYDelta,
+ PM3VideoOverlayYDelta_DELTA(src_h, drw_h));
+ filter = PM3VideoOverlayMode_FILTER_FULL;
+ }
+
WRITE_REG(PM3VideoOverlayIndex, 0);
/* Now set the ramdac video overlay region and mode */
- RAMDAC_SET_REG(PM3RD_VideoOverlayXStartLow, (info->dest.x & 0xff));
- RAMDAC_SET_REG(PM3RD_VideoOverlayXStartHigh, (info->dest.x & 0xf00)>>8);
- RAMDAC_SET_REG(PM3RD_VideoOverlayXEndLow, (info->dest.x+drw_w) & 0xff);
+ RAMDAC_SET_REG(PM3RD_VideoOverlayXStartLow, (drw_x & 0xff));
+ RAMDAC_SET_REG(PM3RD_VideoOverlayXStartHigh, (drw_x & 0xf00)>>8);
+ RAMDAC_SET_REG(PM3RD_VideoOverlayXEndLow, (drw_x+drw_w) & 0xff);
RAMDAC_SET_REG(PM3RD_VideoOverlayXEndHigh,
- ((info->dest.x+drw_w) & 0xf00)>>8);
- RAMDAC_SET_REG(PM3RD_VideoOverlayYStartLow, (info->dest.y & 0xff));
- RAMDAC_SET_REG(PM3RD_VideoOverlayYStartHigh, (info->dest.y & 0xf00)>>8);
- RAMDAC_SET_REG(PM3RD_VideoOverlayYEndLow, (info->dest.y+drw_h) & 0xff);
+ ((drw_x+drw_w) & 0xf00)>>8);
+ RAMDAC_SET_REG(PM3RD_VideoOverlayYStartLow, (drw_y & 0xff));
+ RAMDAC_SET_REG(PM3RD_VideoOverlayYStartHigh, (drw_y & 0xf00)>>8);
+ RAMDAC_SET_REG(PM3RD_VideoOverlayYEndLow, (drw_y+drw_h) & 0xff);
RAMDAC_SET_REG(PM3RD_VideoOverlayYEndHigh,
- ((info->dest.y+drw_h) & 0xf00)>>8);
+ ((drw_y+drw_h) & 0xf00)>>8);
RAMDAC_SET_REG(PM3RD_VideoOverlayKeyR, 0xff);
RAMDAC_SET_REG(PM3RD_VideoOverlayKeyG, 0x00);
@@ -350,20 +333,71 @@ int vixConfigPlayback(vidix_playback_t *info)
overlay_mode =
1 << 5 |
format |
- PM3VideoOverlayMode_FILTER_FULL |
+ filter |
PM3VideoOverlayMode_BUFFERSYNC_MANUAL |
PM3VideoOverlayMode_FLIP_VIDEO;
overlay_control =
PM3RD_VideoOverlayControl_KEY_COLOR |
- PM3RD_VideoOverlayControl_MODE_OVERLAYKEY |
+ PM3RD_VideoOverlayControl_MODE_ALWAYS |
PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED;
+}
+
+int VIDIX_NAME(vixConfigPlayback)(vidix_playback_t *info)
+{
+ unsigned int i;
+ u_int frame_size;
+ u_int vidmem_size;
+ u_int max_frames;
+
+ TRACE_ENTER();
+
+ src_w = info->src.w;
+ src_h = info->src.h;
+ drw_w = info->dest.w;
+ drw_h = info->dest.h;
+ drw_x = info->dest.x;
+ drw_y = info->dest.y;
+
+ frame_size = src_w * src_h * 2;
+ vidmem_size = pm3_vidmem*1024*1024;
+ max_frames = vidmem_size / frame_size;
+ if(max_frames > VID_PLAY_MAXFRAMES)
+ max_frames = VID_PLAY_MAXFRAMES;
+
+ src_h--; /* ugh */
+
+ if(info->num_frames > max_frames)
+ info->num_frames = max_frames;
+ vidmem_size = info->num_frames * frame_size;
+
+ /* Use end of video memory. Assume the card has 32 MB */
+ vid_base = 32*1024*1024 - vidmem_size;
+ info->dga_addr = pm3_mem + vid_base;
+
+ info->dest.pitch.y = 2;
+ info->dest.pitch.u = 0;
+ info->dest.pitch.v = 0;
+ info->offset.y = 0;
+ info->offset.v = 0;
+ info->offset.u = 0;
+ info->frame_size = frame_size;
+
+ for(i = 0; i < info->num_frames; i++){
+ info->offsets[i] = frame_size * i;
+ frames[i] = (vid_base + info->offsets[i]) >> 1;
+ }
+
+ pm3_setup_overlay(info);
+
+ video_control = READ_REG(PM3VideoControl);
+ int_enable = READ_REG(PM3IntEnable);
TRACE_EXIT();
return 0;
}
-int vixPlaybackOn(void)
+int VIDIX_NAME(vixPlaybackOn)(void)
{
TRACE_ENTER();
@@ -374,11 +408,15 @@ int vixPlaybackOn(void)
WRITE_REG(PM3VideoOverlayUpdate,
PM3VideoOverlayUpdate_ENABLE);
+ if(pm3_blank)
+ WRITE_REG(PM3VideoControl,
+ video_control | PM3VideoControl_DISPLAY_ENABLE);
+
TRACE_EXIT();
return 0;
}
-int vixPlaybackOff(void)
+int VIDIX_NAME(vixPlaybackOff)(void)
{
RAMDAC_SET_REG(PM3RD_VideoOverlayControl,
PM3RD_VideoOverlayControl_DISABLE);
@@ -389,12 +427,115 @@ int vixPlaybackOff(void)
RAMDAC_SET_REG(PM3RD_VideoOverlayKeyG, 0x01);
RAMDAC_SET_REG(PM3RD_VideoOverlayKeyB, 0xfe);
+ if(video_control)
+ WRITE_REG(PM3VideoControl, video_control);
+
+ if(pm3_dma)
+ WRITE_REG(PM3IntEnable, 0);
+
return 0;
}
-int vixPlaybackFrameSelect(unsigned int frame)
+int VIDIX_NAME(vixPlaybackFrameSelect)(unsigned int frame)
{
WRITE_REG(PM3VideoOverlayBase0, frames[frame]);
-/* WRITE_REG(PM3Aperture0, frames[frame]); */
+
+ return 0;
+}
+
+struct pm3_bydma_cmd {
+ uint32_t bus_addr;
+ uint32_t fb_addr;
+ uint32_t mask;
+ uint32_t count;
+};
+
+struct pm3_bydma_frame {
+ struct pm3_bydma_cmd *cmds;
+ u_long bus_addr;
+ uint32_t count;
+};
+
+static struct pm3_bydma_frame *
+pm3_setup_bydma(vidix_dma_t *dma)
+{
+ u_int size = dma->size;
+ u_int pages = (size + page_size-1) / page_size;
+ struct pm3_bydma_frame *bdf;
+ long baddr[pages];
+ u_int i;
+ uint32_t dest;
+
+ if(bm_virt_to_bus(dma->src, dma->size, baddr))
+ return NULL;
+
+ bdf = malloc(sizeof(*bdf));
+ bdf->cmds = valloc(pages * sizeof(struct pm3_bydma_cmd));
+
+ dest = vid_base + dma->dest_offset;
+ for(i = 0; i < pages; i++, dest += page_size, size -= page_size){
+ bdf->cmds[i].bus_addr = baddr[i];
+ bdf->cmds[i].fb_addr = dest;
+ bdf->cmds[i].mask = ~0;
+ bdf->cmds[i].count = ((size > page_size)? page_size: size) / 16;
+ }
+
+ bdf->count = pages;
+
+ if(bm_virt_to_bus(bdf->cmds, page_size, &bdf->bus_addr) != 0){
+ free(bdf->cmds);
+ free(bdf);
+ return NULL;
+ }
+
+ return bdf;
+}
+
+extern int
+VIDIX_NAME(vixPlaybackCopyFrame)(vidix_dma_t *dma)
+{
+ u_int frame = dma->idx;
+ struct pm3_bydma_frame *bdf;
+
+ if(dma->internal[frame]){
+ bdf = dma->internal[frame];
+ } else {
+ if(!(bdf = pm3_setup_bydma(dma))){
+ return -1;
+ } else if(dma->flags & BM_DMA_FIXED_BUFFS){
+ if(mlock(bdf->cmds, page_size) == 0){
+ dma->internal[frame] = bdf;
+ } else {
+ printf(PM3_MSG" Can't lock page @ %p\n", bdf->cmds);
+ }
+ }
+ }
+
+ if(dma->flags & BM_DMA_SYNC){
+ WRITE_REG(PM3IntEnable, (1 << 7));
+ while(READ_REG(PM3ByDMAReadMode) & PM3ByDMAReadMode_Active){
+ hwirq_wait(pci_info.irq);
+ }
+ WRITE_REG(PM3IntEnable, 0);
+ }
+
+ WAIT_FIFO(3);
+ WRITE_REG(PM3ByDMAReadCommandBase, bdf->bus_addr);
+ WRITE_REG(PM3ByDMAReadCommandCount, bdf->count);
+ WRITE_REG(PM3ByDMAReadMode,
+ PM3ByDMAReadMode_ByteSwap_NONE |
+ PM3ByDMAReadMode_Format_RAW |
+ PM3ByDMAReadMode_PixelSize(16) |
+ PM3ByDMAReadMode_Active |
+ PM3ByDMAReadMode_Burst(7) |
+ PM3ByDMAReadMode_Align);
+
return 0;
}
+
+extern int
+VIDIX_NAME(vixQueryDMAStatus)(void)
+{
+ uint32_t bdm = READ_REG(PM3ByDMAReadMode);
+ return (bdm & PM3ByDMAReadMode_Active)? 1: 0;
+}