|  | @@ -81,3 +81,124 @@ static struct pxafb_mode_info am200_fb_mode_6inch = {
 | 
	
		
			
				|  |  |  	.vsync_len	= 25,
 | 
	
		
			
				|  |  |  	.upper_margin	= 0,
 | 
	
		
			
				|  |  |  	.lower_margin	= 2,
 | 
	
		
			
				|  |  | +	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static struct pxafb_mach_info am200_fb_info = {
 | 
	
		
			
				|  |  | +	.modes		= &am200_fb_mode_6inch,
 | 
	
		
			
				|  |  | +	.num_modes	= 1,
 | 
	
		
			
				|  |  | +	.lcd_conn	= LCD_TYPE_COLOR_TFT | LCD_PCLK_EDGE_FALL |
 | 
	
		
			
				|  |  | +			  LCD_AC_BIAS_FREQ(24),
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* register offsets for gpio control */
 | 
	
		
			
				|  |  | +#define LED_GPIO_PIN 51
 | 
	
		
			
				|  |  | +#define STDBY_GPIO_PIN 48
 | 
	
		
			
				|  |  | +#define RST_GPIO_PIN 49
 | 
	
		
			
				|  |  | +#define RDY_GPIO_PIN 32
 | 
	
		
			
				|  |  | +#define ERR_GPIO_PIN 17
 | 
	
		
			
				|  |  | +#define PCBPWR_GPIO_PIN 16
 | 
	
		
			
				|  |  | +static int gpios[] = { LED_GPIO_PIN , STDBY_GPIO_PIN , RST_GPIO_PIN,
 | 
	
		
			
				|  |  | +			RDY_GPIO_PIN, ERR_GPIO_PIN, PCBPWR_GPIO_PIN };
 | 
	
		
			
				|  |  | +static char *gpio_names[] = { "LED" , "STDBY" , "RST", "RDY", "ERR", "PCBPWR" };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int am200_init_gpio_regs(struct metronomefb_par *par)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int i;
 | 
	
		
			
				|  |  | +	int err;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (i = 0; i < ARRAY_SIZE(gpios); i++) {
 | 
	
		
			
				|  |  | +		err = gpio_request(gpios[i], gpio_names[i]);
 | 
	
		
			
				|  |  | +		if (err) {
 | 
	
		
			
				|  |  | +			dev_err(&am200_device->dev, "failed requesting "
 | 
	
		
			
				|  |  | +				"gpio %s, err=%d\n", gpio_names[i], err);
 | 
	
		
			
				|  |  | +			goto err_req_gpio;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	gpio_direction_output(LED_GPIO_PIN, 0);
 | 
	
		
			
				|  |  | +	gpio_direction_output(STDBY_GPIO_PIN, 0);
 | 
	
		
			
				|  |  | +	gpio_direction_output(RST_GPIO_PIN, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	gpio_direction_input(RDY_GPIO_PIN);
 | 
	
		
			
				|  |  | +	gpio_direction_input(ERR_GPIO_PIN);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	gpio_direction_output(PCBPWR_GPIO_PIN, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +err_req_gpio:
 | 
	
		
			
				|  |  | +	while (--i >= 0)
 | 
	
		
			
				|  |  | +		gpio_free(gpios[i]);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return err;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void am200_cleanup(struct metronomefb_par *par)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int i;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (i = 0; i < ARRAY_SIZE(gpios); i++)
 | 
	
		
			
				|  |  | +		gpio_free(gpios[i]);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int am200_share_video_mem(struct fb_info *info)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	/* rough check if this is our desired fb and not something else */
 | 
	
		
			
				|  |  | +	if ((info->var.xres != am200_fb_info.modes->xres)
 | 
	
		
			
				|  |  | +		|| (info->var.yres != am200_fb_info.modes->yres))
 | 
	
		
			
				|  |  | +		return 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* we've now been notified that we have our new fb */
 | 
	
		
			
				|  |  | +	am200_board.metromem = info->screen_base;
 | 
	
		
			
				|  |  | +	am200_board.host_fbinfo = info;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* try to refcount host drv since we are the consumer after this */
 | 
	
		
			
				|  |  | +	if (!try_module_get(info->fbops->owner))
 | 
	
		
			
				|  |  | +		return -ENODEV;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int am200_unshare_video_mem(struct fb_info *info)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	dev_dbg(&am200_device->dev, "ENTER %s\n", __func__);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (info != am200_board.host_fbinfo)
 | 
	
		
			
				|  |  | +		return 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	module_put(am200_board.host_fbinfo->fbops->owner);
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int am200_fb_notifier_callback(struct notifier_block *self,
 | 
	
		
			
				|  |  | +				 unsigned long event, void *data)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct fb_event *evdata = data;
 | 
	
		
			
				|  |  | +	struct fb_info *info = evdata->info;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	dev_dbg(&am200_device->dev, "ENTER %s\n", __func__);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (event == FB_EVENT_FB_REGISTERED)
 | 
	
		
			
				|  |  | +		return am200_share_video_mem(info);
 | 
	
		
			
				|  |  | +	else if (event == FB_EVENT_FB_UNREGISTERED)
 | 
	
		
			
				|  |  | +		return am200_unshare_video_mem(info);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static struct notifier_block am200_fb_notif = {
 | 
	
		
			
				|  |  | +	.notifier_call = am200_fb_notifier_callback,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* this gets called as part of our init. these steps must be done now so
 | 
	
		
			
				|  |  | + * that we can use pxa_set_fb_info */
 | 
	
		
			
				|  |  | +static void __init am200_presetup_fb(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int fw;
 | 
	
		
			
				|  |  | +	int fh;
 | 
	
		
			
				|  |  | +	int padding_size;
 | 
	
		
			
				|  |  | +	int totalsize;
 | 
	
		
			
				|  |  | +
 |