summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/include/nvbootargs.h16
-rw-r--r--arch/arm/mach-tegra/nvos/nvos.c16
-rw-r--r--drivers/video/tegra-fb.c125
3 files changed, 141 insertions, 16 deletions
diff --git a/arch/arm/mach-tegra/include/nvbootargs.h b/arch/arm/mach-tegra/include/nvbootargs.h
index 908c26f0ea52..2e11843a9a68 100644
--- a/arch/arm/mach-tegra/include/nvbootargs.h
+++ b/arch/arm/mach-tegra/include/nvbootargs.h
@@ -94,6 +94,7 @@ typedef struct NvBootArgsCarveoutRec
*/
typedef struct NvBootArgsWarmbootRec
{
+ /* The key used for accessing the preserved memory handle */
NvU32 MemHandleKey;
} NvBootArgsWarmboot;
@@ -112,7 +113,6 @@ typedef struct NvBootArgsPreservedMemHandleRec
NvU32 Size;
} NvBootArgsPreservedMemHandle;
-
/**
* Display boot args, indexed by NvBootArgKey_Display.
*
@@ -162,6 +162,16 @@ typedef struct NvBootArgsFramebufferRec
* assumed to begin at Pitch * Height bytes from the
* previous surface. */
NvU8 NumSurfaces;
+ /* Flags for future expandability.
+ * Current allowable flags are:
+ * zero - default
+ * NV_BOOT_ARGS_FB_FLAG_TEARING_EFFECT - use a tearing effect signal in
+ * combination with a trigger from the display software to generate
+ * a frame of pixels for the display device.
+ */
+ NvU32 Flags;
+#define NVBOOTARG_FB_FLAG_TEARING_EFFECT (0x1)
+
} NvBootArgsFramebuffer;
/**
@@ -210,8 +220,8 @@ typedef struct NvBootArgsChipShmooPhysRec
NvU32 Size;
} NvBootArgsChipShmooPhys;
-#define NVBOOTARG_NUM_PRESERVED_HANDLES (NvBootArgKey_PreservedMemHandle_Num - \
- NvBootArgKey_PreservedMemHandle_0)
+#define NVBOOTARG_NUM_PRESERVED_HANDLES \
+ (NvBootArgKey_PreservedMemHandle_Num - NvBootArgKey_PreservedMemHandle_0)
/**
* OS-agnostic bootarg structure.
diff --git a/arch/arm/mach-tegra/nvos/nvos.c b/arch/arm/mach-tegra/nvos/nvos.c
index 9b4329b97dc4..4de8cd4be33f 100644
--- a/arch/arm/mach-tegra/nvos/nvos.c
+++ b/arch/arm/mach-tegra/nvos/nvos.c
@@ -1445,8 +1445,7 @@ NvError NvOsBootArgGet(NvU32 key, void *arg, NvU32 size)
}
else
{
- switch (key)
- {
+ switch (key) {
case NvBootArgKey_ChipShmoo:
src = &s_BootArgs.ChipShmooArgs;
size_src = sizeof(NvBootArgsChipShmoo);
@@ -1478,10 +1477,19 @@ NvError NvOsBootArgGet(NvU32 key, void *arg, NvU32 size)
}
}
- if (!arg || !src || (size_src!=size))
+ if( !arg || !src )
+ {
return NvError_BadParameter;
+ }
- NvOsMemcpy(arg, src, size_src);
+ /* don't copy too much if the size has changed (gotten bigger in new
+ * binaries.
+ */
+ NvOsMemcpy(arg, src, NV_MIN( size, size_src) );
+ if( size > size_src )
+ {
+ NvOsMemset( (NvU8 *)src + size_src, 0, size - size_src );
+ }
return NvSuccess;
}
diff --git a/drivers/video/tegra-fb.c b/drivers/video/tegra-fb.c
index 24a90213ecdc..fa18ad494c79 100644
--- a/drivers/video/tegra-fb.c
+++ b/drivers/video/tegra-fb.c
@@ -3,7 +3,7 @@
*
* Dumb framebuffer driver for NVIDIA Tegra SoCs
*
- * Copyright (C) 2009 NVIDIA Corporation
+ * Copyright (C) 2009 - 2010 NVIDIA Corporation
*
* 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
@@ -37,6 +37,7 @@
#include "nvbootargs.h"
#include "nvrm_module.h"
#include "nvrm_memmgr.h"
+#include "nvrm_power.h"
#include "nvrm_ioctls.h"
static struct fb_info tegra_fb_info = {
@@ -50,6 +51,8 @@ static struct fb_info tegra_fb_info = {
.line_length = 800 * 2,
},
+ // these values are just defaults. they will be over-written with the
+ // correct values from the boot args.
.var = {
.xres = 800,
.yres = 480,
@@ -74,12 +77,19 @@ static struct fb_info tegra_fb_info = {
},
};
-unsigned long s_fb_addr;
-unsigned long s_fb_size;
-unsigned long s_fb_width;
-unsigned long s_fb_height;
-int s_fb_Bpp;
-NvRmMemHandle s_fb_hMem;
+static unsigned long s_fb_addr;
+static unsigned long s_fb_size;
+static unsigned long s_fb_width;
+static unsigned long s_fb_height;
+static int s_fb_Bpp;
+static NvRmMemHandle s_fb_hMem;
+static unsigned long *s_fb_regs;
+static unsigned short s_use_tearing_effect;
+static unsigned long s_power_id = (unsigned long)-1;
+
+#define DISPLAY_BASE (0x54200000)
+#define REGW( reg, val ) \
+ *(s_fb_regs + (reg)) = (val)
/* palette attary used by the fbcon */
u32 pseudo_palette[16];
@@ -159,6 +169,85 @@ int tegra_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
return 0;
}
+static NvBool tegra_fb_power_register( void )
+{
+ if( s_power_id != (unsigned long)-1 )
+ {
+ return NV_TRUE;
+ }
+
+ if( NvRmPowerRegister( s_hRmGlobal, 0, &s_power_id ) != NvSuccess )
+ {
+ printk( "nvtegrafb: unable to load power manager\n" );
+ return NV_FALSE;
+ }
+
+ return NV_TRUE;
+}
+
+static NvBool tegra_fb_power_on( void )
+{
+ if( NvRmPowerVoltageControl( s_hRmGlobal,
+ NVRM_MODULE_ID( NvRmModuleID_GraphicsHost, 0 ),
+ s_power_id, NvRmVoltsUnspecified, NvRmVoltsUnspecified,
+ NULL, 0, NULL ) != NvSuccess )
+ {
+ printk( "nvtegrafb: unable to enable graphics host power\n" );
+ return NV_FALSE;
+ }
+
+ if( NvRmPowerVoltageControl( s_hRmGlobal,
+ NVRM_MODULE_ID( NvRmModuleID_Display, 0 ),
+ s_power_id, NvRmVoltsUnspecified, NvRmVoltsUnspecified,
+ NULL, 0, NULL ) != NvSuccess )
+ {
+ printk( "nvtegrafb: unable to enable display power\n" );
+ return NV_FALSE;
+ }
+
+ NvRmPowerModuleClockControl( s_hRmGlobal, NvRmModuleID_GraphicsHost,
+ s_power_id, NV_TRUE );
+
+ return NV_TRUE;
+}
+
+static void tegra_fb_power_off( void )
+{
+ // this will most likely not actually disable power to the display,
+ // but will make it such that the power reference count is correct
+ NvRmPowerVoltageControl( s_hRmGlobal,
+ NVRM_MODULE_ID( NvRmModuleID_GraphicsHost, 0 ),
+ s_power_id, NvRmVoltsOff, NvRmVoltsOff,
+ NULL, 0, NULL );
+
+ NvRmPowerVoltageControl( s_hRmGlobal,
+ NVRM_MODULE_ID( NvRmModuleID_Display, 0 ),
+ s_power_id, NvRmVoltsOff, NvRmVoltsOff,
+ NULL, 0, NULL );
+
+ NvRmPowerModuleClockControl( s_hRmGlobal, NvRmModuleID_GraphicsHost,
+ s_power_id, NV_FALSE );
+}
+
+static void tegra_fb_trigger_frame( void )
+{
+ if( !s_use_tearing_effect )
+ {
+ return;
+ }
+
+ if( !tegra_fb_power_on() )
+ {
+ return;
+ }
+
+ // state control: write the host trigger bit (24) along with a general
+ // activation request (bit 0)
+ REGW( 0x41, (1 << 24) | 1 );
+
+ tegra_fb_power_off();
+}
+
int tegra_fb_blank(int blank, struct fb_info *info)
{
return 0;
@@ -167,16 +256,19 @@ int tegra_fb_blank(int blank, struct fb_info *info)
void tegra_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
cfb_fillrect(info, rect);
+ tegra_fb_trigger_frame();
}
void tegra_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
cfb_copyarea(info, region);
+ tegra_fb_trigger_frame();
}
void tegra_fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
cfb_imageblit(info, image);
+ tegra_fb_trigger_frame();
}
int tegra_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
@@ -196,23 +288,34 @@ static int tegra_plat_probe( struct platform_device *d )
e = NvOsBootArgGet(NvBootArgKey_Framebuffer, &boot_fb, sizeof(boot_fb));
if (e != NvSuccess || !boot_fb.MemHandleKey) {
- printk("tegrafb: bootargs not found\n");
+ printk("nvtegrafb: bootargs not found\n");
return -1;
}
e = NvRmMemHandleClaimPreservedHandle(s_hRmGlobal, boot_fb.MemHandleKey,
&s_fb_hMem );
if (e != NvSuccess) {
- printk("tegrafb: Unable to query bootup framebuffer memory.\n");
+ printk("nvtegrafb: Unable to query bootup framebuffer memory.\n");
return -1;
}
+ tegra_fb_power_register();
+
s_fb_width = boot_fb.Width;
s_fb_height = boot_fb.Height * boot_fb.NumSurfaces;
s_fb_size = boot_fb.Size;
s_fb_addr = NvRmMemPin(s_fb_hMem);
s_fb_Bpp = NV_COLOR_GET_BPP(boot_fb.ColorFormat) >> 3;
+ /* need to poke a trigger register if the tearing effect signal is
+ * used
+ */
+ if( boot_fb.Flags & NVBOOTARG_FB_FLAG_TEARING_EFFECT )
+ {
+ s_fb_regs = ioremap_nocache( DISPLAY_BASE, 256 * 1024 );
+ s_use_tearing_effect = 1;
+ }
+
tegra_fb_info.fix.smem_start = s_fb_addr;
tegra_fb_info.fix.smem_len = s_fb_size;
tegra_fb_info.fix.line_length = boot_fb.Pitch;
@@ -281,6 +384,10 @@ static int __init tegra_fb_init(void)
static void __exit tegra_exit( void )
{
+ tegra_fb_power_off();
+
+ NvRmPowerUnRegister( s_hRmGlobal, s_power_id );
+
unregister_framebuffer(&tegra_fb_info);
}
module_exit(tegra_exit);