cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

arkfb.c (32278B)


      1/*
      2 *  linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV
      3 *  with ICS 5342 dac (it is easy to add support for different dacs).
      4 *
      5 *  Copyright (c) 2007 Ondrej Zajicek <santiago@crfreenet.org>
      6 *
      7 *  This file is subject to the terms and conditions of the GNU General Public
      8 *  License.  See the file COPYING in the main directory of this archive for
      9 *  more details.
     10 *
     11 *  Code is based on s3fb
     12 */
     13
     14#include <linux/module.h>
     15#include <linux/kernel.h>
     16#include <linux/errno.h>
     17#include <linux/string.h>
     18#include <linux/mm.h>
     19#include <linux/tty.h>
     20#include <linux/slab.h>
     21#include <linux/delay.h>
     22#include <linux/fb.h>
     23#include <linux/svga.h>
     24#include <linux/init.h>
     25#include <linux/pci.h>
     26#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
     27#include <video/vga.h>
     28
     29struct arkfb_info {
     30	int mclk_freq;
     31	int wc_cookie;
     32
     33	struct dac_info *dac;
     34	struct vgastate state;
     35	struct mutex open_lock;
     36	unsigned int ref_count;
     37	u32 pseudo_palette[16];
     38};
     39
     40
     41/* ------------------------------------------------------------------------- */
     42
     43
     44static const struct svga_fb_format arkfb_formats[] = {
     45	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
     46		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,	FB_VISUAL_PSEUDOCOLOR, 8, 8},
     47	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
     48		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
     49	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
     50		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
     51	{ 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
     52		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 8},
     53	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
     54		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},
     55	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
     56		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},
     57	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
     58		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 8, 8},
     59	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
     60		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 2},
     61	SVGA_FORMAT_END
     62};
     63
     64
     65/* CRT timing register sets */
     66
     67static const struct vga_regset ark_h_total_regs[]        = {{0x00, 0, 7}, {0x41, 7, 7}, VGA_REGSET_END};
     68static const struct vga_regset ark_h_display_regs[]      = {{0x01, 0, 7}, {0x41, 6, 6}, VGA_REGSET_END};
     69static const struct vga_regset ark_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x41, 5, 5}, VGA_REGSET_END};
     70static const struct vga_regset ark_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7	}, VGA_REGSET_END};
     71static const struct vga_regset ark_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x41, 4, 4}, VGA_REGSET_END};
     72static const struct vga_regset ark_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
     73
     74static const struct vga_regset ark_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x40, 7, 7}, VGA_REGSET_END};
     75static const struct vga_regset ark_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x40, 6, 6}, VGA_REGSET_END};
     76static const struct vga_regset ark_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x40, 5, 5}, VGA_REGSET_END};
     77// const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 6}, VGA_REGSET_END};
     78static const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
     79static const struct vga_regset ark_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x40, 4, 4}, VGA_REGSET_END};
     80static const struct vga_regset ark_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
     81
     82static const struct vga_regset ark_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END};
     83static const struct vga_regset ark_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END};
     84static const struct vga_regset ark_offset_regs[]         = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END};
     85
     86static const struct svga_timing_regs ark_timing_regs     = {
     87	ark_h_total_regs, ark_h_display_regs, ark_h_blank_start_regs,
     88	ark_h_blank_end_regs, ark_h_sync_start_regs, ark_h_sync_end_regs,
     89	ark_v_total_regs, ark_v_display_regs, ark_v_blank_start_regs,
     90	ark_v_blank_end_regs, ark_v_sync_start_regs, ark_v_sync_end_regs,
     91};
     92
     93
     94/* ------------------------------------------------------------------------- */
     95
     96
     97/* Module parameters */
     98
     99static char *mode_option = "640x480-8@60";
    100
    101MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago@crfreenet.org>");
    102MODULE_LICENSE("GPL");
    103MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
    104
    105module_param(mode_option, charp, 0444);
    106MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
    107module_param_named(mode, mode_option, charp, 0444);
    108MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) (deprecated)");
    109
    110static int threshold = 4;
    111
    112module_param(threshold, int, 0644);
    113MODULE_PARM_DESC(threshold, "FIFO threshold");
    114
    115
    116/* ------------------------------------------------------------------------- */
    117
    118
    119static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map)
    120{
    121	const u8 *font = map->data;
    122	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
    123	int i, c;
    124
    125	if ((map->width != 8) || (map->height != 16) ||
    126	    (map->depth != 1) || (map->length != 256)) {
    127		fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
    128		       map->width, map->height, map->depth, map->length);
    129		return;
    130	}
    131
    132	fb += 2;
    133	for (c = 0; c < map->length; c++) {
    134		for (i = 0; i < map->height; i++) {
    135			fb_writeb(font[i], &fb[i * 4]);
    136			fb_writeb(font[i], &fb[i * 4 + (128 * 8)]);
    137		}
    138		fb += 128;
    139
    140		if ((c % 8) == 7)
    141			fb += 128*8;
    142
    143		font += map->height;
    144	}
    145}
    146
    147static void arkfb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
    148{
    149	struct arkfb_info *par = info->par;
    150
    151	svga_tilecursor(par->state.vgabase, info, cursor);
    152}
    153
    154static struct fb_tile_ops arkfb_tile_ops = {
    155	.fb_settile	= arkfb_settile,
    156	.fb_tilecopy	= svga_tilecopy,
    157	.fb_tilefill    = svga_tilefill,
    158	.fb_tileblit    = svga_tileblit,
    159	.fb_tilecursor  = arkfb_tilecursor,
    160	.fb_get_tilemax = svga_get_tilemax,
    161};
    162
    163
    164/* ------------------------------------------------------------------------- */
    165
    166
    167/* image data is MSB-first, fb structure is MSB-first too */
    168static inline u32 expand_color(u32 c)
    169{
    170	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
    171}
    172
    173/* arkfb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
    174static void arkfb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
    175{
    176	u32 fg = expand_color(image->fg_color);
    177	u32 bg = expand_color(image->bg_color);
    178	const u8 *src1, *src;
    179	u8 __iomem *dst1;
    180	u32 __iomem *dst;
    181	u32 val;
    182	int x, y;
    183
    184	src1 = image->data;
    185	dst1 = info->screen_base + (image->dy * info->fix.line_length)
    186		 + ((image->dx / 8) * 4);
    187
    188	for (y = 0; y < image->height; y++) {
    189		src = src1;
    190		dst = (u32 __iomem *) dst1;
    191		for (x = 0; x < image->width; x += 8) {
    192			val = *(src++) * 0x01010101;
    193			val = (val & fg) | (~val & bg);
    194			fb_writel(val, dst++);
    195		}
    196		src1 += image->width / 8;
    197		dst1 += info->fix.line_length;
    198	}
    199
    200}
    201
    202/* arkfb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
    203static void arkfb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
    204{
    205	u32 fg = expand_color(rect->color);
    206	u8 __iomem *dst1;
    207	u32 __iomem *dst;
    208	int x, y;
    209
    210	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
    211		 + ((rect->dx / 8) * 4);
    212
    213	for (y = 0; y < rect->height; y++) {
    214		dst = (u32 __iomem *) dst1;
    215		for (x = 0; x < rect->width; x += 8) {
    216			fb_writel(fg, dst++);
    217		}
    218		dst1 += info->fix.line_length;
    219	}
    220
    221}
    222
    223
    224/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
    225static inline u32 expand_pixel(u32 c)
    226{
    227	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
    228		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
    229}
    230
    231/* arkfb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
    232static void arkfb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
    233{
    234	u32 fg = image->fg_color * 0x11111111;
    235	u32 bg = image->bg_color * 0x11111111;
    236	const u8 *src1, *src;
    237	u8 __iomem *dst1;
    238	u32 __iomem *dst;
    239	u32 val;
    240	int x, y;
    241
    242	src1 = image->data;
    243	dst1 = info->screen_base + (image->dy * info->fix.line_length)
    244		 + ((image->dx / 8) * 4);
    245
    246	for (y = 0; y < image->height; y++) {
    247		src = src1;
    248		dst = (u32 __iomem *) dst1;
    249		for (x = 0; x < image->width; x += 8) {
    250			val = expand_pixel(*(src++));
    251			val = (val & fg) | (~val & bg);
    252			fb_writel(val, dst++);
    253		}
    254		src1 += image->width / 8;
    255		dst1 += info->fix.line_length;
    256	}
    257
    258}
    259
    260static void arkfb_imageblit(struct fb_info *info, const struct fb_image *image)
    261{
    262	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
    263	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
    264		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
    265			arkfb_iplan_imageblit(info, image);
    266		else
    267			arkfb_cfb4_imageblit(info, image);
    268	} else
    269		cfb_imageblit(info, image);
    270}
    271
    272static void arkfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
    273{
    274	if ((info->var.bits_per_pixel == 4)
    275	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
    276	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
    277		arkfb_iplan_fillrect(info, rect);
    278	 else
    279		cfb_fillrect(info, rect);
    280}
    281
    282
    283/* ------------------------------------------------------------------------- */
    284
    285
    286enum
    287{
    288	DAC_PSEUDO8_8,
    289	DAC_RGB1555_8,
    290	DAC_RGB0565_8,
    291	DAC_RGB0888_8,
    292	DAC_RGB8888_8,
    293	DAC_PSEUDO8_16,
    294	DAC_RGB1555_16,
    295	DAC_RGB0565_16,
    296	DAC_RGB0888_16,
    297	DAC_RGB8888_16,
    298	DAC_MAX
    299};
    300
    301struct dac_ops {
    302	int (*dac_get_mode)(struct dac_info *info);
    303	int (*dac_set_mode)(struct dac_info *info, int mode);
    304	int (*dac_get_freq)(struct dac_info *info, int channel);
    305	int (*dac_set_freq)(struct dac_info *info, int channel, u32 freq);
    306	void (*dac_release)(struct dac_info *info);
    307};
    308
    309typedef void (*dac_read_regs_t)(void *data, u8 *code, int count);
    310typedef void (*dac_write_regs_t)(void *data, u8 *code, int count);
    311
    312struct dac_info
    313{
    314	struct dac_ops *dacops;
    315	dac_read_regs_t dac_read_regs;
    316	dac_write_regs_t dac_write_regs;
    317	void *data;
    318};
    319
    320
    321static inline u8 dac_read_reg(struct dac_info *info, u8 reg)
    322{
    323	u8 code[2] = {reg, 0};
    324	info->dac_read_regs(info->data, code, 1);
    325	return code[1];
    326}
    327
    328static inline void dac_read_regs(struct dac_info *info, u8 *code, int count)
    329{
    330	info->dac_read_regs(info->data, code, count);
    331}
    332
    333static inline void dac_write_reg(struct dac_info *info, u8 reg, u8 val)
    334{
    335	u8 code[2] = {reg, val};
    336	info->dac_write_regs(info->data, code, 1);
    337}
    338
    339static inline void dac_write_regs(struct dac_info *info, u8 *code, int count)
    340{
    341	info->dac_write_regs(info->data, code, count);
    342}
    343
    344static inline int dac_set_mode(struct dac_info *info, int mode)
    345{
    346	return info->dacops->dac_set_mode(info, mode);
    347}
    348
    349static inline int dac_set_freq(struct dac_info *info, int channel, u32 freq)
    350{
    351	return info->dacops->dac_set_freq(info, channel, freq);
    352}
    353
    354static inline void dac_release(struct dac_info *info)
    355{
    356	info->dacops->dac_release(info);
    357}
    358
    359
    360/* ------------------------------------------------------------------------- */
    361
    362
    363/* ICS5342 DAC */
    364
    365struct ics5342_info
    366{
    367	struct dac_info dac;
    368	u8 mode;
    369};
    370
    371#define DAC_PAR(info) ((struct ics5342_info *) info)
    372
    373/* LSB is set to distinguish unused slots */
    374static const u8 ics5342_mode_table[DAC_MAX] = {
    375	[DAC_PSEUDO8_8]  = 0x01, [DAC_RGB1555_8]  = 0x21, [DAC_RGB0565_8]  = 0x61,
    376	[DAC_RGB0888_8]  = 0x41, [DAC_PSEUDO8_16] = 0x11, [DAC_RGB1555_16] = 0x31,
    377	[DAC_RGB0565_16] = 0x51, [DAC_RGB0888_16] = 0x91, [DAC_RGB8888_16] = 0x71
    378};
    379
    380static int ics5342_set_mode(struct dac_info *info, int mode)
    381{
    382	u8 code;
    383
    384	if (mode >= DAC_MAX)
    385		return -EINVAL;
    386
    387	code = ics5342_mode_table[mode];
    388
    389	if (! code)
    390		return -EINVAL;
    391
    392	dac_write_reg(info, 6, code & 0xF0);
    393	DAC_PAR(info)->mode = mode;
    394
    395	return 0;
    396}
    397
    398static const struct svga_pll ics5342_pll = {3, 129, 3, 33, 0, 3,
    399	60000, 250000, 14318};
    400
    401/* pd4 - allow only posdivider 4 (r=2) */
    402static const struct svga_pll ics5342_pll_pd4 = {3, 129, 3, 33, 2, 2,
    403	60000, 335000, 14318};
    404
    405/* 270 MHz should be upper bound for VCO clock according to specs,
    406   but that is too restrictive in pd4 case */
    407
    408static int ics5342_set_freq(struct dac_info *info, int channel, u32 freq)
    409{
    410	u16 m, n, r;
    411
    412	/* only postdivider 4 (r=2) is valid in mode DAC_PSEUDO8_16 */
    413	int rv = svga_compute_pll((DAC_PAR(info)->mode == DAC_PSEUDO8_16)
    414				  ? &ics5342_pll_pd4 : &ics5342_pll,
    415				  freq, &m, &n, &r, 0);
    416
    417	if (rv < 0) {
    418		return -EINVAL;
    419	} else {
    420		u8 code[6] = {4, 3, 5, m-2, 5, (n-2) | (r << 5)};
    421		dac_write_regs(info, code, 3);
    422		return 0;
    423	}
    424}
    425
    426static void ics5342_release(struct dac_info *info)
    427{
    428	ics5342_set_mode(info, DAC_PSEUDO8_8);
    429	kfree(info);
    430}
    431
    432static struct dac_ops ics5342_ops = {
    433	.dac_set_mode	= ics5342_set_mode,
    434	.dac_set_freq	= ics5342_set_freq,
    435	.dac_release	= ics5342_release
    436};
    437
    438
    439static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data)
    440{
    441	struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL);
    442
    443	if (! info)
    444		return NULL;
    445
    446	info->dacops = &ics5342_ops;
    447	info->dac_read_regs = drr;
    448	info->dac_write_regs = dwr;
    449	info->data = data;
    450	DAC_PAR(info)->mode = DAC_PSEUDO8_8; /* estimation */
    451	return info;
    452}
    453
    454
    455/* ------------------------------------------------------------------------- */
    456
    457
    458static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7};
    459
    460static void ark_dac_read_regs(void *data, u8 *code, int count)
    461{
    462	struct fb_info *info = data;
    463	struct arkfb_info *par;
    464	u8 regval;
    465
    466	par = info->par;
    467	regval = vga_rseq(par->state.vgabase, 0x1C);
    468	while (count != 0)
    469	{
    470		vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
    471		code[1] = vga_r(par->state.vgabase, dac_regs[code[0] & 3]);
    472		count--;
    473		code += 2;
    474	}
    475
    476	vga_wseq(par->state.vgabase, 0x1C, regval);
    477}
    478
    479static void ark_dac_write_regs(void *data, u8 *code, int count)
    480{
    481	struct fb_info *info = data;
    482	struct arkfb_info *par;
    483	u8 regval;
    484
    485	par = info->par;
    486	regval = vga_rseq(par->state.vgabase, 0x1C);
    487	while (count != 0)
    488	{
    489		vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
    490		vga_w(par->state.vgabase, dac_regs[code[0] & 3], code[1]);
    491		count--;
    492		code += 2;
    493	}
    494
    495	vga_wseq(par->state.vgabase, 0x1C, regval);
    496}
    497
    498
    499static void ark_set_pixclock(struct fb_info *info, u32 pixclock)
    500{
    501	struct arkfb_info *par = info->par;
    502	u8 regval;
    503
    504	int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);
    505	if (rv < 0) {
    506		fb_err(info, "cannot set requested pixclock, keeping old value\n");
    507		return;
    508	}
    509
    510	/* Set VGA misc register  */
    511	regval = vga_r(par->state.vgabase, VGA_MIS_R);
    512	vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
    513}
    514
    515
    516/* Open framebuffer */
    517
    518static int arkfb_open(struct fb_info *info, int user)
    519{
    520	struct arkfb_info *par = info->par;
    521
    522	mutex_lock(&(par->open_lock));
    523	if (par->ref_count == 0) {
    524		void __iomem *vgabase = par->state.vgabase;
    525
    526		memset(&(par->state), 0, sizeof(struct vgastate));
    527		par->state.vgabase = vgabase;
    528		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
    529		par->state.num_crtc = 0x60;
    530		par->state.num_seq = 0x30;
    531		save_vga(&(par->state));
    532	}
    533
    534	par->ref_count++;
    535	mutex_unlock(&(par->open_lock));
    536
    537	return 0;
    538}
    539
    540/* Close framebuffer */
    541
    542static int arkfb_release(struct fb_info *info, int user)
    543{
    544	struct arkfb_info *par = info->par;
    545
    546	mutex_lock(&(par->open_lock));
    547	if (par->ref_count == 0) {
    548		mutex_unlock(&(par->open_lock));
    549		return -EINVAL;
    550	}
    551
    552	if (par->ref_count == 1) {
    553		restore_vga(&(par->state));
    554		dac_set_mode(par->dac, DAC_PSEUDO8_8);
    555	}
    556
    557	par->ref_count--;
    558	mutex_unlock(&(par->open_lock));
    559
    560	return 0;
    561}
    562
    563/* Validate passed in var */
    564
    565static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
    566{
    567	int rv, mem, step;
    568
    569	if (!var->pixclock)
    570		return -EINVAL;
    571
    572	/* Find appropriate format */
    573	rv = svga_match_format (arkfb_formats, var, NULL);
    574	if (rv < 0)
    575	{
    576		fb_err(info, "unsupported mode requested\n");
    577		return rv;
    578	}
    579
    580	/* Do not allow to have real resoulution larger than virtual */
    581	if (var->xres > var->xres_virtual)
    582		var->xres_virtual = var->xres;
    583
    584	if (var->yres > var->yres_virtual)
    585		var->yres_virtual = var->yres;
    586
    587	/* Round up xres_virtual to have proper alignment of lines */
    588	step = arkfb_formats[rv].xresstep - 1;
    589	var->xres_virtual = (var->xres_virtual+step) & ~step;
    590
    591
    592	/* Check whether have enough memory */
    593	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
    594	if (mem > info->screen_size)
    595	{
    596		fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n",
    597		       mem >> 10, (unsigned int) (info->screen_size >> 10));
    598		return -EINVAL;
    599	}
    600
    601	rv = svga_check_timings (&ark_timing_regs, var, info->node);
    602	if (rv < 0)
    603	{
    604		fb_err(info, "invalid timings requested\n");
    605		return rv;
    606	}
    607
    608	/* Interlaced mode is broken */
    609	if (var->vmode & FB_VMODE_INTERLACED)
    610		return -EINVAL;
    611
    612	return 0;
    613}
    614
    615/* Set video mode from par */
    616
    617static int arkfb_set_par(struct fb_info *info)
    618{
    619	struct arkfb_info *par = info->par;
    620	u32 value, mode, hmul, hdiv, offset_value, screen_size;
    621	u32 bpp = info->var.bits_per_pixel;
    622	u8 regval;
    623
    624	if (bpp != 0) {
    625		info->fix.ypanstep = 1;
    626		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
    627
    628		info->flags &= ~FBINFO_MISC_TILEBLITTING;
    629		info->tileops = NULL;
    630
    631		/* in 4bpp supports 8p wide tiles only, any tiles otherwise */
    632		info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
    633		info->pixmap.blit_y = ~(u32)0;
    634
    635		offset_value = (info->var.xres_virtual * bpp) / 64;
    636		screen_size = info->var.yres_virtual * info->fix.line_length;
    637	} else {
    638		info->fix.ypanstep = 16;
    639		info->fix.line_length = 0;
    640
    641		info->flags |= FBINFO_MISC_TILEBLITTING;
    642		info->tileops = &arkfb_tile_ops;
    643
    644		/* supports 8x16 tiles only */
    645		info->pixmap.blit_x = 1 << (8 - 1);
    646		info->pixmap.blit_y = 1 << (16 - 1);
    647
    648		offset_value = info->var.xres_virtual / 16;
    649		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
    650	}
    651
    652	info->var.xoffset = 0;
    653	info->var.yoffset = 0;
    654	info->var.activate = FB_ACTIVATE_NOW;
    655
    656	/* Unlock registers */
    657	svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
    658
    659	/* Blank screen and turn off sync */
    660	svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
    661	svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
    662
    663	/* Set default values */
    664	svga_set_default_gfx_regs(par->state.vgabase);
    665	svga_set_default_atc_regs(par->state.vgabase);
    666	svga_set_default_seq_regs(par->state.vgabase);
    667	svga_set_default_crt_regs(par->state.vgabase);
    668	svga_wcrt_multi(par->state.vgabase, ark_line_compare_regs, 0xFFFFFFFF);
    669	svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, 0);
    670
    671	/* ARK specific initialization */
    672	svga_wseq_mask(par->state.vgabase, 0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */
    673	svga_wseq_mask(par->state.vgabase, 0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */
    674
    675	vga_wseq(par->state.vgabase, 0x13, info->fix.smem_start >> 16);
    676	vga_wseq(par->state.vgabase, 0x14, info->fix.smem_start >> 24);
    677	vga_wseq(par->state.vgabase, 0x15, 0);
    678	vga_wseq(par->state.vgabase, 0x16, 0);
    679
    680	/* Set the FIFO threshold register */
    681	/* It is fascinating way to store 5-bit value in 8-bit register */
    682	regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1;
    683	vga_wseq(par->state.vgabase, 0x18, regval);
    684
    685	/* Set the offset register */
    686	fb_dbg(info, "offset register       : %d\n", offset_value);
    687	svga_wcrt_multi(par->state.vgabase, ark_offset_regs, offset_value);
    688
    689	/* fix for hi-res textmode */
    690	svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08);
    691
    692	if (info->var.vmode & FB_VMODE_DOUBLE)
    693		svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
    694	else
    695		svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
    696
    697	if (info->var.vmode & FB_VMODE_INTERLACED)
    698		svga_wcrt_mask(par->state.vgabase, 0x44, 0x04, 0x04);
    699	else
    700		svga_wcrt_mask(par->state.vgabase, 0x44, 0x00, 0x04);
    701
    702	hmul = 1;
    703	hdiv = 1;
    704	mode = svga_match_format(arkfb_formats, &(info->var), &(info->fix));
    705
    706	/* Set mode-specific register values */
    707	switch (mode) {
    708	case 0:
    709		fb_dbg(info, "text mode\n");
    710		svga_set_textmode_vga_regs(par->state.vgabase);
    711
    712		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
    713		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
    714		dac_set_mode(par->dac, DAC_PSEUDO8_8);
    715
    716		break;
    717	case 1:
    718		fb_dbg(info, "4 bit pseudocolor\n");
    719		vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
    720
    721		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
    722		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
    723		dac_set_mode(par->dac, DAC_PSEUDO8_8);
    724		break;
    725	case 2:
    726		fb_dbg(info, "4 bit pseudocolor, planar\n");
    727
    728		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
    729		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
    730		dac_set_mode(par->dac, DAC_PSEUDO8_8);
    731		break;
    732	case 3:
    733		fb_dbg(info, "8 bit pseudocolor\n");
    734
    735		vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode */
    736
    737		if (info->var.pixclock > 20000) {
    738			fb_dbg(info, "not using multiplex\n");
    739			svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
    740			dac_set_mode(par->dac, DAC_PSEUDO8_8);
    741		} else {
    742			fb_dbg(info, "using multiplex\n");
    743			svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
    744			dac_set_mode(par->dac, DAC_PSEUDO8_16);
    745			hdiv = 2;
    746		}
    747		break;
    748	case 4:
    749		fb_dbg(info, "5/5/5 truecolor\n");
    750
    751		vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
    752		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
    753		dac_set_mode(par->dac, DAC_RGB1555_16);
    754		break;
    755	case 5:
    756		fb_dbg(info, "5/6/5 truecolor\n");
    757
    758		vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
    759		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
    760		dac_set_mode(par->dac, DAC_RGB0565_16);
    761		break;
    762	case 6:
    763		fb_dbg(info, "8/8/8 truecolor\n");
    764
    765		vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode ??? */
    766		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
    767		dac_set_mode(par->dac, DAC_RGB0888_16);
    768		hmul = 3;
    769		hdiv = 2;
    770		break;
    771	case 7:
    772		fb_dbg(info, "8/8/8/8 truecolor\n");
    773
    774		vga_wseq(par->state.vgabase, 0x11, 0x1E); /* 32bpp accel mode */
    775		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
    776		dac_set_mode(par->dac, DAC_RGB8888_16);
    777		hmul = 2;
    778		break;
    779	default:
    780		fb_err(info, "unsupported mode - bug\n");
    781		return -EINVAL;
    782	}
    783
    784	ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);
    785	svga_set_timings(par->state.vgabase, &ark_timing_regs, &(info->var), hmul, hdiv,
    786			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
    787			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
    788			  hmul, info->node);
    789
    790	/* Set interlaced mode start/end register */
    791	value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
    792	value = ((value * hmul / hdiv) / 8) - 5;
    793	vga_wcrt(par->state.vgabase, 0x42, (value + 1) / 2);
    794
    795	memset_io(info->screen_base, 0x00, screen_size);
    796	/* Device and screen back on */
    797	svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
    798	svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
    799
    800	return 0;
    801}
    802
    803/* Set a colour register */
    804
    805static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
    806				u_int transp, struct fb_info *fb)
    807{
    808	switch (fb->var.bits_per_pixel) {
    809	case 0:
    810	case 4:
    811		if (regno >= 16)
    812			return -EINVAL;
    813
    814		if ((fb->var.bits_per_pixel == 4) &&
    815		    (fb->var.nonstd == 0)) {
    816			outb(0xF0, VGA_PEL_MSK);
    817			outb(regno*16, VGA_PEL_IW);
    818		} else {
    819			outb(0x0F, VGA_PEL_MSK);
    820			outb(regno, VGA_PEL_IW);
    821		}
    822		outb(red >> 10, VGA_PEL_D);
    823		outb(green >> 10, VGA_PEL_D);
    824		outb(blue >> 10, VGA_PEL_D);
    825		break;
    826	case 8:
    827		if (regno >= 256)
    828			return -EINVAL;
    829
    830		outb(0xFF, VGA_PEL_MSK);
    831		outb(regno, VGA_PEL_IW);
    832		outb(red >> 10, VGA_PEL_D);
    833		outb(green >> 10, VGA_PEL_D);
    834		outb(blue >> 10, VGA_PEL_D);
    835		break;
    836	case 16:
    837		if (regno >= 16)
    838			return 0;
    839
    840		if (fb->var.green.length == 5)
    841			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
    842				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
    843		else if (fb->var.green.length == 6)
    844			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
    845				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
    846		else
    847			return -EINVAL;
    848		break;
    849	case 24:
    850	case 32:
    851		if (regno >= 16)
    852			return 0;
    853
    854		((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
    855			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
    856		break;
    857	default:
    858		return -EINVAL;
    859	}
    860
    861	return 0;
    862}
    863
    864/* Set the display blanking state */
    865
    866static int arkfb_blank(int blank_mode, struct fb_info *info)
    867{
    868	struct arkfb_info *par = info->par;
    869
    870	switch (blank_mode) {
    871	case FB_BLANK_UNBLANK:
    872		fb_dbg(info, "unblank\n");
    873		svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
    874		svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
    875		break;
    876	case FB_BLANK_NORMAL:
    877		fb_dbg(info, "blank\n");
    878		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
    879		svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
    880		break;
    881	case FB_BLANK_POWERDOWN:
    882	case FB_BLANK_HSYNC_SUSPEND:
    883	case FB_BLANK_VSYNC_SUSPEND:
    884		fb_dbg(info, "sync down\n");
    885		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
    886		svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
    887		break;
    888	}
    889	return 0;
    890}
    891
    892
    893/* Pan the display */
    894
    895static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
    896{
    897	struct arkfb_info *par = info->par;
    898	unsigned int offset;
    899
    900	/* Calculate the offset */
    901	if (info->var.bits_per_pixel == 0) {
    902		offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
    903		       + (var->xoffset / 2);
    904		offset = offset >> 2;
    905	} else {
    906		offset = (var->yoffset * info->fix.line_length) +
    907			 (var->xoffset * info->var.bits_per_pixel / 8);
    908		offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3);
    909	}
    910
    911	/* Set the offset */
    912	svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, offset);
    913
    914	return 0;
    915}
    916
    917
    918/* ------------------------------------------------------------------------- */
    919
    920
    921/* Frame buffer operations */
    922
    923static const struct fb_ops arkfb_ops = {
    924	.owner		= THIS_MODULE,
    925	.fb_open	= arkfb_open,
    926	.fb_release	= arkfb_release,
    927	.fb_check_var	= arkfb_check_var,
    928	.fb_set_par	= arkfb_set_par,
    929	.fb_setcolreg	= arkfb_setcolreg,
    930	.fb_blank	= arkfb_blank,
    931	.fb_pan_display	= arkfb_pan_display,
    932	.fb_fillrect	= arkfb_fillrect,
    933	.fb_copyarea	= cfb_copyarea,
    934	.fb_imageblit	= arkfb_imageblit,
    935	.fb_get_caps    = svga_get_caps,
    936};
    937
    938
    939/* ------------------------------------------------------------------------- */
    940
    941
    942/* PCI probe */
    943static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
    944{
    945	struct pci_bus_region bus_reg;
    946	struct resource vga_res;
    947	struct fb_info *info;
    948	struct arkfb_info *par;
    949	int rc;
    950	u8 regval;
    951
    952	/* Ignore secondary VGA device because there is no VGA arbitration */
    953	if (! svga_primary_device(dev)) {
    954		dev_info(&(dev->dev), "ignoring secondary device\n");
    955		return -ENODEV;
    956	}
    957
    958	/* Allocate and fill driver data structure */
    959	info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev));
    960	if (!info)
    961		return -ENOMEM;
    962
    963	par = info->par;
    964	mutex_init(&par->open_lock);
    965
    966	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
    967	info->fbops = &arkfb_ops;
    968
    969	/* Prepare PCI device */
    970	rc = pci_enable_device(dev);
    971	if (rc < 0) {
    972		dev_err(info->device, "cannot enable PCI device\n");
    973		goto err_enable_device;
    974	}
    975
    976	rc = pci_request_regions(dev, "arkfb");
    977	if (rc < 0) {
    978		dev_err(info->device, "cannot reserve framebuffer region\n");
    979		goto err_request_regions;
    980	}
    981
    982	par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info);
    983	if (! par->dac) {
    984		rc = -ENOMEM;
    985		dev_err(info->device, "RAMDAC initialization failed\n");
    986		goto err_dac;
    987	}
    988
    989	info->fix.smem_start = pci_resource_start(dev, 0);
    990	info->fix.smem_len = pci_resource_len(dev, 0);
    991
    992	/* Map physical IO memory address into kernel space */
    993	info->screen_base = pci_iomap_wc(dev, 0, 0);
    994	if (! info->screen_base) {
    995		rc = -ENOMEM;
    996		dev_err(info->device, "iomap for framebuffer failed\n");
    997		goto err_iomap;
    998	}
    999
   1000	bus_reg.start = 0;
   1001	bus_reg.end = 64 * 1024;
   1002
   1003	vga_res.flags = IORESOURCE_IO;
   1004
   1005	pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
   1006
   1007	par->state.vgabase = (void __iomem *) (unsigned long) vga_res.start;
   1008
   1009	/* FIXME get memsize */
   1010	regval = vga_rseq(par->state.vgabase, 0x10);
   1011	info->screen_size = (1 << (regval >> 6)) << 20;
   1012	info->fix.smem_len = info->screen_size;
   1013
   1014	strcpy(info->fix.id, "ARK 2000PV");
   1015	info->fix.mmio_start = 0;
   1016	info->fix.mmio_len = 0;
   1017	info->fix.type = FB_TYPE_PACKED_PIXELS;
   1018	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
   1019	info->fix.ypanstep = 0;
   1020	info->fix.accel = FB_ACCEL_NONE;
   1021	info->pseudo_palette = (void*) (par->pseudo_palette);
   1022
   1023	/* Prepare startup mode */
   1024	rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
   1025	if (! ((rc == 1) || (rc == 2))) {
   1026		rc = -EINVAL;
   1027		dev_err(info->device, "mode %s not found\n", mode_option);
   1028		goto err_find_mode;
   1029	}
   1030
   1031	rc = fb_alloc_cmap(&info->cmap, 256, 0);
   1032	if (rc < 0) {
   1033		dev_err(info->device, "cannot allocate colormap\n");
   1034		goto err_alloc_cmap;
   1035	}
   1036
   1037	rc = register_framebuffer(info);
   1038	if (rc < 0) {
   1039		dev_err(info->device, "cannot register framebuffer\n");
   1040		goto err_reg_fb;
   1041	}
   1042
   1043	fb_info(info, "%s on %s, %d MB RAM\n",
   1044		info->fix.id, pci_name(dev), info->fix.smem_len >> 20);
   1045
   1046	/* Record a reference to the driver data */
   1047	pci_set_drvdata(dev, info);
   1048	par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
   1049					  info->fix.smem_len);
   1050	return 0;
   1051
   1052	/* Error handling */
   1053err_reg_fb:
   1054	fb_dealloc_cmap(&info->cmap);
   1055err_alloc_cmap:
   1056err_find_mode:
   1057	pci_iounmap(dev, info->screen_base);
   1058err_iomap:
   1059	dac_release(par->dac);
   1060err_dac:
   1061	pci_release_regions(dev);
   1062err_request_regions:
   1063/*	pci_disable_device(dev); */
   1064err_enable_device:
   1065	framebuffer_release(info);
   1066	return rc;
   1067}
   1068
   1069/* PCI remove */
   1070
   1071static void ark_pci_remove(struct pci_dev *dev)
   1072{
   1073	struct fb_info *info = pci_get_drvdata(dev);
   1074
   1075	if (info) {
   1076		struct arkfb_info *par = info->par;
   1077		arch_phys_wc_del(par->wc_cookie);
   1078		dac_release(par->dac);
   1079		unregister_framebuffer(info);
   1080		fb_dealloc_cmap(&info->cmap);
   1081
   1082		pci_iounmap(dev, info->screen_base);
   1083		pci_release_regions(dev);
   1084/*		pci_disable_device(dev); */
   1085
   1086		framebuffer_release(info);
   1087	}
   1088}
   1089
   1090
   1091/* PCI suspend */
   1092
   1093static int __maybe_unused ark_pci_suspend(struct device *dev)
   1094{
   1095	struct fb_info *info = dev_get_drvdata(dev);
   1096	struct arkfb_info *par = info->par;
   1097
   1098	dev_info(info->device, "suspend\n");
   1099
   1100	console_lock();
   1101	mutex_lock(&(par->open_lock));
   1102
   1103	if (par->ref_count == 0) {
   1104		mutex_unlock(&(par->open_lock));
   1105		console_unlock();
   1106		return 0;
   1107	}
   1108
   1109	fb_set_suspend(info, 1);
   1110
   1111	mutex_unlock(&(par->open_lock));
   1112	console_unlock();
   1113
   1114	return 0;
   1115}
   1116
   1117
   1118/* PCI resume */
   1119
   1120static int __maybe_unused ark_pci_resume(struct device *dev)
   1121{
   1122	struct fb_info *info = dev_get_drvdata(dev);
   1123	struct arkfb_info *par = info->par;
   1124
   1125	dev_info(info->device, "resume\n");
   1126
   1127	console_lock();
   1128	mutex_lock(&(par->open_lock));
   1129
   1130	if (par->ref_count == 0)
   1131		goto fail;
   1132
   1133	arkfb_set_par(info);
   1134	fb_set_suspend(info, 0);
   1135
   1136fail:
   1137	mutex_unlock(&(par->open_lock));
   1138	console_unlock();
   1139	return 0;
   1140}
   1141
   1142static const struct dev_pm_ops ark_pci_pm_ops = {
   1143#ifdef CONFIG_PM_SLEEP
   1144	.suspend	= ark_pci_suspend,
   1145	.resume		= ark_pci_resume,
   1146	.freeze		= NULL,
   1147	.thaw		= ark_pci_resume,
   1148	.poweroff	= ark_pci_suspend,
   1149	.restore	= ark_pci_resume,
   1150#endif
   1151};
   1152
   1153/* List of boards that we are trying to support */
   1154
   1155static const struct pci_device_id ark_devices[] = {
   1156	{PCI_DEVICE(0xEDD8, 0xA099)},
   1157	{0, 0, 0, 0, 0, 0, 0}
   1158};
   1159
   1160
   1161MODULE_DEVICE_TABLE(pci, ark_devices);
   1162
   1163static struct pci_driver arkfb_pci_driver = {
   1164	.name		= "arkfb",
   1165	.id_table	= ark_devices,
   1166	.probe		= ark_pci_probe,
   1167	.remove		= ark_pci_remove,
   1168	.driver.pm	= &ark_pci_pm_ops,
   1169};
   1170
   1171/* Cleanup */
   1172
   1173static void __exit arkfb_cleanup(void)
   1174{
   1175	pr_debug("arkfb: cleaning up\n");
   1176	pci_unregister_driver(&arkfb_pci_driver);
   1177}
   1178
   1179/* Driver Initialisation */
   1180
   1181static int __init arkfb_init(void)
   1182{
   1183
   1184#ifndef MODULE
   1185	char *option = NULL;
   1186
   1187	if (fb_get_options("arkfb", &option))
   1188		return -ENODEV;
   1189
   1190	if (option && *option)
   1191		mode_option = option;
   1192#endif
   1193
   1194	pr_debug("arkfb: initializing\n");
   1195	return pci_register_driver(&arkfb_pci_driver);
   1196}
   1197
   1198module_init(arkfb_init);
   1199module_exit(arkfb_cleanup);