基于tiny210v2的linux-3.9.6内核驱动移植3:LCD移植

      友善的tiny210v2我买的是7寸电容屏,具体型号得再查查,说是S70.
      用原本的LINUX内的SMDKV210的LCD驱动能实现LINUX LOGO的输出,但是有一定的偏差。
      主要参考:
              arm9home.net/read.php?tid=27609
        环境:
                UBUNTU 13.04
        内核:
                LINUX-3.9.6
一、修改arch/arm/mach-s5pv210/mach-smdkv210.c
      添加
        //=========================================================//
extern struct s3cfb_lcd *mini210_get_lcd(void);

#defineLCD_WIDTH             800
#defineLCD_HEIGHT             480
#defineBYTES_PER_PIXEL          4
#defineNUM_BUFFER_OVLY       \
      (CONFIG_FB_S3C_NUM_OVLY_WIN * CONFIG_FB_S3C_NUM_BUF_OVLY_WIN)
#defineNUM_BUFFER          \
      (CONFIG_FB_S3C_NR_BUFFERS + NUM_BUFFER_OVLY)
#definePXL2FIMD(pixels)   \
       ((pixels) *BYTES_PER_PIXEL * NUM_BUFFER)

#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC0       ( 6144 *SZ_1K)
#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC1      (   16 * SZ_1K)
#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC2       ( 6144 *SZ_1K)
#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_MFC0       (36864 *SZ_1K)
#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_MFC1       (36864 *SZ_1K)
#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMD      PXL2FIMD(LCD_WIDTH * LCD_HEIGHT)
#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_JPEG       ( 8192 *SZ_1K)
#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_G2D       ( 8192 *SZ_1K)
#defineS5PV210_VIDEO_SAMSUNG_MEMSIZE_TEXSTREAM   ( 4096 * SZ_1K)
#defineS5PV210_ANDROID_PMEM_MEMSIZE_PMEM       ( 5550 *SZ_1K)
#defineS5PV210_ANDROID_PMEM_MEMSIZE_PMEM_GPU1   ( 1800 *SZ_1K)   //3300
#defineS5PV210_ANDROID_PMEM_MEMSIZE_PMEM_ADSP   ( 1500 * SZ_1K)

static struct s5p_media_device smdkv210_media_devs[] = {
#if defined(CONFIG_VIDEO_MFC50)
    {
      .id          =S5P_MDEV_MFC,
      .name       ="mfc",
      .bank       = 0,
      .memsize    =S5PV210_VIDEO_SAMSUNG_MEMSIZE_MFC0,
      .paddr       = 0,
    },
    {
      .id          =S5P_MDEV_MFC,
      .name       ="mfc",
      .bank       = 1,
      .memsize    =S5PV210_VIDEO_SAMSUNG_MEMSIZE_MFC1,
      .paddr       = 0,
    },
#endif
#if defined(CONFIG_VIDEO_FIMC)
    {
      .id          =S5P_MDEV_FIMC0,
      .name       ="fimc0",
      .bank       = 1,
      .memsize    =S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC0,
      .paddr       = 0,
    },
    {
      .id          =S5P_MDEV_FIMC1,
      .name       ="fimc1",
      .bank       = 1,
      .memsize    =S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC1,
      .paddr       = 0,
    },
    {
      .id          =S5P_MDEV_FIMC2,
      .name       ="fimc2",
      .bank       = 1,
      .memsize    =S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC2,
      .paddr       = 0,
    },
#endif
#if defined(CONFIG_VIDEO_JPEG_V2)
    {
      .id          =S5P_MDEV_JPEG,
      .name       ="jpeg",
      .bank       = 0,
      .memsize    =S5PV210_VIDEO_SAMSUNG_MEMSIZE_JPEG,
      .paddr       = 0,
    },
#endif
    {
      .id          =S5P_MDEV_FIMD,
      .name       ="fimd",
      .bank       = 1,
      .memsize    =S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMD,
      .paddr       = 0,
    },
#if defined(CONFIG_VIDEO_G2D)
    {
      .id          =S5P_MDEV_G2D,
      .name       ="g2d",
      .bank       = 0,
      .memsize    =S5PV210_VIDEO_SAMSUNG_MEMSIZE_G2D,
      .paddr       = 0,
    },
#endif
#if defined(CONFIG_ANDROID_PMEM)
    {
      .id          =S5P_MDEV_PMEM_GPU1,
      .name       ="pmem_gpu1",
      .bank       = 0,
      .memsize    =S5PV210_ANDROID_PMEM_MEMSIZE_PMEM_GPU1,
      .paddr       = 0,
    },
#endif
};
static void smdkv210_fixup_bootmem(int id, unsigned int size){
    int i;

    for (i = 0;i < ARRAY_SIZE(smdkv210_media_devs); i++) {
       if(smdkv210_media_devs[i].id == id) {
         smdkv210_media_devs[i].memsize = size;
       }
    }
}

#if defined(CONFIG_ANDROID_PMEM)
static struct android_pmem_platform_data pmem_pdata = {
   .name          ="pmem",
   .no_allocator   = 1,
   .cached          = 1,
   .start          = 0,
   .size          = 0,
};

static struct android_pmem_platform_data pmem_gpu1_pdata = {
   .name          ="pmem_gpu1",
   .no_allocator   = 1,
   .cached          = 1,
   .buffered       = 1,
   .start          = 0,
   .size          = 0,
};

static struct android_pmem_platform_data pmem_adsp_pdata = {
   .name          ="pmem_adsp",
   .no_allocator   = 1,
   .cached          = 1,
   .buffered       = 1,
   .start          = 0,
   .size          = 0,
};     

static struct platform_device pmem_device = {
    .name ="android_pmem",
    .id =0,
    .dev = {.platform_data = &pmem_pdata },
};

static struct platform_device pmem_gpu1_device = {
    .name ="android_pmem",
    .id =1,
    .dev = {.platform_data = &pmem_gpu1_pdata },
};

static struct platform_device pmem_adsp_device = {
    .name ="android_pmem",
    .id =2,
    .dev = {.platform_data = &pmem_adsp_pdata },
};

static void __init android_pmem_set_platdata(void)
{
#if    0
   pmem_pdata.start = (u32)s5p_get_media_memory_bank(S5P_MDEV_PMEM,0);
   pmem_pdata.size = (u32)s5p_get_media_memsize_bank(S5P_MDEV_PMEM,0);
#endif

   pmem_gpu1_pdata.start =(u32)s5p_get_media_memory_bank(S5P_MDEV_PMEM_GPU1, 0);
   pmem_gpu1_pdata.size =(u32)s5p_get_media_memsize_bank(S5P_MDEV_PMEM_GPU1, 0);

#if    0
   pmem_adsp_pdata.start =(u32)s5p_get_media_memory_bank(S5P_MDEV_PMEM_ADSP, 0);
   pmem_adsp_pdata.size =(u32)s5p_get_media_memsize_bank(S5P_MDEV_PMEM_ADSP, 0);
#endif
}
#endif



//==========================================================//

接着在static void __init smdkv210_map_io(void)函数中加入
   
  structs3cfb_lcd *lcd = smdkv210_get_lcd();
    intframe_size, fimd_size;
    frame_size =lcd->width * lcd->height *BYTES_PER_PIXEL;
    fimd_size =ALIGN(frame_size, PAGE_SIZE) * NUM_BUFFER;
    if(frame_size > 0x200000) {
       fimd_size +=ALIGN(frame_size, PAGE_SIZE) * 2;
    }
   
    fimd_size +=ALIGN(1280*720, PAGE_SIZE) * 3;
    fimd_size +=ALIGN(1280*360, PAGE_SIZE) * 3 + PAGE_SIZE;
    if(fimd_size != S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMD) {
      smdkv210_fixup_bootmem(S5P_MDEV_FIMD, fimd_size);
    }
    if(lcd->width > 1280) {
      smdkv210_fixup_bootmem(S5P_MDEV_FIMC2, 12288 * SZ_1K);
    }
   s5p_reserve_bootmem(smdkv210_media_devs,
         ARRAY_SIZE(smdkv210_media_devs), S5P_RANGE_MFC);


//===============================================//
二、在arch/arm/mach-s5pv210/include/mach 下建立media.h
 

#ifndef _S5PV210_MEDIA_H
#define _S5PV210_MEDIA_H


#defineS5P_MDEV_FIMC0     0
#defineS5P_MDEV_FIMC1     1
#defineS5P_MDEV_FIMC2     2
#defineS5P_MDEV_TV        3
#defineS5P_MDEV_MFC       4
#defineS5P_MDEV_JPEG      5
#defineS5P_MDEV_PMEM      6
#define S5P_MDEV_PMEM_GPU1  7
#define S5P_MDEV_PMEM_ADSP  8
#define S5P_MDEV_TEXSTREAM  9
#defineS5P_MDEV_FIMD      10
#defineS5P_MDEV_G2D       11
#defineS5P_MDEV_MAX       12

#defineS5P_RANGE_MFC      SZ_256M
#endif


//=================================================//
三、在arch/arm/plat-samsung/include/plat新建文件media.h


#ifndef _S5P_MEDIA_H
#define _S5P_MEDIA_H

#include <linux/types.h>
#include <asm/setup.h>

struct s5p_media_device {
   u32       id;
    constchar   *name;
   u32       bank;
   size_t      memsize;
   dma_addr_t   paddr;
};

extern struct meminfo meminfo;
extern dma_addr_t s5p_get_media_memory_bank(int dev_id, intbank);
extern size_t s5p_get_media_memsize_bank(int dev_id, intbank);
extern dma_addr_t s5p_get_media_membase_bank(int bank);
extern void s5p_reserve_bootmem(struct s5p_media_device *mdevs, intnr_mdevs, size_t boundary);

#endif


//===============================================//
四、在/arch/arm/plat-samsung/新建bootmem.c


#include <linux/err.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <asm/setup.h>
#include <linux/io.h>
#include <mach/memory.h>
#include <plat/media.h>
#include <mach/media.h>

static struct s5p_media_device *media_devs;
static int nr_media_devs;

static dma_addr_t media_base[NR_BANKS];

static struct s5p_media_device *s5p_get_media_device(int dev_id,int bank)
{
    structs5p_media_device *mdev = NULL;
    int i = 0,found = 0;

    if (dev_id< 0)
       returnNULL;

    while(!found && (i <nr_media_devs)) {
       mdev =&media_devs[i];
       if(mdev->id == dev_id&& mdev->bank ==bank)
          found =1;
       else
          i++;
    }

    if(!found)
       mdev =NULL;

    returnmdev;
}

dma_addr_t s5p_get_media_memory_bank(int dev_id, int bank)
{
    structs5p_media_device *mdev;

    mdev =s5p_get_media_device(dev_id, bank);
    if (!mdev){
      printk(KERN_ERR "invalid media device %d\n", dev_id);
       return0;
    }

    if(!mdev->paddr) {
      printk(KERN_ERR "no memory for %s\n",mdev->name);
       return0;
    }

    returnmdev->paddr;
}
EXPORT_SYMBOL(s5p_get_media_memory_bank);

size_t s5p_get_media_memsize_bank(int dev_id, int bank)
{
    structs5p_media_device *mdev;

    mdev =s5p_get_media_device(dev_id, bank);
    if (!mdev){
      printk(KERN_ERR "invalid media device %d\n", dev_id);
       return0;
    }

    returnmdev->memsize;
}
EXPORT_SYMBOL(s5p_get_media_memsize_bank);

dma_addr_t s5p_get_media_membase_bank(int bank)
{
    if (bank> meminfo.nr_banks) {
      printk(KERN_ERR "invalid bank.\n");
       return-EINVAL;
    }

    returnmedia_base[bank];
}
EXPORT_SYMBOL(s5p_get_media_membase_bank);

void s5p_reserve_bootmem(struct s5p_media_device *mdevs,
          int nr_mdevs, size_t boundary)
{
    structs5p_media_device *mdev;
    u64 start,end;
    int i,ret;

    media_devs =mdevs;
   nr_media_devs = nr_mdevs;

    for (i = 0;i < meminfo.nr_banks; i++)
      media_base[i] = meminfo.bank[i].start + meminfo.bank[i].size;

    for (i = 0;i < nr_media_devs; i++) {
       mdev =&media_devs[i];
       if(mdev->memsize <= 0)
         continue;

       if(!mdev->paddr) {
          start =meminfo.bank[mdev->bank].start;
          end = start+ meminfo.bank[mdev->bank].size;

          if (boundary&& (boundary < end -start))
             start = end- boundary;

         mdev->paddr = memblock_find_in_range(start,end,
                  mdev->memsize, PAGE_SIZE);
       }

       ret =memblock_remove(mdev->paddr,mdev->memsize);
       if (ret< 0)
         pr_err("memblock_reserve(%x, %x) failed\n",
            mdev->paddr, mdev->memsize);

       if(media_base[mdev->bank] >mdev->paddr)
         media_base[mdev->bank] =mdev->paddr;

      printk(KERN_INFO "s5p: %lu kbytes system memory reserved "
          "for %s at0xx, %d-bank base(0xx)\n",
          (unsignedlong) (mdev->memsize>> 10), mdev->name,mdev->paddr,
         mdev->bank,media_base[mdev->bank]);
    }
}


int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_tsize)
{
    return0;
}


//==================================================//
五、在arch/arm/mach-s5pv210 下建立smdkv210-lcds.c


#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/gpio.h>

#include <plat/fb.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>

#include<../../../drivers/video/s3cfb.h>




static struct s3cfb_lcd wvga_w50 = {
 
   .width=800,
    .height =480,
    .p_width =108,
    .p_height =64,
    .bpp =32,
    .freq =75,

    .timing ={
       .h_fp =40,
       .h_bp =40,
       .h_sw =48,
       .v_fp =20,
       .v_fpe =1,
       .v_bp =20,
       .v_bpe =1,
       .v_sw =12,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};

static struct s3cfb_lcd wvga_a70 = {
    .width =800,
    .height =480,
    .p_width =152,
    .p_height =90,
    .bpp =32,
    .freq =85,

    .timing ={
       .h_fp =40,
       .h_bp =40,
       .h_sw =48,
       .v_fp =17,
       .v_fpe =1,
       .v_bp =29,
       .v_bpe =1,
       .v_sw =24,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};

static struct s3cfb_lcd wvga_s70 = {
    .width =800,
    .height =480,
    .p_width =154,
    .p_height =96,
    .bpp =32,
    .freq =65,

    .timing ={
       .h_fp =80,
       .h_bp =36,
       .h_sw =10,
       .v_fp =22,
       .v_fpe =1,
       .v_bp =15,
       .v_bpe =1,
       .v_sw =8,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};

static struct s3cfb_lcd wvga_h43 = {
    .width =480,
    .height =272,
    .p_width =96,
    .p_height =54,
    .bpp =32,
    .freq =65,

    .timing ={
       .h_fp=  5,
       .h_bp =40,
       .h_sw=  2,
       .v_fp=  8,
       .v_fpe =1,
       .v_bp=  8,
       .v_bpe =1,
       .v_sw=  2,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};

static struct s3cfb_lcd wvga_a97 = {
    .width =1024,
    .height =768,
    .p_width =200,
    .p_height =150,
    .bpp =32,
    .freq =62,

    .timing ={
       .h_fp =12,
       .h_bp =12,
       .h_sw =4,
       .v_fp =8,
       .v_fpe =1,
       .v_bp =8,
       .v_bpe =1,
       .v_sw=  4,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};


static struct s3cfb_lcd wvga_l80 = {
    .width=640,
    .height =480,
    .p_width =160,
    .p_height =120,
    .bpp =32,
    .freq =65,

    .timing ={
       .h_fp =35,
       .h_bp =53,
       .h_sw =73,
       .v_fp =3,
       .v_fpe =1,
       .v_bp =29,
       .v_bpe =1,
       .v_sw =6,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};

static struct s3cfb_lcd wvga_g10 = {
    .width=640,
    .height =480,
    .p_width =213,
    .p_height =160,
    .bpp =32,
    .freq =65,

    .timing ={
       .h_fp =0x3c,
       .h_bp =0x63,
       .h_sw =1,
       .v_fp =0x0a,
       .v_fpe =1,
       .v_bp =0x22,
       .v_bpe =1,
       .v_sw =1,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =0,
       .inv_vsync =0,
       .inv_vden =0,
    },
};

static struct s3cfb_lcd wvga_a56 = {
    .width=640,
    .height =480,
    .p_width =112,
    .p_height =84,
    .bpp =32,
    .freq =65,

    .timing ={
       .h_fp =16,
       .h_bp =134,
       .h_sw =10,
       .v_fp =32,
       .v_fpe =1,
       .v_bp =11,
       .v_bpe =1,
       .v_sw =2,
    },
    .polarity ={
       .rise_vclk =1,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};

static struct s3cfb_lcd wvga_w101 = {
    .width=1024,
    .height =600,
    .p_width =204,
    .p_height =120,
    .bpp =32,
    .freq =60,

    .timing ={
       .h_fp =40,
       .h_bp =40,
       .h_sw =120,
       .v_fp =10,
       .v_fpe =1,
       .v_bp =10,
       .v_bpe =1,
       .v_sw =12,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};

static struct s3cfb_lcd wvga_w35 = {
    .width=320,
    .height =240,
    .p_width =70,
    .p_height =52,
    .bpp =32,
    .freq =65,

    .timing ={
       .h_fp=  4,
       .h_bp =70,
       .h_sw=  4,
       .v_fp=  4,
       .v_fpe =1,
       .v_bp =12,
       .v_bpe =1,
       .v_sw=  4,
    },
    .polarity ={
       .rise_vclk =1,
       .inv_hsync =0,
       .inv_vsync =0,
       .inv_vden =0,
    },
};


static struct s3cfb_lcd hdmi_def = {
    .width =1920,
    .height =1080,
    .p_width =480,
    .p_height =320,
    .bpp =32,
    .freq =62,

    .timing ={
       .h_fp =12,
       .h_bp =12,
       .h_sw =4,
       .v_fp =8,
       .v_fpe =1,
       .v_bp =8,
       .v_bpe =1,
       .v_sw=  4,
    },
    .polarity ={
       .rise_vclk =0,
       .inv_hsync =1,
       .inv_vsync =1,
       .inv_vden =0,
    },
};

static struct hdmi_config {
    char*name;
    intwidth;
    intheight;
} smdkv210_hdmi_config[] = {
    {"HDMI1080P60",   1920, 1080 },
    {"HDMI1080I60",   1920, 1080 },
    {"HDMI1080P30",   1920, 1080 },

    {"HDMI1080P60D",    960,  536 },
    {"HDMI1080I60D",    960,  536 },
    {"HDMI1080P30D",    960,  536 },

    {"HDMI720P60",      1280,  720 },
    {"HDMI720P60D",    640,  360 },

    {"HDMI576P16X9",    720,  576 },
    {"HDMI576P16X9D",    720,  576 },
    {"HDMI576P4X3",    720,  576 },
    {"HDMI576P4X3D",    720,  576 },

    {"HDMI480P16X9",    720,  480 },
    {"HDMI480P16X9D",    720,  480 },
    {"HDMI480P4X3",    720,  480 },
    {"HDMI480P4X3D",    720,  480 },
};




static struct {
    char*name;
    structs3cfb_lcd *lcd;
    intctp;
} smdkv210_lcd_config[] = {
    {"W50", &wvga_w50,  0 },
    {"A70", &wvga_a70,  0 },
    {"S70", &wvga_s70,  1 },
    {"H43", &wvga_h43,  1 },
    {"A97", &wvga_a97,  0 },
    {"L80", &wvga_l80,  0 },
    {"G10", &wvga_g10,  0 },
    {"A56", &wvga_a56,  0 },
    { "W101",&wvga_w101, 0 },
    {"W35", &wvga_w35,  0 },
    {"HDM", &hdmi_def,  0},   
};

static int lcd_idx = 2;

static int __init smdkv210_setup_lcd(char *str)
{
    int i;

    if(!strncasecmp("HDMI", str, 4)) {
       structhdmi_config *cfg = &smdkv210_hdmi_config[0];
       structs3cfb_lcd *lcd;

       lcd_idx =ARRAY_SIZE(smdkv210_lcd_config) - 1;
       lcd =smdkv210_lcd_config[lcd_idx].lcd;
      lcd->args = lcd_idx;

       for (i = 0;i < ARRAY_SIZE(smdkv210_hdmi_config); i++, cfg++){
          if(!strcasecmp(cfg->name, str)) {
            lcd->width = cfg->width;
            lcd->height = cfg->height;
             goto__ret;
          }
       }
    }

    for (i = 0;i < ARRAY_SIZE(smdkv210_lcd_config); i++) {
       if(!strcasecmp(smdkv210_lcd_config[i].name, str)) {
          lcd_idx =i;
         smdkv210_lcd_config[lcd_idx].lcd->args =lcd_idx;
          break;
       }
    }

__ret:
   printk("smdkv210: %s selected\n",smdkv210_lcd_config[lcd_idx].name);
    return0;
}
early_param("lcd", smdkv210_setup_lcd);


struct s3cfb_lcd *smdkv210_get_lcd(void)
{
    returnsmdkv210_lcd_config[lcd_idx].lcd;
}

void smdkv210_get_lcd_res(int *w, int *h)
{
    structs3cfb_lcd *lcd = smdkv210_lcd_config[lcd_idx].lcd;

    if (w)
       *w =lcd->width;
    if (h)
       *h =lcd->height;

   return;
}
EXPORT_SYMBOL(smdkv210_get_lcd_res);



六、修改该目录下的Makefile将obj-$(CONFIG_MACH_SMDKV210)   += mach-smdkv210.o修改为obj-$(CONFIG_MACH_SMDKV210)   += mach-smdkv210.o smdkv210-lcds.o七、在drivers/video下新建s3cfb.h
#ifndef _S3CFB_H
#define _S3CFB_H

#ifdef __KERNEL__
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/fb.h>
#ifdef CONFIG_HAS_WAKELOCK
#include <linux/wakelock.h>
#include <linux/earlysuspend.h>
#endif
#include <plat/fb.h>
#endif


#defineS3CFB_NAME      "s3cfb"

#define S3CFB_AVALUE(r, g,b)    (((r& 0xf) << 8) |\
             ((g& 0xf) << 4) |\
             ((b& 0xf) << 0))
#define S3CFB_CHROMA(r, g,b)    (((r& 0xff) << 16) |\
             ((g& 0xff) << 8) |\
             ((b& 0xff) << 0))


enum s3cfb_data_path_t {
   DATA_PATH_FIFO = 0,
   DATA_PATH_DMA = 1,
   DATA_PATH_IPC = 2,
};

enum s3cfb_alpha_t {
   PLANE_BLENDING,
   PIXEL_BLENDING,
};

enum s3cfb_chroma_dir_t {
   CHROMA_FG,
   CHROMA_BG,
};

enum s3cfb_output_t {
   OUTPUT_RGB,
   OUTPUT_ITU,
   OUTPUT_I80LDI0,
   OUTPUT_I80LDI1,
   OUTPUT_WB_RGB,
   OUTPUT_WB_I80LDI0,
   OUTPUT_WB_I80LDI1,
};

enum s3cfb_rgb_mode_t {
    MODE_RGB_P =0,
    MODE_BGR_P =1,
    MODE_RGB_S =2,
    MODE_BGR_S =3,
};

enum s3cfb_mem_owner_t {
   DMA_MEM_NONE   = 0,
   DMA_MEM_FIMD   = 1,
   DMA_MEM_OTHER   = 2,
};




struct s3cfb_alpha {
   enum      s3cfb_alpha_t mode;
   int      channel;
    unsignedint   value;
};


struct s3cfb_chroma {
   int      enabled;
   int      blended;
    unsignedint   key;
    unsignedint   comp_key;
    unsignedint   alpha;
   enum      s3cfb_chroma_dir_t dir;
};


struct s3cfb_lcd_polarity {
   int   rise_vclk;
   int   inv_hsync;
   int   inv_vsync;
   int   inv_vden;
};


struct s3cfb_lcd_timing {
   int   h_fp;
   int   h_bp;
   int   h_sw;
   int   v_fp;
   int   v_fpe;
   int   v_bp;
   int   v_bpe;
   int   v_sw;
};


struct s3cfb_lcd {
   int   width;
   int   height;
   int   p_width;
   int   p_height;
   int   bpp;
   int   freq;
   struct   s3cfb_lcd_timing timing;
   struct   s3cfb_lcd_polarity polarity;

   void   (*init_ldi)(void);
   void   (*deinit_ldi)(void);
    unsignedlong args;
};


struct s3cfb_window {
   int          id;
   int         enabled;
   int         in_use;
   int          x;
   int          y;
   enum         s3cfb_data_path_t path;
   enum         s3cfb_mem_owner_t owner;
    unsignedint   other_mem_addr;
    unsignedint   other_mem_size;
   int         local_channel;
   int         dma_burst;
    unsignedint      pseudo_pal[16];
   struct          s3cfb_alphaalpha;
   struct          s3cfb_chromachroma;
};


struct s3cfb_global {
   
    void__iomem       *regs;
    structmutex       lock;
    structdevice       *dev;
    structclk      *clock;
    structregulator   *regulator;
    structregulator   *vcc_lcd;
    structregulator   *vlcd;
   int          irq;
    structfb_info       **fb;
    structcompletion   fb_complete;

   
   int         enabled;
   int          dsi;
   int         interlace;
    enums3cfb_output_t   output;
    enums3cfb_rgb_mode_t   rgb_mode;
    structs3cfb_lcd   *lcd;
   u32         pixclock_hz;

#ifdef CONFIG_HAS_WAKELOCK
    structearly_suspend   early_suspend;
    structwake_lock   idle_lock;
#endif

#ifdef CONFIG_CPU_FREQ
    structnotifier_block   freq_transition;
    structnotifier_block   freq_policy;
#endif

};



struct s3cfb_user_window {
    int x;
    int y;
};

struct s3cfb_user_plane_alpha {
   int      channel;
    unsignedchar   red;
    unsignedchar   green;
    unsignedchar   blue;
};

struct s3cfb_user_chroma {
   int      enabled;
    unsignedchar   red;
    unsignedchar   green;
    unsignedchar   blue;
};

struct s3cfb_next_info {
    unsigned intphy_start_addr;
    unsigned intxres;      
    unsigned intyres;
    unsigned intxres_virtual;   
    unsigned intyres_virtual;
    unsigned intxoffset;      
    unsigned intyoffset;      
    unsigned intlcd_offset_x;
    unsigned intlcd_offset_y;
};


#defineS3CFB_WIN_POSITION       _IOW('F',203, \
                   structs3cfb_user_window)
#defineS3CFB_WIN_SET_PLANE_ALPHA   _IOW('F', 204, \
                   structs3cfb_user_plane_alpha)
#defineS3CFB_WIN_SET_CHROMA       _IOW('F',205, \
                   structs3cfb_user_chroma)
#defineS3CFB_SET_VSYNC_INT       _IOW('F',206, u32)
#defineS3CFB_GET_VSYNC_INT_STATUS   _IOR('F', 207, u32)
#defineS3CFB_GET_LCD_WIDTH       _IOR('F',302, int)
#defineS3CFB_GET_LCD_HEIGHT       _IOR('F',303, int)
#defineS3CFB_SET_WRITEBACK       _IOW('F',304, u32)
#defineS3CFB_GET_CURR_FB_INFO       _IOR('F',305, struct s3cfb_next_info)
#defineS3CFB_SET_WIN_ON       _IOW('F',306, u32)
#defineS3CFB_SET_WIN_OFF       _IOW('F',307, u32)
#defineS3CFB_SET_WIN_PATH       _IOW('F',308, \
                   enums3cfb_data_path_t)
#defineS3CFB_SET_WIN_ADDR       _IOW('F',309, unsigned long)
#defineS3CFB_SET_WIN_MEM       _IOW('F',310, \
                   enums3cfb_mem_owner_t)
#defineS3CFB_GET_LCD_ADDR       _IOR('F',311, int)


extern int soft_cursor(struct fb_info *info, struct fb_cursor*cursor);
extern void s3cfb_set_lcd_info(struct s3cfb_global *ctrl);
extern struct s3c_platform_fb *to_fb_plat(struct device*dev);
extern void s3cfb_check_line_count(struct s3cfb_global*ctrl);
extern int s3cfb_set_output(struct s3cfb_global *ctrl);
extern int s3cfb_set_display_mode(struct s3cfb_global *ctrl);
extern int s3cfb_display_on(struct s3cfb_global *ctrl);
extern int s3cfb_display_off(struct s3cfb_global *ctrl);
extern int s3cfb_frame_off(struct s3cfb_global *ctrl);
extern int s3cfb_set_clock(struct s3cfb_global *ctrl);
extern int s3cfb_set_polarity(struct s3cfb_global *ctrl);
extern int s3cfb_set_timing(struct s3cfb_global *ctrl);
extern int s3cfb_set_lcd_size(struct s3cfb_global *ctrl);
extern int s3cfb_set_global_interrupt(struct s3cfb_global *ctrl,int enable);
extern int s3cfb_set_vsync_interrupt(struct s3cfb_global *ctrl, intenable);
extern int s3cfb_get_vsync_interrupt(struct s3cfb_global*ctrl);
extern int s3cfb_set_fifo_interrupt(struct s3cfb_global *ctrl, intenable);
extern int s3cfb_clear_interrupt(struct s3cfb_global *ctrl);
extern int s3cfb_channel_localpath_on(struct s3cfb_global *ctrl,int id);
extern int s3cfb_channel_localpath_off(struct s3cfb_global *ctrl,int id);
extern int s3cfb_window_on(struct s3cfb_global *ctrl, intid);
extern int s3cfb_window_off(struct s3cfb_global *ctrl, intid);
extern int s3cfb_win_map_on(struct s3cfb_global *ctrl, int id, intcolor);
extern int s3cfb_win_map_off(struct s3cfb_global *ctrl, intid);
extern int s3cfb_set_window_control(struct s3cfb_global *ctrl, intid);
extern int s3cfb_set_alpha_blending(struct s3cfb_global *ctrl, intid);
extern int s3cfb_set_window_position(struct s3cfb_global *ctrl, intid);
extern int s3cfb_set_window_size(struct s3cfb_global *ctrl, intid);
extern int s3cfb_set_buffer_address(struct s3cfb_global *ctrl, intid);
extern int s3cfb_set_buffer_size(struct s3cfb_global *ctrl, intid);
extern int s3cfb_set_chroma_key(struct s3cfb_global *ctrl, intid);

#ifdef CONFIG_HAS_WAKELOCK
#ifdef CONFIG_HAS_EARLYSUSPEND
extern void s3cfb_early_suspend(struct early_suspend *h);
extern void s3cfb_late_resume(struct early_suspend *h);
#endif
#endif

#if defined(CONFIG_FB_S3C_TL2796)
extern void tl2796_ldi_init(void);
extern void tl2796_ldi_enable(void);
extern void tl2796_ldi_disable(void);
extern void lcd_cfg_gpio_early_suspend(void);
extern void lcd_cfg_gpio_late_resume(void);
#endif

#endif


//=================================================//
八、修改driver/video/Kconfig
添加

config FB_S3C_DEFAULT_WINDOW
    int "DefaultWindow (0-4)"
    range 04
    depends onFB_S3C
    default"2"
   ---help---
     This indicates the default window number, andwhich is used as console framebuffer

config FB_S3C_NR_BUFFERS
    int "Numberof frame buffers (1-3)"
    depends onFB_S3C
    default"2"
   ---help---
     This indicates the number of buffers for pandisplay,
     1 means no pan display and
     2 means the double size of video buffer will beallocated for default window

config FB_S3C_NUM_OVLY_WIN
    int "Numberof overlay window (0-3)"
    range 03
    depends onFB_S3C
    default"1"
   ---help---
     This indicates the number of overlay windows forvideo rendering

config FB_S3C_NUM_BUF_OVLY_WIN
    int "Numberof buffers for overlay window (2-3)"
    range 23
    depends onFB_S3C
    default"3"
   ---help---
     This indicates the number of buffers for overlaywindows


最后make,测试ing







你可能感兴趣的:(基于tiny210v2的linux-3.9.6内核驱动移植3:LCD移植)