/*
* linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006, 2007 Sony Corporation
*
* This file is based on :
*
* linux/drivers/video/vfb.c -- Virtual frame buffer device
*
* Copyright (C) 2002 James Simmons
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/console.h>
#include <linux/ioctl.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <asm/cell-regs.h>
#include <asm/lv1call.h>
#include <asm/ps3av.h>
#include <asm/ps3fb.h>
#include <asm/ps3.h>
#include <asm/ps3gpu.h>
#define DEVICE_NAME "ps3fb"
#define GPU_CMD_BUF_SIZE (2 * 1024 * 1024)
#define GPU_FB_START (64 * 1024)
#define GPU_IOIF (0x0d000000UL)
#define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64)
#define GPU_MAX_LINE_LENGTH (65536 - 64)
#define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */
#define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */
#define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */
#define GPU_INTR_STATUS_FLIP_1 4 /* flip head B */
#define GPU_INTR_STATUS_QUEUE_0 5 /* queue head A */
#define GPU_INTR_STATUS_QUEUE_1 6 /* queue head B */
#define GPU_DRIVER_INFO_VERSION 0x211
/* gpu internals */
struct display_head {
u64 be_time_stamp;
u32 status;
u32 offset;
u32 res1;
u32 res2;
u32 field;
u32 reserved1;
u64 res3;
u32 raster;
u64 vblank_count;
u32 field_vsync;
u32 reserved2;
};
struct gpu_irq {
u32 irq_outlet;
u32 status;
u32 mask;
u32 video_cause;
u32 graph_cause;
u32 user_cause;
u32 res1;
u64 res2;
u32 reserved[4];
};
struct gpu_driver_info {
u32 version_driver;
u32 version_gpu;
u32 memory_size;
u32 hardware_channel;
u32 nvcore_frequency;
u32 memory_frequency;
u32 reserved[1063];
struct display_head display_head[8];
struct gpu_irq irq;
};
struct ps3fb_priv {
unsigned int irq_no;
u64 context_handle, memory_handle;
struct gpu_driver_info *dinfo;
u64 vblank_count; /* frame count */
wait_queue_head_t wait_vsync;
atomic_t ext_flip; /* on/off flip with vsync */
atomic_t f_count; /* fb_open count */
int is_blanked;
int is_kicked;
struct task_struct *task;
};
static struct ps3fb_priv ps3fb;
struct ps3fb_par {
u32 pseudo_palette[16];
int mode_id, new_mode_id;
unsigned int num_frames; /* num of frame buffers */
unsigned int width;
unsigned int height;
unsigned int ddr_line_length;
unsigned int ddr_frame_size;
unsigned int xdr_frame_size;
unsigned int full_offset; /* start of fullscreen DDR fb */
unsigned int fb_offset; /* start of actual DDR fb */
unsigned int pan_offset;
};
#define FIRST_NATIVE_MODE_INDEX 10
static const struct fb_videomode ps3fb_modedb[] = {
/* 60 Hz broadcast modes (modes "1" to "5") */
{
/* 480i */
"480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
}, {
/* 480p */
"480p", 60, 576, 384