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