You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
(1) |
Apr
(104) |
May
(81) |
Jun
(248) |
Jul
(133) |
Aug
(33) |
Sep
(53) |
Oct
(82) |
Nov
(166) |
Dec
(71) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(121) |
Feb
(42) |
Mar
(39) |
Apr
(84) |
May
(87) |
Jun
(58) |
Jul
(97) |
Aug
(130) |
Sep
(32) |
Oct
(139) |
Nov
(108) |
Dec
(216) |
2003 |
Jan
(299) |
Feb
(136) |
Mar
(392) |
Apr
(141) |
May
(137) |
Jun
(107) |
Jul
(94) |
Aug
(262) |
Sep
(300) |
Oct
(216) |
Nov
(72) |
Dec
(94) |
2004 |
Jan
(174) |
Feb
(192) |
Mar
(215) |
Apr
(314) |
May
(319) |
Jun
(293) |
Jul
(205) |
Aug
(161) |
Sep
(192) |
Oct
(226) |
Nov
(308) |
Dec
(89) |
2005 |
Jan
(127) |
Feb
(269) |
Mar
(588) |
Apr
(106) |
May
(77) |
Jun
(77) |
Jul
(161) |
Aug
(239) |
Sep
(86) |
Oct
(112) |
Nov
(153) |
Dec
(145) |
2006 |
Jan
(87) |
Feb
(57) |
Mar
(129) |
Apr
(109) |
May
(102) |
Jun
(232) |
Jul
(97) |
Aug
(69) |
Sep
(67) |
Oct
(69) |
Nov
(214) |
Dec
(82) |
2007 |
Jan
(133) |
Feb
(307) |
Mar
(121) |
Apr
(171) |
May
(229) |
Jun
(156) |
Jul
(185) |
Aug
(160) |
Sep
(122) |
Oct
(130) |
Nov
(78) |
Dec
(27) |
2008 |
Jan
(105) |
Feb
(137) |
Mar
(146) |
Apr
(148) |
May
(239) |
Jun
(208) |
Jul
(157) |
Aug
(244) |
Sep
(119) |
Oct
(125) |
Nov
(189) |
Dec
(225) |
2009 |
Jan
(157) |
Feb
(139) |
Mar
(106) |
Apr
(130) |
May
(246) |
Jun
(189) |
Jul
(128) |
Aug
(127) |
Sep
(88) |
Oct
(86) |
Nov
(216) |
Dec
(9) |
2010 |
Jan
(5) |
Feb
|
Mar
(11) |
Apr
(31) |
May
(3) |
Jun
|
Jul
(7) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Krzysztof H. <krz...@po...> - 2009-05-23 06:25:40
|
On Thu, 21 May 2009 04:28:53 +0800 Harald Welte <Har...@vi...> wrote: > From: Harald Welte <la...@gn...> > > The VX800/VX820 and the VX855/VX875 chipsets have a different 2D > acceleration engine called "M1". The M1 engine has some subtle > (and some not-so-subtle) differences to the previous engines, > so support for accelerated framebuffer on those chipsets was > disabled so far. > > This patch adds full support for the M1 engine to viafb. > > Signed-off-by: Harald Welte <Har...@vi...> > --- Acked-by: Krzysztof Helt <krz...@wp...> You can use more viafb_2d_writel() function in all the code. > drivers/video/via/accel.c | 72 ++++++++++++++++++++++++++++++++++++----- > drivers/video/via/accel.h | 40 +++++++++++++++++++++++ > drivers/video/via/viafbdev.c | 2 - > 3 files changed, 103 insertions(+), 11 deletions(-) > > diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c > index b3a414e..a4b66be 100644 > --- a/drivers/video/via/accel.c > +++ b/drivers/video/via/accel.c > @@ -20,8 +20,34 @@ > */ > #include "global.h" > > +/* Somehow, the M1 engine has the registers in slightly different > + * locations than previous 2D acceleration engines */ > +static u_int8_t via_m1_eng_reg[] = { > + [VIA_REG_GECMD] = VIA_REG_GECMD_M1, > + [VIA_REG_GEMODE] = VIA_REG_GEMODE_M1, > + [VIA_REG_SRCPOS] = VIA_REG_SRCPOS_M1, > + [VIA_REG_DSTPOS] = VIA_REG_DSTPOS_M1, > + [VIA_REG_DIMENSION] = VIA_REG_DIMENSION_M1, > + [VIA_REG_PATADDR] = VIA_REG_PATADDR_M1, > + [VIA_REG_FGCOLOR] = VIA_REG_FGCOLOR_M1, > + [VIA_REG_BGCOLOR] = VIA_REG_BGCOLOR_M1, > + [VIA_REG_CLIPTL] = VIA_REG_CLIPTL_M1, > + [VIA_REG_CLIPBR] = VIA_REG_CLIPBR_M1, > + [VIA_REG_OFFSET] = VIA_REG_OFFSET_M1, > + [VIA_REG_KEYCONTROL] = VIA_REG_KEYCONTROL_M1, > + [VIA_REG_SRCBASE] = VIA_REG_SRCBASE_M1, > + [VIA_REG_DSTBASE] = VIA_REG_DSTBASE_M1, > + [VIA_REG_PITCH] = VIA_REG_PITCH_M1, > + [VIA_REG_MONOPAT0] = VIA_REG_MONOPAT0_M1, > + [VIA_REG_MONOPAT1] = VIA_REG_MONOPAT1_M1, > +}; > + > void viafb_2d_writel(u_int32_t val, u_int32_t reg) > { > + if (viaparinfo->chip_info->twod_engine == VIA_2D_ENG_M1 && > + reg < ARRAY_SIZE(via_m1_eng_reg)) > + reg = via_m1_eng_reg[reg]; > + > writel(val, viaparinfo->io_virt + reg); > } > > @@ -41,16 +67,26 @@ void viafb_init_2d_engine(void) > { > u32 dwVQStartAddr, dwVQEndAddr; > u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; > - int i; > + int i, highest_reg; > > /* init 2D engine regs to reset 2D engine */ > - for (i = 0; i <= 0x40; i+= 4) > + switch (viaparinfo->chip_info->twod_engine) { > + case VIA_2D_ENG_M1: > + highest_reg = 0x5c; > + break; > + default: > + highest_reg = 0x40; > + break; > + } > + for (i = 0; i <= highest_reg; i+= 4) > writel(0x0, viaparinfo->io_virt + i); > > /* Init AGP and VQ regs */ > switch (viaparinfo->chip_info->gfx_chip_name) { > case UNICHROME_K8M890: > case UNICHROME_P4M900: > + case UNICHROME_VX800: > + case UNICHROME_VX855: > writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET); > writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); > writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); > @@ -85,6 +121,8 @@ void viafb_init_2d_engine(void) > switch (viaparinfo->chip_info->gfx_chip_name) { > case UNICHROME_K8M890: > case UNICHROME_P4M900: > + case UNICHROME_VX800: > + case UNICHROME_VX855: > dwVQStartL |= 0x20000000; > dwVQEndL |= 0x20000000; > dwVQStartEndH |= 0x20000000; > @@ -97,6 +135,8 @@ void viafb_init_2d_engine(void) > switch (viaparinfo->chip_info->gfx_chip_name) { > case UNICHROME_K8M890: > case UNICHROME_P4M900: > + case UNICHROME_VX800: > + case UNICHROME_VX855: > writel(0x00100000, > viaparinfo->io_virt + VIA_REG_CR_TRANSET); You can use more viafb_2d_writel() function in all the code. > writel(dwVQStartEndH, > @@ -162,6 +202,8 @@ void viafb_init_2d_engine(void) > switch (viaparinfo->chip_info->gfx_chip_name) { > case UNICHROME_K8M890: > case UNICHROME_P4M900: > + case UNICHROME_VX800: > + case UNICHROME_VX855: > writel(0x00100000, > viaparinfo->io_virt + VIA_REG_CR_TRANSET); > writel(0x74301000, > @@ -216,7 +258,8 @@ void viafb_set_2d_mode(struct fb_info *info) > /* Set source and destination pitch (128bit aligned) */ > pitch = (viaparinfo->hres * viaparinfo->bpp >> 3) >> 3; > pitch_reg = pitch | (pitch << 16); > - pitch_reg |= VIA_PITCH_ENABLE; > + if (viaparinfo->chip_info->twod_engine != VIA_2D_ENG_M1) > + pitch_reg |= VIA_PITCH_ENABLE; > viafb_2d_writel(pitch_reg, VIA_REG_PITCH); > } > > @@ -259,15 +302,26 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status) > int viafb_wait_engine_idle(void) > { > int loop = 0; > + u_int32_t status_mask; > > - while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & > - VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { > - loop++; > - cpu_relax(); > + switch (viaparinfo->chip_info->twod_engine) { > + case VIA_2D_ENG_H5: > + case VIA_2D_ENG_M1: > + status_mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 | > + VIA_3D_ENG_BUSY_M1; > + break; > + default: > + while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & > + VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { > + loop++; > + cpu_relax(); > + } > + status_mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | > + VIA_3D_ENG_BUSY; > + break; > } > > - while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & > - (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && > + while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & status_mask) && > (loop < MAXLOOP)) { > loop++; > cpu_relax(); > diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h > index 5081ac2..9a39ed1 100644 > --- a/drivers/video/via/accel.h > +++ b/drivers/video/via/accel.h > @@ -67,6 +67,34 @@ > /* from 0x100 to 0x1ff */ > #define VIA_REG_COLORPAT 0x100 > > +/* defines for VIA 2D registers for vt3353/3409 (M1 engine)*/ > +#define VIA_REG_GECMD_M1 0x000 > +#define VIA_REG_GEMODE_M1 0x004 > +#define VIA_REG_GESTATUS_M1 0x004 /* as same as VIA_REG_GEMODE */ > +#define VIA_REG_PITCH_M1 0x008 /* pitch of src and dst */ > +#define VIA_REG_DIMENSION_M1 0x00C /* width and height */ > +#define VIA_REG_DSTPOS_M1 0x010 > +#define VIA_REG_LINE_XY_M1 0x010 > +#define VIA_REG_DSTBASE_M1 0x014 > +#define VIA_REG_SRCPOS_M1 0x018 > +#define VIA_REG_LINE_K1K2_M1 0x018 > +#define VIA_REG_SRCBASE_M1 0x01C > +#define VIA_REG_PATADDR_M1 0x020 > +#define VIA_REG_MONOPAT0_M1 0x024 > +#define VIA_REG_MONOPAT1_M1 0x028 > +#define VIA_REG_OFFSET_M1 0x02C > +#define VIA_REG_LINE_ERROR_M1 0x02C > +#define VIA_REG_CLIPTL_M1 0x040 /* top and left of clipping */ > +#define VIA_REG_CLIPBR_M1 0x044 /* bottom and right of clipping */ > +#define VIA_REG_KEYCONTROL_M1 0x048 /* color key control */ > +#define VIA_REG_FGCOLOR_M1 0x04C > +#define VIA_REG_DSTCOLORKEY_M1 0x04C /* as same as VIA_REG_FG */ > +#define VIA_REG_BGCOLOR_M1 0x050 > +#define VIA_REG_SRCCOLORKEY_M1 0x050 /* as same as VIA_REG_BG */ > +#define VIA_REG_MONOPATFGC_M1 0x058 /* Add BG color of Pattern. */ > +#define VIA_REG_MONOPATBGC_M1 0x05C /* Add FG color of Pattern. */ > +#define VIA_REG_COLORPAT_M1 0x100 /* from 0x100 to 0x1ff */ > + > /* VIA_REG_PITCH(0x38): Pitch Setting */ > #define VIA_PITCH_ENABLE 0x80000000 > > @@ -157,6 +185,18 @@ > /* Virtual Queue is busy */ > #define VIA_VR_QUEUE_BUSY 0x00020000 > > +/* VIA_REG_STATUS(0x400): Engine Status for H5 */ > +#define VIA_CMD_RGTR_BUSY_H5 0x00000010 /* Command Regulator is busy */ > +#define VIA_2D_ENG_BUSY_H5 0x00000002 /* 2D Engine is busy */ > +#define VIA_3D_ENG_BUSY_H5 0x00001FE1 /* 3D Engine is busy */ > +#define VIA_VR_QUEUE_BUSY_H5 0x00000004 /* Virtual Queue is busy */ > + > +/* VIA_REG_STATUS(0x400): Engine Status for VT3353/3409 */ > +#define VIA_CMD_RGTR_BUSY_M1 0x00000010 /* Command Regulator is busy */ > +#define VIA_2D_ENG_BUSY_M1 0x00000002 /* 2D Engine is busy */ > +#define VIA_3D_ENG_BUSY_M1 0x00001FE1 /* 3D Engine is busy */ > +#define VIA_VR_QUEUE_BUSY_M1 0x00000004 /* Virtual Queue is busy */ > + > #define MAXLOOP 0xFFFFFF > > void viafb_2d_writel(u_int32_t val, u_int32_t reg); > diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c > index d6a38ca..3a22a3a 100644 > --- a/drivers/video/via/viafbdev.c > +++ b/drivers/video/via/viafbdev.c > @@ -214,8 +214,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, > if (!info->par) > return -1; > p_viafb_par = (struct viafb_par *)info->par; > - if (p_viafb_par->chip_info->twod_engine == VIA_2D_ENG_M1) > - var->accel_flags = 0; > > return 0; > } > -- > 1.6.2.4 > > > ------------------------------------------------------------------------------ > Crystal Reports - New Free Runtime and 30 Day Trial > Check out the new simplified licensing option that enables > unlimited royalty-free distribution of the report engine > for externally facing server and web deployment. > http://p.sf.net/sfu/businessobjects > _______________________________________________ > Linux-fbdev-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel > ---------------------------------------------------------------------- Weekend w gorach za 100 PLN! Sprawdz >>> http://link.interia.pl/f218c |
From: Krzysztof H. <krz...@po...> - 2009-05-23 06:23:09
|
On Thu, 21 May 2009 04:28:52 +0800 Harald Welte <Har...@vi...> wrote: > From: Harald Welte <la...@gn...> > > This will help us for the upcoming support for 2D acceleration using > the M1 engine. > > Signed-off-by: Harald Welte <Har...@vi...> > --- Acked-by: Krzysztof Helt <krz...@wp...> > drivers/video/via/chip.h | 8 ++++++++ > drivers/video/via/hw.c | 15 +++++++++++++++ > drivers/video/via/viafbdev.c | 3 +-- > 3 files changed, 24 insertions(+), 2 deletions(-) > > diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h > index 03e90cf..7f4bf73 100644 > --- a/drivers/video/via/chip.h > +++ b/drivers/video/via/chip.h > @@ -122,10 +122,18 @@ struct lvds_chip_information { > int i2c_port; > }; > > +/* The type of 2D engine */ > +enum via_2d_engine { > + VIA_2D_ENG_H2, > + VIA_2D_ENG_H5, > + VIA_2D_ENG_M1, > +}; > + > struct chip_information { > int gfx_chip_name; > int gfx_chip_revision; > int chip_on_slot; > + enum via_2d_engine twod_engine; > struct tmds_chip_information tmds_chip_info; > struct lvds_chip_information lvds_chip_info; > struct lvds_chip_information lvds_chip_info2; > diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c > index e06d6b7..e14b852 100644 > --- a/drivers/video/via/hw.c > +++ b/drivers/video/via/hw.c > @@ -2092,6 +2092,21 @@ static void init_gfx_chip_info(struct pci_dev *pdev, > CX700_REVISION_700; > } > } > + > + /* Determine which 2D engine we have */ > + switch (viaparinfo->chip_info->gfx_chip_name) { > + case UNICHROME_VX800: > + case UNICHROME_VX855: > + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1; > + break; > + case UNICHROME_K8M890: > + case UNICHROME_P4M900: > + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5; > + break; > + default: > + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2; > + break; > + } > } > > static void init_tmds_chip_info(void) > diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c > index 859827b..d6a38ca 100644 > --- a/drivers/video/via/viafbdev.c > +++ b/drivers/video/via/viafbdev.c > @@ -214,8 +214,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var, > if (!info->par) > return -1; > p_viafb_par = (struct viafb_par *)info->par; > - if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800 || > - p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX855) > + if (p_viafb_par->chip_info->twod_engine == VIA_2D_ENG_M1) > var->accel_flags = 0; > > return 0; > -- > 1.6.2.4 > > > ------------------------------------------------------------------------------ > Crystal Reports - New Free Runtime and 30 Day Trial > Check out the new simplified licensing option that enables > unlimited royalty-free distribution of the report engine > for externally facing server and web deployment. > http://p.sf.net/sfu/businessobjects > _______________________________________________ > Linux-fbdev-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel > ---------------------------------------------------------------------- Sprawdz pogode na dzis! Kliknij >>> http://link.interia.pl/f217d |
From: Krzysztof H. <krz...@po...> - 2009-05-23 06:22:24
|
On Thu, 21 May 2009 04:28:50 +0800 Harald Welte <Har...@vi...> wrote: > From: Harald Welte <la...@gn...> > > This is required as preparation for supporting the new M1 engine of the > VX800/VX855 which has registers at permutated addresses. > > Signed-off-by: Harald Welte <Har...@vi...> > --- Acked-by: Krzysztof Helt <krz...@wp...> > drivers/video/via/accel.c | 13 +++++++++---- > drivers/video/via/accel.h | 1 + > drivers/video/via/viafbdev.c | 38 +++++++++++++++++--------------------- > 3 files changed, 27 insertions(+), 25 deletions(-) > > diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c > index 4a1183f..c3af95f 100644 > --- a/drivers/video/via/accel.c > +++ b/drivers/video/via/accel.c > @@ -20,6 +20,11 @@ > */ > #include "global.h" > > +void viafb_2d_writel(u_int32_t val, u_int32_t reg) > +{ > + writel(val, viaparinfo->io_virt + reg); > +} > + > void viafb_init_accel(void) > { > viaparinfo->fbmem_free -= CURSOR_SIZE; > @@ -213,18 +218,18 @@ void viafb_set_2d_mode(struct fb_info *info) > dwGEMode |= VIA_GEM_8bpp; > break; > } > - writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE); > + viafb_2d_writel(dwGEMode, VIA_REG_GEMODE); > > /* Set source and destination base */ > base = ((void *)info->screen_base - viafb_FB_MM); > - writel(base >> 3, viaparinfo->io_virt + VIA_REG_SRCBASE); > - writel(base >> 3, viaparinfo->io_virt + VIA_REG_DSTBASE); > + viafb_2d_writel(base >> 3, VIA_REG_SRCBASE); > + viafb_2d_writel(base >> 3, VIA_REG_DSTBASE); > > /* Set source and destination pitch (128bit aligned) */ > pitch = (viaparinfo->hres * viaparinfo->bpp >> 3) >> 3; > pitch_reg = pitch | (pitch << 16); > pitch_reg |= VIA_PITCH_ENABLE; > - writel(pitch_reg, viaparinfo->io_virt + VIA_REG_PITCH); > + viafb_2d_writel(pitch_reg, VIA_REG_PITCH); > } > > void viafb_hw_cursor_init(void) > diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h > index bef3134..5081ac2 100644 > --- a/drivers/video/via/accel.h > +++ b/drivers/video/via/accel.h > @@ -159,6 +159,7 @@ > > #define MAXLOOP 0xFFFFFF > > +void viafb_2d_writel(u_int32_t val, u_int32_t reg); > void viafb_init_accel(void); > void viafb_init_2d_engine(void); > void viafb_set_2d_mode(struct fb_info *info); > diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c > index af8acfe..859827b 100644 > --- a/drivers/video/via/viafbdev.c > +++ b/drivers/video/via/viafbdev.c > @@ -899,16 +899,14 @@ static void viafb_fillrect(struct fb_info *info, > viafb_set_2d_mode(info); > > /* BitBlt Destination Address */ > - writel(((rect->dy << 16) | rect->dx), > - viaparinfo->io_virt + VIA_REG_DSTPOS); > + viafb_2d_writel(((rect->dy << 16) | rect->dx), VIA_REG_DSTPOS); > /* Dimension: width & height */ > - writel((((rect->height - 1) << 16) | (rect->width - 1)), > - viaparinfo->io_virt + VIA_REG_DIMENSION); > + viafb_2d_writel((((rect->height - 1) << 16) | (rect->width - 1)), > + VIA_REG_DIMENSION); > /* Forground color or Destination color */ > - writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR); > + viafb_2d_writel(col, VIA_REG_FGCOLOR); > /* GE Command */ > - writel((0x01 | 0x2000 | (rop << 24)), > - viaparinfo->io_virt + VIA_REG_GECMD); > + viafb_2d_writel((0x01 | 0x2000 | (rop << 24)), VIA_REG_GECMD); > > } > > @@ -943,15 +941,14 @@ static void viafb_copyarea(struct fb_info *info, > viafb_set_2d_mode(info); > > /* BitBlt Source Address */ > - writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS); > + viafb_2d_writel(((sy << 16) | sx), VIA_REG_SRCPOS); > /* BitBlt Destination Address */ > - writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS); > + viafb_2d_writel(((dy << 16) | dx), VIA_REG_DSTPOS); > /* Dimension: width & height */ > - writel((((area->height - 1) << 16) | (area->width - 1)), > - viaparinfo->io_virt + VIA_REG_DIMENSION); > + viafb_2d_writel((((area->height - 1) << 16) | (area->width - 1)), > + VIA_REG_DIMENSION); > /* GE Command */ > - writel((0x01 | direction | (0xCC << 24)), > - viaparinfo->io_virt + VIA_REG_GECMD); > + viafb_2d_writel((0x01 | direction | (0xCC << 24)), VIA_REG_GECMD); > > } > > @@ -987,19 +984,18 @@ static void viafb_imageblit(struct fb_info *info, > viafb_set_2d_mode(info); > > /* BitBlt Source Address */ > - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); > + viafb_2d_writel(0x0, VIA_REG_SRCPOS); > /* BitBlt Destination Address */ > - writel(((image->dy << 16) | image->dx), > - viaparinfo->io_virt + VIA_REG_DSTPOS); > + viafb_2d_writel(((image->dy << 16) | image->dx), VIA_REG_DSTPOS); > /* Dimension: width & height */ > - writel((((image->height - 1) << 16) | (image->width - 1)), > - viaparinfo->io_virt + VIA_REG_DIMENSION); > + viafb_2d_writel((((image->height - 1) << 16) | (image->width - 1)), > + VIA_REG_DIMENSION); > /* fb color */ > - writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR); > + viafb_2d_writel(fg_col, VIA_REG_FGCOLOR); > /* bg color */ > - writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR); > + viafb_2d_writel(bg_col, VIA_REG_BGCOLOR); > /* GE Command */ > - writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD); > + viafb_2d_writel(0xCC020142, VIA_REG_GECMD); > > for (i = 0; i < size / 4; i++) { > writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE); > -- > 1.6.2.4 > > > ------------------------------------------------------------------------------ > Crystal Reports - New Free Runtime and 30 Day Trial > Check out the new simplified licensing option that enables > unlimited royalty-free distribution of the report engine > for externally facing server and web deployment. > http://p.sf.net/sfu/businessobjects > _______________________________________________ > Linux-fbdev-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel > ---------------------------------------------------------------------- Chcesz miec nawigacje GPS ? Zamow lub przedluz umowe na neostrade, a nawigacja bedzie Twoja. Kliknij na link po szczegoly! http://link.interia.pl/f219a |
From: Krzysztof H. <krz...@po...> - 2009-05-23 06:21:56
|
On Thu, 21 May 2009 04:28:49 +0800 Harald Welte <Har...@vi...> wrote: > From: Harald Welte <la...@gn...> > > There are four parts of the viafb code who initialize the bigtblit > screen base and pitch, some of them actually broken. This patch > unifies them in one function called viafb_set_2d_mode() which > replaces and enhances the old function to just set the bpp. > > Signed-off-by: Harald Welte <Har...@vi...> > --- Acked-by: Krzysztof Helt <krz...@wp...> > drivers/video/via/accel.c | 35 ++++++++++++----------- > drivers/video/via/accel.h | 2 +- > drivers/video/via/viafbdev.c | 62 +++++------------------------------------- > 3 files changed, 26 insertions(+), 73 deletions(-) > > diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c > index 45c54bf..4a1183f 100644 > --- a/drivers/video/via/accel.c > +++ b/drivers/video/via/accel.c > @@ -191,26 +191,18 @@ void viafb_init_2d_engine(void) > } > } > > - viafb_set_2d_color_depth(viaparinfo->bpp); > - > - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); > - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); > - > - writel(VIA_PITCH_ENABLE | > - (((viaparinfo->hres * > - viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres * > - viaparinfo-> > - bpp >> 3) >> 3) << 16)), > - viaparinfo->io_virt + VIA_REG_PITCH); > + viafb_set_2d_mode(viafbinfo); > } > > -void viafb_set_2d_color_depth(int bpp) > +/* Set the mode-specific parameters for the 2D acceleration, such as > + * BPP, source and destination base, as well as pitch */ > +void viafb_set_2d_mode(struct fb_info *info) > { > - u32 dwGEMode; > + u32 dwGEMode, pitch, pitch_reg, base; > > + /* Set BPP */ > dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF; > - > - switch (bpp) { > + switch (viaparinfo->bpp) { > case 16: > dwGEMode |= VIA_GEM_16bpp; > break; > @@ -221,9 +213,18 @@ void viafb_set_2d_color_depth(int bpp) > dwGEMode |= VIA_GEM_8bpp; > break; > } > - > - /* Set BPP and Pitch */ > writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE); > + > + /* Set source and destination base */ > + base = ((void *)info->screen_base - viafb_FB_MM); > + writel(base >> 3, viaparinfo->io_virt + VIA_REG_SRCBASE); > + writel(base >> 3, viaparinfo->io_virt + VIA_REG_DSTBASE); > + > + /* Set source and destination pitch (128bit aligned) */ > + pitch = (viaparinfo->hres * viaparinfo->bpp >> 3) >> 3; It is (viaparinfo->hres * viaparinfo->bpp) >> 6. > + pitch_reg = pitch | (pitch << 16); > + pitch_reg |= VIA_PITCH_ENABLE; > + writel(pitch_reg, viaparinfo->io_virt + VIA_REG_PITCH); > } > > void viafb_hw_cursor_init(void) > diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h > index 29bf854..bef3134 100644 > --- a/drivers/video/via/accel.h > +++ b/drivers/video/via/accel.h > @@ -161,7 +161,7 @@ > > void viafb_init_accel(void); > void viafb_init_2d_engine(void); > -void set_2d_color_depth(int); > +void viafb_set_2d_mode(struct fb_info *info); > void viafb_hw_cursor_init(void); > void viafb_show_hw_cursor(struct fb_info *info, int Status); int > viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp); > diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c > index 980eab8..af8acfe 100644 > --- a/drivers/video/via/viafbdev.c > +++ b/drivers/video/via/viafbdev.c > @@ -264,7 +264,7 @@ static int viafb_set_par(struct fb_info *info) > viafb_accel = info->var.accel_flags; > > if (viafb_accel) > - viafb_set_2d_color_depth(info->var.bits_per_pixel); > + viafb_set_2d_mode(info); > } > > return 0; > @@ -865,7 +865,6 @@ static void viafb_fillrect(struct fb_info *info, > const struct fb_fillrect *rect) > { > u32 col = 0, rop = 0; > - int pitch; > > if (!viafb_accel) { > cfb_fillrect(info, rect); > @@ -897,22 +896,8 @@ static void viafb_fillrect(struct fb_info *info, > break; > } > > - /* BitBlt Source Address */ > - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); > - /* Source Base Address */ > - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); > - /* Destination Base Address */ > - writel(((unsigned long) (info->screen_base) - > - (unsigned long) viafb_FB_MM) >> 3, > - viaparinfo->io_virt + VIA_REG_DSTBASE); > - /* Pitch */ > - pitch = (info->var.xres_virtual + 7) & ~7; > - writel(VIA_PITCH_ENABLE | > - (((pitch * > - info->var.bits_per_pixel >> 3) >> 3) | > - (((pitch * info-> > - var.bits_per_pixel >> 3) >> 3) << 16)), > - viaparinfo->io_virt + VIA_REG_PITCH); > + viafb_set_2d_mode(info); > + > /* BitBlt Destination Address */ > writel(((rect->dy << 16) | rect->dx), > viaparinfo->io_virt + VIA_REG_DSTPOS); > @@ -932,7 +917,6 @@ static void viafb_copyarea(struct fb_info *info, > { > u32 dy = area->dy, sy = area->sy, direction = 0x0; > u32 sx = area->sx, dx = area->dx, width = area->width; > - int pitch; > > DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n"); > > @@ -956,25 +940,8 @@ static void viafb_copyarea(struct fb_info *info, > direction |= 0x8000; > } > > - /* Source Base Address */ > - writel(((unsigned long) (info->screen_base) - > - (unsigned long) viafb_FB_MM) >> 3, > - viaparinfo->io_virt + VIA_REG_SRCBASE); > - /* Destination Base Address */ > - writel(((unsigned long) (info->screen_base) - > - (unsigned long) viafb_FB_MM) >> 3, > - viaparinfo->io_virt + VIA_REG_DSTBASE); > - /* Pitch */ > - pitch = (info->var.xres_virtual + 7) & ~7; > - /* VIA_PITCH_ENABLE can be omitted now. */ > - writel(VIA_PITCH_ENABLE | > - (((pitch * > - info->var.bits_per_pixel >> 3) >> 3) | (((pitch * > - info->var. > - bits_per_pixel > - >> 3) >> 3) > - << 16)), > - viaparinfo->io_virt + VIA_REG_PITCH); > + viafb_set_2d_mode(info); > + > /* BitBlt Source Address */ > writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS); > /* BitBlt Destination Address */ > @@ -993,7 +960,6 @@ static void viafb_imageblit(struct fb_info *info, > { > u32 size, bg_col = 0, fg_col = 0, *udata; > int i; > - int pitch; > > if (!viafb_accel) { > cfb_imageblit(info, image); > @@ -1018,22 +984,8 @@ static void viafb_imageblit(struct fb_info *info, > } > size = image->width * image->height; > > - /* Source Base Address */ > - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); > - /* Destination Base Address */ > - writel(((unsigned long) (info->screen_base) - > - (unsigned long) viafb_FB_MM) >> 3, > - viaparinfo->io_virt + VIA_REG_DSTBASE); > - /* Pitch */ > - pitch = (info->var.xres_virtual + 7) & ~7; > - writel(VIA_PITCH_ENABLE | > - (((pitch * > - info->var.bits_per_pixel >> 3) >> 3) | (((pitch * > - info->var. > - bits_per_pixel > - >> 3) >> 3) > - << 16)), > - viaparinfo->io_virt + VIA_REG_PITCH); > + viafb_set_2d_mode(info); > + > /* BitBlt Source Address */ > writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); > /* BitBlt Destination Address */ > -- > 1.6.2.4 > > > ------------------------------------------------------------------------------ > Crystal Reports - New Free Runtime and 30 Day Trial > Check out the new simplified licensing option that enables > unlimited royalty-free distribution of the report engine > for externally facing server and web deployment. > http://p.sf.net/sfu/businessobjects > _______________________________________________ > Linux-fbdev-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel > ---------------------------------------------------------------------- Chcesz miec nawigacje GPS ? Zamow lub przedluz umowe na neostrade, a nawigacja bedzie Twoja. Kliknij na link po szczegoly! http://link.interia.pl/f219a |
From: Krzysztof H. <krz...@po...> - 2009-05-23 06:20:48
|
On Thu, 21 May 2009 04:28:51 +0800 Harald Welte <Har...@vi...> wrote: > From: Harald Welte <la...@gn...> > > We don't need to unroll the register initialization routine when > initializing the 2D engine registers > > Signed-off-by: Harald Welte <Har...@vi...> > --- > drivers/video/via/accel.c | 18 +++--------------- > 1 files changed, 3 insertions(+), 15 deletions(-) > > diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c > index c3af95f..b3a414e 100644 > --- a/drivers/video/via/accel.c > +++ b/drivers/video/via/accel.c > @@ -41,23 +41,11 @@ void viafb_init_2d_engine(void) > { > u32 dwVQStartAddr, dwVQEndAddr; > u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; > + int i; > > /* init 2D engine regs to reset 2D engine */ > - writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE); > - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); > - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS); > - writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION); > - writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR); > - writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR); > - writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR); > - writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL); > - writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR); > - writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET); > - writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL); > - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); > - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); > - writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH); > - writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1); > + for (i = 0; i <= 0x40; i+= 4) > + writel(0x0, viaparinfo->io_virt + i); > Use your new viafb_2d_writel() here. > /* Init AGP and VQ regs */ > switch (viaparinfo->chip_info->gfx_chip_name) { > -- > 1.6.2.4 > > > ------------------------------------------------------------------------------ > Crystal Reports - New Free Runtime and 30 Day Trial > Check out the new simplified licensing option that enables > unlimited royalty-free distribution of the report engine > for externally facing server and web deployment. > http://p.sf.net/sfu/businessobjects > _______________________________________________ > Linux-fbdev-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel > ---------------------------------------------------------------------- Weekend w gorach za 100 PLN! Sprawdz >>> http://link.interia.pl/f218c |
From: Tony L. <to...@at...> - 2009-05-22 22:44:40
|
From: Imre Deak <imr...@no...> Based on an earlier patch by Stanley.Miao <sta...@wi...> with board-*.c changes split to avoid conflicts with other device updates. Cc: lin...@li... Signed-off-by: Stanley.Miao <sta...@wi...> Signed-off-by: Imre Deak <imr...@no...> Signed-off-by: Tony Lindgren <to...@at...> --- arch/arm/mach-omap2/board-ldp.c | 19 +++++++++++++++---- 1 files changed, 15 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index da57b0f..59ac8ed 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -77,10 +77,6 @@ static struct platform_device ldp_smsc911x_device = { }, }; -static struct platform_device *ldp_devices[] __initdata = { - &ldp_smsc911x_device, -}; - static inline void __init ldp_init_smsc911x(void) { int eth_cs; @@ -122,8 +118,18 @@ static struct omap_uart_config ldp_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; +static struct platform_device ldp_lcd_device = { + .name = "ldp_lcd", + .id = -1, +}; + +static struct omap_lcd_config ldp_lcd_config __initdata = { + .ctrl_name = "internal", +}; + static struct omap_board_config_kernel ldp_config[] __initdata = { { OMAP_TAG_UART, &ldp_uart_config }, + { OMAP_TAG_LCD, &ldp_lcd_config }, }; static struct twl4030_gpio_platform_data ldp_gpio_data = { @@ -168,6 +174,11 @@ static struct twl4030_hsmmc_info mmc[] __initdata = { {} /* Terminator */ }; +static struct platform_device *ldp_devices[] __initdata = { + &ldp_smsc911x_device, + &ldp_lcd_device, +}; + static void __init omap_ldp_init(void) { omap_i2c_init(); |
From: Thierry R. <thi...@av...> - 2009-05-22 14:28:47
|
This patch adds support for the Avionic Design Xanthos framebuffer. Signed-off-by: Thierry Reding <thi...@av...> --- drivers/video/Kconfig | 12 ++ drivers/video/Makefile | 1 + drivers/video/adxfb/Makefile | 1 + drivers/video/adxfb/adxfb.h | 118 ++++++++++++ drivers/video/adxfb/fb.c | 411 +++++++++++++++++++++++++++++++++++++++++ drivers/video/adxfb/overlay.c | 190 +++++++++++++++++++ drivers/video/adxfb/scaler.c | 231 +++++++++++++++++++++++ include/video/Kbuild | 1 + include/video/adxfb.h | 128 +++++++++++++ 9 files changed, 1093 insertions(+), 0 deletions(-) create mode 100644 drivers/video/adxfb/Makefile create mode 100644 drivers/video/adxfb/adxfb.h create mode 100644 drivers/video/adxfb/fb.c create mode 100644 drivers/video/adxfb/overlay.c create mode 100644 drivers/video/adxfb/scaler.c create mode 100644 include/video/adxfb.h diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 0048f11..49e1b69 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1663,6 +1663,18 @@ config CARMINE_DRAM_CUSTOM Use custom board timings. endchoice +config FB_ADX + tristate "Avionic Design Xanthos framebuffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Framebuffer driver for the LCD controller in Avionic Design + Xanthos boards. + + If in doubt, say N. + config FB_AU1100 bool "Au1100 LCD Driver" depends on (FB = y) && MIPS && SOC_AU1100 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index d8d0be5..4de52a5 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -125,6 +125,7 @@ obj-$(CONFIG_FB_OMAP) += omap/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ +obj-$(CONFIG_FB_ADX) += adxfb/ # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/adxfb/Makefile b/drivers/video/adxfb/Makefile new file mode 100644 index 0000000..389d65c --- /dev/null +++ b/drivers/video/adxfb/Makefile @@ -0,0 +1 @@ +obj-y += fb.o overlay.o scaler.o diff --git a/drivers/video/adxfb/adxfb.h b/drivers/video/adxfb/adxfb.h new file mode 100644 index 0000000..8238bf3 --- /dev/null +++ b/drivers/video/adxfb/adxfb.h @@ -0,0 +1,118 @@ +/* + * linux/drivers/video/adxfb/adxfb.h + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thi...@av...> + */ + +#ifndef _DRIVERS_VIDEO_ADXFB_ADXFB_H +#define _DRIVERS_VIDEO_ADXFB_ADXFB_H 1 + +#include <linux/spinlock.h> +#include <video/adxfb.h> + +/** + * struct adxfb_info - Avionic Design Xanthos framebuffer info structure + * @palette: VGA palette storage + * @io_base: memory-mapped base address for graphics controller + * @scaler_base: memory-mapped base address for scaler + * @ioctl: machine-specific I/O control handler + */ +struct adxfb_info { + u32 palette[16]; + + void __iomem *io_base; + void __iomem *scaler_base; + spinlock_t lock; + + int (*ioctl)(struct fb_info *info, unsigned int command, + unsigned long arg); +}; + +/* register definitions */ +#define ADXFB_CONTROL 0x000 +#define ADXFB_CONTROL_ENABLE (1 << 0) +#define ADXFB_CONTROL_SYNC (1 << 1) +#define ADXFB_CONTROL_DOUBLE_Y (1 << 2) +#define ADXFB_CONTROL_HALVE_X (1 << 3) +#define ADXFB_CONTROL_TRIPLE_Y (1 << 4) +#define ADXFB_CONTROL_LOCK (1 << 31) +#define ADXFB_OVERLAY_CONTROL 0x008 +#define ADXFB_OVERLAY_CONTROL_OVERLAY (1 << 0) +#define ADXFB_OVERLAY_CONTROL_ALPHA (1 << 1) +#define ADXFB_OVERLAY_START 0x010 +#define ADXFB_OVERLAY_END 0x018 +#define ADXFB_OVERLAY_PAGE0_START 0x020 +#define ADXFB_OVERLAY_PAGE0_END 0x028 +#define ADXFB_OVERLAY_PAGE0_SIZE 0x030 +#define ADXFB_OVERLAY_PAGE1_START 0x038 +#define ADXFB_OVERLAY_PAGE1_END 0x040 +#define ADXFB_OVERLAY_PAGE1_SIZE 0x048 +#define ADXFB_OVERLAY_LEVEL 0x050 +#define ADXFB_ALPHA_START 0x058 +#define ADXFB_ALPHA_END 0x060 +#define ADXFB_ALPHA_PAGE1_START 0x068 +#define ADXFB_ALPHA_PAGE1_END 0x070 +#define ADXFB_ALPHA_PAGE1_SIZE 0x078 +#define ADXFB_PAGE0_BASE 0x080 +#define ADXFB_PAGE0_FORMAT 0x088 +#define ADXFB_PAGE0_RESOLUTION 0x090 +#define ADXFB_PAGE0_RESOLUTION_BYTE 0x098 +#define ADXFB_PAGE0_SIZE 0x0a0 +#define ADXFB_PAGE1_BASE 0x0b0 +#define ADXFB_PAGE1_FORMAT 0x0b8 +#define ADXFB_PAGE1_RESOLUTION 0x0c0 +#define ADXFB_PAGE1_RESOLUTION_PHYSICAL 0x0c8 +#define ADXFB_PAGE1_RESOLUTION_VIRTUAL 0x0d0 +#define ADXFB_PAGE1_SIZE_PHYSICAL 0x0d8 +#define ADXFB_PAGE1_SIZE_VIRTUAL 0x0e0 +#define ADXFB_PAGE1_OFFSET 0x0e8 +#define ADXFB_PAGE1_SECONDARY_BASE 0x0f0 +#define ADXFB_COLOR_OFFSET 0x100 +#define ADXFB_COLOR_MUL 0x108 + +/* page format (ADXFB_PAGE0_FORMAT, ADXFB_PAGE1_FORMAT) */ +#define ADXFB_FMT_NONE 0 +#define ADXFB_FMT_GRAYSCALE_8 1 +#define ADXFB_FMT_RGB_565 2 +#define ADXFB_FMT_RGB_888 3 +#define ADXFB_FMT_RGBA_8888 4 + +/** + * adxfb_r32() - read 32-bit register + * @fb: framebuffer context + * @offset: relative register offset + */ +static inline u32 adxfb_r32(struct adxfb_info *fb, unsigned long offset) +{ + return readl(fb->io_base + offset); +} + +/** + * adxfb_w32() - write 32-bit register + * @fb: framebuffer context + * @offset: relative register offset + * @value: value to write to register + */ +static inline void adxfb_w32(struct adxfb_info *fb, unsigned long offset, + u32 value) +{ + writel(value, fb->io_base + offset); +} + +extern int adxfb_scaler_set_mode(struct fb_info *info, + struct adxfb_scaler_mode *mode); +extern int adxfb_scaler_get_mode(struct fb_info *info, + struct adxfb_scaler_mode *mode); + +extern int adxfb_overlay_enable(struct fb_info *info, unsigned long flags); +extern int adxfb_overlay_set_viewport(struct fb_info *info, + struct adxfb_viewport *viewport); + +#endif /* !_DRIVERS_VIDEO_ADXFB_ADXFB_H */ diff --git a/drivers/video/adxfb/fb.c b/drivers/video/adxfb/fb.c new file mode 100644 index 0000000..7b6f0a5 --- /dev/null +++ b/drivers/video/adxfb/fb.c @@ -0,0 +1,411 @@ +/* + * linux/drivers/video/adxfb/fb.c + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thi...@av...> + */ + +#include <linux/fb.h> +#include <linux/io.h> +#include <linux/mm.h> +#include <linux/platform_device.h> +#include <linux/uaccess.h> + +#include "adxfb.h" + +/** + * adxfb_setcolreg() - set color register + * @regno: register number to set + * @red: red color component + * @green: green color component + * @blue: blue color component + * @transp: transparency component + * @info: framebuffer context + */ +static int adxfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *info) +{ + if ((regno >= info->cmap.len) || (regno > 255)) + return 1; + +#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16) + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { + ((struct adxfb_info *)info->par)->palette[regno] = + (CNVT_TOHW(red, info->var.red.length) + << info->var.red.offset) | + (CNVT_TOHW(green, info->var.green.length) + << info->var.green.offset) | + (CNVT_TOHW(blue, info->var.blue.length) + << info->var.blue.offset) | + (CNVT_TOHW(transp, info->var.transp.length) + << info->var.transp.offset); + } + break; + + default: + dev_err(info->dev, "bad depth: %u\n", info->var.bits_per_pixel); + break; + } +#undef CNVT_TOHW + + return 0; +} + +/** + * adxfb_ioctl() - handle I/O controls + * @info: framebuffer context + * @command: I/O control code + * @arg: I/O control argument + */ +static int adxfb_ioctl(struct fb_info *info, unsigned int command, + unsigned long arg) +{ + struct adxfb_info *fb = info->par; + void __user *argp = (void __user *)arg; + struct adxfb_scaler_mode mode; + struct adxfb_viewport viewport; + int err = 0; + + switch (command) { + case ADXFB_IOCTL_SCALER_SET_MODE: + if (copy_from_user(&mode, argp, sizeof(mode))) + return -EFAULT; + + err = adxfb_scaler_set_mode(info, &mode); + if (err < 0) + return err; + + break; + + case ADXFB_IOCTL_SCALER_GET_MODE: + err = adxfb_scaler_get_mode(info, &mode); + if (err < 0) + return err; + + if (copy_to_user(argp, &mode, sizeof(mode))) + return -EFAULT; + + break; + + case ADXFB_IOCTL_OVERLAY_ENABLE: + err = adxfb_overlay_enable(info, arg); + if (err < 0) + return err; + + break; + + case ADXFB_IOCTL_OVERLAY_SET_VIEWPORT: + if (copy_from_user(&viewport, argp, sizeof(viewport))) + return -EFAULT; + + err = adxfb_overlay_set_viewport(info, &viewport); + if (err < 0) + return err; + + break; + + default: + if (fb && fb->ioctl) + return fb->ioctl(info, command, arg); + + break; + } + + return 0; +} + +/* framebuffer operations */ +static struct fb_ops adxfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = adxfb_setcolreg, + .fb_ioctl = adxfb_ioctl, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +/** + * adxfb_set_bitfield() - initialize a bitfield structure + * @bf: bitfield structure to fill + * @offset: value for offset field + * @length: value for length field + * @msb_right: value for msb_right field + */ +static void adxfb_set_bitfield(struct fb_bitfield *bf, u32 offset, u32 length, + u32 msb_right) +{ + bf->offset = offset; + bf->length = length; + bf->msb_right = msb_right; +} + +/** + * adxfb_fmt_to_mode() - convert format type to video mode parameters + * @fmt: ADXFB format type + * @mode: video mode + */ +static int adxfb_fmt_to_mode(u8 fmt, struct adxfb_mode_info *mode) +{ + switch (fmt) { + case ADXFB_FMT_GRAYSCALE_8: + /* FIXME: use correct values here */ + adxfb_set_bitfield(&mode->red, 5, 3, 0); + adxfb_set_bitfield(&mode->green, 3, 2, 0); + adxfb_set_bitfield(&mode->blue, 0, 3, 0); + mode->bpp = 8; + break; + + case ADXFB_FMT_RGB_565: + adxfb_set_bitfield(&mode->red, 11, 5, 0); + adxfb_set_bitfield(&mode->green, 5, 6, 0); + adxfb_set_bitfield(&mode->blue, 0, 5, 0); + mode->bpp = 16; + break; + + case ADXFB_FMT_RGB_888: + /* FIXME: verify that these are correct values */ + adxfb_set_bitfield(&mode->red, 16, 8, 0); + adxfb_set_bitfield(&mode->green, 8, 8, 0); + adxfb_set_bitfield(&mode->blue, 0, 8, 0); + mode->bpp = 24; + break; + + case ADXFB_FMT_RGBA_8888: + /* FIXME: verify that these are correct values */ + adxfb_set_bitfield(&mode->red, 16, 8, 0); + adxfb_set_bitfield(&mode->green, 8, 8, 0); + adxfb_set_bitfield(&mode->blue, 0, 8, 0); + mode->bpp = 32; + break; + + default: + return -EINVAL; + } + + return 0; +} + +/** + * adxfb_get_mach_mode() - obtain the current video mode + * @fb: framebuffer context + * @mode: structure to return the video mode in + */ +static int adxfb_get_mach_mode(struct adxfb_info *fb, + struct adxfb_mode_info *mode) +{ + u32 size; + u16 resx; + u16 resy; + u8 fmt; + + size = adxfb_r32(fb, ADXFB_PAGE0_RESOLUTION); + resx = (size >> 16) & 0x7ff; + resy = (size >> 0) & 0x7ff; + + fmt = adxfb_r32(fb, ADXFB_PAGE0_FORMAT) & 0xff; + + mode->xres = resx; + mode->yres = resy; + + return adxfb_fmt_to_mode(fmt, mode); +} + +/** + * adxfb_probe() - initialize the framebuffer device + * @pdev: platform device + */ +static int __init adxfb_probe(struct platform_device *pdev) +{ + struct adxfb_mach_info *mach_info = pdev->dev.platform_data; + struct adxfb_mode_info mode; + struct adxfb_info *fb; + struct fb_info *info; + struct resource *res; + int err = 0; + + info = framebuffer_alloc(sizeof(struct adxfb_info), &pdev->dev); + if (!info) { + dev_err(&pdev->dev, "failed to allocate framebuffer device\n"); + return -ENOMEM; + } + + fb = info->par; + spin_lock_init(&fb->lock); + + if (mach_info) + fb->ioctl = mach_info->ioctl; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get graphics controller I/O " + "memory resource\n"); + err = -ENXIO; + goto free; + } + + res = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!res) { + dev_err(&pdev->dev, "failed to request graphics controller " + "I/O memory region\n"); + err = -ENXIO; + goto free; + } + + fb->io_base = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!fb->io_base) { + err = -ENXIO; + goto free; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(&pdev->dev, "failed to get scaler I/O memory " + "resource\n"); + err = -ENXIO; + goto free; + } + + res = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!res) { + dev_err(&pdev->dev, "failed to request scaler I/O memory " + "region\n"); + err = -ENXIO; + goto free; + } + + fb->scaler_base = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!fb->scaler_base) { + err = -ENXIO; + goto free; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (!res) { + dev_err(&pdev->dev, "failed to get framebuffer I/O memory " + "resource\n"); + err = -ENXIO; + goto free; + } + + res = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!res) { + dev_err(&pdev->dev, "failed to request framebuffer I/O " + "memory region\n"); + err = -ENXIO; + goto free; + } + + info->screen_base = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!info->screen_base) { + err = -ENXIO; + goto free; + } + + /* TODO: add some checking for these parameters */ + memset(&mode, 0, sizeof(mode)); + adxfb_get_mach_mode(fb, &mode); + + snprintf(info->fix.id, sizeof(info->fix.id), "adxfb"); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.accel = FB_ACCEL_NONE; + info->fix.line_length = mode.xres * (mode.bpp / 8); + info->fix.smem_start = res->start; + info->fix.smem_len = res->end - res->start + 1; + + info->var.activate = FB_ACTIVATE_NOW; + info->var.vmode = FB_VMODE_NONINTERLACED; + info->var.xres = mode.xres; + info->var.yres = mode.yres; + info->var.xres_virtual = mode.xres; + info->var.yres_virtual = mode.yres; + info->var.bits_per_pixel = mode.bpp; + info->var.red = mode.red; + info->var.green = mode.green; + info->var.blue = mode.blue; + info->var.width = mode.xres; + info->var.height = mode.yres; + + info->fbops = &adxfb_ops; + info->flags = FBINFO_DEFAULT; + info->pseudo_palette = fb->palette; + + err = fb_alloc_cmap(&info->cmap, 256, 0); + if (err < 0) { + err = -ENOMEM; + goto free; + } + + err = register_framebuffer(info); + if (err < 0) { + dev_err(&pdev->dev, "failed to register framebuffer\n"); + goto cmap; + } + + dev_info(info->dev, "ADX framebuffer initialized\n"); + platform_set_drvdata(pdev, info); + return 0; + +cmap: + fb_dealloc_cmap(&info->cmap); +free: + framebuffer_release(info); + return err; +} + +/** + * adxfb_remove() - shutdown the framebuffer device + * @pdev: platform device + */ +static int adxfb_remove(struct platform_device *pdev) +{ + struct fb_info *info = platform_get_drvdata(pdev); + unregister_framebuffer(info); + return 0; +} + +/* ADXFB platform driver */ +static struct platform_driver adxfb_driver = { + .probe = adxfb_probe, + .remove = adxfb_remove, + .driver = { + .name = "adxfb", + }, +}; + +/** + * adxfb_init() - module initialization + */ +int __init adxfb_init(void) +{ + return platform_driver_register(&adxfb_driver); +} + +/** + * adxfb_exit() - module cleanup + */ +void __exit adxfb_exit(void) +{ + platform_driver_unregister(&adxfb_driver); +} + +module_init(adxfb_init); +module_exit(adxfb_exit); + +MODULE_AUTHOR("Thierry Reding <thi...@av...>"); +MODULE_DESCRIPTION("Avionic Design Xanthos framebuffer driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/adxfb/overlay.c b/drivers/video/adxfb/overlay.c new file mode 100644 index 0000000..f114a54 --- /dev/null +++ b/drivers/video/adxfb/overlay.c @@ -0,0 +1,190 @@ +/* + * linux/drivers/video/adxfb/overlay.c + * + * Copyright (C) 2008 Avionic Design Development GmbH + * Copyright (C) 2008 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thi...@av...> + */ + +#include <linux/fb.h> +#include "adxfb.h" + +/* format to bit-depth table */ +struct fmt_bpp { + u8 fmt; + int bpp; +}; + +static struct fmt_bpp formats[] = { + { ADXFB_FMT_GRAYSCALE_8, 8 }, + { ADXFB_FMT_RGB_565, 16 }, + { ADXFB_FMT_RGB_888, 24 }, + { ADXFB_FMT_RGBA_8888, 32 }, +}; + +/** + * fmt_to_bpp() - obtain the bit-depth for a given page format + * @fmt: format of which to retrieve the bit-depth + */ +static int fmt_to_bpp(u8 fmt) +{ + int bpp = 0, i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + if (fmt == formats[i].fmt) { + bpp = formats[i].bpp; + break; + } + } + + return bpp; +} + +/** + * adxfb_disable() - disable the graphics controller + * @fb: framebuffer context + */ +static inline void adxfb_disable(struct adxfb_info *fb) +{ + u32 ctrl; + + spin_lock(&fb->lock); + + ctrl = adxfb_r32(fb, ADXFB_CONTROL); + ctrl &= ~ADXFB_CONTROL_ENABLE; + ctrl |= ADXFB_CONTROL_LOCK; + adxfb_w32(fb, ADXFB_CONTROL, ctrl); + + spin_unlock(&fb->lock); +} + +/** + * adxfb_enable() - enable the graphics controller + * @fb: framebuffer context + */ +static inline void adxfb_enable(struct adxfb_info *fb) +{ + u32 ctrl; + + spin_lock(&fb->lock); + + ctrl = adxfb_r32(fb, ADXFB_CONTROL); + ctrl &= ~ADXFB_CONTROL_LOCK; + ctrl |= ADXFB_CONTROL_ENABLE; + adxfb_w32(fb, ADXFB_CONTROL, ctrl); + + spin_unlock(&fb->lock); +} + +/** + * adxfb_overlay_enable() - enable the overlay window + * @info: framebuffer context + * @flags: flags for enabling/disabling + */ +int adxfb_overlay_enable(struct fb_info *info, unsigned long flags) +{ + struct adxfb_info *fb = info->par; + u32 ctrl; + + if (!info) + return -EINVAL; + + spin_lock(&fb->lock); + + ctrl = adxfb_r32(fb, ADXFB_OVERLAY_CONTROL); + + if (flags & ADXFB_OVERLAY_ENABLE) + ctrl |= ADXFB_OVERLAY_CONTROL_OVERLAY; + else + ctrl &= ~ADXFB_OVERLAY_CONTROL_OVERLAY; + + adxfb_w32(fb, ADXFB_OVERLAY_CONTROL, ctrl); + + spin_unlock(&fb->lock); + return 0; +} + +/** + * adxfb_overlay_set_viewport() - set the region for the overlay window + * @info: framebuffer context + * @viewport: new screen region for the overlay window + */ +int adxfb_overlay_set_viewport(struct fb_info *info, + struct adxfb_viewport *viewport) +{ + struct adxfb_info *fb = info->par; + int sx, sy, dx, dy, ex, ey; + int p0dx, p0dy; + int p0ps, p1ps; + u32 size; + + if (!info || !viewport) + return -EINVAL; + + sx = viewport->x & ~0x3; + sy = viewport->y & ~0x3; + dx = viewport->width & ~0x3; + dy = viewport->height & ~0x3; + ex = sx + dx - 1; + ey = sy + dy - 1; + + size = adxfb_r32(fb, ADXFB_PAGE0_RESOLUTION); + p0dx = (size >> 16) & 0x7ff; + p0dy = (size >> 0) & 0x7ff; + + size = adxfb_r32(fb, ADXFB_PAGE0_FORMAT) & 0xff; + p0ps = fmt_to_bpp(size) / 8; + + size = adxfb_r32(fb, ADXFB_PAGE1_FORMAT) & 0xff; + p1ps = fmt_to_bpp(size) / 8; + + adxfb_disable(fb); + spin_lock(&fb->lock); + + size = (((dx + 0) & 0x7ff) << 16) | (dy & 0x7ff); + adxfb_w32(fb, ADXFB_PAGE1_RESOLUTION, size); + + /* FIXME: (dx + 4) is a hack! */ + size = ((((dx + 4) * p1ps) & 0x1fff) << 16) | (dy & 0x7ff); + adxfb_w32(fb, ADXFB_PAGE1_RESOLUTION_PHYSICAL, size); + + size = ((((p0dx + 0) * p1ps) & 0x1fff) << 16) | (p0dy & 0x7ff); + adxfb_w32(fb, ADXFB_PAGE1_RESOLUTION_VIRTUAL, size); + + adxfb_w32(fb, ADXFB_PAGE1_SIZE_PHYSICAL, dx * dy * p1ps); + adxfb_w32(fb, ADXFB_PAGE1_SIZE_VIRTUAL, p0dx * p0dy * p1ps); + + size = ((sx & 0x7ff) << 16) | (sy & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_START, size); + + size = ((ex & 0x7ff) << 16) | (ey & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_END, size); + + size = (((sx * p0ps) & 0x1fff) << 16) | (sy & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE0_START, size); + adxfb_w32(fb, ADXFB_PAGE1_OFFSET, size); + + size = (((ex * p0ps) & 0x1fff) << 16) | (ey & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE0_END, size); + + size = (((sx * p1ps) & 0x1fff) << 16) | (sy & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE1_START, size); + + size = (((ex * p1ps) & 0x1fff) << 16) | (ey & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE1_END, size); + + adxfb_w32(fb, ADXFB_OVERLAY_PAGE0_SIZE, dx * dy * p0ps); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE1_SIZE, dx * dy * p1ps); + + adxfb_w32(fb, ADXFB_OVERLAY_LEVEL, 0xff); + + spin_unlock(&fb->lock); + adxfb_enable(fb); + + return 0; +} diff --git a/drivers/video/adxfb/scaler.c b/drivers/video/adxfb/scaler.c new file mode 100644 index 0000000..96e5796 --- /dev/null +++ b/drivers/video/adxfb/scaler.c @@ -0,0 +1,231 @@ +/* + * linux/drivers/video/adxfb/fb.c + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thi...@av...> + */ + +#include <linux/fb.h> +#include "adxfb.h" + +/** + * struct scaler_mode - scaler mode values + * @uh: horizontal up scaling factor + * @dh: horizontal down scaling factor + * @uv: vertical up scaling factor + * @dv: vertical down scaling factor + * @ox: original horizontal resolution + * @oy: original vertical resolution + * @tx: target horizontal resolution + * @ty: target vertical resolution + */ +struct scaler_mode { + u16 uh, dh; + u16 uv, dv; + u16 ox, oy; + u16 tx, ty; +}; + +/* register definitions */ +#define SCALER_MODE 0x000 +#define SCALER_MODE_ENABLE_X (1 << 0) +#define SCALER_MODE_ENABLE_Y (1 << 1) +#define SCALER_MODE_BYPASS_X (1 << 2) +#define SCALER_MODE_BYPASS_Y (1 << 3) +#define SCALER_MODE_RGB_888 (1 << 4) +#define SCALER_MODE_LOWPASS (1 << 7) +#define SCALER_MODE_SYNC (1 << 8) +#define SCALER_MODE_RESET (1 << 15) +#define SCALER_MODE_LOCK (1 << 31) +#define SCALER_UH 0x008 +#define SCALER_DH 0x010 +#define SCALER_UV 0x030 +#define SCALER_DV 0x038 +#define SCALER_ORIGIN_X 0x040 +#define SCALER_ORIGIN_Y 0x048 +#define SCALER_OFFSET_X 0x050 +#define SCALER_OFFSET_Y 0x058 +#define SCALER_TARGET_X 0x060 +#define SCALER_TARGET_Y 0x068 +#define SCALER_ORIGIN_STRIDE 0x070 +#define SCALER_TARGET_STRIDE 0x078 +#define SCALER_ORIGIN_SIZE 0x080 +#define SCALER_TARGET_SIZE 0x088 +#define SCALER_PRIMARY_PRE_TARGET_ADDR 0x090 +#define SCALER_PRIMARY_TARGET_ADDR 0x098 +#define SCALER_SECONDARY_PRE_TARGET_ADDR 0x0a0 +#define SCALER_SECONDARY_TARGET_ADDR 0x0a8 + +/** + * scaler_r32() - read a 32-bit register + * @fb: framebuffer context + * @offset: relative register offset + */ +static inline u32 scaler_r32(struct adxfb_info *fb, unsigned long offset) +{ + return readl(fb->scaler_base + offset); +} + +/** + * scaler_w32() - write a 32-bit register + * @fb: framebuffer context + * @offset: relative register offset + * @value: value to write to the register + */ +static inline void scaler_w32(struct adxfb_info *fb, unsigned long offset, + u32 value) +{ + writel(value, fb->scaler_base + offset); +} + +/** + * scaler_enable() - enable the scaling unit + * @fb: framebuffer context + */ +static inline void scaler_enable(struct adxfb_info *fb) +{ + u32 mode; + + spin_lock(&fb->lock); + + mode = scaler_r32(fb, SCALER_MODE); + mode |= SCALER_MODE_ENABLE_X; + mode |= SCALER_MODE_ENABLE_Y; + mode &= ~SCALER_MODE_LOCK; + scaler_w32(fb, SCALER_MODE, mode); + + spin_unlock(&fb->lock); +} + +/** + * scaler_disable() - disable the scaling unit + * @fb: framebuffer context + */ +static inline void scaler_disable(struct adxfb_info *fb) +{ + u32 mode; + + spin_lock(&fb->lock); + + mode = scaler_r32(fb, SCALER_MODE); + mode |= SCALER_MODE_LOCK; + mode &= ~SCALER_MODE_ENABLE_Y; + mode &= ~SCALER_MODE_ENABLE_X; + scaler_w32(fb, SCALER_MODE, mode); + + spin_unlock(&fb->lock); +} + +/** + * find_mode() - match a request to the best mode that can be achieved + * @fb: framebuffer context + * @mode: requested mode + */ +static int find_mode(struct adxfb_info *fb, struct scaler_mode *mode) +{ + if (!fb || !mode) + return -EINVAL; + + if ((mode->tx == 0) || (mode->ty == 0)) + return 0; + + mode->uh = scaler_r32(fb, SCALER_UH) & 0x7ff; + mode->uh = 128; /* FIXME: don't hardcode */ + mode->uv = scaler_r32(fb, SCALER_UV) & 0x7ff; + mode->uv = 128; /* FIXME: don't hardcode */ + + mode->dh = (mode->ox * mode->uh) / mode->tx; + mode->dv = (mode->oy * mode->uv) / mode->ty; + + mode->tx = (mode->ox * mode->uh) / mode->dh; + mode->ty = (mode->oy * mode->uv) / mode->dv; + + /* TODO: check the parameters */ + + return 0; +} + +/** + * adxfb_scaler_set_mode() - set a given scaler mode + * @info: framebuffer context + * @modep: scaler mode + */ +int adxfb_scaler_set_mode(struct fb_info *info, + struct adxfb_scaler_mode *modep) +{ + struct adxfb_info *fb = info->par; + struct scaler_mode mode; + int err, bpp; + u32 ctrl; + + memset(&mode, 0, sizeof(mode)); + mode.ox = modep->origin_x; + mode.oy = modep->origin_y; + mode.tx = modep->target_x; + mode.ty = modep->target_y; + + scaler_disable(fb); + spin_lock(&fb->lock); + + err = find_mode(fb, &mode); + if (err < 0) { + spin_unlock(&fb->lock); + scaler_enable(fb); + return err; + } + + ctrl = scaler_r32(fb, SCALER_MODE); + if (ctrl & SCALER_MODE_RGB_888) + bpp = 24; + else + bpp = 16; + + scaler_w32(fb, SCALER_UH, mode.uh); + scaler_w32(fb, SCALER_DH, mode.dh); + scaler_w32(fb, SCALER_UV, mode.uv); + scaler_w32(fb, SCALER_DV, mode.dv); + + scaler_w32(fb, SCALER_OFFSET_X, 0); + scaler_w32(fb, SCALER_OFFSET_Y, 0); + + scaler_w32(fb, SCALER_ORIGIN_X, mode.ox); + scaler_w32(fb, SCALER_ORIGIN_Y, mode.oy); + scaler_w32(fb, SCALER_TARGET_X, mode.tx); + scaler_w32(fb, SCALER_TARGET_Y, mode.ty); + + scaler_w32(fb, SCALER_ORIGIN_STRIDE, mode.ox * (bpp / 8)); + scaler_w32(fb, SCALER_TARGET_STRIDE, mode.tx * (bpp / 8)); + + scaler_w32(fb, SCALER_ORIGIN_SIZE, mode.ox * mode.oy * (bpp / 8)); + scaler_w32(fb, SCALER_TARGET_SIZE, mode.tx * mode.ty * (bpp / 8)); + + spin_unlock(&fb->lock); + scaler_enable(fb); + return 0; +} + +/** + * adxfb_scaler_mode() - obtain the current scaler mode + * @info: framebuffer context + * @modep: structure to return the mode in + */ +int adxfb_scaler_get_mode(struct fb_info *info, struct adxfb_scaler_mode *modep) +{ + struct adxfb_info *fb = info->par; + + spin_lock(&fb->lock); + + modep->origin_x = scaler_r32(fb, SCALER_ORIGIN_X) & 0x7ff; + modep->origin_y = scaler_r32(fb, SCALER_ORIGIN_Y) & 0x7ff; + modep->target_x = scaler_r32(fb, SCALER_TARGET_X) & 0x7ff; + modep->target_y = scaler_r32(fb, SCALER_TARGET_Y) & 0x7ff; + + spin_unlock(&fb->lock); + return 0; +} diff --git a/include/video/Kbuild b/include/video/Kbuild index 0e406f7..72fc9b0 100644 --- a/include/video/Kbuild +++ b/include/video/Kbuild @@ -1,2 +1,3 @@ unifdef-y += sisfb.h uvesafb.h unifdef-y += edid.h +unifdef-y += adxfb.h diff --git a/include/video/adxfb.h b/include/video/adxfb.h new file mode 100644 index 0000000..e7ef6d0 --- /dev/null +++ b/include/video/adxfb.h @@ -0,0 +1,128 @@ +/* + * linux/include/video/adxfb.h + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Written by Thierry Reding <thi...@av...> + */ + +#ifndef _VIDEO_ADXFB_H +#define _VIDEO_ADXFB_H + +#include <linux/ioctl.h> +#include <linux/types.h> + +#ifdef __KERNEL__ +/* overlay control register */ +#define ADXFB_OVERLAY_CONTROL 0x008 +#define ADXFB_OVERLAY_CONTROL_OVERLAY_ENABLE (1 << 0) +#define ADXFB_OVERLAY_CONTROL_ALPHA_ENABLE (1 << 1) + +#define ADXFB_PAGE0_BASE 0x080 + +/* color correction (brightness) register */ +#define ADXFB_COLOR_BRIGHTNESS 0x100 +#define ADXFB_COLOR_BRIGHTNESS_MIN 0x00 +#define ADXFB_COLOR_BRIGHTNESS_MAX 0x7f + +/* color correction (contrast) register */ +#define ADXFB_COLOR_CONTRAST 0x108 +#define ADXFB_COLOR_CONTRAST_MIN 0x48 +#define ADXFB_COLOR_CONTRAST_MAX 0x7f + +/** + * struct adxfb_mode_info - video mode information structure + * @xres: horizontal resolution + * @yres: vertical resolution + * @bpp: pixel depth + * @red: packing for red color component + * @green: packing for green color component + * @blue: packing for blue color component + */ +struct adxfb_mode_info { + /* mode resolution */ + u_short xres; + u_short yres; + u_short bpp; + + /* color packing specification */ + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; +}; + +/** + * struct adxfb_mach_info - machine-specific information structure + * @ioctl: machine-specific I/O control handler + */ +struct adxfb_mach_info { + int (*ioctl)(struct fb_info *info, unsigned int command, + unsigned long arg); +}; +#endif /* __KERNEL__ */ + +/** + * struct adxfb_scaler_mode - scaler mode definition structure + * @origin_x: original horizontal resolution + * @origin_y: original vertical resolution + * @target_x: targetted horizontal resolution + * @target_y: targetted vertical resolution + */ +struct adxfb_scaler_mode { + /* original resolution */ + __u16 origin_x; + __u16 origin_y; + /* target resolution */ + __u16 target_x; + __u16 target_y; +}; + +/** + * struct adxfb_viewport - overlay viewport structure + * @x: horizontal start position of the overlay window + * @y: vertical start position of the overlay window + * @width: width of the overlay window + * @height: height of the overlay window + */ +struct adxfb_viewport { + /* viewport position */ + __u16 x; + __u16 y; + /* viewport resolution */ + __u16 width; + __u16 height; +}; + +/* I/O control codes */ +#define ADXFB_IOC_MAGIC 'a' + +/* set a new scaler mode */ +#define ADXFB_IOCTL_SCALER_SET_MODE \ + _IOW(ADXFB_IOC_MAGIC, 0, struct adxfb_scaler_mode) +/* obtain the current scaler mode */ +#define ADXFB_IOCTL_SCALER_GET_MODE \ + _IOR(ADXFB_IOC_MAGIC, 1, struct adxfb_scaler_mode) +/* enable/disable the overlay window */ +#define ADXFB_IOCTL_OVERLAY_ENABLE \ + _IOW(ADXFB_IOC_MAGIC, 2, unsigned long) +/* set a new region for the overlay window */ +#define ADXFB_IOCTL_OVERLAY_SET_VIEWPORT \ + _IOW(ADXFB_IOC_MAGIC, 3, struct adxfb_viewport) +/* set a new input video standard */ +#define ADXFB_IOCTL_SET_INPUT \ + _IOW(ADXFB_IOC_MAGIC, 4, unsigned long) + +/* ADXFB_IOCTL_OVERLAY_ENABLE flags */ +#define ADXFB_OVERLAY_ENABLE (1 << 0) /* enable/disable overlay */ + +/* ADXFB_IOCTL_SET_INPUT parameters */ +#define ADXFB_INPUT_PAL (0x00) /* input is PAL standard */ +#define ADXFB_INPUT_NTSC (0x01) /* input is NTSC stardard */ +#define ADXFB_INPUT_MASK (0xff) /* mask to extract input */ + +#endif /* !_VIDEO_ADXFB_H */ -- 1.6.3.1 |
From: Krzysztof H. <krz...@po...> - 2009-05-21 16:51:50
|
On Thu, 21 May 2009 04:28:39 +0800 Harald Welte <Har...@vi...> wrote: > From: Harald Welte <la...@gn...> > > This patch makes fixes a bug in viafb on x86_64 builds (e.g. for VIA Nano CPU). > You cannot make the assumption that sizeof(unsigned int) == sizeof(unsigned > long), so the parsing of the default mode (640x480) fails, leading to a > division by zero during insmod of the driver. > > Signed-off-by: Harald Welte <Har...@vi...> > --- How does this differ from the commit ee1ef82c7e6d073f881952348960bbc639687482? viafb: make it work on x86_64 Fix a bug in viafb on x86_64 builds (e.g. for VIA Nano CPU). You cannot make the assumption that sizeof(unsigned int) == sizeof(unsigned long), so the parsing of the default mode (640x480) fails, leading to a division by zero during insmod of the driver. The commit is already in the main kernel tree (2.6.30-rc6). Regards, Krzysztof > drivers/video/via/viafbdev.c | 6 +++--- > 1 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c > index e327b84..a0fec29 100644 > --- a/drivers/video/via/viafbdev.c > +++ b/drivers/video/via/viafbdev.c > @@ -2103,7 +2103,7 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) > > static int __devinit via_pci_probe(void) > { > - unsigned int default_xres, default_yres; > + unsigned long default_xres, default_yres; > char *tmpc, *tmpm; > char *tmpc_sec, *tmpm_sec; > int vmode_index; > @@ -2196,8 +2196,8 @@ static int __devinit via_pci_probe(void) > viafb_FB_MM = viaparinfo->fbmem_virt; > tmpm = viafb_mode; > tmpc = strsep(&tmpm, "x"); > - strict_strtoul(tmpc, 0, (unsigned long *)&default_xres); > - strict_strtoul(tmpm, 0, (unsigned long *)&default_yres); > + strict_strtoul(tmpc, 0, &default_xres); > + strict_strtoul(tmpm, 0, &default_yres); > > vmode_index = viafb_get_mode_index(default_xres, default_yres, 0); > DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); > -- > 1.6.2.4 > > > ------------------------------------------------------------------------------ > Crystal Reports - New Free Runtime and 30 Day Trial > Check out the new simplified licensing option that enables > unlimited royalty-free distribution of the report engine > for externally facing server and web deployment. > http://p.sf.net/sfu/businessobjects > _______________________________________________ > Linux-fbdev-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel > ---------------------------------------------------------------------- Fantastyczne nagrody do zgarniecia! Zagraj >> http://link.interia.pl/f2177 |
From: Eric M. <eri...@gm...> - 2009-05-21 14:28:25
|
Incorporated all the feedback, except for the duplicated fbi->dev with info->dev, which could be easier for some function to do dev_xxx() message output. ===========>8=========== This driver is originally written by Lennert, modified by Green to be feature complete, and ported by Jun Nie and Kevin Liu for pxa168/910 processors. The patch adds support for the on-chip LCD display controller, it currently supports the base (graphics) layer only. Signed-off-by: Lennert Buytenhek <bu...@ma...> Signed-off-by: Green Wan <gw...@ma...> Cc: Peter Liao <pl...@ma...> Signed-off-by: Jun Nie <nj...@ma...> Signed-off-by: Kevin Liu <kl...@ma...> Signed-off-by: Eric Miao <eri...@ma...> --- drivers/video/Kconfig | 10 + drivers/video/Makefile | 1 + drivers/video/pxa168fb.c | 798 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/video/pxa168fb.h | 558 ++++++++++++++++++++++++++++++++ include/video/pxa168fb.h | 128 ++++++++ 5 files changed, 1495 insertions(+), 0 deletions(-) create mode 100644 drivers/video/pxa168fb.c create mode 100644 drivers/video/pxa168fb.h create mode 100644 include/video/pxa168fb.h diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 0048f11..13fd66a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1759,6 +1759,16 @@ config FB_68328 Say Y here if you want to support the built-in frame buffer of the Motorola 68328 CPU family. +config FB_PXA168 + tristate "PXA168/910 LCD framebuffer support" + depends on FB && (CPU_PXA168 || CPU_PXA910) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Marvell + MMP processor. + config FB_PXA tristate "PXA LCD framebuffer support" depends on FB && ARCH_PXA diff --git a/drivers/video/Makefile b/drivers/video/Makefile index d8d0be5..01a819f 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -97,6 +97,7 @@ obj-$(CONFIG_FB_GBE) += gbefb.o obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o obj-$(CONFIG_FB_PXA) += pxafb.o +obj-$(CONFIG_FB_PXA168) += pxa168fb.o obj-$(CONFIG_FB_W100) += w100fb.o obj-$(CONFIG_FB_TMIO) += tmiofb.o obj-$(CONFIG_FB_AU1100) += au1100fb.o diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c new file mode 100644 index 0000000..707f20c --- /dev/null +++ b/drivers/video/pxa168fb.c @@ -0,0 +1,798 @@ +/* + * linux/drivers/video/pxa168fb.c -- Marvell PXA168 LCD Controller + * + * Copyright (C) 2008 Marvell International Ltd. + * All rights reserved. + * + * 2009-02-16 adapted from original version for PXA168/910 + * Jun Nie <nj...@ma...> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/uaccess.h> +#include <video/pxa168fb.h> + +#include "pxa168fb.h" + +#define DEFAULT_REFRESH 60 /* Hz */ + +static int determine_best_pix_fmt(struct fb_var_screeninfo *var) +{ + /* + * Pseudocolor mode? + */ + if (var->bits_per_pixel == 8) + return PIX_FMT_PSEUDOCOLOR; + + /* + * Check for 565/1555. + */ + if (var->bits_per_pixel == 16 && var->red.length <= 5 && + var->green.length <= 6 && var->blue.length <= 5) { + if (var->transp.length == 0) { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGB565; + else + return PIX_FMT_BGR565; + } + + if (var->transp.length == 1 && var->green.length <= 5) { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGB1555; + else + return PIX_FMT_BGR1555; + } + + /* fall through */ + } + + /* + * Check for 888/A888. + */ + if (var->bits_per_pixel <= 32 && var->red.length <= 8 && + var->green.length <= 8 && var->blue.length <= 8) { + if (var->bits_per_pixel == 24 && var->transp.length == 0) { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGB888PACK; + else + return PIX_FMT_BGR888PACK; + } + + if (var->bits_per_pixel == 32 && var->transp.length == 8) { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGBA888; + else + return PIX_FMT_BGRA888; + } else { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGB888UNPACK; + else + return PIX_FMT_BGR888UNPACK; + } + + /* fall through */ + } + + return -EINVAL; +} + +static void set_pix_fmt(struct fb_var_screeninfo *var, int pix_fmt) +{ + switch (pix_fmt) { + case PIX_FMT_RGB565: + var->bits_per_pixel = 16; + var->red.offset = 11; var->red.length = 5; + var->green.offset = 5; var->green.length = 6; + var->blue.offset = 0; var->blue.length = 5; + var->transp.offset = 0; var->transp.length = 0; + break; + case PIX_FMT_BGR565: + var->bits_per_pixel = 16; + 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; + case PIX_FMT_RGB1555: + var->bits_per_pixel = 16; + var->red.offset = 10; var->red.length = 5; + var->green.offset = 5; var->green.length = 5; + var->blue.offset = 0; var->blue.length = 5; + var->transp.offset = 15; var->transp.length = 1; + break; + case PIX_FMT_BGR1555: + var->bits_per_pixel = 16; + var->red.offset = 0; var->red.length = 5; + var->green.offset = 5; var->green.length = 5; + var->blue.offset = 10; var->blue.length = 5; + var->transp.offset = 15; var->transp.length = 1; + break; + case PIX_FMT_RGB888PACK: + var->bits_per_pixel = 24; + var->red.offset = 16; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + var->transp.offset = 0; var->transp.length = 0; + break; + case PIX_FMT_BGR888PACK: + var->bits_per_pixel = 24; + var->red.offset = 0; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 16; var->blue.length = 8; + var->transp.offset = 0; var->transp.length = 0; + break; + case PIX_FMT_RGBA888: + var->bits_per_pixel = 32; + var->red.offset = 16; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + var->transp.offset = 24; var->transp.length = 8; + break; + case PIX_FMT_BGRA888: + var->bits_per_pixel = 32; + var->red.offset = 0; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 16; var->blue.length = 8; + var->transp.offset = 24; var->transp.length = 8; + break; + case PIX_FMT_PSEUDOCOLOR: + var->bits_per_pixel = 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; + } +} + +static void set_mode(struct pxa168fb_info *fbi, struct fb_var_screeninfo *var, + struct fb_videomode *mode, int pix_fmt, int ystretch) +{ + set_pix_fmt(var, pix_fmt); + + var->xres = mode->xres; + var->yres = mode->yres; + var->xres_virtual = max(var->xres, var->xres_virtual); + if (ystretch) + var->yres_virtual = fbi->fb_size / + (var->xres_virtual * (var->bits_per_pixel >> 3)); + else + var->yres_virtual = max(var->yres, var->yres_virtual); + var->grayscale = 0; + var->accel_flags = FB_ACCEL_NONE; + var->pixclock = mode->pixclock; + var->left_margin = mode->left_margin; + var->right_margin = mode->right_margin; + var->upper_margin = mode->upper_margin; + var->lower_margin = mode->lower_margin; + var->hsync_len = mode->hsync_len; + var->vsync_len = mode->vsync_len; + var->sync = mode->sync; + var->vmode = FB_VMODE_NONINTERLACED; + var->rotate = FB_ROTATE_UR; +} + +static int pxa168fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + + if (var->bits_per_pixel == 8) + return -EINVAL; + /* + * Basic geometry sanity checks. + */ + if (var->xoffset + var->xres > var->xres_virtual) + return -EINVAL; + if (var->yoffset + var->yres > var->yres_virtual) + return -EINVAL; + if (var->xres + var->right_margin + + var->hsync_len + var->left_margin > 2048) + return -EINVAL; + if (var->yres + var->lower_margin + + var->vsync_len + var->upper_margin > 2048) + return -EINVAL; + + /* + * Check size of framebuffer. + */ + if (var->xres_virtual * var->yres_virtual * + (var->bits_per_pixel >> 3) > fbi->fb_size) + return -EINVAL; + + return 0; +} + +/* + * The hardware clock divider has an integer and a fractional + * stage: + * + * clk2 = clk_in / integer_divider + * clk_out = clk2 * (1 - (fractional_divider >> 12)) + * + * Calculate integer and fractional divider for given clk_in + * and clk_out. + */ +static void set_clock_divider(struct pxa168fb_info *fbi, + const struct fb_videomode *m) +{ + int divider_int; + int needed_pixclk; + u64 div_result; + u32 x = 0; + + /* + * Notice: The field pixclock is used by linux fb + * is in pixel second. E.g. struct fb_videomode & + * struct fb_var_screeninfo + */ + + /* + * Check input values. + */ + if (!m || !m->pixclock || !m->refresh) { + dev_err(fbi->dev, "Input refresh or pixclock is wrong.\n"); + return; + } + + /* + * Using PLL/AXI clock. + */ + x = 0x80000000; + + /* + * Calc divider according to refresh rate. + */ + div_result = 1000000000000ll; + do_div(div_result, m->pixclock); + needed_pixclk = (u32)div_result; + + divider_int = clk_get_rate(fbi->clk) / needed_pixclk; + + /* check whether divisor is too small. */ + if (divider_int < 2) { + dev_warn(fbi->dev, "Warning: clock source is too slow." + "Try smaller resolution\n"); + divider_int = 2; + } + + /* + * Set setting to reg. + */ + x |= divider_int; + writel(x, fbi->reg_base + LCD_CFG_SCLK_DIV); +} + +static void set_dma_control0(struct pxa168fb_info *fbi) +{ + u32 x; + + /* + * Set bit to enable graphics DMA. + */ + x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); + x |= fbi->active ? 0x00000100 : 0; + fbi->active = 0; + + /* + * If we are in a pseudo-color mode, we need to enable + * palette lookup. + */ + if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR) + x |= 0x10000000; + + /* + * Configure hardware pixel format. + */ + x &= ~(0xF << 16); + x |= (fbi->pix_fmt >> 1) << 16; + + /* + * Check red and blue pixel swap. + * 1. source data swap + * 2. panel output data swap + */ + x &= ~(1 << 12); + x |= ((fbi->pix_fmt & 1) ^ (fbi->panel_rbswap)) << 12; + + writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0); +} + +static void set_dma_control1(struct pxa168fb_info *fbi, int sync) +{ + u32 x; + + /* + * Configure default bits: vsync triggers DMA, gated clock + * enable, power save enable, configure alpha registers to + * display 100% graphics, and set pixel command. + */ + x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1); + x |= 0x2032ff81; + + /* + * We trigger DMA on the falling edge of vsync if vsync is + * active low, or on the rising edge if vsync is active high. + */ + if (!(sync & FB_SYNC_VERT_HIGH_ACT)) + x |= 0x08000000; + + writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL1); +} + +static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset) +{ + struct pxa168fb_info *fbi = info->par; + struct fb_var_screeninfo *var = &info->var; + int pixel_offset; + unsigned long addr; + + pixel_offset = (yoffset * var->xres_virtual) + xoffset; + + addr = fbi->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3)); + writel(addr, fbi->reg_base + LCD_CFG_GRA_START_ADDR0); +} + +static void set_dumb_panel_control(struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + struct pxa168fb_mach_info *mi = fbi->dev->platform_data; + u32 x; + + /* + * Preserve enable flag. + */ + x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL) & 0x00000001; + + x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28; + x |= mi->gpio_output_data << 20; + x |= mi->gpio_output_mask << 12; + x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0; + x |= mi->invert_composite_blank ? 0x00000040 : 0; + x |= (info->var.sync & FB_SYNC_COMP_HIGH_ACT) ? 0x00000020 : 0; + x |= mi->invert_pix_val_ena ? 0x00000010 : 0; + x |= (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x00000008; + x |= (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x00000004; + x |= mi->invert_pixclock ? 0x00000002 : 0; + + writel(x, fbi->reg_base + LCD_SPU_DUMB_CTRL); +} + +static void set_dumb_screen_dimensions(struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + struct fb_var_screeninfo *v = &info->var; + int x; + int y; + + x = v->xres + v->right_margin + v->hsync_len + v->left_margin; + y = v->yres + v->lower_margin + v->vsync_len + v->upper_margin; + + writel((y << 16) | x, fbi->reg_base + LCD_SPUT_V_H_TOTAL); +} + +static int pxa168fb_set_par(struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + struct fb_var_screeninfo *var = &info->var; + struct fb_videomode mode; + int pix_fmt; + u32 x; + struct pxa168fb_mach_info *mi; + + mi = fbi->dev->platform_data; + /* + * Determine which pixel format we're going to use. + */ + pix_fmt = determine_best_pix_fmt(&info->var); + if (pix_fmt < 0) + return pix_fmt; + fbi->pix_fmt = pix_fmt; + + /* + * Set additional mode info. + */ + if (pix_fmt == PIX_FMT_PSEUDOCOLOR) + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + else + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; + info->fix.ypanstep = var->yres; + + /* + * Disable panel output while we setup the display. + */ + x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); + writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL); + + /* + * Configure global panel parameters. + */ + writel((var->yres << 16) | var->xres, + fbi->reg_base + LCD_SPU_V_H_ACTIVE); + + /* + * convet var to video mode + */ + fb_var_to_videomode(&mode, &info->var); + + /* Calculate clock divisor. */ + set_clock_divider(fbi, &mode); + + /* Configure dma ctrl regs. */ + set_dma_control0(fbi); + set_dma_control1(fbi, info->var.sync); + + /* + * Configure graphics DMA parameters. + */ + set_graphics_start(info, info->var.xoffset, info->var.yoffset); + x = readl(fbi->reg_base + LCD_CFG_GRA_PITCH); + x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3); + writel(x, fbi->reg_base + LCD_CFG_GRA_PITCH); + writel((var->yres << 16) | var->xres, + fbi->reg_base + LCD_SPU_GRA_HPXL_VLN); + writel((var->yres << 16) | var->xres, + fbi->reg_base + LCD_SPU_GZM_HPXL_VLN); + + /* + * Configure dumb panel ctrl regs & timings. + */ + set_dumb_panel_control(info); + set_dumb_screen_dimensions(info); + + writel((var->left_margin << 16) | var->right_margin, + fbi->reg_base + LCD_SPU_H_PORCH); + writel((var->upper_margin << 16) | var->lower_margin, + fbi->reg_base + LCD_SPU_V_PORCH); + + /* + * Re-enable panel output. + */ + x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); + writel(x | 1, fbi->reg_base + LCD_SPU_DUMB_CTRL); + + return 0; +} + +static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) +{ + return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; +} + +static u32 to_rgb(u16 red, u16 green, u16 blue) +{ + red >>= 8; + green >>= 8; + blue >>= 8; + + return (red << 16) | (green << 8) | blue; +} + +static int +pxa168fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, + unsigned int blue, unsigned int trans, struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + u32 val; + + if (info->var.grayscale) + red = green = blue = (19595 * red + 38470 * green + + 7471 * blue) >> 16; + + if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) { + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue , &info->var.blue); + fbi->pseudo_palette[regno] = val; + } + + if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) { + val = to_rgb(red, green, blue); + writel(val, fbi->reg_base + LCD_SPU_SRAM_WRDAT); + writel(0x8300 | regno, fbi->reg_base + LCD_SPU_SRAM_CTRL); + } + + return 0; +} + +static int pxa168fb_blank(int blank, struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + + fbi->is_blanked = (blank == FB_BLANK_UNBLANK) ? 0 : 1; + set_dumb_panel_control(info); + + return 0; +} + +static int pxa168fb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + set_graphics_start(info, var->xoffset, var->yoffset); + + return 0; +} + +static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id) +{ + struct pxa168fb_info *fbi = dev_id; + u32 isr = readl(fbi->reg_base + SPU_IRQ_ISR); + + if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) { + + writel(isr & (~GRA_FRAME_IRQ0_ENA_MASK), + fbi->reg_base + SPU_IRQ_ISR); + + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static struct fb_ops pxa168fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = pxa168fb_check_var, + .fb_set_par = pxa168fb_set_par, + .fb_setcolreg = pxa168fb_setcolreg, + .fb_blank = pxa168fb_blank, + .fb_pan_display = pxa168fb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int pxa168fb_init_mode(struct fb_info *info, + struct pxa168fb_mach_info *mi) +{ + struct pxa168fb_info *fbi = info->par; + struct fb_var_screeninfo *var = &info->var; + int ret = 0; + u32 total_w, total_h, refresh; + u64 div_result; + const struct fb_videomode *m; + + /* + * Set default value + */ + refresh = DEFAULT_REFRESH; + + /* try to find best video mode. */ + m = fb_find_best_mode(&info->var, &info->modelist); + if (m) + fb_videomode_to_var(&info->var, m); + + /* Init settings. */ + var->xres_virtual = var->xres; + var->yres_virtual = fbi->fb_size / + (var->xres_virtual * (var->bits_per_pixel >> 3)); + dev_dbg(fbi->dev, "pxa168fb: find best mode: res = %dx%d\n", + var->xres, var->yres); + + /* correct pixclock. */ + total_w = var->xres + var->left_margin + var->right_margin + + var->hsync_len; + total_h = var->yres + var->upper_margin + var->lower_margin + + var->vsync_len; + + div_result = 1000000000000ll; + do_div(div_result, total_w * total_h * refresh); + var->pixclock = (u32)div_result; + + return ret; +} + +static int __init pxa168fb_probe(struct platform_device *pdev) +{ + struct pxa168fb_mach_info *mi; + struct fb_info *info = 0; + struct pxa168fb_info *fbi = 0; + struct resource *res; + struct clk *clk; + int irq, ret; + + mi = pdev->dev.platform_data; + if (mi == NULL) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } + + clk = clk_get(&pdev->dev, "LCDCLK"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "unable to get LCDCLK"); + return PTR_ERR(clk); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no IO memory defined\n"); + return -ENOENT; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no IRQ defined\n"); + return -ENOENT; + } + + info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev); + if (info == NULL) + return -ENOMEM; + + /* Initialize private data */ + fbi = info->par; + platform_set_drvdata(pdev, fbi); + fbi->clk = clk; + fbi->dev = info->dev = &pdev->dev; + fbi->panel_rbswap = mi->panel_rbswap; + fbi->is_blanked = 0; + fbi->active = mi->active; + + /* + * Initialise static fb parameters. + */ + info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | + FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; + info->node = -1; + strlcpy(info->fix.id, mi->id, 16); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.type_aux = 0; + info->fix.xpanstep = 0; + info->fix.ypanstep = 0; + info->fix.ywrapstep = 0; + info->fix.mmio_start = res->start; + info->fix.mmio_len = res->end - res->start + 1; + info->fix.accel = FB_ACCEL_NONE; + info->fbops = &pxa168fb_ops; + info->pseudo_palette = fbi->pseudo_palette; + + /* + * Map LCD controller registers. + */ + fbi->reg_base = ioremap_nocache(res->start, res->end - res->start); + if (fbi->reg_base == NULL) { + ret = -ENOMEM; + goto failed; + } + + /* + * Allocate framebuffer memory. + */ + fbi->fb_size = PAGE_ALIGN(DEFAULT_FB_SIZE); + + fbi->fb_start = dma_alloc_writecombine(fbi->dev, fbi->fb_size, + &fbi->fb_start_dma, + GFP_KERNEL); + if (fbi->fb_start == NULL) { + ret = -ENOMEM; + goto failed; + } + + info->fix.smem_start = fbi->fb_start_dma; + info->fix.smem_len = fbi->fb_size; + info->screen_base = fbi->fb_start; + info->screen_size = fbi->fb_size; + + /* + * Set video mode according to platform data. + */ + set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1); + + fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist); + + /* + * init video mode data. + */ + pxa168fb_init_mode(info, mi); + + /* + * enable controller clock + */ + clk_enable(fbi->clk); + + /* + * Fill in sane defaults. + */ + pxa168fb_set_par(info); + + /* + * Configure default register values. + */ + writel(0, fbi->reg_base + LCD_SPU_BLANKCOLOR); + writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL); + writel(0, fbi->reg_base + LCD_CFG_GRA_START_ADDR1); + writel(0, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN); + writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0); + writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1), + fbi->reg_base + LCD_SPU_SRAM_PARA1); + + /* + * Allocate color map. + */ + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + ret = -ENOMEM; + goto failed_free_clk; + } + + /* + * Register irq handler. + */ + ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED, + info->fix.id, fbi); + if (ret < 0) { + dev_err(&pdev->dev, "unable to request IRQ\n"); + ret = -ENXIO; + goto failed_free_cmap; + } + + /* + * Enable GFX interrupt + */ + writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base + SPU_IRQ_ENA); + + /* + * Register framebuffer. + */ + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret); + ret = -ENXIO; + goto failed_free_irq; + } + + return 0; + +failed_free_irq: + free_irq(irq, fbi); +failed_free_cmap: + fb_dealloc_cmap(&info->cmap); +failed_free_clk: + clk_disable(fbi->clk); + clk_put(fbi->clk); +failed: + pr_err("pxa168-fb: frame buffer device init failed\n"); + platform_set_drvdata(pdev, NULL); + fb_dealloc_cmap(&info->cmap); + + if (fbi && fbi->reg_base) { + iounmap(fbi->reg_base); + kfree(fbi); + } + + return ret; +} + +static struct platform_driver pxa168fb_driver = { + .driver = { + .name = "pxa168-fb", + .owner = THIS_MODULE, + }, + .probe = pxa168fb_probe, +}; + +static int __devinit pxa168fb_init(void) +{ + return platform_driver_register(&pxa168fb_driver); +} +module_init(pxa168fb_init); + +MODULE_AUTHOR("Lennert Buytenhek <bu...@ma...> " + "Green Wan <gw...@ma...>"); +MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h new file mode 100644 index 0000000..eee0927 --- /dev/null +++ b/drivers/video/pxa168fb.h @@ -0,0 +1,558 @@ +#ifndef __PXA168FB_H__ +#define __PXA168FB_H__ + +/* ------------< LCD register >------------ */ +/* Video Frame 0&1 start address registers */ +#define LCD_SPU_DMA_START_ADDR_Y0 0x00C0 +#define LCD_SPU_DMA_START_ADDR_U0 0x00C4 +#define LCD_SPU_DMA_START_ADDR_V0 0x00C8 +#define LCD_CFG_DMA_START_ADDR_0 0x00CC /* Cmd address */ +#define LCD_SPU_DMA_START_ADDR_Y1 0x00D0 +#define LCD_SPU_DMA_START_ADDR_U1 0x00D4 +#define LCD_SPU_DMA_START_ADDR_V1 0x00D8 +#define LCD_CFG_DMA_START_ADDR_1 0x00DC /* Cmd address */ + +/* YC & UV Pitch */ +#define LCD_SPU_DMA_PITCH_YC 0x00E0 +#define SPU_DMA_PITCH_C(c) ((c) << 16) +#define SPU_DMA_PITCH_Y(y) (y) +#define LCD_SPU_DMA_PITCH_UV 0x00E4 +#define SPU_DMA_PITCH_V(v) ((v) << 16) +#define SPU_DMA_PITCH_U(u) (u) + +/* Video Starting Point on Screen Register */ +#define LCD_SPUT_DMA_OVSA_HPXL_VLN 0x00E8 +#define CFG_DMA_OVSA_VLN(y) ((y) << 16) /* 0~0xfff */ +#define CFG_DMA_OVSA_HPXL(x) (x) /* 0~0xfff */ + +/* Video Size Register */ +#define LCD_SPU_DMA_HPXL_VLN 0x00EC +#define CFG_DMA_VLN(y) ((y) << 16) +#define CFG_DMA_HPXL(x) (x) + +/* Video Size After zooming Register */ +#define LCD_SPU_DZM_HPXL_VLN 0x00F0 +#define CFG_DZM_VLN(y) ((y) << 16) +#define CFG_DZM_HPXL(x) (x) + +/* Graphic Frame 0&1 Starting Address Register */ +#define LCD_CFG_GRA_START_ADDR0 0x00F4 +#define LCD_CFG_GRA_START_ADDR1 0x00F8 + +/* Graphic Frame Pitch */ +#define LCD_CFG_GRA_PITCH 0x00FC + +/* Graphic Starting Point on Screen Register */ +#define LCD_SPU_GRA_OVSA_HPXL_VLN 0x0100 +#define CFG_GRA_OVSA_VLN(y) ((y) << 16) +#define CFG_GRA_OVSA_HPXL(x) (x) + +/* Graphic Size Register */ +#define LCD_SPU_GRA_HPXL_VLN 0x0104 +#define CFG_GRA_VLN(y) ((y) << 16) +#define CFG_GRA_HPXL(x) (x) + +/* Graphic Size after Zooming Register */ +#define LCD_SPU_GZM_HPXL_VLN 0x0108 +#define CFG_GZM_VLN(y) ((y) << 16) +#define CFG_GZM_HPXL(x) (x) + +/* HW Cursor Starting Point on Screen Register */ +#define LCD_SPU_HWC_OVSA_HPXL_VLN 0x010C +#define CFG_HWC_OVSA_VLN(y) ((y) << 16) +#define CFG_HWC_OVSA_HPXL(x) (x) + +/* HW Cursor Size */ +#define LCD_SPU_HWC_HPXL_VLN 0x0110 +#define CFG_HWC_VLN(y) ((y) << 16) +#define CFG_HWC_HPXL(x) (x) + +/* Total Screen Size Register */ +#define LCD_SPUT_V_H_TOTAL 0x0114 +#define CFG_V_TOTAL(y) ((y) << 16) +#define CFG_H_TOTAL(x) (x) + +/* Total Screen Active Size Register */ +#define LCD_SPU_V_H_ACTIVE 0x0118 +#define CFG_V_ACTIVE(y) ((y) << 16) +#define CFG_H_ACTIVE(x) (x) + +/* Screen H&V Porch Register */ +#define LCD_SPU_H_PORCH 0x011C +#define CFG_H_BACK_PORCH(b) ((b) << 16) +#define CFG_H_FRONT_PORCH(f) (f) +#define LCD_SPU_V_PORCH 0x0120 +#define CFG_V_BACK_PORCH(b) ((b) << 16) +#define CFG_V_FRONT_PORCH(f) (f) + +/* Screen Blank Color Register */ +#define LCD_SPU_BLANKCOLOR 0x0124 +#define CFG_BLANKCOLOR_MASK 0x00FFFFFF +#define CFG_BLANKCOLOR_R_MASK 0x000000FF +#define CFG_BLANKCOLOR_G_MASK 0x0000FF00 +#define CFG_BLANKCOLOR_B_MASK 0x00FF0000 + +/* HW Cursor Color 1&2 Register */ +#define LCD_SPU_ALPHA_COLOR1 0x0128 +#define CFG_HWC_COLOR1 0x00FFFFFF +#define CFG_HWC_COLOR1_R(red) ((red) << 16) +#define CFG_HWC_COLOR1_G(green) ((green) << 8) +#define CFG_HWC_COLOR1_B(blue) (blue) +#define CFG_HWC_COLOR1_R_MASK 0x000000FF +#define CFG_HWC_COLOR1_G_MASK 0x0000FF00 +#define CFG_HWC_COLOR1_B_MASK 0x00FF0000 +#define LCD_SPU_ALPHA_COLOR2 0x012C +#define CFG_HWC_COLOR2 0x00FFFFFF +#define CFG_HWC_COLOR2_R_MASK 0x000000FF +#define CFG_HWC_COLOR2_G_MASK 0x0000FF00 +#define CFG_HWC_COLOR2_B_MASK 0x00FF0000 + +/* Video YUV Color Key Control */ +#define LCD_SPU_COLORKEY_Y 0x0130 +#define CFG_CKEY_Y2(y2) ((y2) << 24) +#define CFG_CKEY_Y2_MASK 0xFF000000 +#define CFG_CKEY_Y1(y1) ((y1) << 16) +#define CFG_CKEY_Y1_MASK 0x00FF0000 +#define CFG_CKEY_Y(y) ((y) << 8) +#define CFG_CKEY_Y_MASK 0x0000FF00 +#define CFG_ALPHA_Y(y) (y) +#define CFG_ALPHA_Y_MASK 0x000000FF +#define LCD_SPU_COLORKEY_U 0x0134 +#define CFG_CKEY_U2(u2) ((u2) << 24) +#define CFG_CKEY_U2_MASK 0xFF000000 +#define CFG_CKEY_U1(u1) ((u1) << 16) +#define CFG_CKEY_U1_MASK 0x00FF0000 +#define CFG_CKEY_U(u) ((u) << 8) +#define CFG_CKEY_U_MASK 0x0000FF00 +#define CFG_ALPHA_U(u) (u) +#define CFG_ALPHA_U_MASK 0x000000FF +#define LCD_SPU_COLORKEY_V 0x0138 +#define CFG_CKEY_V2(v2) ((v2) << 24) +#define CFG_CKEY_V2_MASK 0xFF000000 +#define CFG_CKEY_V1(v1) ((v1) << 16) +#define CFG_CKEY_V1_MASK 0x00FF0000 +#define CFG_CKEY_V(v) ((v) << 8) +#define CFG_CKEY_V_MASK 0x0000FF00 +#define CFG_ALPHA_V(v) (v) +#define CFG_ALPHA_V_MASK 0x000000FF + +/* SPI Read Data Register */ +#define LCD_SPU_SPI_RXDATA 0x0140 + +/* Smart Panel Read Data Register */ +#define LCD_SPU_ISA_RSDATA 0x0144 +#define ISA_RXDATA_16BIT_1_DATA_MASK 0x000000FF +#define ISA_RXDATA_16BIT_2_DATA_MASK 0x0000FF00 +#define ISA_RXDATA_16BIT_3_DATA_MASK 0x00FF0000 +#define ISA_RXDATA_16BIT_4_DATA_MASK 0xFF000000 +#define ISA_RXDATA_32BIT_1_DATA_MASK 0x00FFFFFF + +/* HWC SRAM Read Data Register */ +#define LCD_SPU_HWC_RDDAT 0x0158 + +/* Gamma Table SRAM Read Data Register */ +#define LCD_SPU_GAMMA_RDDAT 0x015c +#define CFG_GAMMA_RDDAT_MASK 0x000000FF + +/* Palette Table SRAM Read Data Register */ +#define LCD_SPU_PALETTE_RDDAT 0x0160 +#define CFG_PALETTE_RDDAT_MASK 0x00FFFFFF + +/* I/O Pads Input Read Only Register */ +#define LCD_SPU_IOPAD_IN 0x0178 +#define CFG_IOPAD_IN_MASK 0x0FFFFFFF + +/* Reserved Read Only Registers */ +#define LCD_CFG_RDREG5F 0x017C +#define IRE_FRAME_CNT_MASK 0x000000C0 +#define IPE_FRAME_CNT_MASK 0x00000030 +#define GRA_FRAME_CNT_MASK 0x0000000C /* Graphic */ +#define DMA_FRAME_CNT_MASK 0x00000003 /* Video */ + +/* SPI Control Register. */ +#define LCD_SPU_SPI_CTRL 0x0180 +#define CFG_SCLKCNT(div) ((div) << 24) /* 0xFF~0x2 */ +#define CFG_SCLKCNT_MASK 0xFF000000 +#define CFG_RXBITS(rx) ((rx) << 16) /* 0x1F~0x1 */ +#define CFG_RXBITS_MASK 0x00FF0000 +#define CFG_TXBITS(tx) ((tx) << 8) /* 0x1F~0x1 */ +#define CFG_TXBITS_MASK 0x0000FF00 +#define CFG_CLKINV(clk) ((clk) << 7) +#define CFG_CLKINV_MASK 0x00000080 +#define CFG_KEEPXFER(transfer) ((transfer) << 6) +#define CFG_KEEPXFER_MASK 0x00000040 +#define CFG_RXBITSTO0(rx) ((rx) << 5) +#define CFG_RXBITSTO0_MASK 0x00000020 +#define CFG_TXBITSTO0(tx) ((tx) << 4) +#define CFG_TXBITSTO0_MASK 0x00000010 +#define CFG_SPI_ENA(spi) ((spi) << 3) +#define CFG_SPI_ENA_MASK 0x00000008 +#define CFG_SPI_SEL(spi) ((spi) << 2) +#define CFG_SPI_SEL_MASK 0x00000004 +#define CFG_SPI_3W4WB(wire) ((wire) << 1) +#define CFG_SPI_3W4WB_MASK 0x00000002 +#define CFG_SPI_START(start) (start) +#define CFG_SPI_START_MASK 0x00000001 + +/* SPI Tx Data Register */ +#define LCD_SPU_SPI_TXDATA 0x0184 + +/* + 1. Smart Pannel 8-bit Bus Control Register. + 2. AHB Slave Path Data Port Register +*/ +#define LCD_SPU_SMPN_CTRL 0x0188 + +/* DMA Control 0 Register */ +#define LCD_SPU_DMA_CTRL0 0x0190 +#define CFG_NOBLENDING(nb) ((nb) << 31) +#define CFG_NOBLENDING_MASK 0x80000000 +#define CFG_GAMMA_ENA(gn) ((gn) << 30) +#define CFG_GAMMA_ENA_MASK 0x40000000 +#define CFG_CBSH_ENA(cn) ((cn) << 29) +#define CFG_CBSH_ENA_MASK 0x20000000 +#define CFG_PALETTE_ENA(pn) ((pn) << 28) +#define CFG_PALETTE_ENA_MASK 0x10000000 +#define CFG_ARBFAST_ENA(an) ((an) << 27) +#define CFG_ARBFAST_ENA_MASK 0x08000000 +#define CFG_HWC_1BITMOD(mode) ((mode) << 26) +#define CFG_HWC_1BITMOD_MASK 0x04000000 +#define CFG_HWC_1BITENA(mn) ((mn) << 25) +#define CFG_HWC_1BITENA_MASK 0x02000000 +#define CFG_HWC_ENA(cn) ((cn) << 24) +#define CFG_HWC_ENA_MASK 0x01000000 +#define CFG_DMAFORMAT(dmaformat) ((dmaformat) << 20) +#define CFG_DMAFORMAT_MASK 0x00F00000 +#define CFG_GRAFORMAT(graformat) ((graformat) << 16) +#define CFG_GRAFORMAT_MASK 0x000F0000 +/* for graphic part */ +#define CFG_GRA_FTOGGLE(toggle) ((toggle) << 15) +#define CFG_GRA_FTOGGLE_MASK 0x00008000 +#define CFG_GRA_HSMOOTH(smooth) ((smooth) << 14) +#define CFG_GRA_HSMOOTH_MASK 0x00004000 +#define CFG_GRA_TSTMODE(test) ((test) << 13) +#define CFG_GRA_TSTMODE_MASK 0x00002000 +#define CFG_GRA_SWAPRB(swap) ((swap) << 12) +#define CFG_GRA_SWAPRB_MASK 0x00001000 +#define CFG_GRA_SWAPUV(swap) ((swap) << 11) +#define CFG_GRA_SWAPUV_MASK 0x00000800 +#define CFG_GRA_SWAPYU(swap) ((swap) << 10) +#define CFG_GRA_SWAPYU_MASK 0x00000400 +#define CFG_YUV2RGB_GRA(cvrt) ((cvrt) << 9) +#define CFG_YUV2RGB_GRA_MASK 0x00000200 +#define CFG_GRA_ENA(gra) ((gra) << 8) +#define CFG_GRA_ENA_MASK 0x00000100 +/* for video part */ +#define CFG_DMA_FTOGGLE(toggle) ((toggle) << 7) +#define CFG_DMA_FTOGGLE_MASK 0x00000080 +#define CFG_DMA_HSMOOTH(smooth) ((smooth) << 6) +#define CFG_DMA_HSMOOTH_MASK 0x00000040 +#define CFG_DMA_TSTMODE(test) ((test) << 5) +#define CFG_DMA_TSTMODE_MASK 0x00000020 +#define CFG_DMA_SWAPRB(swap) ((swap) << 4) +#define CFG_DMA_SWAPRB_MASK 0x00000010 +#define CFG_DMA_SWAPUV(swap) ((swap) << 3) +#define CFG_DMA_SWAPUV_MASK 0x00000008 +#define CFG_DMA_SWAPYU(swap) ((swap) << 2) +#define CFG_DMA_SWAPYU_MASK 0x00000004 +#define CFG_DMA_SWAP_MASK 0x0000001C +#define CFG_YUV2RGB_DMA(cvrt) ((cvrt) << 1) +#define CFG_YUV2RGB_DMA_MASK 0x00000002 +#define CFG_DMA_ENA(video) (video) +#define CFG_DMA_ENA_MASK 0x00000001 + +/* DMA Control 1 Register */ +#define LCD_SPU_DMA_CTRL1 0x0194 +#define CFG_FRAME_TRIG(trig) ((trig) << 31) +#define CFG_FRAME_TRIG_MASK 0x80000000 +#define CFG_VSYNC_TRIG(trig) ((trig) << 28) +#define CFG_VSYNC_TRIG_MASK 0x70000000 +#define CFG_VSYNC_INV(inv) ((inv) << 27) +#define CFG_VSYNC_INV_MASK 0x08000000 +#define CFG_COLOR_KEY_MODE(cmode) ((cmode) << 24) +#define CFG_COLOR_KEY_MASK 0x07000000 +#define CFG_CARRY(carry) ((carry) << 23) +#define CFG_CARRY_MASK 0x00800000 +#define CFG_LNBUF_ENA(lnbuf) ((lnbuf) << 22) +#define CFG_LNBUF_ENA_MASK 0x00400000 +#define CFG_GATED_ENA(gated) ((gated) << 21) +#define CFG_GATED_ENA_MASK 0x00200000 +#define CFG_PWRDN_ENA(power) ((power) << 20) +#define CFG_PWRDN_ENA_MASK 0x00100000 +#define CFG_DSCALE(dscale) ((dscale) << 18) +#define CFG_DSCALE_MASK 0x000C0000 +#define CFG_ALPHA_MODE(amode) ((amode) << 16) +#define CFG_ALPHA_MODE_MASK 0x00030000 +#define CFG_ALPHA(alpha) ((alpha) << 8) +#define CFG_ALPHA_MASK 0x0000FF00 +#define CFG_PXLCMD(pxlcmd) (pxlcmd) +#define CFG_PXLCMD_MASK 0x000000FF + +/* SRAM Control Register */ +#define LCD_SPU_SRAM_CTRL 0x0198 +#define CFG_SRAM_INIT_WR_RD(mode) ((mode) << 14) +#define CFG_SRAM_INIT_WR_RD_MASK 0x0000C000 +#define CFG_SRAM_ADDR_LCDID(id) ((id) << 8) +#define CFG_SRAM_ADDR_LCDID_MASK 0x00000F00 +#define CFG_SRAM_ADDR(addr) (addr) +#define CFG_SRAM_ADDR_MASK 0x000000FF + +/* SRAM Write Data Register */ +#define LCD_SPU_SRAM_WRDAT 0x019C + +/* SRAM RTC/WTC Control Register */ +#define LCD_SPU_SRAM_PARA0 0x01A0 + +/* SRAM Power Down Control Register */ +#define LCD_SPU_SRAM_PARA1 0x01A4 +#define CFG_CSB_256x32(hwc) ((hwc) << 15) /* HWC */ +#define CFG_CSB_256x32_MASK 0x00008000 +#define CFG_CSB_256x24(palette) ((palette) << 14) /* Palette */ +#define CFG_CSB_256x24_MASK 0x00004000 +#define CFG_CSB_256x8(gamma) ((gamma) << 13) /* Gamma */ +#define CFG_CSB_256x8_MASK 0x00002000 +#define CFG_PDWN256x32(pdwn) ((pdwn) << 7) /* HWC */ +#define CFG_PDWN256x32_MASK 0x00000080 +#define CFG_PDWN256x24(pdwn) ((pdwn) << 6) /* Palette */ +#define CFG_PDWN256x24_MASK 0x00000040 +#define CFG_PDWN256x8(pdwn) ((pdwn) << 5) /* Gamma */ +#define CFG_PDWN256x8_MASK 0x00000020 +#define CFG_PDWN32x32(pdwn) ((pdwn) << 3) +#define CFG_PDWN32x32_MASK 0x00000008 +#define CFG_PDWN16x66(pdwn) ((pdwn) << 2) +#define CFG_PDWN16x66_MASK 0x00000004 +#define CFG_PDWN32x66(pdwn) ((pdwn) << 1) +#define CFG_PDWN32x66_MASK 0x00000002 +#define CFG_PDWN64x66(pdwn) (pdwn) +#define CFG_PDWN64x66_MASK 0x00000001 + +/* Smart or Dumb Panel Clock Divider */ +#define LCD_CFG_SCLK_DIV 0x01A8 +#define SCLK_SOURCE_SELECT(src) ((src) << 31) +#define SCLK_SOURCE_SELECT_MASK 0x80000000 +#define CLK_FRACDIV(frac) ((frac) << 16) +#define CLK_FRACDIV_MASK 0x0FFF0000 +#define CLK_INT_DIV(div) (div) +#define CLK_INT_DIV_MASK 0x0000FFFF + +/* Video Contrast Register */ +#define LCD_SPU_CONTRAST 0x01AC +#define CFG_BRIGHTNESS(bright) ((bright) << 16) +#define CFG_BRIGHTNESS_MASK 0xFFFF0000 +#define CFG_CONTRAST(contrast) (contrast) +#define CFG_CONTRAST_MASK 0x0000FFFF + +/* Video Saturation Register */ +#define LCD_SPU_SATURATION 0x01B0 +#define CFG_C_MULTS(mult) ((mult) << 16) +#define CFG_C_MULTS_MASK 0xFFFF0000 +#define CFG_SATURATION(sat) (sat) +#define CFG_SATURATION_MASK 0x0000FFFF + +/* Video Hue Adjust Register */ +#define LCD_SPU_CBSH_HUE 0x01B4 +#define CFG_SIN0(sin0) ((sin0) << 16) +#define CFG_SIN0_MASK 0xFFFF0000 +#define CFG_COS0(con0) (con0) +#define CFG_COS0_MASK 0x0000FFFF + +/* Dump LCD Panel Control Register */ +#define LCD_SPU_DUMB_CTRL 0x01B8 +#define CFG_DUMBMODE(mode) ((mode) << 28) +#define CFG_DUMBMODE_MASK 0xF0000000 +#define CFG_LCDGPIO_O(data) ((data) << 20) +#define CFG_LCDGPIO_O_MASK 0x0FF00000 +#define CFG_LCDGPIO_ENA(gpio) ((gpio) << 12) +#define CFG_LCDGPIO_ENA_MASK 0x000FF000 +#define CFG_BIAS_OUT(bias) ((bias) << 8) +#define CFG_BIAS_OUT_MASK 0x00000100 +#define CFG_REVERSE_RGB(rRGB) ((rRGB) << 7) +#define CFG_REVERSE_RGB_MASK 0x00000080 +#define CFG_INV_COMPBLANK(blank) ((blank) << 6) +#define CFG_INV_COMPBLANK_MASK 0x00000040 +#define CFG_INV_COMPSYNC(sync) ((sync) << 5) +#define CFG_INV_COMPSYNC_MASK 0x00000020 +#define CFG_INV_HENA(hena) ((hena) << 4) +#define CFG_INV_HENA_MASK 0x00000010 +#define CFG_INV_VSYNC(vsync) ((vsync) << 3) +#define CFG_INV_VSYNC_MASK 0x00000008 +#define CFG_INV_HSYNC(hsync) ((hsync) << 2) +#define CFG_INV_HSYNC_MASK 0x00000004 +#define CFG_INV_PCLK(pclk) ((pclk) << 1) +#define CFG_INV_PCLK_MASK 0x00000002 +#define CFG_DUMB_ENA(dumb) (dumb) +#define CFG_DUMB_ENA_MASK 0x00000001 + +/* LCD I/O Pads Control Register */ +#define SPU_IOPAD_CONTROL 0x01BC +#define CFG_GRA_VM_ENA(vm) ((vm) << 15) /* gfx */ +#define CFG_GRA_VM_ENA_MASK 0x00008000 +#define CFG_DMA_VM_ENA(vm) ((vm) << 13) /* video */ +#define CFG_DMA_VM_ENA_MASK 0x00002000 +#define CFG_CMD_VM_ENA(vm) ((vm) << 13) +#define CFG_CMD_VM_ENA_MASK 0x00000800 +#define CFG_CSC(csc) ((csc) << 8) /* csc */ +#define CFG_CSC_MASK 0x00000300 +#define CFG_AXICTRL(axi) ((axi) << 4) +#define CFG_AXICTRL_MASK 0x000000F0 +#define CFG_IOPADMODE(iopad) (iopad) +#define CFG_IOPADMODE_MASK 0x0000000F + +/* LCD Interrupt Control Register */ +#define SPU_IRQ_ENA 0x01C0 +#define DMA_FRAME_IRQ0_ENA(irq) ((irq) << 31) +#define DMA_FRAME_IRQ0_ENA_MASK 0x80000000 +#define DMA_FRAME_IRQ1_ENA(irq) ((irq) << 30) +#define DMA_FRAME_IRQ1_ENA_MASK 0x40000000 +#define DMA_FF_UNDERFLOW_ENA(ff) ((ff) << 29) +#define DMA_FF_UNDERFLOW_ENA_MASK 0x20000000 +#define GRA_FRAME_IRQ0_ENA(irq) ((irq) << 27) +#define GRA_FRAME_IRQ0_ENA_MASK 0x08000000 +#define GRA_FRAME_IRQ1_ENA(irq) ((irq) << 26) +#define GRA_FRAME_IRQ1_ENA_MASK 0x04000000 +#define GRA_FF_UNDERFLOW_ENA(ff) ((ff) << 25) +#define GRA_FF_UNDERFLOW_ENA_MASK 0x02000000 +#define VSYNC_IRQ_ENA(vsync_irq) ((vsync_irq) << 23) +#define VSYNC_IRQ_ENA_MASK 0x00800000 +#define DUMB_FRAMEDONE_ENA(fdone) ((fdone) << 22) +#define DUMB_FRAMEDONE_ENA_MASK 0x00400000 +#define TWC_FRAMEDONE_ENA(fdone) ((fdone) << 21) +#define TWC_FRAMEDONE_ENA_MASK 0x00200000 +#define HWC_FRAMEDONE_ENA(fdone) ((fdone) << 20) +#define HWC_FRAMEDONE_ENA_MASK 0x00100000 +#define SLV_IRQ_ENA(irq) ((irq) << 19) +#define SLV_IRQ_ENA_MASK 0x00080000 +#define SPI_IRQ_ENA(irq) ((irq) << 18) +#define SPI_IRQ_ENA_MASK 0x00040000 +#define PWRDN_IRQ_ENA(irq) ((irq) << 17) +#define PWRDN_IRQ_ENA_MASK 0x00020000 +#define ERR_IRQ_ENA(irq) ((irq) << 16) +#define ERR_IRQ_ENA_MASK 0x00010000 +#define CLEAN_SPU_IRQ_ISR(irq) (irq) +#define CLEAN_SPU_IRQ_ISR_MASK 0x0000FFFF + +/* LCD Interrupt Status Register */ +#define SPU_IRQ_ISR 0x01C4 +#define DMA_FRAME_IRQ0(irq) ((irq) << 31) +#define DMA_FRAME_IRQ0_MASK 0x80000000 +#define DMA_FRAME_IRQ1(irq) ((irq) << 30) +#define DMA_FRAME_IRQ1_MASK 0x40000000 +#define DMA_FF_UNDERFLOW(ff) ((ff) << 29) +#define DMA_FF_UNDERFLOW_MASK 0x20000000 +#define GRA_FRAME_IRQ0(irq) ((irq) << 27) +#define GRA_FRAME_IRQ0_MASK 0x08000000 +#define GRA_FRAME_IRQ1(irq) ((irq) << 26) +#define GRA_FRAME_IRQ1_MASK 0x04000000 +#define GRA_FF_UNDERFLOW(ff) ((ff) << 25) +#define GRA_FF_UNDERFLOW_MASK 0x02000000 +#define VSYNC_IRQ(vsync_irq) ((vsync_irq) << 23) +#define VSYNC_IRQ_MASK 0x00800000 +#define DUMB_FRAMEDONE(fdone) ((fdone) << 22) +#define DUMB_FRAMEDONE_MASK 0x00400000 +#define TWC_FRAMEDONE(fdone) ((fdone) << 21) +#define TWC_FRAMEDONE_MASK 0x00200000 +#define HWC_FRAMEDONE(fdone) ((fdone) << 20) +#define HWC_FRAMEDONE_MASK 0x00100000 +#define SLV_IRQ(irq) ((irq) << 19) +#define SLV_IRQ_MASK 0x00080000 +#define SPI_IRQ(irq) ((irq) << 18) +#define SPI_IRQ_MASK 0x00040000 +#define PWRDN_IRQ(irq) ((irq) << 17) +#define PWRDN_IRQ_MASK 0x00020000 +#define ERR_IRQ(irq) ((irq) << 16) +#define ERR_IRQ_MASK 0x00010000 +/* read-only */ +#define DMA_FRAME_IRQ0_LEVEL_MASK 0x00008000 +#define DMA_FRAME_IRQ1_LEVEL_MASK 0x00004000 +#define DMA_FRAME_CNT_ISR_MASK 0x00003000 +#define GRA_FRAME_IRQ0_LEVEL_MASK 0x00000800 +#define GRA_FRAME_IRQ1_LEVEL_MASK 0x00000400 +#define GRA_FRAME_CNT_ISR_MASK 0x00000300 +#define VSYNC_IRQ_LEVEL_MASK 0x00000080 +#define DUMB_FRAMEDONE_LEVEL_MASK 0x00000040 +#define TWC_FRAMEDONE_LEVEL_MASK 0x00000020 +#define HWC_FRAMEDONE_LEVEL_MASK 0x00000010 +#define SLV_FF_EMPTY_MASK 0x00000008 +#define DMA_FF_ALLEMPTY_MASK 0x00000004 +#define GRA_FF_ALLEMPTY_MASK 0x00000002 +#define PWRDN_IRQ_LEVEL_MASK 0x00000001 + + +/* + * defined Video Memory Color format for DMA control 0 register + * DMA0 bit[23:20] + */ +#define VMODE_RGB565 0x0 +#define VMODE_RGB1555 0x1 +#define VMODE_RGB888PACKED 0x2 +#define VMODE_RGB888UNPACKED 0x3 +#define VMODE_RGBA888 0x4 +#define VMODE_YUV422PACKED 0x5 +#define VMODE_YUV422PLANAR 0x6 +#define VMODE_YUV420PLANAR 0x7 +#define VMODE_SMPNCMD 0x8 +#define VMODE_PALETTE4BIT 0x9 +#define VMODE_PALETTE8BIT 0xa +#define VMODE_RESERVED 0xb + +/* + * defined Graphic Memory Color format for DMA control 0 register + * DMA0 bit[19:16] + */ +#define GMODE_RGB565 0x0 +#define GMODE_RGB1555 0x1 +#define GMODE_RGB888PACKED 0x2 +#define GMODE_RGB888UNPACKED 0x3 +#define GMODE_RGBA888 0x4 +#define GMODE_YUV422PACKED 0x5 +#define GMODE_YUV422PLANAR 0x6 +#define GMODE_YUV420PLANAR 0x7 +#define GMODE_SMPNCMD 0x8 +#define GMODE_PALETTE4BIT 0x9 +#define GMODE_PALETTE8BIT 0xa +#define GMODE_RESERVED 0xb + +/* + * define for DMA control 1 register + */ +#define DMA1_FRAME_TRIG 31 /* bit location */ +#define DMA1_VSYNC_MODE 28 +#define DMA1_VSYNC_INV 27 +#define DMA1_CKEY 24 +#define DMA1_CARRY 23 +#define DMA1_LNBUF_ENA 22 +#define DMA1_GATED_ENA 21 +#define DMA1_PWRDN_ENA 20 +#define DMA1_DSCALE 18 +#define DMA1_ALPHA_MODE 16 +#define DMA1_ALPHA 08 +#define DMA1_PXLCMD 00 + +/* + * defined for Configure Dumb Mode + * DUMB LCD Panel bit[31:28] + */ +#define DUMB16_RGB565_0 0x0 +#define DUMB16_RGB565_1 0x1 +#define DUMB18_RGB666_0 0x2 +#define DUMB18_RGB666_1 0x3 +#define DUMB12_RGB444_0 0x4 +#define DUMB12_RGB444_1 0x5 +#define DUMB24_RGB888_0 0x6 +#define DUMB_BLANK 0x7 + +/* + * defined for Configure I/O Pin Allocation Mode + * LCD LCD I/O Pads control register bit[3:0] + */ +#define IOPAD_DUMB24 0x0 +#define IOPAD_DUMB18SPI 0x1 +#define IOPAD_DUMB18GPIO 0x2 +#define IOPAD_DUMB16SPI 0x3 +#define IOPAD_DUMB16GPIO 0x4 +#define IOPAD_DUMB12 0x5 +#define IOPAD_SMART18SPI 0x6 +#define IOPAD_SMART16SPI 0x7 +#define IOPAD_SMART8BOTH 0x8 + +#endif /* __PXA168FB_H__ */ diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h new file mode 100644 index 0000000..65324e3 --- /dev/null +++ b/include/video/pxa168fb.h @@ -0,0 +1,128 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/pxa168fb.h + * + * Copyright (C) 2009 Marvell International Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_PXA168FB_H +#define __ASM_MACH_PXA168FB_H + +#include <linux/fb.h> +#include <linux/interrupt.h> + +/* Dumb interface */ +#define PIN_MODE_DUMB_24 0 +#define PIN_MODE_DUMB_18_SPI 1 +#define PIN_MODE_DUMB_18_GPIO 2 +#define PIN_MODE_DUMB_16_SPI 3 +#define PIN_MODE_DUMB_16_GPIO 4 +#define PIN_MODE_DUMB_12_SPI_GPIO 5 +#define PIN_MODE_SMART_18_SPI 6 +#define PIN_MODE_SMART_16_SPI 7 +#define PIN_MODE_SMART_8_SPI_GPIO 8 + +/* Dumb interface pin allocation */ +#define DUMB_MODE_RGB565 0 +#define DUMB_MODE_RGB565_UPPER 1 +#define DUMB_MODE_RGB666 2 +#define DUMB_MODE_RGB666_UPPER 3 +#define DUMB_MODE_RGB444 4 +#define DUMB_MODE_RGB444_UPPER 5 +#define DUMB_MODE_RGB888 6 + +/* default fb buffer size WVGA-32bits */ +#define DEFAULT_FB_SIZE (800 * 480 * 4) + +/* + * Buffer pixel format + * bit0 is for rb swap. + * bit12 is for Y UorV swap + */ +#define PIX_FMT_RGB565 0 +#define PIX_FMT_BGR565 1 +#define PIX_FMT_RGB1555 2 +#define PIX_FMT_BGR1555 3 +#define PIX_FMT_RGB888PACK 4 +#define PIX_FMT_BGR888PACK 5 +#define PIX_FMT_RGB888UNPACK 6 +#define PIX_FMT_BGR888UNPACK 7 +#define PIX_FMT_RGBA888 8 +#define PIX_FMT_BGRA888 9 +#define PIX_FMT_YUV422PACK 10 +#define PIX_FMT_YVU422PACK 11 +#define PIX_FMT_YUV422PLANAR 12 +#define PIX_FMT_YVU422PLANAR 13 +#define PIX_FMT_YUV420PLANAR 14 +#define PIX_FMT_YVU420PLANAR 15 +#define PIX_FMT_PSEUDOCOLOR 20 +#define PIX_FMT_UYVY422PACK (0x1000|PIX_FMT_YUV422PACK) + +/* + * PXA LCD controller private state. + */ +struct pxa168fb_info { + struct device *dev; + struct clk *clk; + + void __iomem *reg_base; + dma_addr_t fb_start_dma; + void *fb_start; + int fb_size; + u32 pseudo_palette[16]; + + int pix_fmt; + unsigned is_blanked:1; + unsigned panel_rbswap:1; + unsigned active:1; +}; + +/* + * PXA fb machine information + */ +struct pxa168fb_mach_info { + char id[16]; + + int num_modes; + struct fb_videomode *modes; + + /* + * Pix_fmt + */ + unsigned pix_fmt; + + /* + * I/O pin allocation. + */ + unsigned io_pin_allocation_mode:4; + + /* + * Dumb panel -- assignment of R/G/B component info to the 24 + * available external data lanes. + */ + unsigned dumb_mode:4; + unsigned panel_rgb_reverse_lanes:1; + + /* + * Dumb panel -- GPIO output data. + */ + unsigned gpio_output_mask:8; + unsigned gpio_output_data:8; + + /* + * Dumb panel -- configurable output signal polarity. + */ + unsigned invert_composite_blank:1; + unsigned invert_pix_val_ena:1; + unsigned invert_pixclock:1; + unsigned invert_vsync:1; + unsigned invert_hsync:1; + unsigned panel_rbswap:1; + unsigned active:1; + unsigned enable_lcd:1; +}; + +#endif /* __ASM_MACH_PXA168FB_H */ -- 1.6.0.4 |
From: Russell K. - A. L. <li...@ar...> - 2009-05-21 09:42:36
|
On Thu, May 21, 2009 at 05:03:33PM +0800, Eric Miao wrote: > + /* check whether divisor is too small. */ > + if (divider_int < 2) { > + printk(KERN_WARNING "Warning: clock source is too slow." > + "Try smaller resolution\n"); dev_warn() ? > +static void set_dma_control1(struct pxa168fb_info *fbi, int sync) > +{ > + u32 x; > + > + /* > + * Configure default bits: vsync triggers DMA, gated clock > + * enable, power save enable, configure alpha registers to > + * display 100% graphics, and set pixel command. > + */ > + x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1); > + x |= 0x2032ff81; > + > + /* > + * We trigger DMA on the falling edge of vsync if vsync is > + * active low, or on the rising edge if vsync is active high. > + */ > + if (!(sync & FB_SYNC_VERT_HIGH_ACT)) > + x |= 0x08000000; > + > + Unnecessary double-blank line. > +static int pxa168fb_set_par(struct fb_info *info) > +{ > + struct pxa168fb_info *fbi = info->par; > + struct fb_var_screeninfo *var = &info->var; > + const struct fb_videomode *m = 0; = NULL, not = 0, though is 'm' required... > + struct fb_videomode mode; > + int pix_fmt; > + u32 x; > + struct pxa168fb_mach_info *mi; > + > + mi = fbi->dev->platform_data; > + /* > + * Determine which pixel format we're going to use. > + */ > + pix_fmt = determine_best_pix_fmt(&info->var); > + if (pix_fmt < 0) > + return pix_fmt; > + fbi->pix_fmt = pix_fmt; > + > + /* > + * Set additional mode info. > + */ > + if (pix_fmt == PIX_FMT_PSEUDOCOLOR) > + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; > + else > + info->fix.visual = FB_VISUAL_TRUECOLOR; > + info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; > + info->fix.ypanstep = var->yres; > + > + /* > + * Disable panel output while we setup the display. > + */ > + x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); > + writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL); > + > + /* > + * Configure global panel parameters. > + */ > + writel((var->yres << 16) | var->xres, > + fbi->reg_base + LCD_SPU_V_H_ACTIVE); > + > + /* > + * convet var to video mode > + */ > + fb_var_to_videomode(&mode, &info->var); > + m = &mode; since this seems to be its only use. > +static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id) > +{ > + struct pxa168fb_info *fbi = (struct pxa168fb_info *)dev_id; Casts from void * to another pointer are never required. > + u32 isr; > + > + isr = readl(fbi->reg_base+SPU_IRQ_ISR); > + > + if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) { > + /* wake up queue. */ > + atomic_set(&fbi->w_intr, 1); w_intr seems to be a write only variable and can therefore be removed. > +static int pxa168fb_init_mode(struct fb_info *info, > + struct pxa168fb_mach_info *mi) > +{ > + struct pxa168fb_info *fbi = info->par; > + struct fb_var_screeninfo *var = &info->var; > + int ret = 0; > + u32 total_w, total_h, refresh; > + u64 div_result; > + const struct fb_videomode *m; > + > + /* > + * Set default value > + */ > + refresh = DEFAULT_REFRESH; > + > + /* > + * If has bootargs, apply it first. > + */ > + if (fbi->dft_vmode.xres && fbi->dft_vmode.yres && > + fbi->dft_vmode.refresh) { > + /* set data according bootargs */ > + var->xres = fbi->dft_vmode.xres; > + var->yres = fbi->dft_vmode.yres; > + refresh = fbi->dft_vmode.refresh; > + } > + > + /* try to find best video mode. */ > + m = fb_find_best_mode(&info->var, &info->modelist); > + if (m) > + fb_videomode_to_var(&info->var, m); > + > + /* Init settings. */ > + var->xres_virtual = var->xres; > + var->yres_virtual = fbi->fb_size / > + (var->xres_virtual * (var->bits_per_pixel >> 3)); > + printk("pxa168fb: find best mode: res = %dx%d\n", var->xres, var->yres); dev_debug() ? > +static int __init pxa168fb_probe(struct platform_device *pdev) > +{ > + struct pxa168fb_mach_info *mi; > + struct fb_info *info = 0; > + struct pxa168fb_info *fbi = 0; > + struct resource *res; > + struct clk *clk; > + int irq, ret; > + > + mi = pdev->dev.platform_data; > + if (mi == NULL) { > + dev_err(&pdev->dev, "no platform data defined\n"); > + return -EINVAL; > + } > + > + clk = clk_get(&pdev->dev, "LCDCLK"); > + if (IS_ERR(clk)) { > + dev_err(&pdev->dev, "unable to get LCDCLK"); > + return PTR_ERR(clk); > + } > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (res == NULL) { > + dev_err(&pdev->dev, "no IO memory defined\n"); > + return -ENOENT; > + } > + > + irq = platform_get_irq(pdev, 0); > + if (irq < 0) { > + dev_err(&pdev->dev, "no IRQ defined\n"); > + return -ENOENT; > + } > + > + info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev); > + if (info == NULL) > + return -ENOMEM; > + > + /* Initialize private data */ > + fbi = info->par; > + platform_set_drvdata(pdev, fbi); > + fbi->clk = clk; > + fbi->dev = &pdev->dev; This duplicates info->device. > + fbi->panel_rbswap = mi->panel_rbswap; > + fbi->is_blanked = 0; > + fbi->debug = 0; Write only variable. > + fbi->active = mi->active; > + init_waitqueue_head(&fbi->w_intr_wq); > + > + /* > + * Initialise static fb parameters. > + */ > + info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | > + FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; > + info->node = -1; > + strcpy(info->fix.id, mi->id); strlcpy() ? > + info->fix.type = FB_TYPE_PACKED_PIXELS; > + info->fix.type_aux = 0; > + info->fix.xpanstep = 0; > + info->fix.ypanstep = 0; > + info->fix.ywrapstep = 0; > + info->fix.mmio_start = res->start; > + info->fix.mmio_len = res->end - res->start + 1; > + info->fix.accel = FB_ACCEL_NONE; > + info->fbops = &pxa168fb_ops; > + info->pseudo_palette = fbi->pseudo_palette; > + > + /* > + * Map LCD controller registers. > + */ > + fbi->reg_base = ioremap_nocache(res->start, res->end - res->start); > + if (fbi->reg_base == NULL) { > + ret = -ENOMEM; > + goto failed; > + } > + > + /* > + * Allocate framebuffer memory. > + */ > + fbi->fb_size = PAGE_ALIGN(DEFAULT_FB_SIZE); > + > + fbi->fb_start = dma_alloc_writecombine(fbi->dev, fbi->fb_size, > + &fbi->fb_start_dma, > + GFP_KERNEL); > + if (fbi->fb_start == NULL) { > + ret = -ENOMEM; > + goto failed; > + } > + > + memset(fbi->fb_start, 0, fbi->fb_size); Wasn't there a patch recently removing memset after dma_alloc_* ? In any case, the buffer is already zeroed so this additional memset is not required. > + info->fix.smem_start = fbi->fb_start_dma; > + info->fix.smem_len = fbi->fb_size; > + info->screen_base = fbi->fb_start; > + info->screen_size = fbi->fb_size; > + > + /* > + * Set video mode according to platform data. > + */ > + set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1); > + > + fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist); > + > + /* > + * init video mode data. > + */ > + pxa168fb_init_mode(info, mi); > + > + /* > + * enable controller clock > + */ > + clk_enable(fbi->clk); > + > + /* > + * Fill in sane defaults. > + */ > + pxa168fb_set_par(info); > + > + /* > + * Configure default register values. > + */ > + writel(0x00000000, fbi->reg_base + LCD_SPU_BLANKCOLOR); > + writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL); > + writel(0x00000000, fbi->reg_base + LCD_CFG_GRA_START_ADDR1); > + writel(0x00000000, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN); > + writel(0x0, fbi->reg_base + LCD_SPU_SRAM_PARA0); Hmm, why 8 digits for some zeros, and only 1 digit for others? > + writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1), > + fbi->reg_base + LCD_SPU_SRAM_PARA1); > + > + /* > + * Allocate color map. > + */ > + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { > + ret = -ENOMEM; > + goto failed_free_clk; > + } > + > + /* > + * Register irq handler. > + */ > + ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED, mi->id, fbi); Why not use info->fix.id here? > diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h > new file mode 100644 > index 0000000..a43a10b > --- /dev/null > +++ b/drivers/video/pxa168fb.h > @@ -0,0 +1,558 @@ > +#ifndef __PXA168FB_H__ > +#define __PXA168FB_H__ > + > +/* ------------< LCD register >------------ */ > +/* Video Frame 0&1 start address registers */ > +#define LCD_SPU_DMA_START_ADDR_Y0 0x00C0 > +#define LCD_SPU_DMA_START_ADDR_U0 0x00C4 > +#define LCD_SPU_DMA_START_ADDR_V0 0x00C8 > +#define LCD_CFG_DMA_START_ADDR_0 0x00CC /* Cmd address */ > +#define LCD_SPU_DMA_START_ADDR_Y1 0x00D0 > +#define LCD_SPU_DMA_START_ADDR_U1 0x00D4 > +#define LCD_SPU_DMA_START_ADDR_V1 0x00D8 > +#define LCD_CFG_DMA_START_ADDR_1 0x00DC /* Cmd address */ > + > +/* YC & UV Pitch */ > +#define LCD_SPU_DMA_PITCH_YC 0x00E0 > +#define SPU_DMA_PITCH_C(c) (c<<16) Ouch. Think what happens if you do this: SPU_DMA_PITCH_C(1 + 2) It ends up as: 1 + 2 << 16 which is surely not what you want. If you do anything with macro arguments it's always a good idea to put parens around them. > diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h > new file mode 100644 > index 0000000..59c4a1b > --- /dev/null > +++ b/include/video/pxa168fb.h > @@ -0,0 +1,138 @@ > +/* > + * linux/arch/arm/mach-mmp/include/mach/pxa168fb.h > + * > + * Copyright (C) 2009 Marvell International Ltd. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#ifndef __ASM_MACH_PXA168FB_H > +#define __ASM_MACH_PXA168FB_H > + > +#include <linux/fb.h> > +#include <linux/interrupt.h> > + > +/* Dumb interface */ > +#define PIN_MODE_DUMB_24 0 > +#define PIN_MODE_DUMB_18_SPI 1 > +#define PIN_MODE_DUMB_18_GPIO 2 > +#define PIN_MODE_DUMB_16_SPI 3 > +#define PIN_MODE_DUMB_16_GPIO 4 > +#define PIN_MODE_DUMB_12_SPI_GPIO 5 > +#define PIN_MODE_SMART_18_SPI 6 > +#define PIN_MODE_SMART_16_SPI 7 > +#define PIN_MODE_SMART_8_SPI_GPIO 8 > + > +/* Dumb interface pin allocation */ > +#define DUMB_MODE_RGB565 0 > +#define DUMB_MODE_RGB565_UPPER 1 > +#define DUMB_MODE_RGB666 2 > +#define DUMB_MODE_RGB666_UPPER 3 > +#define DUMB_MODE_RGB444 4 > +#define DUMB_MODE_RGB444_UPPER 5 > +#define DUMB_MODE_RGB888 6 > + > +/* default fb buffer size WVGA-32bits */ > +#define DEFAULT_FB_SIZE (800 * 480 * 4) > + > +/* > + * Buffer pixel format > + * bit0 is for rb swap. > + * bit12 is for Y UorV swap > + */ > +#define PIX_FMT_RGB565 0 > +#define PIX_FMT_BGR565 1 > +#define PIX_FMT_RGB1555 2 > +#define PIX_FMT_BGR1555 3 > +#define PIX_FMT_RGB888PACK 4 > +#define PIX_FMT_BGR888PACK 5 > +#define PIX_FMT_RGB888UNPACK 6 > +#define PIX_FMT_BGR888UNPACK 7 > +#define PIX_FMT_RGBA888 8 > +#define PIX_FMT_BGRA888 9 > +#define PIX_FMT_YUV422PACK 10 > +#define PIX_FMT_YVU422PACK 11 > +#define PIX_FMT_YUV422PLANAR 12 > +#define PIX_FMT_YVU422PLANAR 13 > +#define PIX_FMT_YUV420PLANAR 14 > +#define PIX_FMT_YVU420PLANAR 15 > +#define PIX_FMT_PSEUDOCOLOR 20 > +#define PIX_FMT_UYVY422PACK (0x1000|PIX_FMT_YUV422PACK) > + > +/* > + * PXA LCD controller private state. > + */ > +struct pxa168fb_info { > + struct device *dev; > + struct clk *clk; > + > + void *reg_base; Should be void __iomem *, not void *. > + unsigned long new_addr; Unused. > + dma_addr_t fb_start_dma; > + void *fb_start; > + int fb_size; > + atomic_t w_intr; Write only. > + wait_queue_head_t w_intr_wq; Only initialized/woken up. Nothing sleeps on this wait queue. Is it needed? > + struct mutex access_ok; Unused. > + struct fb_videomode dft_vmode; This seems to be read only and never written. > + unsigned char *hwc_buf; Unused. > + unsigned int pseudo_palette[16]; This is supposed to be a 'u32' type. > + struct tasklet_struct tasklet; Unused. > + char *mode_option; Unused. > + > + int pix_fmt; > + unsigned is_blanked:1; > + unsigned panel_rbswap:1; > + unsigned debug:1; Write only variable. > + unsigned active:1; > +}; > + > +/* > + * PXA fb machine information > + */ > +struct pxa168fb_mach_info { > + char id[16]; > + unsigned int sclk_clock; Unused. > + > + int num_modes; > + struct fb_videomode *modes; > + > + /* > + * Pix_fmt > + */ > + unsigned pix_fmt; > + > + /* > + * I/O pin allocation. > + */ > + unsigned io_pin_allocation_mode:4; > + > + /* > + * Dumb panel -- assignment of R/G/B component info to the 24 > + * available external data lanes. > + */ > + unsigned dumb_mode:4; > + unsigned panel_rgb_reverse_lanes:1; > + > + /* > + * Dumb panel -- GPIO output data. > + */ > + unsigned gpio_output_mask:8; > + unsigned gpio_output_data:8; > + > + /* > + * Dumb panel -- configurable output signal polarity. > + */ > + unsigned invert_composite_blank:1; > + unsigned invert_pix_val_ena:1; > + unsigned invert_pixclock:1; > + unsigned invert_vsync:1; > + unsigned invert_hsync:1; > + unsigned panel_rbswap:1; > + unsigned active:1; > + unsigned enable_lcd:1; > +}; > + > +#endif /* __ASM_MACH_PXA168FB_H */ > -- > 1.6.0.4 > > > -- > Cheers > - eric > > ------------------------------------------------------------------- > List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel > FAQ: http://www.arm.linux.org.uk/mailinglists/faq.php > Etiquette: http://www.arm.linux.org.uk/mailinglists/etiquette.php |
From: Eric M. <eri...@gm...> - 2009-05-21 09:03:40
|
This driver is originally written by Lennert, modified by Green to be feature complete, and ported by Jun Nie and Kevin Liu for pxa168/910 processors. The patch adds support for the on-chip LCD display controller, it currently supports the base (graphics) layer only. Signed-off-by: Lennert Buytenhek <bu...@ma...> Signed-off-by: Green Wan <gw...@ma...> Cc: Peter Liao <pl...@ma...> Signed-off-by: Jun Nie <nj...@ma...> Signed-off-by: Kevin Liu <kl...@ma...> Signed-off-by: Eric Miao <eri...@ma...> --- drivers/video/Kconfig | 10 + drivers/video/Makefile | 1 + drivers/video/pxa168fb.c | 821 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/video/pxa168fb.h | 558 +++++++++++++++++++++++++++++++ include/video/pxa168fb.h | 138 ++++++++ 5 files changed, 1528 insertions(+), 0 deletions(-) create mode 100644 drivers/video/pxa168fb.c create mode 100644 drivers/video/pxa168fb.h create mode 100644 include/video/pxa168fb.h diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 0048f11..0991bf4 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1759,6 +1759,16 @@ config FB_68328 Say Y here if you want to support the built-in frame buffer of the Motorola 68328 CPU family. +config FB_PXA168 + tristate "PXA168 LCD framebuffer support" + depends on FB && CPU_PXA168 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Marvell + MMP processor. + config FB_PXA tristate "PXA LCD framebuffer support" depends on FB && ARCH_PXA diff --git a/drivers/video/Makefile b/drivers/video/Makefile index d8d0be5..01a819f 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -97,6 +97,7 @@ obj-$(CONFIG_FB_GBE) += gbefb.o obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o obj-$(CONFIG_FB_PXA) += pxafb.o +obj-$(CONFIG_FB_PXA168) += pxa168fb.o obj-$(CONFIG_FB_W100) += w100fb.o obj-$(CONFIG_FB_TMIO) += tmiofb.o obj-$(CONFIG_FB_AU1100) += au1100fb.o diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c new file mode 100644 index 0000000..47c8b8b --- /dev/null +++ b/drivers/video/pxa168fb.c @@ -0,0 +1,821 @@ +/* + * linux/drivers/video/pxa168fb.c -- Marvell PXA168 LCD Controller + * + * Copyright (C) 2008 Marvell International Ltd. + * All rights reserved. + * + * 2009-02-16 adapted from original version for PXA168/910 + * Jun Nie <nj...@ma...> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/uaccess.h> +#include <video/pxa168fb.h> + +#include "pxa168fb.h" + +#define DEFAULT_REFRESH 60 /* Hz */ + +static int determine_best_pix_fmt(struct fb_var_screeninfo *var) +{ + /* + * Pseudocolor mode? + */ + if (var->bits_per_pixel == 8) + return PIX_FMT_PSEUDOCOLOR; + + /* + * Check for 565/1555. + */ + if (var->bits_per_pixel == 16 && var->red.length <= 5 && + var->green.length <= 6 && var->blue.length <= 5) { + if (var->transp.length == 0) { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGB565; + else + return PIX_FMT_BGR565; + } + + if (var->transp.length == 1 && var->green.length <= 5) { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGB1555; + else + return PIX_FMT_BGR1555; + } + + /* fall through */ + } + + /* + * Check for 888/A888. + */ + if (var->bits_per_pixel <= 32 && var->red.length <= 8 && + var->green.length <= 8 && var->blue.length <= 8) { + if (var->bits_per_pixel == 24 && var->transp.length == 0) { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGB888PACK; + else + return PIX_FMT_BGR888PACK; + } + + if (var->bits_per_pixel == 32 && var->transp.length == 8) { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGBA888; + else + return PIX_FMT_BGRA888; + } else { + if (var->red.offset >= var->blue.offset) + return PIX_FMT_RGB888UNPACK; + else + return PIX_FMT_BGR888UNPACK; + } + + /* fall through */ + } + + return -EINVAL; +} + +static void set_pix_fmt(struct fb_var_screeninfo *var, int pix_fmt) +{ + switch (pix_fmt) { + case PIX_FMT_RGB565: + var->bits_per_pixel = 16; + var->red.offset = 11; var->red.length = 5; + var->green.offset = 5; var->green.length = 6; + var->blue.offset = 0; var->blue.length = 5; + var->transp.offset = 0; var->transp.length = 0; + break; + case PIX_FMT_BGR565: + var->bits_per_pixel = 16; + 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; + case PIX_FMT_RGB1555: + var->bits_per_pixel = 16; + var->red.offset = 10; var->red.length = 5; + var->green.offset = 5; var->green.length = 5; + var->blue.offset = 0; var->blue.length = 5; + var->transp.offset = 15; var->transp.length = 1; + break; + case PIX_FMT_BGR1555: + var->bits_per_pixel = 16; + var->red.offset = 0; var->red.length = 5; + var->green.offset = 5; var->green.length = 5; + var->blue.offset = 10; var->blue.length = 5; + var->transp.offset = 15; var->transp.length = 1; + break; + case PIX_FMT_RGB888PACK: + var->bits_per_pixel = 24; + var->red.offset = 16; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + var->transp.offset = 0; var->transp.length = 0; + break; + case PIX_FMT_BGR888PACK: + var->bits_per_pixel = 24; + var->red.offset = 0; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 16; var->blue.length = 8; + var->transp.offset = 0; var->transp.length = 0; + break; + case PIX_FMT_RGBA888: + var->bits_per_pixel = 32; + var->red.offset = 16; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + var->transp.offset = 24; var->transp.length = 8; + break; + case PIX_FMT_BGRA888: + var->bits_per_pixel = 32; + var->red.offset = 0; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 16; var->blue.length = 8; + var->transp.offset = 24; var->transp.length = 8; + break; + case PIX_FMT_PSEUDOCOLOR: + var->bits_per_pixel = 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; + } +} + +static void set_mode(struct pxa168fb_info *fbi, struct fb_var_screeninfo *var, + struct fb_videomode *mode, int pix_fmt, int ystretch) +{ + set_pix_fmt(var, pix_fmt); + + var->xres = mode->xres; + var->yres = mode->yres; + var->xres_virtual = max(var->xres, var->xres_virtual); + if (ystretch) + var->yres_virtual = fbi->fb_size / + (var->xres_virtual * (var->bits_per_pixel >> 3)); + else + var->yres_virtual = max(var->yres, var->yres_virtual); + var->grayscale = 0; + var->accel_flags = FB_ACCEL_NONE; + var->pixclock = mode->pixclock; + var->left_margin = mode->left_margin; + var->right_margin = mode->right_margin; + var->upper_margin = mode->upper_margin; + var->lower_margin = mode->lower_margin; + var->hsync_len = mode->hsync_len; + var->vsync_len = mode->vsync_len; + var->sync = mode->sync; + var->vmode = FB_VMODE_NONINTERLACED; + var->rotate = FB_ROTATE_UR; +} + +static int pxa168fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + + if (var->bits_per_pixel == 8) + return -EINVAL; + /* + * Basic geometry sanity checks. + */ + if (var->xoffset + var->xres > var->xres_virtual) + return -EINVAL; + if (var->yoffset + var->yres > var->yres_virtual) + return -EINVAL; + if (var->xres + var->right_margin + + var->hsync_len + var->left_margin > 2048) + return -EINVAL; + if (var->yres + var->lower_margin + + var->vsync_len + var->upper_margin > 2048) + return -EINVAL; + + /* + * Check size of framebuffer. + */ + if (var->xres_virtual * var->yres_virtual * + (var->bits_per_pixel >> 3) > fbi->fb_size) + return -EINVAL; + + return 0; +} + +/* + * The hardware clock divider has an integer and a fractional + * stage: + * + * clk2 = clk_in / integer_divider + * clk_out = clk2 * (1 - (fractional_divider >> 12)) + * + * Calculate integer and fractional divider for given clk_in + * and clk_out. + */ +static void set_clock_divider(struct pxa168fb_info *fbi, + const struct fb_videomode *m) +{ + int divider_int; + int needed_pixclk; + u64 div_result; + u32 x = 0; + + /* + * Notice: The field pixclock is used by linux fb + * is in pixel second. E.g. struct fb_videomode & + * struct fb_var_screeninfo + */ + + /* + * Check input values. + */ + if (!m || !m->pixclock || !m->refresh) { + printk(KERN_ERR "Input refresh or pixclock is wrong.\n"); + return; + } + + /* + * Using PLL/AXI clock. + */ + x = 0x80000000; + + /* + * Calc divider according to refresh rate. + */ + div_result = 1000000000000ll; + do_div(div_result, m->pixclock); + needed_pixclk = (u32)div_result; + + divider_int = clk_get_rate(fbi->clk) / needed_pixclk; + + /* check whether divisor is too small. */ + if (divider_int < 2) { + printk(KERN_WARNING "Warning: clock source is too slow." + "Try smaller resolution\n"); + divider_int = 2; + } + + /* + * Set setting to reg. + */ + x |= divider_int; + writel(x, fbi->reg_base + LCD_CFG_SCLK_DIV); +} + +static void set_dma_control0(struct pxa168fb_info *fbi) +{ + u32 x; + + /* + * Set bit to enable graphics DMA. + */ + x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); + x |= fbi->active ? 0x00000100 : 0; + fbi->active = 0; + + /* + * If we are in a pseudo-color mode, we need to enable + * palette lookup. + */ + if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR) + x |= 0x10000000; + + /* + * Configure hardware pixel format. + */ + x &= ~(0xF << 16); + x |= (fbi->pix_fmt >> 1) << 16; + + /* + * Check red and blue pixel swap. + * 1. source data swap + * 2. panel output data swap + */ + x &= ~(1 << 12); + x |= ((fbi->pix_fmt & 1) ^ (fbi->panel_rbswap)) << 12; + + writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0); +} + +static void set_dma_control1(struct pxa168fb_info *fbi, int sync) +{ + u32 x; + + /* + * Configure default bits: vsync triggers DMA, gated clock + * enable, power save enable, configure alpha registers to + * display 100% graphics, and set pixel command. + */ + x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1); + x |= 0x2032ff81; + + /* + * We trigger DMA on the falling edge of vsync if vsync is + * active low, or on the rising edge if vsync is active high. + */ + if (!(sync & FB_SYNC_VERT_HIGH_ACT)) + x |= 0x08000000; + + + writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL1); +} + +static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset) +{ + struct pxa168fb_info *fbi = info->par; + struct fb_var_screeninfo *var = &info->var; + int pixel_offset; + unsigned long addr; + + pixel_offset = (yoffset * var->xres_virtual) + xoffset; + + addr = fbi->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3)); + writel(addr, fbi->reg_base + LCD_CFG_GRA_START_ADDR0); +} + +static void set_dumb_panel_control(struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + struct pxa168fb_mach_info *mi = fbi->dev->platform_data; + u32 x; + + /* + * Preserve enable flag. + */ + x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL) & 0x00000001; + + x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28; + x |= mi->gpio_output_data << 20; + x |= mi->gpio_output_mask << 12; + x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0; + x |= mi->invert_composite_blank ? 0x00000040 : 0; + x |= (info->var.sync & FB_SYNC_COMP_HIGH_ACT) ? 0x00000020 : 0; + x |= mi->invert_pix_val_ena ? 0x00000010 : 0; + x |= (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x00000008; + x |= (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x00000004; + x |= mi->invert_pixclock ? 0x00000002 : 0; + + writel(x, fbi->reg_base + LCD_SPU_DUMB_CTRL); +} + +static void set_dumb_screen_dimensions(struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + struct fb_var_screeninfo *v = &info->var; + int x; + int y; + + x = v->xres + v->right_margin + v->hsync_len + v->left_margin; + y = v->yres + v->lower_margin + v->vsync_len + v->upper_margin; + + writel((y << 16) | x, fbi->reg_base + LCD_SPUT_V_H_TOTAL); +} + +static int pxa168fb_set_par(struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + struct fb_var_screeninfo *var = &info->var; + const struct fb_videomode *m = 0; + struct fb_videomode mode; + int pix_fmt; + u32 x; + struct pxa168fb_mach_info *mi; + + mi = fbi->dev->platform_data; + /* + * Determine which pixel format we're going to use. + */ + pix_fmt = determine_best_pix_fmt(&info->var); + if (pix_fmt < 0) + return pix_fmt; + fbi->pix_fmt = pix_fmt; + + /* + * Set additional mode info. + */ + if (pix_fmt == PIX_FMT_PSEUDOCOLOR) + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + else + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; + info->fix.ypanstep = var->yres; + + /* + * Disable panel output while we setup the display. + */ + x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); + writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL); + + /* + * Configure global panel parameters. + */ + writel((var->yres << 16) | var->xres, + fbi->reg_base + LCD_SPU_V_H_ACTIVE); + + /* + * convet var to video mode + */ + fb_var_to_videomode(&mode, &info->var); + m = &mode; + + /* Calculate clock divisor. */ + set_clock_divider(fbi, &mode); + + /* Configure dma ctrl regs. */ + set_dma_control0(fbi); + set_dma_control1(fbi, info->var.sync); + + /* + * Configure graphics DMA parameters. + */ + set_graphics_start(info, info->var.xoffset, info->var.yoffset); + x = readl(fbi->reg_base + LCD_CFG_GRA_PITCH); + x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3); + writel(x, fbi->reg_base + LCD_CFG_GRA_PITCH); + writel((var->yres << 16) | var->xres, + fbi->reg_base + LCD_SPU_GRA_HPXL_VLN); + writel((var->yres << 16) | var->xres, + fbi->reg_base + LCD_SPU_GZM_HPXL_VLN); + + /* + * Configure dumb panel ctrl regs & timings. + */ + set_dumb_panel_control(info); + set_dumb_screen_dimensions(info); + + writel((var->left_margin << 16) | var->right_margin, + fbi->reg_base + LCD_SPU_H_PORCH); + writel((var->upper_margin << 16) | var->lower_margin, + fbi->reg_base + LCD_SPU_V_PORCH); + + /* + * Re-enable panel output. + */ + x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); + writel(x | 1, fbi->reg_base + LCD_SPU_DUMB_CTRL); + + return 0; +} + +static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) +{ + return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; +} + +static u32 to_rgb(u16 red, u16 green, u16 blue) +{ + red >>= 8; + green >>= 8; + blue >>= 8; + + return (red << 16) | (green << 8) | blue; +} + +static int +pxa168fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, + unsigned int blue, unsigned int trans, struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + u32 val; + +#if 0 + if (info->var.grayscale) + red = green = blue = (19595 * red + 38470 * green + + 7471 * blue) >> 16; +#endif + + if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) { + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue , &info->var.blue); + fbi->pseudo_palette[regno] = val; + } + + if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) { + val = to_rgb(red, green, blue); + writel(val, fbi->reg_base + LCD_SPU_SRAM_WRDAT); + writel(0x8300 | regno, fbi->reg_base + LCD_SPU_SRAM_CTRL); + } + + return 0; +} + +static int pxa168fb_blank(int blank, struct fb_info *info) +{ + struct pxa168fb_info *fbi = info->par; + + fbi->is_blanked = (blank == FB_BLANK_UNBLANK) ? 0 : 1; + set_dumb_panel_control(info); + + return 0; +} + +static int pxa168fb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + set_graphics_start(info, var->xoffset, var->yoffset); + + return 0; +} + +static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id) +{ + struct pxa168fb_info *fbi = (struct pxa168fb_info *)dev_id; + u32 isr; + + isr = readl(fbi->reg_base+SPU_IRQ_ISR); + + if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) { + /* wake up queue. */ + atomic_set(&fbi->w_intr, 1); + wake_up(&fbi->w_intr_wq); + + writel(isr & (~GRA_FRAME_IRQ0_ENA_MASK), + fbi->reg_base+SPU_IRQ_ISR); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static struct fb_ops pxa168fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = pxa168fb_check_var, + .fb_set_par = pxa168fb_set_par, + .fb_setcolreg = pxa168fb_setcolreg, + .fb_blank = pxa168fb_blank, + .fb_pan_display = pxa168fb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int pxa168fb_init_mode(struct fb_info *info, + struct pxa168fb_mach_info *mi) +{ + struct pxa168fb_info *fbi = info->par; + struct fb_var_screeninfo *var = &info->var; + int ret = 0; + u32 total_w, total_h, refresh; + u64 div_result; + const struct fb_videomode *m; + + /* + * Set default value + */ + refresh = DEFAULT_REFRESH; + + /* + * If has bootargs, apply it first. + */ + if (fbi->dft_vmode.xres && fbi->dft_vmode.yres && + fbi->dft_vmode.refresh) { + /* set data according bootargs */ + var->xres = fbi->dft_vmode.xres; + var->yres = fbi->dft_vmode.yres; + refresh = fbi->dft_vmode.refresh; + } + + /* try to find best video mode. */ + m = fb_find_best_mode(&info->var, &info->modelist); + if (m) + fb_videomode_to_var(&info->var, m); + + /* Init settings. */ + var->xres_virtual = var->xres; + var->yres_virtual = fbi->fb_size / + (var->xres_virtual * (var->bits_per_pixel >> 3)); + printk("pxa168fb: find best mode: res = %dx%d\n", var->xres, var->yres); + + /* correct pixclock. */ + total_w = var->xres + var->left_margin + var->right_margin + + var->hsync_len; + total_h = var->yres + var->upper_margin + var->lower_margin + + var->vsync_len; + + div_result = 1000000000000ll; + do_div(div_result, total_w * total_h * refresh); + var->pixclock = (u32)div_result; + + return ret; +} + +static int __init pxa168fb_probe(struct platform_device *pdev) +{ + struct pxa168fb_mach_info *mi; + struct fb_info *info = 0; + struct pxa168fb_info *fbi = 0; + struct resource *res; + struct clk *clk; + int irq, ret; + + mi = pdev->dev.platform_data; + if (mi == NULL) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } + + clk = clk_get(&pdev->dev, "LCDCLK"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "unable to get LCDCLK"); + return PTR_ERR(clk); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no IO memory defined\n"); + return -ENOENT; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no IRQ defined\n"); + return -ENOENT; + } + + info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev); + if (info == NULL) + return -ENOMEM; + + /* Initialize private data */ + fbi = info->par; + platform_set_drvdata(pdev, fbi); + fbi->clk = clk; + fbi->dev = &pdev->dev; + fbi->panel_rbswap = mi->panel_rbswap; + fbi->is_blanked = 0; + fbi->debug = 0; + fbi->active = mi->active; + init_waitqueue_head(&fbi->w_intr_wq); + + /* + * Initialise static fb parameters. + */ + info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | + FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; + info->node = -1; + strcpy(info->fix.id, mi->id); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.type_aux = 0; + info->fix.xpanstep = 0; + info->fix.ypanstep = 0; + info->fix.ywrapstep = 0; + info->fix.mmio_start = res->start; + info->fix.mmio_len = res->end - res->start + 1; + info->fix.accel = FB_ACCEL_NONE; + info->fbops = &pxa168fb_ops; + info->pseudo_palette = fbi->pseudo_palette; + + /* + * Map LCD controller registers. + */ + fbi->reg_base = ioremap_nocache(res->start, res->end - res->start); + if (fbi->reg_base == NULL) { + ret = -ENOMEM; + goto failed; + } + + /* + * Allocate framebuffer memory. + */ + fbi->fb_size = PAGE_ALIGN(DEFAULT_FB_SIZE); + + fbi->fb_start = dma_alloc_writecombine(fbi->dev, fbi->fb_size, + &fbi->fb_start_dma, + GFP_KERNEL); + if (fbi->fb_start == NULL) { + ret = -ENOMEM; + goto failed; + } + + memset(fbi->fb_start, 0, fbi->fb_size); + info->fix.smem_start = fbi->fb_start_dma; + info->fix.smem_len = fbi->fb_size; + info->screen_base = fbi->fb_start; + info->screen_size = fbi->fb_size; + + /* + * Set video mode according to platform data. + */ + set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1); + + fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist); + + /* + * init video mode data. + */ + pxa168fb_init_mode(info, mi); + + /* + * enable controller clock + */ + clk_enable(fbi->clk); + + /* + * Fill in sane defaults. + */ + pxa168fb_set_par(info); + + /* + * Configure default register values. + */ + writel(0x00000000, fbi->reg_base + LCD_SPU_BLANKCOLOR); + writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL); + writel(0x00000000, fbi->reg_base + LCD_CFG_GRA_START_ADDR1); + writel(0x00000000, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN); + writel(0x0, fbi->reg_base + LCD_SPU_SRAM_PARA0); + writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1), + fbi->reg_base + LCD_SPU_SRAM_PARA1); + + /* + * Allocate color map. + */ + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + ret = -ENOMEM; + goto failed_free_clk; + } + + /* + * Register irq handler. + */ + ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED, mi->id, fbi); + if (ret < 0) { + dev_err(&pdev->dev, "unable to request IRQ\n"); + ret = -ENXIO; + goto failed_free_cmap; + } + + /* + * Enable GFX interrupt + */ + writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base+SPU_IRQ_ENA); + + /* + * Register framebuffer. + */ + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret); + ret = -ENXIO; + goto failed_free_irq; + } + + return 0; + +failed_free_irq: + free_irq(irq, fbi); +failed_free_cmap: + fb_dealloc_cmap(&info->cmap); +failed_free_clk: + clk_disable(fbi->clk); + clk_put(fbi->clk); +failed: + pr_err("pxa168-fb: frame buffer device init failed\n"); + platform_set_drvdata(pdev, NULL); + fb_dealloc_cmap(&info->cmap); + + if (fbi && fbi->reg_base) { + iounmap(fbi->reg_base); + kfree(fbi); + } + + return ret; +} + +static struct platform_driver pxa168fb_driver = { + .driver = { + .name = "pxa168-fb", + .owner = THIS_MODULE, + }, + .probe = pxa168fb_probe, +}; + +static int __devinit pxa168fb_init(void) +{ + return platform_driver_register(&pxa168fb_driver); +} +module_init(pxa168fb_init); + +MODULE_AUTHOR("Lennert Buytenhek <bu...@ma...> " + "Green Wan <gw...@ma...>"); +MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h new file mode 100644 index 0000000..a43a10b --- /dev/null +++ b/drivers/video/pxa168fb.h @@ -0,0 +1,558 @@ +#ifndef __PXA168FB_H__ +#define __PXA168FB_H__ + +/* ------------< LCD register >------------ */ +/* Video Frame 0&1 start address registers */ +#define LCD_SPU_DMA_START_ADDR_Y0 0x00C0 +#define LCD_SPU_DMA_START_ADDR_U0 0x00C4 +#define LCD_SPU_DMA_START_ADDR_V0 0x00C8 +#define LCD_CFG_DMA_START_ADDR_0 0x00CC /* Cmd address */ +#define LCD_SPU_DMA_START_ADDR_Y1 0x00D0 +#define LCD_SPU_DMA_START_ADDR_U1 0x00D4 +#define LCD_SPU_DMA_START_ADDR_V1 0x00D8 +#define LCD_CFG_DMA_START_ADDR_1 0x00DC /* Cmd address */ + +/* YC & UV Pitch */ +#define LCD_SPU_DMA_PITCH_YC 0x00E0 +#define SPU_DMA_PITCH_C(c) (c<<16) +#define SPU_DMA_PITCH_Y(y) (y) +#define LCD_SPU_DMA_PITCH_UV 0x00E4 +#define SPU_DMA_PITCH_V(v) (v<<16) +#define SPU_DMA_PITCH_U(u) (u) + +/* Video Starting Point on Screen Register */ +#define LCD_SPUT_DMA_OVSA_HPXL_VLN 0x00E8 +#define CFG_DMA_OVSA_VLN(y) (y<<16) /* 0~0xfff */ +#define CFG_DMA_OVSA_HPXL(x) (x) /* 0~0xfff */ + +/* Video Size Register */ +#define LCD_SPU_DMA_HPXL_VLN 0x00EC +#define CFG_DMA_VLN(y) (y<<16) +#define CFG_DMA_HPXL(x) (x) + +/* Video Size After zooming Register */ +#define LCD_SPU_DZM_HPXL_VLN 0x00F0 +#define CFG_DZM_VLN(y) (y<<16) +#define CFG_DZM_HPXL(x) (x) + +/* Graphic Frame 0&1 Starting Address Register */ +#define LCD_CFG_GRA_START_ADDR0 0x00F4 +#define LCD_CFG_GRA_START_ADDR1 0x00F8 + +/* Graphic Frame Pitch */ +#define LCD_CFG_GRA_PITCH 0x00FC + +/* Graphic Starting Point on Screen Register */ +#define LCD_SPU_GRA_OVSA_HPXL_VLN 0x0100 +#define CFG_GRA_OVSA_VLN(y) (y<<16) +#define CFG_GRA_OVSA_HPXL(x) (x) + +/* Graphic Size Register */ +#define LCD_SPU_GRA_HPXL_VLN 0x0104 +#define CFG_GRA_VLN(y) (y<<16) +#define CFG_GRA_HPXL(x) (x) + +/* Graphic Size after Zooming Register */ +#define LCD_SPU_GZM_HPXL_VLN 0x0108 +#define CFG_GZM_VLN(y) (y<<16) +#define CFG_GZM_HPXL(x) (x) + +/* HW Cursor Starting Point on Screen Register */ +#define LCD_SPU_HWC_OVSA_HPXL_VLN 0x010C +#define CFG_HWC_OVSA_VLN(y) (y<<16) +#define CFG_HWC_OVSA_HPXL(x) (x) + +/* HW Cursor Size */ +#define LCD_SPU_HWC_HPXL_VLN 0x0110 +#define CFG_HWC_VLN(y) (y<<16) +#define CFG_HWC_HPXL(x) (x) + +/* Total Screen Size Register */ +#define LCD_SPUT_V_H_TOTAL 0x0114 +#define CFG_V_TOTAL(y) ((y)<<16) +#define CFG_H_TOTAL(x) (x) + +/* Total Screen Active Size Register */ +#define LCD_SPU_V_H_ACTIVE 0x0118 +#define CFG_V_ACTIVE(y) ((y)<<16) +#define CFG_H_ACTIVE(x) (x) + +/* Screen H&V Porch Register */ +#define LCD_SPU_H_PORCH 0x011C +#define CFG_H_BACK_PORCH(b) (b<<16) +#define CFG_H_FRONT_PORCH(f) (f) +#define LCD_SPU_V_PORCH 0x0120 +#define CFG_V_BACK_PORCH(b) (b<<16) +#define CFG_V_FRONT_PORCH(f) (f) + +/* Screen Blank Color Register */ +#define LCD_SPU_BLANKCOLOR 0x0124 +#define CFG_BLANKCOLOR_MASK 0x00FFFFFF +#define CFG_BLANKCOLOR_R_MASK 0x000000FF +#define CFG_BLANKCOLOR_G_MASK 0x0000FF00 +#define CFG_BLANKCOLOR_B_MASK 0x00FF0000 + +/* HW Cursor Color 1&2 Register */ +#define LCD_SPU_ALPHA_COLOR1 0x0128 +#define CFG_HWC_COLOR1 0x00FFFFFF +#define CFG_HWC_COLOR1_R(red) (red<<16) +#define CFG_HWC_COLOR1_G(green) (green<<8) +#define CFG_HWC_COLOR1_B(blue) (blue) +#define CFG_HWC_COLOR1_R_MASK 0x000000FF +#define CFG_HWC_COLOR1_G_MASK 0x0000FF00 +#define CFG_HWC_COLOR1_B_MASK 0x00FF0000 +#define LCD_SPU_ALPHA_COLOR2 0x012C +#define CFG_HWC_COLOR2 0x00FFFFFF +#define CFG_HWC_COLOR2_R_MASK 0x000000FF +#define CFG_HWC_COLOR2_G_MASK 0x0000FF00 +#define CFG_HWC_COLOR2_B_MASK 0x00FF0000 + +/* Video YUV Color Key Control */ +#define LCD_SPU_COLORKEY_Y 0x0130 +#define CFG_CKEY_Y2(y2) ((y2)<<24) +#define CFG_CKEY_Y2_MASK 0xFF000000 +#define CFG_CKEY_Y1(y1) ((y1)<<16) +#define CFG_CKEY_Y1_MASK 0x00FF0000 +#define CFG_CKEY_Y(y) ((y)<<8) +#define CFG_CKEY_Y_MASK 0x0000FF00 +#define CFG_ALPHA_Y(y) (y) +#define CFG_ALPHA_Y_MASK 0x000000FF +#define LCD_SPU_COLORKEY_U 0x0134 +#define CFG_CKEY_U2(u2) ((u2)<<24) +#define CFG_CKEY_U2_MASK 0xFF000000 +#define CFG_CKEY_U1(u1) ((u1)<<16) +#define CFG_CKEY_U1_MASK 0x00FF0000 +#define CFG_CKEY_U(u) ((u)<<8) +#define CFG_CKEY_U_MASK 0x0000FF00 +#define CFG_ALPHA_U(u) (u) +#define CFG_ALPHA_U_MASK 0x000000FF +#define LCD_SPU_COLORKEY_V 0x0138 +#define CFG_CKEY_V2(v2) ((v2)<<24) +#define CFG_CKEY_V2_MASK 0xFF000000 +#define CFG_CKEY_V1(v1) ((v1)<<16) +#define CFG_CKEY_V1_MASK 0x00FF0000 +#define CFG_CKEY_V(v) ((v)<<8) +#define CFG_CKEY_V_MASK 0x0000FF00 +#define CFG_ALPHA_V(v) (v) +#define CFG_ALPHA_V_MASK 0x000000FF + +/* SPI Read Data Register */ +#define LCD_SPU_SPI_RXDATA 0x0140 + +/* Smart Panel Read Data Register */ +#define LCD_SPU_ISA_RSDATA 0x0144 +#define ISA_RXDATA_16BIT_1_DATA_MASK 0x000000FF +#define ISA_RXDATA_16BIT_2_DATA_MASK 0x0000FF00 +#define ISA_RXDATA_16BIT_3_DATA_MASK 0x00FF0000 +#define ISA_RXDATA_16BIT_4_DATA_MASK 0xFF000000 +#define ISA_RXDATA_32BIT_1_DATA_MASK 0x00FFFFFF + +/* HWC SRAM Read Data Register */ +#define LCD_SPU_HWC_RDDAT 0x0158 + +/* Gamma Table SRAM Read Data Register */ +#define LCD_SPU_GAMMA_RDDAT 0x015c +#define CFG_GAMMA_RDDAT_MASK 0x000000FF + +/* Palette Table SRAM Read Data Register */ +#define LCD_SPU_PALETTE_RDDAT 0x0160 +#define CFG_PALETTE_RDDAT_MASK 0x00FFFFFF + +/* I/O Pads Input Read Only Register */ +#define LCD_SPU_IOPAD_IN 0x0178 +#define CFG_IOPAD_IN_MASK 0x0FFFFFFF + +/* Reserved Read Only Registers */ +#define LCD_CFG_RDREG5F 0x017C +#define IRE_FRAME_CNT_MASK 0x000000C0 +#define IPE_FRAME_CNT_MASK 0x00000030 +#define GRA_FRAME_CNT_MASK 0x0000000C /* Graphic */ +#define DMA_FRAME_CNT_MASK 0x00000003 /* Video */ + +/* SPI Control Register. */ +#define LCD_SPU_SPI_CTRL 0x0180 +#define CFG_SCLKCNT(div) (div<<24) /* 0xFF~0x2 */ +#define CFG_SCLKCNT_MASK 0xFF000000 +#define CFG_RXBITS(rx) (rx<<16) /* 0x1F~0x1 */ +#define CFG_RXBITS_MASK 0x00FF0000 +#define CFG_TXBITS(tx) (tx<<8) /* 0x1F~0x1 */ +#define CFG_TXBITS_MASK 0x0000FF00 +#define CFG_CLKINV(clk) (clk<<7) +#define CFG_CLKINV_MASK 0x00000080 +#define CFG_KEEPXFER(transfer) (transfer<<6) +#define CFG_KEEPXFER_MASK 0x00000040 +#define CFG_RXBITSTO0(rx) (rx<<5) +#define CFG_RXBITSTO0_MASK 0x00000020 +#define CFG_TXBITSTO0(tx) (tx<<4) +#define CFG_TXBITSTO0_MASK 0x00000010 +#define CFG_SPI_ENA(spi) (spi<<3) +#define CFG_SPI_ENA_MASK 0x00000008 +#define CFG_SPI_SEL(spi) (spi<<2) +#define CFG_SPI_SEL_MASK 0x00000004 +#define CFG_SPI_3W4WB(wire) (wire<<1) +#define CFG_SPI_3W4WB_MASK 0x00000002 +#define CFG_SPI_START(start) (start) +#define CFG_SPI_START_MASK 0x00000001 + +/* SPI Tx Data Register */ +#define LCD_SPU_SPI_TXDATA 0x0184 + +/* + 1. Smart Pannel 8-bit Bus Control Register. + 2. AHB Slave Path Data Port Register +*/ +#define LCD_SPU_SMPN_CTRL 0x0188 + +/* DMA Control 0 Register */ +#define LCD_SPU_DMA_CTRL0 0x0190 +#define CFG_NOBLENDING(nb) (nb<<31) +#define CFG_NOBLENDING_MASK 0x80000000 +#define CFG_GAMMA_ENA(gn) (gn<<30) +#define CFG_GAMMA_ENA_MASK 0x40000000 +#define CFG_CBSH_ENA(cn) (cn<<29) +#define CFG_CBSH_ENA_MASK 0x20000000 +#define CFG_PALETTE_ENA(pn) (pn<<28) +#define CFG_PALETTE_ENA_MASK 0x10000000 +#define CFG_ARBFAST_ENA(an) (an<<27) +#define CFG_ARBFAST_ENA_MASK 0x08000000 +#define CFG_HWC_1BITMOD(mode) (mode<<26) +#define CFG_HWC_1BITMOD_MASK 0x04000000 +#define CFG_HWC_1BITENA(mn) (mn<<25) +#define CFG_HWC_1BITENA_MASK 0x02000000 +#define CFG_HWC_ENA(cn) (cn<<24) +#define CFG_HWC_ENA_MASK 0x01000000 +#define CFG_DMAFORMAT(dmaformat) (dmaformat<<20) +#define CFG_DMAFORMAT_MASK 0x00F00000 +#define CFG_GRAFORMAT(graformat) (graformat<<16) +#define CFG_GRAFORMAT_MASK 0x000F0000 +/* for graphic part */ +#define CFG_GRA_FTOGGLE(toggle) (toggle<<15) +#define CFG_GRA_FTOGGLE_MASK 0x00008000 +#define CFG_GRA_HSMOOTH(smooth) (smooth<<14) +#define CFG_GRA_HSMOOTH_MASK 0x00004000 +#define CFG_GRA_TSTMODE(test) (test<<13) +#define CFG_GRA_TSTMODE_MASK 0x00002000 +#define CFG_GRA_SWAPRB(swap) (swap<<12) +#define CFG_GRA_SWAPRB_MASK 0x00001000 +#define CFG_GRA_SWAPUV(swap) (swap<<11) +#define CFG_GRA_SWAPUV_MASK 0x00000800 +#define CFG_GRA_SWAPYU(swap) (swap<<10) +#define CFG_GRA_SWAPYU_MASK 0x00000400 +#define CFG_YUV2RGB_GRA(cvrt) (cvrt<<9) +#define CFG_YUV2RGB_GRA_MASK 0x00000200 +#define CFG_GRA_ENA(gra) (gra<<8) +#define CFG_GRA_ENA_MASK 0x00000100 +/* for video part */ +#define CFG_DMA_FTOGGLE(toggle) (toggle<<7) +#define CFG_DMA_FTOGGLE_MASK 0x00000080 +#define CFG_DMA_HSMOOTH(smooth) (smooth<<6) +#define CFG_DMA_HSMOOTH_MASK 0x00000040 +#define CFG_DMA_TSTMODE(test) (test<<5) +#define CFG_DMA_TSTMODE_MASK 0x00000020 +#define CFG_DMA_SWAPRB(swap) (swap<<4) +#define CFG_DMA_SWAPRB_MASK 0x00000010 +#define CFG_DMA_SWAPUV(swap) (swap<<3) +#define CFG_DMA_SWAPUV_MASK 0x00000008 +#define CFG_DMA_SWAPYU(swap) (swap<<2) +#define CFG_DMA_SWAPYU_MASK 0x00000004 +#define CFG_DMA_SWAP_MASK 0x0000001C +#define CFG_YUV2RGB_DMA(cvrt) (cvrt<<1) +#define CFG_YUV2RGB_DMA_MASK 0x00000002 +#define CFG_DMA_ENA(video) (video) +#define CFG_DMA_ENA_MASK 0x00000001 + +/* DMA Control 1 Register */ +#define LCD_SPU_DMA_CTRL1 0x0194 +#define CFG_FRAME_TRIG(trig) (trig<<31) +#define CFG_FRAME_TRIG_MASK 0x80000000 +#define CFG_VSYNC_TRIG(trig) (trig<<28) +#define CFG_VSYNC_TRIG_MASK 0x70000000 +#define CFG_VSYNC_INV(inv) (inv<<27) +#define CFG_VSYNC_INV_MASK 0x08000000 +#define CFG_COLOR_KEY_MODE(cmode) (cmode<<24) +#define CFG_COLOR_KEY_MASK 0x07000000 +#define CFG_CARRY(carry) (carry<<23) +#define CFG_CARRY_MASK 0x00800000 +#define CFG_LNBUF_ENA(lnbuf) (lnbuf<<22) +#define CFG_LNBUF_ENA_MASK 0x00400000 +#define CFG_GATED_ENA(gated) (gated<<21) +#define CFG_GATED_ENA_MASK 0x00200000 +#define CFG_PWRDN_ENA(power) (power<<20) +#define CFG_PWRDN_ENA_MASK 0x00100000 +#define CFG_DSCALE(dscale) (dscale<<18) +#define CFG_DSCALE_MASK 0x000C0000 +#define CFG_ALPHA_MODE(amode) (amode<<16) +#define CFG_ALPHA_MODE_MASK 0x00030000 +#define CFG_ALPHA(alpha) (alpha<<8) +#define CFG_ALPHA_MASK 0x0000FF00 +#define CFG_PXLCMD(pxlcmd) (pxlcmd) +#define CFG_PXLCMD_MASK 0x000000FF + +/* SRAM Control Register */ +#define LCD_SPU_SRAM_CTRL 0x0198 +#define CFG_SRAM_INIT_WR_RD(mode) (mode<<14) +#define CFG_SRAM_INIT_WR_RD_MASK 0x0000C000 +#define CFG_SRAM_ADDR_LCDID(id) (id<<8) +#define CFG_SRAM_ADDR_LCDID_MASK 0x00000F00 +#define CFG_SRAM_ADDR(addr) (addr) +#define CFG_SRAM_ADDR_MASK 0x000000FF + +/* SRAM Write Data Register */ +#define LCD_SPU_SRAM_WRDAT 0x019C + +/* SRAM RTC/WTC Control Register */ +#define LCD_SPU_SRAM_PARA0 0x01A0 + +/* SRAM Power Down Control Register */ +#define LCD_SPU_SRAM_PARA1 0x01A4 +#define CFG_CSB_256x32(hwc) (hwc<<15) /* HWC */ +#define CFG_CSB_256x32_MASK 0x00008000 +#define CFG_CSB_256x24(palette) (palette<<14) /* Palette */ +#define CFG_CSB_256x24_MASK 0x00004000 +#define CFG_CSB_256x8(gamma) (gamma<<13) /* Gamma */ +#define CFG_CSB_256x8_MASK 0x00002000 +#define CFG_PDWN256x32(pdwn) (pdwn<<7) /* HWC */ +#define CFG_PDWN256x32_MASK 0x00000080 +#define CFG_PDWN256x24(pdwn) (pdwn<<6) /* Palette */ +#define CFG_PDWN256x24_MASK 0x00000040 +#define CFG_PDWN256x8(pdwn) (pdwn<<5) /* Gamma */ +#define CFG_PDWN256x8_MASK 0x00000020 +#define CFG_PDWN32x32(pdwn) (pdwn<<3) +#define CFG_PDWN32x32_MASK 0x00000008 +#define CFG_PDWN16x66(pdwn) (pdwn<<2) +#define CFG_PDWN16x66_MASK 0x00000004 +#define CFG_PDWN32x66(pdwn) (pdwn<<1) +#define CFG_PDWN32x66_MASK 0x00000002 +#define CFG_PDWN64x66(pdwn) (pdwn) +#define CFG_PDWN64x66_MASK 0x00000001 + +/* Smart or Dumb Panel Clock Divider */ +#define LCD_CFG_SCLK_DIV 0x01A8 +#define SCLK_SOURCE_SELECT(src) (src<<31) +#define SCLK_SOURCE_SELECT_MASK 0x80000000 +#define CLK_FRACDIV(frac) (frac<<16) +#define CLK_FRACDIV_MASK 0x0FFF0000 +#define CLK_INT_DIV(div) (div) +#define CLK_INT_DIV_MASK 0x0000FFFF + +/* Video Contrast Register */ +#define LCD_SPU_CONTRAST 0x01AC +#define CFG_BRIGHTNESS(bright) (bright<<16) +#define CFG_BRIGHTNESS_MASK 0xFFFF0000 +#define CFG_CONTRAST(contrast) (contrast) +#define CFG_CONTRAST_MASK 0x0000FFFF + +/* Video Saturation Register */ +#define LCD_SPU_SATURATION 0x01B0 +#define CFG_C_MULTS(mult) (mult<<16) +#define CFG_C_MULTS_MASK 0xFFFF0000 +#define CFG_SATURATION(sat) (sat) +#define CFG_SATURATION_MASK 0x0000FFFF + +/* Video Hue Adjust Register */ +#define LCD_SPU_CBSH_HUE 0x01B4 +#define CFG_SIN0(sin0) (sin0<<16) +#define CFG_SIN0_MASK 0xFFFF0000 +#define CFG_COS0(con0) (con0) +#define CFG_COS0_MASK 0x0000FFFF + +/* Dump LCD Panel Control Register */ +#define LCD_SPU_DUMB_CTRL 0x01B8 +#define CFG_DUMBMODE(mode) (mode<<28) +#define CFG_DUMBMODE_MASK 0xF0000000 +#define CFG_LCDGPIO_O(data) (data<<20) +#define CFG_LCDGPIO_O_MASK 0x0FF00000 +#define CFG_LCDGPIO_ENA(gpio) (gpio<<12) +#define CFG_LCDGPIO_ENA_MASK 0x000FF000 +#define CFG_BIAS_OUT(bias) (bias<<8) +#define CFG_BIAS_OUT_MASK 0x00000100 +#define CFG_REVERSE_RGB(rRGB) (rRGB<<7) +#define CFG_REVERSE_RGB_MASK 0x00000080 +#define CFG_INV_COMPBLANK(blank) (blank<<6) +#define CFG_INV_COMPBLANK_MASK 0x00000040 +#define CFG_INV_COMPSYNC(sync) (sync<<5) +#define CFG_INV_COMPSYNC_MASK 0x00000020 +#define CFG_INV_HENA(hena) (hena<<4) +#define CFG_INV_HENA_MASK 0x00000010 +#define CFG_INV_VSYNC(vsync) (vsync<<3) +#define CFG_INV_VSYNC_MASK 0x00000008 +#define CFG_INV_HSYNC(hsync) (hsync<<2) +#define CFG_INV_HSYNC_MASK 0x00000004 +#define CFG_INV_PCLK(pclk) (pclk<<1) +#define CFG_INV_PCLK_MASK 0x00000002 +#define CFG_DUMB_ENA(dumb) (dumb) +#define CFG_DUMB_ENA_MASK 0x00000001 + +/* LCD I/O Pads Control Register */ +#define SPU_IOPAD_CONTROL 0x01BC +#define CFG_GRA_VM_ENA(vm) (vm<<15) /* gfx */ +#define CFG_GRA_VM_ENA_MASK 0x00008000 +#define CFG_DMA_VM_ENA(vm) (vm<<13) /* video */ +#define CFG_DMA_VM_ENA_MASK 0x00002000 +#define CFG_CMD_VM_ENA(vm) (vm<<13) +#define CFG_CMD_VM_ENA_MASK 0x00000800 +#define CFG_CSC(csc) (csc<<8) /* csc */ +#define CFG_CSC_MASK 0x00000300 +#define CFG_AXICTRL(axi) (axi<<4) +#define CFG_AXICTRL_MASK 0x000000F0 +#define CFG_IOPADMODE(iopad) (iopad) +#define CFG_IOPADMODE_MASK 0x0000000F + +/* LCD Interrupt Control Register */ +#define SPU_IRQ_ENA 0x01C0 +#define DMA_FRAME_IRQ0_ENA(irq) (irq<<31) +#define DMA_FRAME_IRQ0_ENA_MASK 0x80000000 +#define DMA_FRAME_IRQ1_ENA(irq) (irq<<30) +#define DMA_FRAME_IRQ1_ENA_MASK 0x40000000 +#define DMA_FF_UNDERFLOW_ENA(ff) (ff<<29) +#define DMA_FF_UNDERFLOW_ENA_MASK 0x20000000 +#define GRA_FRAME_IRQ0_ENA(irq) (irq<<27) +#define GRA_FRAME_IRQ0_ENA_MASK 0x08000000 +#define GRA_FRAME_IRQ1_ENA(irq) (irq<<26) +#define GRA_FRAME_IRQ1_ENA_MASK 0x04000000 +#define GRA_FF_UNDERFLOW_ENA(ff) (ff<<25) +#define GRA_FF_UNDERFLOW_ENA_MASK 0x02000000 +#define VSYNC_IRQ_ENA(vsync_irq) (vsync_irq<<23) +#define VSYNC_IRQ_ENA_MASK 0x00800000 +#define DUMB_FRAMEDONE_ENA(fdone) (fdone<<22) +#define DUMB_FRAMEDONE_ENA_MASK 0x00400000 +#define TWC_FRAMEDONE_ENA(fdone) (fdone<<21) +#define TWC_FRAMEDONE_ENA_MASK 0x00200000 +#define HWC_FRAMEDONE_ENA(fdone) (fdone<<20) +#define HWC_FRAMEDONE_ENA_MASK 0x00100000 +#define SLV_IRQ_ENA(irq) (irq<<19) +#define SLV_IRQ_ENA_MASK 0x00080000 +#define SPI_IRQ_ENA(irq) (irq<<18) +#define SPI_IRQ_ENA_MASK 0x00040000 +#define PWRDN_IRQ_ENA(irq) (irq<<17) +#define PWRDN_IRQ_ENA_MASK 0x00020000 +#define ERR_IRQ_ENA(irq) (irq<<16) +#define ERR_IRQ_ENA_MASK 0x00010000 +#define CLEAN_SPU_IRQ_ISR(irq) (irq) +#define CLEAN_SPU_IRQ_ISR_MASK 0x0000FFFF + +/* LCD Interrupt Status Register */ +#define SPU_IRQ_ISR 0x01C4 +#define DMA_FRAME_IRQ0(irq) (irq<<31) +#define DMA_FRAME_IRQ0_MASK 0x80000000 +#define DMA_FRAME_IRQ1(irq) (irq<<30) +#define DMA_FRAME_IRQ1_MASK 0x40000000 +#define DMA_FF_UNDERFLOW(ff) (ff<<29) +#define DMA_FF_UNDERFLOW_MASK 0x20000000 +#define GRA_FRAME_IRQ0(irq) (irq<<27) +#define GRA_FRAME_IRQ0_MASK 0x08000000 +#define GRA_FRAME_IRQ1(irq) (irq<<26) +#define GRA_FRAME_IRQ1_MASK 0x04000000 +#define GRA_FF_UNDERFLOW(ff) (ff<<25) +#define GRA_FF_UNDERFLOW_MASK 0x02000000 +#define VSYNC_IRQ(vsync_irq) (vsync_irq<<23) +#define VSYNC_IRQ_MASK 0x00800000 +#define DUMB_FRAMEDONE(fdone) (fdone<<22) +#define DUMB_FRAMEDONE_MASK 0x00400000 +#define TWC_FRAMEDONE(fdone) (fdone<<21) +#define TWC_FRAMEDONE_MASK 0x00200000 +#define HWC_FRAMEDONE(fdone) (fdone<<20) +#define HWC_FRAMEDONE_MASK 0x00100000 +#define SLV_IRQ(irq) (irq<<19) +#define SLV_IRQ_MASK 0x00080000 +#define SPI_IRQ(irq) (irq<<18) +#define SPI_IRQ_MASK 0x00040000 +#define PWRDN_IRQ(irq) (irq<<17) +#define PWRDN_IRQ_MASK 0x00020000 +#define ERR_IRQ(irq) (irq<<16) +#define ERR_IRQ_MASK 0x00010000 +/* read-only */ +#define DMA_FRAME_IRQ0_LEVEL_MASK 0x00008000 +#define DMA_FRAME_IRQ1_LEVEL_MASK 0x00004000 +#define DMA_FRAME_CNT_ISR_MASK 0x00003000 +#define GRA_FRAME_IRQ0_LEVEL_MASK 0x00000800 +#define GRA_FRAME_IRQ1_LEVEL_MASK 0x00000400 +#define GRA_FRAME_CNT_ISR_MASK 0x00000300 +#define VSYNC_IRQ_LEVEL_MASK 0x00000080 +#define DUMB_FRAMEDONE_LEVEL_MASK 0x00000040 +#define TWC_FRAMEDONE_LEVEL_MASK 0x00000020 +#define HWC_FRAMEDONE_LEVEL_MASK 0x00000010 +#define SLV_FF_EMPTY_MASK 0x00000008 +#define DMA_FF_ALLEMPTY_MASK 0x00000004 +#define GRA_FF_ALLEMPTY_MASK 0x00000002 +#define PWRDN_IRQ_LEVEL_MASK 0x00000001 + + +/* + * defined Video Memory Color format for DMA control 0 register + * DMA0 bit[23:20] + */ +#define VMODE_RGB565 0x0 +#define VMODE_RGB1555 0x1 +#define VMODE_RGB888PACKED 0x2 +#define VMODE_RGB888UNPACKED 0x3 +#define VMODE_RGBA888 0x4 +#define VMODE_YUV422PACKED 0x5 +#define VMODE_YUV422PLANAR 0x6 +#define VMODE_YUV420PLANAR 0x7 +#define VMODE_SMPNCMD 0x8 +#define VMODE_PALETTE4BIT 0x9 +#define VMODE_PALETTE8BIT 0xa +#define VMODE_RESERVED 0xb + +/* + * defined Graphic Memory Color format for DMA control 0 register + * DMA0 bit[19:16] + */ +#define GMODE_RGB565 0x0 +#define GMODE_RGB1555 0x1 +#define GMODE_RGB888PACKED 0x2 +#define GMODE_RGB888UNPACKED 0x3 +#define GMODE_RGBA888 0x4 +#define GMODE_YUV422PACKED 0x5 +#define GMODE_YUV422PLANAR 0x6 +#define GMODE_YUV420PLANAR 0x7 +#define GMODE_SMPNCMD 0x8 +#define GMODE_PALETTE4BIT 0x9 +#define GMODE_PALETTE8BIT 0xa +#define GMODE_RESERVED 0xb + +/* + * define for DMA control 1 register + */ +#define DMA1_FRAME_TRIG 31 /* bit location */ +#define DMA1_VSYNC_MODE 28 +#define DMA1_VSYNC_INV 27 +#define DMA1_CKEY 24 +#define DMA1_CARRY 23 +#define DMA1_LNBUF_ENA 22 +#define DMA1_GATED_ENA 21 +#define DMA1_PWRDN_ENA 20 +#define DMA1_DSCALE 18 +#define DMA1_ALPHA_MODE 16 +#define DMA1_ALPHA 08 +#define DMA1_PXLCMD 00 + +/* + * defined for Configure Dumb Mode + * DUMB LCD Panel bit[31:28] + */ +#define DUMB16_RGB565_0 0x0 +#define DUMB16_RGB565_1 0x1 +#define DUMB18_RGB666_0 0x2 +#define DUMB18_RGB666_1 0x3 +#define DUMB12_RGB444_0 0x4 +#define DUMB12_RGB444_1 0x5 +#define DUMB24_RGB888_0 0x6 +#define DUMB_BLANK 0x7 + +/* + * defined for Configure I/O Pin Allocation Mode + * LCD LCD I/O Pads control register bit[3:0] + */ +#define IOPAD_DUMB24 0x0 +#define IOPAD_DUMB18SPI 0x1 +#define IOPAD_DUMB18GPIO 0x2 +#define IOPAD_DUMB16SPI 0x3 +#define IOPAD_DUMB16GPIO 0x4 +#define IOPAD_DUMB12 0x5 +#define IOPAD_SMART18SPI 0x6 +#define IOPAD_SMART16SPI 0x7 +#define IOPAD_SMART8BOTH 0x8 + +#endif /* __PXA168FB_H__ */ diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h new file mode 100644 index 0000000..59c4a1b --- /dev/null +++ b/include/video/pxa168fb.h @@ -0,0 +1,138 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/pxa168fb.h + * + * Copyright (C) 2009 Marvell International Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_PXA168FB_H +#define __ASM_MACH_PXA168FB_H + +#include <linux/fb.h> +#include <linux/interrupt.h> + +/* Dumb interface */ +#define PIN_MODE_DUMB_24 0 +#define PIN_MODE_DUMB_18_SPI 1 +#define PIN_MODE_DUMB_18_GPIO 2 +#define PIN_MODE_DUMB_16_SPI 3 +#define PIN_MODE_DUMB_16_GPIO 4 +#define PIN_MODE_DUMB_12_SPI_GPIO 5 +#define PIN_MODE_SMART_18_SPI 6 +#define PIN_MODE_SMART_16_SPI 7 +#define PIN_MODE_SMART_8_SPI_GPIO 8 + +/* Dumb interface pin allocation */ +#define DUMB_MODE_RGB565 0 +#define DUMB_MODE_RGB565_UPPER 1 +#define DUMB_MODE_RGB666 2 +#define DUMB_MODE_RGB666_UPPER 3 +#define DUMB_MODE_RGB444 4 +#define DUMB_MODE_RGB444_UPPER 5 +#define DUMB_MODE_RGB888 6 + +/* default fb buffer size WVGA-32bits */ +#define DEFAULT_FB_SIZE (800 * 480 * 4) + +/* + * Buffer pixel format + * bit0 is for rb swap. + * bit12 is for Y UorV swap + */ +#define PIX_FMT_RGB565 0 +#define PIX_FMT_BGR565 1 +#define PIX_FMT_RGB1555 2 +#define PIX_FMT_BGR1555 3 +#define PIX_FMT_RGB888PACK 4 +#define PIX_FMT_BGR888PACK 5 +#define PIX_FMT_RGB888UNPACK 6 +#define PIX_FMT_BGR888UNPACK 7 +#define PIX_FMT_RGBA888 8 +#define PIX_FMT_BGRA888 9 +#define PIX_FMT_YUV422PACK 10 +#define PIX_FMT_YVU422PACK 11 +#define PIX_FMT_YUV422PLANAR 12 +#define PIX_FMT_YVU422PLANAR 13 +#define PIX_FMT_YUV420PLANAR 14 +#define PIX_FMT_YVU420PLANAR 15 +#define PIX_FMT_PSEUDOCOLOR 20 +#define PIX_FMT_UYVY422PACK (0x1000|PIX_FMT_YUV422PACK) + +/* + * PXA LCD controller private state. + */ +struct pxa168fb_info { + struct device *dev; + struct clk *clk; + + void *reg_base; + unsigned long new_addr; + dma_addr_t fb_start_dma; + void *fb_start; + int fb_size; + atomic_t w_intr; + wait_queue_head_t w_intr_wq; + struct mutex access_ok; + struct fb_videomode dft_vmode; + unsigned char *hwc_buf; + unsigned int pseudo_palette[16]; + struct tasklet_struct tasklet; + char *mode_option; + + int pix_fmt; + unsigned is_blanked:1; + unsigned panel_rbswap:1; + unsigned debug:1; + unsigned active:1; +}; + +/* + * PXA fb machine information + */ +struct pxa168fb_mach_info { + char id[16]; + unsigned int sclk_clock; + + int num_modes; + struct fb_videomode *modes; + + /* + * Pix_fmt + */ + unsigned pix_fmt; + + /* + * I/O pin allocation. + */ + unsigned io_pin_allocation_mode:4; + + /* + * Dumb panel -- assignment of R/G/B component info to the 24 + * available external data lanes. + */ + unsigned dumb_mode:4; + unsigned panel_rgb_reverse_lanes:1; + + /* + * Dumb panel -- GPIO output data. + */ + unsigned gpio_output_mask:8; + unsigned gpio_output_data:8; + + /* + * Dumb panel -- configurable output signal polarity. + */ + unsigned invert_composite_blank:1; + unsigned invert_pix_val_ena:1; + unsigned invert_pixclock:1; + unsigned invert_vsync:1; + unsigned invert_hsync:1; + unsigned panel_rbswap:1; + unsigned active:1; + unsigned enable_lcd:1; +}; + +#endif /* __ASM_MACH_PXA168FB_H */ -- 1.6.0.4 -- Cheers - eric |
From: Harald W. <Har...@vi...> - 2009-05-20 20:49:45
|
From: Harald Welte <la...@gn...> Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/hw.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index fcd53ce..59ddf09 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -2272,6 +2272,7 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, case UNICHROME_CX700: viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs); + break; case UNICHROME_VX800: viafb_write_regx(VX800_ModeXregs, NUM_TOTAL_VX800_ModeXregs); -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:49:43
|
From: Harald Welte <la...@gn...> We don't need to unroll the register initialization routine when initializing the 2D engine registers Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/accel.c | 18 +++--------------- 1 files changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index c3af95f..b3a414e 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -41,23 +41,11 @@ void viafb_init_2d_engine(void) { u32 dwVQStartAddr, dwVQEndAddr; u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; + int i; /* init 2D engine regs to reset 2D engine */ - writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE); - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS); - writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION); - writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR); - writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR); - writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR); - writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL); - writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR); - writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET); - writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL); - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); - writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH); - writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1); + for (i = 0; i <= 0x40; i+= 4) + writel(0x0, viaparinfo->io_virt + i); /* Init AGP and VQ regs */ switch (viaparinfo->chip_info->gfx_chip_name) { -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:49:24
|
From: Harald Welte <la...@gn...> This is required as preparation for supporting the new M1 engine of the VX800/VX855 which has registers at permutated addresses. Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/accel.c | 13 +++++++++---- drivers/video/via/accel.h | 1 + drivers/video/via/viafbdev.c | 38 +++++++++++++++++--------------------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 4a1183f..c3af95f 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -20,6 +20,11 @@ */ #include "global.h" +void viafb_2d_writel(u_int32_t val, u_int32_t reg) +{ + writel(val, viaparinfo->io_virt + reg); +} + void viafb_init_accel(void) { viaparinfo->fbmem_free -= CURSOR_SIZE; @@ -213,18 +218,18 @@ void viafb_set_2d_mode(struct fb_info *info) dwGEMode |= VIA_GEM_8bpp; break; } - writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE); + viafb_2d_writel(dwGEMode, VIA_REG_GEMODE); /* Set source and destination base */ base = ((void *)info->screen_base - viafb_FB_MM); - writel(base >> 3, viaparinfo->io_virt + VIA_REG_SRCBASE); - writel(base >> 3, viaparinfo->io_virt + VIA_REG_DSTBASE); + viafb_2d_writel(base >> 3, VIA_REG_SRCBASE); + viafb_2d_writel(base >> 3, VIA_REG_DSTBASE); /* Set source and destination pitch (128bit aligned) */ pitch = (viaparinfo->hres * viaparinfo->bpp >> 3) >> 3; pitch_reg = pitch | (pitch << 16); pitch_reg |= VIA_PITCH_ENABLE; - writel(pitch_reg, viaparinfo->io_virt + VIA_REG_PITCH); + viafb_2d_writel(pitch_reg, VIA_REG_PITCH); } void viafb_hw_cursor_init(void) diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h index bef3134..5081ac2 100644 --- a/drivers/video/via/accel.h +++ b/drivers/video/via/accel.h @@ -159,6 +159,7 @@ #define MAXLOOP 0xFFFFFF +void viafb_2d_writel(u_int32_t val, u_int32_t reg); void viafb_init_accel(void); void viafb_init_2d_engine(void); void viafb_set_2d_mode(struct fb_info *info); diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index af8acfe..859827b 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -899,16 +899,14 @@ static void viafb_fillrect(struct fb_info *info, viafb_set_2d_mode(info); /* BitBlt Destination Address */ - writel(((rect->dy << 16) | rect->dx), - viaparinfo->io_virt + VIA_REG_DSTPOS); + viafb_2d_writel(((rect->dy << 16) | rect->dx), VIA_REG_DSTPOS); /* Dimension: width & height */ - writel((((rect->height - 1) << 16) | (rect->width - 1)), - viaparinfo->io_virt + VIA_REG_DIMENSION); + viafb_2d_writel((((rect->height - 1) << 16) | (rect->width - 1)), + VIA_REG_DIMENSION); /* Forground color or Destination color */ - writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR); + viafb_2d_writel(col, VIA_REG_FGCOLOR); /* GE Command */ - writel((0x01 | 0x2000 | (rop << 24)), - viaparinfo->io_virt + VIA_REG_GECMD); + viafb_2d_writel((0x01 | 0x2000 | (rop << 24)), VIA_REG_GECMD); } @@ -943,15 +941,14 @@ static void viafb_copyarea(struct fb_info *info, viafb_set_2d_mode(info); /* BitBlt Source Address */ - writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS); + viafb_2d_writel(((sy << 16) | sx), VIA_REG_SRCPOS); /* BitBlt Destination Address */ - writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS); + viafb_2d_writel(((dy << 16) | dx), VIA_REG_DSTPOS); /* Dimension: width & height */ - writel((((area->height - 1) << 16) | (area->width - 1)), - viaparinfo->io_virt + VIA_REG_DIMENSION); + viafb_2d_writel((((area->height - 1) << 16) | (area->width - 1)), + VIA_REG_DIMENSION); /* GE Command */ - writel((0x01 | direction | (0xCC << 24)), - viaparinfo->io_virt + VIA_REG_GECMD); + viafb_2d_writel((0x01 | direction | (0xCC << 24)), VIA_REG_GECMD); } @@ -987,19 +984,18 @@ static void viafb_imageblit(struct fb_info *info, viafb_set_2d_mode(info); /* BitBlt Source Address */ - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); + viafb_2d_writel(0x0, VIA_REG_SRCPOS); /* BitBlt Destination Address */ - writel(((image->dy << 16) | image->dx), - viaparinfo->io_virt + VIA_REG_DSTPOS); + viafb_2d_writel(((image->dy << 16) | image->dx), VIA_REG_DSTPOS); /* Dimension: width & height */ - writel((((image->height - 1) << 16) | (image->width - 1)), - viaparinfo->io_virt + VIA_REG_DIMENSION); + viafb_2d_writel((((image->height - 1) << 16) | (image->width - 1)), + VIA_REG_DIMENSION); /* fb color */ - writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR); + viafb_2d_writel(fg_col, VIA_REG_FGCOLOR); /* bg color */ - writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR); + viafb_2d_writel(bg_col, VIA_REG_BGCOLOR); /* GE Command */ - writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD); + viafb_2d_writel(0xCC020142, VIA_REG_GECMD); for (i = 0; i < size / 4; i++) { writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE); -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:49:18
|
From: Harald Welte <la...@gn...> Instead of using private structure members, we use the standard ones: * viapar->fbmem converted to fb_info->fix.smem_start * viapar->memsize is converted to fb_info->fix.smem_len * viapar->fbmem_virt is convereted to fb_info->screen_base Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/global.c | 1 - drivers/video/via/hw.c | 2 +- drivers/video/via/viafbdev.c | 47 +++++++++++++++++++---------------------- drivers/video/via/viafbdev.h | 3 -- 4 files changed, 23 insertions(+), 30 deletions(-) diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c index 468be24..2b7d0d3 100644 --- a/drivers/video/via/global.c +++ b/drivers/video/via/global.c @@ -57,4 +57,3 @@ struct fb_info *viafbinfo; struct fb_info *viafbinfo1; struct viafb_par *viaparinfo; struct viafb_par *viaparinfo1; - diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 40b7c0c..e06d6b7 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -680,7 +680,7 @@ void viafb_set_start_addr(void) size = 8 * 1024 * 1024; } else { - size = viaparinfo1->memsize; + size = viafbinfo1->fix.smem_len; } offset = viafb_second_offset; DEBUG_MSG(KERN_INFO diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 7e8f2f6..c420623 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -119,10 +119,8 @@ static int viafb_update_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, struct viafb_par *viaparinfo) { - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, viafb_name); - fix->smem_start = viaparinfo->fbmem; fix->smem_len = viaparinfo->fbmem_free; fix->mmio_start = viaparinfo->mmio_base; fix->mmio_len = viaparinfo->mmio_len; @@ -196,7 +194,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var, /*32 pixel alignment */ var->xres_virtual = (var->xres_virtual + 31) & ~31; if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > - ppar->memsize) + info->fix.smem_len) return -EINVAL; /* Based on var passed in to calculate the refresh, @@ -630,13 +628,13 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) (viaparinfo->fbmem_free >> 1); } } - u.viasamm.mem_base = viaparinfo->fbmem; + u.viasamm.mem_base = viafbinfo->fix.smem_start; u.viasamm.offset_sec = viafb_second_offset; } else { u.viasamm.size_prim = - viaparinfo->memsize - viaparinfo->fbmem_used; + viafbinfo->fix.smem_len - viaparinfo->fbmem_used; u.viasamm.size_sec = 0; - u.viasamm.mem_base = viaparinfo->fbmem; + u.viasamm.mem_base = viafbinfo->fix.smem_start; u.viasamm.offset_sec = 0; } @@ -1245,7 +1243,7 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) } } - memcpy(((struct viafb_par *)(info->par))->fbmem_virt + + memcpy(info->screen_base + ((struct viafb_par *)(info->par))->cursor_start, cr_data->bak, CURSOR_SIZE); out: @@ -2164,15 +2162,14 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, goto out_fb_release; viafb_init_chip_info(pdev, ent); - viaparinfo->fbmem = pci_resource_start(pdev, 0); - viaparinfo->memsize = viafb_get_fb_size_from_pci(); - viaparinfo->fbmem_free = viaparinfo->memsize; + viafbinfo->fix.smem_start = pci_resource_start(pdev, 0); + viafbinfo->fix.smem_len = viafb_get_fb_size_from_pci(); + viaparinfo->fbmem_free = viafbinfo->fix.smem_len; viaparinfo->fbmem_used = 0; - viaparinfo->fbmem_virt = ioremap_nocache(viaparinfo->fbmem, - viaparinfo->memsize); - viafbinfo->screen_base = (char *)viaparinfo->fbmem_virt; + viafbinfo->screen_base = ioremap_nocache(viafbinfo->fix.smem_start, + viafbinfo->fix.smem_len); - if (!viaparinfo->fbmem_virt) { + if (!viafbinfo->screen_base) { printk(KERN_ERR "ioremap of fbmem failed\n"); rc = -EIO; goto out_delete_i2c; @@ -2208,7 +2205,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viafb_second_size * 1024 * 1024; } - viafb_FB_MM = viaparinfo->fbmem_virt; + viafb_FB_MM = viafbinfo->screen_base; tmpm = viafb_mode; tmpc = strsep(&tmpm, "x"); strict_strtoul(tmpc, 0, &default_xres); @@ -2298,17 +2295,18 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, } viaparinfo1 = viafbinfo1->par; memcpy(viaparinfo1, viaparinfo, viafb_par_length); - viaparinfo1->memsize = viaparinfo->memsize - - viafb_second_offset; - viaparinfo->memsize = viafb_second_offset; - viaparinfo1->fbmem_virt = viaparinfo->fbmem_virt + + viafbinfo1->fix.smem_len = viafbinfo->fix.smem_len - + viafb_second_offset; + viafbinfo->fix.smem_len = viafb_second_offset; + viafbinfo1->screen_base = viafbinfo->screen_base + viafb_second_offset; - viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset; + viafbinfo1->fix.smem_start = viafbinfo->fix.smem_start + + viafb_second_offset; viaparinfo1->fbmem_used = viaparinfo->fbmem_used; - viaparinfo1->fbmem_free = viaparinfo1->memsize - + viaparinfo1->fbmem_free = viafbinfo1->fix.smem_len - viaparinfo1->fbmem_used; - viaparinfo->fbmem_free = viaparinfo->memsize; + viaparinfo->fbmem_free = viafbinfo->fix.smem_len; viaparinfo->fbmem_used = 0; if (viafb_accel) { viaparinfo1->cursor_start = @@ -2322,7 +2320,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info)); viafbinfo1->screen_base = viafbinfo->screen_base + viafb_second_offset; - viafbinfo1->fix.smem_start = viaparinfo1->fbmem; viafbinfo1->fix.smem_len = viaparinfo1->fbmem_free; default_var.xres = viafb_second_xres; @@ -2398,7 +2395,7 @@ out_fb1_release: out_unmap_mmio: iounmap(viaparinfo->io_virt); out_unmap_fbmem: - iounmap((void *)viaparinfo->fbmem_virt); + iounmap((void *)viafbinfo->screen_base); out_delete_i2c: viafb_delete_i2c_buss(viaparinfo); out_fb_release: @@ -2413,7 +2410,7 @@ static void __devexit via_pci_remove(struct pci_dev *pdev) unregister_framebuffer(viafbinfo); if (viafb_dual_fb) unregister_framebuffer(viafbinfo1); - iounmap((void *)viaparinfo->fbmem_virt); + iounmap((void *)viafbinfo->screen_base); iounmap(viaparinfo->io_virt); viafb_delete_i2c_buss(viaparinfo); diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index a4158e8..ed4129e 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -45,10 +45,7 @@ struct viafb_par { u32 xoffset; u32 yoffset; - void __iomem *fbmem_virt; /*framebuffer virtual memory address */ void __iomem *io_virt; /*iospace virtual memory address */ - unsigned int fbmem; /*framebuffer physical memory address */ - unsigned int memsize; /*size of fbmem */ unsigned int io; /*io space address */ unsigned long mmio_base; /*mmio base address */ unsigned long mmio_len; /*mmio base length */ -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:49:17
|
From: Harald Welte <la...@gn...> --- drivers/video/via/hw.c | 116 +++-------------------------------------- drivers/video/via/hw.h | 7 +-- drivers/video/via/viafbdev.c | 65 ++++++++++++++++++++--- 3 files changed, 68 insertions(+), 120 deletions(-) diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index b111b6c..6306c88 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -21,22 +21,6 @@ #include "global.h" -static const struct pci_device_id_info pciidlist[] = { - {PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, UNICHROME_CLE266}, - {PCI_VIA_VENDOR_ID, UNICHROME_PM800_DID, UNICHROME_PM800}, - {PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, UNICHROME_K400}, - {PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, UNICHROME_K800}, - {PCI_VIA_VENDOR_ID, UNICHROME_CN700_DID, UNICHROME_CN700}, - {PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, UNICHROME_P4M890}, - {PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, UNICHROME_K8M890}, - {PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, UNICHROME_CX700}, - {PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, UNICHROME_P4M900}, - {PCI_VIA_VENDOR_ID, UNICHROME_CN750_DID, UNICHROME_CN750}, - {PCI_VIA_VENDOR_ID, UNICHROME_VX800_DID, UNICHROME_VX800}, - {PCI_VIA_VENDOR_ID, UNICHROME_VX855_DID, UNICHROME_VX855}, - {0, 0, 0} -}; - struct offset offset_reg = { /* IGA1 Offset Register */ {IGA1_OFFSET_REG_NUM, {{CR13, 0, 7}, {CR35, 5, 7} } }, @@ -549,7 +533,8 @@ static void set_dvi_output_path(int set_iga, int output_interface); static void set_lcd_output_path(int set_iga, int output_interface); static int search_mode_setting(int ModeInfoIndex); static void load_fix_bit_crtc_reg(void); -static void init_gfx_chip_info(void); +static void init_gfx_chip_info(struct pci_dev *pdev, + const struct pci_device_id *pdi); static void init_tmds_chip_info(void); static void init_lvds_chip_info(void); static void device_screen_off(void); @@ -559,7 +544,6 @@ static void device_off(void); static void device_on(void); static void enable_second_display_channel(void); static void disable_second_display_channel(void); -static int get_fb_size_from_pci(void); void viafb_write_reg(u8 index, u16 io_port, u8 data) { @@ -1996,9 +1980,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, } -void viafb_init_chip_info(void) +void viafb_init_chip_info(struct pci_dev *pdev, + const struct pci_device_id *pdi) { - init_gfx_chip_info(); + init_gfx_chip_info(pdev, pdi); init_tmds_chip_info(); init_lvds_chip_info(); @@ -2071,24 +2056,12 @@ void viafb_update_device_setting(int hres, int vres, } } -static void init_gfx_chip_info(void) +static void init_gfx_chip_info(struct pci_dev *pdev, + const struct pci_device_id *pdi) { - struct pci_dev *pdev = NULL; - u32 i; u8 tmp; - /* Indentify GFX Chip Name */ - for (i = 0; pciidlist[i].vendor != 0; i++) { - pdev = pci_get_device(pciidlist[i].vendor, - pciidlist[i].device, 0); - if (pdev) - break; - } - - if (!pciidlist[i].vendor) - return ; - - viaparinfo->chip_info->gfx_chip_name = pciidlist[i].chip_index; + viaparinfo->chip_info->gfx_chip_name = pdi->driver_data; /* Check revision of CLE266 Chip */ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { @@ -2119,8 +2092,6 @@ static void init_gfx_chip_info(void) CX700_REVISION_700; } } - - pci_dev_put(pdev); } static void init_tmds_chip_info(void) @@ -2612,38 +2583,6 @@ void viafb_crt_enable(void) viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4); } -void viafb_get_mmio_info(unsigned long *mmio_base, - unsigned long *mmio_len) -{ - struct pci_dev *pdev = NULL; - u32 vendor, device; - u32 i; - - for (i = 0; pciidlist[i].vendor != 0; i++) - if (viaparinfo->chip_info->gfx_chip_name == - pciidlist[i].chip_index) - break; - - if (!pciidlist[i].vendor) - return ; - - vendor = pciidlist[i].vendor; - device = pciidlist[i].device; - - pdev = pci_get_device(vendor, device, NULL); - - if (!pdev) { - *mmio_base = 0; - *mmio_len = 0; - return ; - } - - *mmio_base = pci_resource_start(pdev, 1); - *mmio_len = pci_resource_len(pdev, 1); - - pci_dev_put(pdev); -} - static void enable_second_display_channel(void) { /* to enable second display channel. */ @@ -2660,44 +2599,7 @@ static void disable_second_display_channel(void) viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); } -void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len) -{ - struct pci_dev *pdev = NULL; - u32 vendor, device; - u32 i; - - for (i = 0; pciidlist[i].vendor != 0; i++) - if (viaparinfo->chip_info->gfx_chip_name == - pciidlist[i].chip_index) - break; - - if (!pciidlist[i].vendor) - return ; - - vendor = pciidlist[i].vendor; - device = pciidlist[i].device; - - pdev = pci_get_device(vendor, device, NULL); - - if (!pdev) { - *fb_base = viafb_read_reg(VIASR, SR30) << 24; - *fb_len = viafb_get_memsize(); - DEBUG_MSG(KERN_INFO "Get FB info from SR30!\n"); - DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base); - DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len); - return ; - } - - *fb_base = (unsigned int)pci_resource_start(pdev, 0); - *fb_len = get_fb_size_from_pci(); - DEBUG_MSG(KERN_INFO "Get FB info from PCI system!\n"); - DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base); - DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len); - - pci_dev_put(pdev); -} - -static int get_fb_size_from_pci(void) +int viafb_get_fb_size_from_pci(void) { unsigned long configid, deviceid, FBSize = 0; int VideoMemSize; diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 22786a5..1cd0648 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -931,17 +931,16 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, int vmode_index1, int hor_res1, int ver_res1, int video_bpp1); -void viafb_init_chip_info(void); +void viafb_init_chip_info(struct pci_dev *pdev, + const struct pci_device_id *pdi); void viafb_init_dac(int set_iga); int viafb_get_pixclock(int hres, int vres, int vmode_refresh); int viafb_get_refresh(int hres, int vres, u32 float_refresh); void viafb_update_device_setting(int hres, int vres, int bpp, int vmode_refresh, int flag); -void viafb_get_mmio_info(unsigned long *mmio_base, - unsigned long *mmio_len); +int viafb_get_fb_size_from_pci(void); void viafb_set_iga_path(void); void viafb_set_start_addr(void); -void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); #endif /* __HW_H__ */ diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 72387d4..3040dd9 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2104,7 +2104,8 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) remove_proc_entry("viafb", NULL); } -static int __devinit via_pci_probe(void) +static int __devinit via_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { unsigned long default_xres, default_yres; char *tmpc, *tmpm; @@ -2161,8 +2162,9 @@ static int __devinit via_pci_probe(void) if (rc) goto out_fb_release; - viafb_init_chip_info(); - viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize); + viafb_init_chip_info(pdev, ent); + viaparinfo->fbmem = pci_resource_start(pdev, 0); + viaparinfo->memsize = viafb_get_fb_size_from_pci(); viaparinfo->fbmem_free = viaparinfo->memsize; viaparinfo->fbmem_used = 0; viaparinfo->fbmem_virt = ioremap_nocache(viaparinfo->fbmem, @@ -2170,14 +2172,20 @@ static int __devinit via_pci_probe(void) viafbinfo->screen_base = (char *)viaparinfo->fbmem_virt; if (!viaparinfo->fbmem_virt) { - printk(KERN_INFO "ioremap failed\n"); + printk(KERN_ERR "ioremap of fbmem failed\n"); rc = -EIO; goto out_delete_i2c; } - viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len); + viaparinfo->mmio_base = pci_resource_start(pdev, 1); + viaparinfo->mmio_len = pci_resource_len(pdev, 1); viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base, viaparinfo->mmio_len); + if (!viaparinfo->io_virt) { + printk(KERN_ERR "ioremap of MMIO failed\n"); + rc = -EIO; + goto out_unmap_fbmem; + } viafbinfo->node = 0; viafbinfo->fbops = &viafb_ops; @@ -2284,7 +2292,8 @@ static int __devinit via_pci_probe(void) if (!viafbinfo1) { printk(KERN_ERR "allocate the second framebuffer struct error\n"); - goto out_delete_i2c; + rc = -ENOMEM; + goto out_unmap_mmio; } viaparinfo1 = viafbinfo1->par; memcpy(viaparinfo1, viaparinfo, viafb_par_length); @@ -2385,6 +2394,10 @@ out_dealloc_cmap: out_fb1_release: if (viafbinfo1) framebuffer_release(viafbinfo1); +out_unmap_mmio: + iounmap(viaparinfo->io_virt); +out_unmap_fbmem: + iounmap((void *)viaparinfo->fbmem_virt); out_delete_i2c: viafb_delete_i2c_buss(viaparinfo); out_fb_release: @@ -2392,7 +2405,7 @@ out_fb_release: return rc; } -static void __devexit via_pci_remove(void) +static void __devexit via_pci_remove(struct pci_dev *pdev) { DEBUG_MSG(KERN_INFO "via_pci_remove!\n"); fb_dealloc_cmap(&viafbinfo->cmap); @@ -2486,6 +2499,40 @@ static int __init viafb_setup(char *options) } #endif +static struct pci_device_id viafb_pci_table[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID), + .driver_data = UNICHROME_CLE266 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID), + .driver_data = UNICHROME_PM800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID), + .driver_data = UNICHROME_K400 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID), + .driver_data = UNICHROME_K800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID), + .driver_data = UNICHROME_CN700 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID), + .driver_data = UNICHROME_K8M890 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID), + .driver_data = UNICHROME_CX700 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID), + .driver_data = UNICHROME_P4M900 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID), + .driver_data = UNICHROME_CN750 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID), + .driver_data = UNICHROME_VX800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), + .driver_data = UNICHROME_VX855 }, + { } +}; +MODULE_DEVICE_TABLE(pci, viafb_pci_table); + +static struct pci_driver viafb_driver = { + .name = "viafb", + .id_table = viafb_pci_table, + .probe = via_pci_probe, + .remove = __devexit_p(via_pci_remove), +}; + static int __init viafb_init(void) { #ifndef MODULE @@ -2497,13 +2544,13 @@ static int __init viafb_init(void) printk(KERN_INFO "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", VERSION_MAJOR, VERSION_MINOR); - return via_pci_probe(); + return pci_register_driver(&viafb_driver); } static void __exit viafb_exit(void) { DEBUG_MSG(KERN_INFO "viafb_exit!\n"); - via_pci_remove(); + pci_unregister_driver(&viafb_driver); } static struct fb_ops viafb_ops = { -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:49:06
|
From: Harald Welte <la...@gn...> Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/viafbdev.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 3040dd9..7e8f2f6 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2128,7 +2128,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, * variables */ viafbinfo = framebuffer_alloc(viafb_par_length + 2 * lvds_length + - tmds_length + crt_length + chip_length, NULL); + tmds_length + crt_length + chip_length, + &pdev->dev); if (!viafbinfo) { printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); return -ENOMEM; -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:49:03
|
From: Harald Welte <la...@gn...> This patch adds support for a new VIA integrated graphics chipset, the VX855. Signed-off-by: HaraldWelte <Har...@vi...> --- drivers/video/via/chip.h | 3 + drivers/video/via/hw.c | 207 ++++++++++++++++++++++++++++-------------- drivers/video/via/hw.h | 14 +++ drivers/video/via/share.h | 98 ++++++++++++++++++++ drivers/video/via/viafbdev.c | 7 +- drivers/video/via/viamode.c | 55 +++++++++++ drivers/video/via/viamode.h | 2 + 7 files changed, 316 insertions(+), 70 deletions(-) diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index dde95ed..03e90cf 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h @@ -68,6 +68,9 @@ #define UNICHROME_VX800 11 #define UNICHROME_VX800_DID 0x1122 +#define UNICHROME_VX855 12 +#define UNICHROME_VX855_DID 0x5122 + /**************************************************/ /* Definition TMDS Trasmitter Information */ /**************************************************/ diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 59ddf09..b111b6c 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -33,6 +33,7 @@ static const struct pci_device_id_info pciidlist[] = { {PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, UNICHROME_P4M900}, {PCI_VIA_VENDOR_ID, UNICHROME_CN750_DID, UNICHROME_CN750}, {PCI_VIA_VENDOR_ID, UNICHROME_VX800_DID, UNICHROME_VX800}, + {PCI_VIA_VENDOR_ID, UNICHROME_VX855_DID, UNICHROME_VX855}, {0, 0, 0} }; @@ -44,102 +45,142 @@ struct offset offset_reg = { }; static struct pll_map pll_value[] = { - {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, CX700_25_175M}, - {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, CX700_29_581M}, - {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, CX700_26_880M}, - {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, CX700_31_490M}, - {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, CX700_31_500M}, - {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, CX700_31_728M}, - {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, CX700_32_668M}, - {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, CX700_36_000M}, - {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, CX700_40_000M}, - {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, CX700_41_291M}, - {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, CX700_43_163M}, - {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, CX700_45_250M}, - {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, CX700_46_000M}, - {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, CX700_46_996M}, - {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, CX700_48_000M}, - {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, CX700_48_875M}, - {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, CX700_49_500M}, - {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, CX700_52_406M}, - {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, CX700_52_977M}, - {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, CX700_56_250M}, - {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, CX700_60_466M}, - {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, CX700_61_500M}, - {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, CX700_65_000M}, - {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, CX700_65_178M}, - {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, CX700_66_750M}, - {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, CX700_68_179M}, - {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, CX700_69_924M}, - {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, CX700_70_159M}, - {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, CX700_72_000M}, - {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, CX700_78_750M}, - {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, CX700_80_136M}, - {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, CX700_83_375M}, - {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, CX700_83_950M}, - {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, CX700_84_750M}, - {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, CX700_85_860M}, - {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, CX700_88_750M}, - {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, CX700_94_500M}, - {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, CX700_97_750M}, + {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, + CX700_25_175M, VX855_25_175M}, + {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, + CX700_29_581M, VX855_29_581M}, + {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, + CX700_26_880M, VX855_26_880M}, + {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, + CX700_31_490M, VX855_31_490M}, + {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, + CX700_31_500M, VX855_31_500M}, + {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, + CX700_31_728M, VX855_31_728M}, + {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, + CX700_32_668M, VX855_32_668M}, + {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, + CX700_36_000M, VX855_36_000M}, + {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, + CX700_40_000M, VX855_40_000M}, + {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, + CX700_41_291M, VX855_41_291M}, + {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, + CX700_43_163M, VX855_43_163M}, + {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, + CX700_45_250M, VX855_45_250M}, + {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, + CX700_46_000M, VX855_46_000M}, + {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, + CX700_46_996M, VX855_46_996M}, + {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, + CX700_48_000M, VX855_48_000M}, + {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, + CX700_48_875M, VX855_48_875M}, + {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, + CX700_49_500M, VX855_49_500M}, + {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, + CX700_52_406M, VX855_52_406M}, + {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, + CX700_52_977M, VX855_52_977M}, + {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, + CX700_56_250M, VX855_56_250M}, + {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, + CX700_60_466M, VX855_60_466M}, + {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, + CX700_61_500M, VX855_61_500M}, + {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, + CX700_65_000M, VX855_65_000M}, + {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, + CX700_65_178M, VX855_65_178M}, + {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, + CX700_66_750M, VX855_66_750M}, + {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, + CX700_68_179M, VX855_68_179M}, + {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, + CX700_69_924M, VX855_69_924M}, + {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, + CX700_70_159M, VX855_70_159M}, + {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, + CX700_72_000M, VX855_72_000M}, + {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, + CX700_78_750M, VX855_78_750M}, + {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, + CX700_80_136M, VX855_80_136M}, + {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, + CX700_83_375M, VX855_83_375M}, + {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, + CX700_83_950M, VX855_83_950M}, + {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, + CX700_84_750M, VX855_84_750M}, + {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, + CX700_85_860M, VX855_85_860M}, + {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, + CX700_88_750M, VX855_88_750M}, + {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, + CX700_94_500M, VX855_94_500M}, + {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, + CX700_97_750M, VX855_97_750M}, {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M, - CX700_101_000M}, + CX700_101_000M, VX855_101_000M}, {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M, - CX700_106_500M}, + CX700_106_500M, VX855_106_500M}, {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M, - CX700_108_000M}, + CX700_108_000M, VX855_108_000M}, {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M, - CX700_113_309M}, + CX700_113_309M, VX855_113_309M}, {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M, - CX700_118_840M}, + CX700_118_840M, VX855_118_840M}, {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M, - CX700_119_000M}, + CX700_119_000M, VX855_119_000M}, {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M, - CX700_121_750M}, + CX700_121_750M, 0}, {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M, - CX700_125_104M}, + CX700_125_104M, 0}, {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M, - CX700_133_308M}, + CX700_133_308M, 0}, {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M, - CX700_135_000M}, + CX700_135_000M, VX855_135_000M}, {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M, - CX700_136_700M}, + CX700_136_700M, VX855_136_700M}, {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M, - CX700_138_400M}, + CX700_138_400M, VX855_138_400M}, {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M, - CX700_146_760M}, + CX700_146_760M, VX855_146_760M}, {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M, - CX700_153_920M}, + CX700_153_920M, VX855_153_920M}, {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M, - CX700_156_000M}, + CX700_156_000M, VX855_156_000M}, {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M, - CX700_157_500M}, + CX700_157_500M, VX855_157_500M}, {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M, - CX700_162_000M}, + CX700_162_000M, VX855_162_000M}, {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M, - CX700_187_000M}, + CX700_187_000M, VX855_187_000M}, {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M, - CX700_193_295M}, + CX700_193_295M, VX855_193_295M}, {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M, - CX700_202_500M}, + CX700_202_500M, VX855_202_500M}, {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M, - CX700_204_000M}, + CX700_204_000M, VX855_204_000M}, {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M, - CX700_218_500M}, + CX700_218_500M, VX855_218_500M}, {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M, - CX700_234_000M}, + CX700_234_000M, VX855_234_000M}, {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M, - CX700_267_250M}, + CX700_267_250M, VX855_267_250M}, {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M, - CX700_297_500M}, - {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, CX700_74_481M}, + CX700_297_500M, VX855_297_500M}, + {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, + CX700_74_481M, VX855_74_481M}, {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M, - CX700_172_798M}, + CX700_172_798M, VX855_172_798M}, {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M, - CX700_122_614M}, - {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, CX700_74_270M}, + CX700_122_614M, VX855_122_614M}, + {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, + CX700_74_270M, 0}, {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M, - CX700_148_500M} + CX700_148_500M, VX855_148_500M} }; static struct fifo_depth_select display_fifo_depth_reg = { @@ -1277,6 +1318,15 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active) VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; } + if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) { + iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH; + iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD; + iga1_fifo_high_threshold = + VX855_IGA1_FIFO_HIGH_THRESHOLD; + iga1_display_queue_expire_num = + VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; + } + /* Set Display FIFO Depath Select */ reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth); viafb_load_reg_num = @@ -1408,6 +1458,15 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active) VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; } + if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) { + iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH; + iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD; + iga2_fifo_high_threshold = + VX855_IGA2_FIFO_HIGH_THRESHOLD; + iga2_display_queue_expire_num = + VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; + } + if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { /* Set Display FIFO Depath Select */ reg_value = @@ -1496,6 +1555,8 @@ u32 viafb_get_clk_value(int clk) case UNICHROME_P4M900: case UNICHROME_VX800: return pll_value[i].cx700_pll; + case UNICHROME_VX855: + return pll_value[i].vx855_pll; } } } @@ -1529,6 +1590,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) case UNICHROME_P4M890: case UNICHROME_P4M900: case UNICHROME_VX800: + case UNICHROME_VX855: viafb_write_reg(SR44, VIASR, CLK / 0x10000); DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000); viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100); @@ -1557,6 +1619,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) case UNICHROME_P4M890: case UNICHROME_P4M900: case UNICHROME_VX800: + case UNICHROME_VX855: viafb_write_reg(SR4A, VIASR, CLK / 0x10000); viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100); viafb_write_reg(SR4C, VIASR, CLK % 0x100); @@ -2276,7 +2339,10 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, case UNICHROME_VX800: viafb_write_regx(VX800_ModeXregs, NUM_TOTAL_VX800_ModeXregs); + break; + case UNICHROME_VX855: + viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs); break; } @@ -2657,6 +2723,7 @@ static int get_fb_size_from_pci(void) case P4M890_FUNCTION3: case P4M900_FUNCTION3: case VX800_FUNCTION3: + case VX855_FUNCTION3: /*case CN750_FUNCTION3: */ outl(configid + 0xA0, (unsigned long)0xCF8); FBSize = inl((unsigned long)0xCFC); @@ -2720,6 +2787,10 @@ static int get_fb_size_from_pci(void) VideoMemSize = (256 << 20); /*256M */ break; + case 0x00007000: /* Only on VX855/875 */ + VideoMemSize = (512 << 20); /*512M */ + break; + default: VideoMemSize = (32 << 20); /*32M */ break; diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 6ff38fa..22786a5 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -335,6 +335,17 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */ /* location: {CR94,0,6} */ #define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128 +/* For VT3409 */ +#define VX855_IGA1_FIFO_MAX_DEPTH 400 +#define VX855_IGA1_FIFO_THRESHOLD 320 +#define VX855_IGA1_FIFO_HIGH_THRESHOLD 320 +#define VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 160 + +#define VX855_IGA2_FIFO_MAX_DEPTH 200 +#define VX855_IGA2_FIFO_THRESHOLD 160 +#define VX855_IGA2_FIFO_HIGH_THRESHOLD 160 +#define VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 320 + #define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1 #define IGA1_FIFO_THRESHOLD_REG_NUM 2 #define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2 @@ -716,6 +727,7 @@ struct pll_map { u32 cle266_pll; u32 k800_pll; u32 cx700_pll; + u32 vx855_pll; }; struct rgbLUT { @@ -860,6 +872,8 @@ struct iga2_crtc_timing { #define P4M900_FUNCTION3 0x3364 /* VT3353 chipset*/ #define VX800_FUNCTION3 0x3353 +/* VT3409 chipset*/ +#define VX855_FUNCTION3 0x3409 #define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value) diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 2e1254d..1eacd1c 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -167,6 +167,10 @@ #define SR4B 0x4B #define SR4C 0x4C #define SR52 0x52 +#define SR57 0x57 +#define SR58 0x58 +#define SR59 0x59 +#define SR5D 0x5D #define SR5E 0x5E #define SR65 0x65 @@ -966,6 +970,100 @@ #define CX700_297_500M 0x00CE0403 #define CX700_122_614M 0x00870802 +/* PLL for VX855 */ +#define VX855_22_000M 0x007B1005 +#define VX855_25_175M 0x008D1005 +#define VX855_26_719M 0x00961005 +#define VX855_26_880M 0x00961005 +#define VX855_27_000M 0x00971005 +#define VX855_29_581M 0x00A51005 +#define VX855_29_829M 0x00641003 +#define VX855_31_490M 0x00B01005 +#define VX855_31_500M 0x00B01005 +#define VX855_31_728M 0x008E1004 +#define VX855_32_668M 0x00921004 +#define VX855_36_000M 0x00A11004 +#define VX855_40_000M 0x00700C05 +#define VX855_41_291M 0x00730C05 +#define VX855_43_163M 0x00790C05 +#define VX855_45_250M 0x007F0C05 /* 45.46MHz */ +#define VX855_46_000M 0x00670C04 +#define VX855_46_996M 0x00690C04 +#define VX855_48_000M 0x00860C05 +#define VX855_48_875M 0x00890C05 +#define VX855_49_500M 0x00530C03 +#define VX855_52_406M 0x00580C03 +#define VX855_52_977M 0x00940C05 +#define VX855_56_250M 0x009D0C05 +#define VX855_60_466M 0x00A90C05 +#define VX855_61_500M 0x00AC0C05 +#define VX855_65_000M 0x006D0C03 +#define VX855_65_178M 0x00B60C05 +#define VX855_66_750M 0x00700C03 /*67.116MHz */ +#define VX855_67_295M 0x00BC0C05 +#define VX855_68_179M 0x00BF0C05 +#define VX855_68_369M 0x00BF0C05 +#define VX855_69_924M 0x00C30C05 +#define VX855_70_159M 0x00C30C05 +#define VX855_72_000M 0x00A10C04 +#define VX855_73_023M 0x00CC0C05 +#define VX855_74_481M 0x00D10C05 +#define VX855_78_750M 0x006E0805 +#define VX855_79_466M 0x006F0805 +#define VX855_80_136M 0x00700805 +#define VX855_81_627M 0x00720805 +#define VX855_83_375M 0x00750805 +#define VX855_83_527M 0x00750805 +#define VX855_83_950M 0x00750805 +#define VX855_84_537M 0x00760805 +#define VX855_84_750M 0x00760805 /* 84.537Mhz */ +#define VX855_85_500M 0x00760805 /* 85.909080 MHz*/ +#define VX855_85_860M 0x00760805 +#define VX855_85_909M 0x00760805 +#define VX855_88_750M 0x007C0805 +#define VX855_89_489M 0x007D0805 +#define VX855_94_500M 0x00840805 +#define VX855_96_648M 0x00870805 +#define VX855_97_750M 0x00890805 +#define VX855_101_000M 0x008D0805 +#define VX855_106_500M 0x00950805 +#define VX855_108_000M 0x00970805 +#define VX855_110_125M 0x00990805 +#define VX855_112_000M 0x009D0805 +#define VX855_113_309M 0x009F0805 +#define VX855_115_000M 0x00A10805 +#define VX855_118_840M 0x00A60805 +#define VX855_119_000M 0x00A70805 +#define VX855_121_750M 0x00AA0805 /* 121.704MHz */ +#define VX855_122_614M 0x00AC0805 +#define VX855_126_266M 0x00B10805 +#define VX855_130_250M 0x00B60805 /* 130.250 */ +#define VX855_135_000M 0x00BD0805 +#define VX855_136_700M 0x00BF0805 +#define VX855_137_750M 0x00C10805 +#define VX855_138_400M 0x00C20805 +#define VX855_144_300M 0x00CA0805 +#define VX855_146_760M 0x00CE0805 +#define VX855_148_500M 0x00D00805 +#define VX855_153_920M 0x00540402 +#define VX855_156_000M 0x006C0405 +#define VX855_156_867M 0x006E0405 +#define VX855_157_500M 0x006E0405 +#define VX855_162_000M 0x00710405 +#define VX855_172_798M 0x00790405 +#define VX855_187_000M 0x00830405 +#define VX855_193_295M 0x00870405 +#define VX855_202_500M 0x008E0405 +#define VX855_204_000M 0x008F0405 +#define VX855_218_500M 0x00990405 +#define VX855_229_500M 0x00A10405 +#define VX855_234_000M 0x00A40405 +#define VX855_267_250M 0x00BB0405 +#define VX855_297_500M 0x00D00405 +#define VX855_339_500M 0x00770005 +#define VX855_340_772M 0x00770005 + + /* Definition CRTC Timing Index */ #define H_TOTAL_INDEX 0 #define H_ADDR_INDEX 1 diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index a0fec29..02e7a72 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -218,7 +218,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var, if (!info->par) return -1; p_viafb_par = (struct viafb_par *)info->par; - if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800) + if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800 || + p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX855) var->accel_flags = 0; return 0; @@ -1162,8 +1163,10 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) if ((p_viafb_par->chip_info->gfx_chip_name == UNICHROME_CX700) || + (p_viafb_par->chip_info->gfx_chip_name == + UNICHROME_VX800) || ((p_viafb_par->chip_info->gfx_chip_name == - UNICHROME_VX800))) { + UNICHROME_VX855))) { bg_col = (((info->cmap.red)[viacursor.image.bg_color] & 0xFFC0) << 14) | diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 6dcf583..209c3af 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -390,6 +390,61 @@ struct io_reg VX800_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, {VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */ }; +struct io_reg VX855_ModeXregs[] = { +{VIASR, SR10, 0xFF, 0x01}, +{VIASR, SR15, 0x02, 0x02}, +{VIASR, SR16, 0xBF, 0x08}, +{VIASR, SR17, 0xFF, 0x1F}, +{VIASR, SR18, 0xFF, 0x4E}, +{VIASR, SR1A, 0xFB, 0x08}, +{VIASR, SR1B, 0xFF, 0xF0}, +{VIASR, SR1E, 0x07, 0x01}, +{VIASR, SR2A, 0xF0, 0x00}, +{VIASR, SR58, 0xFF, 0x00}, +{VIASR, SR59, 0xFF, 0x00}, +{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */ +{VIACR, CR09, 0xFF, 0x00}, /* Initial CR09=0*/ +{VIACR, CR11, 0x8F, 0x00}, /* IGA1 initial Vertical end */ +{VIACR, CR17, 0x7F, 0x00}, /* IGA1 CRT Mode control init */ +{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */ +{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */ +{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */ +{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ +{VIACR, CR32, 0xFF, 0x00}, +{VIACR, CR33, 0x7F, 0x00}, +{VIACR, CR34, 0xFF, 0x00}, +{VIACR, CR35, 0xFF, 0x00}, +{VIACR, CR36, 0x08, 0x00}, +{VIACR, CR69, 0xFF, 0x00}, +{VIACR, CR6A, 0xFD, 0x60}, +{VIACR, CR6B, 0xFF, 0x00}, +{VIACR, CR6C, 0xFF, 0x00}, +{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ +{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ +{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ +{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ +{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ +{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ +{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ +{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ +{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ +{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ +{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ +{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ +{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ +{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ +{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ +{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ +{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ +{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */ +{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */ +{VIACR, CR96, 0xFF, 0x00}, +{VIACR, CR97, 0xFF, 0x00}, +{VIACR, CR99, 0xFF, 0x00}, +{VIACR, CR9B, 0xFF, 0x00}, +{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */ +}; + /* Video Mode Table */ /* Common Setting for Video Mode */ struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00}, diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index 1a5de50..3636694 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h @@ -57,6 +57,7 @@ struct res_map_refresh { #define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs) #define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs) #define NUM_TOTAL_VX800_ModeXregs ARRAY_SIZE(VX800_ModeXregs) +#define NUM_TOTAL_VX855_ModeXregs ARRAY_SIZE(VX855_ModeXregs) #define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs) #define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table) #define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes) @@ -170,6 +171,7 @@ extern struct io_reg CN700_ModeXregs[66]; extern struct io_reg KM400_ModeXregs[55]; extern struct io_reg CX700_ModeXregs[58]; extern struct io_reg VX800_ModeXregs[58]; +extern struct io_reg VX855_ModeXregs[52]; extern struct io_reg CLE266_ModeXregs[32]; extern struct io_reg PM1024x768[2]; extern struct patch_table res_patch_table[1]; -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:48:57
|
From: Harald Welte <la...@gn...> This will help us for the upcoming support for 2D acceleration using the M1 engine. Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/chip.h | 8 ++++++++ drivers/video/via/hw.c | 15 +++++++++++++++ drivers/video/via/viafbdev.c | 3 +-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index 03e90cf..7f4bf73 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h @@ -122,10 +122,18 @@ struct lvds_chip_information { int i2c_port; }; +/* The type of 2D engine */ +enum via_2d_engine { + VIA_2D_ENG_H2, + VIA_2D_ENG_H5, + VIA_2D_ENG_M1, +}; + struct chip_information { int gfx_chip_name; int gfx_chip_revision; int chip_on_slot; + enum via_2d_engine twod_engine; struct tmds_chip_information tmds_chip_info; struct lvds_chip_information lvds_chip_info; struct lvds_chip_information lvds_chip_info2; diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index e06d6b7..e14b852 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -2092,6 +2092,21 @@ static void init_gfx_chip_info(struct pci_dev *pdev, CX700_REVISION_700; } } + + /* Determine which 2D engine we have */ + switch (viaparinfo->chip_info->gfx_chip_name) { + case UNICHROME_VX800: + case UNICHROME_VX855: + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1; + break; + case UNICHROME_K8M890: + case UNICHROME_P4M900: + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5; + break; + default: + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2; + break; + } } static void init_tmds_chip_info(void) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 859827b..d6a38ca 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -214,8 +214,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var, if (!info->par) return -1; p_viafb_par = (struct viafb_par *)info->par; - if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800 || - p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX855) + if (p_viafb_par->chip_info->twod_engine == VIA_2D_ENG_M1) var->accel_flags = 0; return 0; -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:48:50
|
From: Harald Welte <la...@gn...> This patch makes fixes a bug in viafb on x86_64 builds (e.g. for VIA Nano CPU). You cannot make the assumption that sizeof(unsigned int) == sizeof(unsigned long), so the parsing of the default mode (640x480) fails, leading to a division by zero during insmod of the driver. Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/viafbdev.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index e327b84..a0fec29 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2103,7 +2103,7 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) static int __devinit via_pci_probe(void) { - unsigned int default_xres, default_yres; + unsigned long default_xres, default_yres; char *tmpc, *tmpm; char *tmpc_sec, *tmpm_sec; int vmode_index; @@ -2196,8 +2196,8 @@ static int __devinit via_pci_probe(void) viafb_FB_MM = viaparinfo->fbmem_virt; tmpm = viafb_mode; tmpc = strsep(&tmpm, "x"); - strict_strtoul(tmpc, 0, (unsigned long *)&default_xres); - strict_strtoul(tmpm, 0, (unsigned long *)&default_yres); + strict_strtoul(tmpc, 0, &default_xres); + strict_strtoul(tmpm, 0, &default_yres); vmode_index = viafb_get_mode_index(default_xres, default_yres, 0); DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:48:42
|
From: Harald Welte <la...@gn...> Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/viafbdev.c | 45 +++++++++++++++++++++-------------------- 1 files changed, 23 insertions(+), 22 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 00f58c8..980eab8 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -20,6 +20,7 @@ */ #include <linux/module.h> +#include <linux/stat.h> #define _MASTER_FILE #include "global.h" @@ -2570,82 +2571,82 @@ module_init(viafb_init); module_exit(viafb_exit); #ifdef MODULE -module_param(viafb_memsize, int, 0); +module_param(viafb_memsize, int, S_IRUSR); -module_param(viafb_mode, charp, 0); +module_param(viafb_mode, charp, S_IRUSR); MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); -module_param(viafb_mode1, charp, 0); +module_param(viafb_mode1, charp, S_IRUSR); MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)"); -module_param(viafb_bpp, int, 0); +module_param(viafb_bpp, int, S_IRUSR); MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)"); -module_param(viafb_bpp1, int, 0); +module_param(viafb_bpp1, int, S_IRUSR); MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)"); -module_param(viafb_refresh, int, 0); +module_param(viafb_refresh, int, S_IRUSR); MODULE_PARM_DESC(viafb_refresh, "Set CRT viafb_refresh rate (default = 60)"); -module_param(viafb_refresh1, int, 0); +module_param(viafb_refresh1, int, S_IRUSR); MODULE_PARM_DESC(viafb_refresh1, "Set CRT refresh rate (default = 60)"); -module_param(viafb_lcd_panel_id, int, 0); +module_param(viafb_lcd_panel_id, int, S_IRUSR); MODULE_PARM_DESC(viafb_lcd_panel_id, "Set Flat Panel type(Default=1024x768)"); -module_param(viafb_lcd_dsp_method, int, 0); +module_param(viafb_lcd_dsp_method, int, S_IRUSR); MODULE_PARM_DESC(viafb_lcd_dsp_method, "Set Flat Panel display scaling method.(Default=Expandsion)"); -module_param(viafb_SAMM_ON, int, 0); +module_param(viafb_SAMM_ON, int, S_IRUSR); MODULE_PARM_DESC(viafb_SAMM_ON, "Turn on/off flag of SAMM(Default=OFF)"); -module_param(viafb_accel, int, 0); +module_param(viafb_accel, int, S_IRUSR); MODULE_PARM_DESC(viafb_accel, "Set 2D Hardware Acceleration.(Default = OFF)"); -module_param(viafb_active_dev, charp, 0); +module_param(viafb_active_dev, charp, S_IRUSR); MODULE_PARM_DESC(viafb_active_dev, "Specify active devices."); -module_param(viafb_display_hardware_layout, int, 0); +module_param(viafb_display_hardware_layout, int, S_IRUSR); MODULE_PARM_DESC(viafb_display_hardware_layout, "Display Hardware Layout (LCD Only, DVI Only...,etc)"); -module_param(viafb_second_size, int, 0); +module_param(viafb_second_size, int, S_IRUSR); MODULE_PARM_DESC(viafb_second_size, "Set secondary device memory size"); -module_param(viafb_dual_fb, int, 0); +module_param(viafb_dual_fb, int, S_IRUSR); MODULE_PARM_DESC(viafb_dual_fb, "Turn on/off flag of dual framebuffer devices.(Default = OFF)"); -module_param(viafb_platform_epia_dvi, int, 0); +module_param(viafb_platform_epia_dvi, int, S_IRUSR); MODULE_PARM_DESC(viafb_platform_epia_dvi, "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)"); -module_param(viafb_device_lcd_dualedge, int, 0); +module_param(viafb_device_lcd_dualedge, int, S_IRUSR); MODULE_PARM_DESC(viafb_device_lcd_dualedge, "Turn on/off flag of dual edge panel.(Default = OFF)"); -module_param(viafb_bus_width, int, 0); +module_param(viafb_bus_width, int, S_IRUSR); MODULE_PARM_DESC(viafb_bus_width, "Set bus width of panel.(Default = 12)"); -module_param(viafb_lcd_mode, int, 0); +module_param(viafb_lcd_mode, int, S_IRUSR); MODULE_PARM_DESC(viafb_lcd_mode, "Set Flat Panel mode(Default=OPENLDI)"); -module_param(viafb_video_dev, charp, 0); +module_param(viafb_video_dev, charp, S_IRUSR); MODULE_PARM_DESC(viafb_video_dev, "Specify video devices."); -module_param(viafb_lcd_port, charp, 0); +module_param(viafb_lcd_port, charp, S_IRUSR); MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port."); -module_param(viafb_dvi_port, charp, 0); +module_param(viafb_dvi_port, charp, S_IRUSR); MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port."); MODULE_LICENSE("GPL"); -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:48:42
|
From: Harald Welte <la...@gn...> The VX800/VX820 and the VX855/VX875 chipsets have a different 2D acceleration engine called "M1". The M1 engine has some subtle (and some not-so-subtle) differences to the previous engines, so support for accelerated framebuffer on those chipsets was disabled so far. This patch adds full support for the M1 engine to viafb. Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/accel.c | 72 ++++++++++++++++++++++++++++++++++++----- drivers/video/via/accel.h | 40 +++++++++++++++++++++++ drivers/video/via/viafbdev.c | 2 - 3 files changed, 103 insertions(+), 11 deletions(-) diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index b3a414e..a4b66be 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -20,8 +20,34 @@ */ #include "global.h" +/* Somehow, the M1 engine has the registers in slightly different + * locations than previous 2D acceleration engines */ +static u_int8_t via_m1_eng_reg[] = { + [VIA_REG_GECMD] = VIA_REG_GECMD_M1, + [VIA_REG_GEMODE] = VIA_REG_GEMODE_M1, + [VIA_REG_SRCPOS] = VIA_REG_SRCPOS_M1, + [VIA_REG_DSTPOS] = VIA_REG_DSTPOS_M1, + [VIA_REG_DIMENSION] = VIA_REG_DIMENSION_M1, + [VIA_REG_PATADDR] = VIA_REG_PATADDR_M1, + [VIA_REG_FGCOLOR] = VIA_REG_FGCOLOR_M1, + [VIA_REG_BGCOLOR] = VIA_REG_BGCOLOR_M1, + [VIA_REG_CLIPTL] = VIA_REG_CLIPTL_M1, + [VIA_REG_CLIPBR] = VIA_REG_CLIPBR_M1, + [VIA_REG_OFFSET] = VIA_REG_OFFSET_M1, + [VIA_REG_KEYCONTROL] = VIA_REG_KEYCONTROL_M1, + [VIA_REG_SRCBASE] = VIA_REG_SRCBASE_M1, + [VIA_REG_DSTBASE] = VIA_REG_DSTBASE_M1, + [VIA_REG_PITCH] = VIA_REG_PITCH_M1, + [VIA_REG_MONOPAT0] = VIA_REG_MONOPAT0_M1, + [VIA_REG_MONOPAT1] = VIA_REG_MONOPAT1_M1, +}; + void viafb_2d_writel(u_int32_t val, u_int32_t reg) { + if (viaparinfo->chip_info->twod_engine == VIA_2D_ENG_M1 && + reg < ARRAY_SIZE(via_m1_eng_reg)) + reg = via_m1_eng_reg[reg]; + writel(val, viaparinfo->io_virt + reg); } @@ -41,16 +67,26 @@ void viafb_init_2d_engine(void) { u32 dwVQStartAddr, dwVQEndAddr; u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; - int i; + int i, highest_reg; /* init 2D engine regs to reset 2D engine */ - for (i = 0; i <= 0x40; i+= 4) + switch (viaparinfo->chip_info->twod_engine) { + case VIA_2D_ENG_M1: + highest_reg = 0x5c; + break; + default: + highest_reg = 0x40; + break; + } + for (i = 0; i <= highest_reg; i+= 4) writel(0x0, viaparinfo->io_virt + i); /* Init AGP and VQ regs */ switch (viaparinfo->chip_info->gfx_chip_name) { case UNICHROME_K8M890: case UNICHROME_P4M900: + case UNICHROME_VX800: + case UNICHROME_VX855: writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET); writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); @@ -85,6 +121,8 @@ void viafb_init_2d_engine(void) switch (viaparinfo->chip_info->gfx_chip_name) { case UNICHROME_K8M890: case UNICHROME_P4M900: + case UNICHROME_VX800: + case UNICHROME_VX855: dwVQStartL |= 0x20000000; dwVQEndL |= 0x20000000; dwVQStartEndH |= 0x20000000; @@ -97,6 +135,8 @@ void viafb_init_2d_engine(void) switch (viaparinfo->chip_info->gfx_chip_name) { case UNICHROME_K8M890: case UNICHROME_P4M900: + case UNICHROME_VX800: + case UNICHROME_VX855: writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET); writel(dwVQStartEndH, @@ -162,6 +202,8 @@ void viafb_init_2d_engine(void) switch (viaparinfo->chip_info->gfx_chip_name) { case UNICHROME_K8M890: case UNICHROME_P4M900: + case UNICHROME_VX800: + case UNICHROME_VX855: writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET); writel(0x74301000, @@ -216,7 +258,8 @@ void viafb_set_2d_mode(struct fb_info *info) /* Set source and destination pitch (128bit aligned) */ pitch = (viaparinfo->hres * viaparinfo->bpp >> 3) >> 3; pitch_reg = pitch | (pitch << 16); - pitch_reg |= VIA_PITCH_ENABLE; + if (viaparinfo->chip_info->twod_engine != VIA_2D_ENG_M1) + pitch_reg |= VIA_PITCH_ENABLE; viafb_2d_writel(pitch_reg, VIA_REG_PITCH); } @@ -259,15 +302,26 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status) int viafb_wait_engine_idle(void) { int loop = 0; + u_int32_t status_mask; - while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & - VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { - loop++; - cpu_relax(); + switch (viaparinfo->chip_info->twod_engine) { + case VIA_2D_ENG_H5: + case VIA_2D_ENG_M1: + status_mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 | + VIA_3D_ENG_BUSY_M1; + break; + default: + while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & + VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { + loop++; + cpu_relax(); + } + status_mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | + VIA_3D_ENG_BUSY; + break; } - while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & - (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && + while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & status_mask) && (loop < MAXLOOP)) { loop++; cpu_relax(); diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h index 5081ac2..9a39ed1 100644 --- a/drivers/video/via/accel.h +++ b/drivers/video/via/accel.h @@ -67,6 +67,34 @@ /* from 0x100 to 0x1ff */ #define VIA_REG_COLORPAT 0x100 +/* defines for VIA 2D registers for vt3353/3409 (M1 engine)*/ +#define VIA_REG_GECMD_M1 0x000 +#define VIA_REG_GEMODE_M1 0x004 +#define VIA_REG_GESTATUS_M1 0x004 /* as same as VIA_REG_GEMODE */ +#define VIA_REG_PITCH_M1 0x008 /* pitch of src and dst */ +#define VIA_REG_DIMENSION_M1 0x00C /* width and height */ +#define VIA_REG_DSTPOS_M1 0x010 +#define VIA_REG_LINE_XY_M1 0x010 +#define VIA_REG_DSTBASE_M1 0x014 +#define VIA_REG_SRCPOS_M1 0x018 +#define VIA_REG_LINE_K1K2_M1 0x018 +#define VIA_REG_SRCBASE_M1 0x01C +#define VIA_REG_PATADDR_M1 0x020 +#define VIA_REG_MONOPAT0_M1 0x024 +#define VIA_REG_MONOPAT1_M1 0x028 +#define VIA_REG_OFFSET_M1 0x02C +#define VIA_REG_LINE_ERROR_M1 0x02C +#define VIA_REG_CLIPTL_M1 0x040 /* top and left of clipping */ +#define VIA_REG_CLIPBR_M1 0x044 /* bottom and right of clipping */ +#define VIA_REG_KEYCONTROL_M1 0x048 /* color key control */ +#define VIA_REG_FGCOLOR_M1 0x04C +#define VIA_REG_DSTCOLORKEY_M1 0x04C /* as same as VIA_REG_FG */ +#define VIA_REG_BGCOLOR_M1 0x050 +#define VIA_REG_SRCCOLORKEY_M1 0x050 /* as same as VIA_REG_BG */ +#define VIA_REG_MONOPATFGC_M1 0x058 /* Add BG color of Pattern. */ +#define VIA_REG_MONOPATBGC_M1 0x05C /* Add FG color of Pattern. */ +#define VIA_REG_COLORPAT_M1 0x100 /* from 0x100 to 0x1ff */ + /* VIA_REG_PITCH(0x38): Pitch Setting */ #define VIA_PITCH_ENABLE 0x80000000 @@ -157,6 +185,18 @@ /* Virtual Queue is busy */ #define VIA_VR_QUEUE_BUSY 0x00020000 +/* VIA_REG_STATUS(0x400): Engine Status for H5 */ +#define VIA_CMD_RGTR_BUSY_H5 0x00000010 /* Command Regulator is busy */ +#define VIA_2D_ENG_BUSY_H5 0x00000002 /* 2D Engine is busy */ +#define VIA_3D_ENG_BUSY_H5 0x00001FE1 /* 3D Engine is busy */ +#define VIA_VR_QUEUE_BUSY_H5 0x00000004 /* Virtual Queue is busy */ + +/* VIA_REG_STATUS(0x400): Engine Status for VT3353/3409 */ +#define VIA_CMD_RGTR_BUSY_M1 0x00000010 /* Command Regulator is busy */ +#define VIA_2D_ENG_BUSY_M1 0x00000002 /* 2D Engine is busy */ +#define VIA_3D_ENG_BUSY_M1 0x00001FE1 /* 3D Engine is busy */ +#define VIA_VR_QUEUE_BUSY_M1 0x00000004 /* Virtual Queue is busy */ + #define MAXLOOP 0xFFFFFF void viafb_2d_writel(u_int32_t val, u_int32_t reg); diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index d6a38ca..3a22a3a 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -214,8 +214,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, if (!info->par) return -1; p_viafb_par = (struct viafb_par *)info->par; - if (p_viafb_par->chip_info->twod_engine == VIA_2D_ENG_M1) - var->accel_flags = 0; return 0; } -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:48:35
|
From: Harald Welte <la...@gn...> There are four parts of the viafb code who initialize the bigtblit screen base and pitch, some of them actually broken. This patch unifies them in one function called viafb_set_2d_mode() which replaces and enhances the old function to just set the bpp. Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/accel.c | 35 ++++++++++++----------- drivers/video/via/accel.h | 2 +- drivers/video/via/viafbdev.c | 62 +++++------------------------------------- 3 files changed, 26 insertions(+), 73 deletions(-) diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 45c54bf..4a1183f 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -191,26 +191,18 @@ void viafb_init_2d_engine(void) } } - viafb_set_2d_color_depth(viaparinfo->bpp); - - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); - - writel(VIA_PITCH_ENABLE | - (((viaparinfo->hres * - viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres * - viaparinfo-> - bpp >> 3) >> 3) << 16)), - viaparinfo->io_virt + VIA_REG_PITCH); + viafb_set_2d_mode(viafbinfo); } -void viafb_set_2d_color_depth(int bpp) +/* Set the mode-specific parameters for the 2D acceleration, such as + * BPP, source and destination base, as well as pitch */ +void viafb_set_2d_mode(struct fb_info *info) { - u32 dwGEMode; + u32 dwGEMode, pitch, pitch_reg, base; + /* Set BPP */ dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF; - - switch (bpp) { + switch (viaparinfo->bpp) { case 16: dwGEMode |= VIA_GEM_16bpp; break; @@ -221,9 +213,18 @@ void viafb_set_2d_color_depth(int bpp) dwGEMode |= VIA_GEM_8bpp; break; } - - /* Set BPP and Pitch */ writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE); + + /* Set source and destination base */ + base = ((void *)info->screen_base - viafb_FB_MM); + writel(base >> 3, viaparinfo->io_virt + VIA_REG_SRCBASE); + writel(base >> 3, viaparinfo->io_virt + VIA_REG_DSTBASE); + + /* Set source and destination pitch (128bit aligned) */ + pitch = (viaparinfo->hres * viaparinfo->bpp >> 3) >> 3; + pitch_reg = pitch | (pitch << 16); + pitch_reg |= VIA_PITCH_ENABLE; + writel(pitch_reg, viaparinfo->io_virt + VIA_REG_PITCH); } void viafb_hw_cursor_init(void) diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h index 29bf854..bef3134 100644 --- a/drivers/video/via/accel.h +++ b/drivers/video/via/accel.h @@ -161,7 +161,7 @@ void viafb_init_accel(void); void viafb_init_2d_engine(void); -void set_2d_color_depth(int); +void viafb_set_2d_mode(struct fb_info *info); void viafb_hw_cursor_init(void); void viafb_show_hw_cursor(struct fb_info *info, int Status); int viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp); diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 980eab8..af8acfe 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -264,7 +264,7 @@ static int viafb_set_par(struct fb_info *info) viafb_accel = info->var.accel_flags; if (viafb_accel) - viafb_set_2d_color_depth(info->var.bits_per_pixel); + viafb_set_2d_mode(info); } return 0; @@ -865,7 +865,6 @@ static void viafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { u32 col = 0, rop = 0; - int pitch; if (!viafb_accel) { cfb_fillrect(info, rect); @@ -897,22 +896,8 @@ static void viafb_fillrect(struct fb_info *info, break; } - /* BitBlt Source Address */ - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); - /* Source Base Address */ - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); - /* Destination Base Address */ - writel(((unsigned long) (info->screen_base) - - (unsigned long) viafb_FB_MM) >> 3, - viaparinfo->io_virt + VIA_REG_DSTBASE); - /* Pitch */ - pitch = (info->var.xres_virtual + 7) & ~7; - writel(VIA_PITCH_ENABLE | - (((pitch * - info->var.bits_per_pixel >> 3) >> 3) | - (((pitch * info-> - var.bits_per_pixel >> 3) >> 3) << 16)), - viaparinfo->io_virt + VIA_REG_PITCH); + viafb_set_2d_mode(info); + /* BitBlt Destination Address */ writel(((rect->dy << 16) | rect->dx), viaparinfo->io_virt + VIA_REG_DSTPOS); @@ -932,7 +917,6 @@ static void viafb_copyarea(struct fb_info *info, { u32 dy = area->dy, sy = area->sy, direction = 0x0; u32 sx = area->sx, dx = area->dx, width = area->width; - int pitch; DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n"); @@ -956,25 +940,8 @@ static void viafb_copyarea(struct fb_info *info, direction |= 0x8000; } - /* Source Base Address */ - writel(((unsigned long) (info->screen_base) - - (unsigned long) viafb_FB_MM) >> 3, - viaparinfo->io_virt + VIA_REG_SRCBASE); - /* Destination Base Address */ - writel(((unsigned long) (info->screen_base) - - (unsigned long) viafb_FB_MM) >> 3, - viaparinfo->io_virt + VIA_REG_DSTBASE); - /* Pitch */ - pitch = (info->var.xres_virtual + 7) & ~7; - /* VIA_PITCH_ENABLE can be omitted now. */ - writel(VIA_PITCH_ENABLE | - (((pitch * - info->var.bits_per_pixel >> 3) >> 3) | (((pitch * - info->var. - bits_per_pixel - >> 3) >> 3) - << 16)), - viaparinfo->io_virt + VIA_REG_PITCH); + viafb_set_2d_mode(info); + /* BitBlt Source Address */ writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS); /* BitBlt Destination Address */ @@ -993,7 +960,6 @@ static void viafb_imageblit(struct fb_info *info, { u32 size, bg_col = 0, fg_col = 0, *udata; int i; - int pitch; if (!viafb_accel) { cfb_imageblit(info, image); @@ -1018,22 +984,8 @@ static void viafb_imageblit(struct fb_info *info, } size = image->width * image->height; - /* Source Base Address */ - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); - /* Destination Base Address */ - writel(((unsigned long) (info->screen_base) - - (unsigned long) viafb_FB_MM) >> 3, - viaparinfo->io_virt + VIA_REG_DSTBASE); - /* Pitch */ - pitch = (info->var.xres_virtual + 7) & ~7; - writel(VIA_PITCH_ENABLE | - (((pitch * - info->var.bits_per_pixel >> 3) >> 3) | (((pitch * - info->var. - bits_per_pixel - >> 3) >> 3) - << 16)), - viaparinfo->io_virt + VIA_REG_PITCH); + viafb_set_2d_mode(info); + /* BitBlt Source Address */ writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); /* BitBlt Destination Address */ -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:48:29
|
From: Harald Welte <la...@gn...> The current code executed from module_init() in viafb does not have proper error checking and [partial] resoure release paths in case an error happens half way through driver initialization. This patch adresses the most obvious of those issues, such as a leftover i2c bus if module_init (and thus module load) fails. Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/viafbdev.c | 52 ++++++++++++++++++++++++++++++----------- 1 files changed, 38 insertions(+), 14 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 02e7a72..72387d4 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. * This program is free software; you can redistribute it and/or @@ -2109,7 +2109,7 @@ static int __devinit via_pci_probe(void) unsigned long default_xres, default_yres; char *tmpc, *tmpm; char *tmpc_sec, *tmpm_sec; - int vmode_index; + int rc, vmode_index; u32 tmds_length, lvds_length, crt_length, chip_length, viafb_par_length; DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); @@ -2130,7 +2130,7 @@ static int __devinit via_pci_probe(void) tmds_length + crt_length + chip_length, NULL); if (!viafbinfo) { printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); - return -ENODEV; + return -ENOMEM; } viaparinfo = (struct viafb_par *)viafbinfo->par; @@ -2157,7 +2157,9 @@ static int __devinit via_pci_probe(void) viafb_dual_fb = 0; /* Set up I2C bus stuff */ - viafb_create_i2c_bus(viaparinfo); + rc = viafb_create_i2c_bus(viaparinfo); + if (rc) + goto out_fb_release; viafb_init_chip_info(); viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize); @@ -2169,7 +2171,8 @@ static int __devinit via_pci_probe(void) if (!viaparinfo->fbmem_virt) { printk(KERN_INFO "ioremap failed\n"); - return -1; + rc = -EIO; + goto out_delete_i2c; } viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len); @@ -2281,8 +2284,7 @@ static int __devinit via_pci_probe(void) if (!viafbinfo1) { printk(KERN_ERR "allocate the second framebuffer struct error\n"); - framebuffer_release(viafbinfo); - return -ENOMEM; + goto out_delete_i2c; } viaparinfo1 = viafbinfo1->par; memcpy(viaparinfo1, viaparinfo, viafb_par_length); @@ -2343,21 +2345,26 @@ static int __devinit via_pci_probe(void) viafb_update_viafb_par(viafbinfo); viafb_update_fix(&viafbinfo->fix, viafbinfo); default_var.activate = FB_ACTIVATE_NOW; - fb_alloc_cmap(&viafbinfo->cmap, 256, 0); + rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0); + if (rc) + goto out_fb1_release; if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) { - if (register_framebuffer(viafbinfo1) < 0) - return -EINVAL; + rc = register_framebuffer(viafbinfo1); + if (rc) + goto out_dealloc_cmap; } - if (register_framebuffer(viafbinfo) < 0) - return -EINVAL; + rc = register_framebuffer(viafbinfo); + if (rc) + goto out_fb1_unreg_lcd_cle266; if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device) || (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266))) { - if (register_framebuffer(viafbinfo1) < 0) - return -EINVAL; + rc = register_framebuffer(viafbinfo1); + if (rc) + goto out_fb_unreg; } DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n", viafbinfo->node, viafbinfo->fix.id, default_var.xres, @@ -2366,6 +2373,23 @@ static int __devinit via_pci_probe(void) viafb_init_proc(&viaparinfo->proc_entry); viafb_init_dac(IGA2); return 0; + +out_fb_unreg: + unregister_framebuffer(viafbinfo); +out_fb1_unreg_lcd_cle266: + if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) + && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) + unregister_framebuffer(viafbinfo1); +out_dealloc_cmap: + fb_dealloc_cmap(&viafbinfo->cmap); +out_fb1_release: + if (viafbinfo1) + framebuffer_release(viafbinfo1); +out_delete_i2c: + viafb_delete_i2c_buss(viaparinfo); +out_fb_release: + framebuffer_release(viafbinfo); + return rc; } static void __devexit via_pci_remove(void) -- 1.6.2.4 |
From: Harald W. <Har...@vi...> - 2009-05-20 20:48:24
|
From: Harald Welte <la...@gn...> This patch alters viafb to use the proper Linux in-kernel API to access PCI configuration space, rather than poking at I/O ports by itself. Signed-off-by: Harald Welte <Har...@vi...> --- drivers/video/via/hw.c | 64 +++++++++++++++++++++++++++++------------------ drivers/video/via/hw.h | 4 +- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 6306c88..40b7c0c 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -2599,24 +2599,37 @@ static void disable_second_display_channel(void) viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); } +static u_int16_t via_function3[] = { + CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3, + CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3, + P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, +}; + +/* Get the BIOS-configured framebuffer size from PCI configuration space + * of function 3 in the respective chipset */ int viafb_get_fb_size_from_pci(void) { - unsigned long configid, deviceid, FBSize = 0; - int VideoMemSize; - int DeviceFound = false; - - for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) { - outl(configid, (unsigned long)0xCF8); - deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff; - - switch (deviceid) { - case CLE266: - case KM400: - outl(configid + 0xE0, (unsigned long)0xCF8); - FBSize = inl((unsigned long)0xCFC); - DeviceFound = true; /* Found device id */ - break; + int i; + u_int8_t offset = 0; + u_int32_t FBSize; + u_int32_t VideoMemSize; + + /* search for the "FUNCTION3" device in this chipset */ + for (i = 0; i < ARRAY_SIZE(via_function3); i++) { + struct pci_dev *pdev; + + pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i], + NULL); + if (!pdev) + continue; + + DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device); + switch (pdev->device) { + case CLE266_FUNCTION3: + case KM400_FUNCTION3: + offset = 0xE0; + break; case CN400_FUNCTION3: case CN700_FUNCTION3: case CX700_FUNCTION3: @@ -2626,21 +2639,22 @@ int viafb_get_fb_size_from_pci(void) case P4M900_FUNCTION3: case VX800_FUNCTION3: case VX855_FUNCTION3: - /*case CN750_FUNCTION3: */ - outl(configid + 0xA0, (unsigned long)0xCF8); - FBSize = inl((unsigned long)0xCFC); - DeviceFound = true; /* Found device id */ - break; - - default: + /*case CN750_FUNCTION3: */ + offset = 0xA0; break; } - - if (DeviceFound) + + if (!offset) break; + + pci_read_config_dword(pdev, offset, &FBSize); + pci_dev_put(pdev); } - DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid); + if (!offset) { + printk(KERN_ERR "cannot determine framebuffer size\n"); + return -EIO; + } FBSize = FBSize & 0x00007000; DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize); diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 1cd0648..a69e907 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -850,8 +850,8 @@ struct iga2_crtc_timing { }; /* device ID */ -#define CLE266 0x3123 -#define KM400 0x3205 +#define CLE266_FUNCTION3 0x3123 +#define KM400_FUNCTION3 0x3205 #define CN400_FUNCTION2 0x2259 #define CN400_FUNCTION3 0x3259 /* support VT3314 chipset */ -- 1.6.2.4 |