All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <502DEDCD.9050303@gmail.com>

diff --git a/a/1.txt b/N1/1.txt
index dd6d0e4..4489532 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -12,7 +12,14 @@ I have written a driver for kernel 2.6.22 but SLCDC and DD12832 are in
 the same driver.
 
 Thank you for your help.
-Gaëtan Carlier
+Ga?tan Carlier
 
 ps : I attach my previous driver for a better overview (this is a 
 working draft for test purpose)
+-------------- next part --------------
+A non-text attachment was scrubbed...
+Name: mx2fb-slcd_dd12832_oled.c
+Type: text/x-csrc
+Size: 35409 bytes
+Desc: not available
+URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120817/ea3df386/attachment-0001.bin>
diff --git a/a/2.hdr b/a/2.hdr
deleted file mode 100644
index b1ac541..0000000
--- a/a/2.hdr
+++ /dev/null
@@ -1,5 +0,0 @@
-Content-Type: text/x-csrc;
- name="mx2fb-slcd_dd12832_oled.c"
-Content-Transfer-Encoding: base64
-Content-Disposition: attachment;
- filename="mx2fb-slcd_dd12832_oled.c"
diff --git a/a/2.txt b/a/2.txt
deleted file mode 100644
index d6f04d1..0000000
--- a/a/2.txt
+++ /dev/null
@@ -1,1319 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/*!
- * @defgroup Framebuffer_MX27 Framebuffer Driver for MX27.
- */
-
-/*!
- * @file mx2fb.c
- *
- * @brief Frame buffer driver for MX27 ADS.
- *
- * @ingroup Framebuffer_MX27
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include <asm/arch/mxcfb.h>
-#include <asm/arch/mx2fb_slcdc.h>
-
-#include <asm/arch/pmic_power.h>
-#include "dd12832_oled.h"
-
-#ifdef CONFIG_PM
-static int mx2fb_suspend(struct platform_device *pdev, pm_message_t state);
-static int mx2fb_resume(struct platform_device *pdev);
-#else
-#define mx2fb_suspend		0
-#define mx2fb_resume		0
-#endif
-
-#define MX2FB_TYPE_BG          0
-#define MX2FB_TYPE_GW          1
-
-#define floor8(a) (a&(~0x07))
-//#define iceil8(a) (((int)((a+7)/8))*8)
-#define iceil8(a) ((int)((a & ~((int)0x03)) + 8))
-
-
-
-extern void gpio_slcdc_active(void);
-extern void gpio_slcdc_inactive(void);
-
-static char *fb_mode;
-static int fb_enabled;
-static unsigned long default_bpp = 1;
-static unsigned char brightness = 255;
-static ATOMIC_NOTIFIER_HEAD(mx2fb_notifier_list);
-static struct clk *slcdc_clk;
-/*!
- * @brief Structure containing the MX2 specific framebuffer parameters.
- */
-struct mx2fb_par {
-	int type;
-	char *id;
-	int registered;
-	int blank;
-	/* Tell if driver compiled with rotate option enabled */
-	int rotate;
-	/* Contains displayed data in 1 byte / column (8 pixels)
-	 * fb data are stored as 1 byte / pixel
-	 * !! must be allocated with 128k alignment using dma_pool_create
-	 */
-	/* FrameBuffer memory map */
-	unsigned char* fb_vmem;
-	size_t fb_len;
-	dma_addr_t fb_pmem;
-	/* Oled cgram memory map */
-	unsigned long cgram_cmd_vaddr;
-	unsigned long cgram_cmd_paddr;
-	unsigned long cgram_cmd_len;
-	struct dma_pool *cgram_cmd_dma_pool;
-	unsigned long cgram_data_vaddr;
-	unsigned long cgram_data_paddr;
-	unsigned long cgram_data_len;
-	struct dma_pool *cgram_data_dma_pool;
-};
-
-/* Framebuffer APIs */
-/*static int mx2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
-static int mx2fb_set_par(struct fb_info *info);
-static void _set_fix(struct fb_info *info);*/
-
-/* Internal functions */
-static int __init _init_fbinfo(struct fb_info *info,
-			       struct platform_device *pdev);
-static int __init _install_fb(struct fb_info *info,
-			      struct platform_device *pdev);
-static void __exit _uninstall_fb(struct fb_info *info);
-static int _map_video_memory(struct fb_info *info);
-static void _unmap_video_memory(struct fb_info *info);
-/*static void _enable_lcdc(struct fb_info *info);
-static void _disable_lcdc(struct fb_info *info);
-static void _update_slcdc(struct fb_info *info);*/
-
-/* Oled display information */
-struct fb_videomode mxcfb_modedb[] = {
-	{
-		/* 128x32 */
-		"Densitron DD12832", /* name */
-		0, /* refresh */
-		128, /* xres */
-		32, /* yres */
-		0, /* pixclock */
-		0, /* left_margin */
-		0, /* right_margin */
-		0, /* upper_margin */
-		0, /* lower_margin */
-		0, /* hsync_len */
-		0, /* vsync_len */
-		0, /* sync */
-		0, /* mode */
-		0}, /* flag */
-};
-int mxcfb_modedb_sz = ARRAY_SIZE(mxcfb_modedb);
-
-struct mx2fb_par mx2fbp_bg = {
-	.type = MX2FB_TYPE_BG,
-	.id = "DISP0 BG",
-	.registered = 0,
-#ifdef CONFIG_FB_MXC_DENSITRON_DD12832_ROTATE
-	.rotate = 1,
-#else
-	.rotate = 0,
-#endif
-};
-
-/*!
- * @brief Framebuffer information structures.
- * There are up to 3 framebuffers: background, TVout, and graphic window.
- * If graphic window is configured, it must be the last framebuffer.
- */
-static struct fb_info mx2fb_info = {
-	.par = &mx2fbp_bg,
-};
-
-/*!
- * Do a minimal setup of SLCDC to be able to send command to DD12832
- */
-static void slcdc_first_init(void)
-{
-	unsigned long val;
-	int i;
-	unsigned long *pdata;
-
-	/* Screen start address register */
-	__raw_writel(mx2fbp_bg.cgram_data_paddr, SLCDC_REG(SLCDC_DATABASEADDR));
-	__raw_writel(mx2fbp_bg.cgram_data_len, SLCDC_REG(SLCDC_DATABUFSIZE));
-
-	/* Copy command array to DMA area */
-	pdata = (unsigned long *)mx2fbp_bg.cgram_cmd_vaddr;
-	for (i = 0; i < mx2fbp_bg.cgram_cmd_len; i++) {
-		if ((i & 0x01) == 0) {
-			/* If even offset, command must be left-aligned in
-			 * 32-bits memory space */
-			*pdata = (unsigned long)_ssd1305_pagecmd_array[i] << 16;
-		} else {
-			/* If odd offset, command must be right-aligned in
-			 * 32-bits memory space */
-			*pdata |= (unsigned long)_ssd1305_pagecmd_array[i];
-			/* When "right column" is filled, go to next address */
-			pdata++;
-		}
-	}
-	/* Set Array of command for page addressing */
-	__raw_writel(mx2fbp_bg.cgram_cmd_paddr, SLCDC_REG(SLCDC_COMBASEADDR));
-	__raw_writel(mx2fbp_bg.cgram_cmd_len, SLCDC_REG(SLCDC_COMBUFSIZE));
-
-	/* Set number of command (words) that must be send to jump to a
-	 * specific page. Size of "word" is define by WORDDEFCOM flag in
-	 * LCDTRANSCONFIG register */
-	__raw_writel(PAGE_COMMAND_PACK_SIZE, SLCDC_REG(SLCDC_COMSTRINGSIZ));
-
-	/* Define DMA burst */
-	__raw_writel(0, SLCDC_REG(SLCDC_FIFOCONFIG));
-
-	/* Define number of column/segment in a page */
-	__raw_writel(OLED_WIDTH, SLCDC_REG(SLCDC_LCDCONFIG));
-
-	/* Set transfer configuration */
-	val = SLCDC_DATA_8BIT | SLCDC_COMMAND_8BIT | SLCDC_PARALLEL |
-		SLCDC_WRITEDATA_8BIT | SLCDC_TRANS_LITLENDIAN_8BIT |
-		SLCDC_CSPOL_LOW;
-	__raw_writel(val, SLCDC_REG(SLCDC_LCDTRANSCONFIG));
-
-	/* Set control register */
-	val = SLCDC_MODE_COMMAND | SLCDC_IRQ_DISABLE | SLCDC_IRQ_FLAGS_MASK;
-	__raw_writel(val, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-
-	/* Set SLCDC clock divider = HCLK_SLCDC * val / 128 */
-	val = 40;
-	__raw_writel(val, SLCDC_REG(SLCDC_LCDCLOCKCONFIG));
-}
-
-
-/*
- * Send one command to oled via SLCDC
- */
-static int _slcdc_sendcmd_single(unsigned char cmd)
-{
-	while (__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT)) & SLCDC_BUSY_MASK);
-	__raw_writel((u32)cmd | WRITE_LCDCMD, SLCDC_REG(SLCDC_LCDWRITEDATA));
-	return 0;
-}
-
-/*
- * Send one data to oled via SLCDC
- */
-static int _slcdc_senddata_single(unsigned char cmd)
-{
-	while (__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT)) & SLCDC_BUSY_MASK);
-	__raw_writel((u32)cmd | WRITE_LCDDATA, SLCDC_REG(SLCDC_LCDWRITEDATA));
-	return 0;
-}
-
-/*
- * Set Start line for Pan function
- */
-static void dd12832_set_start_line(unsigned char y)
-{
-	_slcdc_sendcmd_single(SSD1305_CMD_ROWADDR | (y & 0x3F));
-}
-
-/*
- * Set page address
- */
-static void dd12832_set_yaddr(unsigned char y)
-{
-	_slcdc_sendcmd_single(SSD1305_CMD_PAGEADDR | (y & 0x07));
-}
-
-/*
- * Set segment address
- */
-static void dd12832_set_xaddr(unsigned char x)
-{
-#ifndef CONFIG_FB_MXC_DENSITRON_DD12832_ROTATE
-	_slcdc_sendcmd_single(SSD1305_CMD_HIGHCOLADDR | (x >> 4));
-	_slcdc_sendcmd_single(SSD1305_CMD_LOWCOLADDR | (x & 0x0F));
-#else
-	x += SSD1305_WIDTH - OLED_WIDTH;
-	_slcdc_sendcmd_single(SSD1305_CMD_HIGHCOLADDR | (x >> 4));
-	_slcdc_sendcmd_single(SSD1305_CMD_LOWCOLADDR | (x & 0x0F));
-#endif
-}
-
-/*
- * Modify contrast value
- */
-static void dd12832_set_brightness(unsigned char level)
-{
-	if (level == 0) {
-		/* If level 0 asked, display must be turned off
-		* because Display is still ON when Contrast
-		* is set to 0 */
-		_slcdc_sendcmd_single(SSD1305_CMD_DISPLAY_POWER_OFF);
-	} else {
-		/* Apply new contrast */
-		_slcdc_sendcmd_single(SSD1305_CMD_BRIGHTNESS_MODE);
-		_slcdc_sendcmd_single(level);
-		/* Be sure that DISPLAY is ON */
-		_slcdc_sendcmd_single(SSD1305_CMD_DISPLAY_POWER_ON);
-	}
-}
-
-/*
- * Clear internal RAM of controller
- */
-static void dd12832_clear_lcd(void)
-{
-	unsigned long status;
-	/* Clear OLED RAM mirror buffer */
-	char *pdata = (char *)mx2fbp_bg.cgram_data_vaddr;
-	memset(pdata, 0, mx2fbp_bg.cgram_data_len);
-
-	/* Clear FrameBuffer mirror buffer */
-	pdata = (char __force *) mx2fbp_bg.fb_vmem;
-	memset(pdata, 0, mx2fbp_bg.fb_len);
-
-	dd12832_set_yaddr(0);
-	dd12832_set_xaddr(0);
-	while (__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT)) & SLCDC_BUSY_MASK);
-	status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	status &= ~(SLCDC_SLCDCCTRLSTAT_AUTOMODE_MASK);
-	status |= SLCDC_MODE_DATA | SLCDC_START_TRANSFERT;
-	__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-}
-
-/*
- * Send init sequence to display controller
- */
-static int dd12832_init_controller(void)
-{
-	/* Use SLCDC to send command block */
-	unsigned long i;
-
-	for (i = 0; i < sizeof(_ssd1305_init_array); i++) {
-		_slcdc_sendcmd_single(_ssd1305_init_array[i]);
-	}
-	dd12832_clear_lcd();
-	return 0;
-}
-
-/*!
- * @brief Enable LCD controller.
- * @param info	framebuffer information pointer
- */
-static void _enable_slcdc(struct fb_info *info)
-{
-	if (!fb_enabled) {
-		fb_enabled++;
-
-		if (fb_mode) {
-			unsigned long mode = 0;
-			if (mode == 0) {
-				dd12832_set_brightness(brightness);
-			}
-		}
-	}
-}
-
-/*!
- * @brief Disable LCD controller.
- * @param info	framebuffer information pointer
- */
-static void _disable_slcdc(struct fb_info *info)
-{
-	if (fb_enabled) {
-		dd12832_set_brightness(0);
-		fb_enabled = 0;
-	}
-}
-
-/*!
- * @brief Update SLCDC registers
- * @param info	framebuffer information pointer
- */
-static void _update_slcdc(struct fb_info *info)
-{
-	unsigned long base;
-	unsigned long val;
-	struct fb_var_screeninfo *var = &info->var;
-
-	base = (var->yoffset * var->xres_virtual + var->xoffset);
-	base += (unsigned long)info->screen_base;
-
-	/* Set number of command (words) that must be send to jump to a
-	 * specific page. Size of "word" is define by WORDDEFCOM flag in
-	 * LCDTRANSCONFIG register */
-	__raw_writel(PAGE_COMMAND_PACK_SIZE, SLCDC_REG(SLCDC_COMSTRINGSIZ));
-
-	/* Define DMA burst */
-	__raw_writel(0, SLCDC_REG(SLCDC_FIFOCONFIG));
-
-	/* Define number of column/segment in a page */
-	__raw_writel(OLED_WIDTH, SLCDC_REG(SLCDC_LCDCONFIG));
-
-	/* Set transfer configuration */
-	val = SLCDC_DATA_8BIT | SLCDC_COMMAND_8BIT | SLCDC_PARALLEL |
-		SLCDC_WRITEDATA_8BIT | SLCDC_TRANS_LITLENDIAN_8BIT |
-		SLCDC_CSPOL_LOW;
-	__raw_writel(val, SLCDC_REG(SLCDC_LCDTRANSCONFIG));
-
-	/* Set SLCDC clock divider = HCLK_SLCDC * val / 128 */
-	val = 60;
-	__raw_writel(val, SLCDC_REG(SLCDC_LCDCLOCKCONFIG));
-
-	return;
-}
-
-
-/*!
- * @brief Blanks the display.
- *
- * @param blank_mode	The blank mode we want.
- * @param info		Frame buffer structure that represents a single frame buffer
- *
- * @return		Negative errno on error, or zero on success.
- *
- * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking
- * succeeded, != 0 if un-/blanking failed.
- * blank_mode == 2: suspend vsync
- * blank_mode == 3: suspend hsync
- * blank_mode == 4: powerdown
- */
-static int mx2fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-
-	dev_dbg(info->device, "blank mode = %d\n", blank_mode);
-
-	mx2fbp->blank = blank_mode;
-
-	switch (blank_mode) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		_disable_slcdc(info);
-		break;
-	case FB_BLANK_UNBLANK:
-		_enable_slcdc(info);
-		break;
-	}
-
-	return 0;
-}
-
-/*
- * here we start the process of spliting out the fb update into
- * individual blocks of pixels. we end up spliting into 64x64 blocks
- * and finally down to 64x8 pages.
- */
-static void dd12832_cgram_update(struct fb_info *info, unsigned int dx,
-					unsigned int dy, unsigned int w, unsigned int h)
-{
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-	unsigned int startpage, endpage, startseg, endseg;
-	unsigned int curpage, curseg;
-	unsigned long status;
-	int i;
-	unsigned char myseg;
-	char *cgram;
-	unsigned char *ppixel;
-
-	/* align the request first */
-	/* Get first line of the page where starting pixel is located */
-	startpage = floor8(dy) / 8;
-	/* Get first line of the next page where last pixel to update
-	 * is located */
-	endpage = h + dy - 1;
-	endpage = iceil8(endpage) / 8;
-
-	/* First segment to update */
-	startseg = dx;
-	/* Last segment to update */
-	endseg = dx + (w - 1);
-
-	for (curpage = startpage; curpage < endpage; curpage++) {
-		cgram = (char*)mx2fbp->cgram_data_vaddr;
-		cgram += curpage * info->fix.line_length;
-		cgram += startseg;
-		for (curseg = startseg; curseg <= endseg; curseg++) {
-			/* Get segment to update in video memory */
-			myseg = 0;
-			ppixel = (unsigned char __force *) mx2fbp->fb_vmem;
-			/* There is 8 lines per page */
-			ppixel += curpage * info->fix.line_length * 8;
-			/* Points to upper pixel of the current segment */
-			ppixel += curseg;
-			for (i = 0; i < 8; i++) {
-				if (*ppixel != 0) {
-					myseg |= 1 << i;
-				}
-				/* Jump to next line to get pixel below */
-				ppixel += info->fix.line_length;
-			}
-			*cgram = myseg;
-			cgram++;
-		}
-	}
-	dd12832_set_xaddr(0);
-	dd12832_set_yaddr(0);
-	while (__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT)) & SLCDC_BUSY_MASK);
-	status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	status &= ~(SLCDC_SLCDCCTRLSTAT_AUTOMODE_MASK);
-	status |= SLCDC_MODE_DATA | SLCDC_START_TRANSFERT;
-	__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-}
-
-
-
-static void mx2fb_fillrect(struct fb_info *info,
-			   const struct fb_fillrect *rect)
-{
-	sys_fillrect(info, rect);
-
-	/* update the physical lcd */
-	dd12832_cgram_update(info, rect->dx, rect->dy, rect->width, rect->height);
-}
-
-static void mx2fb_copyarea(struct fb_info *info,
-			   const struct fb_copyarea *area)
-{
-	sys_copyarea(info, area);
-
-	/* update the physical lcd */
-	dd12832_cgram_update(info, area->dx, area->dy, area->width, area->height);
-}
-
-static void mx2fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-	char *ppixel;
-	const char *pdata;
-	int j;
-
-	if (image->depth == 1) {
-		/* Draw image */
-		pdata = image->data;
-		ppixel = mx2fbp->fb_vmem;
-		ppixel += image->dy * info->fix.line_length;
-		ppixel += image->dx;
-		for (j = 0; j < image->height; j++) {
-			memcpy(ppixel, pdata, image->width);
-			pdata += image->width;
-			ppixel += info->fix.line_length;
-		}
-		/* update the physical lcd */
-		dd12832_cgram_update(info, image->dx, image->dy, image->width, image->height);
-	}
-}
-
-
-/*!
- * @brief Pans the display.
- *
- * @param var	Frame buffer variable screen structure
- * @param info	Frame buffer structure that represents a single frame buffer
- *
- * @return	Negative errno on error, or zero on success.
- *
- * Pan (or wrap, depending on the `vmode' field) the display using the
- * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values
- * don't fit, return -EINVAL.
- */
-static int mx2fb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	if (info->var.yoffset == var->yoffset) {
-		return 0;	/* No change, do nothing */
-	}
-
-        if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < OLED_WIDTH)
-                && (info->var.yres <= OLED_WIDTH)) {
-                dd12832_set_start_line(var->yoffset);
-                info->var.yoffset = var->yoffset;
-                return 0;
-        }
-
-        return -EINVAL;
-}
-
-static int mx2fb_sync(struct fb_info *info)
-{
-	dd12832_cgram_update(info, 0, 0, info->fix.line_length, info->var.yres_virtual);
-	return 0;
-}
-
-/*!
- * @brief Ioctl function to support customized ioctl operations.
- *
- * @param info	Framebuffer structure that represents a single frame buffer
- * @param cmd	The command number
- * @param arg	Argument which depends on cmd
- *
- * @return	Negative errno on error, or zero on success.
- */
-static int mx2fb_ioctl(struct fb_info *info, unsigned int cmd,
-		       unsigned long arg)
-{
-	unsigned char level;
-
-	switch (cmd) {
-	case MX2FB_SET_BRIGHTNESS:
-		if (copy_from_user((void *)&level, (void *)arg, sizeof(level)))
-			return -EFAULT;
-		brightness = level;
-		dd12832_set_brightness(level);
-		break;
-	case MX2FB_FORCE_SYNC:
-		mx2fb_sync(info);
-		break;
-	default:
-		dev_dbg(info->device, "Unknown ioctl command (0x%08X)\n", cmd);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*!
- * @brief Set fixed framebuffer parameters based on variable settings.
- *
- * @param info	framebuffer information pointer
- * @return	Negative errno on error, or zero on success.
- */
-static void _set_fix(struct fb_info *info)
-{
-	struct fb_fix_screeninfo *fix = &info->fix;
-	struct fb_var_screeninfo *var = &info->var;
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-
-	strncpy(fix->id, mx2fbp->id, strlen(mx2fbp->id));
-	if (var->bits_per_pixel < 8)
-		fix->line_length = var->xres_virtual;
-	else
-		fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->accel = FB_ACCEL_NONE;
-	fix->visual = FB_VISUAL_MONO10;
-	fix->xpanstep = 0;
-	fix->ypanstep = 1;
-	fix->ywrapstep = 0;
-}
-
-/*!
- * @brief Validates a var passed in.
- *
- * @param var	Frame buffer variable screen structure
- * @param info	Frame buffer structure that represents a single frame buffer
- *
- * @return	Negative errno on error, or zero on success.
- *
- * Checks to see if the hardware supports the state requested by var passed
- * in. This function does not alter the hardware state! If the var passed in
- * is slightly off by what the hardware can support then we alter the var
- * PASSED in to what we can do. If the hardware doesn't support mode change
- * a -EINVAL will be returned by the upper layers.
- *
- */
-static int mx2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	if (var->xoffset < 0)
-		var->xoffset = 0;
-
-	if (var->yoffset < 0)
-		var->yoffset = 0;
-
-	if (var->xoffset + info->var.xres > info->var.xres_virtual)
-		var->xoffset = info->var.xres_virtual - info->var.xres;
-
-	if (var->yoffset + info->var.yres > info->var.yres_virtual)
-		var->yoffset = info->var.yres_virtual - info->var.yres;
-
-	if (var->bits_per_pixel != default_bpp)
-		var->bits_per_pixel = default_bpp;
-
-	if (var->pixclock != 0)
-		var->pixclock = 0;
-	var->red.length = var->green.length = var->blue.length = 1;
-	var->red.offset = var->green.offset = var->blue.offset = 0;
-	var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
-
-	var->transp.length = 0;
-	var->transp.offset = 0;
-	var->transp.msb_right = 0;
-
-	var->height = -1;
-	var->width = -1;
-	var->grayscale = 0;
-
-	/* Copy nonstd field to/from sync for fbset usage */
-	var->sync |= var->nonstd;
-	var->nonstd |= var->sync;
-
-	return 0;
-}
-
-/*!
- * @brief Alters the hardware state.
- *
- * @param info	Frame buffer structure that represents a single frame buffer
- *
- * @return Zero on success others on failure
- *
- * Using the fb_var_screeninfo in fb_info we set the resolution of this
- * particular framebuffer. This function alters the fb_fix_screeninfo stored
- * in fb_info. It doesn't not alter var in fb_info since we are using that
- * data. This means we depend on the data in var inside fb_info to be
- * supported by the hardware. mx2fb_check_var is always called before
- * mx2fb_set_par to ensure this.
- */
-static int mx2fb_set_par(struct fb_info *info)
-{
-	unsigned long len;
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-
-	_set_fix(info);
-
-	len = info->var.yres_virtual * info->fix.line_length;
-	if (len > info->fix.smem_len) {
-		if (info->fix.smem_start)
-			_unmap_video_memory(info);
-
-		/* Memory allocation for framebuffer */
-		if (_map_video_memory(info)) {
-			dev_err(info->device, "Unable to allocate fb memory\n");
-			return -ENOMEM;
-		}
-	}
-
-	_update_slcdc(info);
-
-	mx2fb_blank(mx2fbp->blank, info);
-
-	return 0;
-}
-
-/*
- * this is the access path from userspace. they can seek and write to
- * the fb. it's inefficient for them to do anything less than 64*8
- * writes since we update the lcd in each write() anyway.
- */
-static ssize_t mx2fb_write(struct fb_info *info, const char __user *buf,
-			   size_t count, loff_t *ppos)
-{
-	/* modded from epson 1355 */
-
-	unsigned long p;
-	int err=-EINVAL;
-	unsigned int fbmemlength, x, y, w, h, startpage, endpage;
-	struct arcfb_par *par;
-	unsigned int xres;
-
-	p = *ppos;
-	par = info->par;
-	xres = info->var.xres;
-	fbmemlength = info->fix.smem_len;
-
-	if (p > fbmemlength)
-		return -ENOSPC;
-
-	err = 0;
-	if ((count + p) > fbmemlength) {
-		count = fbmemlength - p;
-		err = -ENOSPC;
-	}
-
-	if (count) {
-		char *base_addr;
-
-		base_addr = (char __force *)info->screen_base;
-		count -= copy_from_user(base_addr + p, buf, count);
-		*ppos += count;
-		err = -EFAULT;
-	}
-
-	/* Check how many page are affected */
-	startpage = floor8(p) / 8;
-	endpage = iceil8((p + count)) / 8;
-	x = p % info->fix.line_length;
-	y = p / info->fix.line_length;
-	w = count % info->fix.line_length;
-	h = count / info->fix.line_length;
-	if (startpage != (endpage - 1)) {
-		/* If several page affected, update complete line
-		 * of all affected pages */
-		dd12832_cgram_update(info, 0, y, info->fix.line_length, h);
-	} else {
-		/* One page has been affected, only updates modified segment
-		 */
-		dd12832_cgram_update(info, x, y, w, h);
-	}
-	if (p+count > info->fix.line_length) {
-		/* Several line must be updated */
-	}
-	if (count)
-		return count;
-	return err;
-}
-
-/* fb_mmap
- * Map video memory in user space. We don't use the generic fb_mmap method
- * mainly
- * to allow the use of the TLB streaming flag (CCA=6)
- */
-int mx2fb_mmap(struct fb_info *info /*fbi*/, struct vm_area_struct *vma)
-{
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-	unsigned int len;
-	unsigned long start=0, off;
-
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
-		return -EINVAL;
-	}
-
-	start = mx2fbp->fb_pmem & PAGE_MASK;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + mx2fbp->fb_len);
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	if ((vma->vm_end - vma->vm_start + off) > len) {
-		return -EINVAL;
-	}
-
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-	pgprot_val(vma->vm_page_prot) |= (6 << 9);
-
-	vma->vm_flags |= VM_IO;
-
-	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-				vma->vm_end - vma->vm_start,
-				vma->vm_page_prot)) {
-		return -EAGAIN;
-	}
-	return 0;
-}
-
-
-/*!
- * @brief Framebuffer file operations
- */
-static struct fb_ops mx2fb_ops = {
-	.owner = THIS_MODULE,
-	//.fb_read        = fb_sys_read,
-	.fb_write 	= mx2fb_write,
-	.fb_check_var 	= mx2fb_check_var,
-	.fb_set_par 	= mx2fb_set_par,
-	.fb_blank 	= mx2fb_blank,
-	.fb_pan_display	= mx2fb_pan_display,
-	.fb_fillrect	= mx2fb_fillrect,
-	.fb_copyarea	= mx2fb_copyarea,
-	.fb_imageblit	= mx2fb_imageblit,
-	.fb_ioctl	= mx2fb_ioctl,
-	.fb_sync	= mx2fb_sync,
-	.fb_mmap	= mx2fb_mmap,
-};
-
-/*!
- * @brief Initialize framebuffer information structure.
- *
- * @param info	framebuffer information pointer
- * @param pdev	pointer to struct device
- * @return	Negative errno on error, or zero on success.
- */
-static int __init _init_fbinfo(struct fb_info *info,
-			       struct platform_device *pdev)
-{
-	info->device = &pdev->dev;
-	info->var.activate = FB_ACTIVATE_NOW;
-	info->fbops = &mx2fb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
-	info->pseudo_palette = NULL;
-
-	return 0;
-}
-
-/*!
- * @brief Install framebuffer into the system.
- *
- * @param info	framebuffer information pointer
- * @param pdev  pointer to struct device
- * @return	Negative errno on error, or zero on success.
- */
-static int __init _install_fb(struct fb_info *info,
-			      struct platform_device *pdev)
-{
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-
-	if (_init_fbinfo(info, pdev))
-		return -EINVAL;
-
-	if (fb_mode == 0)
-		fb_mode = pdev->dev.platform_data;
-
-	if (!fb_find_mode(&info->var, info, fb_mode, mxcfb_modedb,
-			  mxcfb_modedb_sz, NULL, default_bpp)) {
-		return -EBUSY;
-	}
-
-	/* Default Y virtual size is 2x panel size */
-	/* info->var.yres_virtual = info->var.yres << 1; */
-
-	if (mx2fbp->type == MX2FB_TYPE_GW)
-		mx2fbp->blank = FB_BLANK_NORMAL;
-	else
-		mx2fbp->blank = FB_BLANK_UNBLANK;
-
-	if (mx2fb_set_par(info)) {
-		return -EINVAL;
-	}
-
-	if (register_framebuffer(info) < 0) {
-		_unmap_video_memory(info);
-		return -EINVAL;
-	}
-
-	mx2fbp->registered = 1;
-
-	dev_info(info->device, "fb%d registered successfully on %s (rotate = %d).\n",
-		 info->node, fb_mode, mx2fbp->rotate);
-	return 0;
-}
-
-/*!
- * @brief Uninstall framebuffer from the system.
- *
- * @param info	framebuffer information pointer
- */
-static void __exit _uninstall_fb(struct fb_info *info)
-{
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-
-	if (!mx2fbp->registered)
-		return;
-
-	unregister_framebuffer(info);
-	_unmap_video_memory(info);
-	if (&info->cmap)
-		fb_dealloc_cmap(&info->cmap);
-
-	mx2fbp->registered = 0;
-}
-
-/*!
- * @brief Allocate memory for framebuffer.
- *
- * @param info	framebuffer information pointer
- * @return	Negative errno on error, or zero on success.
- */
-static int _map_video_memory(struct fb_info *info)
-{
-	unsigned long page;
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-	mx2fbp->fb_len = info->fix.line_length * info->var.yres_virtual;
-
-	mx2fbp->fb_vmem = dma_alloc_coherent(info->device, PAGE_ALIGN(mx2fbp->fb_len),
-			&mx2fbp->fb_pmem, GFP_KERNEL);
-	if (mx2fbp->fb_vmem == 0) {
-		dev_err(info->device, "fail to allocate frambuffer (size: %dK))",
-				mx2fbp->fb_len / 1024);
-		return -ENOMEM;
-	}
-
-	info->screen_base = mx2fbp->fb_vmem;
-	info->fix.smem_start = mx2fbp->fb_pmem;
-	info->fix.smem_len = mx2fbp->fb_len;
-
-	dev_dbg(info->device, "Allocated fb @ paddr=0x%08lX, size=%d.\n",
-		info->fix.smem_start, info->fix.smem_len);
-
-	info->screen_size = info->fix.smem_len;
-
-	/* Clear the screen */
-	memset((char *)mx2fbp->fb_vmem, 0x00, mx2fbp->fb_len);
-
-	/*
-	 * Set page reserved so that mmap will work. This is necessary
-	 * since we'll be remapping normal memory.
-	 */
-	for (page = (unsigned long)mx2fbp->fb_vmem;
-	     page < PAGE_ALIGN((unsigned long)mx2fbp->fb_vmem + mx2fbp->fb_len);
-	     page += PAGE_SIZE) {
-#ifdef CONFIG_DMA_NONCOHERENT
-		SetPageReserved(virt_to_page(CAC_ADDR(page)));
-#else
-		SetPageReserved(virt_to_page(page));
-#endif
-	}
-
-	return 0;
-}
-
-/*!
- * @brief Release memory for framebuffer.
- * @param info	framebuffer information pointer
- */
-static void _unmap_video_memory(struct fb_info *info)
-{
-	struct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;
-	if (mx2fbp->fb_vmem) {
-		dma_free_noncoherent(info->device, mx2fbp->fb_len, mx2fbp->fb_vmem, mx2fbp->fb_pmem);
-	}
-	mx2fbp->fb_len = 0;
-	mx2fbp->fb_pmem = 0;
-	mx2fbp->fb_vmem = 0;
-	info->screen_base = 0;
-	info->fix.smem_start = 0;
-	info->fix.smem_len = 0;
-	/* Free DMA of SLCDC transfert */
-	dma_pool_free(mx2fbp->cgram_data_dma_pool, (void *)mx2fbp->cgram_data_vaddr, (dma_addr_t) mx2fbp->cgram_data_paddr);
-	dma_pool_destroy(mx2fbp->cgram_data_dma_pool);
-	mx2fbp->cgram_data_dma_pool = 0;
-	mx2fbp->cgram_data_vaddr = 0;
-	mx2fbp->cgram_data_paddr = 0;
-	mx2fbp->cgram_data_len = 0;
-	/* Free DMA of SLCDC transfert */
-	dma_pool_free(mx2fbp->cgram_cmd_dma_pool, (void *)mx2fbp->cgram_cmd_vaddr, (dma_addr_t) mx2fbp->cgram_cmd_paddr);
-	dma_pool_destroy(mx2fbp->cgram_cmd_dma_pool);
-	mx2fbp->cgram_cmd_dma_pool = 0;
-	mx2fbp->cgram_cmd_vaddr = 0;
-	mx2fbp->cgram_cmd_paddr = 0;
-	mx2fbp->cgram_cmd_len = 0;
-}
-
-/*
- * @brief LCDC interrupt handler
- */
-static irqreturn_t mx2fb_isr(int irq, void *dev_id)
-{
-	struct fb_event event;
-	unsigned long status;
-
-	status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	status &= SLCDC_IRQ_FLAGS_MASK;
-
-	if (status & SLCDC_IRQ_FLAG) {
-		printk("Oled xfer done : ");
-		if (status == SLCDC_IRQ_FLAG) {
-			printk("Successful\n");
-		}
-		if (status & SLCDC_IRQ_TEA_FLAG) {
-			printk("DMA error\n");
-			event.info = &mx2fb_info;
-			atomic_notifier_call_chain(&mx2fb_notifier_list,
-					FB_EVENT_MXC_DMA_ERROR, &event);
-		}
-		if (status & SLCDC_IRQ_UNDRFLOW_FLAG) {
-			printk("Underflow occurs\n");
-			event.info = &mx2fb_info;
-			atomic_notifier_call_chain(&mx2fb_notifier_list,
-					FB_EVENT_MXC_UNDERFLOW, &event);
-		}
-	}
-
-	/* Write 1 to clear the status */
-	status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	status |= SLCDC_IRQ_FLAGS_MASK;
-	__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	
-	return IRQ_HANDLED;
-}
-
-/*!
- * @brief Config and request LCDC interrupt
- */
-static void _request_irq(void)
-{
-	unsigned long status;
-	unsigned long flags;
-
-	/* Write 1 to clear the status */
-	status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	status |= SLCDC_IRQ_FLAGS_MASK;
-	__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-
-	if (request_irq(INT_SLCDC, mx2fb_isr, 0, "SLCDC", 0))
-		pr_info("Request LCDC IRQ failed.\n");
-	else {
-		spin_lock_irqsave(&mx2fb_notifier_list.lock, flags);
-
-		/* Enable interrupt in case client has registered */
-		//if (mx2fb_notifier_list.head != NULL) {
-			//unsigned long status;
-			//unsigned long ints = MX2FB_INT_EOF;
-
-			//ints |= MX2FB_INT_GW_EOF;
-
-			/* Enable interrupt in case client has registered */
-			//if (mx2fb_notifier_list.head != NULL) {
-				/* Write 1 to clear the status */
-				status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-				status |= SLCDC_IRQ_FLAGS_MASK;
-				__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-
-				/* Enable SLCDC interrupt */
-				status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-				status |= SLCDC_IRQ_ENABLE;
-				__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-			//}
-		//}
-
-		spin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);
-	}
-}
-
-/*!
- * @brief Free LCDC interrupt handler
- */
-static void _free_irq(void)
-{
-	unsigned long status;
-	status =__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	/* Write 1 to clear the status */
-	status |= SLCDC_IRQ_FLAGS_MASK;
-	/* Disable all LCDC interrupt */
-	status &= ~SLCDC_IRQ_ENABLE;
-	__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-
-	free_irq(INT_SLCDC, 0);
-}
-
-/*!
- * @brief Register a client notifier
- * @param nb	notifier block to callback on events
- */
-int mx2fb_register_client(struct notifier_block *nb)
-{
-	unsigned long flags, status;
-	int ret;
-
-	ret = atomic_notifier_chain_register(&mx2fb_notifier_list, nb);
-
-	spin_lock_irqsave(&mx2fb_notifier_list.lock, flags);
-
-	/* Enable interrupt in case client has registered */
-	if (mx2fb_notifier_list.head != NULL) {
-		/* Write 1 to clear the status */
-		status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-		status |= SLCDC_IRQ_FLAGS_MASK;
-		__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-
-		/* Enable SLCDC interrupt */
-		status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-		status |= SLCDC_IRQ_ENABLE;
-		__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	}
-	spin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);
-
-	return ret;
-}
-
-/*!
- * @brief Unregister a client notifier
- * @param nb	notifier block to callback on events
- */
-int mx2fb_unregister_client(struct notifier_block *nb)
-{
-	unsigned long flags, status;
-	int ret;
-
-	ret = atomic_notifier_chain_unregister(&mx2fb_notifier_list, nb);
-
-	spin_lock_irqsave(&mx2fb_notifier_list.lock, flags);
-
-	/* Mask interrupt in case no client registered */
-	if (mx2fb_notifier_list.head == NULL) {
-		/* Enable SLCDC interrupt */
-		status = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-		status &= ~(SLCDC_IRQ_ENABLE);
-		__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));
-	}
-
-	spin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);
-
-	return ret;
-}
-
-#ifdef CONFIG_PM
-/*
- * Power management hooks. Note that we won't be called from IRQ context,
- * unlike the blank functions above, so we may sleep.
- */
-
-/*!
- * @brief Suspends the framebuffer and blanks the screen.
- * Power management support
- */
-#ifdef CONFIG_FB_MXC_EPSON_L4F0024
-static int mx2fb_spi_suspend(struct spi_device *spi, pm_message_t state)
-{
-#else
-static int mx2fb_suspend(struct platform_device *pdev, pm_message_t state)
-{
-#endif
-	_disable_slcdc(&mx2fb_info);
-
-	return 0;
-}
-
-/*!
- * @brief Resumes the framebuffer and unblanks the screen.
- * Power management support
- */
-#ifdef CONFIG_FB_MXC_EPSON_L4F0024
-static int mx2fb_spi_resume(struct spi_device *spi)
-#else
-static int mx2fb_resume(struct platform_device *pdev)
-#endif
-{
-	_enable_slcdc(&mx2fb_info);
-	return 0;
-}
-#endif				/* CONFIG_PM */
-
-/*!
- * @brief Probe routine for the framebuffer driver. It is called during the
- *        driver binding process.
- *
- * @return Appropriate error code to the kernel common code
- */
-static int mx2fb_probe(struct platform_device *pdev)
-{
-	int ret;
-
-	slcdc_clk = clk_get(&pdev->dev, "slcdc_clk");
-	clk_enable(slcdc_clk);
-
-	gpio_slcdc_active();
-
-	/* Memory allocation of display data for DMA transfert */
-	/* convert 1 byte / pixel length to 1 byte / column (8 pixels) */
-	mx2fbp_bg.cgram_data_len = OLED_WIDTH*OLED_HEIGHT / 8;
-	/* Allocate memory for CGRAM mirror with 128k boundary
-	 * (cf note SLCDC in Ch. 44.2 of i.MX27 RM) aligned on 1 byte */
-	mx2fbp_bg.cgram_data_dma_pool = dma_pool_create("SLCDC_DMA_DATA", &pdev->dev, mx2fbp_bg.cgram_data_len, 1, 128*1024);
-	if (mx2fbp_bg.cgram_data_dma_pool == NULL) {
-		dev_err(&pdev->dev, "Unable to allocated DMA Pool.\n");
-		return -ENOMEM;
-	}
-	mx2fbp_bg.cgram_data_vaddr = (unsigned long)dma_pool_alloc(mx2fbp_bg.cgram_data_dma_pool, GFP_DMA | GFP_KERNEL, (dma_addr_t *) &mx2fbp_bg.cgram_data_paddr);
-	if ((void *)mx2fbp_bg.cgram_data_vaddr == NULL) {
-		dev_err(&pdev->dev, "Unable to allocated DMA memory.\n");
-		return -ENOMEM;
-	}
-
-	/* Memory allocation of display commands for DMA transfert */
-	/* a page address on LCD is defined by 3 three commands.
-	 * Each command must be joined with a byte containing the state
-	 * of RS pin to apply (cf Fig 44-5 from SLCDC chapter in i.MX27 RM).
-	 * Array must be defined as unsigned short */
-	mx2fbp_bg.cgram_cmd_len = sizeof(_ssd1305_pagecmd_array)/sizeof(_ssd1305_pagecmd_array[0]);
-	/* Allocate memory for CGRAM mirror with 128k boundary
-	 * (cf note SLCDC in Ch. 44.2 of i.MX27 RM) aligned on 2 bytes (array of shorts) */
-	mx2fbp_bg.cgram_cmd_dma_pool = dma_pool_create("SLCDC_DMA_CMD", &pdev->dev, mx2fbp_bg.cgram_cmd_len/(sizeof(int)/sizeof(_ssd1305_pagecmd_array[0])), 2, 128*1024);
-	if (mx2fbp_bg.cgram_cmd_dma_pool == NULL) {
-		dev_err(&pdev->dev, "Unable to allocated DMA Pool.\n");
-		return -ENOMEM;
-	}
-	mx2fbp_bg.cgram_cmd_vaddr = (unsigned long)dma_pool_alloc(mx2fbp_bg.cgram_cmd_dma_pool, GFP_DMA | GFP_KERNEL, (dma_addr_t *) &mx2fbp_bg.cgram_cmd_paddr);
-	if ((void *)mx2fbp_bg.cgram_cmd_vaddr == NULL) {
-		dev_err(&pdev->dev, "Unable to allocated DMA memory.\n");
-		return -ENOMEM;
-	}
-
-	slcdc_first_init();
-	dd12832_init_controller();
-
-	ret = _install_fb(&mx2fb_info, pdev);
-	if (ret) {
-		dev_err(&pdev->dev,
-			"Failed to register framebuffer\n");
-		return ret;
-	}
-
-	//_request_irq();
-
-	return 0;
-}
-
-/*!
- * @brief This structure contains pointers to the power management
- * callback functions.
- */
-static struct platform_driver mx2fb_driver = {
-	.driver = {
-		   .name = "mxc_sdc_fb",
-		   .owner = THIS_MODULE,
-		   .bus = &platform_bus_type,
-		   },
-	.probe = mx2fb_probe,
-	.suspend = mx2fb_suspend,
-	.resume = mx2fb_resume,
-};
-
-/*!
- * @brief Initialization
- */
-int __init mx2fb_init(void)
-{
-	int ret = 0;
-	ret = platform_driver_register(&mx2fb_driver);
-	return ret;
-}
-
-/*!
- * @brief Cleanup
- */
-void __exit mx2fb_exit(void)
-{
-	_free_irq();
-	_uninstall_fb(&mx2fb_info);
-
-	platform_driver_unregister(&mx2fb_driver);
-}
-
-/* Modularization */
-module_init(mx2fb_init);
-module_exit(mx2fb_exit);
-
-EXPORT_SYMBOL(mx2_gw_set);
-EXPORT_SYMBOL(mx2fb_register_client);
-EXPORT_SYMBOL(mx2fb_unregister_client);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("MX2 framebuffer driver");
-MODULE_LICENSE("GPL");
diff --git a/a/content_digest b/N1/content_digest
index 2fc7f04..7c0525b 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,8 +1,8 @@
- "From\0Ga\303\253tan Carlier <gcembed@gmail.com>\0"
+ "From\0gcembed@gmail.com (Ga\303\253tan Carlier)\0"
  "Subject\0i.MX27 SLCDC driver\0"
- "Date\0Fri, 17 Aug 2012 07:07:57 +0000\0"
+ "Date\0Fri, 17 Aug 2012 09:07:57 +0200\0"
  "To\0linux-arm-kernel@lists.infradead.org\0"
- "\01:1\0"
+ "\00:1\0"
  "b\0"
  "Hello,\n"
  "I would like to write the driver for SmartLCD controller of i.MX27. This \n"
@@ -18,1331 +18,16 @@
  "the same driver.\n"
  "\n"
  "Thank you for your help.\n"
- "Ga\303\253tan Carlier\n"
+ "Ga?tan Carlier\n"
  "\n"
  "ps : I attach my previous driver for a better overview (this is a \n"
- working draft for test purpose)
- "\01:2\0"
- "fn\0mx2fb-slcd_dd12832_oled.c\0"
- "b\0"
- "/*\n"
- " * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.\n"
- " */\n"
- "\n"
- "/*\n"
- " * The code contained herein is licensed under the GNU General Public\n"
- " * License. You may obtain a copy of the GNU General Public License\n"
- " * Version 2 or later at the following locations:\n"
- " *\n"
- " * http://www.opensource.org/licenses/gpl-license.html\n"
- " * http://www.gnu.org/copyleft/gpl.html\n"
- " */\n"
- "\n"
- "/*!\n"
- " * @defgroup Framebuffer_MX27 Framebuffer Driver for MX27.\n"
- " */\n"
- "\n"
- "/*!\n"
- " * @file mx2fb.c\n"
- " *\n"
- " * @brief Frame buffer driver for MX27 ADS.\n"
- " *\n"
- " * @ingroup Framebuffer_MX27\n"
- " */\n"
- "\n"
- "#include <linux/module.h>\n"
- "#include <linux/kernel.h>\n"
- "#include <linux/errno.h>\n"
- "#include <linux/string.h>\n"
- "#include <linux/vmalloc.h>\n"
- "#include <linux/slab.h>\n"
- "#include <linux/fb.h>\n"
- "#include <linux/init.h>\n"
- "#include <linux/dmapool.h>\n"
- "#include <linux/dma-mapping.h>\n"
- "#include <linux/platform_device.h>\n"
- "#include <linux/interrupt.h>\n"
- "#include <linux/clk.h>\n"
- "#include <linux/delay.h>\n"
- "#include <asm/uaccess.h>\n"
- "#include <asm/arch/mxcfb.h>\n"
- "#include <asm/arch/mx2fb_slcdc.h>\n"
- "\n"
- "#include <asm/arch/pmic_power.h>\n"
- "#include \"dd12832_oled.h\"\n"
- "\n"
- "#ifdef CONFIG_PM\n"
- "static int mx2fb_suspend(struct platform_device *pdev, pm_message_t state);\n"
- "static int mx2fb_resume(struct platform_device *pdev);\n"
- "#else\n"
- "#define mx2fb_suspend\t\t0\n"
- "#define mx2fb_resume\t\t0\n"
- "#endif\n"
- "\n"
- "#define MX2FB_TYPE_BG          0\n"
- "#define MX2FB_TYPE_GW          1\n"
- "\n"
- "#define floor8(a) (a&(~0x07))\n"
- "//#define iceil8(a) (((int)((a+7)/8))*8)\n"
- "#define iceil8(a) ((int)((a & ~((int)0x03)) + 8))\n"
- "\n"
- "\n"
- "\n"
- "extern void gpio_slcdc_active(void);\n"
- "extern void gpio_slcdc_inactive(void);\n"
- "\n"
- "static char *fb_mode;\n"
- "static int fb_enabled;\n"
- "static unsigned long default_bpp = 1;\n"
- "static unsigned char brightness = 255;\n"
- "static ATOMIC_NOTIFIER_HEAD(mx2fb_notifier_list);\n"
- "static struct clk *slcdc_clk;\n"
- "/*!\n"
- " * @brief Structure containing the MX2 specific framebuffer parameters.\n"
- " */\n"
- "struct mx2fb_par {\n"
- "\tint type;\n"
- "\tchar *id;\n"
- "\tint registered;\n"
- "\tint blank;\n"
- "\t/* Tell if driver compiled with rotate option enabled */\n"
- "\tint rotate;\n"
- "\t/* Contains displayed data in 1 byte / column (8 pixels)\n"
- "\t * fb data are stored as 1 byte / pixel\n"
- "\t * !! must be allocated with 128k alignment using dma_pool_create\n"
- "\t */\n"
- "\t/* FrameBuffer memory map */\n"
- "\tunsigned char* fb_vmem;\n"
- "\tsize_t fb_len;\n"
- "\tdma_addr_t fb_pmem;\n"
- "\t/* Oled cgram memory map */\n"
- "\tunsigned long cgram_cmd_vaddr;\n"
- "\tunsigned long cgram_cmd_paddr;\n"
- "\tunsigned long cgram_cmd_len;\n"
- "\tstruct dma_pool *cgram_cmd_dma_pool;\n"
- "\tunsigned long cgram_data_vaddr;\n"
- "\tunsigned long cgram_data_paddr;\n"
- "\tunsigned long cgram_data_len;\n"
- "\tstruct dma_pool *cgram_data_dma_pool;\n"
- "};\n"
- "\n"
- "/* Framebuffer APIs */\n"
- "/*static int mx2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);\n"
- "static int mx2fb_set_par(struct fb_info *info);\n"
- "static void _set_fix(struct fb_info *info);*/\n"
- "\n"
- "/* Internal functions */\n"
- "static int __init _init_fbinfo(struct fb_info *info,\n"
- "\t\t\t       struct platform_device *pdev);\n"
- "static int __init _install_fb(struct fb_info *info,\n"
- "\t\t\t      struct platform_device *pdev);\n"
- "static void __exit _uninstall_fb(struct fb_info *info);\n"
- "static int _map_video_memory(struct fb_info *info);\n"
- "static void _unmap_video_memory(struct fb_info *info);\n"
- "/*static void _enable_lcdc(struct fb_info *info);\n"
- "static void _disable_lcdc(struct fb_info *info);\n"
- "static void _update_slcdc(struct fb_info *info);*/\n"
- "\n"
- "/* Oled display information */\n"
- "struct fb_videomode mxcfb_modedb[] = {\n"
- "\t{\n"
- "\t\t/* 128x32 */\n"
- "\t\t\"Densitron DD12832\", /* name */\n"
- "\t\t0, /* refresh */\n"
- "\t\t128, /* xres */\n"
- "\t\t32, /* yres */\n"
- "\t\t0, /* pixclock */\n"
- "\t\t0, /* left_margin */\n"
- "\t\t0, /* right_margin */\n"
- "\t\t0, /* upper_margin */\n"
- "\t\t0, /* lower_margin */\n"
- "\t\t0, /* hsync_len */\n"
- "\t\t0, /* vsync_len */\n"
- "\t\t0, /* sync */\n"
- "\t\t0, /* mode */\n"
- "\t\t0}, /* flag */\n"
- "};\n"
- "int mxcfb_modedb_sz = ARRAY_SIZE(mxcfb_modedb);\n"
- "\n"
- "struct mx2fb_par mx2fbp_bg = {\n"
- "\t.type = MX2FB_TYPE_BG,\n"
- "\t.id = \"DISP0 BG\",\n"
- "\t.registered = 0,\n"
- "#ifdef CONFIG_FB_MXC_DENSITRON_DD12832_ROTATE\n"
- "\t.rotate = 1,\n"
- "#else\n"
- "\t.rotate = 0,\n"
- "#endif\n"
- "};\n"
- "\n"
- "/*!\n"
- " * @brief Framebuffer information structures.\n"
- " * There are up to 3 framebuffers: background, TVout, and graphic window.\n"
- " * If graphic window is configured, it must be the last framebuffer.\n"
- " */\n"
- "static struct fb_info mx2fb_info = {\n"
- "\t.par = &mx2fbp_bg,\n"
- "};\n"
- "\n"
- "/*!\n"
- " * Do a minimal setup of SLCDC to be able to send command to DD12832\n"
- " */\n"
- "static void slcdc_first_init(void)\n"
- "{\n"
- "\tunsigned long val;\n"
- "\tint i;\n"
- "\tunsigned long *pdata;\n"
- "\n"
- "\t/* Screen start address register */\n"
- "\t__raw_writel(mx2fbp_bg.cgram_data_paddr, SLCDC_REG(SLCDC_DATABASEADDR));\n"
- "\t__raw_writel(mx2fbp_bg.cgram_data_len, SLCDC_REG(SLCDC_DATABUFSIZE));\n"
- "\n"
- "\t/* Copy command array to DMA area */\n"
- "\tpdata = (unsigned long *)mx2fbp_bg.cgram_cmd_vaddr;\n"
- "\tfor (i = 0; i < mx2fbp_bg.cgram_cmd_len; i++) {\n"
- "\t\tif ((i & 0x01) == 0) {\n"
- "\t\t\t/* If even offset, command must be left-aligned in\n"
- "\t\t\t * 32-bits memory space */\n"
- "\t\t\t*pdata = (unsigned long)_ssd1305_pagecmd_array[i] << 16;\n"
- "\t\t} else {\n"
- "\t\t\t/* If odd offset, command must be right-aligned in\n"
- "\t\t\t * 32-bits memory space */\n"
- "\t\t\t*pdata |= (unsigned long)_ssd1305_pagecmd_array[i];\n"
- "\t\t\t/* When \"right column\" is filled, go to next address */\n"
- "\t\t\tpdata++;\n"
- "\t\t}\n"
- "\t}\n"
- "\t/* Set Array of command for page addressing */\n"
- "\t__raw_writel(mx2fbp_bg.cgram_cmd_paddr, SLCDC_REG(SLCDC_COMBASEADDR));\n"
- "\t__raw_writel(mx2fbp_bg.cgram_cmd_len, SLCDC_REG(SLCDC_COMBUFSIZE));\n"
- "\n"
- "\t/* Set number of command (words) that must be send to jump to a\n"
- "\t * specific page. Size of \"word\" is define by WORDDEFCOM flag in\n"
- "\t * LCDTRANSCONFIG register */\n"
- "\t__raw_writel(PAGE_COMMAND_PACK_SIZE, SLCDC_REG(SLCDC_COMSTRINGSIZ));\n"
- "\n"
- "\t/* Define DMA burst */\n"
- "\t__raw_writel(0, SLCDC_REG(SLCDC_FIFOCONFIG));\n"
- "\n"
- "\t/* Define number of column/segment in a page */\n"
- "\t__raw_writel(OLED_WIDTH, SLCDC_REG(SLCDC_LCDCONFIG));\n"
- "\n"
- "\t/* Set transfer configuration */\n"
- "\tval = SLCDC_DATA_8BIT | SLCDC_COMMAND_8BIT | SLCDC_PARALLEL |\n"
- "\t\tSLCDC_WRITEDATA_8BIT | SLCDC_TRANS_LITLENDIAN_8BIT |\n"
- "\t\tSLCDC_CSPOL_LOW;\n"
- "\t__raw_writel(val, SLCDC_REG(SLCDC_LCDTRANSCONFIG));\n"
- "\n"
- "\t/* Set control register */\n"
- "\tval = SLCDC_MODE_COMMAND | SLCDC_IRQ_DISABLE | SLCDC_IRQ_FLAGS_MASK;\n"
- "\t__raw_writel(val, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\n"
- "\t/* Set SLCDC clock divider = HCLK_SLCDC * val / 128 */\n"
- "\tval = 40;\n"
- "\t__raw_writel(val, SLCDC_REG(SLCDC_LCDCLOCKCONFIG));\n"
- "}\n"
- "\n"
- "\n"
- "/*\n"
- " * Send one command to oled via SLCDC\n"
- " */\n"
- "static int _slcdc_sendcmd_single(unsigned char cmd)\n"
- "{\n"
- "\twhile (__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT)) & SLCDC_BUSY_MASK);\n"
- "\t__raw_writel((u32)cmd | WRITE_LCDCMD, SLCDC_REG(SLCDC_LCDWRITEDATA));\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*\n"
- " * Send one data to oled via SLCDC\n"
- " */\n"
- "static int _slcdc_senddata_single(unsigned char cmd)\n"
- "{\n"
- "\twhile (__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT)) & SLCDC_BUSY_MASK);\n"
- "\t__raw_writel((u32)cmd | WRITE_LCDDATA, SLCDC_REG(SLCDC_LCDWRITEDATA));\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*\n"
- " * Set Start line for Pan function\n"
- " */\n"
- "static void dd12832_set_start_line(unsigned char y)\n"
- "{\n"
- "\t_slcdc_sendcmd_single(SSD1305_CMD_ROWADDR | (y & 0x3F));\n"
- "}\n"
- "\n"
- "/*\n"
- " * Set page address\n"
- " */\n"
- "static void dd12832_set_yaddr(unsigned char y)\n"
- "{\n"
- "\t_slcdc_sendcmd_single(SSD1305_CMD_PAGEADDR | (y & 0x07));\n"
- "}\n"
- "\n"
- "/*\n"
- " * Set segment address\n"
- " */\n"
- "static void dd12832_set_xaddr(unsigned char x)\n"
- "{\n"
- "#ifndef CONFIG_FB_MXC_DENSITRON_DD12832_ROTATE\n"
- "\t_slcdc_sendcmd_single(SSD1305_CMD_HIGHCOLADDR | (x >> 4));\n"
- "\t_slcdc_sendcmd_single(SSD1305_CMD_LOWCOLADDR | (x & 0x0F));\n"
- "#else\n"
- "\tx += SSD1305_WIDTH - OLED_WIDTH;\n"
- "\t_slcdc_sendcmd_single(SSD1305_CMD_HIGHCOLADDR | (x >> 4));\n"
- "\t_slcdc_sendcmd_single(SSD1305_CMD_LOWCOLADDR | (x & 0x0F));\n"
- "#endif\n"
- "}\n"
- "\n"
- "/*\n"
- " * Modify contrast value\n"
- " */\n"
- "static void dd12832_set_brightness(unsigned char level)\n"
- "{\n"
- "\tif (level == 0) {\n"
- "\t\t/* If level 0 asked, display must be turned off\n"
- "\t\t* because Display is still ON when Contrast\n"
- "\t\t* is set to 0 */\n"
- "\t\t_slcdc_sendcmd_single(SSD1305_CMD_DISPLAY_POWER_OFF);\n"
- "\t} else {\n"
- "\t\t/* Apply new contrast */\n"
- "\t\t_slcdc_sendcmd_single(SSD1305_CMD_BRIGHTNESS_MODE);\n"
- "\t\t_slcdc_sendcmd_single(level);\n"
- "\t\t/* Be sure that DISPLAY is ON */\n"
- "\t\t_slcdc_sendcmd_single(SSD1305_CMD_DISPLAY_POWER_ON);\n"
- "\t}\n"
- "}\n"
- "\n"
- "/*\n"
- " * Clear internal RAM of controller\n"
- " */\n"
- "static void dd12832_clear_lcd(void)\n"
- "{\n"
- "\tunsigned long status;\n"
- "\t/* Clear OLED RAM mirror buffer */\n"
- "\tchar *pdata = (char *)mx2fbp_bg.cgram_data_vaddr;\n"
- "\tmemset(pdata, 0, mx2fbp_bg.cgram_data_len);\n"
- "\n"
- "\t/* Clear FrameBuffer mirror buffer */\n"
- "\tpdata = (char __force *) mx2fbp_bg.fb_vmem;\n"
- "\tmemset(pdata, 0, mx2fbp_bg.fb_len);\n"
- "\n"
- "\tdd12832_set_yaddr(0);\n"
- "\tdd12832_set_xaddr(0);\n"
- "\twhile (__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT)) & SLCDC_BUSY_MASK);\n"
- "\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\tstatus &= ~(SLCDC_SLCDCCTRLSTAT_AUTOMODE_MASK);\n"
- "\tstatus |= SLCDC_MODE_DATA | SLCDC_START_TRANSFERT;\n"
- "\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "}\n"
- "\n"
- "/*\n"
- " * Send init sequence to display controller\n"
- " */\n"
- "static int dd12832_init_controller(void)\n"
- "{\n"
- "\t/* Use SLCDC to send command block */\n"
- "\tunsigned long i;\n"
- "\n"
- "\tfor (i = 0; i < sizeof(_ssd1305_init_array); i++) {\n"
- "\t\t_slcdc_sendcmd_single(_ssd1305_init_array[i]);\n"
- "\t}\n"
- "\tdd12832_clear_lcd();\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Enable LCD controller.\n"
- " * @param info\tframebuffer information pointer\n"
- " */\n"
- "static void _enable_slcdc(struct fb_info *info)\n"
- "{\n"
- "\tif (!fb_enabled) {\n"
- "\t\tfb_enabled++;\n"
- "\n"
- "\t\tif (fb_mode) {\n"
- "\t\t\tunsigned long mode = 0;\n"
- "\t\t\tif (mode == 0) {\n"
- "\t\t\t\tdd12832_set_brightness(brightness);\n"
- "\t\t\t}\n"
- "\t\t}\n"
- "\t}\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Disable LCD controller.\n"
- " * @param info\tframebuffer information pointer\n"
- " */\n"
- "static void _disable_slcdc(struct fb_info *info)\n"
- "{\n"
- "\tif (fb_enabled) {\n"
- "\t\tdd12832_set_brightness(0);\n"
- "\t\tfb_enabled = 0;\n"
- "\t}\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Update SLCDC registers\n"
- " * @param info\tframebuffer information pointer\n"
- " */\n"
- "static void _update_slcdc(struct fb_info *info)\n"
- "{\n"
- "\tunsigned long base;\n"
- "\tunsigned long val;\n"
- "\tstruct fb_var_screeninfo *var = &info->var;\n"
- "\n"
- "\tbase = (var->yoffset * var->xres_virtual + var->xoffset);\n"
- "\tbase += (unsigned long)info->screen_base;\n"
- "\n"
- "\t/* Set number of command (words) that must be send to jump to a\n"
- "\t * specific page. Size of \"word\" is define by WORDDEFCOM flag in\n"
- "\t * LCDTRANSCONFIG register */\n"
- "\t__raw_writel(PAGE_COMMAND_PACK_SIZE, SLCDC_REG(SLCDC_COMSTRINGSIZ));\n"
- "\n"
- "\t/* Define DMA burst */\n"
- "\t__raw_writel(0, SLCDC_REG(SLCDC_FIFOCONFIG));\n"
- "\n"
- "\t/* Define number of column/segment in a page */\n"
- "\t__raw_writel(OLED_WIDTH, SLCDC_REG(SLCDC_LCDCONFIG));\n"
- "\n"
- "\t/* Set transfer configuration */\n"
- "\tval = SLCDC_DATA_8BIT | SLCDC_COMMAND_8BIT | SLCDC_PARALLEL |\n"
- "\t\tSLCDC_WRITEDATA_8BIT | SLCDC_TRANS_LITLENDIAN_8BIT |\n"
- "\t\tSLCDC_CSPOL_LOW;\n"
- "\t__raw_writel(val, SLCDC_REG(SLCDC_LCDTRANSCONFIG));\n"
- "\n"
- "\t/* Set SLCDC clock divider = HCLK_SLCDC * val / 128 */\n"
- "\tval = 60;\n"
- "\t__raw_writel(val, SLCDC_REG(SLCDC_LCDCLOCKCONFIG));\n"
- "\n"
- "\treturn;\n"
- "}\n"
- "\n"
- "\n"
- "/*!\n"
- " * @brief Blanks the display.\n"
- " *\n"
- " * @param blank_mode\tThe blank mode we want.\n"
- " * @param info\t\tFrame buffer structure that represents a single frame buffer\n"
- " *\n"
- " * @return\t\tNegative errno on error, or zero on success.\n"
- " *\n"
- " * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking\n"
- " * succeeded, != 0 if un-/blanking failed.\n"
- " * blank_mode == 2: suspend vsync\n"
- " * blank_mode == 3: suspend hsync\n"
- " * blank_mode == 4: powerdown\n"
- " */\n"
- "static int mx2fb_blank(int blank_mode, struct fb_info *info)\n"
- "{\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\n"
- "\tdev_dbg(info->device, \"blank mode = %d\\n\", blank_mode);\n"
- "\n"
- "\tmx2fbp->blank = blank_mode;\n"
- "\n"
- "\tswitch (blank_mode) {\n"
- "\tcase FB_BLANK_POWERDOWN:\n"
- "\tcase FB_BLANK_VSYNC_SUSPEND:\n"
- "\tcase FB_BLANK_HSYNC_SUSPEND:\n"
- "\tcase FB_BLANK_NORMAL:\n"
- "\t\t_disable_slcdc(info);\n"
- "\t\tbreak;\n"
- "\tcase FB_BLANK_UNBLANK:\n"
- "\t\t_enable_slcdc(info);\n"
- "\t\tbreak;\n"
- "\t}\n"
- "\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*\n"
- " * here we start the process of spliting out the fb update into\n"
- " * individual blocks of pixels. we end up spliting into 64x64 blocks\n"
- " * and finally down to 64x8 pages.\n"
- " */\n"
- "static void dd12832_cgram_update(struct fb_info *info, unsigned int dx,\n"
- "\t\t\t\t\tunsigned int dy, unsigned int w, unsigned int h)\n"
- "{\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\tunsigned int startpage, endpage, startseg, endseg;\n"
- "\tunsigned int curpage, curseg;\n"
- "\tunsigned long status;\n"
- "\tint i;\n"
- "\tunsigned char myseg;\n"
- "\tchar *cgram;\n"
- "\tunsigned char *ppixel;\n"
- "\n"
- "\t/* align the request first */\n"
- "\t/* Get first line of the page where starting pixel is located */\n"
- "\tstartpage = floor8(dy) / 8;\n"
- "\t/* Get first line of the next page where last pixel to update\n"
- "\t * is located */\n"
- "\tendpage = h + dy - 1;\n"
- "\tendpage = iceil8(endpage) / 8;\n"
- "\n"
- "\t/* First segment to update */\n"
- "\tstartseg = dx;\n"
- "\t/* Last segment to update */\n"
- "\tendseg = dx + (w - 1);\n"
- "\n"
- "\tfor (curpage = startpage; curpage < endpage; curpage++) {\n"
- "\t\tcgram = (char*)mx2fbp->cgram_data_vaddr;\n"
- "\t\tcgram += curpage * info->fix.line_length;\n"
- "\t\tcgram += startseg;\n"
- "\t\tfor (curseg = startseg; curseg <= endseg; curseg++) {\n"
- "\t\t\t/* Get segment to update in video memory */\n"
- "\t\t\tmyseg = 0;\n"
- "\t\t\tppixel = (unsigned char __force *) mx2fbp->fb_vmem;\n"
- "\t\t\t/* There is 8 lines per page */\n"
- "\t\t\tppixel += curpage * info->fix.line_length * 8;\n"
- "\t\t\t/* Points to upper pixel of the current segment */\n"
- "\t\t\tppixel += curseg;\n"
- "\t\t\tfor (i = 0; i < 8; i++) {\n"
- "\t\t\t\tif (*ppixel != 0) {\n"
- "\t\t\t\t\tmyseg |= 1 << i;\n"
- "\t\t\t\t}\n"
- "\t\t\t\t/* Jump to next line to get pixel below */\n"
- "\t\t\t\tppixel += info->fix.line_length;\n"
- "\t\t\t}\n"
- "\t\t\t*cgram = myseg;\n"
- "\t\t\tcgram++;\n"
- "\t\t}\n"
- "\t}\n"
- "\tdd12832_set_xaddr(0);\n"
- "\tdd12832_set_yaddr(0);\n"
- "\twhile (__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT)) & SLCDC_BUSY_MASK);\n"
- "\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\tstatus &= ~(SLCDC_SLCDCCTRLSTAT_AUTOMODE_MASK);\n"
- "\tstatus |= SLCDC_MODE_DATA | SLCDC_START_TRANSFERT;\n"
- "\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "}\n"
- "\n"
- "\n"
- "\n"
- "static void mx2fb_fillrect(struct fb_info *info,\n"
- "\t\t\t   const struct fb_fillrect *rect)\n"
- "{\n"
- "\tsys_fillrect(info, rect);\n"
- "\n"
- "\t/* update the physical lcd */\n"
- "\tdd12832_cgram_update(info, rect->dx, rect->dy, rect->width, rect->height);\n"
- "}\n"
- "\n"
- "static void mx2fb_copyarea(struct fb_info *info,\n"
- "\t\t\t   const struct fb_copyarea *area)\n"
- "{\n"
- "\tsys_copyarea(info, area);\n"
- "\n"
- "\t/* update the physical lcd */\n"
- "\tdd12832_cgram_update(info, area->dx, area->dy, area->width, area->height);\n"
- "}\n"
- "\n"
- "static void mx2fb_imageblit(struct fb_info *info, const struct fb_image *image)\n"
- "{\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\tchar *ppixel;\n"
- "\tconst char *pdata;\n"
- "\tint j;\n"
- "\n"
- "\tif (image->depth == 1) {\n"
- "\t\t/* Draw image */\n"
- "\t\tpdata = image->data;\n"
- "\t\tppixel = mx2fbp->fb_vmem;\n"
- "\t\tppixel += image->dy * info->fix.line_length;\n"
- "\t\tppixel += image->dx;\n"
- "\t\tfor (j = 0; j < image->height; j++) {\n"
- "\t\t\tmemcpy(ppixel, pdata, image->width);\n"
- "\t\t\tpdata += image->width;\n"
- "\t\t\tppixel += info->fix.line_length;\n"
- "\t\t}\n"
- "\t\t/* update the physical lcd */\n"
- "\t\tdd12832_cgram_update(info, image->dx, image->dy, image->width, image->height);\n"
- "\t}\n"
- "}\n"
- "\n"
- "\n"
- "/*!\n"
- " * @brief Pans the display.\n"
- " *\n"
- " * @param var\tFrame buffer variable screen structure\n"
- " * @param info\tFrame buffer structure that represents a single frame buffer\n"
- " *\n"
- " * @return\tNegative errno on error, or zero on success.\n"
- " *\n"
- " * Pan (or wrap, depending on the `vmode' field) the display using the\n"
- " * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values\n"
- " * don't fit, return -EINVAL.\n"
- " */\n"
- "static int mx2fb_pan_display(struct fb_var_screeninfo *var,\n"
- "\t\t\t     struct fb_info *info)\n"
- "{\n"
- "\tif (info->var.yoffset == var->yoffset) {\n"
- "\t\treturn 0;\t/* No change, do nothing */\n"
- "\t}\n"
- "\n"
- "        if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < OLED_WIDTH)\n"
- "                && (info->var.yres <= OLED_WIDTH)) {\n"
- "                dd12832_set_start_line(var->yoffset);\n"
- "                info->var.yoffset = var->yoffset;\n"
- "                return 0;\n"
- "        }\n"
- "\n"
- "        return -EINVAL;\n"
- "}\n"
- "\n"
- "static int mx2fb_sync(struct fb_info *info)\n"
- "{\n"
- "\tdd12832_cgram_update(info, 0, 0, info->fix.line_length, info->var.yres_virtual);\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Ioctl function to support customized ioctl operations.\n"
- " *\n"
- " * @param info\tFramebuffer structure that represents a single frame buffer\n"
- " * @param cmd\tThe command number\n"
- " * @param arg\tArgument which depends on cmd\n"
- " *\n"
- " * @return\tNegative errno on error, or zero on success.\n"
- " */\n"
- "static int mx2fb_ioctl(struct fb_info *info, unsigned int cmd,\n"
- "\t\t       unsigned long arg)\n"
- "{\n"
- "\tunsigned char level;\n"
- "\n"
- "\tswitch (cmd) {\n"
- "\tcase MX2FB_SET_BRIGHTNESS:\n"
- "\t\tif (copy_from_user((void *)&level, (void *)arg, sizeof(level)))\n"
- "\t\t\treturn -EFAULT;\n"
- "\t\tbrightness = level;\n"
- "\t\tdd12832_set_brightness(level);\n"
- "\t\tbreak;\n"
- "\tcase MX2FB_FORCE_SYNC:\n"
- "\t\tmx2fb_sync(info);\n"
- "\t\tbreak;\n"
- "\tdefault:\n"
- "\t\tdev_dbg(info->device, \"Unknown ioctl command (0x%08X)\\n\", cmd);\n"
- "\t\treturn -EINVAL;\n"
- "\t}\n"
- "\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Set fixed framebuffer parameters based on variable settings.\n"
- " *\n"
- " * @param info\tframebuffer information pointer\n"
- " * @return\tNegative errno on error, or zero on success.\n"
- " */\n"
- "static void _set_fix(struct fb_info *info)\n"
- "{\n"
- "\tstruct fb_fix_screeninfo *fix = &info->fix;\n"
- "\tstruct fb_var_screeninfo *var = &info->var;\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\n"
- "\tstrncpy(fix->id, mx2fbp->id, strlen(mx2fbp->id));\n"
- "\tif (var->bits_per_pixel < 8)\n"
- "\t\tfix->line_length = var->xres_virtual;\n"
- "\telse\n"
- "\t\tfix->line_length = var->xres_virtual * var->bits_per_pixel / 8;\n"
- "\tfix->type = FB_TYPE_PACKED_PIXELS;\n"
- "\tfix->accel = FB_ACCEL_NONE;\n"
- "\tfix->visual = FB_VISUAL_MONO10;\n"
- "\tfix->xpanstep = 0;\n"
- "\tfix->ypanstep = 1;\n"
- "\tfix->ywrapstep = 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Validates a var passed in.\n"
- " *\n"
- " * @param var\tFrame buffer variable screen structure\n"
- " * @param info\tFrame buffer structure that represents a single frame buffer\n"
- " *\n"
- " * @return\tNegative errno on error, or zero on success.\n"
- " *\n"
- " * Checks to see if the hardware supports the state requested by var passed\n"
- " * in. This function does not alter the hardware state! If the var passed in\n"
- " * is slightly off by what the hardware can support then we alter the var\n"
- " * PASSED in to what we can do. If the hardware doesn't support mode change\n"
- " * a -EINVAL will be returned by the upper layers.\n"
- " *\n"
- " */\n"
- "static int mx2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)\n"
- "{\n"
- "\tif (var->xres_virtual < var->xres)\n"
- "\t\tvar->xres_virtual = var->xres;\n"
- "\tif (var->yres_virtual < var->yres)\n"
- "\t\tvar->yres_virtual = var->yres;\n"
- "\n"
- "\tif (var->xoffset < 0)\n"
- "\t\tvar->xoffset = 0;\n"
- "\n"
- "\tif (var->yoffset < 0)\n"
- "\t\tvar->yoffset = 0;\n"
- "\n"
- "\tif (var->xoffset + info->var.xres > info->var.xres_virtual)\n"
- "\t\tvar->xoffset = info->var.xres_virtual - info->var.xres;\n"
- "\n"
- "\tif (var->yoffset + info->var.yres > info->var.yres_virtual)\n"
- "\t\tvar->yoffset = info->var.yres_virtual - info->var.yres;\n"
- "\n"
- "\tif (var->bits_per_pixel != default_bpp)\n"
- "\t\tvar->bits_per_pixel = default_bpp;\n"
- "\n"
- "\tif (var->pixclock != 0)\n"
- "\t\tvar->pixclock = 0;\n"
- "\tvar->red.length = var->green.length = var->blue.length = 1;\n"
- "\tvar->red.offset = var->green.offset = var->blue.offset = 0;\n"
- "\tvar->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;\n"
- "\n"
- "\tvar->transp.length = 0;\n"
- "\tvar->transp.offset = 0;\n"
- "\tvar->transp.msb_right = 0;\n"
- "\n"
- "\tvar->height = -1;\n"
- "\tvar->width = -1;\n"
- "\tvar->grayscale = 0;\n"
- "\n"
- "\t/* Copy nonstd field to/from sync for fbset usage */\n"
- "\tvar->sync |= var->nonstd;\n"
- "\tvar->nonstd |= var->sync;\n"
- "\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Alters the hardware state.\n"
- " *\n"
- " * @param info\tFrame buffer structure that represents a single frame buffer\n"
- " *\n"
- " * @return Zero on success others on failure\n"
- " *\n"
- " * Using the fb_var_screeninfo in fb_info we set the resolution of this\n"
- " * particular framebuffer. This function alters the fb_fix_screeninfo stored\n"
- " * in fb_info. It doesn't not alter var in fb_info since we are using that\n"
- " * data. This means we depend on the data in var inside fb_info to be\n"
- " * supported by the hardware. mx2fb_check_var is always called before\n"
- " * mx2fb_set_par to ensure this.\n"
- " */\n"
- "static int mx2fb_set_par(struct fb_info *info)\n"
- "{\n"
- "\tunsigned long len;\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\n"
- "\t_set_fix(info);\n"
- "\n"
- "\tlen = info->var.yres_virtual * info->fix.line_length;\n"
- "\tif (len > info->fix.smem_len) {\n"
- "\t\tif (info->fix.smem_start)\n"
- "\t\t\t_unmap_video_memory(info);\n"
- "\n"
- "\t\t/* Memory allocation for framebuffer */\n"
- "\t\tif (_map_video_memory(info)) {\n"
- "\t\t\tdev_err(info->device, \"Unable to allocate fb memory\\n\");\n"
- "\t\t\treturn -ENOMEM;\n"
- "\t\t}\n"
- "\t}\n"
- "\n"
- "\t_update_slcdc(info);\n"
- "\n"
- "\tmx2fb_blank(mx2fbp->blank, info);\n"
- "\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*\n"
- " * this is the access path from userspace. they can seek and write to\n"
- " * the fb. it's inefficient for them to do anything less than 64*8\n"
- " * writes since we update the lcd in each write() anyway.\n"
- " */\n"
- "static ssize_t mx2fb_write(struct fb_info *info, const char __user *buf,\n"
- "\t\t\t   size_t count, loff_t *ppos)\n"
- "{\n"
- "\t/* modded from epson 1355 */\n"
- "\n"
- "\tunsigned long p;\n"
- "\tint err=-EINVAL;\n"
- "\tunsigned int fbmemlength, x, y, w, h, startpage, endpage;\n"
- "\tstruct arcfb_par *par;\n"
- "\tunsigned int xres;\n"
- "\n"
- "\tp = *ppos;\n"
- "\tpar = info->par;\n"
- "\txres = info->var.xres;\n"
- "\tfbmemlength = info->fix.smem_len;\n"
- "\n"
- "\tif (p > fbmemlength)\n"
- "\t\treturn -ENOSPC;\n"
- "\n"
- "\terr = 0;\n"
- "\tif ((count + p) > fbmemlength) {\n"
- "\t\tcount = fbmemlength - p;\n"
- "\t\terr = -ENOSPC;\n"
- "\t}\n"
- "\n"
- "\tif (count) {\n"
- "\t\tchar *base_addr;\n"
- "\n"
- "\t\tbase_addr = (char __force *)info->screen_base;\n"
- "\t\tcount -= copy_from_user(base_addr + p, buf, count);\n"
- "\t\t*ppos += count;\n"
- "\t\terr = -EFAULT;\n"
- "\t}\n"
- "\n"
- "\t/* Check how many page are affected */\n"
- "\tstartpage = floor8(p) / 8;\n"
- "\tendpage = iceil8((p + count)) / 8;\n"
- "\tx = p % info->fix.line_length;\n"
- "\ty = p / info->fix.line_length;\n"
- "\tw = count % info->fix.line_length;\n"
- "\th = count / info->fix.line_length;\n"
- "\tif (startpage != (endpage - 1)) {\n"
- "\t\t/* If several page affected, update complete line\n"
- "\t\t * of all affected pages */\n"
- "\t\tdd12832_cgram_update(info, 0, y, info->fix.line_length, h);\n"
- "\t} else {\n"
- "\t\t/* One page has been affected, only updates modified segment\n"
- "\t\t */\n"
- "\t\tdd12832_cgram_update(info, x, y, w, h);\n"
- "\t}\n"
- "\tif (p+count > info->fix.line_length) {\n"
- "\t\t/* Several line must be updated */\n"
- "\t}\n"
- "\tif (count)\n"
- "\t\treturn count;\n"
- "\treturn err;\n"
- "}\n"
- "\n"
- "/* fb_mmap\n"
- " * Map video memory in user space. We don't use the generic fb_mmap method\n"
- " * mainly\n"
- " * to allow the use of the TLB streaming flag (CCA=6)\n"
- " */\n"
- "int mx2fb_mmap(struct fb_info *info /*fbi*/, struct vm_area_struct *vma)\n"
- "{\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\tunsigned int len;\n"
- "\tunsigned long start=0, off;\n"
- "\n"
- "\tif (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {\n"
- "\t\treturn -EINVAL;\n"
- "\t}\n"
- "\n"
- "\tstart = mx2fbp->fb_pmem & PAGE_MASK;\n"
- "\tlen = PAGE_ALIGN((start & ~PAGE_MASK) + mx2fbp->fb_len);\n"
- "\n"
- "\toff = vma->vm_pgoff << PAGE_SHIFT;\n"
- "\n"
- "\tif ((vma->vm_end - vma->vm_start + off) > len) {\n"
- "\t\treturn -EINVAL;\n"
- "\t}\n"
- "\n"
- "\toff += start;\n"
- "\tvma->vm_pgoff = off >> PAGE_SHIFT;\n"
- "\n"
- "\tvma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);\n"
- "\tpgprot_val(vma->vm_page_prot) |= (6 << 9);\n"
- "\n"
- "\tvma->vm_flags |= VM_IO;\n"
- "\n"
- "\tif (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,\n"
- "\t\t\t\tvma->vm_end - vma->vm_start,\n"
- "\t\t\t\tvma->vm_page_prot)) {\n"
- "\t\treturn -EAGAIN;\n"
- "\t}\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "\n"
- "/*!\n"
- " * @brief Framebuffer file operations\n"
- " */\n"
- "static struct fb_ops mx2fb_ops = {\n"
- "\t.owner = THIS_MODULE,\n"
- "\t//.fb_read        = fb_sys_read,\n"
- "\t.fb_write \t= mx2fb_write,\n"
- "\t.fb_check_var \t= mx2fb_check_var,\n"
- "\t.fb_set_par \t= mx2fb_set_par,\n"
- "\t.fb_blank \t= mx2fb_blank,\n"
- "\t.fb_pan_display\t= mx2fb_pan_display,\n"
- "\t.fb_fillrect\t= mx2fb_fillrect,\n"
- "\t.fb_copyarea\t= mx2fb_copyarea,\n"
- "\t.fb_imageblit\t= mx2fb_imageblit,\n"
- "\t.fb_ioctl\t= mx2fb_ioctl,\n"
- "\t.fb_sync\t= mx2fb_sync,\n"
- "\t.fb_mmap\t= mx2fb_mmap,\n"
- "};\n"
- "\n"
- "/*!\n"
- " * @brief Initialize framebuffer information structure.\n"
- " *\n"
- " * @param info\tframebuffer information pointer\n"
- " * @param pdev\tpointer to struct device\n"
- " * @return\tNegative errno on error, or zero on success.\n"
- " */\n"
- "static int __init _init_fbinfo(struct fb_info *info,\n"
- "\t\t\t       struct platform_device *pdev)\n"
- "{\n"
- "\tinfo->device = &pdev->dev;\n"
- "\tinfo->var.activate = FB_ACTIVATE_NOW;\n"
- "\tinfo->fbops = &mx2fb_ops;\n"
- "\tinfo->flags = FBINFO_FLAG_DEFAULT;\n"
- "\tinfo->pseudo_palette = NULL;\n"
- "\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Install framebuffer into the system.\n"
- " *\n"
- " * @param info\tframebuffer information pointer\n"
- " * @param pdev  pointer to struct device\n"
- " * @return\tNegative errno on error, or zero on success.\n"
- " */\n"
- "static int __init _install_fb(struct fb_info *info,\n"
- "\t\t\t      struct platform_device *pdev)\n"
- "{\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\n"
- "\tif (_init_fbinfo(info, pdev))\n"
- "\t\treturn -EINVAL;\n"
- "\n"
- "\tif (fb_mode == 0)\n"
- "\t\tfb_mode = pdev->dev.platform_data;\n"
- "\n"
- "\tif (!fb_find_mode(&info->var, info, fb_mode, mxcfb_modedb,\n"
- "\t\t\t  mxcfb_modedb_sz, NULL, default_bpp)) {\n"
- "\t\treturn -EBUSY;\n"
- "\t}\n"
- "\n"
- "\t/* Default Y virtual size is 2x panel size */\n"
- "\t/* info->var.yres_virtual = info->var.yres << 1; */\n"
- "\n"
- "\tif (mx2fbp->type == MX2FB_TYPE_GW)\n"
- "\t\tmx2fbp->blank = FB_BLANK_NORMAL;\n"
- "\telse\n"
- "\t\tmx2fbp->blank = FB_BLANK_UNBLANK;\n"
- "\n"
- "\tif (mx2fb_set_par(info)) {\n"
- "\t\treturn -EINVAL;\n"
- "\t}\n"
- "\n"
- "\tif (register_framebuffer(info) < 0) {\n"
- "\t\t_unmap_video_memory(info);\n"
- "\t\treturn -EINVAL;\n"
- "\t}\n"
- "\n"
- "\tmx2fbp->registered = 1;\n"
- "\n"
- "\tdev_info(info->device, \"fb%d registered successfully on %s (rotate = %d).\\n\",\n"
- "\t\t info->node, fb_mode, mx2fbp->rotate);\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Uninstall framebuffer from the system.\n"
- " *\n"
- " * @param info\tframebuffer information pointer\n"
- " */\n"
- "static void __exit _uninstall_fb(struct fb_info *info)\n"
- "{\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\n"
- "\tif (!mx2fbp->registered)\n"
- "\t\treturn;\n"
- "\n"
- "\tunregister_framebuffer(info);\n"
- "\t_unmap_video_memory(info);\n"
- "\tif (&info->cmap)\n"
- "\t\tfb_dealloc_cmap(&info->cmap);\n"
- "\n"
- "\tmx2fbp->registered = 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Allocate memory for framebuffer.\n"
- " *\n"
- " * @param info\tframebuffer information pointer\n"
- " * @return\tNegative errno on error, or zero on success.\n"
- " */\n"
- "static int _map_video_memory(struct fb_info *info)\n"
- "{\n"
- "\tunsigned long page;\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\tmx2fbp->fb_len = info->fix.line_length * info->var.yres_virtual;\n"
- "\n"
- "\tmx2fbp->fb_vmem = dma_alloc_coherent(info->device, PAGE_ALIGN(mx2fbp->fb_len),\n"
- "\t\t\t&mx2fbp->fb_pmem, GFP_KERNEL);\n"
- "\tif (mx2fbp->fb_vmem == 0) {\n"
- "\t\tdev_err(info->device, \"fail to allocate frambuffer (size: %dK))\",\n"
- "\t\t\t\tmx2fbp->fb_len / 1024);\n"
- "\t\treturn -ENOMEM;\n"
- "\t}\n"
- "\n"
- "\tinfo->screen_base = mx2fbp->fb_vmem;\n"
- "\tinfo->fix.smem_start = mx2fbp->fb_pmem;\n"
- "\tinfo->fix.smem_len = mx2fbp->fb_len;\n"
- "\n"
- "\tdev_dbg(info->device, \"Allocated fb @ paddr=0x%08lX, size=%d.\\n\",\n"
- "\t\tinfo->fix.smem_start, info->fix.smem_len);\n"
- "\n"
- "\tinfo->screen_size = info->fix.smem_len;\n"
- "\n"
- "\t/* Clear the screen */\n"
- "\tmemset((char *)mx2fbp->fb_vmem, 0x00, mx2fbp->fb_len);\n"
- "\n"
- "\t/*\n"
- "\t * Set page reserved so that mmap will work. This is necessary\n"
- "\t * since we'll be remapping normal memory.\n"
- "\t */\n"
- "\tfor (page = (unsigned long)mx2fbp->fb_vmem;\n"
- "\t     page < PAGE_ALIGN((unsigned long)mx2fbp->fb_vmem + mx2fbp->fb_len);\n"
- "\t     page += PAGE_SIZE) {\n"
- "#ifdef CONFIG_DMA_NONCOHERENT\n"
- "\t\tSetPageReserved(virt_to_page(CAC_ADDR(page)));\n"
- "#else\n"
- "\t\tSetPageReserved(virt_to_page(page));\n"
- "#endif\n"
- "\t}\n"
- "\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Release memory for framebuffer.\n"
- " * @param info\tframebuffer information pointer\n"
- " */\n"
- "static void _unmap_video_memory(struct fb_info *info)\n"
- "{\n"
- "\tstruct mx2fb_par *mx2fbp = (struct mx2fb_par *)info->par;\n"
- "\tif (mx2fbp->fb_vmem) {\n"
- "\t\tdma_free_noncoherent(info->device, mx2fbp->fb_len, mx2fbp->fb_vmem, mx2fbp->fb_pmem);\n"
- "\t}\n"
- "\tmx2fbp->fb_len = 0;\n"
- "\tmx2fbp->fb_pmem = 0;\n"
- "\tmx2fbp->fb_vmem = 0;\n"
- "\tinfo->screen_base = 0;\n"
- "\tinfo->fix.smem_start = 0;\n"
- "\tinfo->fix.smem_len = 0;\n"
- "\t/* Free DMA of SLCDC transfert */\n"
- "\tdma_pool_free(mx2fbp->cgram_data_dma_pool, (void *)mx2fbp->cgram_data_vaddr, (dma_addr_t) mx2fbp->cgram_data_paddr);\n"
- "\tdma_pool_destroy(mx2fbp->cgram_data_dma_pool);\n"
- "\tmx2fbp->cgram_data_dma_pool = 0;\n"
- "\tmx2fbp->cgram_data_vaddr = 0;\n"
- "\tmx2fbp->cgram_data_paddr = 0;\n"
- "\tmx2fbp->cgram_data_len = 0;\n"
- "\t/* Free DMA of SLCDC transfert */\n"
- "\tdma_pool_free(mx2fbp->cgram_cmd_dma_pool, (void *)mx2fbp->cgram_cmd_vaddr, (dma_addr_t) mx2fbp->cgram_cmd_paddr);\n"
- "\tdma_pool_destroy(mx2fbp->cgram_cmd_dma_pool);\n"
- "\tmx2fbp->cgram_cmd_dma_pool = 0;\n"
- "\tmx2fbp->cgram_cmd_vaddr = 0;\n"
- "\tmx2fbp->cgram_cmd_paddr = 0;\n"
- "\tmx2fbp->cgram_cmd_len = 0;\n"
- "}\n"
- "\n"
- "/*\n"
- " * @brief LCDC interrupt handler\n"
- " */\n"
- "static irqreturn_t mx2fb_isr(int irq, void *dev_id)\n"
- "{\n"
- "\tstruct fb_event event;\n"
- "\tunsigned long status;\n"
- "\n"
- "\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\tstatus &= SLCDC_IRQ_FLAGS_MASK;\n"
- "\n"
- "\tif (status & SLCDC_IRQ_FLAG) {\n"
- "\t\tprintk(\"Oled xfer done : \");\n"
- "\t\tif (status == SLCDC_IRQ_FLAG) {\n"
- "\t\t\tprintk(\"Successful\\n\");\n"
- "\t\t}\n"
- "\t\tif (status & SLCDC_IRQ_TEA_FLAG) {\n"
- "\t\t\tprintk(\"DMA error\\n\");\n"
- "\t\t\tevent.info = &mx2fb_info;\n"
- "\t\t\tatomic_notifier_call_chain(&mx2fb_notifier_list,\n"
- "\t\t\t\t\tFB_EVENT_MXC_DMA_ERROR, &event);\n"
- "\t\t}\n"
- "\t\tif (status & SLCDC_IRQ_UNDRFLOW_FLAG) {\n"
- "\t\t\tprintk(\"Underflow occurs\\n\");\n"
- "\t\t\tevent.info = &mx2fb_info;\n"
- "\t\t\tatomic_notifier_call_chain(&mx2fb_notifier_list,\n"
- "\t\t\t\t\tFB_EVENT_MXC_UNDERFLOW, &event);\n"
- "\t\t}\n"
- "\t}\n"
- "\n"
- "\t/* Write 1 to clear the status */\n"
- "\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\tstatus |= SLCDC_IRQ_FLAGS_MASK;\n"
- "\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t\n"
- "\treturn IRQ_HANDLED;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Config and request LCDC interrupt\n"
- " */\n"
- "static void _request_irq(void)\n"
- "{\n"
- "\tunsigned long status;\n"
- "\tunsigned long flags;\n"
- "\n"
- "\t/* Write 1 to clear the status */\n"
- "\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\tstatus |= SLCDC_IRQ_FLAGS_MASK;\n"
- "\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\n"
- "\tif (request_irq(INT_SLCDC, mx2fb_isr, 0, \"SLCDC\", 0))\n"
- "\t\tpr_info(\"Request LCDC IRQ failed.\\n\");\n"
- "\telse {\n"
- "\t\tspin_lock_irqsave(&mx2fb_notifier_list.lock, flags);\n"
- "\n"
- "\t\t/* Enable interrupt in case client has registered */\n"
- "\t\t//if (mx2fb_notifier_list.head != NULL) {\n"
- "\t\t\t//unsigned long status;\n"
- "\t\t\t//unsigned long ints = MX2FB_INT_EOF;\n"
- "\n"
- "\t\t\t//ints |= MX2FB_INT_GW_EOF;\n"
- "\n"
- "\t\t\t/* Enable interrupt in case client has registered */\n"
- "\t\t\t//if (mx2fb_notifier_list.head != NULL) {\n"
- "\t\t\t\t/* Write 1 to clear the status */\n"
- "\t\t\t\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t\t\t\tstatus |= SLCDC_IRQ_FLAGS_MASK;\n"
- "\t\t\t\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\n"
- "\t\t\t\t/* Enable SLCDC interrupt */\n"
- "\t\t\t\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t\t\t\tstatus |= SLCDC_IRQ_ENABLE;\n"
- "\t\t\t\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t\t\t//}\n"
- "\t\t//}\n"
- "\n"
- "\t\tspin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);\n"
- "\t}\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Free LCDC interrupt handler\n"
- " */\n"
- "static void _free_irq(void)\n"
- "{\n"
- "\tunsigned long status;\n"
- "\tstatus =__raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t/* Write 1 to clear the status */\n"
- "\tstatus |= SLCDC_IRQ_FLAGS_MASK;\n"
- "\t/* Disable all LCDC interrupt */\n"
- "\tstatus &= ~SLCDC_IRQ_ENABLE;\n"
- "\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\n"
- "\tfree_irq(INT_SLCDC, 0);\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Register a client notifier\n"
- " * @param nb\tnotifier block to callback on events\n"
- " */\n"
- "int mx2fb_register_client(struct notifier_block *nb)\n"
- "{\n"
- "\tunsigned long flags, status;\n"
- "\tint ret;\n"
- "\n"
- "\tret = atomic_notifier_chain_register(&mx2fb_notifier_list, nb);\n"
- "\n"
- "\tspin_lock_irqsave(&mx2fb_notifier_list.lock, flags);\n"
- "\n"
- "\t/* Enable interrupt in case client has registered */\n"
- "\tif (mx2fb_notifier_list.head != NULL) {\n"
- "\t\t/* Write 1 to clear the status */\n"
- "\t\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t\tstatus |= SLCDC_IRQ_FLAGS_MASK;\n"
- "\t\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\n"
- "\t\t/* Enable SLCDC interrupt */\n"
- "\t\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t\tstatus |= SLCDC_IRQ_ENABLE;\n"
- "\t\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t}\n"
- "\tspin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);\n"
- "\n"
- "\treturn ret;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Unregister a client notifier\n"
- " * @param nb\tnotifier block to callback on events\n"
- " */\n"
- "int mx2fb_unregister_client(struct notifier_block *nb)\n"
- "{\n"
- "\tunsigned long flags, status;\n"
- "\tint ret;\n"
- "\n"
- "\tret = atomic_notifier_chain_unregister(&mx2fb_notifier_list, nb);\n"
- "\n"
- "\tspin_lock_irqsave(&mx2fb_notifier_list.lock, flags);\n"
- "\n"
- "\t/* Mask interrupt in case no client registered */\n"
- "\tif (mx2fb_notifier_list.head == NULL) {\n"
- "\t\t/* Enable SLCDC interrupt */\n"
- "\t\tstatus = __raw_readl(SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t\tstatus &= ~(SLCDC_IRQ_ENABLE);\n"
- "\t\t__raw_writel(status, SLCDC_REG(SLCDC_SLCDCCTRLSTAT));\n"
- "\t}\n"
- "\n"
- "\tspin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);\n"
- "\n"
- "\treturn ret;\n"
- "}\n"
- "\n"
- "#ifdef CONFIG_PM\n"
- "/*\n"
- " * Power management hooks. Note that we won't be called from IRQ context,\n"
- " * unlike the blank functions above, so we may sleep.\n"
- " */\n"
- "\n"
- "/*!\n"
- " * @brief Suspends the framebuffer and blanks the screen.\n"
- " * Power management support\n"
- " */\n"
- "#ifdef CONFIG_FB_MXC_EPSON_L4F0024\n"
- "static int mx2fb_spi_suspend(struct spi_device *spi, pm_message_t state)\n"
- "{\n"
- "#else\n"
- "static int mx2fb_suspend(struct platform_device *pdev, pm_message_t state)\n"
- "{\n"
- "#endif\n"
- "\t_disable_slcdc(&mx2fb_info);\n"
- "\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Resumes the framebuffer and unblanks the screen.\n"
- " * Power management support\n"
- " */\n"
- "#ifdef CONFIG_FB_MXC_EPSON_L4F0024\n"
- "static int mx2fb_spi_resume(struct spi_device *spi)\n"
- "#else\n"
- "static int mx2fb_resume(struct platform_device *pdev)\n"
- "#endif\n"
- "{\n"
- "\t_enable_slcdc(&mx2fb_info);\n"
- "\treturn 0;\n"
- "}\n"
- "#endif\t\t\t\t/* CONFIG_PM */\n"
- "\n"
- "/*!\n"
- " * @brief Probe routine for the framebuffer driver. It is called during the\n"
- " *        driver binding process.\n"
- " *\n"
- " * @return Appropriate error code to the kernel common code\n"
- " */\n"
- "static int mx2fb_probe(struct platform_device *pdev)\n"
- "{\n"
- "\tint ret;\n"
- "\n"
- "\tslcdc_clk = clk_get(&pdev->dev, \"slcdc_clk\");\n"
- "\tclk_enable(slcdc_clk);\n"
- "\n"
- "\tgpio_slcdc_active();\n"
- "\n"
- "\t/* Memory allocation of display data for DMA transfert */\n"
- "\t/* convert 1 byte / pixel length to 1 byte / column (8 pixels) */\n"
- "\tmx2fbp_bg.cgram_data_len = OLED_WIDTH*OLED_HEIGHT / 8;\n"
- "\t/* Allocate memory for CGRAM mirror with 128k boundary\n"
- "\t * (cf note SLCDC in Ch. 44.2 of i.MX27 RM) aligned on 1 byte */\n"
- "\tmx2fbp_bg.cgram_data_dma_pool = dma_pool_create(\"SLCDC_DMA_DATA\", &pdev->dev, mx2fbp_bg.cgram_data_len, 1, 128*1024);\n"
- "\tif (mx2fbp_bg.cgram_data_dma_pool == NULL) {\n"
- "\t\tdev_err(&pdev->dev, \"Unable to allocated DMA Pool.\\n\");\n"
- "\t\treturn -ENOMEM;\n"
- "\t}\n"
- "\tmx2fbp_bg.cgram_data_vaddr = (unsigned long)dma_pool_alloc(mx2fbp_bg.cgram_data_dma_pool, GFP_DMA | GFP_KERNEL, (dma_addr_t *) &mx2fbp_bg.cgram_data_paddr);\n"
- "\tif ((void *)mx2fbp_bg.cgram_data_vaddr == NULL) {\n"
- "\t\tdev_err(&pdev->dev, \"Unable to allocated DMA memory.\\n\");\n"
- "\t\treturn -ENOMEM;\n"
- "\t}\n"
- "\n"
- "\t/* Memory allocation of display commands for DMA transfert */\n"
- "\t/* a page address on LCD is defined by 3 three commands.\n"
- "\t * Each command must be joined with a byte containing the state\n"
- "\t * of RS pin to apply (cf Fig 44-5 from SLCDC chapter in i.MX27 RM).\n"
- "\t * Array must be defined as unsigned short */\n"
- "\tmx2fbp_bg.cgram_cmd_len = sizeof(_ssd1305_pagecmd_array)/sizeof(_ssd1305_pagecmd_array[0]);\n"
- "\t/* Allocate memory for CGRAM mirror with 128k boundary\n"
- "\t * (cf note SLCDC in Ch. 44.2 of i.MX27 RM) aligned on 2 bytes (array of shorts) */\n"
- "\tmx2fbp_bg.cgram_cmd_dma_pool = dma_pool_create(\"SLCDC_DMA_CMD\", &pdev->dev, mx2fbp_bg.cgram_cmd_len/(sizeof(int)/sizeof(_ssd1305_pagecmd_array[0])), 2, 128*1024);\n"
- "\tif (mx2fbp_bg.cgram_cmd_dma_pool == NULL) {\n"
- "\t\tdev_err(&pdev->dev, \"Unable to allocated DMA Pool.\\n\");\n"
- "\t\treturn -ENOMEM;\n"
- "\t}\n"
- "\tmx2fbp_bg.cgram_cmd_vaddr = (unsigned long)dma_pool_alloc(mx2fbp_bg.cgram_cmd_dma_pool, GFP_DMA | GFP_KERNEL, (dma_addr_t *) &mx2fbp_bg.cgram_cmd_paddr);\n"
- "\tif ((void *)mx2fbp_bg.cgram_cmd_vaddr == NULL) {\n"
- "\t\tdev_err(&pdev->dev, \"Unable to allocated DMA memory.\\n\");\n"
- "\t\treturn -ENOMEM;\n"
- "\t}\n"
- "\n"
- "\tslcdc_first_init();\n"
- "\tdd12832_init_controller();\n"
- "\n"
- "\tret = _install_fb(&mx2fb_info, pdev);\n"
- "\tif (ret) {\n"
- "\t\tdev_err(&pdev->dev,\n"
- "\t\t\t\"Failed to register framebuffer\\n\");\n"
- "\t\treturn ret;\n"
- "\t}\n"
- "\n"
- "\t//_request_irq();\n"
- "\n"
- "\treturn 0;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief This structure contains pointers to the power management\n"
- " * callback functions.\n"
- " */\n"
- "static struct platform_driver mx2fb_driver = {\n"
- "\t.driver = {\n"
- "\t\t   .name = \"mxc_sdc_fb\",\n"
- "\t\t   .owner = THIS_MODULE,\n"
- "\t\t   .bus = &platform_bus_type,\n"
- "\t\t   },\n"
- "\t.probe = mx2fb_probe,\n"
- "\t.suspend = mx2fb_suspend,\n"
- "\t.resume = mx2fb_resume,\n"
- "};\n"
- "\n"
- "/*!\n"
- " * @brief Initialization\n"
- " */\n"
- "int __init mx2fb_init(void)\n"
- "{\n"
- "\tint ret = 0;\n"
- "\tret = platform_driver_register(&mx2fb_driver);\n"
- "\treturn ret;\n"
- "}\n"
- "\n"
- "/*!\n"
- " * @brief Cleanup\n"
- " */\n"
- "void __exit mx2fb_exit(void)\n"
- "{\n"
- "\t_free_irq();\n"
- "\t_uninstall_fb(&mx2fb_info);\n"
- "\n"
- "\tplatform_driver_unregister(&mx2fb_driver);\n"
- "}\n"
- "\n"
- "/* Modularization */\n"
- "module_init(mx2fb_init);\n"
- "module_exit(mx2fb_exit);\n"
- "\n"
- "EXPORT_SYMBOL(mx2_gw_set);\n"
- "EXPORT_SYMBOL(mx2fb_register_client);\n"
- "EXPORT_SYMBOL(mx2fb_unregister_client);\n"
- "\n"
- "MODULE_AUTHOR(\"Freescale Semiconductor, Inc.\");\n"
- "MODULE_DESCRIPTION(\"MX2 framebuffer driver\");\n"
- "MODULE_LICENSE(\"GPL\");"
+ "working draft for test purpose)\n"
+ "-------------- next part --------------\n"
+ "A non-text attachment was scrubbed...\n"
+ "Name: mx2fb-slcd_dd12832_oled.c\n"
+ "Type: text/x-csrc\n"
+ "Size: 35409 bytes\n"
+ "Desc: not available\n"
+ URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120817/ea3df386/attachment-0001.bin>
 
-5c56b6cfaa6792bdbeea2695e99ca95676506187a4bd9c94b79d216892a7093e
+2d05b305da118cb99804ec354d487b68df5db18c98039a680628b51300b06e49

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.