Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * i740fb - framebuffer driver for Intel740
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * Copyright (c) 2011 Ondrej Zary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * which was partially based on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *  VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *	and Petr Vandrovec <VANDROVE@vc.cvut.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *  i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *	Texas.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *  i740fb by Patrick LERDA, v0.9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/pci_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/i2c-algo-bit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <video/vga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include "i740_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) static char *mode_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) static int mtrr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) struct i740fb_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 	unsigned char __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 	bool has_sgram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 	int wc_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 	bool ddc_registered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 	struct i2c_adapter ddc_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 	struct i2c_algo_bit_data ddc_algo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 	u32 pseudo_palette[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	struct mutex open_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 	unsigned int ref_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 	u8 crtc[VGA_CRT_C];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 	u8 atc[VGA_ATT_C];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 	u8 gdc[VGA_GFX_C];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	u8 seq[VGA_SEQ_C];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	u8 misc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	u8 vss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 	/* i740 specific registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	u8 display_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	u8 pixelpipe_cfg0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 	u8 pixelpipe_cfg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 	u8 pixelpipe_cfg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	u8 video_clk2_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	u8 video_clk2_n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	u8 video_clk2_mn_msbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	u8 video_clk2_div_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	u8 pll_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	u8 address_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	u8 io_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	u8 bitblt_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	u8 ext_vert_total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	u8 ext_vert_disp_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	u8 ext_vert_sync_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	u8 ext_vert_blank_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	u8 ext_horiz_total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	u8 ext_horiz_blank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	u8 ext_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	u8 interlace_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	u32 lmi_fifo_watermark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	u8 ext_start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 	u8 ext_start_addr_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #define DACSPEED8	203
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #define DACSPEED16	163
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define DACSPEED24_SG	136
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define DACSPEED24_SD	128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) #define DACSPEED32	86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) static const struct fb_fix_screeninfo i740fb_fix = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 	.id =		"i740fb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	.type =		FB_TYPE_PACKED_PIXELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	.visual =	FB_VISUAL_TRUECOLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	.xpanstep =	8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	.ypanstep =	1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	.accel =	FB_ACCEL_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	vga_mm_w(par->regs, port, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) static inline u8 i740inb(struct i740fb_par *par, u16 port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	return vga_mm_r(par->regs, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	vga_mm_w_fast(par->regs, port, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	vga_mm_w(par->regs, port, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	return vga_mm_r(par->regs, port+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 				   u8 val, u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	vga_mm_w_fast(par->regs, port, reg, (val & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 		| (i740inreg(par, port, reg) & ~mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) #define REG_DDC_DRIVE	0x62
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) #define REG_DDC_STATE	0x63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) #define DDC_SCL		(1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) #define DDC_SDA		(1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) static void i740fb_ddc_setscl(void *data, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	struct i740fb_par *par = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SCL, DDC_SCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SCL : 0, DDC_SCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) static void i740fb_ddc_setsda(void *data, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	struct i740fb_par *par = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SDA, DDC_SDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SDA : 0, DDC_SDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) static int i740fb_ddc_getscl(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	struct i740fb_par *par = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) static int i740fb_ddc_getsda(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	struct i740fb_par *par = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) static int i740fb_setup_ddc_bus(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	strlcpy(par->ddc_adapter.name, info->fix.id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 		sizeof(par->ddc_adapter.name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	par->ddc_adapter.owner		= THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	par->ddc_adapter.class		= I2C_CLASS_DDC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	par->ddc_adapter.algo_data	= &par->ddc_algo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	par->ddc_adapter.dev.parent	= info->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	par->ddc_algo.setsda		= i740fb_ddc_setsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	par->ddc_algo.setscl		= i740fb_ddc_setscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	par->ddc_algo.getsda		= i740fb_ddc_getsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	par->ddc_algo.getscl		= i740fb_ddc_getscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	par->ddc_algo.udelay		= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	par->ddc_algo.timeout		= 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	par->ddc_algo.data		= par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	i2c_set_adapdata(&par->ddc_adapter, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	return i2c_bit_add_bus(&par->ddc_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) static int i740fb_open(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	par->ref_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) static int i740fb_release(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	if (par->ref_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 		fb_err(info, "release called with zero refcount\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 		mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	par->ref_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	 * Would like to calculate these values automatically, but a generic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	 * algorithm does not seem possible.  Note: These FIFO water mark
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	 * values were tested on several cards and seem to eliminate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	 * all of the snow and vertical banding, but fine adjustments will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	 * probably be required for other cards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	u32 wm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 		if	(freq > 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 			wm = 0x18120000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 		else if (freq > 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 			wm = 0x16110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 		else if (freq > 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 			wm = 0x120E0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 			wm = 0x100D0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	case 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		if (par->has_sgram) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 			if	(freq > 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 				wm = 0x2C1D0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 			else if (freq > 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 				wm = 0x2C180000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 			else if (freq > 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 				wm = 0x24160000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 			else if (freq >  90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 				wm = 0x18120000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 			else if (freq >  50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 				wm = 0x16110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 			else if (freq >  32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 				wm = 0x13100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 				wm = 0x120E0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 			if	(freq > 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 				wm = 0x28200000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 			else if (freq > 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 				wm = 0x2A1E0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 			else if (freq > 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 				wm = 0x2B1A0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 			else if (freq > 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 				wm = 0x2C180000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 			else if (freq > 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 				wm = 0x24180000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 			else if (freq >  90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 				wm = 0x18120000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 			else if (freq >  50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 				wm = 0x16110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 			else if (freq >  32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 				wm = 0x13100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 				wm = 0x120E0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 		if (par->has_sgram) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 			if	(freq > 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 				wm = 0x31200000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 			else if (freq > 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 				wm = 0x2E200000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 			else if (freq > 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 				wm = 0x2C1D0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 			else if (freq >  80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 				wm = 0x25180000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 			else if (freq >  64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 				wm = 0x24160000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 			else if (freq >  49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 				wm = 0x18120000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 			else if (freq >  32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 				wm = 0x16110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 				wm = 0x13100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 			if	(freq > 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 				wm = 0x311F0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 			else if (freq > 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 				wm = 0x2C1D0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 			else if (freq >  80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 				wm = 0x25180000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 			else if (freq >  64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 				wm = 0x24160000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 			else if (freq >  49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 				wm = 0x18120000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 			else if (freq >  32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 				wm = 0x16110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 				wm = 0x13100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 		if (par->has_sgram) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 			if	(freq >  80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 				wm = 0x2A200000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 			else if (freq >  60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 				wm = 0x281A0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 			else if (freq >  49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 				wm = 0x25180000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 			else if (freq >  32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 				wm = 0x18120000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 				wm = 0x16110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 			if	(freq >  80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 				wm = 0x29200000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 			else if (freq >  60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 				wm = 0x281A0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 			else if (freq >  49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 				wm = 0x25180000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 			else if (freq >  32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 				wm = 0x18120000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 				wm = 0x16110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	return wm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) /* clock calculation from i740fb by Patrick LERDA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) #define I740_RFREQ		1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) #define TARGET_MAX_N		30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) #define I740_FFIX		(1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) #define I740_RFREQ_FIX		(I740_RFREQ / I740_FFIX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) #define I740_REF_FREQ		(6667 * I740_FFIX / 100)	/* 66.67 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) #define I740_MAX_VCO_FREQ	(450 * I740_FFIX)		/* 450 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) static void i740_calc_vclk(u32 freq, struct i740fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	const u32 err_max    = freq / (200  * I740_RFREQ / I740_FFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	u32 err_best = 512 * I740_FFIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	u32 f_err, f_vco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	int m_best = 0, n_best = 0, p_best = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	int m, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	freq = freq / I740_RFREQ_FIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	n = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 		n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 		if (m < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 			m = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 			u32 f_out = (((m * I740_REF_FREQ * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 				 / n) + ((1 << p_best) / 2)) / (1 << p_best);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 			f_err = (freq - f_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 			if (abs(f_err) < err_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 				m_best = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 				n_best = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 				err_best = f_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	} while ((abs(f_err) >= err_target) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		 ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	if (abs(f_err) < err_target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		m_best = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		n_best = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	par->video_clk2_m = (m_best - 2) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	par->video_clk2_n = (n_best - 2) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 				 | (((m_best - 2) >> 8) & VCO_M_MSBS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	par->video_clk2_div_sel = ((p_best << 4) | REF_DIV_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) static int i740fb_decode_var(const struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 			     struct i740fb_par *par, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	 * Get the video params out of 'var'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	 * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	u32 xres, right, hslen, left, xtotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	u32 yres, lower, vslen, upper, ytotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	u32 vxres, xoffset, vyres, yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	u32 bpp, base, dacspeed24, mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	u8 r7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 		  var->xres, var->yres, var->xres_virtual, var->xres_virtual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	dev_dbg(info->device, "	xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		  var->xoffset, var->yoffset, var->bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		  var->grayscale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	dev_dbg(info->device, "	activate: %i, nonstd: %i, vmode: %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 		  var->activate, var->nonstd, var->vmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	dev_dbg(info->device, "	pixclock: %i, hsynclen:%i, vsynclen:%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		  var->pixclock, var->hsync_len, var->vsync_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	dev_dbg(info->device, "	left: %i, right: %i, up:%i, lower:%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		  var->left_margin, var->right_margin, var->upper_margin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		  var->lower_margin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	bpp = var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	case 1 ... 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		bpp = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 		if ((1000000 / var->pixclock) > DACSPEED8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 				1000000 / var->pixclock, DACSPEED8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	case 9 ... 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 		bpp = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		if ((1000000 / var->pixclock) > DACSPEED16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 				1000000 / var->pixclock, DACSPEED16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	case 17 ... 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 		bpp = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		if ((1000000 / var->pixclock) > dacspeed24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 				1000000 / var->pixclock, dacspeed24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	case 25 ... 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		bpp = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		if ((1000000 / var->pixclock) > DACSPEED32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 				1000000 / var->pixclock, DACSPEED32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	xres = ALIGN(var->xres, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	vxres = ALIGN(var->xres_virtual, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	if (vxres < xres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		vxres = xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	xoffset = ALIGN(var->xoffset, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	if (xres + xoffset > vxres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		xoffset = vxres - xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	left = ALIGN(var->left_margin, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	right = ALIGN(var->right_margin, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	hslen = ALIGN(var->hsync_len, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	yres = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	vyres = var->yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	if (yres > vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		vyres = yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	yoffset = var->yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	if (yres + yoffset > vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		yoffset = vyres - yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	lower = var->lower_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	vslen = var->vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	upper = var->upper_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	mem = vxres * vyres * ((bpp + 1) / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	if (mem > info->screen_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 		dev_err(info->device, "not enough video memory (%d KB requested, %ld KB available)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 			mem >> 10, info->screen_size >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	if (yoffset + yres > vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		yoffset = vyres - yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	xtotal = xres + right + hslen + left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	ytotal = yres + lower + vslen + upper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 		| ((((xres + right + hslen) >> 3) & 0x20) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		| 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	r7 = 0x10;	/* disable linecompare */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	if (ytotal & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 		r7 |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	if (ytotal & 0x200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		r7 |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	if (var->vmode & FB_VMODE_DOUBLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	if ((yres-1) & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 		r7 |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	if ((yres-1) & 0x200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		r7 |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	if ((yres + lower - 1) & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 		r7 |= 0x0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	if ((yres + lower - 1) & 0x200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 		r7 |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	/* disabled IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	par->crtc[VGA_CRTC_V_SYNC_END] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	/* 0x7F for VGA, but some SVGA chips require all 8 bits to be set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	par->crtc[VGA_CRTC_MODE] = 0xC3 ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	par->crtc[VGA_CRTC_OVERFLOW] = r7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	par->vss = 0x00;	/* 3DA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	for (i = 0x00; i < 0x10; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		par->atc[i] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	par->atc[VGA_ATC_MODE] = 0x81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	par->atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	par->misc = 0xC3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 		par->misc &= ~0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 		par->misc &= ~0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	par->gdc[VGA_GFX_SR_VALUE] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	par->gdc[VGA_GFX_PLANE_READ] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	par->gdc[VGA_GFX_MODE] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	par->gdc[VGA_GFX_MISC] = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	base = (yoffset * vxres + (xoffset & ~7)) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		par->ext_offset = vxres >> 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 		par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		par->bitblt_cntl = COLEXP_8BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	case 15: /* 0rrrrrgg gggbbbbb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 	case 16: /* rrrrrggg gggbbbbb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		par->pixelpipe_cfg1 = (var->green.length == 6) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 			DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		par->ext_offset = vxres >> 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		par->bitblt_cntl = COLEXP_16BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		base *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 		par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 		par->ext_offset = (vxres * 3) >> 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 		par->bitblt_cntl = COLEXP_24BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		base *= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		par->ext_offset = vxres >> 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 		par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		par->bitblt_cntl = COLEXP_RESERVED; /* Unimplemented on i740 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		base *= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	par->ext_start_addr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 		((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	par->pixelpipe_cfg0 = DAC_8_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	par->io_cntl = EXTENDED_CRTC_CNTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	par->display_cntl = HIRES_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	/* Set the MCLK freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	/* Calculate the extended CRTC regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	par->ext_vert_total = (ytotal - 2) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	par->ext_vert_disp_end = (yres - 1) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	par->ext_vert_sync_start = (yres + lower) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	par->ext_vert_blank_start = (yres + lower) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	par->interlace_cntl = INTERLACE_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	/* Set the overscan color to 0. (NOTE: This only affects >8bpp mode) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	par->atc[VGA_ATC_OVERSCAN] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	/* Calculate VCLK that most closely matches the requested dot clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	/* Since we program the clocks ourselves, always use VCLK2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	par->misc |= 0x0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	/* Calculate the FIFO Watermark and Burst Length. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	par->lmi_fifo_watermark =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		i740_calc_fifo(par, 1000000 / var->pixclock, bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	switch (var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 		var->red.offset	= var->green.offset = var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		var->red.length	= var->green.length = var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		switch (var->green.length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 			var->red.offset = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 			var->green.offset = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 			var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 			var->red.length	= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 			var->green.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 			var->blue.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 			var->red.offset = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 			var->green.offset = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 			var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 			var->red.length = var->blue.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 		var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 		var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 		var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		var->red.length	= var->green.length = var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		var->transp.offset = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		var->transp.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		var->red.length = var->green.length = var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	if (var->xres > var->xres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		var->xres_virtual = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	if (var->yres > var->yres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		var->yres_virtual = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	if (info->monspecs.hfmax && info->monspecs.vfmax &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	    info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) static void vga_protect(struct i740fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	/* disable the display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	i740inb(par, 0x3DA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	i740outb(par, VGA_ATT_W, 0x00);	/* enable palette access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) static void vga_unprotect(struct i740fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	/* reenable display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	i740inb(par, 0x3DA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	i740outb(par, VGA_ATT_W, 0x20);	/* disable palette access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) static int i740fb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	u32 itemp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	i = i740fb_decode_var(&info->var, par, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	memset(info->screen_base, 0, info->screen_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	vga_protect(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 			par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	i740inb(par, 0x3DA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	i740outb(par, 0x3C0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	/* update misc output register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	i740outb(par, VGA_MIS_W, par->misc | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	/* synchronous reset on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	/* write sequencer registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 			par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	for (i = 2; i < VGA_SEQ_C; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	/* synchronous reset off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	/* deprotect CRT registers 0-7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 			par->crtc[VGA_CRTC_V_SYNC_END]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	/* write CRT registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	for (i = 0; i < VGA_CRT_C; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	/* write graphics controller registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	for (i = 0; i < VGA_GFX_C; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	/* write attribute controller registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	for (i = 0; i < VGA_ATT_C; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		i740inb(par, VGA_IS1_RC);		/* reset flip-flop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 		i740outb(par, VGA_ATT_IW, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		i740outb(par, VGA_ATT_IW, par->atc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	i740inb(par, VGA_IS1_RC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	i740outb(par, VGA_ATT_IW, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 			par->ext_vert_sync_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 			par->ext_vert_blank_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 			par->interlace_cntl, INTERLACE_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	i740outreg_mask(par, XRX, DISPLAY_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 			par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 			par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	itemp = readl(par->regs + FWATER_BLC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	itemp |= par->lmi_fifo_watermark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	writel(itemp, par->regs + FWATER_BLC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	i740outreg_mask(par, XRX, IO_CTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 			par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		i740outb(par, VGA_PEL_MSK, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 		i740outb(par, VGA_PEL_IW, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		for (i = 0; i < 256; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 			itemp = (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 			i740outb(par, VGA_PEL_D, itemp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 			i740outb(par, VGA_PEL_D, itemp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 			i740outb(par, VGA_PEL_D, itemp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	/* Wait for screen to stabilize. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	mdelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	vga_unprotect(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	info->fix.line_length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			info->var.xres_virtual * info->var.bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	if (info->var.bits_per_pixel == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		info->fix.visual = FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 			   unsigned blue, unsigned transp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 			   struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	u32 r, g, b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		regno, red, green, blue, transp, info->var.bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	switch (info->fix.visual) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	case FB_VISUAL_PSEUDOCOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		if (regno >= 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		i740outb(info->par, VGA_PEL_IW, regno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		i740outb(info->par, VGA_PEL_D, red >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 		i740outb(info->par, VGA_PEL_D, green >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		i740outb(info->par, VGA_PEL_D, blue >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	case FB_VISUAL_TRUECOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		if (regno >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		r = (red >> (16 - info->var.red.length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 			<< info->var.red.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		b = (blue >> (16 - info->var.blue.length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 			<< info->var.blue.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 		g = (green >> (16 - info->var.green.length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 			<< info->var.green.offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 		((u32 *) info->pseudo_palette)[regno] = r | g | b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) static int i740fb_pan_display(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 				 struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	u32 base = (var->yoffset * info->var.xres_virtual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 		 + (var->xoffset & ~7)) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	dev_dbg(info->device, "pan_display: xoffset: %i yoffset: %i base: %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 		var->xoffset, var->yoffset, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	switch (info->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	case 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		base *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 		 * The last bit does not seem to have any effect on the start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		 * address register in 24bpp mode, so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		base *= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		base *= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	par->ext_start_addr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO,  base & 0x000000FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 			(base & 0x0000FF00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 			(base & 0x3FC00000) >> 22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) static int i740fb_blank(int blank_mode, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	unsigned char SEQ01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	int DPMSSyncSelect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	switch (blank_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	case FB_BLANK_UNBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	case FB_BLANK_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		SEQ01 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	case FB_BLANK_VSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		SEQ01 = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	case FB_BLANK_HSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		SEQ01 = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	case FB_BLANK_POWERDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		SEQ01 = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	/* Turn the screen on/off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	i740outb(par, SRX, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	i740outb(par, SRX, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	i740outb(par, SRX + 1, SEQ01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	/* Set the DPMS mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	/* Let fbcon do a soft blank for us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) static const struct fb_ops i740fb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	.owner		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	.fb_open	= i740fb_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	.fb_release	= i740fb_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	.fb_check_var	= i740fb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	.fb_set_par	= i740fb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	.fb_setcolreg	= i740fb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	.fb_blank	= i740fb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	.fb_pan_display	= i740fb_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	.fb_fillrect	= cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	.fb_copyarea	= cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	.fb_imageblit	= cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	struct i740fb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	int ret, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	u8 *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	mutex_init(&par->open_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	info->var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	info->var.bits_per_pixel = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	info->fbops = &i740fb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	info->pseudo_palette = par->pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	ret = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 		dev_err(info->device, "cannot enable PCI device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		goto err_enable_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	ret = pci_request_regions(dev, info->fix.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		dev_err(info->device, "error requesting regions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		goto err_request_regions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	info->screen_base = pci_ioremap_wc_bar(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	if (!info->screen_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 		dev_err(info->device, "error remapping base\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		goto err_ioremap_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	par->regs = pci_ioremap_bar(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	if (!par->regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 		dev_err(info->device, "error remapping MMIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		goto err_ioremap_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	/* detect memory size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 							== DRAM_ROW_1_SDRAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 		i740outb(par, XRX, DRAM_ROW_BNDRY_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 		i740outb(par, XRX, DRAM_ROW_BNDRY_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	/* detect memory type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	tmp = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	par->has_sgram = !((tmp & DRAM_RAS_TIMING) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 			   (tmp & DRAM_RAS_PRECHARGE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	fb_info(info, "Intel740 on %s, %ld KB %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 		pci_name(dev), info->screen_size >> 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 		par->has_sgram ? "SGRAM" : "SDRAM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	info->fix = i740fb_fix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	info->fix.mmio_start = pci_resource_start(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	info->fix.mmio_len = pci_resource_len(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	info->fix.smem_start = pci_resource_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	info->fix.smem_len = info->screen_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	if (i740fb_setup_ddc_bus(info) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		par->ddc_registered = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 		edid = fb_ddc_read(&par->ddc_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 		if (edid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 			fb_edid_to_monspecs(edid, &info->monspecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 			kfree(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 			if (!info->monspecs.modedb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 				dev_err(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 					"error getting mode database\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 			else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 				const struct fb_videomode *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 				fb_videomode_to_modelist(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 					info->monspecs.modedb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 					info->monspecs.modedb_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 					&info->modelist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 				m = fb_find_best_display(&info->monspecs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 							 &info->modelist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 				if (m) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 					fb_videomode_to_var(&info->var, m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 					/* fill all other info->var's fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 					if (!i740fb_check_var(&info->var, info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 						found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	if (!mode_option && !found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 		mode_option = "640x480-8@60";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	if (mode_option) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 		ret = fb_find_mode(&info->var, info, mode_option,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 				   info->monspecs.modedb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 				   info->monspecs.modedb_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 				   NULL, info->var.bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		if (!ret || ret == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 			dev_err(info->device, "mode %s not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 				mode_option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 			ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	fb_destroy_modedb(info->monspecs.modedb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	info->monspecs.modedb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	/* maximize virtual vertical size for fast scrolling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	info->var.yres_virtual = info->fix.smem_len * 8 /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 			(info->var.bits_per_pixel * info->var.xres_virtual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	if (ret == -EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		goto err_find_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	ret = fb_alloc_cmap(&info->cmap, 256, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		dev_err(info->device, "cannot allocate colormap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		goto err_alloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	ret = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		dev_err(info->device, "error registering framebuffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 		goto err_reg_framebuffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	fb_info(info, "%s frame buffer device\n", info->fix.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	pci_set_drvdata(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	if (mtrr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 		par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 						  info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) err_reg_framebuffer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) err_alloc_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) err_find_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	if (par->ddc_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 		i2c_del_adapter(&par->ddc_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	pci_iounmap(dev, par->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) err_ioremap_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	pci_iounmap(dev, info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) err_ioremap_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) err_request_regions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /*	pci_disable_device(dev); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) err_enable_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) static void i740fb_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	struct fb_info *info = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		arch_phys_wc_del(par->wc_cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 		unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 		fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 		if (par->ddc_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 			i2c_del_adapter(&par->ddc_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 		pci_iounmap(dev, par->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		pci_iounmap(dev, info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) /*		pci_disable_device(dev); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) static int __maybe_unused i740fb_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	/* do nothing if framebuffer is not active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	if (par->ref_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 		mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 		console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	fb_set_suspend(info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) static int __maybe_unused i740fb_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 	struct i740fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 	console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	if (par->ref_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	i740fb_set_par(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 	fb_set_suspend(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) static const struct dev_pm_ops i740fb_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	.suspend	= i740fb_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	.resume		= i740fb_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	.freeze		= NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	.thaw		= i740fb_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	.poweroff	= i740fb_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	.restore	= i740fb_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) #define I740_ID_PCI 0x00d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) #define I740_ID_AGP 0x7800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) static const struct pci_device_id i740fb_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	{ 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) MODULE_DEVICE_TABLE(pci, i740fb_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) static struct pci_driver i740fb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	.name		= "i740fb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	.id_table	= i740fb_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 	.probe		= i740fb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	.remove		= i740fb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	.driver.pm	= &i740fb_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) static int  __init i740fb_setup(char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	char *opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 	if (!options || !*options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 	while ((opt = strsep(&options, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 		if (!*opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 		else if (!strncmp(opt, "mtrr:", 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 			mtrr = simple_strtoul(opt + 5, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 			mode_option = opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) static int __init i740fb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	char *option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	if (fb_get_options("i740fb", &option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	i740fb_setup(option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	return pci_register_driver(&i740fb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) static void __exit i740fb_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	pci_unregister_driver(&i740fb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) module_init(i740fb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) module_exit(i740fb_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) MODULE_DESCRIPTION("fbdev driver for Intel740");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) module_param(mode_option, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) module_param(mtrr, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");