3778 lines
100 KiB
C
3778 lines
100 KiB
C
/*
|
||
* linux/drivers/video/auofb.c -- for AUO epaper frame buffer device
|
||
*
|
||
* Modified by Ivan.Ruan
|
||
*
|
||
* Created 2009/04/01 by Ivan.Ruan
|
||
*
|
||
*
|
||
*
|
||
*/
|
||
|
||
#include <linux/module.h>
|
||
#include <linux/kernel.h>
|
||
#include <linux/errno.h>
|
||
#include <linux/string.h>
|
||
#include <linux/mm.h>
|
||
#include <linux/tty.h>
|
||
#include <linux/slab.h>
|
||
#include <linux/delay.h>
|
||
#include <linux/fb.h>
|
||
#include <linux/init.h>
|
||
#include <linux/dma-mapping.h>
|
||
#include <linux/string.h>
|
||
#include <linux/ioctl.h>
|
||
#include <linux/platform_device.h>
|
||
#include <linux/clk.h>
|
||
|
||
#include <linux/freezer.h>
|
||
|
||
#include <asm/io.h>
|
||
#include <asm/uaccess.h>
|
||
#include <asm/div64.h>
|
||
|
||
#include <linux/auofb_ioctl.h>
|
||
|
||
//#include <asm/mach/map.h>
|
||
#include <asm/arch/regs-lcd.h>
|
||
#include <asm/arch/regs-gpio.h>
|
||
#include <asm/arch/regs-timer.h>
|
||
#include <asm/arch/regs-watchdog.h>
|
||
#include <asm/arch/idle.h>
|
||
#include <asm/arch/regs-s3c2450-clock.h>
|
||
#include "epaper.h"
|
||
#include "auofb.h"
|
||
|
||
#ifdef CONFIG_PM
|
||
#include <linux/pm.h>
|
||
#include <asm/plat-s3c24xx/pm.h>
|
||
#endif
|
||
|
||
#include <asm/io.h>
|
||
#include <linux/platform_device.h>
|
||
|
||
//#define FRAMEBUFFER_DMA
|
||
#define EPD_HW_ROTATE
|
||
//#define EPD_HW_ROTATE_NO_MODE4
|
||
//#define AUOFB_ROTATE
|
||
|
||
#if defined(CONFIG_QISDA_QD060B00) || defined(CONFIG_QISDA_QD060N00_DVT1_1) || defined(CONFIG_QISDA_QD090B00) || defined(CONFIG_QISDA_QD090B00_EVT1)||defined(CONFIG_QISDA_SH060B00)
|
||
#define EPD_ENABLE_PRE_DISPLAY
|
||
#endif
|
||
|
||
#define AUO_LUT_LENGTH 983040 //in bytes
|
||
|
||
#define DPRINTK(x...) printk("AUOFB: " x)
|
||
//#define DPRINTK(x...)
|
||
|
||
#define DEF_DISPLAY_BRIGHTNESS 4
|
||
|
||
#define PIXEL_BPP4 4
|
||
#define PIXEL_BPP8 8
|
||
#define PIXEL_BPP16 16 /* RGB 5-6-5 format for SMDK EVAL BOARD */
|
||
#define PIXEL_BPP24 24 /* RGB 8-8-8 format for SMDK EVAL BOARD */
|
||
|
||
#ifdef FRAMEBUFFER_DMA
|
||
|
||
#define UPDATE_WIDTH_MIN 12
|
||
#define UPDATE_WIDTH_MULTIPLES 4
|
||
#define UPDATE_HEIGHT_MIN 8
|
||
#define UPDATE_HEIGHT_MULTIPLES 4
|
||
|
||
#else
|
||
|
||
#define UPDATE_WIDTH_MIN 12
|
||
#define UPDATE_WIDTH_MULTIPLES 4
|
||
#define UPDATE_HEIGHT_MIN 8
|
||
#define UPDATE_HEIGHT_MULTIPLES 4
|
||
|
||
#endif
|
||
|
||
#ifdef EPD_HW_ROTATE
|
||
|
||
#define H_RESOLUTION AUO_EPAPER_PHYSICAL_V_RESOLUTION
|
||
#define V_RESOLUTION AUO_EPAPER_PHYSICAL_H_RESOLUTION
|
||
|
||
#define H_RESOLUTION_OSD AUO_EPAPER_PHYSICAL_V_RESOLUTION
|
||
#define V_RESOLUTION_OSD AUO_EPAPER_PHYSICAL_H_RESOLUTION
|
||
|
||
#else //SW rotate
|
||
|
||
#ifdef AUOFB_ROTATE
|
||
#define H_RESOLUTION AUO_EPAPER_PHYSICAL_V_RESOLUTION
|
||
#define V_RESOLUTION AUO_EPAPER_PHYSICAL_H_RESOLUTION
|
||
|
||
#define H_RESOLUTION_OSD AUO_EPAPER_PHYSICAL_V_RESOLUTION
|
||
#define V_RESOLUTION_OSD AUO_EPAPER_PHYSICAL_H_RESOLUTION
|
||
|
||
#else //not rotate
|
||
|
||
#define H_RESOLUTION AUO_EPAPER_PHYSICAL_H_RESOLUTION
|
||
#define V_RESOLUTION AUO_EPAPER_PHYSICAL_V_RESOLUTION
|
||
|
||
#define H_RESOLUTION_OSD AUO_EPAPER_PHYSICAL_H_RESOLUTION
|
||
#define V_RESOLUTION_OSD AUO_EPAPER_PHYSICAL_V_RESOLUTION
|
||
#endif
|
||
#endif //#ifdef EPD_HW_ROTATE
|
||
|
||
#define MAX_ALPHA_LEVEL 0x0f
|
||
|
||
#define H_FP 1 /* front porch */
|
||
#define H_SW 1 /* Hsync width */
|
||
#define H_BP 1 /* Back porch */
|
||
|
||
#define V_FP 1 /* front porch */
|
||
#define V_SW 1 /* Vsync width */
|
||
#define V_BP 1 /* Back porch */
|
||
|
||
#define VFRAME_FREQ 1
|
||
#define LCD_PIXEL_CLOCK (VFRAME_FREQ *(H_FP+H_SW+H_BP+H_RESOLUTION) * (V_FP+V_SW+V_BP+V_RESOLUTION))
|
||
#define PIXEL_CLOCK VFRAME_FREQ * LCD_PIXEL_CLOCK /* vclk = frame * pixel_count */
|
||
|
||
#define WINCONx_BIT_SWAP_ON (1<<2) //shift on basis of half-word swap
|
||
#define WINCONx_BYTE_SWAP_ON (1<<1) //shift on basis of half-word swap
|
||
#define WINCONx_HALFW_SWAP_ON (1<<0) //shift on basis of half-word swap
|
||
#define WINCONx_4WORD_BURST (2)
|
||
#define WINCONx_8WORD_BURST (1)
|
||
#define WINCONx_16WORD_BURST (0)
|
||
#define WINCONx_PLANE_BLENDING (0)
|
||
#define WINCONx_PIXEL_BLENDING (1)
|
||
#define WINCONx_1BPP_PALLET (0)
|
||
#define WINCONx_2BPP_PALLET (1)
|
||
#define WINCONx_4BPP_PALLET (2)
|
||
#define WINCONx_8BPP_PALLET (3)
|
||
#define WINCONx_8BPP_NO_PALLET (4)
|
||
#define WINCONx_16BPP_565 (5)
|
||
#define WINCONx_16BPP_A555 (6)
|
||
#define WINCONx_16BPP_1555 (7)
|
||
#define WINCONx_18BPP_666 (8)
|
||
#define WINCONx_18BPP_A665 (9)
|
||
#define WINCONx_19BPP_A666 (10)
|
||
#define WINCONx_24BPP_888 (11)
|
||
#define WINCONx_24BPP_A887 (12)
|
||
#define WINCONx_25BPP_A888 (13)
|
||
#define WINCONx_ALPHA_MODE_0 (0)
|
||
#define WINCONx_ALPHA_MODE_1 (1)
|
||
|
||
//bit shift
|
||
#define WINCON_BUFSEL (23)
|
||
#define WINCON_BUFAUTOEN (22)
|
||
#define WINCON_BIT_SWAP_S (18)
|
||
#define WINCON_BYTE_SWAP_S (17)
|
||
#define WINCON_SWAP_S (16)
|
||
#define WINCON_BURSTLEN_S (9)
|
||
#define WINCON_BLENDING_S (6)
|
||
#define WINCON_BPP_S (2)
|
||
#define WINCON_ALPHA_S (1)
|
||
|
||
//* VIDWxADD2
|
||
//bit shift
|
||
#define VIDWxADD2_OFFSET_SIZE_S (13)
|
||
#define VIDWxADD2_PAGE_WIDTH_S (0)
|
||
|
||
|
||
//* VIDOSDxA,B,C
|
||
//bit shift
|
||
#define VIDOSDxAB_HORIZON_X_S (11)
|
||
#define VIDOSDxAB_VERTICAL_Y_S (0)
|
||
#define VIDOSDxC_ALPHA0_S (12)
|
||
|
||
#define LCD_OFF 0
|
||
#define LCD_ON 1
|
||
|
||
#define LCD_WIN_0 0
|
||
#define LCD_WIN_1 1
|
||
#define LCD_WIN_ALL 2
|
||
|
||
#define LCD_BUF_0 0
|
||
#define LCD_BUF_1 1
|
||
|
||
#if defined(AUO_EPAPER_6_INCH)
|
||
#if defined(EPD_HW_ROTATE)
|
||
#define BOOT_PROGRESS_BAR_X 32
|
||
#define BOOT_PROGRESS_BAR_Y 767
|
||
#define BOOT_PROGRESS_BAR_W (567-32)
|
||
#define BOOT_PROGRESS_BAR_H (784-767)
|
||
#else
|
||
#define BOOT_PROGRESS_BAR_X 203
|
||
#define BOOT_PROGRESS_BAR_Y 95
|
||
#define BOOT_PROGRESS_BAR_W 8
|
||
#define BOOT_PROGRESS_BAR_H 413
|
||
#endif
|
||
#ifdef CONFIG_RESCUEOS_BUILD
|
||
#define BOOT_PROGRESS_BAR_DELAY_TIME 100 //2 sec = 420
|
||
#else
|
||
#define BOOT_PROGRESS_BAR_DELAY_TIME 250 //2 sec = 420
|
||
#endif
|
||
#else
|
||
#if defined(EPD_HW_ROTATE)
|
||
#define BOOT_PROGRESS_BAR_X 121
|
||
#define BOOT_PROGRESS_BAR_Y 259
|
||
#define BOOT_PROGRESS_BAR_W 528
|
||
#define BOOT_PROGRESS_BAR_H 8
|
||
#else
|
||
#define BOOT_PROGRESS_BAR_X 259
|
||
#define BOOT_PROGRESS_BAR_Y 119
|
||
#define BOOT_PROGRESS_BAR_W 8
|
||
#define BOOT_PROGRESS_BAR_H 531
|
||
#endif
|
||
#define BOOT_PROGRESS_BAR_DELAY_TIME 250
|
||
#endif
|
||
//test time
|
||
struct timeval now;
|
||
suseconds_t diff;
|
||
|
||
//var
|
||
int pre_mode=0;
|
||
static int delayLoopCount;
|
||
int display_brightness = DEF_DISPLAY_BRIGHTNESS;
|
||
|
||
static int picnum=0;;
|
||
static int Initialize = 0;
|
||
|
||
static unsigned long update_display_timeout = (1600*2); //1600 about 1s
|
||
static pid_t update_display_pid = 0;
|
||
static wait_queue_head_t update_display_wq;
|
||
static DECLARE_COMPLETION(update_display_thread_exited);
|
||
|
||
static pid_t boot_progress_bar_pid = 0;
|
||
static wait_queue_head_t boot_progress_bar_wq;
|
||
static DECLARE_COMPLETION(boot_progress_bar_thread_exited);
|
||
|
||
static unsigned short u16Temperature = 0;
|
||
static unsigned short u16EPDType = 0;
|
||
static unsigned short u16PanelType = 0;
|
||
static unsigned short u16LUTVersion = 0;
|
||
|
||
static unsigned short u16PrevMode = 0;
|
||
static unsigned long u32PowerState = EN_EPD_DEVICE_POWER_STATE_D0;
|
||
/*
|
||
u32FullUpdateThreshold:
|
||
0 ~ (AUO_EPAPER_PHYSICAL_V_RESOLUTION*AUO_EPAPER_PHYSICAL_H_RESOLUTION)
|
||
0: Always full screen update
|
||
AUO_EPAPER_PHYSICAL_V_RESOLUTION*AUO_EPAPER_PHYSICAL_H_RESOLUTION: update region is depand on partial_info
|
||
*/
|
||
static unsigned long u32FullUpdateThreshold = (AUO_EPAPER_PHYSICAL_V_RESOLUTION*AUO_EPAPER_PHYSICAL_H_RESOLUTION);
|
||
|
||
DECLARE_MUTEX(auofb_lock);
|
||
|
||
struct auo_fb_info info;
|
||
static unsigned char* pu8Framebuffer = NULL;
|
||
static unsigned short* pu16Translatebuffer = NULL;
|
||
static unsigned char* pu8RotateBuffer = NULL;
|
||
|
||
u_char * cpu_VideoPhysicalTemp_f1;
|
||
dma_addr_t map_VideoPhysicalTemp_f1;
|
||
|
||
typedef struct partial_update_info
|
||
{
|
||
int mode;
|
||
int x;
|
||
int y;
|
||
int w;
|
||
int h;
|
||
unsigned short u16EpaperCommand;
|
||
}_partial_update_info;
|
||
|
||
//_partial_update_info partial_info;
|
||
_partial_update_info w_partial_info;
|
||
_partial_update_info r_partial_info;
|
||
#define PARTIAL_INFO_QUEUE_SIZE 50
|
||
_partial_update_info partial_info_queue[PARTIAL_INFO_QUEUE_SIZE];
|
||
static int pr=0;
|
||
static int pw=0;
|
||
|
||
#if defined(EPD_ENABLE_PRE_DISPLAY)
|
||
atomic_t gPowerOnFirstDisplay = ATOMIC_INIT(0); // to identify if a screen update is the first update after power on
|
||
#endif
|
||
|
||
struct auo_fb_mach_info auo_mach_info = {
|
||
|
||
//Video control 0 register,
|
||
.vidcon0= S3C_VIDCON0_VIDOUT_RGB_IF | S3C_VIDCON0_PNRMODE_RGB_P | S3C_VIDCON0_CLKDIR_DIVIDED | S3C_VIDCON0_VCLKEN_ENABLE |S3C_VIDCON0_CLKSEL_F_HCLK,
|
||
.vidcon1= S3C_VIDCON1_IHSYNC_INVERT | S3C_VIDCON1_IVSYNC_INVERT,
|
||
|
||
//Video time control 0 register
|
||
.vidtcon0= S3C_VIDTCON0_VBPD(V_BP-1) | S3C_VIDTCON0_VFPD(V_FP-1) | S3C_VIDTCON0_VSPW(V_SW-1),
|
||
.vidtcon1= S3C_VIDTCON1_HBPD(H_BP-1) | S3C_VIDTCON1_HFPD(H_FP-1 ) | S3C_VIDTCON1_HSPW(H_SW-1),
|
||
|
||
|
||
.vidtcon2= S3C_VIDTCON2_LINEVAL(V_RESOLUTION-1) | S3C_VIDTCON2_HOZVAL(H_RESOLUTION-1),
|
||
|
||
|
||
// Window control 0 register, 4 bpp
|
||
.wincon0= S3C_WINCONx_HAWSWP_ENABLE | S3C_WINCONx_BURSTLEN_4WORD | (2<<2),
|
||
.wincon1= S3C_WINCONx_HAWSWP_ENABLE | S3C_WINCONx_BURSTLEN_4WORD | S3C_WINCONx_BPPMODE_F_16BPP_565 | S3C_WINCONx_BLD_PIX_PLANE | S3C_WINCONx_ALPHA_SEL_1, // 4word burst, 16bpp for OSD
|
||
|
||
//Video Window 0, 1<><31>s position control register
|
||
.vidosd0a= S3C_VIDOSDxA_OSD_LTX_F(0) | S3C_VIDOSDxA_OSD_LTY_F(0),
|
||
.vidosd0b= S3C_VIDOSDxB_OSD_RBX_F(H_RESOLUTION-1) | S3C_VIDOSDxB_OSD_RBY_F(V_RESOLUTION-1),
|
||
|
||
.vidosd1a= S3C_VIDOSDxA_OSD_LTX_F(0) | S3C_VIDOSDxA_OSD_LTY_F(0),
|
||
.vidosd1b= S3C_VIDOSDxB_OSD_RBX_F(H_RESOLUTION_OSD-1) | S3C_VIDOSDxB_OSD_RBY_F(V_RESOLUTION_OSD-1),
|
||
.vidosd1c= S3C_VIDOSDxC_ALPHA1_B(MAX_ALPHA_LEVEL) | S3C_VIDOSDxC_ALPHA1_G(MAX_ALPHA_LEVEL) |S3C_VIDOSDxC_ALPHA1_R(MAX_ALPHA_LEVEL),
|
||
|
||
//Indicate the Video interrupt control register
|
||
.vidintcon= S3C_VIDINTCON0_FRAMESEL0_VSYNC | S3C_VIDINTCON0_FRAMESEL1_NONE | S3C_VIDINTCON0_INTFRMEN_ENABLE | S3C_VIDINTCON0_INTEN_ENABLE,
|
||
|
||
|
||
.width= H_RESOLUTION,
|
||
.height= V_RESOLUTION,
|
||
.xres= H_RESOLUTION,
|
||
.yres= V_RESOLUTION,
|
||
|
||
.xoffset= 0,
|
||
.yoffset= 0,
|
||
|
||
|
||
.xres_virtual = H_RESOLUTION,
|
||
.yres_virtual = V_RESOLUTION,
|
||
|
||
|
||
.osd_width= H_RESOLUTION_OSD,
|
||
.osd_height= V_RESOLUTION_OSD,
|
||
.osd_xres= H_RESOLUTION_OSD,
|
||
.osd_yres= V_RESOLUTION_OSD,
|
||
|
||
.osd_xres_virtual= H_RESOLUTION_OSD,
|
||
.osd_yres_virtual= V_RESOLUTION_OSD,
|
||
|
||
|
||
//Ivan
|
||
.bpp= PIXEL_BPP16,
|
||
.bytes_per_pixel= 2,
|
||
|
||
/*
|
||
#if defined (CONFIG_FB_BPP_8)
|
||
.bpp= PIXEL_BPP8,
|
||
.bytes_per_pixel= 1,
|
||
#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
|
||
.wpalcon= W0PAL_24BIT,
|
||
#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
|
||
.wpalcon= W0PAL_16BIT,
|
||
#endif
|
||
#elif defined (CONFIG_FB_BPP_16)
|
||
.bpp= PIXEL_BPP16,
|
||
.bytes_per_pixel= 2,
|
||
|
||
#elif defined (CONFIG_FB_BPP_24)
|
||
.bpp= PIXEL_BPP24,
|
||
.bytes_per_pixel= 4,
|
||
|
||
#endif
|
||
*/
|
||
.pixclock= PIXEL_CLOCK,
|
||
|
||
//Color key control register
|
||
.w1keycon0= S3C_WxKEYCON0_KEYBLEN_DISABLE | S3C_WxKEYCON0_KEYEN_F_DISABLE | S3C_WxKEYCON0_DIRCON_MATCH_FG_IMAGE |
|
||
S3C_WxKEYCON0_COMPKEY(0x0),
|
||
.w1keycon1= S3C_WxKEYCON1_COLVAL(0xffffff),
|
||
.w2keycon0= S3C_WxKEYCON0_KEYBLEN_DISABLE | S3C_WxKEYCON0_KEYEN_F_DISABLE | S3C_WxKEYCON0_DIRCON_MATCH_FG_IMAGE |
|
||
S3C_WxKEYCON0_COMPKEY(0x0),
|
||
.w2keycon1= S3C_WxKEYCON1_COLVAL(0xffffff),
|
||
.w3keycon0= S3C_WxKEYCON0_KEYBLEN_DISABLE | S3C_WxKEYCON0_KEYEN_F_DISABLE | S3C_WxKEYCON0_DIRCON_MATCH_FG_IMAGE |
|
||
S3C_WxKEYCON0_COMPKEY(0x0),
|
||
.w3keycon1= S3C_WxKEYCON1_COLVAL(0xffffff),
|
||
.w4keycon0= S3C_WxKEYCON0_KEYBLEN_DISABLE | S3C_WxKEYCON0_KEYEN_F_DISABLE | S3C_WxKEYCON0_DIRCON_MATCH_FG_IMAGE |
|
||
S3C_WxKEYCON0_COMPKEY(0x0),
|
||
.w4keycon1= S3C_WxKEYCON1_COLVAL(0xffffff),
|
||
|
||
|
||
.hsync_len= H_SW,
|
||
.vsync_len= V_SW,
|
||
|
||
.left_margin= H_FP,
|
||
.upper_margin= V_FP,
|
||
.right_margin= H_BP,
|
||
.lower_margin= V_BP,
|
||
|
||
.sync= 0,
|
||
.cmap_static= 1,
|
||
};
|
||
|
||
struct semaphore vma_list_semaphore;
|
||
|
||
struct fb_vma_list_entry {
|
||
struct list_head list;
|
||
struct vm_area_struct *vma;
|
||
};
|
||
|
||
static unsigned long videomemorysize;
|
||
struct page **videopages;
|
||
static int numpages;
|
||
|
||
LIST_HEAD(vma_list);
|
||
|
||
static bool isInitial = false;
|
||
static bool isReady = true;
|
||
|
||
static bool update_ready = false;
|
||
|
||
T_DISPLAY_FRAME gStDisFrame;
|
||
|
||
//timer
|
||
static struct work_struct workq_panel_update;
|
||
static struct timer_list panel_timer_qisda;
|
||
static void panel_timer_handler_qisda(unsigned long data) { schedule_work(&workq_panel_update); }
|
||
|
||
|
||
static int lock_auofb_entry(char *function_name);
|
||
static void lock_auofb_exit(char *function_name);
|
||
static bool auofb_update_queue_put(_partial_update_info put_region);
|
||
static bool auofb_update_queue_get(_partial_update_info* get_region);
|
||
static bool auofb_update_queue_is_empty(void);
|
||
static bool auofb_update_queue_is_full(void);
|
||
static void auofb_rotate_RGB565(unsigned short w, unsigned short h, unsigned short* src_data, unsigned short* dst_data);
|
||
static void auofb_convert_RGB565(unsigned short w, unsigned short h, unsigned short* src_data, unsigned short* dst_data);
|
||
static int update_display_thread(void *unused);
|
||
static void start_update_display_thread(void);
|
||
static void stop_update_display_thread(void);
|
||
static panel_update_workqueue(struct work_struct *work);
|
||
static void wake_update_display_thread(void);
|
||
static int auo_fb_is_update_region_legal(void);
|
||
|
||
#define LOCK_AUOFB_ENTRY() lock_auofb_entry((char *)__FUNCTION__)
|
||
#define LOCK_AUOFB_EXIT() lock_auofb_exit((char *)__FUNCTION__)
|
||
|
||
static int lock_auofb_entry(char *function_name)
|
||
{
|
||
int result = 0;
|
||
|
||
//DPRINTK("%s(pid=%d) getting lock...\n", function_name, (int)sys_getpid());
|
||
|
||
// Did we get the lock?
|
||
//
|
||
if ( down_interruptible(&auofb_lock) )
|
||
//if ( down(&auofb_lock) )
|
||
{
|
||
DPRINTK("%s(pid=%d) COULD NOT get lock...\n", function_name, (int)sys_getpid());
|
||
result = -ERESTARTSYS;
|
||
}
|
||
else
|
||
{
|
||
;
|
||
DPRINTK("%s(pid=%d) got lock...\n", function_name, (int)sys_getpid());
|
||
}
|
||
|
||
// No, release it.
|
||
//
|
||
if ( result )
|
||
up(&auofb_lock);
|
||
|
||
return ( result );
|
||
}
|
||
|
||
static void lock_auofb_exit(char *function_name)
|
||
{
|
||
up(&auofb_lock);
|
||
//DPRINTK("%s(pid=%d) released lock...\n", function_name, (int)sys_getpid());
|
||
}
|
||
|
||
static bool auofb_update_queue_put(_partial_update_info put_region)
|
||
{
|
||
#if defined(EPD_ENABLE_PRE_DISPLAY)
|
||
// { workaround for MMI first update not using mode 0 after T-Con power on + pre display cmd
|
||
if ((atomic_read(&gPowerOnFirstDisplay ) == 1))
|
||
{
|
||
if(put_region.mode == 0)
|
||
{
|
||
put_region.mode = 1;
|
||
}
|
||
|
||
atomic_set(&gPowerOnFirstDisplay, 0);
|
||
}
|
||
// } workaround for MMI first update not using mode 0 after T-Con power on + pre display cmd
|
||
#endif
|
||
|
||
partial_info_queue[pw] = put_region;
|
||
pw++;
|
||
pw%=PARTIAL_INFO_QUEUE_SIZE;
|
||
return true;
|
||
}
|
||
|
||
static bool auofb_update_queue_get(_partial_update_info* get_region)
|
||
{
|
||
*get_region = partial_info_queue[pr];
|
||
pr++;
|
||
pr%=PARTIAL_INFO_QUEUE_SIZE;
|
||
return true;
|
||
}
|
||
|
||
static bool auofb_update_queue_is_empty(void)
|
||
{
|
||
if(pr == pw)
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
static bool auofb_update_queue_is_full(void)
|
||
{
|
||
if(((pw+1)%PARTIAL_INFO_QUEUE_SIZE) == pr)
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
|
||
static void auofb_rotate_RGB565(unsigned short w, unsigned short h, unsigned short* src_data, unsigned short* dst_data)
|
||
{
|
||
int i,j;
|
||
for(i=0; i< w; i++)
|
||
{
|
||
for(j=0; j< h; j++)
|
||
{
|
||
//printf("%d -%d\n", i * h + j, j * w + (w - i - 1));
|
||
dst_data[i * h + j] = src_data[j * w + (w - i - 1)];
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
#if defined(EPD_ENABLE_PRE_DISPLAY)
|
||
/* RGB table for RGB 565 */
|
||
unsigned short u16TableR[] =
|
||
{
|
||
0,
|
||
77,
|
||
154,
|
||
231,
|
||
308,
|
||
385,
|
||
462,
|
||
539,
|
||
616,
|
||
693,
|
||
770,
|
||
847,
|
||
924,
|
||
1001,
|
||
1078,
|
||
1155,
|
||
1232,
|
||
1309,
|
||
1386,
|
||
1463,
|
||
1540,
|
||
1617,
|
||
1694,
|
||
1771,
|
||
1848,
|
||
1925,
|
||
2002,
|
||
2079,
|
||
2156,
|
||
2233,
|
||
2310,
|
||
2387
|
||
};
|
||
|
||
unsigned short u16TableG[] =
|
||
{
|
||
0,
|
||
151,
|
||
302,
|
||
453,
|
||
604,
|
||
755,
|
||
906,
|
||
1057,
|
||
1208,
|
||
1359,
|
||
1510,
|
||
1661,
|
||
1812,
|
||
1963,
|
||
2114,
|
||
2265,
|
||
2416,
|
||
2567,
|
||
2718,
|
||
2869,
|
||
3020,
|
||
3171,
|
||
3322,
|
||
3473,
|
||
3624,
|
||
3775,
|
||
3926,
|
||
4077,
|
||
4228,
|
||
4379,
|
||
4530,
|
||
4681,
|
||
4832,
|
||
4983,
|
||
5134,
|
||
5285,
|
||
5436,
|
||
5587,
|
||
5738,
|
||
5889,
|
||
6040,
|
||
6191,
|
||
6342,
|
||
6493,
|
||
6644,
|
||
6795,
|
||
6946,
|
||
7097,
|
||
7248,
|
||
7399,
|
||
7550,
|
||
7701,
|
||
7852,
|
||
8003,
|
||
8154,
|
||
8305,
|
||
8456,
|
||
8607,
|
||
8758,
|
||
8909,
|
||
9060,
|
||
9211,
|
||
9362,
|
||
9513
|
||
};
|
||
|
||
unsigned short u16TableB[] =
|
||
{
|
||
0,
|
||
28,
|
||
56,
|
||
84,
|
||
112,
|
||
140,
|
||
168,
|
||
196,
|
||
224,
|
||
252,
|
||
280,
|
||
308,
|
||
336,
|
||
364,
|
||
392,
|
||
420,
|
||
448,
|
||
476,
|
||
504,
|
||
532,
|
||
560,
|
||
588,
|
||
616,
|
||
644,
|
||
672,
|
||
700,
|
||
728,
|
||
756,
|
||
784,
|
||
812,
|
||
840,
|
||
868
|
||
};
|
||
|
||
static void auofb_convert_RGB565(unsigned short w, unsigned short h, unsigned short* src_data, unsigned short* dst_data)
|
||
{
|
||
int i;
|
||
int length = w*h*auo_mach_info.bytes_per_pixel/8;
|
||
|
||
|
||
unsigned short u16val1, u16val2, u16val3, u16val4;
|
||
unsigned short u8R, u8G, u8B;
|
||
|
||
unsigned short* pu16TranslatePtr = dst_data;
|
||
unsigned short* pu16ProcessPtr = src_data;
|
||
unsigned short u16Pixel;
|
||
|
||
|
||
// printk("*** +%s\n", __func__);
|
||
|
||
for(i=0;i<length;i++)
|
||
{
|
||
// 1st pixel
|
||
u16Pixel = *(pu16ProcessPtr + 0);
|
||
u8R = ((u16Pixel & 0xF800) >> auo_fb_rgb_16.red.offset);
|
||
u8G = ((u16Pixel & 0x07E0) >> (auo_fb_rgb_16.green.offset+1));
|
||
u8B = ((u16Pixel & 0x001F) >> auo_fb_rgb_16.blue.offset);
|
||
|
||
|
||
u16val1 = (u16TableR[u8R] + u16TableG[u8G] + u16TableB[u8B]) >> 9;
|
||
|
||
|
||
// 2nd pixel
|
||
u16Pixel = *(pu16ProcessPtr + 1);
|
||
u8R = ((u16Pixel & 0xF800) >> auo_fb_rgb_16.red.offset);
|
||
u8G = ((u16Pixel & 0x07E0) >> (auo_fb_rgb_16.green.offset+1));
|
||
u8B = ((u16Pixel & 0x001F) >> auo_fb_rgb_16.blue.offset);
|
||
|
||
u16val2 = (u16TableR[u8R] + u16TableG[u8G] + u16TableB[u8B]) >> 5;
|
||
|
||
|
||
// 3rd pixel
|
||
u16Pixel = *(pu16ProcessPtr + 2);
|
||
u8R = ((u16Pixel & 0xF800) >> auo_fb_rgb_16.red.offset);
|
||
u8G = ((u16Pixel & 0x07E0) >> (auo_fb_rgb_16.green.offset+1));
|
||
u8B = ((u16Pixel & 0x001F) >> auo_fb_rgb_16.blue.offset);
|
||
|
||
u16val3 = (u16TableR[u8R] + u16TableG[u8G] + u16TableB[u8B]) >> 1;
|
||
|
||
|
||
// 4th pixel
|
||
u16Pixel = *(pu16ProcessPtr + 3);
|
||
u8R = ((u16Pixel & 0xF800) >> auo_fb_rgb_16.red.offset);
|
||
u8G = ((u16Pixel & 0x07E0) >> (auo_fb_rgb_16.green.offset+1));
|
||
u8B = ((u16Pixel & 0x001F) >> auo_fb_rgb_16.blue.offset);
|
||
|
||
u16val4 = (u16TableR[u8R] + u16TableG[u8G] + u16TableB[u8B]) << 3;
|
||
|
||
*pu16TranslatePtr = ( ( (u16val4) & 0xF000)
|
||
| ( (u16val3) & 0x0F00)
|
||
| ( (u16val2) & 0x00F0)
|
||
| ( (u16val1) & 0x000F) );
|
||
|
||
pu16TranslatePtr++;
|
||
pu16ProcessPtr = pu16ProcessPtr + 4;
|
||
}
|
||
// printk("*** -%s\n", __func__);
|
||
}
|
||
|
||
#else
|
||
static void auofb_convert_RGB565(unsigned short w, unsigned short h, unsigned short* src_data, unsigned short* dst_data)
|
||
{
|
||
int i;
|
||
unsigned short u16val;
|
||
|
||
unsigned short* pu16TranslatePtr = dst_data;
|
||
unsigned short* pu16ProcessPtr = src_data;
|
||
|
||
for(i=0;i<(w*h*auo_mach_info.bytes_per_pixel/8);i++)
|
||
{
|
||
*pu16TranslatePtr = 0;
|
||
|
||
// 1st pixel
|
||
u16val = ((((*pu16ProcessPtr & 0xF800) >> auo_fb_rgb_16.red.offset)*77 +
|
||
((*pu16ProcessPtr & 0x07E0) >> (auo_fb_rgb_16.green.offset+1))*151 +
|
||
((*pu16ProcessPtr & 0x1F) >> auo_fb_rgb_16.blue.offset)*28)>>8 >>1);
|
||
|
||
*pu16TranslatePtr = (*pu16TranslatePtr) | (u16val & 0x000F);
|
||
|
||
// 2nd pixel
|
||
u16val = ((((*(pu16ProcessPtr+1) & 0xF800) >> auo_fb_rgb_16.red.offset)*77 +
|
||
((*(pu16ProcessPtr+1) & 0x07E0) >> (auo_fb_rgb_16.green.offset+1))*151 +
|
||
((*(pu16ProcessPtr+1) & 0x1F) >> auo_fb_rgb_16.blue.offset)*28)>>8 >>1);
|
||
|
||
*pu16TranslatePtr = (*pu16TranslatePtr) | ((u16val<<4) & 0x00F0);
|
||
|
||
// 3rd pixel
|
||
u16val = ((((*(pu16ProcessPtr+2) & 0xF800) >> auo_fb_rgb_16.red.offset)*77 +
|
||
((*(pu16ProcessPtr+2) & 0x07E0) >>(auo_fb_rgb_16.green.offset+1))*151 +
|
||
((*(pu16ProcessPtr+2) & 0x1F) >> auo_fb_rgb_16.blue.offset)*28)>>8>>1);
|
||
|
||
*pu16TranslatePtr = (*pu16TranslatePtr) | ((u16val<<8) & 0x0F00);
|
||
|
||
// 4th pixel
|
||
u16val = ((((*(pu16ProcessPtr+3) & 0xF800) >> auo_fb_rgb_16.red.offset)*77 +
|
||
((*(pu16ProcessPtr+3) & 0x07E0) >> (auo_fb_rgb_16.green.offset+1))*151 +
|
||
((*(pu16ProcessPtr+3) & 0x1F) >> auo_fb_rgb_16.blue.offset)*28)>>8>>1);
|
||
|
||
*pu16TranslatePtr = (*pu16TranslatePtr) | ((u16val<<12) & 0xF000);
|
||
|
||
pu16TranslatePtr++;
|
||
pu16ProcessPtr = pu16ProcessPtr+4;
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
}
|
||
#endif
|
||
|
||
static void auofb_basic_display_setting( unsigned long win_num,unsigned long buf_num)
|
||
{
|
||
unsigned long screenwidth_in_byte=0,offsize_in_byte=0;
|
||
unsigned long offsize;
|
||
unsigned long tmp=0;
|
||
|
||
|
||
screenwidth_in_byte = H_RESOLUTION*4/8;
|
||
|
||
if((screenwidth_in_byte%64)!=0) //64 is depanded on WINCONx_16WORD_BURST
|
||
{
|
||
screenwidth_in_byte += 64 - (screenwidth_in_byte%64);
|
||
}
|
||
|
||
offsize =0;
|
||
offsize_in_byte = offsize*8/8;
|
||
|
||
// WINCON0/1
|
||
tmp = (0<<WINCON_BUFSEL)|(0<<WINCON_BUFAUTOEN)|(1<<WINCON_SWAP_S)|(0<<WINCON_BURSTLEN_S)|(5<<WINCON_BPP_S);
|
||
__raw_writel(tmp, S3C_WINCON0);
|
||
|
||
// WIN0/1 OSD(top)
|
||
tmp = (0<<VIDOSDxAB_HORIZON_X_S)|(0);
|
||
__raw_writel(tmp, S3C_VIDOSD0A);
|
||
|
||
// WIN0/1 OSD(bottom)
|
||
tmp = (((H_RESOLUTION)-1)<<VIDOSDxAB_HORIZON_X_S)|((V_RESOLUTION/4)-1);
|
||
__raw_writel(tmp, S3C_VIDOSD0B);
|
||
|
||
|
||
//=================
|
||
cpu_VideoPhysicalTemp_f1 = dma_alloc_writecombine(info.dev, H_RESOLUTION*V_RESOLUTION/2,
|
||
&map_VideoPhysicalTemp_f1, GFP_KERNEL);
|
||
memset(cpu_VideoPhysicalTemp_f1, 0xFF, H_RESOLUTION*V_RESOLUTION/2);
|
||
//=================
|
||
|
||
// WIN0/1 buffer start address
|
||
__raw_writel((unsigned long)map_VideoPhysicalTemp_f1, S3C_VIDW00ADD0B0);
|
||
|
||
// WIN0/1 buffer end address
|
||
__raw_writel((unsigned long)map_VideoPhysicalTemp_f1 + (screenwidth_in_byte+offsize_in_byte)*(V_RESOLUTION), S3C_VIDW00ADD1B0);
|
||
|
||
// WIN0/1 buffer size
|
||
__raw_writel((offsize_in_byte<<VIDWxADD2_OFFSET_SIZE_S)|screenwidth_in_byte, S3C_VIDW00ADD2B0);
|
||
|
||
__raw_writel(0, S3C_WIN0MAP);
|
||
|
||
//if (win_num>0)
|
||
{
|
||
__raw_writel(0, S3C_VIDOSD1C);
|
||
__raw_writel(0, S3C_W1KEYCON0);
|
||
__raw_writel(0, S3C_W1KEYCON1);
|
||
|
||
}
|
||
}
|
||
|
||
|
||
static void auofb_display_setting( unsigned long win_num,unsigned long buf_num, unsigned short x, unsigned short y, unsigned short w, unsigned short h)
|
||
{
|
||
unsigned long screenwidth_in_byte=0,offsize_in_byte=0;
|
||
unsigned long offsize;
|
||
unsigned long tmp=0;
|
||
|
||
printk("\n(%d, %d, %d, %d)\n", x,y,w,h);
|
||
screenwidth_in_byte = w*4/8;
|
||
|
||
if((screenwidth_in_byte%16)!=0) //16 is depanded on WINCONx_16WORD_BURST
|
||
{
|
||
screenwidth_in_byte += 16 - (screenwidth_in_byte%16);
|
||
}
|
||
|
||
offsize =0;
|
||
offsize_in_byte = offsize*8/8;
|
||
|
||
// WINCON0/1
|
||
|
||
tmp = (0<<WINCON_BUFSEL)|(0<<WINCON_BUFAUTOEN)|(0<<WINCON_BIT_SWAP_S)|(0<<WINCON_BYTE_SWAP_S)|(1<<WINCON_SWAP_S)|(WINCONx_4WORD_BURST<<WINCON_BURSTLEN_S)|(5<<WINCON_BPP_S);
|
||
|
||
__raw_writel(tmp, S3C_WINCON0);
|
||
|
||
// WIN0/1 OSD(top)
|
||
tmp = ((0)<<VIDOSDxAB_HORIZON_X_S)|(0);
|
||
__raw_writel(tmp, S3C_VIDOSD0A);
|
||
|
||
// WIN0/1 OSD(bottom)
|
||
tmp = (((w-1))<<VIDOSDxAB_HORIZON_X_S)|((h-1));
|
||
__raw_writel(tmp, S3C_VIDOSD0B);
|
||
|
||
|
||
// WIN0/1 buffer start address
|
||
__raw_writel((unsigned long)map_VideoPhysicalTemp_f1, S3C_VIDW00ADD0B0);
|
||
|
||
// WIN0/1 buffer end address
|
||
__raw_writel((unsigned long)map_VideoPhysicalTemp_f1 + (screenwidth_in_byte+offsize_in_byte)*(h), S3C_VIDW00ADD1B0);
|
||
|
||
// WIN0/1 buffer size
|
||
__raw_writel((offsize_in_byte<<VIDWxADD2_OFFSET_SIZE_S)|screenwidth_in_byte, S3C_VIDW00ADD2B0);
|
||
|
||
}
|
||
|
||
|
||
static void auofb_LcdEnvidOnOff(unsigned char onoff)
|
||
{
|
||
unsigned long tmp = 0;
|
||
|
||
if(onoff==LCD_ON)
|
||
{
|
||
tmp = __raw_readl(S3C_VIDCON0);
|
||
tmp |= (3);
|
||
__raw_writel(tmp, S3C_VIDCON0);
|
||
|
||
}
|
||
else
|
||
{
|
||
tmp = __raw_readl(S3C_VIDCON0);
|
||
tmp &= (~1);
|
||
__raw_writel(tmp, S3C_VIDCON0);
|
||
|
||
__raw_writel((1<<0), S3C_CPUTRIGCON2);
|
||
|
||
|
||
while( 1) // Check end of frame
|
||
{
|
||
tmp = __raw_readl(S3C_VIDCON0);
|
||
|
||
if(!(tmp&1))
|
||
break;
|
||
|
||
msleep(20);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
static void auofb_LcdWindowOnOff(unsigned char num, unsigned char onoff)
|
||
{
|
||
unsigned long tmp = 0;
|
||
switch(num)
|
||
{
|
||
case LCD_WIN_0:
|
||
if(onoff==LCD_ON)
|
||
{
|
||
tmp = __raw_readl(S3C_WINCON0);
|
||
tmp |= 0x01;
|
||
__raw_writel(tmp, S3C_WINCON0);
|
||
}
|
||
else
|
||
{
|
||
tmp = __raw_readl(S3C_WINCON0);
|
||
tmp &= ~0x01;
|
||
__raw_writel(tmp, S3C_WINCON0);
|
||
}
|
||
break;
|
||
|
||
case LCD_WIN_1:
|
||
if(onoff==LCD_ON)
|
||
{
|
||
tmp = __raw_readl(S3C_WINCON1);
|
||
tmp |= 0x01;
|
||
__raw_writel(tmp, S3C_WINCON1);
|
||
}
|
||
else
|
||
{
|
||
tmp = __raw_readl(S3C_WINCON1);
|
||
tmp &= ~0x01;
|
||
__raw_writel(tmp, S3C_WINCON1);
|
||
}
|
||
break;
|
||
|
||
case LCD_WIN_ALL:
|
||
if(onoff==LCD_ON)
|
||
{
|
||
tmp = __raw_readl(S3C_WINCON0);
|
||
tmp |= 0x01;
|
||
__raw_writel(tmp, S3C_WINCON0);
|
||
|
||
tmp = __raw_readl(S3C_WINCON1);
|
||
tmp |= 0x01;
|
||
__raw_writel(tmp, S3C_WINCON1);
|
||
}
|
||
else
|
||
{
|
||
tmp = __raw_readl(S3C_WINCON0);
|
||
tmp &= ~0x01;
|
||
__raw_writel(tmp, S3C_WINCON0);
|
||
|
||
tmp = __raw_readl(S3C_WINCON1);
|
||
tmp &= ~0x01;
|
||
__raw_writel(tmp, S3C_WINCON1);
|
||
}
|
||
|
||
default:
|
||
break;
|
||
}
|
||
return;
|
||
}
|
||
|
||
static void auofb_Display_Start(char win_num) // 0: LCD_WIN_0, 1: LCD_WIN_1, 2: LCD_WIN_ALL
|
||
{
|
||
auofb_LcdWindowOnOff(win_num,LCD_ON);
|
||
auofb_LcdEnvidOnOff(LCD_ON);
|
||
|
||
#if defined(EPD_ENABLE_PRE_DISPLAY)
|
||
mdelay(1);
|
||
#else
|
||
msleep(1);
|
||
#endif
|
||
|
||
__raw_writel((1<<0), S3C_CPUTRIGCON2);
|
||
|
||
|
||
|
||
return;
|
||
}
|
||
|
||
static void auofb_Display_End(unsigned char win_num)
|
||
{
|
||
|
||
auofb_LcdWindowOnOff(win_num,LCD_OFF);
|
||
auofb_LcdEnvidOnOff(LCD_OFF);
|
||
|
||
return;
|
||
}
|
||
|
||
static void auofb_Disp(T_DISPLAY_FRAME tmpDispFrame)
|
||
{
|
||
#ifdef FRAMEBUFFER_DMA
|
||
int get_mode = Epaper_Get_Partial_Update_Mode();
|
||
if((get_mode == PARTIAL_DSP_MODE_4) || (get_mode == PARTIAL_DSP_MODE_4_W))
|
||
{
|
||
Epaper_Disp(tmpDispFrame);
|
||
}
|
||
else
|
||
{
|
||
printk("\nDMA out, (x,y,w,h)=(%d,%d,%d,%d)\n",tmpDispFrame.tFrameRange.X, tmpDispFrame.tFrameRange.Y, tmpDispFrame.tFrameRange.W, tmpDispFrame.tFrameRange.H);
|
||
auofb_display_setting(0,0, tmpDispFrame.tFrameRange.X, tmpDispFrame.tFrameRange.Y, tmpDispFrame.tFrameRange.W, tmpDispFrame.tFrameRange.H);
|
||
|
||
Epaper_Pre_DMA_Disp_Start(tmpDispFrame);
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
auofb_Display_Start(0);
|
||
auofb_Display_End(0);
|
||
}
|
||
Epaper_Pre_DMA_Disp_Stop(tmpDispFrame);
|
||
}
|
||
#else
|
||
|
||
Epaper_Disp(tmpDispFrame);
|
||
|
||
#endif
|
||
|
||
}
|
||
|
||
/*
|
||
static void boot_progress_bar_draw_bar(void)
|
||
{
|
||
//u16boot_progress_bar_Data
|
||
T_DISPLAY_FRAME stDisFrame;
|
||
|
||
stDisFrame.u16EpaperCommand = AUO_EPAPER_CMD_PARTIALDISP;
|
||
stDisFrame.tFrameRange.X = 199;
|
||
stDisFrame.tFrameRange.Y = 92;
|
||
stDisFrame.tFrameRange.W = 12;
|
||
stDisFrame.tFrameRange.H = 420;
|
||
|
||
Epaper_Set_Partial_Update_Mode(1);
|
||
|
||
stDisFrame.pFrameData = u16boot_progress_bar_Data;
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Disp(stDisFrame);
|
||
}
|
||
*/
|
||
|
||
static void boot_progress_bar_draw_percent(int percent)
|
||
{
|
||
T_DISPLAY_FRAME stDisFrame;
|
||
int i;
|
||
//unsigned short progress_bar[BOOT_PROGRESS_BAR_W*BOOT_PROGRESS_BAR_H/4];
|
||
int line_bytes = BOOT_PROGRESS_BAR_W/4*2;
|
||
int draw_len = 0;
|
||
if(percent == 0)
|
||
return;
|
||
|
||
memset((unsigned char*)pu16Translatebuffer, 0xff, BOOT_PROGRESS_BAR_W*BOOT_PROGRESS_BAR_H/4*2);
|
||
|
||
#if defined(EPD_HW_ROTATE)
|
||
|
||
|
||
|
||
|
||
if((BOOT_PROGRESS_BAR_W*percent/100)%4 != 0)
|
||
{
|
||
draw_len = (BOOT_PROGRESS_BAR_W*percent/100) + (4)-((BOOT_PROGRESS_BAR_W*percent/100)%4);
|
||
}
|
||
else
|
||
draw_len = (BOOT_PROGRESS_BAR_W*percent/100);
|
||
|
||
for(i=0; i< BOOT_PROGRESS_BAR_H; i++)
|
||
{
|
||
memset((unsigned char*)pu16Translatebuffer + (BOOT_PROGRESS_BAR_W/2)*i, 0x0, (draw_len/2));
|
||
}
|
||
|
||
#else
|
||
|
||
memset((unsigned char*)pu16Translatebuffer+(BOOT_PROGRESS_BAR_H-(BOOT_PROGRESS_BAR_H*percent/100))*line_bytes, 0x0, (BOOT_PROGRESS_BAR_H*percent/100)*line_bytes);
|
||
|
||
#endif
|
||
|
||
Epaper_Set_Partial_Update_Mode(1);
|
||
stDisFrame.u16EpaperCommand = AUO_EPAPER_CMD_PARTIALDISP;
|
||
stDisFrame.tFrameRange.X = BOOT_PROGRESS_BAR_X;
|
||
stDisFrame.tFrameRange.Y = BOOT_PROGRESS_BAR_Y;
|
||
stDisFrame.tFrameRange.W = BOOT_PROGRESS_BAR_W;
|
||
stDisFrame.tFrameRange.H = BOOT_PROGRESS_BAR_H;
|
||
stDisFrame.pFrameData = pu16Translatebuffer;
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
|
||
DPRINTK("\nEpaper Progress %d",percent);
|
||
//Epaper_Disp(stDisFrame);
|
||
auofb_Disp(stDisFrame);
|
||
}
|
||
}
|
||
|
||
static int boot_progress_bar_thread(void *unused)
|
||
{
|
||
int thread_active = 1;
|
||
int draw_count =0;
|
||
|
||
msleep(500);
|
||
//boot_progress_bar_draw_bar();
|
||
|
||
daemonize("Boot_progress_bar_udt");
|
||
allow_signal(SIGKILL);
|
||
|
||
thread_active = 0;
|
||
|
||
while ( thread_active )
|
||
{
|
||
try_to_freeze(); //for freeze kernel_thread
|
||
|
||
if ( !signal_pending(current) )
|
||
{
|
||
printk("\nboot_progress_bar_thread");
|
||
|
||
boot_progress_bar_draw_percent(10+(draw_count*10));
|
||
|
||
draw_count++;
|
||
if(draw_count ==10)
|
||
{
|
||
thread_active = 0;
|
||
}
|
||
interruptible_sleep_on_timeout(&boot_progress_bar_wq, BOOT_PROGRESS_BAR_DELAY_TIME);
|
||
}
|
||
else
|
||
thread_active = 0;
|
||
|
||
}
|
||
|
||
complete_and_exit(&boot_progress_bar_thread_exited, 0);
|
||
}
|
||
|
||
static int update_display_thread(void *unused)
|
||
{
|
||
int thread_active = 1;
|
||
int i=0;
|
||
unsigned short* pu16ProcessPtr=NULL;
|
||
unsigned short* pu16TranslatePtr=pu16Translatebuffer;
|
||
unsigned short u16val;
|
||
T_DISPLAY_FRAME stDisFrame;
|
||
unsigned long count;
|
||
|
||
unsigned long timeout_time = update_display_timeout;
|
||
unsigned char* pu8Tmp_region = NULL;
|
||
unsigned char* pu8Tmp_copy_ptr = NULL;
|
||
int test_len=0;
|
||
|
||
unsigned long tmp_clock;
|
||
unsigned long total_clock;
|
||
|
||
daemonize("AUOEINK_udt");
|
||
allow_signal(SIGKILL);
|
||
|
||
while ( thread_active )
|
||
{
|
||
try_to_freeze(); //for freeze kernel_thread
|
||
|
||
if ( !signal_pending(current) )
|
||
{
|
||
if ( 0 == LOCK_AUOFB_ENTRY() )
|
||
{
|
||
|
||
pu16ProcessPtr = NULL;
|
||
pu16TranslatePtr = pu16Translatebuffer;
|
||
|
||
//if(update_ready)
|
||
while(!auofb_update_queue_is_empty())
|
||
{
|
||
|
||
DPRINTK("AUO EINK time start, jiffies: %lu, HZ: %lu\n", jiffies, HZ);
|
||
total_clock = tmp_clock = jiffies;
|
||
|
||
auofb_update_queue_get(&r_partial_info);
|
||
|
||
#if defined(EPD_ENABLE_PRE_DISPLAY)
|
||
/*********************************************************/
|
||
if( AUO_EPAPER_CMD_INIT == r_partial_info.u16EpaperCommand )
|
||
{
|
||
#ifdef EPD_HW_ROTATE
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 90, 0, 0, 0, 0, 0);
|
||
#else
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 0, 0, 0, 0, 0, 0);
|
||
#endif
|
||
|
||
continue;
|
||
}
|
||
/*********************************************************/
|
||
#endif
|
||
|
||
Epaper_Set_Partial_Update_Mode(r_partial_info.mode);
|
||
|
||
#ifdef EPD_HW_ROTATE
|
||
|
||
#ifdef EPD_HW_ROTATE_NO_MODE4
|
||
if((r_partial_info.mode == PARTIAL_DSP_MODE_4) || (r_partial_info.mode == PARTIAL_DSP_MODE_4_W))
|
||
{
|
||
|
||
if( (u16PrevMode != PARTIAL_DSP_MODE_4) && (u16PrevMode != PARTIAL_DSP_MODE_4_W) )
|
||
{
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 0, 0, 0, 0, 0, 0);
|
||
}
|
||
|
||
//check if the updated region is valid
|
||
if( (r_partial_info.w == auo_mach_info.xres_virtual) && (r_partial_info.h == auo_mach_info.yres_virtual))
|
||
{
|
||
//rotate
|
||
auofb_rotate_RGB565(auo_mach_info.xres_virtual, auo_mach_info.yres_virtual, (unsigned short*)
|
||
pu8Framebuffer, (unsigned short*)pu8RotateBuffer);
|
||
}
|
||
else
|
||
{
|
||
pu8Tmp_region = vmalloc(r_partial_info.w * 2 * r_partial_info.h); // *2 --> unsigned short
|
||
DPRINTK("\nAlloc tmp region len 1 =%d\n",r_partial_info.w * 2 * r_partial_info.h);
|
||
|
||
pu8Tmp_copy_ptr = pu8Framebuffer + (H_RESOLUTION * 2 * (r_partial_info.y) + ((r_partial_info.x) * 2));
|
||
test_len=0;
|
||
for(i=0;i<r_partial_info.h;i++)
|
||
{
|
||
memcpy(pu8Tmp_region+(i * r_partial_info.w * 2), pu8Tmp_copy_ptr, r_partial_info.w * 2);
|
||
pu8Tmp_copy_ptr = pu8Tmp_copy_ptr + H_RESOLUTION*2;
|
||
test_len = test_len + r_partial_info.w * 2;
|
||
}
|
||
DPRINTK("\nCopy Len 1 =%d\n",test_len);
|
||
|
||
//rotate
|
||
auofb_rotate_RGB565(r_partial_info.w, r_partial_info.h, (unsigned short*)
|
||
pu8Tmp_region, (unsigned short*)pu8RotateBuffer);
|
||
|
||
vfree(pu8Tmp_region);
|
||
}
|
||
|
||
DPRINTK("AUO EINK time rotate, jiffies: %lu, Elapsed time: %lu\n", jiffies, jiffies-tmp_clock);
|
||
tmp_clock = jiffies;
|
||
|
||
|
||
pu16ProcessPtr = (unsigned short*)pu8RotateBuffer;
|
||
auofb_convert_RGB565(r_partial_info.w, r_partial_info.h, (unsigned short*)pu8RotateBuffer, pu16Translatebuffer);
|
||
|
||
if(isInitial)
|
||
{
|
||
stDisFrame.u16EpaperCommand = r_partial_info.u16EpaperCommand;
|
||
stDisFrame.tFrameRange.X = r_partial_info.y + 1;
|
||
stDisFrame.tFrameRange.Y = (H_RESOLUTION - (r_partial_info.x) - r_partial_info.w) +1;
|
||
stDisFrame.tFrameRange.W = r_partial_info.h;
|
||
stDisFrame.tFrameRange.H = r_partial_info.w;
|
||
|
||
stDisFrame.pFrameData = pu16Translatebuffer;
|
||
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
auofb_Disp(stDisFrame);
|
||
|
||
if( (u16PrevMode != PARTIAL_DSP_MODE_4) && (u16PrevMode != PARTIAL_DSP_MODE_4_W) )
|
||
{
|
||
if((r_partial_info.mode == PARTIAL_DSP_MODE_4) || (r_partial_info.mode == PARTIAL_DSP_MODE_4_W))
|
||
{
|
||
if(is_Epaper_Write_Ready())
|
||
auofb_Disp(stDisFrame);
|
||
}
|
||
}
|
||
u16PrevMode = r_partial_info.mode;
|
||
|
||
update_ready = false;
|
||
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
if( (u16PrevMode == PARTIAL_DSP_MODE_4) || (u16PrevMode == PARTIAL_DSP_MODE_4_W) )
|
||
{
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 90, 0, 0, 0, 0, 0);
|
||
}
|
||
|
||
|
||
#endif //#ifdef EPD_HW_ROTATE_NO_MODE4
|
||
|
||
if( (r_partial_info.w == auo_mach_info.xres_virtual) && (r_partial_info.h == auo_mach_info.yres_virtual))
|
||
{
|
||
auofb_convert_RGB565(r_partial_info.w, r_partial_info.h, (unsigned short*)pu8Framebuffer, pu16Translatebuffer);
|
||
}
|
||
else
|
||
{
|
||
//pu8Tmp_region = vmalloc(r_partial_info.w * 2 * r_partial_info.h); // *2 --> unsigned short
|
||
DPRINTK("\nAlloc tmp region len 1 =%d\n",r_partial_info.w * 2 * r_partial_info.h);
|
||
|
||
pu8Tmp_copy_ptr = pu8Framebuffer + (H_RESOLUTION * 2 * (r_partial_info.y) + ((r_partial_info.x) * 2));
|
||
test_len=0;
|
||
for(i=0;i<r_partial_info.h;i++)
|
||
{
|
||
//memcpy(pu8Tmp_region+(i * r_partial_info.w * 2), pu8Tmp_copy_ptr, r_partial_info.w * 2);
|
||
memcpy(pu8RotateBuffer+(i * r_partial_info.w * 2), pu8Tmp_copy_ptr, r_partial_info.w * 2);
|
||
pu8Tmp_copy_ptr = pu8Tmp_copy_ptr + H_RESOLUTION*2;
|
||
test_len = test_len + r_partial_info.w * 2;
|
||
}
|
||
DPRINTK("\nCopy Len 1 =%d\n",test_len);
|
||
|
||
//rotate
|
||
/*auofb_rotate_RGB565(r_partial_info.w, r_partial_info.h, (unsigned short*)
|
||
pu8Tmp_region, (unsigned short*)pu8RotateBuffer);*/
|
||
|
||
//vfree(pu8Tmp_region);
|
||
|
||
pu16ProcessPtr = (unsigned short*)pu8RotateBuffer;
|
||
|
||
auofb_convert_RGB565(r_partial_info.w, r_partial_info.h, (unsigned short*)pu8RotateBuffer, pu16Translatebuffer);
|
||
}
|
||
|
||
|
||
|
||
if(isInitial)
|
||
{
|
||
stDisFrame.u16EpaperCommand = r_partial_info.u16EpaperCommand;
|
||
{
|
||
|
||
stDisFrame.tFrameRange.X = r_partial_info.x+1;
|
||
stDisFrame.tFrameRange.Y = r_partial_info.y+1;
|
||
stDisFrame.tFrameRange.W = r_partial_info.w;
|
||
stDisFrame.tFrameRange.H = r_partial_info.h;
|
||
|
||
|
||
}
|
||
stDisFrame.pFrameData = pu16Translatebuffer;
|
||
//stDisFrame.pFrameData = (unsigned short*)pu8Framebuffer; //do not need to convert
|
||
|
||
gStDisFrame = stDisFrame;
|
||
if(is_Epaper_Write_Ready())
|
||
auofb_Disp(stDisFrame);
|
||
|
||
if( (u16PrevMode != PARTIAL_DSP_MODE_4) && (u16PrevMode != PARTIAL_DSP_MODE_4_W) )
|
||
{
|
||
if((r_partial_info.mode == PARTIAL_DSP_MODE_4) || (r_partial_info.mode == PARTIAL_DSP_MODE_4_W))
|
||
{
|
||
if(is_Epaper_Write_Ready())
|
||
auofb_Disp(stDisFrame);
|
||
}
|
||
}
|
||
u16PrevMode = r_partial_info.mode;
|
||
|
||
update_ready = false;
|
||
|
||
DPRINTK("AUO EINK time display, jiffies: %lu, Elapsed time: %lu\n", jiffies, jiffies-tmp_clock);
|
||
tmp_clock = jiffies;
|
||
|
||
}
|
||
|
||
#ifdef EPD_HW_ROTATE_NO_MODE4
|
||
}
|
||
#endif
|
||
|
||
#else //sw rotate
|
||
|
||
|
||
#ifdef AUOFB_ROTATE
|
||
|
||
|
||
//check if the updated region is valid
|
||
if( (r_partial_info.w == auo_mach_info.xres_virtual) && (r_partial_info.h == auo_mach_info.yres_virtual))
|
||
{
|
||
//rotate
|
||
auofb_rotate_RGB565(auo_mach_info.xres_virtual, auo_mach_info.yres_virtual, (unsigned short*)
|
||
pu8Framebuffer, (unsigned short*)pu8RotateBuffer);
|
||
}
|
||
else
|
||
{
|
||
pu8Tmp_region = vmalloc(r_partial_info.w * 2 * r_partial_info.h); // *2 --> unsigned short
|
||
DPRINTK("\nAlloc tmp region len 1 =%d\n",r_partial_info.w * 2 * r_partial_info.h);
|
||
|
||
pu8Tmp_copy_ptr = pu8Framebuffer + (H_RESOLUTION * 2 * (r_partial_info.y) + ((r_partial_info.x) * 2));
|
||
test_len=0;
|
||
for(i=0;i<r_partial_info.h;i++)
|
||
{
|
||
memcpy(pu8Tmp_region+(i * r_partial_info.w * 2), pu8Tmp_copy_ptr, r_partial_info.w * 2);
|
||
pu8Tmp_copy_ptr = pu8Tmp_copy_ptr + H_RESOLUTION*2;
|
||
test_len = test_len + r_partial_info.w * 2;
|
||
}
|
||
DPRINTK("\nCopy Len 1 =%d\n",test_len);
|
||
|
||
//rotate
|
||
auofb_rotate_RGB565(r_partial_info.w, r_partial_info.h, (unsigned short*)
|
||
pu8Tmp_region, (unsigned short*)pu8RotateBuffer);
|
||
|
||
vfree(pu8Tmp_region);
|
||
}
|
||
|
||
DPRINTK("AUO EINK time rotate, jiffies: %lu, Elapsed time: %lu\n", jiffies, jiffies-tmp_clock);
|
||
tmp_clock = jiffies;
|
||
|
||
|
||
#endif
|
||
|
||
|
||
|
||
#ifdef AUOFB_ROTATE
|
||
pu16ProcessPtr = (unsigned short*)pu8RotateBuffer;
|
||
#else
|
||
pu16ProcessPtr = (unsigned short*)pu8Framebuffer;
|
||
#endif
|
||
|
||
|
||
#ifdef AUOFB_ROTATE
|
||
auofb_convert_RGB565(r_partial_info.w, r_partial_info.h, (unsigned short*)pu8RotateBuffer, pu16Translatebuffer);
|
||
#else
|
||
auofb_convert_RGB565(r_partial_info.w, r_partial_info.h, (unsigned short*)pu8Framebuffer, pu16Translatebuffer);
|
||
#endif
|
||
DPRINTK("AUO EINK time convert grey, jiffies: %lu, Elapsed time: %lu\n", jiffies, jiffies-tmp_clock);
|
||
tmp_clock = jiffies;
|
||
|
||
if(isInitial)
|
||
{
|
||
//DPRINTK("\n@@@@@@@@@@@@send i80...");
|
||
//stDisFrame.u16EpaperCommand = AUO_EPAPER_CMD_FULLDISP;
|
||
stDisFrame.u16EpaperCommand = r_partial_info.u16EpaperCommand;
|
||
/*
|
||
if(r_partial_info.mode == 0)
|
||
{
|
||
stDisFrame.tFrameRange.X = 1;
|
||
stDisFrame.tFrameRange.Y = 1;
|
||
//stDisFrame.tFrameRange.W = H_RESOLUTION;
|
||
//stDisFrame.tFrameRange.H = V_RESOLUTION;
|
||
//rotation test: still send 800x600
|
||
stDisFrame.tFrameRange.W = 800;
|
||
stDisFrame.tFrameRange.H = 600;
|
||
}
|
||
else*/
|
||
{
|
||
#ifdef AUOFB_ROTATE
|
||
stDisFrame.tFrameRange.X = r_partial_info.y + 1;
|
||
stDisFrame.tFrameRange.Y = (H_RESOLUTION - (r_partial_info.x) - r_partial_info.w) +1;
|
||
stDisFrame.tFrameRange.W = r_partial_info.h;
|
||
stDisFrame.tFrameRange.H = r_partial_info.w;
|
||
#else
|
||
|
||
stDisFrame.tFrameRange.X = r_partial_info.x;
|
||
stDisFrame.tFrameRange.Y = r_partial_info.y;
|
||
stDisFrame.tFrameRange.W = r_partial_info.w;
|
||
stDisFrame.tFrameRange.H = r_partial_info.h;
|
||
|
||
#endif
|
||
}
|
||
stDisFrame.pFrameData = pu16Translatebuffer;
|
||
//stDisFrame.pFrameData = (unsigned short*)pu8Framebuffer; //do not need to convert
|
||
|
||
gStDisFrame = stDisFrame;
|
||
if(is_Epaper_Write_Ready())
|
||
auofb_Disp(stDisFrame);
|
||
|
||
if( (u16PrevMode != PARTIAL_DSP_MODE_4) && (u16PrevMode != PARTIAL_DSP_MODE_4_W) )
|
||
{
|
||
if((r_partial_info.mode == PARTIAL_DSP_MODE_4) || (r_partial_info.mode == PARTIAL_DSP_MODE_4_W))
|
||
{
|
||
if(is_Epaper_Write_Ready())
|
||
auofb_Disp(stDisFrame);
|
||
}
|
||
}
|
||
u16PrevMode = r_partial_info.mode;
|
||
|
||
update_ready = false;
|
||
|
||
DPRINTK("AUO EINK time display, jiffies: %lu, Elapsed time: %lu\n", jiffies, jiffies-tmp_clock);
|
||
tmp_clock = jiffies;
|
||
|
||
}
|
||
#endif //#ifdef EPD_HW_ROTATE
|
||
|
||
if(stDisFrame.u16EpaperCommand != AUO_EPAPER_CMD_PRE_DISPLAY_START)
|
||
{
|
||
if((r_partial_info.mode == PARTIAL_DSP_MODE_4) || (r_partial_info.mode == PARTIAL_DSP_MODE_4_W))
|
||
msleep(20);
|
||
else
|
||
msleep(500);
|
||
}
|
||
|
||
//printk("pw=%d, pr=%d\n",pw,pr);
|
||
}
|
||
DPRINTK("AUO EINK time end: %lu, Total Elapsed time: %lu\n", jiffies, jiffies-total_clock);
|
||
|
||
LOCK_AUOFB_EXIT();
|
||
|
||
|
||
}
|
||
|
||
|
||
//interruptible_sleep_on_timeout(&update_display_wq, 1500);
|
||
interruptible_sleep_on(&update_display_wq);
|
||
|
||
}
|
||
else
|
||
thread_active = 0;
|
||
|
||
}
|
||
|
||
complete_and_exit(&update_display_thread_exited, 0);
|
||
}
|
||
|
||
static void start_boot_progress_bar_thread(void)
|
||
{
|
||
return;
|
||
init_waitqueue_head(&boot_progress_bar_wq);
|
||
|
||
if ( 0 > (boot_progress_bar_pid = kernel_thread(boot_progress_bar_thread, NULL, CLONE_KERNEL)) )
|
||
boot_progress_bar_pid = 0;
|
||
|
||
}
|
||
|
||
static void start_update_display_thread(void)
|
||
{
|
||
return;
|
||
init_waitqueue_head(&update_display_wq);
|
||
|
||
if ( 0 > (update_display_pid = kernel_thread(update_display_thread, NULL, CLONE_KERNEL)) )
|
||
update_display_pid = 0;
|
||
|
||
isInitial = true;
|
||
}
|
||
|
||
static void stop_boot_progress_bar_thread(void)
|
||
{
|
||
return;
|
||
if ( 0 < boot_progress_bar_pid )
|
||
if ( 0 == kill_proc(boot_progress_bar_pid, SIGKILL, 1) )
|
||
wait_for_completion(&boot_progress_bar_thread_exited);
|
||
}
|
||
|
||
static void stop_update_display_thread(void)
|
||
{
|
||
return;
|
||
if ( 0 < update_display_pid )
|
||
if ( 0 == kill_proc(update_display_pid, SIGKILL, 1) )
|
||
wait_for_completion(&update_display_thread_exited);
|
||
}
|
||
|
||
static panel_update_workqueue(struct work_struct *work)
|
||
{
|
||
return;
|
||
if ( 0 == LOCK_AUOFB_ENTRY() )
|
||
{
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
DPRINTK("\n!!! Time's up!\n");
|
||
panel_timer_qisda.expires = jiffies + (10*HZ)/10;
|
||
|
||
//update_ready = true;
|
||
wake_up(&update_display_wq);
|
||
}
|
||
LOCK_AUOFB_EXIT();
|
||
}
|
||
|
||
//mod_timer(&panel_timer_qisda,panel_timer_qisda.expires);
|
||
//del_timer(&touch_iic_timer_qisda);
|
||
}
|
||
|
||
static void wake_update_display_thread(void)
|
||
{
|
||
return;
|
||
if ( 0 == LOCK_AUOFB_ENTRY() )
|
||
{
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
|
||
update_ready = true;
|
||
wake_up(&update_display_wq);
|
||
|
||
}
|
||
|
||
LOCK_AUOFB_EXIT();
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
/**
|
||
* auofb_open - Optional function. Called when the framebuffer is
|
||
* first accessed.
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
* @user: tell us if the userland (value=1) or the console is accessing
|
||
* the framebuffer.
|
||
*
|
||
* This function is the first function called in the framebuffer api.
|
||
* Usually you don't need to provide this function. The case where it
|
||
* is used is to change from a text mode hardware state to a graphics
|
||
* mode state.
|
||
*
|
||
* Returns negative errno on error, or zero on success.
|
||
*/
|
||
static int auofb_open(const struct fb_info *info, int user)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* auofb_release - Optional function. Called when the framebuffer
|
||
* device is closed.
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
* @user: tell us if the userland (value=1) or the console is accessing
|
||
* the framebuffer.
|
||
*
|
||
* Thus function is called when we close /dev/fb or the framebuffer
|
||
* console system is released. Usually you don't need this function.
|
||
* The case where it is usually used is to go from a graphics state
|
||
* to a text mode state.
|
||
*
|
||
* Returns negative errno on error, or zero on success.
|
||
*/
|
||
static int auofb_release(const struct fb_info *info, int user)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* auofb_check_var - Optional function. Validates a var passed in.
|
||
* @var: frame buffer variable screen structure
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
*
|
||
* Checks to see if the hardware supports the state requested by
|
||
* var passed in. This function does not alter the hardware state!!!
|
||
* This means the data stored in struct fb_info and struct auo_par do
|
||
* not change. This includes the var inside of struct fb_info.
|
||
* Do NOT change these. This function can be called on its own if we
|
||
* intent to only test a mode and not actually set it. The stuff in
|
||
* modedb.c is a example of this. 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.
|
||
*
|
||
* For values that are off, this function must round them _up_ to the
|
||
* next value that is supported by the hardware. If the value is
|
||
* greater than the highest value supported by the hardware, then this
|
||
* function must return -EINVAL.
|
||
*
|
||
* Exception to the above rule: Some drivers have a fixed mode, ie,
|
||
* the hardware is already set at boot up, and cannot be changed. In
|
||
* this case, it is more acceptable that this function just return
|
||
* a copy of the currently working var (info->var). Better is to not
|
||
* implement this function, as the upper layer will do the copying
|
||
* of the current var for you.
|
||
*
|
||
* Note: This is the only function where the contents of var can be
|
||
* freely adjusted after the driver has been registered. If you find
|
||
* that you have code outside of this function that alters the content
|
||
* of var, then you are doing something wrong. Note also that the
|
||
* contents of info->var must be left untouched at all times after
|
||
* driver registration.
|
||
*
|
||
* Returns negative errno on error, or zero on success.
|
||
*/
|
||
static int auofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||
{
|
||
DPRINTK("check_var(var=%p, info=%p)\n", var, info);
|
||
|
||
switch (var->bits_per_pixel) {
|
||
case 4:
|
||
var->red = auo_fb_rgb_4.red;
|
||
var->green = auo_fb_rgb_4.green;
|
||
var->blue = auo_fb_rgb_4.blue;
|
||
var->transp = auo_fb_rgb_4.transp;
|
||
break;
|
||
|
||
case 8:
|
||
var->red = auo_fb_rgb_8.red;
|
||
var->green = auo_fb_rgb_8.green;
|
||
var->blue = auo_fb_rgb_8.blue;
|
||
var->transp = auo_fb_rgb_8.transp;
|
||
break;
|
||
|
||
case 16:
|
||
var->red = auo_fb_rgb_16.red;
|
||
var->green = auo_fb_rgb_16.green;
|
||
var->blue = auo_fb_rgb_16.blue;
|
||
var->transp = auo_fb_rgb_16.transp;
|
||
break;
|
||
|
||
case 24:
|
||
var->red = auo_fb_rgb_24.red;
|
||
var->green = auo_fb_rgb_24.green;
|
||
var->blue = auo_fb_rgb_24.blue;
|
||
var->transp = auo_fb_rgb_24.transp;
|
||
break;
|
||
|
||
case 32:
|
||
var->red = auo_fb_rgb_32.red;
|
||
var->green = auo_fb_rgb_32.green;
|
||
var->blue = auo_fb_rgb_32.blue;
|
||
var->transp = auo_fb_rgb_32.transp;
|
||
break;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void auo_fb_activate_var(struct auo_fb_info *fbi,
|
||
struct fb_var_screeninfo *var)
|
||
{
|
||
DPRINTK("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
|
||
|
||
switch (var->bits_per_pixel) {
|
||
|
||
case 4:
|
||
auo_mach_info.wincon0= S3C_WINCONx_HAWSWP_ENABLE | S3C_WINCONx_BURSTLEN_4WORD | S3C_WINCONx_BPPMODE_F_16BPP_565; // 4word burst, 16bpp,
|
||
auo_mach_info.wincon1= S3C_WINCONx_HAWSWP_ENABLE | S3C_WINCONx_BURSTLEN_4WORD | S3C_WINCONx_BPPMODE_F_16BPP_565 | S3C_WINCONx_BLD_PIX_PLANE | S3C_WINCONx_ALPHA_SEL_1; //
|
||
auo_mach_info.bpp= PIXEL_BPP4;
|
||
auo_mach_info.bytes_per_pixel= 1;
|
||
break;
|
||
|
||
case 8:
|
||
auo_mach_info.wincon0= S3C_WINCONx_BYTSWP_ENABLE | S3C_WINCONx_BURSTLEN_4WORD | S3C_WINCONx_BPPMODE_F_8BPP_PAL; // 4word burst, 8bpp-palletized,
|
||
auo_mach_info.wincon1= S3C_WINCONx_HAWSWP_ENABLE | S3C_WINCONx_BURSTLEN_4WORD | S3C_WINCONx_BPPMODE_F_16BPP_565 | S3C_WINCONx_BLD_PIX_PLANE | S3C_WINCONx_ALPHA_SEL_1; // 4word burst, 16bpp for OSD
|
||
|
||
auo_mach_info.bpp= PIXEL_BPP8;
|
||
auo_mach_info.bytes_per_pixel= 1;
|
||
auo_mach_info.wpalcon= S3C_WPALCON_W0PAL_24BIT;
|
||
break;
|
||
|
||
case 16:
|
||
auo_mach_info.wincon0= S3C_WINCONx_HAWSWP_ENABLE | S3C_WINCONx_BURSTLEN_4WORD | S3C_WINCONx_BPPMODE_F_16BPP_565; // 4word burst, 16bpp,
|
||
auo_mach_info.wincon1= S3C_WINCONx_HAWSWP_ENABLE | S3C_WINCONx_BURSTLEN_4WORD | S3C_WINCONx_BPPMODE_F_16BPP_565 | S3C_WINCONx_BLD_PIX_PLANE | S3C_WINCONx_ALPHA_SEL_1; //
|
||
auo_mach_info.bpp= PIXEL_BPP16;
|
||
auo_mach_info.bytes_per_pixel= 2;
|
||
break;
|
||
|
||
case 24:
|
||
auo_mach_info.wincon0= S3C_WINCONx_HAWSWP_DISABLE | S3C_WINCONx_BURSTLEN_16WORD | S3C_WINCONx_BPPMODE_F_24BPP_888; // 4word burst, 24bpp,,
|
||
auo_mach_info.wincon1= S3C_WINCONx_HAWSWP_DISABLE | S3C_WINCONx_BURSTLEN_16WORD | S3C_WINCONx_BPPMODE_F_24BPP_888 | S3C_WINCONx_BLD_PIX_PLANE | S3C_WINCONx_ALPHA_SEL_1; // 4word burst, 24bpp for OSD
|
||
auo_mach_info.bpp= PIXEL_BPP24;
|
||
auo_mach_info.bytes_per_pixel= 4;
|
||
break;
|
||
|
||
case 32:
|
||
auo_mach_info.bytes_per_pixel= 4;
|
||
break;
|
||
}
|
||
|
||
#if 0
|
||
/* write new registers */
|
||
__raw_writel(auo_mach_info.wincon0, S3C_WINCON0);
|
||
__raw_writel(auo_mach_info.wincon1, S3C_WINCON1);
|
||
|
||
__raw_writel(auo_mach_info.wpalcon, S3C_WPALCON);
|
||
|
||
//__raw_writel(mach_info.wincon0|S3C_WINCONx_ENWIN_F_ENABLE|S3C_WINCONx_BUFAUTOEN_ENABLE, S3C_WINCON0); /* Double buffer auto enable bit */
|
||
__raw_writel(auo_mach_info.wincon0|S3C_WINCONx_ENWIN_F_ENABLE, S3C_WINCON0);
|
||
__raw_writel(auo_mach_info.vidcon0|S3C_VIDCON0_ENVID_ENABLE|S3C_VIDCON0_ENVID_F_ENABLE, S3C_VIDCON0);
|
||
#endif
|
||
|
||
}
|
||
|
||
/**
|
||
* auofb_set_par - Optional function. Alters the hardware state.
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
*
|
||
* Using the fb_var_screeninfo in fb_info we set the resolution of the
|
||
* this particular framebuffer. This function alters the par AND 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.
|
||
*
|
||
* This function is also used to recover/restore the hardware to a
|
||
* known working state.
|
||
*
|
||
* auofb_check_var is always called before auofb_set_par to ensure that
|
||
* the contents of var is always valid.
|
||
*
|
||
* Again if you can't change the resolution you don't need this function.
|
||
*
|
||
* However, even if your hardware does not support mode changing,
|
||
* a set_par might be needed to at least initialize the hardware to
|
||
* a known working state, especially if it came back from another
|
||
* process that also modifies the same hardware, such as X.
|
||
*
|
||
* If this is the case, a combination such as the following should work:
|
||
*
|
||
* static int auofb_check_var(struct fb_var_screeninfo *var,
|
||
* struct fb_info *info)
|
||
* {
|
||
* *var = info->var;
|
||
* return 0;
|
||
* }
|
||
*
|
||
* static int auofb_set_par(struct fb_info *info)
|
||
* {
|
||
* init your hardware here
|
||
* }
|
||
*
|
||
* Returns negative errno on error, or zero on success.
|
||
*/
|
||
static int auofb_set_par(struct fb_info *info)
|
||
{
|
||
struct auo_fb_info *fbi = (struct auo_fb_info *)info;
|
||
struct fb_var_screeninfo *var = &info->var;
|
||
|
||
if (var->bits_per_pixel == 16)
|
||
fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
|
||
else if (var->bits_per_pixel == 32)
|
||
fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
|
||
else
|
||
fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
|
||
|
||
fbi->fb.fix.line_length = var->width * auo_mach_info.bytes_per_pixel;
|
||
|
||
/* activate this new configuration */
|
||
auo_fb_activate_var(fbi, var);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* auofb_setcolreg - Optional function. Sets a color register.
|
||
* @regno: Which register in the CLUT we are programming
|
||
* @red: The red value which can be up to 16 bits wide
|
||
* @green: The green value which can be up to 16 bits wide
|
||
* @blue: The blue value which can be up to 16 bits wide.
|
||
* @transp: If supported, the alpha value which can be up to 16 bits wide.
|
||
* @info: frame buffer info structure
|
||
*
|
||
* Set a single color register. The values supplied have a 16 bit
|
||
* magnitude which needs to be scaled in this function for the hardware.
|
||
* Things to take into consideration are how many color registers, if
|
||
* any, are supported with the current color visual. With truecolor mode
|
||
* no color palettes are supported. Here a pseudo palette is created
|
||
* which we store the value in pseudo_palette in struct fb_info. For
|
||
* pseudocolor mode we have a limited color palette. To deal with this
|
||
* we can program what color is displayed for a particular pixel value.
|
||
* DirectColor is similar in that we can program each color field. If
|
||
* we have a static colormap we don't need to implement this function.
|
||
*
|
||
* Returns negative errno on error, or zero on success.
|
||
*/
|
||
static int auofb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||
unsigned blue, unsigned transp,
|
||
const struct fb_info *info)
|
||
{
|
||
struct auo_fb_info *fbi = (struct auo_fb_info *)info;
|
||
unsigned int val;
|
||
|
||
|
||
switch (fbi->fb.fix.visual) {
|
||
case FB_VISUAL_TRUECOLOR:
|
||
/* true-colour, use pseuo-palette */
|
||
if (regno < 16) {
|
||
u32 *pal = fbi->fb.pseudo_palette;
|
||
|
||
/*
|
||
val = chan_to_field(red, fbi->fb.var.red);
|
||
val |= chan_to_field(green, fbi->fb.var.green);
|
||
val |= chan_to_field(blue, fbi->fb.var.blue);
|
||
*/
|
||
pal[regno] = val;
|
||
}
|
||
break;
|
||
|
||
case FB_VISUAL_PSEUDOCOLOR:
|
||
if (regno < 256) {
|
||
|
||
/* currently assume RGB 8-8-8 mode -- for SONY */
|
||
val = ((red << 8) & 0xff0000);
|
||
val |= ((green >> 0) & 0xff00);
|
||
val |= ((blue >> 8) & 0xff);
|
||
|
||
DPRINTK("index = %d, val = 0x%8X\n", regno, val);
|
||
//schedule_palette_update(fbi, regno, val);
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
return 1; /* unknown type */
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* auofb_pan_display - NOT a required function. Pans the display.
|
||
* @var: frame buffer variable screen structure
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
*
|
||
* 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.
|
||
*
|
||
* Returns negative errno on error, or zero on success.
|
||
*/
|
||
static int auofb_pan_display(struct fb_var_screeninfo *var,
|
||
const struct fb_info *info)
|
||
{
|
||
/*
|
||
* If your hardware does not support panning, _do_ _not_ implement this
|
||
* function. Creating a dummy function will just confuse user apps.
|
||
*/
|
||
|
||
/*
|
||
* Note that even if this function is fully functional, a setting of
|
||
* 0 in both xpanstep and ypanstep means that this function will never
|
||
* get called.
|
||
*/
|
||
|
||
/* ... */
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* auofb_blank - NOT a required function. Blanks the display.
|
||
* @blank_mode: the blank mode we want.
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
*
|
||
* Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
|
||
* Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
|
||
* e.g. a video mode which doesn't support it.
|
||
*
|
||
* Implements VESA suspend and powerdown modes on hardware that supports
|
||
* disabling hsync/vsync:
|
||
*
|
||
* FB_BLANK_NORMAL = display is blanked, syncs are on.
|
||
* FB_BLANK_HSYNC_SUSPEND = hsync off
|
||
* FB_BLANK_VSYNC_SUSPEND = vsync off
|
||
* FB_BLANK_POWERDOWN = hsync and vsync off
|
||
*
|
||
* If implementing this function, at least support FB_BLANK_UNBLANK.
|
||
* Return !0 for any modes that are unimplemented.
|
||
*
|
||
*/
|
||
static int auofb_blank(int blank_mode, const struct fb_info *info)
|
||
{
|
||
/* ... */
|
||
return 0;
|
||
}
|
||
|
||
/* ------------ Accelerated Functions --------------------- */
|
||
|
||
/*
|
||
* We provide our own functions if we have hardware acceleration
|
||
* or non packed pixel format layouts. If we have no hardware
|
||
* acceleration, we can use a generic unaccelerated function. If using
|
||
* a pack pixel format just use the functions in cfb_*.c. Each file
|
||
* has one of the three different accel functions we support.
|
||
*/
|
||
|
||
/**
|
||
* auofb_fillrect - REQUIRED function. Can use generic routines if
|
||
* non acclerated hardware and packed pixel based.
|
||
* Draws a rectangle on the screen.
|
||
*
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
* @region: The structure representing the rectangular region we
|
||
* wish to draw to.
|
||
*
|
||
* This drawing operation places/removes a retangle on the screen
|
||
* depending on the rastering operation with the value of color which
|
||
* is in the current color depth format.
|
||
*/
|
||
void auofb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
|
||
{
|
||
/* Meaning of struct fb_fillrect
|
||
*
|
||
* @dx: The x and y corrdinates of the upper left hand corner of the
|
||
* @dy: area we want to draw to.
|
||
* @width: How wide the rectangle is we want to draw.
|
||
* @height: How tall the rectangle is we want to draw.
|
||
* @color: The color to fill in the rectangle with.
|
||
* @rop: The raster operation. We can draw the rectangle with a COPY
|
||
* of XOR which provides erasing effect.
|
||
*/
|
||
}
|
||
|
||
/**
|
||
* auofb_copyarea - REQUIRED function. Can use generic routines if
|
||
* non acclerated hardware and packed pixel based.
|
||
* Copies one area of the screen to another area.
|
||
*
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
* @area: Structure providing the data to copy the framebuffer contents
|
||
* from one region to another.
|
||
*
|
||
* This drawing operation copies a rectangular area from one area of the
|
||
* screen to another area.
|
||
*/
|
||
void auofb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
|
||
{
|
||
/*
|
||
* @dx: The x and y coordinates of the upper left hand corner of the
|
||
* @dy: destination area on the screen.
|
||
* @width: How wide the rectangle is we want to copy.
|
||
* @height: How tall the rectangle is we want to copy.
|
||
* @sx: The x and y coordinates of the upper left hand corner of the
|
||
* @sy: source area on the screen.
|
||
*/
|
||
}
|
||
|
||
|
||
/**
|
||
* auofb_imageblit - REQUIRED function. Can use generic routines if
|
||
* non acclerated hardware and packed pixel based.
|
||
* Copies a image from system memory to the screen.
|
||
*
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
* @image: structure defining the image.
|
||
*
|
||
* This drawing operation draws a image on the screen. It can be a
|
||
* mono image (needed for font handling) or a color image (needed for
|
||
* tux).
|
||
*/
|
||
void auofb_imageblit(struct fb_info *p, const struct fb_image *image)
|
||
{
|
||
/*
|
||
* @dx: The x and y coordinates of the upper left hand corner of the
|
||
* @dy: destination area to place the image on the screen.
|
||
* @width: How wide the image is we want to copy.
|
||
* @height: How tall the image is we want to copy.
|
||
* @fg_color: For mono bitmap images this is color data for
|
||
* @bg_color: the foreground and background of the image to
|
||
* write directly to the frmaebuffer.
|
||
* @depth: How many bits represent a single pixel for this image.
|
||
* @data: The actual data used to construct the image on the display.
|
||
* @cmap: The colormap used for color images.
|
||
*/
|
||
|
||
/*
|
||
* The generic function, cfb_imageblit, expects that the bitmap scanlines are
|
||
* padded to the next byte. Most hardware accelerators may require padding to
|
||
* the next u16 or the next u32. If that is the case, the driver can specify
|
||
* this by setting info->pixmap.scan_align = 2 or 4. See a more
|
||
* comprehensive description of the pixmap below.
|
||
*/
|
||
}
|
||
|
||
/**
|
||
* auofb_cursor - OPTIONAL. If your hardware lacks support
|
||
* for a cursor, leave this field NULL.
|
||
*
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
* @cursor: structure defining the cursor to draw.
|
||
*
|
||
* This operation is used to set or alter the properities of the
|
||
* cursor.
|
||
*
|
||
* Returns negative errno on error, or zero on success.
|
||
*/
|
||
#if 0
|
||
int auofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
|
||
{
|
||
/*
|
||
* @set: Which fields we are altering in struct fb_cursor
|
||
* @enable: Disable or enable the cursor
|
||
* @rop: The bit operation we want to do.
|
||
* @mask: This is the cursor mask bitmap.
|
||
* @dest: A image of the area we are going to display the cursor.
|
||
* Used internally by the driver.
|
||
* @hot: The hot spot.
|
||
* @image: The actual data for the cursor image.
|
||
*
|
||
* NOTES ON FLAGS (cursor->set):
|
||
*
|
||
* FB_CUR_SETIMAGE - the cursor image has changed (cursor->image.data)
|
||
* FB_CUR_SETPOS - the cursor position has changed (cursor->image.dx|dy)
|
||
* FB_CUR_SETHOT - the cursor hot spot has changed (cursor->hot.dx|dy)
|
||
* FB_CUR_SETCMAP - the cursor colors has changed (cursor->fg_color|bg_color)
|
||
* FB_CUR_SETSHAPE - the cursor bitmask has changed (cursor->mask)
|
||
* FB_CUR_SETSIZE - the cursor size has changed (cursor->width|height)
|
||
* FB_CUR_SETALL - everything has changed
|
||
*
|
||
* NOTES ON ROPs (cursor->rop, Raster Operation)
|
||
*
|
||
* ROP_XOR - cursor->image.data XOR cursor->mask
|
||
* ROP_COPY - curosr->image.data AND cursor->mask
|
||
*
|
||
* OTHER NOTES:
|
||
*
|
||
* - fbcon only supports a 2-color cursor (cursor->image.depth = 1)
|
||
* - The fb_cursor structure, @cursor, _will_ always contain valid
|
||
* fields, whether any particular bitfields in cursor->set is set
|
||
* or not.
|
||
*/
|
||
}
|
||
|
||
/**
|
||
* auofb_rotate - NOT a required function. If your hardware
|
||
* supports rotation the whole screen then
|
||
* you would provide a hook for this.
|
||
*
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
* @angle: The angle we rotate the screen.
|
||
*
|
||
* This operation is used to set or alter the properities of the
|
||
* cursor.
|
||
*/
|
||
void auofb_rotate(struct fb_info *info, int angle)
|
||
{
|
||
/* Will be deprecated */
|
||
}
|
||
|
||
/**
|
||
* auofb_poll - NOT a required function. The purpose of this
|
||
* function is to provide a way for some process
|
||
* to wait until a specific hardware event occurs
|
||
* for the framebuffer device.
|
||
*
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
* @wait: poll table where we store process that await a event.
|
||
*/
|
||
void auofb_poll(struct fb_info *info, poll_table *wait)
|
||
{
|
||
}
|
||
|
||
/**
|
||
* auofb_sync - NOT a required function. Normally the accel engine
|
||
* for a graphics card take a specific amount of time.
|
||
* Often we have to wait for the accelerator to finish
|
||
* its operation before we can write to the framebuffer
|
||
* so we can have consistent display output.
|
||
*
|
||
* @info: frame buffer structure that represents a single frame buffer
|
||
*
|
||
* If the driver has implemented its own hardware-based drawing function,
|
||
* implementing this function is highly recommended.
|
||
*/
|
||
void auofb_sync(struct fb_info *info)
|
||
{
|
||
}
|
||
#endif
|
||
/*
|
||
* Initialization
|
||
*/
|
||
|
||
static int add_vma(struct vm_area_struct *vma)
|
||
{
|
||
struct fb_vma_list_entry *list_entry;
|
||
|
||
DPRINTK("\n@@@@@@@@@add_vma");
|
||
|
||
list_entry = kmalloc(sizeof(struct fb_vma_list_entry), GFP_KERNEL);
|
||
list_entry->vma = vma;
|
||
|
||
down_interruptible(&vma_list_semaphore);
|
||
|
||
list_add_tail((struct list_head *)list_entry, &vma_list);
|
||
|
||
up(&vma_list_semaphore);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static struct fb_vma_list_entry *find_fb_vma_entry(struct vm_area_struct *vma)
|
||
{
|
||
struct list_head *ptr;
|
||
struct fb_vma_list_entry *entry;
|
||
|
||
DPRINTK("\n@@@@@@@@@find_fb_vma_entry");
|
||
|
||
for (ptr = vma_list.next; ptr != &vma_list; ptr = ptr->next) {
|
||
entry = list_entry(ptr, struct fb_vma_list_entry, list);
|
||
if (entry->vma == vma) {
|
||
return entry;
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static int remove_vma(struct vm_area_struct *vma)
|
||
{
|
||
struct fb_vma_list_entry *entry;
|
||
|
||
DPRINTK("\n@@@@@@@@@remove_vma");
|
||
|
||
down_interruptible(&vma_list_semaphore);
|
||
|
||
entry = find_fb_vma_entry(vma);
|
||
if (entry != NULL) {
|
||
list_del((struct list_head *) entry);
|
||
kfree(entry);
|
||
}
|
||
|
||
up(&vma_list_semaphore);
|
||
|
||
return 0;
|
||
}
|
||
|
||
void auo_fb_vma_open(struct vm_area_struct *vma)
|
||
{
|
||
DPRINTK("\n@@@@@@@@@auo_fb_vma_open");
|
||
add_vma(vma);
|
||
|
||
}
|
||
|
||
void auo_fb_vma_close(struct vm_area_struct *vma)
|
||
{
|
||
DPRINTK("\n@@@@@@@@@auo_fb_vma_close");
|
||
remove_vma(vma);
|
||
}
|
||
|
||
struct page *auo_fb_vma_nopage( struct vm_area_struct *vma, unsigned long address, int *type)
|
||
{
|
||
unsigned long offset;
|
||
struct page *page = NOPAGE_SIGBUS;
|
||
|
||
//DPRINTK("\n@@@@@@@@@auo_fb_vma_nopage");
|
||
|
||
offset = address - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT);
|
||
|
||
if (offset > videomemorysize) {
|
||
return page;
|
||
}
|
||
|
||
page = videopages[offset >> PAGE_SHIFT];
|
||
get_page(page);
|
||
|
||
return page;
|
||
}
|
||
|
||
|
||
|
||
|
||
static struct vm_operations_struct auo_fb_vma_ops = {
|
||
open: auo_fb_vma_open,
|
||
close: auo_fb_vma_close,
|
||
nopage: auo_fb_vma_nopage,
|
||
};
|
||
|
||
int auo_fb_mmap(
|
||
//struct fb_info *info,
|
||
struct file *file,
|
||
struct vm_area_struct *vma)
|
||
{
|
||
DPRINTK("\n@@@@@@@@@auo_fb_mmap");
|
||
DPRINTK("\n@@@@@@@@@@mmap size=%d\n", vma->vm_end - vma->vm_start);
|
||
vma->vm_ops = &auo_fb_vma_ops;
|
||
vma->vm_flags |= VM_RESERVED;
|
||
auo_fb_vma_open(vma);
|
||
|
||
/* unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
|
||
|
||
if(offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
|
||
vma->vm_flags |= VM_IO;
|
||
|
||
vma->vm_flags |= VM_RESERVED;
|
||
DPRINTK("\noffset=%d",offset);
|
||
offset += S3C24XX_PA_LCD;
|
||
|
||
if(remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot))
|
||
return -EAGAIN;
|
||
*/
|
||
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int auo_fb_is_update_region_legal(void)
|
||
{
|
||
|
||
#ifdef EPD_HW_ROTATE
|
||
|
||
#ifdef EPD_HW_ROTATE_NO_MODE4
|
||
if((w_partial_info.mode == PARTIAL_DSP_MODE_4) || (w_partial_info.mode == PARTIAL_DSP_MODE_4_W))
|
||
{
|
||
if( (w_partial_info.x > (H_RESOLUTION-1)) ||
|
||
(w_partial_info.y > (V_RESOLUTION-1)) ||
|
||
(w_partial_info.w == 0) ||
|
||
(w_partial_info.h == 0) ||
|
||
(w_partial_info.w > H_RESOLUTION) ||
|
||
(w_partial_info.h > V_RESOLUTION))
|
||
return -EINVAL;
|
||
|
||
//fill data to legal region
|
||
if((w_partial_info.x + w_partial_info.w) > H_RESOLUTION)
|
||
w_partial_info.w = H_RESOLUTION - w_partial_info.x;
|
||
|
||
if((w_partial_info.y + w_partial_info.h) > V_RESOLUTION)
|
||
w_partial_info.h = V_RESOLUTION - w_partial_info.y;
|
||
|
||
|
||
if(((w_partial_info.y+1) % 2)==0) //In EPD view, X is not odd
|
||
{
|
||
DPRINTK("\nw_partial_info.y=%d\n",w_partial_info.y);
|
||
w_partial_info.y--;
|
||
w_partial_info.h++; //because w_partial_info.y--
|
||
}
|
||
|
||
if(w_partial_info.h < UPDATE_WIDTH_MIN)
|
||
w_partial_info.h = UPDATE_WIDTH_MIN;
|
||
|
||
if((w_partial_info.h % UPDATE_WIDTH_MULTIPLES) != 0) //In EPD view, w is not times of UPDATE_WIDTH_MULTIPLES
|
||
{
|
||
DPRINTK("\nw_partial_info.h=%d\n",w_partial_info.h);
|
||
int tmp_offset = UPDATE_WIDTH_MULTIPLES - w_partial_info.h%UPDATE_WIDTH_MULTIPLES;
|
||
|
||
w_partial_info.h = w_partial_info.h + tmp_offset;
|
||
|
||
}
|
||
|
||
if(((w_partial_info.y + 1) + w_partial_info.h)> (V_RESOLUTION+1))
|
||
{
|
||
w_partial_info.y = V_RESOLUTION - w_partial_info.h ;
|
||
|
||
//w_partial_info.h = V_RESOLUTION;
|
||
//w_partial_info.y = 0;
|
||
}
|
||
|
||
if(w_partial_info.w < UPDATE_HEIGHT_MIN)
|
||
w_partial_info.w = UPDATE_HEIGHT_MIN;
|
||
|
||
if((((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1) % 2)==0) //In EPD view, Y is not odd
|
||
{
|
||
//w_partial_info.x--;
|
||
w_partial_info.w = w_partial_info.w+1;
|
||
}
|
||
|
||
if((w_partial_info.w % UPDATE_HEIGHT_MULTIPLES) != 0) //In EPD view, h is not times of UPDATE_HEIGHT_MULTIPLES
|
||
{
|
||
DPRINTK("\nw_partial_info.w=%d\n",w_partial_info.w);
|
||
int tmp_offset = UPDATE_HEIGHT_MULTIPLES - w_partial_info.w%UPDATE_HEIGHT_MULTIPLES;
|
||
|
||
w_partial_info.w = w_partial_info.w + tmp_offset;
|
||
w_partial_info.x = w_partial_info.x - tmp_offset;
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
if((((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1) + w_partial_info.w)> (H_RESOLUTION+1))
|
||
{
|
||
w_partial_info.x = H_RESOLUTION - w_partial_info.w ;
|
||
|
||
}
|
||
|
||
|
||
//check (x,y,w,h) again
|
||
if(((w_partial_info.y + 1) < 1) ||
|
||
(((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1) < 1) ||
|
||
(w_partial_info.h < UPDATE_HEIGHT_MIN) ||
|
||
(w_partial_info.w < UPDATE_WIDTH_MIN) ||
|
||
((w_partial_info.y + 1 + w_partial_info.h)>(V_RESOLUTION+1)) ||
|
||
(((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1 + w_partial_info.w)>(H_RESOLUTION+1)) ||
|
||
(((w_partial_info.y+1) % 2)==0) ||
|
||
((((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1) % 2)==0) ||
|
||
((w_partial_info.h % UPDATE_WIDTH_MULTIPLES) != 0) ||
|
||
((w_partial_info.w % UPDATE_HEIGHT_MULTIPLES) != 0)
|
||
)
|
||
{
|
||
printk("\nAUOFB ERROR: (X,Y,W,L)=(%d,%d,%d,%d)",w_partial_info.y + 1, (H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1, w_partial_info.h, w_partial_info.w);
|
||
return -EFAULT;
|
||
|
||
}
|
||
|
||
return 0;
|
||
|
||
}
|
||
#endif
|
||
printk("\nAUOFB: Check coordinator"); //do not remove this printk
|
||
//check (X,Y,W,H) first time
|
||
if( (w_partial_info.x > (H_RESOLUTION-1)) ||
|
||
(w_partial_info.y > (V_RESOLUTION-1)) ||
|
||
(w_partial_info.w == 0) ||
|
||
(w_partial_info.h == 0) ||
|
||
(w_partial_info.w > H_RESOLUTION) ||
|
||
(w_partial_info.h > V_RESOLUTION))
|
||
return -EINVAL;
|
||
|
||
//fill data to legal region
|
||
if((w_partial_info.x + w_partial_info.w) > H_RESOLUTION)
|
||
w_partial_info.w = H_RESOLUTION - w_partial_info.x;
|
||
|
||
if((w_partial_info.y + w_partial_info.h) > V_RESOLUTION)
|
||
w_partial_info.h = V_RESOLUTION - w_partial_info.y;
|
||
|
||
if(((w_partial_info.x+1) % 2)==0) //X is not odd
|
||
{
|
||
DPRINTK("\nw_partial_info.x=%d\n",w_partial_info.x);
|
||
w_partial_info.x--;
|
||
w_partial_info.w++; //because w_partial_info.x--
|
||
}
|
||
/*
|
||
if(w_partial_info.w < 12)
|
||
w_partial_info.w = 12;
|
||
|
||
if((w_partial_info.w % 4) != 0) //w is not times of 4
|
||
{
|
||
DPRINTK("\nw_partial_info.w=%d\n",w_partial_info.w);
|
||
int tmp_offset = 4 - w_partial_info.w%4;
|
||
|
||
w_partial_info.w = w_partial_info.w + tmp_offset;
|
||
|
||
}
|
||
*/
|
||
|
||
if(w_partial_info.w < UPDATE_WIDTH_MIN)
|
||
w_partial_info.w = UPDATE_WIDTH_MIN;
|
||
|
||
if((w_partial_info.w % UPDATE_WIDTH_MULTIPLES) != 0) //w is not times of UPDATE_WIDTH_MULTIPLES
|
||
{
|
||
DPRINTK("\nw_partial_info.w=%d\n",w_partial_info.w);
|
||
int tmp_offset = UPDATE_WIDTH_MULTIPLES - w_partial_info.w%UPDATE_WIDTH_MULTIPLES;
|
||
|
||
w_partial_info.w = w_partial_info.w + tmp_offset;
|
||
|
||
}
|
||
|
||
|
||
//test end
|
||
|
||
|
||
if(((w_partial_info.x + 1) + w_partial_info.w)> (H_RESOLUTION+1))
|
||
{
|
||
w_partial_info.x = H_RESOLUTION - w_partial_info.w ;
|
||
|
||
|
||
}
|
||
|
||
if(w_partial_info.h < UPDATE_HEIGHT_MIN)
|
||
w_partial_info.h = UPDATE_HEIGHT_MIN;
|
||
|
||
if(((w_partial_info.y+1) % 2)==0) //Y is not odd
|
||
{
|
||
if(w_partial_info.y > 3)
|
||
{
|
||
w_partial_info.y = w_partial_info.y -3;
|
||
w_partial_info.h = w_partial_info.h+3;
|
||
}
|
||
else
|
||
{
|
||
w_partial_info.y--;
|
||
w_partial_info.h = w_partial_info.h+1;
|
||
}
|
||
}
|
||
|
||
/*
|
||
if((w_partial_info.h % 2) != 0) //h is not times of 2
|
||
{
|
||
DPRINTK("\nw_partial_info.h=%d\n",w_partial_info.h);
|
||
int tmp_offset = 2 - w_partial_info.h%2;
|
||
|
||
w_partial_info.h = w_partial_info.h + tmp_offset;
|
||
|
||
}
|
||
*/
|
||
|
||
if((w_partial_info.h % UPDATE_HEIGHT_MULTIPLES) != 0) //h is not times of UPDATE_HEIGHT_MULTIPLES
|
||
{
|
||
DPRINTK("\nw_partial_info.h=%d\n",w_partial_info.h);
|
||
int tmp_offset = UPDATE_HEIGHT_MULTIPLES - w_partial_info.h%UPDATE_HEIGHT_MULTIPLES;
|
||
|
||
w_partial_info.h = w_partial_info.h + tmp_offset;
|
||
|
||
}
|
||
|
||
if(((w_partial_info.y + 1) + w_partial_info.h)> (V_RESOLUTION+1))
|
||
{
|
||
w_partial_info.y = V_RESOLUTION - w_partial_info.h ;
|
||
|
||
|
||
}
|
||
|
||
//check (x,y,w,h) again
|
||
if(((w_partial_info.x + 1) < 1) ||
|
||
((w_partial_info.y +1) < 1) ||
|
||
(w_partial_info.w < UPDATE_WIDTH_MIN) ||
|
||
(w_partial_info.h < UPDATE_HEIGHT_MIN) ||
|
||
((w_partial_info.x + 1 + w_partial_info.w)>(H_RESOLUTION+1)) ||
|
||
((w_partial_info.y +1 + w_partial_info.h)>(V_RESOLUTION+1)) ||
|
||
(((w_partial_info.x+1) % 2)==0) ||
|
||
(((w_partial_info.y +1) % 2)==0) ||
|
||
((w_partial_info.w %UPDATE_WIDTH_MULTIPLES) != 0) ||
|
||
// ((w_partial_info.h % 2) != 0)
|
||
((w_partial_info.h % UPDATE_HEIGHT_MULTIPLES) != 0)
|
||
)
|
||
{
|
||
printk("\nAUOFB ERROR 111: (X,Y,W,L)=(%d,%d,%d,%d)",w_partial_info.x + 1, w_partial_info.y + 1, w_partial_info.w, w_partial_info.h);
|
||
return -EFAULT;
|
||
|
||
}
|
||
|
||
#else
|
||
#ifdef AUOFB_ROTATE
|
||
//check (X,Y,W,H) first time
|
||
if( (w_partial_info.x > (H_RESOLUTION-1)) ||
|
||
(w_partial_info.y > (V_RESOLUTION-1)) ||
|
||
(w_partial_info.w == 0) ||
|
||
(w_partial_info.h == 0) ||
|
||
(w_partial_info.w > H_RESOLUTION) ||
|
||
(w_partial_info.h > V_RESOLUTION))
|
||
return -EINVAL;
|
||
|
||
//fill data to legal region
|
||
if((w_partial_info.x + w_partial_info.w) > H_RESOLUTION)
|
||
w_partial_info.w = H_RESOLUTION - w_partial_info.x;
|
||
|
||
if((w_partial_info.y + w_partial_info.h) > V_RESOLUTION)
|
||
w_partial_info.h = V_RESOLUTION - w_partial_info.y;
|
||
|
||
|
||
if(((w_partial_info.y+1) % 2)==0) //In EPD view, X is not odd
|
||
{
|
||
DPRINTK("\nw_partial_info.y=%d\n",w_partial_info.y);
|
||
w_partial_info.y--;
|
||
w_partial_info.h++; //because w_partial_info.y--
|
||
}
|
||
|
||
if(w_partial_info.h < UPDATE_WIDTH_MIN)
|
||
w_partial_info.h = UPDATE_WIDTH_MIN;
|
||
|
||
if((w_partial_info.h % UPDATE_WIDTH_MULTIPLES) != 0) //In EPD view, w is not times of UPDATE_WIDTH_MULTIPLES
|
||
{
|
||
DPRINTK("\nw_partial_info.h=%d\n",w_partial_info.h);
|
||
int tmp_offset = UPDATE_WIDTH_MULTIPLES - w_partial_info.h%UPDATE_WIDTH_MULTIPLES;
|
||
|
||
w_partial_info.h = w_partial_info.h + tmp_offset;
|
||
|
||
}
|
||
|
||
if(((w_partial_info.y + 1) + w_partial_info.h)> (V_RESOLUTION+1))
|
||
{
|
||
w_partial_info.y = V_RESOLUTION - w_partial_info.h ;
|
||
|
||
//w_partial_info.h = V_RESOLUTION;
|
||
//w_partial_info.y = 0;
|
||
}
|
||
|
||
if(w_partial_info.w < UPDATE_HEIGHT_MIN)
|
||
w_partial_info.w = UPDATE_HEIGHT_MIN;
|
||
|
||
if((((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1) % 2)==0) //In EPD view, Y is not odd
|
||
{
|
||
//w_partial_info.x--;
|
||
w_partial_info.w = w_partial_info.w+1;
|
||
}
|
||
|
||
if((w_partial_info.w % UPDATE_HEIGHT_MULTIPLES) != 0) //In EPD view, h is not times of 2
|
||
{
|
||
DPRINTK("\nw_partial_info.w=%d\n",w_partial_info.w);
|
||
int tmp_offset = UPDATE_HEIGHT_MULTIPLES - w_partial_info.w%UPDATE_HEIGHT_MULTIPLES;
|
||
|
||
w_partial_info.w = w_partial_info.w + tmp_offset;
|
||
w_partial_info.x = w_partial_info.x - tmp_offset;
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
if((((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1) + w_partial_info.w)> (H_RESOLUTION+1))
|
||
{
|
||
w_partial_info.x = H_RESOLUTION - w_partial_info.w ;
|
||
|
||
}
|
||
|
||
|
||
//check (x,y,w,h) again
|
||
if(((w_partial_info.y + 1) < 1) ||
|
||
(((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1) < 1) ||
|
||
(w_partial_info.h < UPDATE_WIDTH_MIN) ||
|
||
(w_partial_info.w < UPDATE_HEIGHT_MIN) ||
|
||
((w_partial_info.y + 1 + w_partial_info.h)>(V_RESOLUTION+1)) ||
|
||
(((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1 + w_partial_info.w)>(H_RESOLUTION+1)) ||
|
||
(((w_partial_info.y+1) % 2)==0) ||
|
||
((((H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1) % 2)==0) ||
|
||
((w_partial_info.h % UPDATE_WIDTH_MULTIPLES) != 0) ||
|
||
((w_partial_info.w % UPDATE_HEIGHT_MULTIPLES) != 0)
|
||
)
|
||
{
|
||
printk("\nAUOFB ERROR: (X,Y,W,L)=(%d,%d,%d,%d)",w_partial_info.y + 1, (H_RESOLUTION - (w_partial_info.x) - w_partial_info.w) +1, w_partial_info.h, w_partial_info.w);
|
||
return -EFAULT;
|
||
|
||
}
|
||
|
||
#endif //#ifdef AUOFB_ROTATE
|
||
#endif //#ifdef EPD_HW_ROTATE
|
||
|
||
return 0;
|
||
}
|
||
|
||
#ifdef EPD_ENABLE_PRE_DISPLAY
|
||
int auo_fb_pre_display(void)
|
||
{
|
||
if ( 0 == LOCK_AUOFB_ENTRY() )
|
||
{
|
||
_partial_update_info tmp_partial_info;
|
||
|
||
tmp_partial_info.x = 0;
|
||
tmp_partial_info.y = 0;
|
||
tmp_partial_info.w = H_RESOLUTION;
|
||
tmp_partial_info.h = V_RESOLUTION;
|
||
tmp_partial_info.mode = 0;
|
||
tmp_partial_info.u16EpaperCommand = AUO_EPAPER_CMD_PRE_DISPLAY_START;
|
||
Epaper_Set_Partial_Update_Mode(tmp_partial_info.mode);
|
||
|
||
if(!auofb_update_queue_is_full())
|
||
auofb_update_queue_put(tmp_partial_info);
|
||
|
||
LOCK_AUOFB_EXIT();
|
||
}
|
||
|
||
|
||
// don't wakeup display thread.
|
||
//wake_update_display_thread(); w
|
||
//printk("\nauo_fb_pre_display\n");
|
||
|
||
|
||
}
|
||
#endif
|
||
|
||
#if defined(EPD_ENABLE_PRE_DISPLAY)
|
||
/*****************************************************************************/
|
||
void auo_fb_put_epd_init_command(void)
|
||
{
|
||
// printk("*** +%s\n", __func__);
|
||
if ( 0 == LOCK_AUOFB_ENTRY() )
|
||
{
|
||
_partial_update_info tmp_partial_info;
|
||
|
||
tmp_partial_info.x = 0;
|
||
tmp_partial_info.y = 0;
|
||
tmp_partial_info.w = 0;
|
||
tmp_partial_info.h = 0;
|
||
tmp_partial_info.mode = 0;
|
||
tmp_partial_info.u16EpaperCommand = AUO_EPAPER_CMD_INIT;
|
||
|
||
if(!auofb_update_queue_is_full())
|
||
{
|
||
// printk("*** %s: put init command\n", __func__);
|
||
auofb_update_queue_put(tmp_partial_info);
|
||
}
|
||
|
||
LOCK_AUOFB_EXIT();
|
||
}
|
||
// printk("*** -%s\n", __func__);
|
||
}
|
||
/*****************************************************************************/
|
||
#endif
|
||
|
||
int auo_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
|
||
{
|
||
struct auo_fb_info *fbi = container_of(info, struct auo_fb_info, fb);
|
||
struct fb_var_screeninfo *var= &fbi->fb.var;
|
||
|
||
void __user *argp = (void __user *)arg;
|
||
|
||
struct vm_area_struct *tvma;
|
||
struct page *tpage;
|
||
u_int virt_addr, phys_addr, offset;
|
||
struct mm_struct *mm = current->mm;
|
||
|
||
int brightness;
|
||
auo_win_info_t win_info_from_app;
|
||
auo_color_key_info_t colkey_info;
|
||
auo_color_val_info_t colval_info;
|
||
bool panel_status;
|
||
|
||
/*
|
||
0xFF00 ~ 0xFF7F : Control TCON
|
||
0xFF80 ~ 0xFF9F : Customer
|
||
0xFFA0 ~ 0xFFDF : Read info from TCON
|
||
0xFFE0 ~ 0xFFFF : Utility or test
|
||
*/
|
||
switch(cmd){
|
||
/* [MTR] */
|
||
case IOCTL_AUO_SENDCOMMAND:
|
||
{
|
||
sAUOCommand cmd;
|
||
unsigned char buffer[2048];
|
||
unsigned char *user_buffer;
|
||
unsigned long user_buflen, copysize, copysize16;
|
||
unsigned short *ptr16;
|
||
|
||
if (copy_from_user (&cmd, argp, sizeof(cmd)))
|
||
return -EFAULT;
|
||
|
||
/* Now execute the command */
|
||
Epaper_sendCommandStart(&cmd);
|
||
|
||
///INFOL(INFO_VERBOSE, ("/* Seventh: Send data if needed */"));
|
||
if (GET_COMMAND_HAVE_DATA(cmd.cmd) != 0)
|
||
{
|
||
//INFOL(INFO_VERBOSE, ("Yes, we have data to send!"));
|
||
user_buflen = cmd.datalen;
|
||
user_buffer = (unsigned char *)cmd.data;
|
||
|
||
while (user_buflen != 0)
|
||
{
|
||
copysize = user_buflen;
|
||
|
||
if (user_buflen > sizeof(buffer))
|
||
copysize = sizeof(buffer);
|
||
|
||
if ( copy_from_user(buffer, user_buffer, copysize) )
|
||
return -EFAULT;
|
||
|
||
copysize16 = (copysize + 1) / 2;
|
||
//printk(KERN_ERR "cp16=%ld cp=%ld\n", copysize16, copysize);
|
||
|
||
ptr16 = (unsigned short *) buffer;
|
||
|
||
Epaper_sendData(buffer, copysize16);
|
||
|
||
user_buflen -= copysize;
|
||
user_buffer += copysize;
|
||
}
|
||
}
|
||
|
||
|
||
Epaper_sendCommandEnd(&cmd);
|
||
}
|
||
break;
|
||
/* [/MTR] */
|
||
//*********************************************************************************
|
||
case AUOFB_IOCTL_TCON_GET_BUSY_STATUS: //busy pin
|
||
|
||
panel_status = is_Epaper_Write_Ready_No_Wait();
|
||
if(copy_to_user((void *)arg, (const void *) &panel_status, sizeof(bool)))
|
||
return -EFAULT;
|
||
break;
|
||
case AUOFB_IOCTL_SW_REFRESH:
|
||
//DPRINTK("\nAUOFB full update!!!");
|
||
if ( 0 == LOCK_AUOFB_ENTRY() )
|
||
{
|
||
w_partial_info.x = 0;
|
||
w_partial_info.y = 0;
|
||
w_partial_info.w = H_RESOLUTION;
|
||
w_partial_info.h = V_RESOLUTION;
|
||
w_partial_info.mode = 0;
|
||
Epaper_Set_Partial_Update_Mode(w_partial_info.mode);
|
||
w_partial_info.u16EpaperCommand = AUO_EPAPER_CMD_PARTIALDISP;
|
||
|
||
if(!auofb_update_queue_is_full())
|
||
auofb_update_queue_put(w_partial_info);
|
||
|
||
LOCK_AUOFB_EXIT();
|
||
}
|
||
|
||
wake_update_display_thread();
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_PARTIAL_UPDATE:
|
||
DPRINTK("\nAUOFB partial update!!!");
|
||
|
||
if ( 0 == LOCK_AUOFB_ENTRY() )
|
||
{
|
||
//if(is_Epaper_Write_Ready())
|
||
{
|
||
|
||
if(copy_from_user(&w_partial_info, (_partial_update_info *) arg, sizeof(_partial_update_info)))
|
||
return -EFAULT;
|
||
|
||
DPRINTK("\nAUOFB partial update, (%d,%d,%d,%d,%d)!!!",
|
||
w_partial_info.mode, w_partial_info.x, w_partial_info.y, w_partial_info.w, w_partial_info.h);
|
||
|
||
if(auo_fb_is_update_region_legal() != 0)
|
||
{
|
||
LOCK_AUOFB_EXIT();
|
||
return -EFAULT;
|
||
}
|
||
|
||
if( (w_partial_info.w*w_partial_info.h) >= u32FullUpdateThreshold )
|
||
{
|
||
w_partial_info.x = 0;
|
||
w_partial_info.y = 0;
|
||
w_partial_info.w = H_RESOLUTION;
|
||
w_partial_info.h = V_RESOLUTION;
|
||
}
|
||
|
||
Epaper_Set_Partial_Update_Mode(w_partial_info.mode);
|
||
|
||
w_partial_info.u16EpaperCommand = AUO_EPAPER_CMD_PARTIALDISP;
|
||
|
||
if(!auofb_update_queue_is_full())
|
||
auofb_update_queue_put(w_partial_info);
|
||
}
|
||
|
||
|
||
LOCK_AUOFB_EXIT();
|
||
}
|
||
|
||
|
||
wake_update_display_thread();
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_SHUTDOWN: //shutdown TCON
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
//AUO T-CON Standby
|
||
msleep(100);
|
||
Epaper_Enter_Standby_Mode(1);
|
||
|
||
msleep(100);
|
||
|
||
//AUO T-CON Sleep
|
||
Epaper_Enter_Sleep_Mode(1);
|
||
|
||
msleep(5);
|
||
|
||
//Shutdown T-CON Power
|
||
Epaper_Power(0);
|
||
|
||
//Shutdown i80 of s3c
|
||
EPaper_CloseLcdPort();
|
||
|
||
//msleep(1000);
|
||
|
||
u32PowerState = EN_EPD_DEVICE_POWER_STATE_D3;
|
||
}
|
||
else
|
||
return -EFAULT;
|
||
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_STANDBY: //TCON Standby
|
||
|
||
if(u32PowerState == EN_EPD_DEVICE_POWER_STATE_D0)
|
||
{
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
msleep(100);
|
||
Epaper_Enter_Standby_Mode(1);
|
||
msleep(100); //TCON need at least 64ms to enter standby mode
|
||
|
||
u32PowerState = EN_EPD_DEVICE_POWER_STATE_D1;
|
||
}
|
||
else
|
||
return -EFAULT;
|
||
}
|
||
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_WAKEUP: //TCON Wakeup (leave standby)
|
||
if(u32PowerState == EN_EPD_DEVICE_POWER_STATE_D1)
|
||
{
|
||
Epaper_Enter_Standby_Mode(0);
|
||
msleep(100);
|
||
u32PowerState = EN_EPD_DEVICE_POWER_STATE_D0;
|
||
}
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_SLEEP: //TCON Sleep
|
||
if(u32PowerState == EN_EPD_DEVICE_POWER_STATE_D1)
|
||
{
|
||
Epaper_Enter_Sleep_Mode(1);
|
||
msleep(5);
|
||
u32PowerState = EN_EPD_DEVICE_POWER_STATE_D2;
|
||
}
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_NO_SLEEP: //TCON no Sleep
|
||
if(u32PowerState == EN_EPD_DEVICE_POWER_STATE_D2)
|
||
{
|
||
Epaper_Enter_Sleep_Mode(0);
|
||
msleep(5);
|
||
u32PowerState = EN_EPD_DEVICE_POWER_STATE_D1;
|
||
}
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_REFRESH: //Display refresh
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Display_Refresh();
|
||
else
|
||
return -EFAULT;
|
||
break;
|
||
|
||
case AUOFB_IOCTL_SET_UPDATE_THRESHOLD: //Set u32FullUpdateThreshold
|
||
if(copy_from_user(&u32FullUpdateThreshold, (unsigned long*) arg, sizeof(unsigned long)))
|
||
return -EFAULT;
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_RESET: //TCON RESET command
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Reset();
|
||
else
|
||
return -EFAULT;
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_INIT:
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_UPDATE_LUT:
|
||
{
|
||
unsigned char* lut_data = NULL;
|
||
|
||
lut_data = __get_free_pages(GFP_KERNEL, get_order(AUO_LUT_LENGTH));
|
||
if(lut_data == NULL)
|
||
{
|
||
return -EFAULT;
|
||
}
|
||
|
||
if(copy_from_user(lut_data, (unsigned char*) arg, AUO_LUT_LENGTH))
|
||
{
|
||
free_pages((unsigned long)lut_data, get_order(AUO_LUT_LENGTH));
|
||
return -EFAULT;
|
||
}
|
||
|
||
Epaper_Update_LUT((unsigned short*)lut_data,AUO_LUT_LENGTH/2 );
|
||
|
||
|
||
free_pages((unsigned long)lut_data, get_order(AUO_LUT_LENGTH));
|
||
|
||
break;
|
||
}
|
||
|
||
case AUOFB_IOCTL_TCON_POWER_STATE:
|
||
{
|
||
unsigned long UserPowerState = 0;
|
||
if(copy_from_user(&UserPowerState, (unsigned long*) arg, sizeof(unsigned long)))
|
||
return -EFAULT;
|
||
|
||
switch(u32PowerState)
|
||
{
|
||
case EN_EPD_DEVICE_POWER_STATE_D0:
|
||
|
||
switch(UserPowerState)
|
||
{
|
||
case EN_EPD_DEVICE_POWER_STATE_D0:
|
||
//do nothing
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D1:
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
msleep(100);
|
||
Epaper_Enter_Standby_Mode(1);
|
||
msleep(100); //TCON need at least 64ms to enter standby mode
|
||
}
|
||
else
|
||
return -EFAULT;
|
||
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D2:
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
//AUO T-CON Standby
|
||
msleep(100);
|
||
Epaper_Enter_Standby_Mode(1);
|
||
|
||
msleep(100);
|
||
|
||
//AUO T-CON Sleep
|
||
Epaper_Enter_Sleep_Mode(1);
|
||
msleep(5);
|
||
|
||
}
|
||
else
|
||
return -EFAULT;
|
||
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D3:
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
//AUO T-CON Standby
|
||
msleep(100);
|
||
Epaper_Enter_Standby_Mode(1);
|
||
|
||
msleep(100);
|
||
|
||
//AUO T-CON Sleep
|
||
Epaper_Enter_Sleep_Mode(1);
|
||
|
||
msleep(5);
|
||
|
||
//Shutdown T-CON Power
|
||
Epaper_Power(0);
|
||
|
||
//Shutdown i80 of s3c
|
||
EPaper_CloseLcdPort();
|
||
|
||
//msleep(1000);
|
||
}
|
||
else
|
||
return -EFAULT;
|
||
|
||
break;
|
||
|
||
default:
|
||
return -EFAULT;
|
||
|
||
}
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D1:
|
||
|
||
switch(UserPowerState)
|
||
{
|
||
case EN_EPD_DEVICE_POWER_STATE_D0:
|
||
|
||
Epaper_Enter_Standby_Mode(0);
|
||
|
||
msleep(100);
|
||
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D1:
|
||
//do nothing
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D2:
|
||
Epaper_Enter_Sleep_Mode(1);
|
||
msleep(5);
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D3:
|
||
|
||
Epaper_Enter_Sleep_Mode(1);
|
||
|
||
msleep(5);
|
||
|
||
//Shutdown T-CON Power
|
||
Epaper_Power(0);
|
||
|
||
//Shutdown i80 of s3c
|
||
EPaper_CloseLcdPort();
|
||
|
||
//msleep(1000);
|
||
break;
|
||
|
||
default:
|
||
return -EFAULT;
|
||
|
||
}
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D2:
|
||
|
||
switch(UserPowerState)
|
||
{
|
||
case EN_EPD_DEVICE_POWER_STATE_D0:
|
||
|
||
Epaper_Enter_Sleep_Mode(0);
|
||
|
||
msleep(5);
|
||
|
||
Epaper_Enter_Standby_Mode(0);
|
||
|
||
msleep(100);
|
||
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D1:
|
||
|
||
Epaper_Enter_Sleep_Mode(0);
|
||
|
||
msleep(5);
|
||
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D2:
|
||
//do nothing
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D3:
|
||
|
||
//Shutdown T-CON Power
|
||
Epaper_Power(0);
|
||
|
||
//Shutdown i80 of s3c
|
||
EPaper_CloseLcdPort();
|
||
|
||
//msleep(1000);
|
||
|
||
break;
|
||
|
||
default:
|
||
return -EFAULT;
|
||
|
||
}
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D3:
|
||
|
||
switch(UserPowerState)
|
||
{
|
||
case EN_EPD_DEVICE_POWER_STATE_D0:
|
||
|
||
msleep(100);
|
||
|
||
#ifdef EPD_HW_ROTATE
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 90, 0, 0, 0, 0, 0);
|
||
#else
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 0, 0, 0, 0, 0, 0);
|
||
#endif
|
||
|
||
#ifdef EPD_ENABLE_PRE_DISPLAY
|
||
|
||
atomic_set(&gPowerOnFirstDisplay, 1);
|
||
|
||
auo_fb_pre_display();
|
||
#endif
|
||
break;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D1:
|
||
//not allowed
|
||
return -EFAULT;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D2:
|
||
//not allowed
|
||
return -EFAULT;
|
||
|
||
case EN_EPD_DEVICE_POWER_STATE_D3:
|
||
//do nothing
|
||
break;
|
||
|
||
default:
|
||
return -EFAULT;
|
||
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return -EFAULT;
|
||
|
||
}
|
||
u32PowerState = UserPowerState;
|
||
|
||
break;
|
||
}
|
||
//*********************************************************************************
|
||
|
||
case AUOFB_IOCTL_TCON_GET_TEMPERATURE: //Get Tempterature
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Read_R_TEMP(&u16Temperature,&u16EPDType,&u16PanelType,&u16LUTVersion);
|
||
|
||
if(copy_to_user((void *)arg, (const void *) &u16Temperature, sizeof(unsigned short)))
|
||
return -EFAULT;
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_GET_EPD_TYPE: //Get EPD type
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Read_R_TEMP(&u16Temperature,&u16EPDType,&u16PanelType,&u16LUTVersion);
|
||
|
||
if(copy_to_user((void *)arg, (const void *) &u16EPDType, sizeof(unsigned short)))
|
||
return -EFAULT;
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_GET_PANEL_TYPE: //Get Panel type
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Read_R_TEMP(&u16Temperature,&u16EPDType,&u16PanelType,&u16LUTVersion);
|
||
|
||
if(copy_to_user((void *)arg, (const void *) &u16PanelType, sizeof(unsigned short)))
|
||
return -EFAULT;
|
||
break;
|
||
|
||
case AUOFB_IOCTL_TCON_GET_LUT_INFO: //Get LUT version
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Read_R_TEMP(&u16Temperature,&u16EPDType,&u16PanelType,&u16LUTVersion);
|
||
|
||
if(copy_to_user((void *)arg, (const void *) &u16LUTVersion, sizeof(unsigned short)))
|
||
return -EFAULT;
|
||
break;
|
||
|
||
|
||
//*********************************************************************************
|
||
case AUOFB_IOCTL_SHOW_PROGRESS_BAR:
|
||
{
|
||
int percent = 0;
|
||
if(copy_from_user(&percent, (int *) arg, sizeof(int)))
|
||
return -EFAULT;
|
||
|
||
//Epaper_Show_Progress(percent);
|
||
break;
|
||
}
|
||
|
||
case AUOFB_IOCTL_CLEAN_EPD:
|
||
{
|
||
Epaper_Clean_Panel();
|
||
break;
|
||
}
|
||
/* Qisda, Howard Hsu, 2010/01/11, Add show image ioctrl { */
|
||
case AUOFB_IOCTL_SHOW_IMAGE:
|
||
{
|
||
T_DISPLAY_FRAME stDisFrame;
|
||
_partial_update_info partial_info;
|
||
unsigned long pic_array_size = 0;
|
||
unsigned long pic_array_max = AUO_EPAPER_PHYSICAL_H_RESOLUTION*AUO_EPAPER_PHYSICAL_V_RESOLUTION/2;
|
||
unsigned char *pic_array = vmalloc(pic_array_max, GFP_KERNEL);
|
||
|
||
if(copy_from_user(&partial_info, (_partial_update_info *) arg, sizeof(_partial_update_info)))
|
||
return -EFAULT;
|
||
if(copy_from_user(&pic_array_size, (unsigned long*) ((char *)arg+sizeof(_partial_update_info)), sizeof(unsigned long)))
|
||
return -EFAULT;
|
||
if(copy_from_user(pic_array, (char*) ((char *)arg+sizeof(_partial_update_info)+sizeof(unsigned long)), pic_array_size))
|
||
return -EFAULT;
|
||
|
||
stDisFrame.u16EpaperCommand = AUO_EPAPER_CMD_PARTIALDISP;
|
||
Epaper_Set_Partial_Update_Mode(partial_info.mode);
|
||
stDisFrame.tFrameRange.W = partial_info.w;
|
||
stDisFrame.tFrameRange.H = partial_info.h;
|
||
stDisFrame.tFrameRange.X = partial_info.x;
|
||
stDisFrame.tFrameRange.Y = partial_info.y;
|
||
if ( partial_info.x==0 || partial_info.y==0)
|
||
{
|
||
stDisFrame.tFrameRange.X = (H_RESOLUTION-partial_info.w)/2;
|
||
stDisFrame.tFrameRange.Y = (V_RESOLUTION-partial_info.h)/2;
|
||
if((stDisFrame.tFrameRange.X % 2) == 0)
|
||
stDisFrame.tFrameRange.X ++;
|
||
if((stDisFrame.tFrameRange.Y % 2) == 0)
|
||
stDisFrame.tFrameRange.Y ++;
|
||
}
|
||
stDisFrame.pFrameData = (unsigned short*)pic_array;
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
printk("Show Image on EPD\n");
|
||
Epaper_Disp(stDisFrame);
|
||
}
|
||
else
|
||
{
|
||
printk("EPD not ready to show Image\n");
|
||
}
|
||
vfree(pic_array);
|
||
break;
|
||
}
|
||
/* } Qisda, Howard Hsu, 2010/01/11, Add show image ioctrl */
|
||
|
||
default:
|
||
return -EINVAL;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/* ------------------------------------------------------------------------- */
|
||
|
||
/*
|
||
* Frame buffer operations
|
||
*/
|
||
|
||
static struct fb_ops auofb_ops = {
|
||
.owner = THIS_MODULE,
|
||
.fb_check_var = auofb_check_var,
|
||
.fb_set_par = auofb_set_par,
|
||
.fb_blank = auofb_blank,
|
||
.fb_pan_display = auofb_pan_display,
|
||
.fb_setcolreg = auofb_setcolreg,
|
||
.fb_fillrect = cfb_fillrect,
|
||
.fb_copyarea = cfb_copyarea,
|
||
.fb_imageblit = cfb_imageblit,
|
||
//.fb_cursor = soft_cursor,
|
||
.fb_ioctl = auo_fb_ioctl,
|
||
.fb_mmap = auo_fb_mmap,
|
||
};
|
||
|
||
/* ------------------------------------------------------------------------- */
|
||
|
||
struct fb_monspecs monspecs __initdata = {
|
||
.hfmin = 30000,
|
||
.hfmax = 70000,
|
||
.vfmin = 50,
|
||
.vfmax = 65,
|
||
};
|
||
|
||
|
||
struct page *vmalloc_2_page(void *addr)
|
||
{
|
||
unsigned long lpage;
|
||
pgd_t *pgd;
|
||
pmd_t *pmd;
|
||
pte_t *pte;
|
||
struct page *page;
|
||
|
||
lpage = (unsigned long)(addr);
|
||
spin_lock(&init_mm.page_table_lock);
|
||
|
||
pgd = pgd_offset(&init_mm, lpage);
|
||
pmd = pmd_offset(pgd, lpage);
|
||
pte = pte_offset_map(pmd, lpage);
|
||
page = pte_page(*pte);
|
||
|
||
spin_unlock(&init_mm.page_table_lock);
|
||
|
||
return page;
|
||
|
||
//return vmalloc_to_page(addr);
|
||
}
|
||
|
||
int init_page_array(void)
|
||
{
|
||
int i;
|
||
|
||
numpages = (videomemorysize >> PAGE_SHIFT) + 1;
|
||
|
||
videopages = kmalloc(numpages * sizeof(struct page *), GFP_KERNEL);
|
||
if (videopages == NULL) {
|
||
return 1;
|
||
}
|
||
|
||
for (i = 0; (i << PAGE_SHIFT) < videomemorysize; i++) {
|
||
videopages[i] = vmalloc_2_page(pu8Framebuffer + (i << PAGE_SHIFT));
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int clear_page_array(void)
|
||
{
|
||
if (videopages != NULL) {
|
||
kfree(videopages);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void auo_fb_init_fbinfo(struct auo_fb_info *finfo, char *drv_name, int index)
|
||
{
|
||
int i = 0;
|
||
|
||
//Epaper is open at boot code
|
||
|
||
|
||
#ifdef EPD_HW_ROTATE
|
||
//Epaper_Reset();
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 90, 0, 0, 0, 0, 0);
|
||
#else
|
||
//Epaper_Reset();
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 0, 0, 0, 0, 0, 0);
|
||
#endif
|
||
strcpy(finfo->fb.fix.id, drv_name);
|
||
|
||
finfo->win_id = index;
|
||
finfo->fb.fix.type = FB_TYPE_PACKED_PIXELS;
|
||
finfo->fb.fix.type_aux = 0;
|
||
finfo->fb.fix.xpanstep = 0;
|
||
finfo->fb.fix.ypanstep = 0;
|
||
finfo->fb.fix.ywrapstep = 0;
|
||
finfo->fb.fix.accel = FB_ACCEL_NONE;
|
||
|
||
finfo->fb.fbops = &auofb_ops;
|
||
finfo->fb.flags = FBINFO_FLAG_DEFAULT;
|
||
finfo->fb.monspecs = monspecs;
|
||
finfo->fb.pseudo_palette = &finfo->pseudo_pal;
|
||
|
||
finfo->fb.var.nonstd = 0;
|
||
finfo->fb.var.activate = FB_ACTIVATE_NOW;
|
||
finfo->fb.var.accel_flags = 0;
|
||
finfo->fb.var.vmode = FB_VMODE_NONINTERLACED;
|
||
|
||
finfo->fb.var.xoffset = auo_mach_info.xoffset;
|
||
finfo->fb.var.yoffset = auo_mach_info.yoffset;
|
||
|
||
if(index==0){
|
||
finfo->fb.var.height = auo_mach_info.height;
|
||
finfo->fb.var.width = auo_mach_info.width;
|
||
|
||
finfo->fb.var.xres = auo_mach_info.xres;
|
||
finfo->fb.var.xres_virtual = auo_mach_info.xres_virtual;
|
||
|
||
finfo->fb.var.yres = auo_mach_info.yres;
|
||
finfo->fb.var.yres_virtual = auo_mach_info.yres_virtual;
|
||
}
|
||
else{
|
||
finfo->fb.var.height = auo_mach_info.osd_height;
|
||
finfo->fb.var.width = auo_mach_info.osd_width;
|
||
|
||
finfo->fb.var.xres = auo_mach_info.osd_xres;
|
||
finfo->fb.var.xres_virtual = auo_mach_info.osd_xres_virtual;
|
||
|
||
finfo->fb.var.yres = auo_mach_info.osd_yres;
|
||
finfo->fb.var.yres_virtual = auo_mach_info.osd_yres_virtual;
|
||
}
|
||
|
||
finfo->fb.var.bits_per_pixel = auo_mach_info.bpp;
|
||
finfo->fb.var.pixclock = auo_mach_info.pixclock;
|
||
finfo->fb.var.hsync_len = auo_mach_info.hsync_len;
|
||
finfo->fb.var.left_margin = auo_mach_info.left_margin;
|
||
finfo->fb.var.right_margin = auo_mach_info.right_margin;
|
||
finfo->fb.var.vsync_len = auo_mach_info.vsync_len;
|
||
finfo->fb.var.upper_margin = auo_mach_info.upper_margin;
|
||
finfo->fb.var.lower_margin = auo_mach_info.lower_margin;
|
||
finfo->fb.var.sync = auo_mach_info.sync;
|
||
finfo->fb.var.grayscale = auo_mach_info.cmap_grayscale;
|
||
|
||
|
||
videomemorysize = finfo->fb.fix.smem_len = finfo->fb.var.xres_virtual * finfo->fb.var.yres_virtual *
|
||
auo_mach_info.bytes_per_pixel;
|
||
//DPRINTK("\nsmem_len=%d * %d * %d", finfo->fb.var.xres_virtual, finfo->fb.var.yres_virtual, auo_mach_info.bytes_per_pixel);
|
||
finfo->fb.fix.line_length = finfo->fb.var.width * auo_mach_info.bytes_per_pixel;
|
||
|
||
for (i = 0; i < 256; i++)
|
||
finfo->palette_buffer[i] = PALETTE_BUFF_CLEAR;
|
||
|
||
}
|
||
|
||
|
||
/* static int __init xxfb_probe (struct device *device) -- for platform devs */
|
||
int __init auo_fb_probe(struct platform_device *pdev)
|
||
{
|
||
char driver_name[]="s3c_fb";
|
||
int ret,i;
|
||
int index=0;
|
||
|
||
DPRINTK("\n!!!!!!!!!!!init AUO EINK");
|
||
|
||
|
||
|
||
auo_fb_init_fbinfo(&info, driver_name, 0);
|
||
|
||
#ifdef FRAMEBUFFER_DMA
|
||
if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c-lcd")) {
|
||
ret = -EBUSY;
|
||
return ret;
|
||
}
|
||
|
||
auofb_basic_display_setting(0,0);
|
||
#endif
|
||
/*
|
||
* Dynamically allocate info and par
|
||
*/
|
||
//pu8Framebuffer = vmalloc(800*600*3);
|
||
///pu8Framebuffer = vmalloc(info.fb.fix.smem_len);
|
||
pu8Framebuffer = vmalloc(V_RESOLUTION*H_RESOLUTION*2);
|
||
|
||
#ifdef FRAMEBUFFER_DMA
|
||
pu16Translatebuffer = cpu_VideoPhysicalTemp_f1;
|
||
#else
|
||
pu16Translatebuffer = vmalloc(V_RESOLUTION*H_RESOLUTION/2);
|
||
#endif
|
||
|
||
pu8RotateBuffer = vmalloc(V_RESOLUTION*H_RESOLUTION*2);
|
||
|
||
/*
|
||
* Here we set the screen_base to the virtual memory address
|
||
* for the framebuffer. Usually we obtain the resource address
|
||
* from the bus layer and then translate it to virtual memory
|
||
* space via ioremap. Consult ioport.h.
|
||
*/
|
||
info.fb.screen_base = pu8Framebuffer;
|
||
//pu8Framebuffer = info.fb.screen_base = ioremap_nocache(S3C24XX_PA_LCD, SZ_1M);
|
||
info.fb.fbops = &auofb_ops;
|
||
|
||
info.fb.fix.smem_start = (unsigned long)pu8Framebuffer;
|
||
///info.fb.fix.smem_start =S3C24XX_PA_LCD;
|
||
|
||
|
||
/*
|
||
* Set up flags to indicate what sort of acceleration your
|
||
* driver can provide (pan/wrap/copyarea/etc.) and whether it
|
||
* is a module -- see FBINFO_* in include/linux/fb.h
|
||
*
|
||
* If your hardware can support any of the hardware accelerated functions
|
||
* fbcon performance will improve if info->flags is set properly.
|
||
*
|
||
* FBINFO_HWACCEL_COPYAREA - hardware moves
|
||
* FBINFO_HWACCEL_FILLRECT - hardware fills
|
||
* FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion
|
||
* FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis
|
||
* FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis
|
||
* FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled
|
||
* FBINFO_READS_FAST - if set, prefer moves over mono->color expansion
|
||
* FBINFO_MISC_TILEBLITTING - hardware can do tile blits
|
||
*
|
||
* NOTE: These are for fbcon use only.
|
||
*/
|
||
|
||
init_page_array();
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/* This has to been done !!! */
|
||
fb_alloc_cmap(&info.fb.cmap, 256, 0);
|
||
|
||
//Ivan test
|
||
sema_init(&vma_list_semaphore, 1);
|
||
|
||
/*
|
||
* For drivers that can...
|
||
*/
|
||
auofb_check_var(&info.fb.var, &info.fb);
|
||
|
||
/* The TCON MUST be inited before anythings! We can't wait for the
|
||
* bootloader to do all the things for us!! */
|
||
Epaper_SetLcdPort();
|
||
|
||
/*
|
||
* Does a call to fb_set_par() before register_framebuffer needed? This
|
||
* will depend on you and the hardware. If you are sure that your driver
|
||
* is the only device in the system, a call to fb_set_par() is safe.
|
||
*
|
||
* Hardware in x86 systems has a VGA core. Calling set_par() at thisEpaper_Enter_Sleep_Mode(1);
|
||
* point will corrupt the VGA console, so it might be safer to skip a
|
||
* call to set_par here and just allow fbcon to do it for you.
|
||
*/
|
||
/* auofb_set_par(info); */
|
||
|
||
if (register_framebuffer(&info.fb) < 0)
|
||
return -EINVAL;
|
||
|
||
//start_update_display_thread();
|
||
|
||
//timer
|
||
/*
|
||
init_timer(&panel_timer_qisda);
|
||
panel_timer_qisda.function =panel_timer_handler_qisda;
|
||
INIT_WORK(&workq_panel_update,panel_update_workqueue);
|
||
|
||
panel_timer_qisda.expires = jiffies + (2*HZ);
|
||
add_timer(&panel_timer_qisda);
|
||
*/
|
||
|
||
u32PowerState = EN_EPD_DEVICE_POWER_STATE_D0;
|
||
memset((unsigned char*)partial_info_queue, 0x0, sizeof(_partial_update_info)*PARTIAL_INFO_QUEUE_SIZE);
|
||
|
||
//refresh logo
|
||
|
||
if ( 0 == LOCK_AUOFB_ENTRY() )
|
||
{
|
||
//if(is_Epaper_Write_Ready())
|
||
{
|
||
|
||
w_partial_info.x = 0;
|
||
w_partial_info.y = 0;
|
||
w_partial_info.w = H_RESOLUTION;
|
||
w_partial_info.h = V_RESOLUTION;
|
||
w_partial_info.mode = 0; //test
|
||
w_partial_info.u16EpaperCommand = AUO_EPAPER_CMD_PARTIALDISP;
|
||
|
||
DPRINTK("\nAUOFB partial init, (%d,%d,%d,%d,%d)!!!", w_partial_info.mode, w_partial_info.x, w_partial_info.y, w_partial_info.w, w_partial_info.h);
|
||
Epaper_Set_Partial_Update_Mode(w_partial_info.mode);
|
||
}
|
||
|
||
LOCK_AUOFB_EXIT();
|
||
}
|
||
|
||
auofb_update_queue_put(w_partial_info);
|
||
|
||
wake_update_display_thread();
|
||
|
||
#ifdef CONFIG_LOGO_LINUX_SH060B00_6_INCH_CLUT224
|
||
#else
|
||
//start_boot_progress_bar_thread();
|
||
#endif
|
||
|
||
if(is_Epaper_Write_Ready())
|
||
Epaper_Read_R_TEMP(&u16Temperature,&u16EPDType,&u16PanelType,&u16LUTVersion);
|
||
printk("\nTCON Temperature=%d\nEPD Type=0x%x\nPanel Type=0x%x\nLUT=0x%x\n", u16Temperature/2,u16EPDType, u16PanelType, u16LUTVersion);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* -----------------------------------------
|
||
* s3c_fb_stop_lcd & s3c_fb_start_lcd
|
||
*
|
||
* shutdown/ start the lcd controller
|
||
*/
|
||
static void s3c_fb_stop_lcd(void)
|
||
{
|
||
unsigned long flags;
|
||
unsigned long tmp;
|
||
|
||
local_irq_save(flags);
|
||
|
||
tmp = __raw_readl(S3C_VIDCON0);
|
||
__raw_writel(tmp & ~(S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE), S3C_VIDCON0);
|
||
|
||
local_irq_restore(flags);
|
||
}
|
||
|
||
void s3c_fb_start_lcd(void) {
|
||
unsigned long flags;
|
||
unsigned long tmp;
|
||
|
||
local_irq_save(flags);
|
||
|
||
tmp = __raw_readl(S3C_VIDCON0);
|
||
__raw_writel(tmp | S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE, S3C_VIDCON0);
|
||
|
||
local_irq_restore(flags);
|
||
}
|
||
|
||
/*
|
||
* Cleanup
|
||
*/
|
||
static int auofb_remove(struct platform_device *pdev)
|
||
{
|
||
struct fb_info *fbinfo = platform_get_drvdata(pdev);
|
||
struct auo_fb_info *info = fbinfo->par;
|
||
int irq;
|
||
int index=0;
|
||
|
||
vfree(pu8Framebuffer);
|
||
|
||
#ifdef FRAMEBUFFER_DMA
|
||
dma_free_writecombine(((struct auo_fb_info *)&info[index])->dev, H_RESOLUTION*V_RESOLUTION/2, cpu_VideoPhysicalTemp_f1, map_VideoPhysicalTemp_f1);
|
||
release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
|
||
#else
|
||
vfree(pu16Translatebuffer);
|
||
#endif
|
||
vfree(pu8RotateBuffer);
|
||
unregister_framebuffer(&(info[index].fb));
|
||
|
||
return 0;
|
||
}
|
||
|
||
#ifdef CONFIG_PM
|
||
|
||
static struct sleep_save lcd_save[] = {
|
||
SAVE_ITEM(S3C_VIDCON0),SAVE_ITEM(S3C_VIDCON1),
|
||
SAVE_ITEM(S3C_VIDTCON0),SAVE_ITEM(S3C_VIDTCON1),
|
||
SAVE_ITEM(S3C_VIDTCON2),SAVE_ITEM(S3C_WINCON0),
|
||
SAVE_ITEM(S3C_WINCON1),
|
||
SAVE_ITEM(S3C_VIDINTCON),SAVE_ITEM(S3C_SYSIFCON0),
|
||
SAVE_ITEM(S3C_SIFCCON0),
|
||
|
||
SAVE_ITEM(S3C_CPUTRIGCON2),SAVE_ITEM(S3C_VIDOSD0A),
|
||
SAVE_ITEM(S3C_VIDOSD0B),SAVE_ITEM(S3C_VIDOSD0C),
|
||
SAVE_ITEM(S3C_VIDOSD1A),SAVE_ITEM(S3C_VIDOSD1B),
|
||
SAVE_ITEM(S3C_VIDOSD1C),SAVE_ITEM(S3C_VIDW00ADD0B0),
|
||
SAVE_ITEM(S3C_VIDW00ADD0B1),SAVE_ITEM(S3C_VIDW01ADD0),
|
||
SAVE_ITEM(S3C_VIDW00ADD1B0),SAVE_ITEM(S3C_VIDW00ADD1B1),
|
||
SAVE_ITEM(S3C_VIDW01ADD1),SAVE_ITEM(S3C_VIDW00ADD2B0),
|
||
SAVE_ITEM(S3C_VIDW00ADD2B1),SAVE_ITEM(S3C_VIDW01ADD2),
|
||
|
||
};
|
||
|
||
|
||
/* suspend and resume support for the AUO T-CON */
|
||
|
||
static int auofb_suspend(struct platform_device *dev, pm_message_t state)
|
||
{
|
||
#if 1
|
||
if(is_Epaper_Write_Ready())
|
||
{
|
||
//Suspend LCD controller
|
||
//s3c_fb_stop_lcd();
|
||
//s3c2410_pm_do_save(lcd_save, ARRAY_SIZE(lcd_save));
|
||
|
||
//AUO T-CON Standby
|
||
msleep(100);
|
||
Epaper_Enter_Standby_Mode(1);
|
||
|
||
msleep(100);
|
||
|
||
//AUO T-CON Sleep
|
||
Epaper_Enter_Sleep_Mode(1);
|
||
|
||
msleep(5);
|
||
|
||
//Shutdown T-CON Power
|
||
Epaper_Power(0);
|
||
|
||
//Shutdown i80 of s3c
|
||
EPaper_CloseLcdPort();
|
||
|
||
//msleep(1000);
|
||
|
||
DPRINTK("\nAUOFB Suspend");
|
||
|
||
u32PowerState = EN_EPD_DEVICE_POWER_STATE_D3;
|
||
|
||
return 0;
|
||
}
|
||
return -EINVAL;
|
||
#else
|
||
//EPaper_CloseLcdPort();
|
||
return 0;
|
||
#endif
|
||
}
|
||
|
||
static int auofb_resume(struct platform_device *dev)
|
||
{
|
||
Epaper_SetLcdPort();
|
||
#if 0
|
||
DPRINTK("\nAUOFB Resume");
|
||
|
||
//AUO T-CON leave standby (If shutdown power of TCON, then do not need to leave standby mode)
|
||
//Epaper_Enter_Standby_Mode(0);
|
||
|
||
//AUO T-CON leave sleep
|
||
//Epaper_Enter_Sleep_Mode(0);
|
||
|
||
msleep(100); //sleep for RST_N pull high
|
||
|
||
u32PowerState = EN_EPD_DEVICE_POWER_STATE_D0;
|
||
|
||
#if defined(EPD_ENABLE_PRE_DISPLAY)
|
||
auo_fb_put_epd_init_command();
|
||
#else
|
||
|
||
#ifdef EPD_HW_ROTATE
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 90, 0, 0, 0, 0, 0);
|
||
#else
|
||
Epaper_Init(AUO_EPAPER_PHYSICAL_H_RESOLUTION, AUO_EPAPER_PHYSICAL_V_RESOLUTION, 0, 0, 0, 0, 0, 0, 0, 0);
|
||
#endif
|
||
|
||
#endif
|
||
|
||
#ifdef EPD_ENABLE_PRE_DISPLAY
|
||
|
||
atomic_set(&gPowerOnFirstDisplay, 1);
|
||
|
||
auo_fb_pre_display();
|
||
#endif
|
||
#endif
|
||
return 0;
|
||
}
|
||
|
||
#define auofb_shutdown NULL
|
||
|
||
#else //no CONFIG_PM
|
||
|
||
#define auofb_shutdown NULL
|
||
#define auofb_suspend NULL
|
||
#define auofb_resume NULL
|
||
|
||
#endif //CONFIG_PM
|
||
|
||
|
||
/* for platform devices */
|
||
static struct platform_driver auo_fb_driver = {
|
||
.probe = auo_fb_probe,
|
||
.remove = auofb_remove,
|
||
.shutdown = auofb_shutdown,
|
||
.suspend = auofb_suspend,
|
||
.resume = auofb_resume,
|
||
.driver = {
|
||
.name = "s3c-lcd",
|
||
.owner = THIS_MODULE,
|
||
},
|
||
};
|
||
|
||
|
||
int __devinit auofb_init(void)
|
||
{
|
||
int ret = 0;
|
||
|
||
return platform_driver_register(&auo_fb_driver);
|
||
|
||
}
|
||
|
||
static void __exit auofb_cleanup(void)
|
||
{
|
||
platform_driver_unregister(&auo_fb_driver);
|
||
}
|
||
|
||
/*
|
||
* Setup
|
||
*/
|
||
|
||
|
||
/*
|
||
* Modularization
|
||
*/
|
||
|
||
|
||
|
||
|
||
module_init(auofb_init);
|
||
module_exit(auofb_cleanup);
|
||
|
||
MODULE_AUTHOR("");
|
||
MODULE_DESCRIPTION("Framebuffer driver for the AUO-EINK");
|
||
MODULE_LICENSE("GPL");
|