12ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior/*
22ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * Frame buffer driver for the Carmine GPU.
32ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior *
42ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * The driver configures the GPU as follows
52ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * - FB0 is display 0 with unique memory area
62ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * - FB1 is display 1 with unique memory area
72ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * - both display use 32 bit colors
82ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior */
92ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#include <linux/delay.h>
102ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#include <linux/errno.h>
112ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#include <linux/fb.h>
122ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#include <linux/interrupt.h>
132ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#include <linux/pci.h>
145a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
15355b200bacdb6017669cdc5bc9e7b1037aac42a2Paul Gortmaker#include <linux/module.h>
162ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
172ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#include "carminefb.h"
182ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#include "carminefb_regs.h"
192ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
202ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
212ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#error  "The endianness of the target host has not been defined."
222ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#endif
232ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
242ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior/*
252ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * The initial video mode can be supplied via two different ways:
262ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
272ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * - as an integer that picks the video mode from carmine_modedb[] (module
282ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior *   option fb_mode)
292ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior *
302ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * If nothing is used than the initial video mode will be the
312ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
322ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior */
332ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#define CARMINEFB_DEFAULT_VIDEO_MODE	1
342ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
352ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
36c84c14224bbca6ec60d5851fcc87be0e34df2f44Jean Delvaremodule_param(fb_mode, uint, 0444);
372ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian SiewiorMODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
382ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
392ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic char *fb_mode_str;
40c84c14224bbca6ec60d5851fcc87be0e34df2f44Jean Delvaremodule_param(fb_mode_str, charp, 0444);
412ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian SiewiorMODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
422ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
432ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior/*
442ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * Carminefb displays:
452ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * 0b000 None
462ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * 0b001 Display 0
472ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior * 0b010 Display 1
482ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior */
492ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
50c84c14224bbca6ec60d5851fcc87be0e34df2f44Jean Delvaremodule_param(fb_displays, int, 0444);
512ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian SiewiorMODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
522ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
532ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstruct carmine_hw {
542ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	void __iomem *v_regs;
552ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	void __iomem *screen_mem;
562ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct fb_info *fb[MAX_DISPLAY];
572ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
582ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
592ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstruct carmine_resolution {
602ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 htp;
612ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 hsp;
622ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 hsw;
632ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 hdp;
642ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 vtr;
652ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 vsp;
662ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 vsw;
672ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 vdp;
682ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 disp_mode;
692ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
702ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
712ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstruct carmine_fb {
722ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	void __iomem *display_reg;
732ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	void __iomem *screen_base;
742ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 smem_offset;
752ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 cur_mode;
762ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 new_mode;
772ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct carmine_resolution *res;
782ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 pseudo_palette[16];
792ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
802ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
8148c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_fix_screeninfo carminefb_fix = {
822ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.id = "Carmine",
832ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.type = FB_TYPE_PACKED_PIXELS,
842ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.visual = FB_VISUAL_TRUECOLOR,
852ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.accel = FB_ACCEL_NONE,
862ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
872ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
882ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic const struct fb_videomode carmine_modedb[] = {
892ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	{
902ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.name		= "640x480",
912ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.xres		= 640,
922ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.yres		= 480,
932ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}, {
942ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.name		= "800x600",
952ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.xres		= 800,
962ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.yres		= 600,
972ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	},
982ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
992ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1002ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic struct carmine_resolution car_modes[] = {
1012ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	{
1022ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		/* 640x480 */
1032ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.htp = 800,
1042ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.hsp = 672,
1052ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.hsw = 96,
1062ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.hdp = 640,
1072ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.vtr = 525,
1082ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.vsp = 490,
1092ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.vsw = 2,
1102ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.vdp = 480,
1112ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.disp_mode = 0x1400,
1122ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	},
1132ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	{
1142ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		/* 800x600 */
1152ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.htp = 1060,
1162ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.hsp = 864,
1172ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.hsw = 72,
1182ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.hdp = 800,
1192ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.vtr = 628,
1202ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.vsp = 601,
1212ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.vsw = 2,
1222ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.vdp = 600,
1232ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		.disp_mode = 0x0d00,
1242ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
1252ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
1262ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1272ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic int carmine_find_mode(const struct fb_var_screeninfo *var)
1282ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
1292ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	int i;
1302ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1312ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	for (i = 0; i < ARRAY_SIZE(car_modes); i++)
1322ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		if (car_modes[i].hdp == var->xres &&
1332ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		    car_modes[i].vdp == var->yres)
1342ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			return i;
1352ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return -EINVAL;
1362ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
1372ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1382ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic void c_set_disp_reg(const struct carmine_fb *par,
1392ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		u32 offset, u32 val)
1402ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
1412ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	writel(val, par->display_reg + offset);
1422ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
1432ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1442ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic u32 c_get_disp_reg(const struct carmine_fb *par,
1452ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		u32 offset)
1462ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
1472ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return readl(par->display_reg + offset);
1482ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
1492ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1502ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic void c_set_hw_reg(const struct carmine_hw *hw,
1512ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		u32 offset, u32 val)
1522ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
1532ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	writel(val, hw->v_regs + offset);
1542ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
1552ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1562ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic u32 c_get_hw_reg(const struct carmine_hw *hw,
1572ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		u32 offset)
1582ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
1592ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return readl(hw->v_regs + offset);
1602ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
1612ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1622ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
1632ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		unsigned blue, unsigned transp, struct fb_info *info)
1642ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
1652ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (regno >= 16)
1662ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		return 1;
1672ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1682ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	red >>= 8;
1692ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	green >>= 8;
1702ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	blue >>= 8;
1712ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	transp >>= 8;
1722ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
17308cc6341cc04fad45c28995db796317b5b413045Harvey Harrison	((__be32 *)info->pseudo_palette)[regno] = cpu_to_be32(transp << 24 |
1742ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		red << 0 | green << 8 | blue << 16);
1752ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return 0;
1762ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
1772ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1782ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic int carmine_check_var(struct fb_var_screeninfo *var,
1792ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		struct fb_info *info)
1802ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
1812ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	int ret;
1822ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1832ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	ret = carmine_find_mode(var);
1842ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (ret < 0)
1852ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		return ret;
1862ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1872ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (var->grayscale || var->rotate || var->nonstd)
1882ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		return -EINVAL;
1892ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1902ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->xres_virtual = var->xres;
1912ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->yres_virtual = var->yres;
1922ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1932ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->bits_per_pixel = 32;
1942ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
1952ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#ifdef __BIG_ENDIAN
1962ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->transp.offset = 24;
1972ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->red.offset = 0;
1982ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->green.offset = 8;
1992ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->blue.offset = 16;
2002ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#else
2012ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->transp.offset = 24;
2022ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->red.offset = 16;
2032ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->green.offset = 8;
2042ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->blue.offset = 0;
2052ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#endif
2062ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2072ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->red.length = 8;
2082ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->green.length = 8;
2092ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->blue.length = 8;
2102ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->transp.length = 8;
2112ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2122ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->red.msb_right = 0;
2132ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->green.msb_right = 0;
2142ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->blue.msb_right = 0;
2152ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	var->transp.msb_right = 0;
2162ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return 0;
2172ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
2182ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2192ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic void carmine_init_display_param(struct carmine_fb *par)
2202ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
2212ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 width;
2222ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 height;
2232ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 param;
2242ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 window_size;
2252ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 soffset = par->smem_offset;
2262ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2272ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
2282ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
2292ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
2302ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_CURSOR0_PRIORITY_MASK |
2312ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_CURSOR1_PRIORITY_MASK |
2322ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_CURSOR_CUTZ_MASK);
2332ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2342ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default cursor position */
2352ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
2362ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
2372ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2382ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default display mode */
2392ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
2402ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_EXT_CMODE_DIRECT24_RGBA);
2412ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
2422ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_EXT_CMODE_DIRECT24_RGBA);
2432ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
2442ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_EXT_CMODE_DIRECT24_RGBA);
2452ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
2462ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_EXT_CMODE_DIRECT24_RGBA);
2472ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
2482ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_EXT_CMODE_DIRECT24_RGBA);
2492ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
2502ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_EXT_CMODE_DIRECT24_RGBA);
2512ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
2522ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_EXT_CMODE_DIRECT24_RGBA);
2532ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
2542ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_EXT_CMODE_DIRECT24_RGBA);
2552ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2562ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default frame size to layer mode register */
2572ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
2582ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	width = width << CARMINE_DISP_WIDTH_SHIFT;
2592ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2602ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	height = par->res->vdp - 1;
2612ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	param = width | height;
2622ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2632ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
2642ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
2652ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
2662ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
2672ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
2682ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
2692ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
2702ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
2712ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2722ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default pos and size */
2732ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
2742ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	window_size |= par->res->hdp;
2752ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2762ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
2772ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
2782ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
2792ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
2802ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
2812ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
2822ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
2832ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
2842ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
2852ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
2862ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
2872ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
2882ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
2892ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
2902ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
2912ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
2922ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
2932ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default origin address */
2942ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
2952ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
2962ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
2972ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
2982ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
2992ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
3002ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
3012ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
3022ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3032ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default display address */
3042ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
3052ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
3062ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
3072ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
3082ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
3092ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
3102ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
3112ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3122ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default display position */
3132ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
3142ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
3152ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
3162ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
3172ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
3182ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
3192ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
3202ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3212ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default blend mode */
3222ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
3232ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
3242ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
3252ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
3262ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
3272ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
3282ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
3292ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
3302ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3312ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* default transparency mode */
3322ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
3332ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
3342ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
3352ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
3362ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
3372ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
3382ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
3392ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
3402ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3412ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set default read skip parameter */
3422ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
3432ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
3442ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
3452ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
3462ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
3472ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
3482ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
3492ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3502ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
3512ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
3522ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
3532ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
3542ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
3552ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
3562ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
3572ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3582ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
3592ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
3602ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
3612ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
3622ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
3632ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
3642ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
3652ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
3662ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3672ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic void set_display_parameters(struct carmine_fb *par)
3682ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
3692ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 mode;
3702ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
3712ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3722ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/*
3732ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	 * display timing. Parameters are decreased by one because hardware
3742ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	 * spec is 0 to (n - 1)
3752ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	 * */
3762ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	hdp = par->res->hdp - 1;
3772ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	vdp = par->res->vdp - 1;
3782ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	htp = par->res->htp - 1;
3792ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	hsp = par->res->hsp - 1;
3802ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	hsw = par->res->hsw - 1;
3812ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	vtr = par->res->vtr - 1;
3822ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	vsp = par->res->vsp - 1;
3832ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	vsw = par->res->vsw - 1;
3842ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3852ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
3862ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			htp << CARMINE_DISP_HTP_SHIFT);
3872ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
3882ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			(hdp << CARMINE_DISP_HDB_SHIFT)	| hdp);
3892ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
3902ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			(vsw << CARMINE_DISP_VSW_SHIFT) |
3912ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			(hsw << CARMINE_DISP_HSW_SHIFT) |
3922ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			(hsp));
3932ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
3942ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			vtr << CARMINE_DISP_VTR_SHIFT);
3952ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
3962ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			(vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
3972ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
3982ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* clock */
3992ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
4002ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	mode = (mode & ~CARMINE_DISP_DCM_MASK) |
4012ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		(par->res->disp_mode & CARMINE_DISP_DCM_MASK);
4022ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* enable video output and layer 0 */
4032ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	mode |= CARMINE_DEN | CARMINE_L0E;
4042ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
4052ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
4062ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4072ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic int carmine_set_par(struct fb_info *info)
4082ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
4092ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct carmine_fb *par = info->par;
4102ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	int ret;
4112ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4122ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	ret = carmine_find_mode(&info->var);
4132ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (ret < 0)
4142ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		return ret;
4152ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4162ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	par->new_mode = ret;
4172ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (par->cur_mode != par->new_mode) {
4182ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4192ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		par->cur_mode = par->new_mode;
4202ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		par->res = &car_modes[par->new_mode];
4212ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4222ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		carmine_init_display_param(par);
4232ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		set_display_parameters(par);
4242ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
4252ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4262ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
4272ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return 0;
4282ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
4292ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4302ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic int init_hardware(struct carmine_hw *hw)
4312ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
4322ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 flags;
4332ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 loops;
4342ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	u32 ret;
4352ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
436421f91d21ad6f799dc7b489bb33cc560ccc56f98Uwe Kleine-König	/* Initialize Carmine */
4372ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Sets internal clock */
4382ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
4392ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_DFLT_IP_CLOCK_ENABLE);
4402ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4412ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Video signal output is turned off */
4422ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
4432ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
4442ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4452ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Software reset */
4462ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
4472ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
4482ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4492ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* I/O mode settings */
4502ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
4512ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		CARMINE_DFLT_IP_DCTL_IO_CONT0;
4522ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
4532ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			flags);
4542ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4552ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* DRAM initial sequence */
4562ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
4572ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
4582ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			flags);
4592ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4602ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
4612ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		CARMINE_DFLT_IP_DCTL_EMODE;
4622ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
4632ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			flags);
4642ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4652ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
4662ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		CARMINE_DFLT_IP_DCTL_SET_TIME2;
4672ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
4682ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			flags);
4692ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4702ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
4712ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
4722ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
4732ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4742ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
4752ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
4762ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			flags);
4772ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4782ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
4792ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		CARMINE_DFLT_IP_DCTL_STATES;
4802ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
4812ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			flags);
4822ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4832ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Executes DLL reset */
4842ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (CARMINE_DCTL_DLL_RESET) {
4852ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
4862ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4872ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
4882ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior					CARMINE_DCTL_REG_RSV0_STATES);
4892ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			ret &= CARMINE_DCTL_REG_STATES_MASK;
4902ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			if (!ret)
4912ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				break;
4922ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4932ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
4942ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		}
4952ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
4962ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
4972ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			printk(KERN_ERR "DRAM init failed\n");
4982ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			return -EIO;
4992ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		}
5002ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
5012ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5022ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
5032ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		CARMINE_DFLT_IP_DCTL_ADD;
5042ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
5052ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5062ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
5072ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
5082ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
5092ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			flags);
5102ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5112ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Initialize the write back register */
5122ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
5132ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			CARMINE_WB_REG_WBM_DEFAULT);
5142ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5152ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Initialize the Kottos registers */
5162ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
5172ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
5182ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5192ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* Set DC offsets */
5202ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
5212ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
5222ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
5232ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
5242ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
5252ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
5262ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return 0;
5272ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
5282ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5292ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic struct fb_ops carminefb_ops = {
5302ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.owner		= THIS_MODULE,
5312ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.fb_fillrect	= cfb_fillrect,
5322ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.fb_copyarea	= cfb_copyarea,
5332ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.fb_imageblit	= cfb_imageblit,
5342ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5352ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.fb_check_var	= carmine_check_var,
5362ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.fb_set_par	= carmine_set_par,
5372ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.fb_setcolreg	= carmine_setcolreg,
5382ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
5392ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
54048c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
54148c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartman			    int smem_offset, struct device *device,
54248c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartman			    struct fb_info **rinfo)
5432ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
5442ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	int ret;
5452ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct fb_info *info;
5462ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct carmine_fb *par;
5472ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5482ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info = framebuffer_alloc(sizeof *par, device);
5492ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (!info)
5502ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		return -ENOMEM;
5512ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5522ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	par = info->par;
5532ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	par->display_reg = regs;
5542ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	par->smem_offset = smem_offset;
5552ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5562ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info->screen_base = smem_base + smem_offset;
5572ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info->screen_size = CARMINE_DISPLAY_MEM;
5582ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info->fbops = &carminefb_ops;
5592ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5602ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info->fix = carminefb_fix;
5612ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info->pseudo_palette = par->pseudo_palette;
5622ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info->flags = FBINFO_DEFAULT;
5632ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5642ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	ret = fb_alloc_cmap(&info->cmap, 256, 1);
5652ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (ret < 0)
5662ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_free_fb;
5672ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
568493f139ecf9ee72f73ccbabd016325a145e884eeRoel Kluin	if (fb_mode >= ARRAY_SIZE(carmine_modedb))
5692ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
5702ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5712ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	par->cur_mode = par->new_mode = ~0;
5722ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5732ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
5742ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			ARRAY_SIZE(carmine_modedb),
5752ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			&carmine_modedb[fb_mode], 32);
5762ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (!ret || ret == 4) {
5772ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		ret = -EINVAL;
5782ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_dealloc_cmap;
5792ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
5802ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5812ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
5822ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			&info->modelist);
5832ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5842ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	ret = register_framebuffer(info);
5852ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (ret < 0)
5862ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_dealloc_cmap;
5872ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
58831b6780c15a4e3a90fe260e977f5186772ce7afbJoe Perches	fb_info(info, "%s frame buffer device\n", info->fix.id);
5892ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5902ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	*rinfo = info;
5912ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return 0;
5922ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
5932ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_dealloc_cmap:
5942ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	fb_dealloc_cmap(&info->cmap);
5952ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_free_fb:
5962ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	framebuffer_release(info);
5972ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return ret;
5982ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
5992ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6002ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic void cleanup_fb_device(struct fb_info *info)
6012ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
6022ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (info) {
6032ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		unregister_framebuffer(info);
6042ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		fb_dealloc_cmap(&info->cmap);
6052ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		framebuffer_release(info);
6062ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
6072ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
6082ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
60948c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
6102ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
6112ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct carmine_hw *hw;
6122ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct device *device = &dev->dev;
6132ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct fb_info *info;
6142ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	int ret;
6152ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6162ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	ret = pci_enable_device(dev);
6172ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (ret)
6182ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		return ret;
6192ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6202ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	ret = -ENOMEM;
6212ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	hw = kzalloc(sizeof *hw, GFP_KERNEL);
6222ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (!hw)
6232ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_enable_pci;
6242ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6252ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
6262ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
6272ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6282ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (!request_mem_region(carminefb_fix.mmio_start,
6292ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				carminefb_fix.mmio_len,
6302ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				"carminefb regbase")) {
6312ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
6322ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		ret = -EBUSY;
6332ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_free_hw;
6342ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
6352ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start,
6362ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			carminefb_fix.mmio_len);
6372ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (!hw->v_regs) {
6382ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		printk(KERN_ERR "carminefb: Can't remap %s register.\n",
6392ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				carminefb_fix.id);
6402ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_free_reg_mmio;
6412ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
6422ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6432ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
6442ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
6452ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6462ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* The memory area tends to be very large (256 MiB). Remap only what
6472ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	 * is required for that largest resolution to avoid remaps at run
6482ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	 * time
6492ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	 */
6502ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
6512ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
6522ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6532ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
6542ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
6552ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				"are required.", carminefb_fix.smem_len,
6562ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				CARMINE_TOTAL_DIPLAY_MEM);
657e045da7d835a28950543f5f10f0cb1905ca9bbafJulia Lawall		goto err_unmap_vregs;
6582ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
6592ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6602ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (!request_mem_region(carminefb_fix.smem_start,
6612ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				carminefb_fix.smem_len,	"carminefb smem")) {
6622ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		printk(KERN_ERR "carminefb: Can't reserve smem.\n");
6632ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_unmap_vregs;
6642ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
6652ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6662ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start,
6672ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			carminefb_fix.smem_len);
6682ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (!hw->screen_mem) {
6692ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
6702ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_reg_smem;
6712ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
6722ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6732ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	ret = init_hardware(hw);
6742ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (ret)
6752ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		goto err_unmap_screen;
6762ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6772ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info = NULL;
6782ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (fb_displays & CARMINE_USE_DISPLAY0) {
6792ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
6802ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
6812ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				device, &info);
6822ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		if (ret)
6832ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			goto err_deinit_hw;
6842ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
6852ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6862ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	hw->fb[0] = info;
6872ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6882ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info = NULL;
6892ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (fb_displays & CARMINE_USE_DISPLAY1) {
6902ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
6912ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
6922ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				device, &info);
6932ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		if (ret)
6942ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior			goto err_cleanup_fb0;
6952ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
6962ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
6972ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	hw->fb[1] = info;
6982ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	info = NULL;
6992ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7002ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	pci_set_drvdata(dev, hw);
7012ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return 0;
7022ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7032ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_cleanup_fb0:
7042ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	cleanup_fb_device(hw->fb[0]);
7052ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_deinit_hw:
7062ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* disable clock, etc */
7072ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
7082ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_unmap_screen:
7092ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	iounmap(hw->screen_mem);
7102ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_reg_smem:
711e045da7d835a28950543f5f10f0cb1905ca9bbafJulia Lawall	release_mem_region(carminefb_fix.smem_start, carminefb_fix.smem_len);
7122ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_unmap_vregs:
7132ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	iounmap(hw->v_regs);
7142ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_free_reg_mmio:
7152ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
7162ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_free_hw:
7172ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	kfree(hw);
7182ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorerr_enable_pci:
7192ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	pci_disable_device(dev);
7202ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return ret;
7212ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
7222ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
72348c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic void carminefb_remove(struct pci_dev *dev)
7242ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
7252ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct carmine_hw *hw = pci_get_drvdata(dev);
7262ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	struct fb_fix_screeninfo fix;
7272ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	int i;
7282ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7292ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* in case we use only fb1 and not fb1 */
7302ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (hw->fb[0])
7312ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		fix = hw->fb[0]->fix;
7322ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	else
7332ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		fix = hw->fb[1]->fix;
7342ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7352ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	/* deactivate display(s) and switch clocks */
7362ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
7372ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
7382ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
7392ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7402ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	for (i = 0; i < MAX_DISPLAY; i++)
7412ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		cleanup_fb_device(hw->fb[i]);
7422ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7432ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	iounmap(hw->screen_mem);
7442ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	release_mem_region(fix.smem_start, fix.smem_len);
7452ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	iounmap(hw->v_regs);
7462ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	release_mem_region(fix.mmio_start, fix.mmio_len);
7472ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7482ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	pci_disable_device(dev);
7492ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	kfree(hw);
7502ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
7512ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7522ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
75348c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct pci_device_id carmine_devices[] = {
7542ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
7552ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
7562ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	{0, 0, 0, 0, 0, 0, 0}
7572ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
7582ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7592ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian SiewiorMODULE_DEVICE_TABLE(pci, carmine_devices);
7602ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7612ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic struct pci_driver carmine_pci_driver = {
7622ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.name		= "carminefb",
7632ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.id_table	= carmine_devices,
7642ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	.probe		= carminefb_probe,
76548c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartman	.remove		= carminefb_remove,
7662ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior};
7672ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7682ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic int __init carminefb_init(void)
7692ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
7702ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	if (!(fb_displays &
7712ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		(CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
7722ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		printk(KERN_ERR "If you disable both displays than you don't "
7732ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior				"need the driver at all\n");
7742ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior		return -EINVAL;
7752ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	}
7762ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	return pci_register_driver(&carmine_pci_driver);
7772ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
7782ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiormodule_init(carminefb_init);
7792ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7802ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiorstatic void __exit carminefb_cleanup(void)
7812ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior{
7822ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior	pci_unregister_driver(&carmine_pci_driver);
7832ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior}
7842ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewiormodule_exit(carminefb_cleanup);
7852ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian Siewior
7862ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian SiewiorMODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
7872ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian SiewiorMODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
7882ece5f43b041b96fa2a05107a10a6b0ea0c03a3bSebastian SiewiorMODULE_LICENSE("GPL v2");
789