summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorArthur Spence <aspence@nvidia.com>2010-05-20 13:25:29 -0700
committerGary King <gking@nvidia.com>2010-05-25 10:44:01 -0700
commit16624522eb677d10c3846f25283f95530a7d5017 (patch)
treee4dfd0d5c2fd6e8a9d0607119fed07647f08ee4e /drivers
parent5d5cbf7c3abb9220a3583eade382e4361950a648 (diff)
tegra framebuffer - dsi one shot support
DSI one shot support requires register access in the tegra framebuffer to poke the frame trigger bit (with both the trigger bit and the tearing effect signal are high, a frame of pixels will be sent to the panel). The boot args must also be expanded to have a "use tearing effect" flag. Change-Id: Id0c3960cac5b59dd23fd6547f1b7dae4d422ac32 Reviewed-on: http://git-master/r/1460 Reviewed-by: Gary King <gking@nvidia.com> Tested-by: Arthur Spence <aspence@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra-fb.c125
1 files changed, 116 insertions, 9 deletions
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);