3.9.6内核驱动移植(3)

友善的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

<PRE class=css>#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);</PRE>

<PRE></PRE>
六、修改该目录下的Makefile将obj-$(CONFIG_MACH_SMDKV210)+= mach-smdkv210.o修改为obj-$(CONFIG_MACH_SMDKV210)+= mach-smdkv210.o smdkv210-lcds.o七、在drivers/video下新建s3cfb.h<PRE class=css>#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</PRE>

//=================================================//
八、修改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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/4eec2197978e18c5525ca90941f1e2ae.html