* [PATCH 2/3] viafb: delete clock and PLL initialization
From: Florian Tobias Schandinat @ 2011-04-24 1:58 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1303611201-8727-1-git-send-email-FlorianSchandinat@gmx.de>
We do this also in the real program code so there is no reason to
do it here too (and here it's hardly readable).
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/via/viamode.c | 8 ++------
1 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 8c5bc41..e550063 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -41,7 +41,6 @@ struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
{VIACR, CR69, 0xFF, 0x00},
{VIACR, CR6A, 0xFF, 0x40},
{VIACR, CR6B, 0xFF, 0x00},
-{VIACR, CR6C, 0xFF, 0x00},
{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
@@ -87,7 +86,6 @@ struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
{VIACR, CR69, 0xFF, 0x00},
{VIACR, CR6A, 0xFD, 0x40},
{VIACR, CR6B, 0xFF, 0x00},
-{VIACR, CR6C, 0xFF, 0x00},
{VIACR, CR77, 0xFF, 0x00}, /* LCD scaling Factor */
{VIACR, CR78, 0xFF, 0x00}, /* LCD scaling Factor */
{VIACR, CR79, 0xFF, 0x00}, /* LCD scaling Factor */
@@ -161,7 +159,7 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
{VIASR, SR1B, 0xFF, 0xF0},
{VIASR, SR1E, 0xFF, 0x01},
{VIASR, SR2A, 0xFF, 0x00},
-{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */
+{VIASR, SR2D, 0xC0, 0xC0}, /* delayed E3_ECK */
{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
@@ -174,7 +172,6 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
{VIACR, CR69, 0xFF, 0x00},
{VIACR, CR6A, 0xFF, 0x40},
{VIACR, CR6B, 0xFF, 0x00},
-{VIACR, CR6C, 0xFF, 0x00},
{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
@@ -204,7 +201,7 @@ struct io_reg VX855_ModeXregs[] = {
{VIASR, SR2A, 0xF0, 0x00},
{VIASR, SR58, 0xFF, 0x00},
{VIASR, SR59, 0xFF, 0x00},
-{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */
+{VIASR, SR2D, 0xC0, 0xC0}, /* delayed E3_ECK */
{VIACR, CR09, 0xFF, 0x00}, /* Initial CR09=0*/
{VIACR, CR11, 0x8F, 0x00}, /* IGA1 initial Vertical end */
{VIACR, CR17, 0x7F, 0x00}, /* IGA1 CRT Mode control init */
@@ -219,7 +216,6 @@ struct io_reg VX855_ModeXregs[] = {
{VIACR, CR69, 0xFF, 0x00},
{VIACR, CR6A, 0xFD, 0x60},
{VIACR, CR6B, 0xFF, 0x00},
-{VIACR, CR6C, 0xFF, 0x00},
{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
--
1.6.3.2
^ permalink raw reply related
* [PATCH 1/3] viafb: add engine clock support
From: Florian Tobias Schandinat @ 2011-04-24 1:58 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1303611201-8727-1-git-send-email-FlorianSchandinat@gmx.de>
This patch adds support for enabling and configuring the engine on
VIAs IGPs. This is the main clock used for everything but pixel
output.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/via/hw.c | 1 +
drivers/video/via/via_clock.c | 51 +++++++++++++++++++++++++++++++++++++++++
drivers/video/via/via_clock.h | 3 ++
3 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index df84251..e531147 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -2289,6 +2289,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
get_sync(viafbinfo1));
}
+ clock.set_engine_pll_state(VIA_STATE_ON);
clock.set_primary_clock_source(VIA_CLKSRC_X1, true);
clock.set_secondary_clock_source(VIA_CLKSRC_X1, true);
diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c
index a829a24..af8f26b 100644
--- a/drivers/video/via/via_clock.c
+++ b/drivers/video/via/via_clock.c
@@ -87,6 +87,15 @@ static inline void k800_set_secondary_pll_encoded(u32 data)
via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
}
+static inline void set_engine_pll_encoded(u32 data)
+{
+ via_write_reg_mask(VIASR, 0x40, 0x01, 0x01); /* enable reset */
+ via_write_reg(VIASR, 0x47, data & 0xFF);
+ via_write_reg(VIASR, 0x48, (data >> 8) & 0xFF);
+ via_write_reg(VIASR, 0x49, (data >> 16) & 0xFF);
+ via_write_reg_mask(VIASR, 0x40, 0x00, 0x01); /* disable reset */
+}
+
static void cle266_set_primary_pll(struct via_pll_config config)
{
cle266_set_primary_pll_encoded(cle266_encode_pll(config));
@@ -117,6 +126,16 @@ static void vx855_set_secondary_pll(struct via_pll_config config)
k800_set_secondary_pll_encoded(vx855_encode_pll(config));
}
+static void k800_set_engine_pll(struct via_pll_config config)
+{
+ set_engine_pll_encoded(k800_encode_pll(config));
+}
+
+static void vx855_set_engine_pll(struct via_pll_config config)
+{
+ set_engine_pll_encoded(vx855_encode_pll(config));
+}
+
static void set_primary_pll_state(u8 state)
{
u8 value;
@@ -153,6 +172,24 @@ static void set_secondary_pll_state(u8 state)
via_write_reg_mask(VIASR, 0x2D, value, 0x0C);
}
+static void set_engine_pll_state(u8 state)
+{
+ u8 value;
+
+ switch (state) {
+ case VIA_STATE_ON:
+ value = 0x02;
+ break;
+ case VIA_STATE_OFF:
+ value = 0x00;
+ break;
+ default:
+ return;
+ }
+
+ via_write_reg_mask(VIASR, 0x2D, value, 0x03);
+}
+
static void set_primary_clock_state(u8 state)
{
u8 value;
@@ -247,6 +284,11 @@ static void dummy_set_pll_state(u8 state)
printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap);
}
+static void dummy_set_pll(struct via_pll_config config)
+{
+ printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
+}
+
void via_clock_init(struct via_clock *clock, int gfx_chip)
{
switch (gfx_chip) {
@@ -261,6 +303,9 @@ void via_clock_init(struct via_clock *clock, int gfx_chip)
clock->set_secondary_clock_source = dummy_set_clock_source;
clock->set_secondary_pll_state = dummy_set_pll_state;
clock->set_secondary_pll = cle266_set_secondary_pll;
+
+ clock->set_engine_pll_state = dummy_set_pll_state;
+ clock->set_engine_pll = dummy_set_pll;
break;
case UNICHROME_K800:
case UNICHROME_PM800:
@@ -280,6 +325,9 @@ void via_clock_init(struct via_clock *clock, int gfx_chip)
clock->set_secondary_clock_source = set_secondary_clock_source;
clock->set_secondary_pll_state = set_secondary_pll_state;
clock->set_secondary_pll = k800_set_secondary_pll;
+
+ clock->set_engine_pll_state = set_engine_pll_state;
+ clock->set_engine_pll = k800_set_engine_pll;
break;
case UNICHROME_VX855:
case UNICHROME_VX900:
@@ -292,6 +340,9 @@ void via_clock_init(struct via_clock *clock, int gfx_chip)
clock->set_secondary_clock_source = set_secondary_clock_source;
clock->set_secondary_pll_state = set_secondary_pll_state;
clock->set_secondary_pll = vx855_set_secondary_pll;
+
+ clock->set_engine_pll_state = set_engine_pll_state;
+ clock->set_engine_pll = vx855_set_engine_pll;
break;
}
diff --git a/drivers/video/via/via_clock.h b/drivers/video/via/via_clock.h
index f213a7a..88714ae 100644
--- a/drivers/video/via/via_clock.h
+++ b/drivers/video/via/via_clock.h
@@ -53,6 +53,9 @@ struct via_clock {
void (*set_secondary_clock_source)(enum via_clksrc src, bool use_pll);
void (*set_secondary_pll_state)(u8 state);
void (*set_secondary_pll)(struct via_pll_config config);
+
+ void (*set_engine_pll_state)(u8 state);
+ void (*set_engine_pll)(struct via_pll_config config);
};
--
1.6.3.2
^ permalink raw reply related
* viafb OLPC patches
From: Florian Tobias Schandinat @ 2011-04-24 2:39 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel
This patch series contains OLPC specific patches. One fixes the
devices connected as seen by the driver and the other is a further
refresh rate reduction.
Both are required to prevent regressions of the other patch series
as we increasingly require the information of the driver to be
correct which (hopefully only on OLPC) is not the case now.
As usual all patches are also available at
git://github.com/schandinat/linux-2.6.git viafb-olpc
and will soon show up in linux-next.
Thanks,
Florian Tobias Schandinat
^ permalink raw reply
* [PATCH 1/2] viafb: fix OLPC XO 1.5 device connection
From: Florian Tobias Schandinat @ 2011-04-24 2:39 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1303612763-8852-1-git-send-email-FlorianSchandinat@gmx.de>
This patch fixes the devices connected on OLPC. The OLPC panel seems
to be connected to DVP1 and LVDS2 for some reasons and if not both
are handled correct the display does not work correct or not at all.
This patch prevents regressions on the OLPC where it worked by
accident but would break in future as the driver did not know the
correct devices connected. This might also fix hardware scaling.
Hopefully the OLPC is the only device with such a requirement but it
will be certainly better to actually know what devices are actually
connected and to not work by accident.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/via/hw.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 980e263..b8f0110 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -20,6 +20,7 @@
*/
#include <linux/via-core.h>
+#include <asm/olpc.h>
#include "global.h"
static struct pll_config cle266_pll_config[] = {
@@ -875,6 +876,10 @@ void viafb_set_iga_path(void)
viaparinfo->chip_info->
lvds_chip_info2.output_interface);
}
+
+ /* looks like the OLPC has its display wired to DVP1 and LVDS2 */
+ if (machine_is_olpc())
+ viaparinfo->shared->iga2_devices = VIA_DVP1 | VIA_LVDS2;
}
static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
--
1.6.3.2
^ permalink raw reply related
* [PATCH 2/2] viafb: reduce OLPC refresh a bit
From: Florian Tobias Schandinat @ 2011-04-24 2:39 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1303612763-8852-1-git-send-email-FlorianSchandinat@gmx.de>
When allowing some PLL calculation we get a frequency that seems to
be a bit higher than what the OLPC DCON likes resulting in a still
readable but not so good image. We don't really know whether this is
a problem with the calculation formula or the OLPC but as other
displays seem to be happy with the other modes adjusting the OLPC
refresh looks like the better thing. This patch prevents a
regression when dynamic PLL calculation is allowed.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/via/hw.c | 2 +-
drivers/video/via/share.h | 1 +
drivers/video/via/viamode.c | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index b8f0110..56ad185 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -2605,7 +2605,7 @@ int viafb_get_refresh(int hres, int vres, u32 long_refresh)
if (abs(best->refresh_rate - long_refresh) > 3) {
if (hres = 1200 && vres = 900)
- return 50; /* OLPC DCON only supports 50 Hz */
+ return 49; /* OLPC DCON only supports 50 Hz */
else
return 60;
}
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 4b7831f..62bed2b 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -290,6 +290,7 @@
#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
/* Definition Refresh Rate */
+#define REFRESH_49 49
#define REFRESH_50 50
#define REFRESH_60 60
#define REFRESH_75 75
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 260d339..ccb5eec 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -606,7 +606,7 @@ static struct crt_mode_table CRTM1200x720[] = {
/* 1200x900 (DCON) */
static struct crt_mode_table DCON1200x900[] = {
/* r_rate, hsp, vsp */
- {REFRESH_50, M1200X900_R60_HSP, M1200X900_R60_VSP,
+ {REFRESH_49, M1200X900_R60_HSP, M1200X900_R60_VSP,
/* The correct htotal is 1240, but this doesn't raster on VX855. */
/* Via suggested changing to a multiple of 16, hence 1264. */
/* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
--
1.6.3.2
^ permalink raw reply related
* Dear Friend
From: Liu Yan @ 2011-04-25 9:11 UTC (permalink / raw)
To: linux-fbdev
Dear Friend,
I am Liu Yan, an employee of one of the top financial institutions here in Hong Kong. I want to use this opportunity to offer you a business undertaking with a very high monetary gain and value, mutually beneficial to both parties if you are interested, please get back to me on the following email, lyan2003@omisg.com
Regard,
Liu Yan
^ permalink raw reply
* [PATCH] video: s3c-fb: correct transparency checking in 32bpp
From: Jingoo Han @ 2011-04-25 10:14 UTC (permalink / raw)
To: linux-fbdev
32bpp means ARGB 8888 in the driver, therfore the transparency length
and offset should be 8 and 24 respectively. However, the transparency
length and offset were previously 0, which means that the driver supports
RGB 888 without alpha blending when 32bpp is used.
So, the transparency checking in 32bpp is corrected so that the
transparency length and offset are 8 and 24 respectively.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/video/s3c-fb.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 3fa7911..fd0bb57 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -302,6 +302,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
var->blue.length = 5;
break;
+ case 32:
case 28:
case 25:
var->transp.length = var->bits_per_pixel - 24;
@@ -310,7 +311,6 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
case 24:
/* our 24bpp is unpacked, so 32bpp */
var->bits_per_pixel = 32;
- case 32:
var->red.offset = 16;
var->red.length = 8;
var->green.offset = 8;
--
1.7.1
^ permalink raw reply related
* [PATCH] video: s3c-fb: add gpio setup function to resume function
From: Jingoo Han @ 2011-04-25 10:38 UTC (permalink / raw)
To: linux-fbdev
This patch adds gpio setup function to resume function to ensure
gpio used by FIMD IP and LCD panel during a resume.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/video/s3c-fb.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 3fa7911..9457546 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1528,7 +1528,8 @@ static int s3c_fb_resume(struct device *dev)
clk_enable(sfb->bus_clk);
- /* setup registers */
+ /* setup gpio and output polarity controls */
+ pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
/* zero all windows before we do anything */
@@ -1586,7 +1587,8 @@ static int s3c_fb_runtime_resume(struct device *dev)
clk_enable(sfb->bus_clk);
- /* setup registers */
+ /* setup gpio and output polarity controls */
+ pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
/* zero all windows before we do anything */
--
1.7.1
^ permalink raw reply related
* Re: [RFC][PATCH 0/3] MERAM support for LCDC
From: Magnus Damm @ 2011-04-26 5:46 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1301369758-18394-1-git-send-email-dhobsong@igel.co.jp>
Hi Damian,
Thanks for your work on this!
On Tue, Mar 29, 2011 at 12:35 PM, Damian Hobson-Garcia
<dhobsong@igel.co.jp> wrote:
> This patch series is based on the fbdev tree.
>
> This series adds support for read-ahead cache access through the ICBs and
> MERAM available on SH devices. The exact ICBs to use are chip specific
> and are specified in the platform data.
>
> Damian Hobson-Garcia (3):
> sh_mobile_meram: MERAM framework for LCDC
> sh_mobile_meram: Add support for NV24 framebuffers
> sh_mobile_meram: MERAM platform data for LCDC
I think these patches look very good in general. I have one request
and some general comments:
Please add Runtime PM support to the MERAM driver. The MSTP113 bit of
SMSTPCR1 should be dynamically controlled using pm_runtime_get_sync()
and pm_runtime_put_sync().
I also wonder if we can chose to use MERAM dynamically somehow. I know
the sh7372 MERAM can be used to back the entire frame buffer memory
(controlled by the LRCTRL register, see the MERAM section in the
sh7372 data sheet). This fully-backed mode can perhaps be used to save
power for regular low-performance operation and/or semi-standby.
For low-performance operation I imagine that by using MERAM for frame
buffer memory we can put the SDRAM in self-refresh mode and that way
enter deep idle modes even though the screen is still operating.
The semi-standby would be that the "real" framebuffer is in say 32-bit
RGB in SDRAM, but we keep a 8-bit RGB shadow buffer in MERAM and
switch to that at the same instant we move from full backlight to low
backlight. This is most likely useful only when combined with
switching the LCD panel itself to 8-bit mode as well to save
bandwidth.
Then you have your full-performance mode that I guess is what these
patches implement. =)
Any ideas/suggestions about the low power LCDC modes?
Thanks,
/ magnus
^ permalink raw reply
* Query: Implementation of overlay on linux
From: vipul kumar samar @ 2011-04-26 13:53 UTC (permalink / raw)
To: linux-fbdev
Hello,
I am working on LCD module and I want to implement two overlay windows
on frame buffer. I have some queries related to this:
1. Can any buddy suggest me how to proceed towards it??
2. Is their any standard way to use frame buffer ioctl calls??
3. If i have to define my own ioctls then how application manage it??
Thanks and Regards
Vipul Samar
^ permalink raw reply
* Re: [RFC][PATCH 0/3] MERAM support for LCDC
From: Damian Hobson-Garcia @ 2011-04-28 6:08 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1301369758-18394-1-git-send-email-dhobsong@igel.co.jp>
Hi Magnus,
Thanks for your comments.
On 2011/04/26 14:46, Magnus Damm wrote:
> Hi Damian,
>
> Thanks for your work on this!
>
> I think these patches look very good in general. I have one request
> and some general comments:
>
> Please add Runtime PM support to the MERAM driver. The MSTP113 bit of
> SMSTPCR1 should be dynamically controlled using pm_runtime_get_sync()
> and pm_runtime_put_sync().
Ok, I'll look into this, but I think that it will take some thinking.
The MERAM is accessed not only from the LCDC, but can also be accessed
from user space via the uio_pdrv_genirq driver. I think we need to take
care of proper reference counting across these drivers.
>
> I also wonder if we can chose to use MERAM dynamically somehow. I know
> the sh7372 MERAM can be used to back the entire frame buffer memory
> (controlled by the LRCTRL register, see the MERAM section in the
> sh7372 data sheet). This fully-backed mode can perhaps be used to save
> power for regular low-performance operation and/or semi-standby.
>
> For low-performance operation I imagine that by using MERAM for frame
> buffer memory we can put the SDRAM in self-refresh mode and that way
> enter deep idle modes even though the screen is still operating.
I'm not sure that I follow your criteria for "low-performance
operation". What do you define as low-performance? Is this assuming
that we don't have (or disable) high-resolution (i.e. HDMI) secondary
output?
If so,it may be possible to dynamically reassign the area of the MERAM
that was allocated to HDMI for LCD output. Otherwise the whole
framebuffer will not fit in MERAM and we'd have to revert to SDRAM.
>
> The semi-standby would be that the "real" framebuffer is in say 32-bit
> RGB in SDRAM, but we keep a 8-bit RGB shadow buffer in MERAM and
> switch to that at the same instant we move from full backlight to low
> backlight. This is most likely useful only when combined with
> switching the LCD panel itself to 8-bit mode as well to save
> bandwidth.
By "keep an 8-bit RGB shadow buffer" are you talking about generating a
quantized version (RGB 332) of the "real" framebuffer in the MERAM when
we switch modes? It would be nice to be able to do such a conversion in
the hardware, but there currently isn't any support for VEU or the like
in the kernel.
>
> Then you have your full-performance mode that I guess is what these
> patches implement. =)
>
> Any ideas/suggestions about the low power LCDC modes?
>
> Thanks,
>
> / magnus
Thanks again for your feedback,
Damian
^ permalink raw reply
* viafb misc patches
From: Florian Tobias Schandinat @ 2011-04-30 14:18 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel
This patch series contains various patches. One is a significant
performance improvement for applications which use the framebuffer.
Another one tries harder to make the framebuffer work by reducing
the address space required for remapping, but as VIAs X server we
still need a lot of parameters to be set correct to get a usable
display. The last one is a little dead code removal.
Best regards,
Florian Tobias Schandinat
^ permalink raw reply
* [PATCH 1/3] viafb: use write combining for video ram
From: Florian Tobias Schandinat @ 2011-04-30 14:18 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1304173086-3434-1-git-send-email-FlorianSchandinat@gmx.de>
This can give a speed up of factor 6-9, which is quite notable.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/via/via-core.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index 6723d69..5b0129b 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -505,7 +505,7 @@ static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev)
ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
if (ret < 0)
goto out_unmap;
- vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len);
+ vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
if (vdev->fbmem = NULL) {
ret = -ENOMEM;
goto out_unmap;
--
1.6.3.2
^ permalink raw reply related
* [PATCH 2/3] viafb: try to map less memory in case of failure
From: Florian Tobias Schandinat @ 2011-04-30 14:18 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1304173086-3434-1-git-send-email-FlorianSchandinat@gmx.de>
The current code might result in trying to remap 512MB video ram on
a 32 bit system which is quite likely to fail.
This patch tries to map less of it down to 8MB as this should still
be enough to get a reasonably well working framebuffer. This should
make viafb work for many people without requiring them to manually
allocate more space.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/via/via-core.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index 5b0129b..eb112b6 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -505,7 +505,14 @@ static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev)
ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
if (ret < 0)
goto out_unmap;
- vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
+
+ /* try to map less memory on failure, 8 MB should be still enough */
+ for (; vdev->fbmem_len >= 8 << 20; vdev->fbmem_len /= 2) {
+ vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
+ if (vdev->fbmem)
+ break;
+ }
+
if (vdev->fbmem = NULL) {
ret = -ENOMEM;
goto out_unmap;
--
1.6.3.2
^ permalink raw reply related
* [PATCH 3/3] viafb: remove unused CEA mode
From: Florian Tobias Schandinat @ 2011-04-30 14:18 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1304173086-3434-1-git-send-email-FlorianSchandinat@gmx.de>
This trivial patch removes unused mode tables.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/via/share.h | 8 --------
drivers/video/via/viamode.c | 17 -----------------
drivers/video/via/viamode.h | 9 ---------
3 files changed, 0 insertions(+), 34 deletions(-)
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 8b93e2f..61b0bd5 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -568,10 +568,6 @@
#define M1280X720_R50_HSP NEGATIVE
#define M1280X720_R50_VSP POSITIVE
-/* 1280x720@60 Sync Polarity (CEA Mode) */
-#define M1280X720_CEA_R60_HSP POSITIVE
-#define M1280X720_CEA_R60_VSP POSITIVE
-
/* 1440x900@60 Sync Polarity (CVT Mode) */
#define M1440X900_R60_HSP NEGATIVE
#define M1440X900_R60_VSP POSITIVE
@@ -612,10 +608,6 @@
#define M1920X1200_RB_R60_HSP POSITIVE
#define M1920X1200_RB_R60_VSP NEGATIVE
-/* 1920x1080@60 Sync Polarity (CEA Mode) */
-#define M1920X1080_CEA_R60_HSP POSITIVE
-#define M1920X1080_CEA_R60_VSP POSITIVE
-
/* 2048x1536@60 Sync Polarity (CVT Mode) */
#define M2048x1536_R60_HSP NEGATIVE
#define M2048x1536_R60_VSP POSITIVE
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 50de07f..58df74e 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -854,23 +854,6 @@ static struct VideoModeTable viafb_rb_modes[] = {
{CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)}
};
-struct crt_mode_table CEAM1280x720[] = {
- {REFRESH_60, M1280X720_CEA_R60_HSP, M1280X720_CEA_R60_VSP,
- /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
- {1650, 1280, 1280, 370, 1390, 40, 750, 720, 720, 30, 725, 5} }
-};
-struct crt_mode_table CEAM1920x1080[] = {
- {REFRESH_60, M1920X1080_CEA_R60_HSP, M1920X1080_CEA_R60_VSP,
- /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
- {2200, 1920, 1920, 300, 2008, 44, 1125, 1080, 1080, 45, 1084, 5} }
-};
-struct VideoModeTable CEA_HDMI_Modes[] = {
- /* Display : 1280x720 */
- {CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
- {CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
-};
-
-int NUM_TOTAL_CEA_MODES = ARRAY_SIZE(CEA_HDMI_Modes);
int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs);
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 8a67ea1..3751289 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -41,7 +41,6 @@ struct patch_table {
struct io_reg *io_reg_table;
};
-extern int NUM_TOTAL_CEA_MODES;
extern int NUM_TOTAL_CN400_ModeXregs;
extern int NUM_TOTAL_CN700_ModeXregs;
extern int NUM_TOTAL_KM400_ModeXregs;
@@ -50,14 +49,6 @@ extern int NUM_TOTAL_VX855_ModeXregs;
extern int NUM_TOTAL_CLE266_ModeXregs;
extern int NUM_TOTAL_PATCH_MODE;
-/********************/
-/* Mode Table */
-/********************/
-
-extern struct crt_mode_table CEAM1280x720[];
-extern struct crt_mode_table CEAM1920x1080[];
-extern struct VideoModeTable CEA_HDMI_Modes[];
-
extern struct io_reg CN400_ModeXregs[];
extern struct io_reg CN700_ModeXregs[];
extern struct io_reg KM400_ModeXregs[];
--
1.6.3.2
^ permalink raw reply related
* fbdev test application
From: Laurent Pinchart @ 2011-04-30 14:43 UTC (permalink / raw)
To: linux-fbdev
Hi everybody,
I've developed a small fbdev application for internal test purpose that might
be useful to other developers, so I'm releasing it under the GPL.
The code can be found in a git repository at
http://git.ideasonboard.org/?pûdev-test.git;a=summary. I'm also adding the
initial patch to this e-mail, in case someone would like to review the
code :-)
diff -Nur a/fbdev.c b/fbdev.c
--- a/fbdev.c 1970-01-01 01:00:00.000000000 +0100
+++ b/fbdev.c 2011-04-29 17:04:03.000000000 +0200
@@ -0,0 +1,1062 @@
+/*
+ * fbdev -- Frame buffer device test application
+ *
+ * Copyright (C) 2011 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#include <linux/fb.h>
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+struct device {
+ int fd;
+ void *mem;
+
+ struct fb_fix_screeninfo fix_info;
+ struct fb_var_screeninfo var_info;
+};
+
+enum fb_fill_mode {
+ FB_FILL_NONE = 0,
+ FB_FILL_DISPLAY = 1,
+ FB_FILL_VIRTUAL = 2,
+};
+
+/* -----------------------------------------------------------------------------
+ * FB information display
+ */
+
+struct fb_value_name {
+ unsigned int value;
+ const char *name;
+};
+
+static const struct fb_value_name fb_type_names[] = {
+ { FB_TYPE_PACKED_PIXELS, "Packed Pixels" },
+ { FB_TYPE_PLANES, "Non Interleaved Planes" },
+ { FB_TYPE_INTERLEAVED_PLANES, "Interleaved Planes" },
+ { FB_TYPE_TEXT, "Text/Attributes" },
+ { FB_TYPE_VGA_PLANES, "EGA/VGA Planes" },
+};
+
+static const struct fb_value_name fb_visual_names[] = {
+ { FB_VISUAL_MONO01, "Monochrome (white 0, black 1)" },
+ { FB_VISUAL_MONO10, "Monochrome (white 1, black 0)" },
+ { FB_VISUAL_TRUECOLOR, "True Color" },
+ { FB_VISUAL_PSEUDOCOLOR, "Pseudo Color" },
+ { FB_VISUAL_DIRECTCOLOR, "Direct Color" },
+ { FB_VISUAL_STATIC_PSEUDOCOLOR, "Pseudo Color (read-only)" },
+};
+
+static const struct fb_value_name fb_accel_names[] = {
+ { FB_ACCEL_NONE, "no hardware accelerator" },
+ { FB_ACCEL_ATARIBLITT, "Atari Blitter" },
+ { FB_ACCEL_AMIGABLITT, "Amiga Blitter" },
+ { FB_ACCEL_S3_TRIO64, "Cybervision64 (S3 Trio64)" },
+ { FB_ACCEL_NCR_77C32BLT, "RetinaZ3 (NCR 77C32BLT)" },
+ { FB_ACCEL_S3_VIRGE, "Cybervision64/3D (S3 ViRGE)" },
+ { FB_ACCEL_ATI_MACH64GX, "ATI Mach 64GX family" },
+ { FB_ACCEL_DEC_TGA, "DEC 21030 TGA" },
+ { FB_ACCEL_ATI_MACH64CT, "ATI Mach 64CT family" },
+ { FB_ACCEL_ATI_MACH64VT, "ATI Mach 64CT family VT class" },
+ { FB_ACCEL_ATI_MACH64GT, "ATI Mach 64CT family GT class" },
+ { FB_ACCEL_SUN_CREATOR, "Sun Creator/Creator3D" },
+ { FB_ACCEL_SUN_CGSIX, "Sun cg6" },
+ { FB_ACCEL_SUN_LEO, "Sun leo/zx" },
+ { FB_ACCEL_IMS_TWINTURBO, "IMS Twin Turbo" },
+ { FB_ACCEL_3DLABS_PERMEDIA2, "3Dlabs Permedia 2" },
+ { FB_ACCEL_MATROX_MGA2064W, "Matrox MGA2064W (Millenium)" },
+ { FB_ACCEL_MATROX_MGA1064SG, "Matrox MGA1064SG (Mystique)" },
+ { FB_ACCEL_MATROX_MGA2164W, "Matrox MGA2164W (Millenium II)" },
+ { FB_ACCEL_MATROX_MGA2164W_AGP, "Matrox MGA2164W (Millenium II)" },
+ { FB_ACCEL_MATROX_MGAG100, "Matrox G100 (Productiva G100)" },
+ { FB_ACCEL_MATROX_MGAG200, "Matrox G200 (Myst, Mill, ...)" },
+ { FB_ACCEL_SUN_CG14, "Sun cgfourteen" },
+ { FB_ACCEL_SUN_BWTWO, "Sun bwtwo" },
+ { FB_ACCEL_SUN_CGTHREE, "Sun cgthree" },
+ { FB_ACCEL_SUN_TCX, "Sun tcx" },
+ { FB_ACCEL_MATROX_MGAG400, "Matrox G400" },
+ { FB_ACCEL_NV3, "nVidia RIVA 128" },
+ { FB_ACCEL_NV4, "nVidia RIVA TNT" },
+ { FB_ACCEL_NV5, "nVidia RIVA TNT2" },
+ { FB_ACCEL_CT_6555x, "C&T 6555x" },
+ { FB_ACCEL_3DFX_BANSHEE, "3Dfx Banshee" },
+ { FB_ACCEL_ATI_RAGE128, "ATI Rage128 family" },
+ { FB_ACCEL_IGS_CYBER2000, "CyberPro 2000" },
+ { FB_ACCEL_IGS_CYBER2010, "CyberPro 2010" },
+ { FB_ACCEL_IGS_CYBER5000, "CyberPro 5000" },
+ { FB_ACCEL_SIS_GLAMOUR, "SiS 300/630/540" },
+ { FB_ACCEL_3DLABS_PERMEDIA3, "3Dlabs Permedia 3" },
+ { FB_ACCEL_ATI_RADEON, "ATI Radeon family" },
+ { FB_ACCEL_I810, "Intel 810/815" },
+ { FB_ACCEL_SIS_GLAMOUR_2, "SiS 315, 650, 740" },
+ { FB_ACCEL_SIS_XABRE, "SiS 330 (\"Xabre\")" },
+ { FB_ACCEL_I830, "Intel 830M/845G/85x/865G" },
+ { FB_ACCEL_NV_10, "nVidia Arch 10" },
+ { FB_ACCEL_NV_20, "nVidia Arch 20" },
+ { FB_ACCEL_NV_30, "nVidia Arch 30" },
+ { FB_ACCEL_NV_40, "nVidia Arch 40" },
+ { FB_ACCEL_XGI_VOLARI_V, "XGI Volari V3XT, V5, V8" },
+ { FB_ACCEL_XGI_VOLARI_Z, "XGI Volari Z7" },
+ { FB_ACCEL_OMAP1610, "TI OMAP16xx" },
+ { FB_ACCEL_TRIDENT_TGUI, "Trident TGUI" },
+ { FB_ACCEL_TRIDENT_3DIMAGE, "Trident 3DImage" },
+ { FB_ACCEL_TRIDENT_BLADE3D, "Trident Blade3D" },
+ { FB_ACCEL_TRIDENT_BLADEXP, "Trident BladeXP" },
+ { FB_ACCEL_CIRRUS_ALPINE, "Cirrus Logic 543x/544x/5480" },
+ { FB_ACCEL_NEOMAGIC_NM2070, "NeoMagic NM2070" },
+ { FB_ACCEL_NEOMAGIC_NM2090, "NeoMagic NM2090" },
+ { FB_ACCEL_NEOMAGIC_NM2093, "NeoMagic NM2093" },
+ { FB_ACCEL_NEOMAGIC_NM2097, "NeoMagic NM2097" },
+ { FB_ACCEL_NEOMAGIC_NM2160, "NeoMagic NM2160" },
+ { FB_ACCEL_NEOMAGIC_NM2200, "NeoMagic NM2200" },
+ { FB_ACCEL_NEOMAGIC_NM2230, "NeoMagic NM2230" },
+ { FB_ACCEL_NEOMAGIC_NM2360, "NeoMagic NM2360" },
+ { FB_ACCEL_NEOMAGIC_NM2380, "NeoMagic NM2380" },
+ { FB_ACCEL_SAVAGE4, "S3 Savage4" },
+ { FB_ACCEL_SAVAGE3D, "S3 Savage3D" },
+ { FB_ACCEL_SAVAGE3D_MV, "S3 Savage3D-MV" },
+ { FB_ACCEL_SAVAGE2000, "S3 Savage2000" },
+ { FB_ACCEL_SAVAGE_MX_MV, "S3 Savage/MX-MV" },
+ { FB_ACCEL_SAVAGE_MX, "S3 Savage/MX" },
+ { FB_ACCEL_SAVAGE_IX_MV, "S3 Savage/IX-MV" },
+ { FB_ACCEL_SAVAGE_IX, "S3 Savage/IX" },
+ { FB_ACCEL_PROSAVAGE_PM, "S3 ProSavage PM133" },
+ { FB_ACCEL_PROSAVAGE_KM, "S3 ProSavage KM133" },
+ { FB_ACCEL_S3TWISTER_P, "S3 Twister" },
+ { FB_ACCEL_S3TWISTER_K, "S3 TwisterK" },
+ { FB_ACCEL_SUPERSAVAGE, "S3 Supersavage" },
+ { FB_ACCEL_PROSAVAGE_DDR, "S3 ProSavage DDR" },
+ { FB_ACCEL_PROSAVAGE_DDRK, "S3 ProSavage DDR-K" },
+};
+
+static const char *fb_value_name(const struct fb_value_name *names,
+ unsigned int size, unsigned int value)
+{
+ unsigned int i;
+
+ for (i = 0; i < size; ++i) {
+ if (names[i].value = value)
+ return names[i].name;
+ }
+
+ return "Unknown";
+}
+
+static const char *fb_type_name(unsigned int type)
+{
+ return fb_value_name(fb_type_names, ARRAY_SIZE(fb_type_names), type);
+}
+
+static const char *fb_visual_name(unsigned int visual)
+{
+ return fb_value_name(fb_visual_names, ARRAY_SIZE(fb_visual_names), visual);
+}
+
+static const char *fb_accel_name(unsigned int accel)
+{
+ return fb_value_name(fb_accel_names, ARRAY_SIZE(fb_accel_names), accel);
+}
+
+/*
+ * fb_print_fix - Print fixed screen information
+ * @dev: FB device
+ * @var: fixed screen information
+ */
+static void fb_print_fix(struct device *dev __attribute__((__unused__)),
+ struct fb_fix_screeninfo *fix)
+{
+ printf("--- Fixed screen info ---\n");
+ printf(" Type:\t\t%s\n", fb_type_name(fix->type));
+ printf(" Visual:\t%s\n", fb_visual_name(fix->visual));
+ printf(" Chip/card:\t%s\n", fb_accel_name(fix->accel));
+
+ printf(" Memory:\t%u bytes @0x%08lx\n", fix->smem_len,
+ fix->smem_start);
+
+ if (fix->xpanstep = 0)
+ printf(" X Pan:\t\tUnsupported\n");
+ else
+ printf(" X Pan Step:\t%u\n", fix->xpanstep);
+
+ if (fix->ypanstep = 0)
+ printf(" Y Pan:\t\tUnsupported\n");
+ else
+ printf(" Y Pan Step:\t%u\n", fix->ypanstep);
+
+ printf(" Line Length:\t%u bytes\n", fix->line_length);
+}
+
+/*
+ * fb_print_var - Print fixed screen information
+ * @dev: FB device
+ * @var: variable screen information
+ */
+static void fb_print_var(struct device *dev, struct fb_var_screeninfo *var)
+{
+ unsigned int i;
+
+ printf("--- Variable screen info ---\n");
+ printf(" Resolution:\t\t%ux%u\n", var->xres, var->yres);
+ printf(" Virtual Resolution:\t%ux%u\n", var->xres_virtual,
+ var->yres_virtual);
+ printf(" X/Y Offset:\t\t(%u,%u)\n", var->xoffset, var->yoffset);
+ printf(" Size:\t\t\t%umm x %umm\n", var->width, var->height);
+
+ if (dev->fix_info.visual = FB_VISUAL_TRUECOLOR) {
+ printf(" Pixel organization:\t");
+ for (i = var->bits_per_pixel - 1; i < var->bits_per_pixel; --i) {
+ if (var->red.offset <= i && var->red.offset + var->red.length > i)
+ printf("R");
+ else if (var->green.offset <= i && var->green.offset + var->green.length > i)
+ printf("G");
+ else if (var->blue.offset <= i && var->blue.offset + var->green.length > i)
+ printf("B");
+ else if (var->transp.offset <= i && var->transp.offset + var->transp.length > i)
+ printf("A");
+ }
+ printf("\n (%u bits per pixel)\t", var->bits_per_pixel);
+ for (i = var->bits_per_pixel - 1; i < var->bits_per_pixel; --i) {
+ if (var->red.offset <= i &&
+ var->red.offset + var->red.length > i)
+ printf("%u", var->red.msb_right ?
+ var->red.offset + var->red.length - 1 - i :
+ i - var->red.offset);
+ else if (var->green.offset <= i &&
+ var->green.offset + var->green.length > i)
+ printf("%u", var->green.msb_right ?
+ var->green.offset + var->green.length - 1 - i :
+ i - var->green.offset);
+ else if (var->blue.offset <= i &&
+ var->blue.offset + var->green.length > i)
+ printf("%u", var->blue.msb_right ?
+ var->blue.offset + var->blue.length - 1 - i :
+ i - var->blue.offset);
+ else if (var->transp.offset <= i &&
+ var->transp.offset + var->transp.length > i)
+ printf("%u", var->transp.msb_right ?
+ var->transp.offset + var->transp.length - 1 - i :
+ i - var->transp.offset);
+ }
+ printf("\n");
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Memory mapping
+ */
+
+/*
+ * fb_map_memory - Map the frame buffer memory to userspace
+ * @dev: FB device
+ */
+static int fb_map_memory(struct device *dev)
+{
+ void *mem;
+
+ mem = mmap(NULL, dev->fix_info.smem_len, PROT_READ | PROT_WRITE,
+ MAP_SHARED, dev->fd, 0);
+ if (mem = MAP_FAILED) {
+ printf("Error: FB memory map failed: %s (%d)\n",
+ strerror(errno), errno);
+ return -1;
+ }
+
+ dev->mem = mem;
+ return 0;
+}
+
+/*
+ * fb_unmap_memory - Unmap the frame buffer memory from userspace
+ * @dev: FB device
+ */
+static void fb_unmap_memory(struct device *dev)
+{
+ if (dev->mem = MAP_FAILED)
+ return;
+
+ munmap(dev->mem, dev->fix_info.smem_len);
+}
+
+/* -----------------------------------------------------------------------------
+ * Open/close
+ */
+
+/*
+ * fb_open - Open a frame buffer device
+ * @dev: FB device
+ * @devname: FB device node name and path
+ *
+ * Open the FB devide referenced by devname. Retrieve fixed and variable screen
+ * information, map the frame buffer memory and fill the dev structure.
+ */
+static int fb_open(struct device *dev, const char *devname)
+{
+ int ret;
+
+ memset(dev, 0, sizeof *dev);
+ dev->fd = -1;
+ dev->mem = MAP_FAILED;
+
+ dev->fd = open(devname, O_RDWR);
+ if (dev->fd < 0) {
+ printf("Error opening device %s: %d.\n", devname, errno);
+ return dev->fd;
+ }
+
+ ret = ioctl(dev->fd, FBIOGET_FSCREENINFO, &dev->fix_info);
+ if (ret < 0) {
+ printf("Error opening device %s: unable to get fixed screen "
+ "info.\n", devname);
+ close(dev->fd);
+ return ret;
+ }
+
+ ret = ioctl(dev->fd, FBIOGET_VSCREENINFO, &dev->var_info);
+ if (ret < 0) {
+ printf("Error opening device %s: unable to get variable screen "
+ "info.\n", devname);
+ close(dev->fd);
+ return ret;
+ }
+
+ printf("Device %s opened: %s\n\n", devname, dev->fix_info.id);
+ fb_print_fix(dev, &dev->fix_info);
+ printf("\n");
+ fb_print_var(dev, &dev->var_info);
+ printf("\n");
+
+ ret = fb_map_memory(dev);
+ if (ret < 0) {
+ close(dev->fd);
+ return ret;
+ }
+
+ printf("FB memory mapped at %p\n", dev->mem);
+ return 0;
+}
+
+/*
+ * fb_close - Close a frame buffer device
+ * @dev: FB device
+ *
+ * Close a frame buffer device previously opened by fb_open().
+ */
+static void fb_close(struct device *dev)
+{
+ fb_unmap_memory(dev);
+ close(dev->fd);
+}
+
+/* -----------------------------------------------------------------------------
+ * Blanking and sync
+ */
+
+/*
+ * fb_blank - Control screen blanking
+ * @dev: FB device
+ * @blank: Blanking state
+ *
+ * Set the frame buffer screen blanking state. Acceptable values for the blank
+ * parameter are
+ *
+ * FB_BLANK_UNBLANK Blanking off, screen active
+ * FB_BLANK_NORMAL Blanked, HSync on, VSync on
+ * FB_BLANK_VSYNC_SUSPEND Blanked, HSync on, VSync off
+ * FB_BLANK_HSYNC_SUSPEND Blanked, HSync off, VSync on
+ * FB_BLANK_POWERDOWN Blanked, HSync off, VSync off
+ */
+static int fb_blank(struct device *dev, int blank)
+{
+ int ret;
+
+ ret = ioctl(dev->fd, FBIOBLANK, blank);
+ if (ret < 0) {
+ printf("Error: blank failed: %s (%d)\n", strerror(errno), errno);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * fb_wait_for_vsync - Wait for vsync
+ * @dev: FB device
+ * @screen: Screen number
+ *
+ * Unblank the screen to make sure vsync events are generated and wait for 1000
+ * 1000 vsync events on the given screen. Print the average refresh rate when
+ * done.
+ */
+static int fb_wait_for_vsync(struct device *dev, unsigned int screen)
+{
+ struct timespec start, end;
+ unsigned int i;
+ double fps;
+ int ret;
+
+ /* Can't wait for vsync if the displayed is blanked. */
+ fb_blank(dev, FB_BLANK_UNBLANK);
+
+ printf("waiting for 1000 vsync events... ");
+ fflush(stdout);
+
+ clock_gettime(CLOCK_MONOTONIC, &start);
+
+ for (i = 0; i < 1000; ++i) {
+ ret = ioctl(dev->fd, FBIO_WAITFORVSYNC, &screen);
+ if (ret < 0) {
+ printf("\nError: wait for vsync failed: %s (%d)\n",
+ strerror(errno), errno);
+ return ret;
+ }
+ }
+
+ clock_gettime(CLOCK_MONOTONIC, &end);
+
+ end.tv_sec -= start.tv_sec;
+ end.tv_nsec -= start.tv_nsec;
+ if (end.tv_nsec < 0) {
+ end.tv_sec--;
+ end.tv_nsec += 1000000000;
+ }
+
+ fps = i / (end.tv_sec + end.tv_nsec / 1000000000.);
+
+ printf("done\n");
+ printf("%u vsync interrupts in %lu.%06lu s, %f Hz\n",
+ i, end.tv_sec, end.tv_nsec / 1000, fps);
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Resolution and pan
+ */
+
+/*
+ * fb_set_format - Set the frame buffer pixel format
+ * @dev: FB device
+ * @bpp: Bits per pixel
+ */
+static int fb_set_format(struct device *dev, unsigned int bpp)
+{
+ struct fb_var_screeninfo var_info;
+ int ret;
+
+ var_info = dev->var_info;
+
+ var_info.bits_per_pixel = bpp;
+ var_info.activate = FB_ACTIVATE_NOW;
+
+ ret = ioctl(dev->fd, FBIOPUT_VSCREENINFO, &var_info);
+ if (ret < 0) {
+ printf("Error: set format failed: %s (%d)\n",
+ strerror(errno), errno);
+ return ret;
+ }
+
+ dev->var_info = var_info;
+
+ printf("Format set to %u bits per pixel\n\n",
+ var_info.bits_per_pixel);
+
+ fb_print_var(dev, &var_info);
+
+ return 0;
+}
+
+/*
+ * fb_set_resolution - Set the frame buffer real and virtual resolutions
+ * @dev: FB device
+ * @xres: Horizontal resolution
+ * @yres: Vertical resolution
+ * @xres_virtual: Horizontal virtual resolution
+ * @yres_virtual: Vertical virtual resolution
+ *
+ * Modify the real and virtual resolutions of the frame buffer to (xres, yres)
+ * and (xres_virtual, yres_virtual). The real or virtual resolution can be kept
+ * unchanged by setting its value to (-1, -1).
+ */
+static int fb_set_resolution(struct device *dev, int xres, int yres,
+ int xres_virtual, int yres_virtual)
+{
+ struct fb_var_screeninfo var_info;
+ int ret;
+
+ var_info = dev->var_info;
+
+ if (xres != -1 && yres != -1 ) {
+ var_info.xres = xres;
+ var_info.yres = yres;
+ }
+
+ if (xres_virtual != -1 && yres_virtual != -1 ) {
+ var_info.xres_virtual = xres_virtual;
+ var_info.yres_virtual = yres_virtual;
+ }
+
+ printf("Setting resolution to %ux%u (virtual %ux%u)\n",
+ var_info.xres, var_info.yres,
+ var_info.xres_virtual, var_info.yres_virtual);
+
+ var_info.bits_per_pixel = 16;
+ var_info.activate = FB_ACTIVATE_NOW;
+
+ ret = ioctl(dev->fd, FBIOPUT_VSCREENINFO, &var_info);
+ if (ret < 0) {
+ printf("Error: set resolution failed: %s (%d)\n",
+ strerror(errno), errno);
+ return ret;
+ }
+
+ dev->var_info = var_info;
+
+ printf("Resolution set to %ux%u (virtual %ux%u)\n\n",
+ var_info.xres, var_info.yres,
+ var_info.xres_virtual, var_info.yres_virtual);
+
+ fb_print_var(dev, &var_info);
+
+ return 0;
+}
+
+/*
+ * fb_pan - Pan the display
+ * @dev: FB device
+ * @x: Horizontal offset
+ * @y: Vertical offset
+ *
+ * Pan the display to set the virtual point (x, y) on the top left corner of the
+ * screen.
+ */
+static int fb_pan(struct device *dev, unsigned int x, unsigned int y)
+{
+ struct fb_var_screeninfo var_info;
+ int ret;
+
+ memset(&var_info, 0, sizeof var_info);
+ var_info.xoffset = x;
+ var_info.yoffset = y;
+
+ ret = ioctl(dev->fd, FBIOPAN_DISPLAY, &var_info);
+ if (ret < 0) {
+ printf("Error: pan failed: %s (%d)\n", strerror(errno), errno);
+ return ret;
+ }
+
+ dev->var_info.xoffset = var_info.xoffset;
+ dev->var_info.yoffset = var_info.yoffset;
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Test pattern
+ */
+
+#define FB_MAKE_COLOR(var, r, g, b) \
+ ((((r) >> (8 - (var)->red.length)) << (var)->red.offset) | \
+ (((g) >> (8 - (var)->green.length)) << (var)->green.offset) | \
+ (((b) >> (8 - (var)->blue.length)) << (var)->blue.offset))
+
+static void
+fb_fill_rgb16(struct device *dev, unsigned int xoffset, unsigned int yoffset,
+ unsigned int xres, unsigned int yres)
+{
+ const uint16_t colors_top[] = {
+ FB_MAKE_COLOR(&dev->var_info, 192, 192, 192), /* grey */
+ FB_MAKE_COLOR(&dev->var_info, 192, 192, 0), /* yellow */
+ FB_MAKE_COLOR(&dev->var_info, 0, 192, 192), /* cyan */
+ FB_MAKE_COLOR(&dev->var_info, 0, 192, 0), /* green */
+ FB_MAKE_COLOR(&dev->var_info, 192, 0, 192), /* magenta */
+ FB_MAKE_COLOR(&dev->var_info, 192, 0, 0), /* red */
+ FB_MAKE_COLOR(&dev->var_info, 0, 0, 192), /* blue */
+ };
+ const uint16_t colors_middle[] = {
+ FB_MAKE_COLOR(&dev->var_info, 0, 0, 192), /* blue */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR(&dev->var_info, 192, 0, 192), /* magenta */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR(&dev->var_info, 0, 192, 192), /* cyan */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR(&dev->var_info, 192, 192, 192), /* grey */
+ };
+ const uint16_t colors_bottom[] = {
+ FB_MAKE_COLOR(&dev->var_info, 0, 33, 76), /* in-phase */
+ FB_MAKE_COLOR(&dev->var_info, 255, 255, 255), /* super white */
+ FB_MAKE_COLOR(&dev->var_info, 50, 0, 106), /* quadrature */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR(&dev->var_info, 9, 9, 9), /* 3.5% */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* 7.5% */
+ FB_MAKE_COLOR(&dev->var_info, 29, 29, 29), /* 11.5% */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ };
+ void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ + xoffset * dev->var_info.bits_per_pixel / 8;
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < yres * 6 / 9; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((uint16_t *)mem)[x] = colors_top[x * 7 / xres];
+ mem += dev->fix_info.line_length;
+ }
+
+ for (; y < yres * 7 / 9; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((uint16_t *)mem)[x] = colors_middle[x * 7 / xres];
+ mem += dev->fix_info.line_length;
+ }
+
+ for (; y < yres; ++y) {
+ for (x = 0; x < xres * 5 / 7; ++x)
+ ((uint16_t *)mem)[x] + colors_bottom[x * 4 / (xres * 5 / 7)];
+ for (; x < xres * 6 / 7; ++x)
+ ((uint16_t *)mem)[x] + colors_bottom[(x - xres * 5 / 7) * 3
+ / (xres / 7) + 4];
+ for (; x < xres; ++x)
+ ((uint16_t *)mem)[x] = colors_bottom[7];
+ mem += dev->fix_info.line_length;
+ }
+}
+
+struct fb_color24 {
+ unsigned int value:24;
+} __attribute__((__packed__));
+
+#define FB_MAKE_COLOR24(var, r, g, b) \
+ { .value = FB_MAKE_COLOR(var, r, g, b) }
+
+static void
+fb_fill_rgb24(struct device *dev, unsigned int xoffset, unsigned int yoffset,
+ unsigned int xres, unsigned int yres)
+{
+ const struct fb_color24 colors_top[] = {
+ FB_MAKE_COLOR24(&dev->var_info, 192, 192, 192), /* grey */
+ FB_MAKE_COLOR24(&dev->var_info, 192, 192, 0), /* yellow */
+ FB_MAKE_COLOR24(&dev->var_info, 0, 192, 192), /* cyan */
+ FB_MAKE_COLOR24(&dev->var_info, 0, 192, 0), /* green */
+ FB_MAKE_COLOR24(&dev->var_info, 192, 0, 192), /* magenta */
+ FB_MAKE_COLOR24(&dev->var_info, 192, 0, 0), /* red */
+ FB_MAKE_COLOR24(&dev->var_info, 0, 0, 192), /* blue */
+ };
+ const struct fb_color24 colors_middle[] = {
+ FB_MAKE_COLOR24(&dev->var_info, 0, 0, 192), /* blue */
+ FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR24(&dev->var_info, 192, 0, 192), /* magenta */
+ FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR24(&dev->var_info, 0, 192, 192), /* cyan */
+ FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR24(&dev->var_info, 192, 192, 192), /* grey */
+ };
+ const struct fb_color24 colors_bottom[] = {
+ FB_MAKE_COLOR24(&dev->var_info, 0, 33, 76), /* in-phase */
+ FB_MAKE_COLOR24(&dev->var_info, 255, 255, 255), /* super white */
+ FB_MAKE_COLOR24(&dev->var_info, 50, 0, 106), /* quadrature */
+ FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR24(&dev->var_info, 9, 9, 9), /* 3.5% */
+ FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19), /* 7.5% */
+ FB_MAKE_COLOR24(&dev->var_info, 29, 29, 29), /* 11.5% */
+ FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19), /* black */
+ };
+ void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ + xoffset * dev->var_info.bits_per_pixel / 8;
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < yres * 6 / 9; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((struct fb_color24 *)mem)[x] + colors_top[x * 7 / xres];
+ mem += dev->fix_info.line_length;
+ }
+
+ for (; y < yres * 7 / 9; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((struct fb_color24 *)mem)[x] + colors_middle[x * 7 / xres];
+ mem += dev->fix_info.line_length;
+ }
+
+ for (; y < yres; ++y) {
+ for (x = 0; x < xres * 5 / 7; ++x)
+ ((struct fb_color24 *)mem)[x] + colors_bottom[x * 4 / (xres * 5 / 7)];
+ for (; x < xres * 6 / 7; ++x)
+ ((struct fb_color24 *)mem)[x] + colors_bottom[(x - xres * 5 / 7) * 3
+ / (xres / 7) + 4];
+ for (; x < xres; ++x)
+ ((struct fb_color24 *)mem)[x] = colors_bottom[7];
+ mem += dev->fix_info.line_length;
+ }
+}
+
+static void
+fb_fill_rgb32(struct device *dev, unsigned int xoffset, unsigned int yoffset,
+ unsigned int xres, unsigned int yres)
+{
+ const uint32_t colors_top[] = {
+ FB_MAKE_COLOR(&dev->var_info, 192, 192, 192), /* grey */
+ FB_MAKE_COLOR(&dev->var_info, 192, 192, 0), /* yellow */
+ FB_MAKE_COLOR(&dev->var_info, 0, 192, 192), /* cyan */
+ FB_MAKE_COLOR(&dev->var_info, 0, 192, 0), /* green */
+ FB_MAKE_COLOR(&dev->var_info, 192, 0, 192), /* magenta */
+ FB_MAKE_COLOR(&dev->var_info, 192, 0, 0), /* red */
+ FB_MAKE_COLOR(&dev->var_info, 0, 0, 192), /* blue */
+ };
+ const uint32_t colors_middle[] = {
+ FB_MAKE_COLOR(&dev->var_info, 0, 0, 192), /* blue */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR(&dev->var_info, 192, 0, 192), /* magenta */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR(&dev->var_info, 0, 192, 192), /* cyan */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR(&dev->var_info, 192, 192, 192), /* grey */
+ };
+ const uint32_t colors_bottom[] = {
+ FB_MAKE_COLOR(&dev->var_info, 0, 33, 76), /* in-phase */
+ FB_MAKE_COLOR(&dev->var_info, 255, 255, 255), /* super white */
+ FB_MAKE_COLOR(&dev->var_info, 50, 0, 106), /* quadrature */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ FB_MAKE_COLOR(&dev->var_info, 9, 9, 9), /* 3.5% */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* 7.5% */
+ FB_MAKE_COLOR(&dev->var_info, 29, 29, 29), /* 11.5% */
+ FB_MAKE_COLOR(&dev->var_info, 19, 19, 19), /* black */
+ };
+ void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ + xoffset * dev->var_info.bits_per_pixel / 8;
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < yres * 6 / 9; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((uint32_t *)mem)[x] = colors_top[x * 7 / xres];
+ mem += dev->fix_info.line_length;
+ }
+
+ for (; y < yres * 7 / 9; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((uint32_t *)mem)[x] = colors_middle[x * 7 / xres];
+ mem += dev->fix_info.line_length;
+ }
+
+ for (; y < yres; ++y) {
+ for (x = 0; x < xres * 5 / 7; ++x)
+ ((uint32_t *)mem)[x] + colors_bottom[x * 4 / (xres * 5 / 7)];
+ for (; x < xres * 6 / 7; ++x)
+ ((uint32_t *)mem)[x] + colors_bottom[(x - xres * 5 / 7) * 3
+ / (xres / 7) + 4];
+ for (; x < xres; ++x)
+ ((uint32_t *)mem)[x] = colors_bottom[7];
+ mem += dev->fix_info.line_length;
+ }
+}
+
+/*
+ * fb_fill - Fill the frame buffer with an SMPTE test pattern
+ * @dev: FB device
+ * @mode: Fill mode
+ *
+ * Fill the display (when mode is FB_FILL_DISPLAY) or virtual frame buffer area
+ * (when mode is FB_FILL_VIRTUAL) with an SMPTE color bars pattern. Only RGB16,
+ * RGB24 and RGB32 on true color visuals are supported.
+ */
+static void fb_fill(struct device *dev, enum fb_fill_mode mode)
+{
+ unsigned int xoffset, yoffset;
+ unsigned int xres, yres;
+
+ if (dev->fix_info.visual != FB_VISUAL_TRUECOLOR) {
+ printf("Error: test pattern is only supported for true color "
+ "visuals.\n");
+ return;
+ }
+
+ printf("Filling frame buffer with SMPTE test pattern\n");
+
+ if (mode = FB_FILL_DISPLAY) {
+ xoffset = dev->var_info.xoffset;
+ yoffset = dev->var_info.yoffset;
+ xres = dev->var_info.xres;
+ yres = dev->var_info.yres;
+ } else {
+ xoffset = 0;
+ yoffset = 0;
+ xres = dev->var_info.xres_virtual;
+ yres = dev->var_info.yres_virtual;
+ }
+
+ switch (dev->var_info.bits_per_pixel) {
+ case 16:
+ return fb_fill_rgb16(dev, xoffset, yoffset, xres, yres);
+ case 24:
+ return fb_fill_rgb24(dev, xoffset, yoffset, xres, yres);
+ case 32:
+ return fb_fill_rgb32(dev, xoffset, yoffset, xres, yres);
+ default:
+ printf("Error: display depth %u bpp not supported.\n",
+ dev->var_info.bits_per_pixel);
+ break;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Main
+ */
+
+static void usage(const char *argv0)
+{
+ printf("Usage: %s [options] device\n", argv0);
+ printf("Supported options:\n");
+ printf("-b, --blank mode Set blanking mode\n");
+ printf("-f, --fill[=mode] Fill the frame buffer with a test pattern\n");
+ printf("-F, --format bpp Set the number of bits per pixel\n");
+ printf("-h, --help Show this help screen\n");
+ printf("-p, --pan x,y Pan the display to position (x,y)\n");
+ printf("-r, --resolution wxh Set the display resolution to width x height\n");
+ printf("-v, --virtual wxh Set the display virtual resolution to width x height\n");
+ printf("-w, --wait-vsync[=screen] Wait for VSync on the given screen\n");
+ printf("\n");
+ printf("Support fill modes are:\n");
+ printf("display Fill the displayed frame buffer only\n");
+ printf("virtual Fill the whole virtual frame buffer\n");
+ printf("Supported blanking modes are:\n");
+ printf(" off Blanking off, screen active\n");
+ printf(" on Blanked, HSync on, VSync on\n");
+ printf(" vsync Blanked, HSync on, VSync off\n");
+ printf(" hsync Blanked, HSync off, VSync on\n");
+ printf(" powerdown Blanked, HSync off, VSync off\n");
+}
+
+static struct option opts[] = {
+ {"blank", 1, 0, 'b'},
+ {"fill", 2, 0, 'f'},
+ {"format", 1, 0, 'F'},
+ {"help", 0, 0, 'h'},
+ {"pan", 1, 0, 'p'},
+ {"resolution", 1, 0, 'r'},
+ {"virtual", 1, 0, 'v'},
+ {"wait-vsync", 2, 0, 'w'},
+ {0, 0, 0, 0}
+};
+
+static int fb_blank_parse(const char *arg, int *value)
+{
+ static const struct fb_value_name names[] = {
+ { FB_BLANK_UNBLANK, "off" },
+ { FB_BLANK_NORMAL, "on" },
+ { FB_BLANK_VSYNC_SUSPEND, "vsync" },
+ { FB_BLANK_HSYNC_SUSPEND, "hsync" },
+ { FB_BLANK_POWERDOWN, "powerdown" },
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(names); ++i) {
+ if (strcmp(names[i].name, arg) = 0) {
+ *value = names[i].value;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int fb_point_parse(const char *arg, unsigned int *x, unsigned int *y)
+{
+ unsigned long value;
+ char *endptr;
+
+ value = strtoul(arg, &endptr, 10);
+ if (endptr = arg || *endptr != ',')
+ return -1;
+ *x = value;
+ arg = endptr + 1;
+
+ value = strtoul(arg, &endptr, 10);
+ if (endptr = arg || *endptr != '\0')
+ return -1;
+ *y = value;
+
+ return 0;
+}
+
+static int fb_size_parse(const char *arg, int *x, int *y)
+{
+ unsigned long value;
+ char *endptr;
+
+ value = strtoul(arg, &endptr, 10);
+ if (endptr = arg || *endptr != 'x')
+ return -1;
+ *x = value;
+ arg = endptr + 1;
+
+ value = strtoul(arg, &endptr, 10);
+ if (endptr = arg || *endptr != '\0')
+ return -1;
+ *y = value;
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ struct device dev;
+ int ret;
+
+ /* Options parsing. */
+ bool do_blank = false;
+ int blank = 0;
+
+ enum fb_fill_mode fill_mode = FB_FILL_NONE;
+
+ bool do_format = false;
+ unsigned int bpp = 0;
+
+ bool do_pan = false;
+ unsigned int pan_x = 0;
+ unsigned int pan_y = 0;
+
+ bool do_resolution = false;
+ int xres = -1;
+ int yres = -1;
+ int xres_virtual = -1;
+ int yres_virtual = -1;
+
+ bool do_wait_for_vsync = false;
+ unsigned int screen = 0;
+
+ int c;
+
+ opterr = 0;
+ while ((c = getopt_long(argc, argv, "b:f::F:hp:r:v:w::", opts, NULL)) != -1) {
+
+ switch (c) {
+ case 'b':
+ do_blank = true;
+ if (fb_blank_parse(optarg, &blank) < 0) {
+ printf("Invalid blanking mode `%s'\n", optarg);
+ printf("Run %s -h for help.\n", argv[0]);
+ return 1;
+ }
+ break;
+ case 'f':
+ if (optarg = NULL)
+ fill_mode = FB_FILL_DISPLAY;
+ else if (strcmp(optarg, "display") = 0)
+ fill_mode = FB_FILL_DISPLAY;
+ else if (strcmp(optarg, "virtual") = 0)
+ fill_mode = FB_FILL_VIRTUAL;
+ else {
+ printf("Invalid fill mode `%s'\n", optarg);
+ printf("Run %s -h for help.\n", argv[0]);
+ return 1;
+ }
+ break;
+ case 'F':
+ do_format = true;
+ bpp = atoi(optarg);
+ break;
+ case 'h':
+ usage(argv[0]);
+ return 0;
+ case 'p':
+ do_pan = true;
+ if (fb_point_parse(optarg, &pan_x, &pan_y) < 0) {
+ printf("Invalid pan point `%s'\n", optarg);
+ printf("Run %s -h for help.\n", argv[0]);
+ return 1;
+ }
+ break;
+ case 'r':
+ do_resolution = true;
+ if (fb_size_parse(optarg, &xres, &yres) < 0) {
+ printf("Invalid resolution `%s'\n", optarg);
+ printf("Run %s -h for help.\n", argv[0]);
+ return 1;
+ }
+ break;
+ case 'v':
+ do_resolution = true;
+ if (fb_size_parse(optarg, &xres_virtual, &yres_virtual) < 0) {
+ printf("Invalid virtual resolution `%s'\n", optarg);
+ printf("Run %s -h for help.\n", argv[0]);
+ return 1;
+ }
+ break;
+ case 'w':
+ do_wait_for_vsync = true;
+ if (optarg)
+ screen = atoi(optarg);
+ break;
+ default:
+ printf("Invalid option -%c\n", c);
+ printf("Run %s -h for help.\n", argv[0]);
+ return 1;
+ }
+ }
+
+ if (optind >= argc) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ ret = fb_open(&dev, argv[optind]);
+ if (ret < 0)
+ return 1;
+
+ if (do_blank)
+ fb_blank(&dev, blank);
+
+ if (do_format)
+ fb_set_format(&dev, bpp);
+
+ if (do_resolution)
+ fb_set_resolution(&dev, xres, yres, xres_virtual, yres_virtual);
+
+ if (fill_mode != FB_FILL_NONE)
+ fb_fill(&dev, fill_mode);
+
+ if (do_pan)
+ fb_pan(&dev, pan_x, pan_y);
+
+ if (do_wait_for_vsync)
+ fb_wait_for_vsync(&dev, screen);
+
+ fb_close(&dev);
+ return 0;
+}
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: fbdev test application
From: Geert Uytterhoeven @ 2011-04-30 17:13 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201104301643.23482.laurent.pinchart@ideasonboard.com>
On Sat, Apr 30, 2011 at 16:43, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi everybody,
>
> I've developed a small fbdev application for internal test purpose that might
> be useful to other developers, so I'm releasing it under the GPL.
Have you ever looked at
http://git.kernel.org/?p=linux/kernel/git/geert/fbtest.git,
which is a git clone of CVS module FBdev/utlilities/fbtest of project
linux-fbdev on
sf.net?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: fbdev test application
From: Laurent Pinchart @ 2011-04-30 17:31 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201104301643.23482.laurent.pinchart@ideasonboard.com>
Hi Geert,
On Saturday 30 April 2011 19:13:47 Geert Uytterhoeven wrote:
> On Sat, Apr 30, 2011 at 16:43, Laurent Pinchart
>
> <laurent.pinchart@ideasonboard.com> wrote:
> > Hi everybody,
> >
> > I've developed a small fbdev application for internal test purpose that
> > might be useful to other developers, so I'm releasing it under the GPL.
>
> Have you ever looked at
> http://git.kernel.org/?p=linux/kernel/git/geert/fbtest.git,
> which is a git clone of CVS module FBdev/utlilities/fbtest of project
> linux-fbdev on sf.net?
I've seen the project, but my fbdev test application serves slightly different
purposes, as I wanted to control FB devices from the command line, not run a
test suite. It was also a way for me to learn the FB API, no existing
application could have properly helped me there :-)
I see that fbtest.git hasn't been updated for quite some time. Do you think we
should try to merge the projects ?
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: fbdev test application
From: Geert Uytterhoeven @ 2011-04-30 18:30 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201104301643.23482.laurent.pinchart@ideasonboard.com>
Hi Laurent,
On Sat, Apr 30, 2011 at 19:31, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> On Saturday 30 April 2011 19:13:47 Geert Uytterhoeven wrote:
>> On Sat, Apr 30, 2011 at 16:43, Laurent Pinchart
>> > I've developed a small fbdev application for internal test purpose that
>> > might be useful to other developers, so I'm releasing it under the GPL.
>>
>> Have you ever looked at
>> http://git.kernel.org/?p=linux/kernel/git/geert/fbtest.git,
>> which is a git clone of CVS module FBdev/utlilities/fbtest of project
>> linux-fbdev on sf.net?
>
> I've seen the project, but my fbdev test application serves slightly different
> purposes, as I wanted to control FB devices from the command line, not run a
Ah, so it's more like fbset.
> test suite. It was also a way for me to learn the FB API, no existing
> application could have properly helped me there :-)
IC...
> I see that fbtest.git hasn't been updated for quite some time. Do you think we
> should try to merge the projects ?
Perhaps, if you're willing to spend time on it. I don't think I can
work much on it
currently.
One big advantage of fbtest is that it knows how to draw on whatever
frame buffer
format and visual, while most fbdev apps support cfb8 in pseudocolor
and cfb32 in
truecolor only.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 0/2] OMAP: DSS: Support new dpi panels
From: Enric Balletbo i Serra @ 2011-05-02 10:29 UTC (permalink / raw)
To: tomi.valkeinen, linux-omap, linux-fbdev; +Cc: Enric Balletbo i Serra
Hi all,
These patches add support for two new panels to the generic-dpi-panel.
The first patch adds support for the Seiko 70WVW1TZ3 LCD panel, and the second
adds support for the Powertip PH480272T LCD panel.
Tested with an IGEP v2 board.
Please consider to add in next merge window, thanks,
Enric Balletbo i Serra (2):
OMAP: DSS2: Support for Seiko 70WVW1TZ3
OMAP: DSS2: Support for Powertip PH480272T
drivers/video/omap2/displays/panel-generic-dpi.c | 50 ++++++++++++++++++++++
1 files changed, 50 insertions(+), 0 deletions(-)
^ permalink raw reply
* [PATCH 1/2] OMAP: DSS2: Support for Seiko 70WVW1TZ3
From: Enric Balletbo i Serra @ 2011-05-02 10:29 UTC (permalink / raw)
To: tomi.valkeinen, linux-omap, linux-fbdev; +Cc: Enric Balletbo i Serra
In-Reply-To: <1304332184-14687-1-git-send-email-eballetbo@iseebcn.com>
Add support for Seiko 70WVW1TZ3, a LCD 7.0inch WVGA (800x480) display
type with 24-bit RGB interface and Touch-Panel, to panel-generic-dpi.
Signed-off-by: Enric Balletbo i Serra <eballetbo@iseebcn.com>
---
drivers/video/omap2/displays/panel-generic-dpi.c | 25 ++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 4a9b9ff..e8819ee 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -181,6 +181,31 @@ static struct panel_config generic_dpi_panels[] = {
.power_off_delay = 0,
.name = "samsung_lte430wq_f0c",
},
+
+ /* Seiko 70WVW1TZ3Z3 */
+ {
+ {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 33000,
+
+ .hsw = 128,
+ .hfp = 10,
+ .hbp = 10,
+
+ .vsw = 2,
+ .vfp = 4,
+ .vbp = 11,
+ },
+ .acbi = 0x0,
+ .acb = 0x0,
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .power_on_delay = 0,
+ .power_off_delay = 0,
+ .name = "70wvw1tz3",
+ },
};
struct panel_drv_data {
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/2] OMAP: DSS2: Support for Powertip PH480272T
From: Enric Balletbo i Serra @ 2011-05-02 10:29 UTC (permalink / raw)
To: tomi.valkeinen, linux-omap, linux-fbdev; +Cc: Enric Balletbo i Serra
In-Reply-To: <1304332184-14687-1-git-send-email-eballetbo@iseebcn.com>
Add support for Powertip PH480242T, a LCD 4.3inch (480x242) display
type with 24-bit RGB interface, to panel-generic-dpi.
Signed-off-by: Enric Balletbo i Serra <eballetbo@iseebcn.com>
---
drivers/video/omap2/displays/panel-generic-dpi.c | 25 ++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index e8819ee..3250a85 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -206,6 +206,31 @@ static struct panel_config generic_dpi_panels[] = {
.power_off_delay = 0,
.name = "70wvw1tz3",
},
+
+ /* Powertip PH480272T */
+ {
+ {
+ .x_res = 480,
+ .y_res = 272,
+
+ .pixel_clock = 9000,
+
+ .hsw = 40,
+ .hfp = 2,
+ .hbp = 2,
+
+ .vsw = 10,
+ .vfp = 2,
+ .vbp = 2,
+ },
+ .acbi = 0x0,
+ .acb = 0x0,
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
+ .power_on_delay = 0,
+ .power_off_delay = 0,
+ .name = "ph480272t",
+ },
};
struct panel_drv_data {
--
1.7.0.4
^ permalink raw reply related
* Query: Implementation of overlay on linux
From: vipul kumar samar @ 2011-05-02 11:16 UTC (permalink / raw)
To: linux-media, linux-fbdev
In-Reply-To: <4DB6CE44.2020000@st.com>
Hello,
I am working on LCD module and I want to implement two overlay windows
on frame buffer. I have some queries related to this:
1. Can any body suggest me how to proceed towards it??
2. Is their any standard way to use frame buffer ioctl calls??
3. If i have to define my own ioctls then how application manage it??
Thanks and Regards
Vipul Samar
^ permalink raw reply
* Re: Query: Implementation of overlay on linux
From: Hans Verkuil @ 2011-05-02 13:20 UTC (permalink / raw)
To: vipul kumar samar; +Cc: linux-media, linux-fbdev
In-Reply-To: <4DBE8FDB.5010506@st.com>
On Monday, May 02, 2011 13:04:59 vipul kumar samar wrote:
> Hello,
>
> I am working on LCD module and I want to implement two overlay windows
> on frame buffer. I have some queries related to this:
You mean capture overlay windows? E.g. you want to capture from a video input
and have the video directly rendered in the framebuffer?
The "Video Overlay Interface" section in the V4L2 specification describes how
to do that, but it also depends on whether the V4L2 driver in question
supports that feature.
It might be that you mean something else, though.
Regards,
Hans
> 1. Can any body suggest me how to proceed towards it??
> 2. Is their any standard way to use frame buffer ioctl calls??
> 3. If i have to define my own ioctls then how application manage it??
>
>
> Thanks and Regards
> Vipul Samar
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
^ permalink raw reply
* Login prompt on a video console instead of serial port?
From: Timur Tabi @ 2011-05-02 19:30 UTC (permalink / raw)
To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, devicetree-discuss,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA
I'm using a Freescale P1022DS (PowerPC e500 core) system, which has a built-in
video controller. I have a framebuffer driver that works fine, and if I add
"video=fslfb:1280x1024-32@60,monitor=0 console=tty0" to the command-line, then
*most* of the kernel boot log appears on the serial port and the video display.
However, the login prompt is always on the serial port. This happens even if I
delete the "console=ttyS0,115200" from the command-line. I presume this is
because the "linux,stdout-path" property in the device tree always points to a
serial port node.
So my question is: what do I need to do get the login prompt on the video
console? That is, stdout goes to /dev/fb0 but stdin is still from /dev/ttyS0.
I presume I need to direct "linux,stdout-path" to the fslfb node in the device
tree, but there doesn't appear to be support for "linux,stdin-path".
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox