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)  * drivers/mb862xx/mb862xxfb.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * (C) 2008 Anatolij Gustschin <agust@denx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * DENX Software Engineering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #if defined(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include "mb862xxfb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include "mb862xx_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #define NR_PALETTE		256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #define MB862XX_MEM_SIZE	0x1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #define CORALP_MEM_SIZE		0x2000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #define CARMINE_MEM_SIZE	0x8000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #define DRV_NAME		"mb862xxfb"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #if defined(CONFIG_SOCRATES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) static struct mb862xx_gc_mode socrates_gc_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) 	/* Mode for Prime View PM070WL4 TFT LCD Panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 	{ "800x480", 45, 800, 480, 40000, 86, 42, 33, 10, 128, 2, 0, 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 	/* 16 bits/pixel, 16MB, 133MHz, SDRAM memory mode value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 	16, 0x1000000, GC_CCF_COT_133, 0x4157ba63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) /* Helpers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) static inline int h_total(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	return var->xres + var->left_margin +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 		var->right_margin + var->hsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) static inline int v_total(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	return var->yres + var->upper_margin +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 		var->lower_margin + var->vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) static inline int hsp(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	return var->xres + var->right_margin - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) static inline int vsp(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	return var->yres + var->lower_margin - 1;
^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) static inline int d_pitch(struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	return var->xres * var->bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) static inline unsigned int chan_to_field(unsigned int chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 					 struct fb_bitfield *bf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	chan &= 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	chan >>= 16 - bf->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	return chan << bf->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) static int mb862xxfb_setcolreg(unsigned regno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 			       unsigned red, unsigned green, unsigned blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 			       unsigned transp, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	struct mb862xxfb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	switch (info->fix.visual) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 	case FB_VISUAL_TRUECOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 		if (regno < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 			val  = chan_to_field(red,   &info->var.red);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 			val |= chan_to_field(green, &info->var.green);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 			val |= chan_to_field(blue,  &info->var.blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 			par->pseudo_palette[regno] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	case FB_VISUAL_PSEUDOCOLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 		if (regno < 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 			val = (red >> 8) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 			val |= (green >> 8) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 			val |= blue >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 			outreg(disp, GC_L0PAL0 + (regno * 4), val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 		return 1;   /* unsupported type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) static int mb862xxfb_check_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 			       struct fb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	if (fbi->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 		dev_dbg(fbi->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	/* check if these values fit into the registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	if (var->hsync_len > 255 || var->vsync_len > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	if ((var->xres + var->right_margin) >= 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	if ((var->yres + var->lower_margin) > 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	if (h_total(var) > 4096 || v_total(var) > 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 	if (var->xres_virtual > 4096 || var->yres_virtual > 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	if (var->bits_per_pixel <= 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		var->bits_per_pixel = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	else if (var->bits_per_pixel <= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		var->bits_per_pixel = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	else if (var->bits_per_pixel <= 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 		var->bits_per_pixel = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	 * can cope with 8,16 or 24/32bpp if resulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	 * pitch is divisible by 64 without remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 		int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 		var->bits_per_pixel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 			var->bits_per_pixel += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 			r = d_pitch(&fbi->var) % GC_L0M_L0W_UNIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 		} while (r && var->bits_per_pixel <= 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 		if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	/* line length is going to be 128 bit aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	tmp = (var->xres * var->bits_per_pixel) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	if ((tmp & 15) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	/* set r/g/b positions and validate bpp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	switch (var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 		var->red.length		= var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 		var->green.length	= var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 		var->blue.length	= var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 		var->red.offset		= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 		var->green.offset	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 		var->blue.offset	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 		var->transp.length	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 		var->red.length		= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 		var->green.length	= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 		var->blue.length	= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 		var->red.offset		= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 		var->green.offset	= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 		var->blue.offset	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		var->transp.length	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 		var->transp.length	= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 		var->red.length		= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 		var->green.length	= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 		var->blue.length	= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 		var->transp.offset	= 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 		var->red.offset		= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 		var->green.offset	= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 		var->blue.offset	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) static struct fb_ops mb862xxfb_ops;
^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)  * set display parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) static int mb862xxfb_set_par(struct fb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	struct mb862xxfb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	unsigned long reg, sc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	dev_dbg(par->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	if (par->type == BT_CORALP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		mb862xxfb_init_accel(fbi, &mb862xxfb_ops, fbi->var.xres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	if (par->pre_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	/* disp off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	reg &= ~GC_DCM01_DEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	outreg(disp, GC_DCM1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	/* set display reference clock div. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	sc = par->refclk / (1000000 / fbi->var.pixclock) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	reg &= ~(GC_DCM01_CKS | GC_DCM01_RESV | GC_DCM01_SC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	reg |= sc << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	outreg(disp, GC_DCM1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	dev_dbg(par->dev, "SC 0x%lx\n", sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	/* disp dimension, format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	reg =  pack(d_pitch(&fbi->var) / GC_L0M_L0W_UNIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 		    (fbi->var.yres - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	if (fbi->var.bits_per_pixel == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 		reg |= GC_L0M_L0C_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	outreg(disp, GC_L0M, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	if (fbi->var.bits_per_pixel == 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		reg = inreg(disp, GC_L0EM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 		outreg(disp, GC_L0EM, reg | GC_L0EM_L0EC_24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	outreg(disp, GC_WY_WX, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	reg = pack(fbi->var.yres - 1, fbi->var.xres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	outreg(disp, GC_WH_WW, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	outreg(disp, GC_L0OA0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	outreg(disp, GC_L0DA0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	outreg(disp, GC_L0DY_L0DX, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	outreg(disp, GC_L0WY_L0WX, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	outreg(disp, GC_L0WH_L0WW, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	/* both HW-cursors off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	reg = inreg(disp, GC_CPM_CUTC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	reg &= ~(GC_CPM_CEN0 | GC_CPM_CEN1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	outreg(disp, GC_CPM_CUTC, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	/* timings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	reg = pack(fbi->var.xres - 1, fbi->var.xres - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	outreg(disp, GC_HDB_HDP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	reg = pack((fbi->var.yres - 1), vsp(&fbi->var));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	outreg(disp, GC_VDP_VSP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	reg = ((fbi->var.vsync_len - 1) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	      pack((fbi->var.hsync_len - 1), hsp(&fbi->var));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	outreg(disp, GC_VSW_HSW_HSP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	outreg(disp, GC_HTP, pack(h_total(&fbi->var) - 1, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	outreg(disp, GC_VTR, pack(v_total(&fbi->var) - 1, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	/* display on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	reg |= GC_DCM01_DEN | GC_DCM01_L0E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	reg &= ~GC_DCM01_ESY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	outreg(disp, GC_DCM1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) static int mb862xxfb_pan(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 			 struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	struct mb862xxfb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	unsigned long reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	reg = pack(var->yoffset, var->xoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	outreg(disp, GC_L0WY_L0WX, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	reg = pack(info->var.yres_virtual, info->var.xres_virtual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	outreg(disp, GC_L0WH_L0WW, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	return 0;
^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) static int mb862xxfb_blank(int mode, struct fb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	struct mb862xxfb_par  *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	unsigned long reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	dev_dbg(fbi->dev, "blank mode=%d\n", mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	case FB_BLANK_POWERDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 		reg &= ~GC_DCM01_DEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 		outreg(disp, GC_DCM1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	case FB_BLANK_UNBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 		reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 		reg |= GC_DCM01_DEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 		outreg(disp, GC_DCM1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	case FB_BLANK_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	case FB_BLANK_VSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	case FB_BLANK_HSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 			   unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	struct mb862xxfb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	struct mb862xx_l1_cfg *l1_cfg = &par->l1_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	int *enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	u32 l1em = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	case MB862XX_L1_GET_CFG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 		if (copy_to_user(argp, l1_cfg, sizeof(*l1_cfg)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	case MB862XX_L1_SET_CFG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 		if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 		if (l1_cfg->dh == 0 || l1_cfg->dw == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 		if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 			/* downscaling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 			outreg(cap, GC_CAP_CSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 				pack((l1_cfg->sh << 11) / l1_cfg->dh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 				     (l1_cfg->sw << 11) / l1_cfg->dw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 			l1em = inreg(disp, GC_L1EM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 			l1em &= ~GC_L1EM_DM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 		} else if ((l1_cfg->sw <= l1_cfg->dw) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 			   (l1_cfg->sh <= l1_cfg->dh)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 			/* upscaling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 			outreg(cap, GC_CAP_CSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 				pack((l1_cfg->sh << 11) / l1_cfg->dh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 				     (l1_cfg->sw << 11) / l1_cfg->dw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 			outreg(cap, GC_CAP_CMSS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 				pack(l1_cfg->sw >> 1, l1_cfg->sh));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 			outreg(cap, GC_CAP_CMDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 				pack(l1_cfg->dw >> 1, l1_cfg->dh));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 			l1em = inreg(disp, GC_L1EM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 			l1em |= GC_L1EM_DM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		if (l1_cfg->mirror) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 			outreg(cap, GC_CAP_CBM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 				inreg(cap, GC_CAP_CBM) | GC_CBM_HRV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 			l1em |= l1_cfg->dw * 2 - 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 			outreg(cap, GC_CAP_CBM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 				inreg(cap, GC_CAP_CBM) & ~GC_CBM_HRV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 			l1em &= 0xffff0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 		outreg(disp, GC_L1EM, l1em);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	case MB862XX_L1_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 		enable = (int *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 		if (*enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 			outreg(disp, GC_L1DA, par->cap_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 			outreg(cap, GC_CAP_IMG_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 				pack(l1_cfg->sy >> 1, l1_cfg->sx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 			outreg(cap, GC_CAP_IMG_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 				pack(l1_cfg->sh, l1_cfg->sw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 			outreg(disp, GC_L1M, GC_L1M_16 | GC_L1M_YC | GC_L1M_CS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 					     (par->l1_stride << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 			outreg(disp, GC_L1WY_L1WX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 				pack(l1_cfg->dy, l1_cfg->dx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 			outreg(disp, GC_L1WH_L1WW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 				pack(l1_cfg->dh - 1, l1_cfg->dw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 			outreg(disp, GC_DLS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 			outreg(cap, GC_CAP_VCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 				GC_VCM_VIE | GC_VCM_CM | GC_VCM_VS_PAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 			outreg(disp, GC_DCM1, inreg(disp, GC_DCM1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 					      GC_DCM1_DEN | GC_DCM1_L1E);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 			outreg(cap, GC_CAP_VCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 				inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 			outreg(disp, GC_DCM1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 				inreg(disp, GC_DCM1) & ~GC_DCM1_L1E);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	case MB862XX_L1_CAP_CTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 		enable = (int *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 		if (*enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 			outreg(cap, GC_CAP_VCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 				inreg(cap, GC_CAP_VCM) | GC_VCM_VIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 			outreg(cap, GC_CAP_VCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 				inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) /* framebuffer ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) static struct fb_ops mb862xxfb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	.owner		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	.fb_check_var	= mb862xxfb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	.fb_set_par	= mb862xxfb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	.fb_setcolreg	= mb862xxfb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	.fb_blank	= mb862xxfb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	.fb_pan_display	= mb862xxfb_pan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	.fb_fillrect	= cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	.fb_copyarea	= cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	.fb_imageblit	= cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	.fb_ioctl	= mb862xxfb_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) /* initialize fb_info data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) static int mb862xxfb_init_fbinfo(struct fb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	struct mb862xxfb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	struct mb862xx_gc_mode *mode = par->gc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	unsigned long reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	int stride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	fbi->fbops = &mb862xxfb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	fbi->pseudo_palette = par->pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	fbi->screen_base = par->fb_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	fbi->screen_size = par->mapped_vram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	strcpy(fbi->fix.id, DRV_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	fbi->fix.smem_start = (unsigned long)par->fb_base_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	fbi->fix.mmio_len = par->mmio_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	fbi->fix.accel = FB_ACCEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	fbi->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	fbi->fix.type_aux = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	fbi->fix.xpanstep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	fbi->fix.ypanstep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	fbi->fix.ywrapstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 		/* get the disp mode from active display cfg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		unsigned long sc = ((reg & GC_DCM01_SC) >> 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		unsigned long hsp, vsp, ht, vt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		dev_dbg(par->dev, "using bootloader's disp. mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 		fbi->var.pixclock = (sc * 1000000) / par->refclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		fbi->var.xres = (inreg(disp, GC_HDB_HDP) & 0x0fff) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		reg = inreg(disp, GC_VDP_VSP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		fbi->var.yres = ((reg >> 16) & 0x0fff) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 		vsp = (reg & 0x0fff) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		fbi->var.xres_virtual = fbi->var.xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		fbi->var.yres_virtual = fbi->var.yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		reg = inreg(disp, GC_L0EM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		if (reg & GC_L0EM_L0EC_24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 			fbi->var.bits_per_pixel = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 			reg = inreg(disp, GC_L0M);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 			if (reg & GC_L0M_L0C_16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 				fbi->var.bits_per_pixel = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 				fbi->var.bits_per_pixel = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		reg = inreg(disp, GC_VSW_HSW_HSP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		fbi->var.hsync_len = ((reg & 0xff0000) >> 16) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		fbi->var.vsync_len = ((reg & 0x3f000000) >> 24) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 		hsp = (reg & 0xffff) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		ht = ((inreg(disp, GC_HTP) & 0xfff0000) >> 16) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		fbi->var.right_margin = hsp - fbi->var.xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		fbi->var.left_margin = ht - hsp - fbi->var.hsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		vt = ((inreg(disp, GC_VTR) & 0xfff0000) >> 16) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 		fbi->var.lower_margin = vsp - fbi->var.yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		fbi->var.upper_margin = vt - vsp - fbi->var.vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	} else if (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		dev_dbg(par->dev, "using supplied mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		fb_videomode_to_var(&fbi->var, (struct fb_videomode *)mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		fbi->var.bits_per_pixel = mode->def_bpp ? mode->def_bpp : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 		ret = fb_find_mode(&fbi->var, fbi, "640x480-16@60",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 				   NULL, 0, NULL, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 		if (ret == 0 || ret == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 			dev_err(par->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 				"failed to get initial mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	fbi->var.xoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	fbi->var.yoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	fbi->var.grayscale = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	fbi->var.nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	fbi->var.height = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	fbi->var.width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	fbi->var.accel_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	fbi->var.vmode = FB_VMODE_NONINTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	fbi->var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	fbi->flags = FBINFO_DEFAULT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 		     FBINFO_FOREIGN_ENDIAN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 		     FBINFO_HWACCEL_XPAN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		     FBINFO_HWACCEL_YPAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	/* check and possibly fix bpp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	if ((fbi->fbops->fb_check_var)(&fbi->var, fbi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 		dev_err(par->dev, "check_var() failed on initial setup?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	fbi->fix.visual = fbi->var.bits_per_pixel == 8 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 			 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	fbi->fix.line_length = (fbi->var.xres_virtual *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 				fbi->var.bits_per_pixel) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	fbi->fix.smem_len = fbi->fix.line_length * fbi->var.yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	 * reserve space for capture buffers and two cursors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	 * at the end of vram: 720x576 * 2 * 2.2 + 64x64 * 16.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	par->cap_buf = par->mapped_vram - 0x1bd800 - 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	par->cap_len = 0x1bd800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	par->l1_cfg.sx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	par->l1_cfg.sy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	par->l1_cfg.sw = 720;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	par->l1_cfg.sh = 576;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	par->l1_cfg.dx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	par->l1_cfg.dy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	par->l1_cfg.dw = 720;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	par->l1_cfg.dh = 576;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	stride = par->l1_cfg.sw * (fbi->var.bits_per_pixel / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	par->l1_stride = stride / 64 + ((stride % 64) ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	outreg(cap, GC_CAP_CBM, GC_CBM_OO | GC_CBM_CBST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 				(par->l1_stride << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	outreg(cap, GC_CAP_CBOA, par->cap_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	outreg(cap, GC_CAP_CBLA, par->cap_buf + par->cap_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543)  * show some display controller and cursor registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) static ssize_t mb862xxfb_show_dispregs(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 				       struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	struct fb_info *fbi = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	struct mb862xxfb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	char *ptr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	for (reg = GC_DCM0; reg <= GC_L0DY_L0DX; reg += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 		ptr += sprintf(ptr, "%08x = %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 			       reg, inreg(disp, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	for (reg = GC_CPM_CUTC; reg <= GC_CUY1_CUX1; reg += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 		ptr += sprintf(ptr, "%08x = %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 			       reg, inreg(disp, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	for (reg = GC_DCM1; reg <= GC_L0WH_L0WW; reg += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 		ptr += sprintf(ptr, "%08x = %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 			       reg, inreg(disp, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	for (reg = 0x400; reg <= 0x410; reg += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		ptr += sprintf(ptr, "geo %08x = %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 			       reg, inreg(geo, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	for (reg = 0x400; reg <= 0x410; reg += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		ptr += sprintf(ptr, "draw %08x = %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 			       reg, inreg(draw, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	for (reg = 0x440; reg <= 0x450; reg += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 		ptr += sprintf(ptr, "draw %08x = %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 			       reg, inreg(draw, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	return ptr - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) static irqreturn_t mb862xx_intr(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	unsigned long reg_ist, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	if (!par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	if (par->type == BT_CARMINE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		/* Get Interrupt Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		reg_ist = inreg(ctrl, GC_CTRL_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		mask = inreg(ctrl, GC_CTRL_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		if (reg_ist == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 			return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		reg_ist &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		if (reg_ist == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 			return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 		/* Clear interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		outreg(ctrl, 0x0, reg_ist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		/* Get status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		reg_ist = inreg(host, GC_IST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		mask = inreg(host, GC_IMASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		reg_ist &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		if (reg_ist == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 			return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		/* Clear status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		outreg(host, GC_IST, ~reg_ist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) #if defined(CONFIG_FB_MB862XX_LIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620)  * GDC (Lime, Coral(B/Q), Mint, ...) on host bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) static int mb862xx_gdc_init(struct mb862xxfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	unsigned long ccf, mmr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	unsigned long ver, rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	if (!par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) #if defined(CONFIG_FB_PRE_INIT_FB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	par->pre_init = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	par->host = par->mmio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	par->i2c = par->mmio_base + MB862XX_I2C_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	par->disp = par->mmio_base + MB862XX_DISP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	par->cap = par->mmio_base + MB862XX_CAP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	par->draw = par->mmio_base + MB862XX_DRAW_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	par->geo = par->mmio_base + MB862XX_GEO_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	par->pio = par->mmio_base + MB862XX_PIO_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	par->refclk = GC_DISP_REFCLK_400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	ver = inreg(host, GC_CID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	rev = inreg(pio, GC_REVISION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	if ((ver == 0x303) && (rev & 0xffffff00) == 0x20050100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 		dev_info(par->dev, "Fujitsu Lime v1.%d found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 			 (int)rev & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 		par->type = BT_LIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 		ccf = par->gc_mode ? par->gc_mode->ccf : GC_CCF_COT_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 		mmr = par->gc_mode ? par->gc_mode->mmr : 0x414fb7f2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		dev_info(par->dev, "? GDC, CID/Rev.: 0x%lx/0x%lx \n", ver, rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	if (!par->pre_init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		outreg(host, GC_CCF, ccf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 		outreg(host, GC_MMR, mmr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	/* interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	outreg(host, GC_IST, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	outreg(host, GC_IMASK, GC_INT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) static int of_platform_mb862xx_probe(struct platform_device *ofdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	struct device_node *np = ofdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	struct device *dev = &ofdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	struct mb862xxfb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 	resource_size_t res_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	unsigned long ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	if (of_address_to_resource(np, 0, &res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 		dev_err(dev, "Invalid address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	par->info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	par->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	par->irq = irq_of_parse_and_map(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	if (par->irq == NO_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		dev_err(dev, "failed to map irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		goto fbrel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	res_size = resource_size(&res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	par->res = request_mem_region(res.start, res_size, DRV_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	if (par->res == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		dev_err(dev, "Cannot claim framebuffer/mmio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		ret = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		goto irqdisp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) #if defined(CONFIG_SOCRATES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	par->gc_mode = &socrates_gc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	par->fb_base_phys = res.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	par->mmio_base_phys = res.start + MB862XX_MMIO_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	par->mmio_len = MB862XX_MMIO_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	if (par->gc_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 		par->mapped_vram = par->gc_mode->max_vram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 		par->mapped_vram = MB862XX_MEM_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	if (par->fb_base == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 		dev_err(dev, "Cannot map framebuffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		goto rel_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	if (par->mmio_base == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		dev_err(dev, "Cannot map registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 		goto fb_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 		(u64)par->fb_base_phys, (ulong)par->mapped_vram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	dev_dbg(dev, "mmio phys 0x%llx 0x%lx, (irq = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		(u64)par->mmio_base_phys, (ulong)par->mmio_len, par->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	if (mb862xx_gdc_init(par))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		goto io_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	if (request_irq(par->irq, mb862xx_intr, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 			DRV_NAME, (void *)par)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		dev_err(dev, "Cannot request irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 		goto io_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	mb862xxfb_init_fbinfo(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		dev_err(dev, "Could not allocate cmap for fb_info.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		goto free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	if ((info->fbops->fb_set_par)(info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 		dev_err(dev, "set_var() failed on initial setup?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	if (register_framebuffer(info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		dev_err(dev, "failed to register framebuffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 		goto rel_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	dev_set_drvdata(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	if (device_create_file(dev, &dev_attr_dispregs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 		dev_err(dev, "Can't create sysfs regdump file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) rel_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	outreg(host, GC_IMASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	free_irq(par->irq, (void *)par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) io_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	iounmap(par->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) fb_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	iounmap(par->fb_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) rel_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	release_mem_region(res.start, res_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) irqdisp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	irq_dispose_mapping(par->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) fbrel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) static int of_platform_mb862xx_remove(struct platform_device *ofdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	struct mb862xxfb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	resource_size_t res_size = resource_size(par->res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	unsigned long reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	/* display off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	outreg(disp, GC_DCM1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	/* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	outreg(host, GC_IMASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	free_irq(par->irq, (void *)par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	irq_dispose_mapping(par->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	device_remove_file(&ofdev->dev, &dev_attr_dispregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	unregister_framebuffer(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	fb_dealloc_cmap(&fbi->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	iounmap(par->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	iounmap(par->fb_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	release_mem_region(par->res->start, res_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	framebuffer_release(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818)  * common types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) static struct of_device_id of_platform_mb862xx_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	{ .compatible = "fujitsu,MB86276", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	{ .compatible = "fujitsu,lime", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	{ .compatible = "fujitsu,MB86277", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	{ .compatible = "fujitsu,mint", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	{ .compatible = "fujitsu,MB86293", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	{ .compatible = "fujitsu,MB86294", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	{ .compatible = "fujitsu,coral", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	{ /* end */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) MODULE_DEVICE_TABLE(of, of_platform_mb862xx_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) static struct platform_driver of_platform_mb862xxfb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 		.name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 		.of_match_table = of_platform_mb862xx_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	.probe		= of_platform_mb862xx_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	.remove		= of_platform_mb862xx_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) #if defined(CONFIG_FB_MB862XX_PCI_GDC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) static int coralp_init(struct mb862xxfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	int cn, ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	par->host = par->mmio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	par->i2c = par->mmio_base + MB862XX_I2C_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	par->disp = par->mmio_base + MB862XX_DISP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	par->cap = par->mmio_base + MB862XX_CAP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	par->draw = par->mmio_base + MB862XX_DRAW_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	par->geo = par->mmio_base + MB862XX_GEO_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	par->pio = par->mmio_base + MB862XX_PIO_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	par->refclk = GC_DISP_REFCLK_400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	if (par->mapped_vram >= 0x2000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		/* relocate gdc registers space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		writel(1, par->fb_base + MB862XX_MMIO_BASE + GC_RSW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 		udelay(1); /* wait at least 20 bus cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	ver = inreg(host, GC_CID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	cn = (ver & GC_CID_CNAME_MSK) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	ver = ver & GC_CID_VERSION_MSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	if (cn == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		unsigned long reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 		dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 			 (ver == 6) ? "P" : (ver == 8) ? "PA" : "?",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 			 par->pdev->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 			par->pre_init = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		if (!par->pre_init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 			outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 			udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 			outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 			udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 		/* Clear interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		outreg(host, GC_IST, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	mb862xx_i2c_init(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) static int init_dram_ctrl(struct mb862xxfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	unsigned long i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	 * Set io mode first! Spec. says IC may be destroyed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	 * if not set to SSTL2/LVCMOS before init.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	outreg(dram_ctrl, GC_DCTL_IOCONT1_IOCONT0, GC_EVB_DCTL_IOCONT1_IOCONT0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	/* DRAM init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	outreg(dram_ctrl, GC_DCTL_SETTIME1_EMODE, GC_EVB_DCTL_SETTIME1_EMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	outreg(dram_ctrl, GC_DCTL_REFRESH_SETTIME2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	       GC_EVB_DCTL_REFRESH_SETTIME2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	outreg(dram_ctrl, GC_DCTL_RSV2_RSV1, GC_EVB_DCTL_RSV2_RSV1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	outreg(dram_ctrl, GC_DCTL_DDRIF2_DDRIF1, GC_EVB_DCTL_DDRIF2_DDRIF1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	/* DLL reset done? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	while ((inreg(dram_ctrl, GC_DCTL_RSV0_STATES) & GC_DCTL_STATES_MSK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 		udelay(GC_DCTL_INIT_WAIT_INTERVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		if (i++ > GC_DCTL_INIT_WAIT_CNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 			dev_err(par->dev, "VRAM init failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD_AFT_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES_AFT_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) static int carmine_init(struct mb862xxfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	unsigned long reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	par->ctrl = par->mmio_base + MB86297_CTRL_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	par->i2c = par->mmio_base + MB86297_I2C_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	par->disp = par->mmio_base + MB86297_DISP0_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	par->disp1 = par->mmio_base + MB86297_DISP1_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	par->cap = par->mmio_base + MB86297_CAP0_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	par->cap1 = par->mmio_base + MB86297_CAP1_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	par->draw = par->mmio_base + MB86297_DRAW_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	par->dram_ctrl = par->mmio_base + MB86297_DRAMCTRL_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	par->wrback = par->mmio_base + MB86297_WRBACK_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	par->refclk = GC_DISP_REFCLK_533;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	/* warm up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	reg = GC_CTRL_CLK_EN_DRAM | GC_CTRL_CLK_EN_2D3D | GC_CTRL_CLK_EN_DISP0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	outreg(ctrl, GC_CTRL_CLK_ENABLE, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	/* check for engine module revision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	if (inreg(draw, GC_2D3D_REV) == GC_RE_REVISION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		dev_info(par->dev, "Fujitsu Carmine GDC Rev.%d found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 			 par->pdev->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		goto err_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	reg &= ~GC_CTRL_CLK_EN_2D3D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	outreg(ctrl, GC_CTRL_CLK_ENABLE, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	/* set up vram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	if (init_dram_ctrl(par) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		goto err_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	outreg(ctrl, GC_CTRL_INT_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) err_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	outreg(ctrl, GC_CTRL_CLK_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	switch (par->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	case BT_CORALP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		return coralp_init(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	case BT_CARMINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		return carmine_init(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) #define CHIP_ID(id)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	{ PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) static const struct pci_device_id mb862xx_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	/* MB86295/MB86296 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	/* MB86297 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CARMINE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	{ 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) static int mb862xx_pci_probe(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 			     const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	struct mb862xxfb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	ret = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 		dev_err(dev, "Cannot enable PCI device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	if (!info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 		goto dis_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	}
^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) 	par->info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	par->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	par->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	par->irq = pdev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	ret = pci_request_regions(pdev, DRV_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		dev_err(dev, "Cannot reserve region(s) for PCI device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		goto rel_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	switch (pdev->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	case PCI_DEVICE_ID_FUJITSU_CORALP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	case PCI_DEVICE_ID_FUJITSU_CORALPA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 		par->fb_base_phys = pci_resource_start(par->pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		par->mapped_vram = CORALP_MEM_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		if (par->mapped_vram >= 0x2000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 			par->mmio_base_phys = par->fb_base_phys +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 					      MB862XX_MMIO_HIGH_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 			par->mmio_base_phys = par->fb_base_phys +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 					      MB862XX_MMIO_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		par->mmio_len = MB862XX_MMIO_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		par->type = BT_CORALP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	case PCI_DEVICE_ID_FUJITSU_CARMINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		par->fb_base_phys = pci_resource_start(par->pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 		par->mmio_base_phys = pci_resource_start(par->pdev, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 		par->mmio_len = pci_resource_len(par->pdev, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		par->mapped_vram = CARMINE_MEM_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 		par->type = BT_CARMINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 		/* should never occur */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 		goto rel_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	if (par->fb_base == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		dev_err(dev, "Cannot map framebuffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		goto rel_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	if (par->mmio_base == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 		dev_err(dev, "Cannot map registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 		goto fb_unmap;
^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) 	dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 		(unsigned long long)par->fb_base_phys, (ulong)par->mapped_vram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 		(unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	ret = mb862xx_pci_gdc_init(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 		goto io_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	ret = request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 			  DRV_NAME, (void *)par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		dev_err(dev, "Cannot request irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 		goto io_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	mb862xxfb_init_fbinfo(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		dev_err(dev, "Could not allocate cmap for fb_info.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 		goto free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	if ((info->fbops->fb_set_par)(info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		dev_err(dev, "set_var() failed on initial setup?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	ret = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 		dev_err(dev, "failed to register framebuffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 		goto rel_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	pci_set_drvdata(pdev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	if (device_create_file(dev, &dev_attr_dispregs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		dev_err(dev, "Can't create sysfs regdump file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	if (par->type == BT_CARMINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		outreg(ctrl, GC_CTRL_INT_MASK, GC_CARMINE_INT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		outreg(host, GC_IMASK, GC_INT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) rel_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	free_irq(par->irq, (void *)par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) io_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	iounmap(par->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) fb_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	iounmap(par->fb_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) rel_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	pci_release_regions(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) rel_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) dis_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) static void mb862xx_pci_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 	struct fb_info *fbi = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	struct mb862xxfb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	unsigned long reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	/* display off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	reg = inreg(disp, GC_DCM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	outreg(disp, GC_DCM1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	if (par->type == BT_CARMINE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 		outreg(ctrl, GC_CTRL_INT_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		outreg(ctrl, GC_CTRL_CLK_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 		outreg(host, GC_IMASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	mb862xx_i2c_exit(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	device_remove_file(&pdev->dev, &dev_attr_dispregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	unregister_framebuffer(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	fb_dealloc_cmap(&fbi->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	free_irq(par->irq, (void *)par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	iounmap(par->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	iounmap(par->fb_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	pci_release_regions(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	framebuffer_release(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) static struct pci_driver mb862xxfb_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	.name		= DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	.id_table	= mb862xx_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	.probe		= mb862xx_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 	.remove		= mb862xx_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) static int mb862xxfb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	int ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) #if defined(CONFIG_FB_MB862XX_LIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	ret = platform_driver_register(&of_platform_mb862xxfb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) #if defined(CONFIG_FB_MB862XX_PCI_GDC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	ret = pci_register_driver(&mb862xxfb_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static void __exit mb862xxfb_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) #if defined(CONFIG_FB_MB862XX_LIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	platform_driver_unregister(&of_platform_mb862xxfb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) #if defined(CONFIG_FB_MB862XX_PCI_GDC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	pci_unregister_driver(&mb862xxfb_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) module_init(mb862xxfb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) module_exit(mb862xxfb_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) MODULE_DESCRIPTION("Fujitsu MB862xx Framebuffer driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) MODULE_LICENSE("GPL v2");