/drivers/video/carminefb.c
C | 789 lines | 609 code | 122 blank | 58 comment | 42 complexity | 8dbf01717038e576b6c52943da67beca MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * Frame buffer driver for the Carmine GPU.
- *
- * The driver configures the GPU as follows
- * - FB0 is display 0 with unique memory area
- * - FB1 is display 1 with unique memory area
- * - both display use 32 bit colors
- */
- #include <linux/delay.h>
- #include <linux/errno.h>
- #include <linux/fb.h>
- #include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/slab.h>
- #include "carminefb.h"
- #include "carminefb_regs.h"
- #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
- #error "The endianness of the target host has not been defined."
- #endif
- /*
- * The initial video mode can be supplied via two different ways:
- * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
- * - as an integer that picks the video mode from carmine_modedb[] (module
- * option fb_mode)
- *
- * If nothing is used than the initial video mode will be the
- * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
- */
- #define CARMINEFB_DEFAULT_VIDEO_MODE 1
- static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
- module_param(fb_mode, uint, 0444);
- MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
- static char *fb_mode_str;
- module_param(fb_mode_str, charp, 0444);
- MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
- /*
- * Carminefb displays:
- * 0b000 None
- * 0b001 Display 0
- * 0b010 Display 1
- */
- static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
- module_param(fb_displays, int, 0444);
- MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
- struct carmine_hw {
- void __iomem *v_regs;
- void __iomem *screen_mem;
- struct fb_info *fb[MAX_DISPLAY];
- };
- struct carmine_resolution {
- u32 htp;
- u32 hsp;
- u32 hsw;
- u32 hdp;
- u32 vtr;
- u32 vsp;
- u32 vsw;
- u32 vdp;
- u32 disp_mode;
- };
- struct carmine_fb {
- void __iomem *display_reg;
- void __iomem *screen_base;
- u32 smem_offset;
- u32 cur_mode;
- u32 new_mode;
- struct carmine_resolution *res;
- u32 pseudo_palette[16];
- };
- static struct fb_fix_screeninfo carminefb_fix __devinitdata = {
- .id = "Carmine",
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
- .accel = FB_ACCEL_NONE,
- };
- static const struct fb_videomode carmine_modedb[] = {
- {
- .name = "640x480",
- .xres = 640,
- .yres = 480,
- }, {
- .name = "800x600",
- .xres = 800,
- .yres = 600,
- },
- };
- static struct carmine_resolution car_modes[] = {
- {
- /* 640x480 */
- .htp = 800,
- .hsp = 672,
- .hsw = 96,
- .hdp = 640,
- .vtr = 525,
- .vsp = 490,
- .vsw = 2,
- .vdp = 480,
- .disp_mode = 0x1400,
- },
- {
- /* 800x600 */
- .htp = 1060,
- .hsp = 864,
- .hsw = 72,
- .hdp = 800,
- .vtr = 628,
- .vsp = 601,
- .vsw = 2,
- .vdp = 600,
- .disp_mode = 0x0d00,
- }
- };
- static int carmine_find_mode(const struct fb_var_screeninfo *var)
- {
- int i;
- for (i = 0; i < ARRAY_SIZE(car_modes); i++)
- if (car_modes[i].hdp == var->xres &&
- car_modes[i].vdp == var->yres)
- return i;
- return -EINVAL;
- }
- static void c_set_disp_reg(const struct carmine_fb *par,
- u32 offset, u32 val)
- {
- writel(val, par->display_reg + offset);
- }
- static u32 c_get_disp_reg(const struct carmine_fb *par,
- u32 offset)
- {
- return readl(par->display_reg + offset);
- }
- static void c_set_hw_reg(const struct carmine_hw *hw,
- u32 offset, u32 val)
- {
- writel(val, hw->v_regs + offset);
- }
- static u32 c_get_hw_reg(const struct carmine_hw *hw,
- u32 offset)
- {
- return readl(hw->v_regs + offset);
- }
- static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp, struct fb_info *info)
- {
- if (regno >= 16)
- return 1;
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- transp >>= 8;
- ((__be32 *)info->pseudo_palette)[regno] = cpu_to_be32(transp << 24 |
- red << 0 | green << 8 | blue << 16);
- return 0;
- }
- static int carmine_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
- {
- int ret;
- ret = carmine_find_mode(var);
- if (ret < 0)
- return ret;
- if (var->grayscale || var->rotate || var->nonstd)
- return -EINVAL;
- var->xres_virtual = var->xres;
- var->yres_virtual = var->yres;
- var->bits_per_pixel = 32;
- #ifdef __BIG_ENDIAN
- var->transp.offset = 24;
- var->red.offset = 0;
- var->green.offset = 8;
- var->blue.offset = 16;
- #else
- var->transp.offset = 24;
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- #endif
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->transp.length = 8;
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
- var->transp.msb_right = 0;
- return 0;
- }
- static void carmine_init_display_param(struct carmine_fb *par)
- {
- u32 width;
- u32 height;
- u32 param;
- u32 window_size;
- u32 soffset = par->smem_offset;
- c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
- c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
- c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
- CARMINE_CURSOR0_PRIORITY_MASK |
- CARMINE_CURSOR1_PRIORITY_MASK |
- CARMINE_CURSOR_CUTZ_MASK);
- /* Set default cursor position */
- c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
- c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
- /* Set default display mode */
- c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
- CARMINE_EXT_CMODE_DIRECT24_RGBA);
- c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
- CARMINE_EXT_CMODE_DIRECT24_RGBA);
- c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
- CARMINE_EXT_CMODE_DIRECT24_RGBA);
- c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
- CARMINE_EXT_CMODE_DIRECT24_RGBA);
- c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
- CARMINE_EXT_CMODE_DIRECT24_RGBA);
-