2006-07-03 00:24:19 -07:00
/*
* drivers / video / pnx4008 / pnxrgbfb . c
*
* PNX4008 ' s framebuffer support
*
* Author : Grigory Tolstolytkin < gtolstolytkin @ ru . mvista . com >
* Based on Philips Semiconductors ' s code
*
* Copyrght ( c ) 2005 MontaVista Software , Inc .
* Copyright ( c ) 2005 Philips Semiconductors
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed " as is " without any warranty of any
* kind , whether express or implied .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/string.h>
# include <linux/mm.h>
# include <linux/vmalloc.h>
# include <linux/delay.h>
# include <linux/interrupt.h>
# include <linux/fb.h>
# include <linux/init.h>
# include <linux/platform_device.h>
# include "sdum.h"
# include "fbcommon.h"
static u32 colreg [ 16 ] ;
static struct fb_var_screeninfo rgbfb_var __initdata = {
. xres = LCD_X_RES ,
. yres = LCD_Y_RES ,
. xres_virtual = LCD_X_RES ,
. yres_virtual = LCD_Y_RES ,
. bits_per_pixel = 32 ,
. red . offset = 16 ,
. red . length = 8 ,
. green . offset = 8 ,
. green . length = 8 ,
. blue . offset = 0 ,
. blue . length = 8 ,
. left_margin = 0 ,
. right_margin = 0 ,
. upper_margin = 0 ,
. lower_margin = 0 ,
. vmode = FB_VMODE_NONINTERLACED ,
} ;
static struct fb_fix_screeninfo rgbfb_fix __initdata = {
. id = " RGBFB " ,
. line_length = LCD_X_RES * LCD_BBP ,
. type = FB_TYPE_PACKED_PIXELS ,
. visual = FB_VISUAL_TRUECOLOR ,
. xpanstep = 0 ,
. ypanstep = 0 ,
. ywrapstep = 0 ,
. accel = FB_ACCEL_NONE ,
} ;
static int channel_owned ;
static int no_cursor ( struct fb_info * info , struct fb_cursor * cursor )
{
return 0 ;
}
static int rgbfb_setcolreg ( u_int regno , u_int red , u_int green , u_int blue ,
u_int transp , struct fb_info * info )
{
if ( regno > 15 )
return 1 ;
colreg [ regno ] = ( ( red & 0xff00 ) < < 8 ) | ( green & 0xff00 ) |
( ( blue & 0xff00 ) > > 8 ) ;
return 0 ;
}
static int rgbfb_mmap ( struct fb_info * info , struct vm_area_struct * vma )
{
return pnx4008_sdum_mmap ( info , vma , NULL ) ;
}
static struct fb_ops rgbfb_ops = {
. fb_mmap = rgbfb_mmap ,
. fb_setcolreg = rgbfb_setcolreg ,
. fb_fillrect = cfb_fillrect ,
. fb_copyarea = cfb_copyarea ,
. fb_imageblit = cfb_imageblit ,
} ;
static int rgbfb_remove ( struct platform_device * pdev )
{
struct fb_info * info = platform_get_drvdata ( pdev ) ;
if ( info ) {
unregister_framebuffer ( info ) ;
fb_dealloc_cmap ( & info - > cmap ) ;
framebuffer_release ( info ) ;
platform_set_drvdata ( pdev , NULL ) ;
}
pnx4008_free_dum_channel ( channel_owned , pdev - > id ) ;
pnx4008_set_dum_exit_notification ( pdev - > id ) ;
return 0 ;
}
static int __devinit rgbfb_probe ( struct platform_device * pdev )
{
struct fb_info * info ;
struct dumchannel_uf chan_uf ;
int ret ;
char * option ;
info = framebuffer_alloc ( sizeof ( u32 ) * 16 , & pdev - > dev ) ;
if ( ! info ) {
ret = - ENOMEM ;
goto err ;
}
pnx4008_get_fb_addresses ( FB_TYPE_RGB , ( void * * ) & info - > screen_base ,
( dma_addr_t * ) & rgbfb_fix . smem_start ,
& rgbfb_fix . smem_len ) ;
if ( ( ret = pnx4008_alloc_dum_channel ( pdev - > id ) ) < 0 )
goto err0 ;
else {
channel_owned = ret ;
chan_uf . channelnr = channel_owned ;
chan_uf . dirty = ( u32 * ) NULL ;
chan_uf . source = ( u32 * ) rgbfb_fix . smem_start ;
chan_uf . x_offset = 0 ;
chan_uf . y_offset = 0 ;
chan_uf . width = LCD_X_RES ;
chan_uf . height = LCD_Y_RES ;
if ( ( ret = pnx4008_put_dum_channel_uf ( chan_uf , pdev - > id ) ) < 0 )
goto err1 ;
if ( ( ret =
pnx4008_set_dum_channel_sync ( channel_owned , CONF_SYNC_ON ,
pdev - > id ) ) < 0 )
goto err1 ;
if ( ( ret =
pnx4008_set_dum_channel_dirty_detect ( channel_owned ,
CONF_DIRTYDETECTION_ON ,
pdev - > id ) ) < 0 )
goto err1 ;
}
2006-11-16 01:19:14 -08:00
if ( ! fb_get_options ( " pnxrgbfb " , & option ) & & option & &
! strcmp ( option , " nocursor " ) )
2006-07-03 00:24:19 -07:00
rgbfb_ops . fb_cursor = no_cursor ;
info - > node = - 1 ;
info - > flags = FBINFO_FLAG_DEFAULT ;
info - > fbops = & rgbfb_ops ;
info - > fix = rgbfb_fix ;
info - > var = rgbfb_var ;
info - > screen_size = rgbfb_fix . smem_len ;
info - > pseudo_palette = info - > par ;
info - > par = NULL ;
ret = fb_alloc_cmap ( & info - > cmap , 256 , 0 ) ;
if ( ret < 0 )
2008-05-12 14:02:16 -07:00
goto err1 ;
2006-07-03 00:24:19 -07:00
ret = register_framebuffer ( info ) ;
if ( ret < 0 )
2008-05-12 14:02:16 -07:00
goto err2 ;
2006-07-03 00:24:19 -07:00
platform_set_drvdata ( pdev , info ) ;
return 0 ;
err2 :
2008-05-12 14:02:16 -07:00
fb_dealloc_cmap ( & info - > cmap ) ;
2006-07-03 00:24:19 -07:00
err1 :
pnx4008_free_dum_channel ( channel_owned , pdev - > id ) ;
err0 :
2008-05-12 14:02:16 -07:00
framebuffer_release ( info ) ;
2006-07-03 00:24:19 -07:00
err :
return ret ;
}
static struct platform_driver rgbfb_driver = {
. driver = {
2006-11-16 01:19:11 -08:00
. name = " pnx4008-rgbfb " ,
2006-07-03 00:24:19 -07:00
} ,
. probe = rgbfb_probe ,
. remove = rgbfb_remove ,
} ;
2011-12-09 10:01:15 +08:00
module_platform_driver ( rgbfb_driver ) ;
2006-07-03 00:24:19 -07:00
MODULE_LICENSE ( " GPL " ) ;