From 16624522eb677d10c3846f25283f95530a7d5017 Mon Sep 17 00:00:00 2001 From: Arthur Spence Date: Thu, 20 May 2010 13:25:29 -0700 Subject: 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 Tested-by: Arthur Spence --- arch/arm/mach-tegra/include/nvbootargs.h | 16 +++- arch/arm/mach-tegra/nvos/nvos.c | 16 +++- drivers/video/tegra-fb.c | 125 ++++++++++++++++++++++++++++--- 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); -- cgit v1.2.3