blob: 95409927f1005b63075857eb674e352ff4de3dd3 [file] [log] [blame]
/*
* Copyright 2008 Sony Corporation of America
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <asm/ps3fb.h>
#define VFB_DEVICE "/dev/fb0"
#define VFB_BPP 4
typedef struct
{
int device;
unsigned int size;
unsigned int xres;
unsigned int yres;
unsigned int xoff;
unsigned int yoff;
unsigned int frames;
void * addr;
} vfb_t __attribute__((aligned(128)));
static inline int vfb_open(vfb_t *vfb)
{
struct ps3fb_ioctl_res res;
struct fb_vblank vblank;
memset(vfb, 0, sizeof(vfb_t));
if ((vfb->device = open(VFB_DEVICE, O_RDWR)) < 0)
return -1;
if (ioctl(vfb->device, FBIOGET_VBLANK, (unsigned long)&vblank) < 0) {
close(vfb->device);
return -1;
} else if (!(vblank.flags & FB_VBLANK_HAVE_VSYNC)) {
close(vfb->device);
return -1;
}
if (ioctl(vfb->device, PS3FB_IOCTL_SCREENINFO, (unsigned long)&res) < 0) {
close(vfb->device);
return -1;
}
vfb->frames = res.num_frames;
vfb->xres = res.xres;
vfb->yres = res.yres;
vfb->xoff = res.xoff;
vfb->yoff = res.yoff;
vfb->size = res.xres * res.yres * VFB_BPP * res.num_frames - res.xres * res.yoff * VFB_BPP * 2;
vfb->addr = mmap(NULL, vfb->size, PROT_WRITE, MAP_SHARED, vfb->device, 0);
if (vfb->addr == MAP_FAILED) {
close(vfb->device);
return -1;
}
ioctl(vfb->device, PS3FB_IOCTL_ON, 0);
memset(vfb->addr, 0, vfb->size);
return 0;
}
static inline int vfb_close(vfb_t *vfb)
{
ioctl(vfb->device, PS3FB_IOCTL_OFF, 0);
munmap(vfb->addr, vfb->size);
close(vfb->device);
return 0;
}
static inline int vfb_clear(vfb_t *vfb)
{
memset(vfb->addr, 0, vfb->size);
return 0;
}
static inline int vfb_wait_vsync(vfb_t * vfb)
{
uint32_t crt = 0;
ioctl(vfb->device, FBIO_WAITFORVSYNC, (unsigned long)&crt);
return 0;
}
static inline int vfb_flip(vfb_t *vfb, unsigned int frame)
{
uint32_t frm = frame;
if (frm >= vfb->frames)
return -1;
ioctl(vfb->device, PS3FB_IOCTL_FSEL, (unsigned long)&frm);
return 0;
}