this patch adds features for supportting MIPI Interface and CPU mode to s3c-fb.c for this, I added following features. . add struct fb_cmdmode - this structure would be used for cpu interface. . add interface_mode to struct s3c_fb_platdata. - this variable would be used to distinguishe whether CPU or RGB mode. . add two functions for cpu interface. - s3c_fb_set_trigger would be used for to send trigger signal to FIMD. - s3c_fb_is_i80_frame_done would be used to check framedone status. . add a function for setting timing. - I added this function because it have to distinguishe interfaces. (CPU or RGB mode) . add register definitions for using MIPI-DSI mode. Signed-off-by: InKi Dae <inki.dae@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/inc lude/plat/fb.h index 27d3b49..b0204f8 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h @@ -22,6 +22,23 @@ */ #define S3C_FB_MAX_WIN (5) +enum { + FIMD_VIDEO_MODE = 0, + FIMD_COMMAND_MODE +}; + +struct fb_cmdmode { + const char *name; /* optional */ + u32 refresh; /* optional */ + u32 xres; + u32 yres; + u32 pixclock; + u32 cs_setup; + u32 wr_setup; + u32 wr_act; + u32 wr_hold; +}; + /** * struct s3c_fb_pd_win - per window setup data * @win_mode: The display parameters to initialise (not for window 0) @@ -30,6 +47,7 @@ */ struct s3c_fb_pd_win { struct fb_videomode win_mode; + struct fb_cmdmode cmd_mode; unsigned short default_bpp; unsigned short max_bpp; @@ -42,6 +60,7 @@ struct s3c_fb_pd_win { * @setup_gpio: Setup the external GPIO pins to the right state to transfer * the data from the display system to the connected display * device. + * @interface_mode: cpu mode or rgb mode. * @vidcon0: The base vidcon0 values to control the panel data format. * @vidcon1: The base vidcon1 values to control the panel data output. * @win: The setup data for each hardware window, or NULL for unused. @@ -57,6 +76,7 @@ struct s3c_fb_platdata { void (*setup_gpio)(void); struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; + u32 interface_mode; u32 vidcon0; u32 vidcon1; @@ -91,4 +111,10 @@ extern void s5pc100_fb_gpio_setup_24bpp(void); */ extern void s5pv210_fb_gpio_setup_24bpp(void); +struct fb_info; + +extern void s3c_fb_set_trigger(struct fb_info *info); + +extern int s3c_fb_is_i80_frame_done(struct fb_info *info); + #endif /* __PLAT_S3C_FB_H */ diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-sam sung/include/plat/regs-fb-v4.h index 0f43599..4d5954b 100644 --- a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h +++ b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h @@ -135,6 +135,22 @@ #define WPALCON (0x1A0) +/* For CPU interface. */ +#define TRIGCON (0x1a4) +#define TRGMODE_I80_ENABLE (1 << 0) +#define SWTRGCMD_I80_TRIGGER (1 << 1) +#define SWFRSTATUS_I80 (1 << 2) + +#define I80IFCONA0 (0x1b0) +#define I80IFEN_ENABLE (1 << 0) +#define RSPOL_HIGH (1 << 2) +#define LCD_WR_HOLD(x) (((x) & 0xf) << 4) +#define LCD_WR_ACT(x) (((x) & 0xf) << 8) +#define LCD_WR_SETUP(x) (((x) & 0xf) << 12) +#define LCD_CS_SETUP(x) (((x) & 0xf) << 16) + +#define I80IFCONB0 (0x1b8) + /* Palette control */ /* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L), * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */ diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsun g/include/plat/regs-fb.h index 0ef806e..70342aa 100644 --- a/arch/arm/plat-samsung/include/plat/regs-fb.h +++ b/arch/arm/plat-samsung/include/plat/regs-fb.h @@ -38,6 +38,7 @@ #define VIDCON0_VIDOUT_TV (0x1 << 26) #define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26) #define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26) +#define VIDCON0_DSI_EN_ENABLE (1 << 30) #define VIDCON0_L1_DATA_MASK (0x7 << 23) #define VIDCON0_L1_DATA_SHIFT (23) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 9682ecc..28d34ef 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -255,6 +255,73 @@ static int s3c_fb_align_word(unsigned int bpp, unsigned int pix) } /** + * s3c_fb_set_trigger - fimd trigger based on cpu interface. + */ +void s3c_fb_set_trigger(struct fb_info *info) +{ + struct s3c_fb_win *win = info->par; + struct s3c_fb *sfb = win->parent; + void __iomem *regs = sfb->regs; + u32 reg = 0; + + reg = readl(regs + TRIGCON); + + reg |= TRGMODE_I80_ENABLE | SWTRGCMD_I80_TRIGGER; + + writel(reg, regs + TRIGCON); +} + +/** + * s3c_fb_is_i80_frame_done - get i80 frame done status. + */ +int s3c_fb_is_i80_frame_done(struct fb_info *info) +{ + struct s3c_fb_win *win = info->par; + struct s3c_fb *sfb = win->parent; + void __iomem *regs = sfb->regs; + u32 reg = 0; + + reg = readl(regs + TRIGCON); + + return (((reg & SWFRSTATUS_I80) == SWFRSTATUS_I80) ? 1 : 0); +} + +/** + * s3c_fb_set_cpu_timing - set cpu timing. + */ +static void s3c_fb_set_timing(struct s3c_fb *sfb, struct fb_info *info) +{ + struct s3c_fb_win *win = info->par; + struct s3c_fb_pd_win *windata = win->windata; + struct fb_var_screeninfo *var = &info->var; + void __iomem *regs = sfb->regs; + u32 reg = 0; + + if (sfb->pdata->interface_mode == FIMD_VIDEO_MODE) { + reg = VIDTCON0_VBPD(var->upper_margin - 1) | + VIDTCON0_VFPD(var->lower_margin - 1) | + VIDTCON0_VSPW(var->vsync_len - 1); + + writel(reg, regs + VIDTCON0); + + reg = VIDTCON1_HBPD(var->left_margin - 1) | + VIDTCON1_HFPD(var->right_margin - 1) | + VIDTCON1_HSPW(var->hsync_len - 1); + + writel(reg, regs + VIDTCON1); + } else if (sfb->pdata->interface_mode == FIMD_COMMAND_MODE) { + reg = LCD_CS_SETUP(windata->cmd_mode.cs_setup) | + LCD_WR_SETUP(windata->cmd_mode.wr_setup) | + LCD_WR_ACT(windata->cmd_mode.wr_act) | + LCD_WR_HOLD(windata->cmd_mode.wr_hold) | + I80IFEN_ENABLE; + + writel(reg, regs + I80IFCONA0); + } else + dev_warn(sfb->dev, "wrong interface type.\n"); +} + +/** * s3c_fb_set_par() - framebuffer request to set new framebuffer state. * @info: The framebuffer to change. * @@ -318,17 +385,7 @@ static int s3c_fb_set_par(struct fb_info *info) data |= VIDCON0_ENVID | VIDCON0_ENVID_F; writel(data, regs + VIDCON0); - data = VIDTCON0_VBPD(var->upper_margin - 1) | - VIDTCON0_VFPD(var->lower_margin - 1) | - VIDTCON0_VSPW(var->vsync_len - 1); - - writel(data, regs + VIDTCON0); - - data = VIDTCON1_HBPD(var->left_margin - 1) | - VIDTCON1_HFPD(var->right_margin - 1) | - VIDTCON1_HSPW(var->hsync_len - 1); - - writel(data, regs + VIDTCON1); + s3c_fb_set_timing(sfb, info); data = VIDTCON2_LINEVAL(var->yres - 1) | VIDTCON2_HOZVAL(var->xres - 1); @@ -744,7 +801,8 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, un signed int win_no, struct s3c_fb_win **res) { struct fb_var_screeninfo *var; - struct fb_videomode *initmode; + struct fb_videomode *videomode; + struct fb_cmdmode *cmdmode; struct s3c_fb_pd_win *windata; struct s3c_fb_win *win; struct fb_info *fbinfo; @@ -763,11 +821,20 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, } windata = sfb->pdata->win[win_no]; - initmode = &windata->win_mode; WARN_ON(windata->max_bpp == 0); - WARN_ON(windata->win_mode.xres == 0); - WARN_ON(windata->win_mode.yres == 0); + + if (sfb->pdata->interface_mode == FIMD_VIDEO_MODE) { + WARN_ON(windata->win_mode.xres == 0); + WARN_ON(windata->win_mode.yres == 0); + + videomode = &windata->win_mode; + } else { + WARN_ON(windata->cmd_mode.xres == 0); + WARN_ON(windata->cmd_mode.yres == 0); + + cmdmode = &windata->cmd_mode; + } win = fbinfo->par; var = &fbinfo->var; @@ -777,18 +844,19 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, win->index = win_no; win->palette_buffer = (u32 *)(win + 1); - ret = s3c_fb_alloc_memory(sfb, win); - if (ret) { - dev_err(sfb->dev, "failed to allocate display memory\n"); - return ret; + /* setup the initial video or cpu mode from the window */ + if (sfb->pdata->interface_mode == FIMD_VIDEO_MODE) + fb_videomode_to_var(&fbinfo->var, videomode); + else { + var->xres = cmdmode->xres; + var->yres = cmdmode->yres; + var->xres_virtual = cmdmode->xres; + var->yres_virtual = cmdmode->yres; + var->xoffset = 0; + var->yoffset = 0; + var->pixclock = cmdmode->pixclock; } - /* setup the r/b/g positions for the window's palette */ - s3c_fb_init_palette(win_no, &win->palette); - - /* setup the initial video mode from the window */ - fb_videomode_to_var(&fbinfo->var, initmode); - fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; fbinfo->fix.accel = FB_ACCEL_NONE; fbinfo->var.activate = FB_ACTIVATE_NOW; @@ -798,6 +866,15 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, u nsigned int win_no, fbinfo->flags = FBINFO_FLAG_DEFAULT; fbinfo->pseudo_palette = &win->pseudo_palette; + ret = s3c_fb_alloc_memory(sfb, win); + if (ret) { + dev_err(sfb->dev, "failed to allocate display memory\n"); + return ret; + } + + /* setup the r/b/g positions for the window's palette */ + s3c_fb_init_palette(win_no, &win->palette); + /* prepare to actually start the framebuffer */ ret = s3c_fb_check_var(&fbinfo->var, fbinfo); [ Part 3: "Included Message" ] From: linux-fbdev-devel-request@xxxxxxxxxxxxxxxxxxxxx Subject: confirm 037aaa7ee1b9ad14a6db9b9fd69a7de8519f45e5 If you reply to this message, keeping the Subject: header intact, Mailman will discard the held message. Do this if the message is spam. If you reply to this message and include an Approved: header with the list password in it, the message will be approved for posting to the list. The Approved: header can also appear in the first line of the body of the reply.