On Thu, Jun 18, 2009 at 03:08:54, Krzysztof Helt wrote:
> On Wed, 17 Jun 2009 10:01:10 -0400
> "Rajashekhara, Sudhakar" <[email protected]> wrote:
> 
> > Resending the same patch with additional Signed-off information.
> > 
> > Adds LCD controller (LCDC) driver for TI's DA8xx/OMAP-L1xx architecture.
> > LCDC specifications can be found at http://www.ti.com/litv/pdf/sprufm0a.
> > 
> > LCDC on DA8xx consists of two independent controllers, the Raster
Controller
> > and the LCD Interface Display Driver (LIDD) controller. LIDD further
supports
> > character and graphic displays.
> > 
> > This patch adds support for the graphic display (Sharp LQ035Q3DG01)
found on
> > the DA830 based EVM. The EVM details can be found at:
> > http://support.spectrumdigital.com/boards/dskda830/revc/.
> > 
> > Signed-off-by: Sudhakar Rajashekhara <[email protected]>
> > Signed-off-by: Pavel Kiryukhin <[email protected]>
> > Signed-off-by: Steve Chen <[email protected]>
> > ---
> >  drivers/video/Kconfig    |   11 +
> >  drivers/video/Makefile   |    1 +
> >  drivers/video/da8xx-fb.c |  964
++++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/da8xx-fb.h |  106 +++++
> >  4 files changed, 1082 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/video/da8xx-fb.c
> >  create mode 100644 include/linux/da8xx-fb.h
> > 
> > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > index 693fb4e..fc0c191 100644
> > --- a/drivers/video/Kconfig
> > +++ b/drivers/video/Kconfig
> > @@ -1984,6 +1984,17 @@ config FB_DAVINCI
> >       hardware found on the TI DaVinci EVM.  If
> >       unsure, say N.
> >  
> > +config FB_DA8XX
> > +        tristate "DA8xx/OMAP-L1xx Framebuffer support"
> > +        depends on FB && ARCH_DAVINCI_DA830
> > +   select FB_CFB_FILLRECT
> > +   select FB_CFB_COPYAREA
> > +   select FB_CFB_IMAGEBLIT
> > +   ---help---
> > +          This is the frame buffer device driver for the TI LCD
controller
> > +     found on DA8xx/OMAP-L1xx SoCs.
> > +          If unsure, say N.
> > +
> >  config FB_VIRTUAL
> >     tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
> >     depends on FB
> > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > index 902d199..e7a3e7d 100644
> > --- a/drivers/video/Makefile
> > +++ b/drivers/video/Makefile
> > @@ -136,6 +136,7 @@ obj-$(CONFIG_FB_BF54X_LQ043)      += bf54x-lq043fb.o
> >  obj-$(CONFIG_FB_BFIN_T350MCQB)       += bfin-t350mcqb-fb.o
> >  obj-$(CONFIG_FB_MX3)                 += mx3fb.o
> >  obj-$(CONFIG_FB_DAVINCI)     += davincifb.o
> > +obj-$(CONFIG_FB_DA8XX)               += da8xx-fb.o
> >  
> >  # the test framebuffer is last
> >  obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
> > diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> > new file mode 100644
> > index 0000000..5e3b861
> > --- /dev/null
> > +++ b/drivers/video/da8xx-fb.c
> > @@ -0,0 +1,964 @@
> > +/*
> > + * Copyright (C) 2008-2009 MontaVista Software Inc.
> > + * Copyright (C) 2008-2009 Texas Instruments Inc
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option)any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
> > + */
> > +#include <linux/module.h>
> > +#include <linux/kernel.h>
> > +#include <linux/fb.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/device.h>
> > +#include <linux/platform_device.h>
> > +#include <mach/cputype.h>
> > +#include <mach/io.h>
> > +#include <mach/hardware.h>
> > +#include <linux/uaccess.h>
> > +#include <linux/device.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/clk.h>
> > +#include <linux/da8xx-fb.h>
> > +
> > +#define DRIVER_NAME "da8xx_lcdc"
> > +
> > +/* LCD Status Register */
> > +#define LCD_END_OF_FRAME0          BIT(8)
> > +#define LCD_FIFO_UNDERFLOW         BIT(5)
> > +#define LCD_SYNC_LOST                      BIT(2)
> > +
> > +/* LCD DMA Control Register */
> > +#define LCD_DMA_BURST_SIZE(x)              ((x) << 4)
> > +#define LCD_DMA_BURST_1                    0x0
> > +#define LCD_DMA_BURST_2                    0x1
> > +#define LCD_DMA_BURST_4                    0x2
> > +#define LCD_DMA_BURST_8                    0x3
> > +#define LCD_DMA_BURST_16           0x4
> > +#define LCD_END_OF_FRAME_INT_ENA   BIT(2)
> > +#define LCD_DUAL_FRAME_BUFFER_ENABLE       BIT(0)
> > +
> > +/* LCD Control Register */
> > +#define LCD_CLK_DIVISOR(x)         ((x) << 8)
> > +#define LCD_RASTER_MODE                    0x01
> > +
> > +/* LCD Raster Control Register */
> > +#define LCD_PALETTE_LOAD_MODE(x)   ((x) << 20)
> > +#define PALETTE_AND_DATA           0x00
> > +#define PALETTE_ONLY                       0x01
> > +
> > +#define LCD_MONO_8BIT_MODE         BIT(9)
> > +#define LCD_RASTER_ORDER           BIT(8)
> > +#define LCD_TFT_MODE                       BIT(7)
> > +#define LCD_UNDERFLOW_INT_ENA              BIT(6)
> > +#define LCD_MONOCHROME_MODE                BIT(1)
> > +#define LCD_RASTER_ENABLE          BIT(0)
> > +#define LCD_TFT_ALT_ENABLE         BIT(23)
> > +#define LCD_STN_565_ENABLE         BIT(24)
> > +
> > +/* LCD Raster Timing 2 Register */
> > +#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
> > +#define LCD_AC_BIAS_FREQUENCY(x)           ((x) << 8)
> > +#define LCD_SYNC_CTRL                              BIT(25)
> > +#define LCD_SYNC_EDGE                              BIT(24)
> > +#define LCD_INVERT_PIXEL_CLOCK                     BIT(22)
> > +#define LCD_INVERT_LINE_CLOCK                      BIT(21)
> > +#define LCD_INVERT_FRAME_CLOCK                     BIT(20)
> > +
> > +/* LCD Block */
> > +#define  LCD_CTRL_REG                              0x4
> > +#define  LCD_STAT_REG                              0x8
> > +#define  LCD_RASTER_CTRL_REG                       0x28
> > +#define  LCD_RASTER_TIMING_0_REG           0x2C
> > +#define  LCD_RASTER_TIMING_1_REG           0x30
> > +#define  LCD_RASTER_TIMING_2_REG           0x34
> > +#define  LCD_DMA_CTRL_REG                  0x40
> > +#define  LCD_DMA_FRM_BUF_BASE_ADDR_0_REG   0x44
> > +#define  LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG        0x48
> > +
> > +#define lcdc_read(addr)            __raw_readl(da8xx_fb_reg_base +
(addr))
> > +#define lcdc_write(val, addr)      __raw_writel(val, da8xx_fb_reg_base
+ (addr))
> > +
> 
> Inline functions are preferred over macros.

OK. I'll change these into inline functions.

> 
> > +#define WSI_TIMEOUT        50
> > +#define PALETTE_SIZE       256
> > +#define LEFT_MARGIN        64
> > +#define RIGHT_MARGIN       64
> > +#define UPPER_MARGIN       32
> > +#define LOWER_MARGIN       32
> > +
> > +static resource_size_t da8xx_fb_reg_base;
> > +static wait_queue_head_t da8xx_wq;
> 
> These two variables should not exist. You should store them
> in your da8xx_fb_par structure and use them from there
> (the reg_base seems already there).

I'll move the da8xx_wq into da8xx_fb_par structure, but I don't want to move
the reg_base inside it. This reg_base is being used in lcdc_read and
lcdc_write functions and if I move reg_base into da8xx_fb_par then lcdc_read
and lcdc_write have to take an extra argument. What do you suggest?

> 
> > +
> > +struct da8xx_fb_par {
> > +   resource_size_t p_regs_base;
> > +   resource_size_t p_frame_buffer_mem_base;
> > +   resource_size_t p_screen_base;
> > +   resource_size_t p_palette_base;
> > +   unsigned char *v_frame_buffer_mem_base;
> > +   unsigned char *v_screen_base;
> > +   unsigned char *v_palette_base;
> > +   unsigned long screen_size;
> 
> These address and length fields duplicate standard fields from 
> the fb_info and fb_info->fix structures (except regs_base).
> Please use standard fields.

I could not find equivalent fields for p_palette_base abd v_palette_base.
I'll replace others with standard fields.

> 
> > +   unsigned int palette_size;
> > +   unsigned int bpp;
> 
> These fields are also duplicated by the fb_info->var->bits_per_pixel 
> and the fb_info->cmap.len.

I'll modify them.

> 
> > +   struct clk *lcdc_clk;
> > +   unsigned int irq;
> > +   u16 pseudo_palette[16];
> > +};
> > +
> > +/* Variable Screen Information */
> > +static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
> > +   .xoffset = 0,
> > +   .yoffset = 0,
> > +   .transp = {0, 0, 0},
> > +   .nonstd = 0,
> > +   .activate = 0,
> > +   .height = -1,
> > +   .width = -1,
> > +   .pixclock = 46666,      /* 46us - AUO display */
> > +   .accel_flags = 0,
> > +   .left_margin = LEFT_MARGIN,
> > +   .right_margin = RIGHT_MARGIN,
> > +   .upper_margin = UPPER_MARGIN,
> > +   .lower_margin = LOWER_MARGIN,
> > +   .sync = 0,
> > +   .vmode = FB_VMODE_NONINTERLACED
> > +};
> > +
> > +static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
> > +   .id = "DA8xx FB Drv",
> > +   .type = FB_TYPE_PACKED_PIXELS,
> > +   .type_aux = 0,
> > +   .visual = FB_VISUAL_PSEUDOCOLOR,
> > +   .xpanstep = 1,
> > +   .ypanstep = 1,
> > +   .ywrapstep = 1,
> > +   .accel = FB_ACCEL_NONE
> > +};
> > +
> > +struct da8xx_panel {
> > +   const char      name[25];       /* Full name <vendor>_<model> */
> > +   unsigned short  width;
> > +   unsigned short  height;
> > +   int             hfp;            /* Horizontal front porch */
> > +   int             hbp;            /* Horizontal back porch */
> > +   int             hsw;            /* Horizontal Sync Pulse Width */
> > +   int             vfp;            /* Vertical front porch */
> > +   int             vbp;            /* Vertical back porch */
> > +   int             vsw;            /* Vertical Sync Pulse Width */
> > +   int             pxl_clk;        /* Pixel clock */
> > +};
> > +
> > +static struct da8xx_panel known_lcd_panels[] = {
> > +   /* Sharp LCD035Q3DG01 */
> > +   [0] = {
> > +           .name = "Sharp_LCD035Q3DG01",
> > +           .width = 320,
> > +           .height = 240,
> > +           .hfp = 8,
> > +           .hbp = 6,
> > +           .hsw = 0,
> > +           .vfp = 2,
> > +           .vbp = 2,
> > +           .vsw = 0,
> > +           .pxl_clk = 0x10,
> > +   },
> > +   /* Sharp LK043T1DG01 */
> > +   [1] = {
> > +           .name = "Sharp_LK043T1DG01",
> > +           .width = 480,
> > +           .height = 272,
> > +           .hfp = 2,
> > +           .hbp = 2,
> > +           .hsw = 41,
> > +           .vfp = 2,
> > +           .vbp = 2,
> > +           .vsw = 10,
> > +           .pxl_clk = 0x12,
> > +   },
> > +};
> > +
> > +static u32 databuf_sz;
> > +static u32 palette_sz;
> 
> Again, these should be part of your da8xx_fb_par structure.

Agree.

> 
> > +static struct fb_ops da8xx_fb_ops;
> 
> Just move definition of the da8xx_fb_ops before probe function
> and this forward declaration is not needed.

OK.

> 
> 
> 
> > +
> > +/* Disable the Raster Engine of the LCD Controller */
> > +static int lcd_disable_raster(struct device *dev)
> > +{
> 
> You give the device structure's pointer as the argument to many 
> functions. You should use fb_info pointer here and use &fb_info->device
> if needed. Eventually, you can pass only da8xx_fb_par pointer as it is
> enough to get all needed data to most functions (no dev_xxx() messages
> then).

OK.

> 
> > +   int ret = 0;
> > +   u32 reg;
> > +
> > +   reg = lcdc_read(LCD_RASTER_CTRL_REG);
> > +   if (reg & LCD_RASTER_ENABLE) {
> > +           lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
> > +           ret = wait_event_interruptible_timeout(da8xx_wq,
> > +                                           !lcdc_read(LCD_STAT_REG) &
> > +                                           LCD_END_OF_FRAME0,
WSI_TIMEOUT);
> > +   }
> > +
> > +   if (ret < 0)
> > +           return ret;
> > +   if (ret == 0)
> > +           return -ETIMEDOUT;
> > +
> > +   return 0;
> > +}
> > +
> > +static void lcd_blit(int load_mode, u32 p_buf)
> > +{
> > +   u32 tmp = p_buf + databuf_sz - 4;
> > +   u32 reg;
> > +
> > +   /* Update the databuf in the hw. */
> > +   lcdc_write(p_buf, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
> > +   lcdc_write(tmp, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
> > +
> > +   /* Start the DMA. */
> > +   reg = lcdc_read(LCD_RASTER_CTRL_REG);
> > +   reg &= ~(3 << 20);
> > +   if (load_mode == LOAD_DATA)
> > +           reg |= LCD_PALETTE_LOAD_MODE(PALETTE_AND_DATA);
> > +   else if (load_mode == LOAD_PALETTE)
> > +           reg |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
> > +
> > +   lcdc_write(reg, LCD_RASTER_CTRL_REG);
> > +}
> > +
> > +/* Configure the Burst Size of DMA */
> > +static int lcd_cfg_dma(struct device *dev, int burst_size)
> > +{
> > +   u32 reg;
> > +
> > +   reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001;
> > +   switch (burst_size) {
> > +   case 1:
> > +           reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1);
> > +           break;
> > +   case 2:
> > +           reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2);
> > +           break;
> > +   case 4:
> > +           reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4);
> > +           break;
> > +   case 8:
> > +           reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
> > +           break;
> > +   case 16:
> > +           reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
> > +           break;
> > +   default:
> > +           return -EINVAL;
> > +   }
> > +   lcdc_write(reg | LCD_END_OF_FRAME_INT_ENA, LCD_DMA_CTRL_REG);
> > +
> > +   return 0;
> > +}
> > +
> > +static void lcd_cfg_ac_bias(struct device *dev, int period,
> > +                           int transitions_per_int)
> > +{
> > +   u32 reg;
> > +
> > +   /* Set the AC Bias Period and Number of Transisitons per Interrupt
*/
> > +   reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000;
> > +   reg |= LCD_AC_BIAS_FREQUENCY(period) |
> > +           LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int);
> > +   lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
> > +}
> > +
> > +static void lcd_cfg_horizontal_sync(struct device *dev, int back_porch,
> > +                                   int pulse_width, int front_porch)
> > +{
> > +   u32 reg;
> > +
> > +   reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf;
> > +   reg |= ((back_porch & 0xff) << 24)
> > +       | ((front_porch & 0xff) << 16)
> > +       | ((pulse_width & 0x3f) << 10);
> > +   lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
> > +}
> > +
> > +static void lcd_cfg_vertical_sync(struct device *dev, int back_porch,
> > +                                   int pulse_width, int front_porch)
> > +{
> > +   u32 reg;
> > +
> > +   reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff;
> > +   reg |= ((back_porch & 0xff) << 24)
> > +       | ((front_porch & 0xff) << 16)
> > +       | ((pulse_width & 0x3f) << 10);
> > +   lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
> > +}
> > +
> > +static int lcd_cfg_display(struct device *dev,
> > +                           const struct lcd_ctrl_config *cfg)
> > +{
> > +   u32 reg;
> > +
> > +   reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
> > +                                           LCD_MONO_8BIT_MODE |
> > +                                           LCD_MONOCHROME_MODE);
> > +
> > +   switch (cfg->p_disp_panel->panel_shade) {
> > +   case MONOCHROME:
> > +           reg |= LCD_MONOCHROME_MODE;
> > +           if (cfg->mono_8bit_mode)
> > +                   reg |= LCD_MONO_8BIT_MODE;
> > +           break;
> > +   case COLOR_ACTIVE:
> > +           reg |= LCD_TFT_MODE;
> > +           if (cfg->tft_alt_mode)
> > +                   reg |= LCD_TFT_ALT_ENABLE;
> > +           break;
> > +
> > +   case COLOR_PASSIVE:
> > +           if (cfg->stn_565_mode)
> > +                   reg |= LCD_STN_565_ENABLE;
> > +           break;
> > +
> > +   default:
> > +           dev_err(dev, "Undefined LCD type\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   /* enable additional interrupts here */
> > +   reg |= LCD_UNDERFLOW_INT_ENA;
> > +
> > +   lcdc_write(reg, LCD_RASTER_CTRL_REG);
> > +
> > +   reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
> > +
> > +   if (cfg->sync_ctrl)
> > +           reg |= LCD_SYNC_CTRL;
> > +   else
> > +           reg &= ~LCD_SYNC_CTRL;
> > +
> > +   if (cfg->sync_edge)
> > +           reg |= LCD_SYNC_EDGE;
> > +   else
> > +           reg &= ~LCD_SYNC_EDGE;
> > +
> > +   if (cfg->invert_pxl_clock)
> > +           reg |= LCD_INVERT_PIXEL_CLOCK;
> > +   else
> > +           reg &= ~LCD_INVERT_PIXEL_CLOCK;
> > +
> > +   if (cfg->invert_line_clock)
> > +           reg |= LCD_INVERT_LINE_CLOCK;
> > +   else
> > +           reg &= ~LCD_INVERT_LINE_CLOCK;
> > +
> > +   if (cfg->invert_frm_clock)
> > +           reg |= LCD_INVERT_FRAME_CLOCK;
> > +   else
> > +           reg &= ~LCD_INVERT_FRAME_CLOCK;
> > +
> > +   lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
> > +
> > +   return 0;
> > +}
> > +
> > +static int lcd_cfg_frame_buffer(struct device *dev, u32 width, u32
height,
> > +                                   u32 bpp, u32 raster_order)
> > +{
> > +   u32 bpl, reg;
> > +
> > +   /* Disable Dual Frame Buffer. */
> > +   reg = lcdc_read(LCD_DMA_CTRL_REG);
> > +   lcdc_write(reg & ~LCD_DUAL_FRAME_BUFFER_ENABLE,
> > +                                           LCD_DMA_CTRL_REG);
> > +   /* Set the Panel Width */
> > +   /* Pixels per line = (PPL + 1)*16 */
> > +   /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/
> > +   width &= 0x3f0;
> > +   reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
> > +   reg = (((width >> 4) - 1) << 4) | (reg & 0xfffffc00);
> 
> You can easily break lines like this into two to reduce bracket's depth:

OK.

> 
> reg &= 0xfffffc00;
> reg |= ((width >> 4) - 1) << 4;
> 
> > +   lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
> > +
> > +   /* Set the Panel Height */
> > +   reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
> > +   reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
> > +   lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
> > +
> > +   /* Set the Raster Order of the Frame Buffer */
> > +   reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
> > +   if (raster_order)
> > +           reg |= LCD_RASTER_ORDER;
> > +   lcdc_write(reg, LCD_RASTER_CTRL_REG);
> > +
> > +   switch (bpp) {
> > +   case 1:
> > +   case 2:
> > +   case 4:
> > +   case 16:
> > +           palette_sz = 16 * 2;
> > +           break;
> > +
> > +   case 8:
> > +           palette_sz = 256 * 2;
> 
> The global palette_sz seems like a way to return this value
> to a calling function. Just pas the fb_info or da8xx_fb_par pointer 
> here and set their values directly.

Agree.

> 
> > +           break;
> > +
> > +   default:
> > +           dev_dbg(dev, "GLCD: Unsupported BPP!\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   bpl = width * bpp / 8;
> > +   databuf_sz = height * bpl + palette_sz;
> > +
> > +   return 0;
> > +}
> > +
> > +/* Palette Initialization */
> > +static int init_palette(struct device *dev, struct fb_info *info)
> 
> There is no need to pass the device pointer if you can do &info->device
here.

Agree.

> 
> > +{
> > +   struct da8xx_fb_par *par = info->par;
> > +   unsigned short *palette = (unsigned short *)par->p_palette_base;
> > +   unsigned short i, size;
> > +
> > +   /* Palette Size */
> > +   size = (par->palette_size / sizeof(*palette));
> > +
> > +   /* Clear the Palette */
> > +   memset(palette, 0, par->palette_size);
> > +
> > +   /* Initialization of Palette for Default values */
> > +   for (i = 0; i < size; i++)
> > +           *(unsigned short *)(palette + i) = i;
> > +
> > +   /* Setup the BPP */
> > +   switch (par->bpp) {
> > +   case 1:
> > +           palette[0] |= BIT(11);
> > +           break;
> > +   case 2:
> > +           palette[0] |= BIT(12);
> > +           break;
> > +   case 4:
> > +           palette[0] |= (2 << 12);
> > +           break;
> > +   case 8:
> > +           palette[0] |= (3 << 12);
> > +           break;
> > +   case 16:
> > +           palette[0] |= (4 << 12);
> > +           break;
> > +   default:
> > +           dev_dbg(dev, "GLCD: Unsupported Video BPP %d!\n", par->bpp);
> > +           return -EINVAL;
> > +   }
> > +
> > +   for (i = 0; i < size; i++)
> > +           par->pseudo_palette[i] = i;
> > +
> > +   return 0;
> > +}
> > +
> > +static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
> > +                         unsigned blue, unsigned transp,
> > +                         struct fb_info *info)
> > +{
> > +   struct da8xx_fb_par *par = info->par;
> > +   unsigned short *palette = (unsigned short *)par->v_palette_base;
> > +   u_short pal;
> > +
> > +   if (regno > 255)
> > +           return 1;
> > +
> > +   if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
> > +       info->fix.visual == FB_VISUAL_TRUECOLOR)
> > +           return 1;
> > +
> 
> Setting pallete won't work for truecolor mode (16-bit). 
> Look at other framebuffers (e.g. tdfxfb) how to set palette
> for truecolor modes.

DA8XX LCD controller will not use palette data for 16-bit.

> 
> > +   if (par->bpp == 8) {
> > +           red >>= 8;
> > +           green >>= 8;
> > +           blue >>= 8;
> > +   }
> > +
> > +   pal = (red & 0x0f00);
> > +   pal |= (green & 0x00f0);
> > +   pal |= (blue & 0x000f);
> > +
> > +   palette[regno] = pal;
> > +
> > +   return 0;
> > +}
> > +
> > +static int lcd_reset(struct device *dev)
> > +{
> > +   int ret = 0;
> > +
> > +   /* Disable the Raster if previously Enabled */
> > +   if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE)
> > +           ret = lcd_disable_raster(dev);
> > +
> > +   /* DMA has to be disabled */
> > +   lcdc_write(0, LCD_DMA_CTRL_REG);
> > +   lcdc_write(0, LCD_RASTER_CTRL_REG);
> > +
> > +   return ret;
> > +}
> > +
> > +static int lcd_init(struct device *dev, const struct lcd_ctrl_config
*cfg,
> > +                   struct da8xx_panel *info)
> > +{
> > +   u32 bpp, ret = 0;
> > +
> > +   ret = lcd_reset(dev);
> > +   if (ret != 0)
> > +           return ret;
> > +
> > +   /* Configure the LCD clock divisor. */
> > +   lcdc_write(LCD_CLK_DIVISOR(info->pxl_clk) |
> > +                   (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
> > +
> > +   /* Configure the DMA burst size. */
> > +   ret = lcd_cfg_dma(dev, cfg->dma_burst_sz);
> > +   if (ret < 0)
> > +           return ret;
> > +
> > +   /* Configure the AC bias properties. */
> > +   lcd_cfg_ac_bias(dev, cfg->ac_bias, cfg->ac_bias_intrpt);
> > +
> > +   /* Configure the vertical and horizontal sync properties. */
> > +   lcd_cfg_vertical_sync(dev, info->vbp, info->vsw, info->vfp);
> > +   lcd_cfg_horizontal_sync(dev, info->hbp, info->hsw, info->hfp);
> > +
> > +   /* Configure for disply */
> > +   ret = lcd_cfg_display(dev, cfg);
> > +   if (ret < 0)
> > +           return ret;
> > +
> > +   if (QVGA != cfg->p_disp_panel->panel_type) {
> > +           dev_err(dev, "GLCD: Only QVGA panel is currently supported
!");
> > +           return -EINVAL;
> > +   }
> > +   if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
> > +       cfg->bpp >= cfg->p_disp_panel->min_bpp)
> > +           bpp = cfg->bpp;
> > +   else
> > +           bpp = cfg->p_disp_panel->max_bpp;
> > +   if (bpp == 12)
> > +           bpp = 16;
> > +   ret = lcd_cfg_frame_buffer(dev, (unsigned int)info->width,
> > +                           (unsigned int)info->height, bpp,
> > +                           cfg->raster_order);
> > +   if (ret < 0)
> > +           return ret;
> > +
> > +   /* Configure FDD */
> > +   lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) |
> > +                  (cfg->fdd << 12), LCD_RASTER_CTRL_REG);
> > +
> > +   return 0;
> > +}
> > +
> > +static irqreturn_t lcdc_irq_handler(int irq, void *arg)
> > +{
> > +   u32 stat = lcdc_read(LCD_STAT_REG);
> > +   u32 reg;
> > +
> > +   if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
> > +           reg = lcdc_read(LCD_RASTER_CTRL_REG);
> > +           lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
> > +           lcdc_write(stat, LCD_STAT_REG);
> > +           lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
> > +   } else
> > +           lcdc_write(stat, LCD_STAT_REG);
> > +
> > +   wake_up_interruptible(&da8xx_wq);
> > +   return IRQ_HANDLED;
> > +}
> > +
> > +static int fb_check_var(struct fb_var_screeninfo *var,
> > +                         struct fb_info *info)
> > +{
> > +   int err = 0;
> > +   switch (var->bits_per_pixel) {
> > +   case 1:
> > +   case 8:
> > +           var->red.offset = 0;
> > +           var->red.length = 8;
> > +           var->green.offset = 0;
> > +           var->green.length = 8;
> > +           var->blue.offset = 0;
> > +           var->blue.length = 8;
> > +           var->transp.offset = 0;
> > +           var->transp.length = 0;
> > +           break;
> > +   case 4:
> > +           var->red.offset = 0;
> > +           var->red.length = 4;
> > +           var->green.offset = 0;
> > +           var->green.length = 4;
> > +           var->blue.offset = 0;
> > +           var->blue.length = 4;
> > +           var->transp.offset = 0;
> > +           var->transp.length = 0;
> > +           break;
> > +   case 16:                /* RGB 565 */
> > +           var->red.offset = 0;
> > +           var->red.length = 5;
> > +           var->green.offset = 5;
> > +           var->green.length = 6;
> > +           var->blue.offset = 11;
> > +           var->blue.length = 5;
> > +           var->transp.offset = 0;
> > +           var->transp.length = 0;
> > +           break;
> > +   default:
> > +           err = -EINVAL;
> > +   }
> > +
> > +   var->red.msb_right = 0;
> > +   var->green.msb_right = 0;
> > +   var->blue.msb_right = 0;
> > +   var->transp.msb_right = 0;
> > +   return err;
> > +}
> > +
> > +static int fb_set_par(struct fb_info *info)
> > +{
> > +   struct fb_fix_screeninfo *fix = &info->fix;
> > +   struct fb_var_screeninfo *var = &info->var;
> > +
> > +   switch (var->bits_per_pixel) {
> > +   case 1:
> > +           fix->visual = FB_VISUAL_MONO01;
> > +           break;
> > +
> > +   case 2:
> > +   case 4:
> > +   case 8:
> > +           fix->visual = FB_VISUAL_PSEUDOCOLOR;
> > +           break;
> > +
> > +   case 16:
> > +           fix->visual = FB_VISUAL_TRUECOLOR;
> > +           break;
> > +   }
> > +
> > +   fix->line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
> > +   return 0;
> > +}
> > +
> 
> This function obviously does not change framebuffer mode as
> LCD controller's registers are not changed. This call can only mess
> up your display because fix->line_length is changed. If you do not
> intend to add mode changing to your driver remove completely
> the fb_check_var() and fb_set_par() functions.

I'll remove these two functions.

> 
> > +static int __devexit fb_remove(struct platform_device *dev)
> > +{
> > +   struct fb_info *info = dev_get_drvdata(&dev->dev);
> > +   int ret = 0;
> > +
> > +   if (info) {
> > +           struct da8xx_fb_par *par = info->par;
> > +
> > +           if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE)
> > +                   ret = lcd_disable_raster(&dev->dev);
> > +           lcdc_write(0, LCD_RASTER_CTRL_REG);
> > +
> > +           /* disable DMA  */
> > +           lcdc_write(0, LCD_DMA_CTRL_REG);
> > +
> > +           unregister_framebuffer(info);
> > +           fb_dealloc_cmap(&info->cmap);
> > +           dma_free_coherent(NULL, databuf_sz + PAGE_SIZE,
> > +                                   par->v_frame_buffer_mem_base,
> > +                                   par->p_frame_buffer_mem_base);
> > +           free_irq(par->irq, NULL);
> > +           clk_disable(par->lcdc_clk);
> > +           clk_put(par->lcdc_clk);
> > +           framebuffer_release(info);
> > +
> > +   }
> > +   return ret;
> > +}
> > +static int __init fb_probe(struct platform_device *device)
> > +{
> > +   struct da8xx_lcdc_platform_data *fb_pdata =
> > +                                           device->dev.platform_data;
> > +   struct lcd_ctrl_config *lcd_cfg;
> > +   struct da8xx_panel *lcdc_info;
> > +   struct fb_info *da8xx_fb_info;
> > +   struct resource *lcdc_regs;
> > +   struct clk *fb_clk = NULL;
> > +   struct da8xx_fb_par *par;
> > +   resource_size_t len;
> > +   int ret, i;
> > +
> > +   if (fb_pdata == NULL) {
> > +           dev_err(&device->dev, "Can not get platform data\n");
> > +           return -ENOENT;
> > +   }
> > +
> > +   lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
> > +   if (!lcdc_regs) {
> > +           dev_err(&device->dev,
> > +                   "Can not get memory resource for LCD controller\n");
> > +           return -ENOENT;
> > +   }
> > +
> > +   len = lcdc_regs->end - lcdc_regs->start + 1;
> > +
> > +   lcdc_regs = request_mem_region(lcdc_regs->start, len,
lcdc_regs->name);
> > +   if (!lcdc_regs)
> > +           return -EBUSY;
> > +
> > +   da8xx_fb_reg_base = (resource_size_t) ioremap(lcdc_regs->start,
len);
> > +
> > +   fb_clk = clk_get(&device->dev, NULL);
> > +   if (IS_ERR(fb_clk)) {
> > +           dev_err(&device->dev, "Can not get device clock\n");
> > +           return -ENODEV;
> > +   }
> > +   ret = clk_enable(fb_clk);
> > +   if (ret)
> > +           goto err_clk_put;
> > +
> > +   for (i = 0, lcdc_info = known_lcd_panels;
> > +           i < ARRAY_SIZE(known_lcd_panels);
> > +           i++, lcdc_info++) {
> > +           if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
> > +                   break;
> > +   }
> > +
> > +   if (i == ARRAY_SIZE(known_lcd_panels)) {
> > +           dev_err(&device->dev, "GLCD: No valid panel found\n");
> > +           return -ENODEV;
> > +   } else
> > +           dev_info(&device->dev, "GLCD: Found %s panel\n",
> > +                                   fb_pdata->type);
> > +
> > +   lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
> > +
> > +   if (lcd_init(&device->dev, lcd_cfg, lcdc_info) < 0) {
> > +           dev_err(&device->dev, "lcd_init failed\n");
> > +           ret = -EFAULT;
> > +           goto err_clk_disable;
> > +   }
> > +   da8xx_fb_info = framebuffer_alloc(sizeof(struct fb_info),
> > +                                                   &device->dev);
> 
> The first argument to the framebuffer_alloc is amount of additional 
> space allocated after the fb_info structure. You are supposed to put
> the size of the structure pointed by the fb->info_par parameter here.
> You have allocated space for two fb_info structure. Your code suggest
> you wanted space for one fb_info and one da8xx_fb_par structure.

I'll correct this to use da8xx_fb_par.

> 
> > +   if (!da8xx_fb_info) {
> > +           dev_dbg(&device->dev, "Memory allocation failed for
fb_info\n");
> > +           ret = -ENOMEM;
> > +           goto err_clk_disable;
> > +   }
> > +
> > +   par = da8xx_fb_info->par;
> 
> This is already done inside the framebuffer_alloc().

fb_info->par assignment is done inside framebuffer_alloc but here I'm
assigning fb_info->par to a local da8xx_fb_par variable.

> 
> > +   /* allocate frame buffer */
> > +   par->v_frame_buffer_mem_base = dma_alloc_coherent(NULL,
> > +                                           databuf_sz + PAGE_SIZE,
> > +
&par->p_frame_buffer_mem_base,
> > +                                           GFP_KERNEL | GFP_DMA);
> > +
> > +   if (!par->v_frame_buffer_mem_base) {
> > +           dev_err(&device->dev,
> > +                   "GLCD: kmalloc for frame buffer failed\n");
> > +           ret = -EINVAL;
> > +           goto err_release_fb;
> > +   }
> > +
> > +   /* move palette base pointer by (PAGE_SIZE - palette_sz) bytes */
> > +   par->v_palette_base = par->v_frame_buffer_mem_base +
> > +                           (PAGE_SIZE - palette_sz);
> > +   par->p_palette_base = par->p_frame_buffer_mem_base +
> > +                           (PAGE_SIZE - palette_sz);
> > +
> > +   /* First palette_sz byte of the frame buffer is the palette */
> > +   par->palette_size = palette_sz;
> > +
> > +   /* the rest of the frame buffer is pixel data */
> > +   par->v_screen_base = par->v_palette_base + palette_sz;
> > +   par->p_screen_base = par->p_palette_base + palette_sz;
> > +   par->screen_size = databuf_sz - palette_sz;
> > +
> > +   par->lcdc_clk = fb_clk;
> > +
> > +   da8xx_fb_fix.smem_start = (unsigned long)par->p_screen_base;
> > +   da8xx_fb_fix.smem_len = par->screen_size;
> 
> It shows that your da8xx_fb_par fields duplicates the standard ones.

You are right.

> 
> > +
> > +   init_waitqueue_head(&da8xx_wq);
> > +
> > +   par->irq = platform_get_irq(device, 0);
> > +   if (par->irq < 0) {
> > +           ret = -ENOENT;
> > +           goto err_release_fb_mem;
> > +   }
> > +
> > +   ret = request_irq(par->irq, lcdc_irq_handler, 0,
> > +                     DRIVER_NAME, NULL);
> 
> You can give a pointer to the fb_info structure as the last
> parameter here. It will be available inside the irq handler as 
> the argument.

Instead of fb_info, I'll pass the da8xx_fb_par structure so that I can use
da8xx_wq inside the irq_handler.

> 
> > +   if (ret)
> > +           goto err_free_irq;
> > +
> > +   /* Initialize par */
> > +   par->bpp = lcd_cfg->bpp;
> > +
> > +   da8xx_fb_var.xres = lcdc_info->width;
> > +   da8xx_fb_var.xres_virtual = lcdc_info->width;
> > +
> > +   da8xx_fb_var.yres = lcdc_info->height;
> > +   da8xx_fb_var.yres_virtual = lcdc_info->height;
> > +
> > +   da8xx_fb_var.grayscale =
> > +       lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
> > +   da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
> > +
> > +   da8xx_fb_var.hsync_len = lcdc_info->hsw;
> > +   da8xx_fb_var.vsync_len = lcdc_info->vsw;
> > +
> > +   /* Initialize fbinfo */
> > +   da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
> > +   da8xx_fb_info->screen_base = par->v_screen_base;
> > +   da8xx_fb_info->device = &device->dev;
> 
> This line does the same as there is already done inside the
framebuffer_alloc().

I'll remove this line.

> 
> > +   da8xx_fb_info->fix = da8xx_fb_fix;
> > +   da8xx_fb_info->var = da8xx_fb_var;
> > +   da8xx_fb_info->fbops = &da8xx_fb_ops;
> > +   da8xx_fb_info->pseudo_palette = par->pseudo_palette;
> > +
> > +   /* Initialize the Palette */
> > +   ret = init_palette(&device->dev, da8xx_fb_info);
> 
> I suppose you want to initialize the fb_info->cmap here (the 8 bit
palette)
> which is not allocated yet (next lines).

I'll modify this.

> 
> > +   if (ret < 0)
> > +           goto err_free_irq;
> > +
> > +   ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
> > +   if (ret)
> > +           goto err_free_irq;
> > +
> > +   /* Flush the buffer to the screen. */
> > +   lcd_blit(LOAD_DATA, (u32) par->p_palette_base);
> > +
> > +   /* initialize var_screeninfo */
> > +   da8xx_fb_var.activate = FB_ACTIVATE_FORCE;
> > +   fb_set_var(da8xx_fb_info, &da8xx_fb_var);
> > +
> > +   dev_set_drvdata(&device->dev, da8xx_fb_info);
> > +   /* Register the Frame Buffer  */
> > +   if (register_framebuffer(da8xx_fb_info) < 0) {
> > +           dev_err(&device->dev,
> > +                   "GLCD: Frame Buffer Registration Failed!\n");
> > +           ret = -EINVAL;
> > +           goto err_dealloc_cmap;
> > +   }
> > +
> > +   /* enable raster engine */
> > +   lcdc_write(lcdc_read(LCD_RASTER_CTRL_REG) |
> > +                   LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
> > +
> > +   return 0;
> > +
> > +err_dealloc_cmap:
> > +   fb_dealloc_cmap(&da8xx_fb_info->cmap);
> > +
> > +err_free_irq:
> > +   free_irq(par->irq, NULL);
> > +
> > +err_release_fb_mem:
> > +   dma_free_coherent(NULL, databuf_sz + PAGE_SIZE,
> > +                           par->v_frame_buffer_mem_base,
> > +                           par->p_frame_buffer_mem_base);
> > +
> > +err_release_fb:
> > +   framebuffer_release(da8xx_fb_info);
> > +
> > +err_clk_disable:
> > +   clk_disable(fb_clk);
> > +
> > +err_clk_put:
> > +   clk_put(fb_clk);
> > +
> > +   return ret;
> > +}
> > +
> > +static int fb_ioctl(struct fb_info *info, unsigned int cmd,
> > +                     unsigned long arg)
> > +{
> > +   struct lcd_sync_arg sync_arg;
> > +
> > +   switch (cmd) {
> > +   case FBIOGET_CONTRAST:
> > +   case FBIOPUT_CONTRAST:
> > +   case FBIGET_BRIGHTNESS:
> > +   case FBIPUT_BRIGHTNESS:
> > +   case FBIGET_COLOR:
> > +   case FBIPUT_COLOR:
> > +           return -EINVAL;
> > +   case FBIPUT_HSYNC:
> > +           if (copy_from_user(&sync_arg, (char *)arg,
> > +                           sizeof(struct lcd_sync_arg)))
> > +                   return -EINVAL;
> > +           lcd_cfg_horizontal_sync(info->dev, sync_arg.back_porch,
> > +                                   sync_arg.pulse_width,
> > +                                   sync_arg.front_porch);
> > +           break;
> > +   case FBIPUT_VSYNC:
> > +           if (copy_from_user(&sync_arg, (char *)arg,
> > +                           sizeof(struct lcd_sync_arg)))
> > +                   return -EINVAL;
> > +           lcd_cfg_vertical_sync(info->dev, sync_arg.back_porch,
> > +                                   sync_arg.pulse_width,
> > +                                   sync_arg.front_porch);
> > +           break;
> > +   default:
> > +           return -EINVAL;
> > +   }
> > +   return 0;
> > +}
> > +
> > +static struct fb_ops da8xx_fb_ops = {
> > +   .owner = THIS_MODULE,
> > +   .fb_check_var = fb_check_var,
> > +   .fb_set_par = fb_set_par,
> > +   .fb_setcolreg = fb_setcolreg,
> > +   .fb_ioctl = fb_ioctl,
> > +   .fb_fillrect = cfb_fillrect,
> > +   .fb_copyarea = cfb_copyarea,
> > +   .fb_imageblit = cfb_imageblit,
> > +};
> > +
> > +#ifdef CONFIG_PM
> > +static int fb_suspend(struct platform_device *dev, pm_message_t state)
> > +{
> > +    return -EBUSY;
> > +}
> > +static int fb_resume(struct platform_device *dev)
> > +{
> > +    return -EBUSY;
> > +}
> > +#else
> > +#define fb_suspend NULL
> > +#define fb_resume NULL
> > +#endif
> > +
> > +static struct platform_driver da8xx_fb_driver = {
> > +   .probe = fb_probe,
> > +   .remove = fb_remove,
> > +   .suspend = fb_suspend,
> > +   .resume = fb_resume,
> > +   .driver = {
> > +              .name = DRIVER_NAME,
> > +              .owner = THIS_MODULE,
> > +              },
> > +};
> > +
> > +static int __init da8xx_fb_init(void)
> > +{
> > +   return platform_driver_register(&da8xx_fb_driver);
> > +}
> > +
> > +static void __exit da8xx_fb_cleanup(void)
> > +{
> > +   platform_driver_unregister(&da8xx_fb_driver);
> > +}
> > +
> > +module_init(da8xx_fb_init);
> > +module_exit(da8xx_fb_cleanup);
> > +
> > +MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx");
> > +MODULE_AUTHOR("MontaVista Software");
> > +MODULE_LICENSE("GPL");
> > diff --git a/include/linux/da8xx-fb.h b/include/linux/da8xx-fb.h
> 
> It is probably better to put this header into the include/video 
> or platform specific include directory. The include/linux is for
> global stuff.

I'll move this file into linux/video folder.

> 
> > new file mode 100644
> > index 0000000..5f77675
> > --- /dev/null
> > +++ b/include/linux/da8xx-fb.h
> > @@ -0,0 +1,106 @@
> > +/*
> > + * Header file for TI DA8XX LCD controller platform data.
> > + *
> > + * Copyright (C) 2008-2009 MontaVista Software Inc.
> > + * Copyright (C) 2008-2009 Texas Instruments Inc
> > + *
> > + * This file is licensed under the terms of the GNU General Public
License
> > + * version 2. This program is licensed "as is" without any warranty of
any
> > + * kind, whether express or implied.
> > + */
> > +
> > +#ifndef DA8XX_FB_H
> > +#define DA8XX_FB_H
> > +
> > +enum panel_type {
> > +   QVGA = 0
> > +};
> > +
> > +enum panel_shade {
> > +   MONOCHROME = 0,
> > +   COLOR_ACTIVE,
> > +   COLOR_PASSIVE,
> > +};
> > +
> > +enum raster_load_mode {
> > +   LOAD_DATA = 1,
> > +   LOAD_PALETTE,
> > +};
> > +
> > +struct display_panel {
> > +   enum panel_type panel_type; /* QVGA */
> > +   int max_bpp;
> > +   int min_bpp;
> > +   enum panel_shade panel_shade;
> > +};
> > +
> > +struct da8xx_lcdc_platform_data {
> > +   const char manu_name[10];
> > +   void *controller_data;
> > +   const char type[25];
> > +};
> > +
> > +struct lcd_ctrl_config {
> > +   const struct display_panel *p_disp_panel;
> > +
> > +   /* AC Bias Pin Frequency */
> > +   int ac_bias;
> > +
> > +   /* AC Bias Pin Transitions per Interrupt */
> > +   int ac_bias_intrpt;
> > +
> > +   /* DMA burst size */
> > +   int dma_burst_sz;
> > +
> > +   /* Bits per pixel */
> > +   int bpp;
> > +
> > +   /* FIFO DMA Request Delay */
> > +   int fdd;
> > +
> > +   /* TFT Alternative Signal Mapping (Only for active) */
> > +   unsigned char tft_alt_mode;
> > +
> > +   /* 12 Bit Per Pixel (5-6-5) Mode (Only for passive) */
> > +   unsigned char stn_565_mode;
> > +
> > +   /* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */
> > +   unsigned char mono_8bit_mode;
> > +
> > +   /* Invert pixel clock */
> > +   unsigned char invert_pxl_clock;
> > +
> > +   /* Invert line clock */
> > +   unsigned char invert_line_clock;
> > +
> > +   /* Invert frame clock  */
> > +   unsigned char invert_frm_clock;
> > +
> > +   /* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
> > +   unsigned char sync_edge;
> > +
> > +   /* Horizontal and Vertical Sync: Control: 0=ignore */
> > +   unsigned char sync_ctrl;
> > +
> > +   /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
> > +   unsigned char raster_order;
> > +};
> > +
> > +struct lcd_sync_arg {
> > +   int back_porch;
> > +   int front_porch;
> > +   int pulse_width;
> > +};
> > +
> > +/* ioctls */
> > +#define FBIOGET_CONTRAST   _IOR('F', 1, int)
> > +#define FBIOPUT_CONTRAST   _IOW('F', 2, int)
> > +#define FBIGET_BRIGHTNESS  _IOR('F', 3, int)
> > +#define FBIPUT_BRIGHTNESS  _IOW('F', 3, int)
> > +#define FBIGET_COLOR               _IOR('F', 5, int)
> > +#define FBIPUT_COLOR               _IOW('F', 6, int)
> > +#define FBIPUT_HSYNC               _IOW('F', 9, int)
> > +#define FBIPUT_VSYNC               _IOW('F', 10, int)
> > +
> > +#endif  /* ifndef DA8XX_FB_H */
> > +
> > -- 
> > 1.5.6
> > 
> 
> I am looking forward to updated version of this patch.
> 

Thanks very much for your comments. I'll re-submit this patch.

Regards, Sudhakar


_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to