2008-10-16 12:03:27 +07:00
|
|
|
/*
|
2009-05-19 16:12:58 +07:00
|
|
|
* Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
|
2008-10-16 12:03:27 +07:00
|
|
|
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
* 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, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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.,
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
2009-09-23 06:47:27 +07:00
|
|
|
#include <linux/seq_file.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 15:04:11 +07:00
|
|
|
#include <linux/slab.h>
|
2009-09-23 06:47:32 +07:00
|
|
|
#include <linux/stat.h>
|
2010-05-06 03:44:55 +07:00
|
|
|
#include <linux/via-core.h>
|
2011-05-11 04:34:11 +07:00
|
|
|
#include <asm/olpc.h>
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-05-06 03:44:55 +07:00
|
|
|
#define _MASTER_FILE
|
2008-10-16 12:03:27 +07:00
|
|
|
#include "global.h"
|
|
|
|
|
|
|
|
static char *viafb_name = "Via";
|
|
|
|
static u32 pseudo_pal[17];
|
|
|
|
|
|
|
|
/* video mode */
|
2010-03-11 06:21:34 +07:00
|
|
|
static char *viafb_mode;
|
|
|
|
static char *viafb_mode1;
|
2010-03-11 06:21:37 +07:00
|
|
|
static int viafb_bpp = 32;
|
|
|
|
static int viafb_bpp1 = 32;
|
|
|
|
|
2011-03-27 09:54:32 +07:00
|
|
|
static unsigned int viafb_second_xres = 640;
|
|
|
|
static unsigned int viafb_second_yres = 480;
|
2010-03-11 06:21:37 +07:00
|
|
|
static unsigned int viafb_second_offset;
|
|
|
|
static int viafb_second_size;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:31 +07:00
|
|
|
static int viafb_accel = 1;
|
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
/* Added for specifying active devices.*/
|
2011-03-04 01:00:08 +07:00
|
|
|
static char *viafb_active_dev;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
/*Added for specify lcd output port*/
|
2011-03-04 01:00:08 +07:00
|
|
|
static char *viafb_lcd_port = "";
|
|
|
|
static char *viafb_dvi_port = "";
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
static void retrieve_device_setting(struct viafb_ioctl_setting
|
|
|
|
*setting_info);
|
2010-03-11 06:21:32 +07:00
|
|
|
static int viafb_pan_display(struct fb_var_screeninfo *var,
|
|
|
|
struct fb_info *info);
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
static struct fb_ops viafb_ops;
|
|
|
|
|
2010-09-19 11:20:55 +07:00
|
|
|
/* supported output devices on each IGP
|
2010-10-24 11:02:14 +07:00
|
|
|
* only CX700, VX800, VX855, VX900 were documented
|
2010-09-19 11:20:55 +07:00
|
|
|
* VIA_CRT should be everywhere
|
|
|
|
* VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL
|
|
|
|
* source selection on CX700 and later
|
|
|
|
* K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
|
|
|
|
*/
|
|
|
|
static const u32 supported_odev_map[] = {
|
2010-09-19 11:40:15 +07:00
|
|
|
[UNICHROME_CLE266] = VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
|
|
|
|
[UNICHROME_K400] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
|
2010-09-19 11:20:55 +07:00
|
|
|
| VIA_LVDS2,
|
2010-09-19 11:40:15 +07:00
|
|
|
[UNICHROME_K800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
|
2010-09-19 11:20:55 +07:00
|
|
|
| VIA_LVDS2,
|
2010-09-19 11:40:15 +07:00
|
|
|
[UNICHROME_PM800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
|
2010-09-19 11:20:55 +07:00
|
|
|
| VIA_LVDS2,
|
2010-09-19 11:40:15 +07:00
|
|
|
[UNICHROME_CN700] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
|
2010-09-19 11:20:55 +07:00
|
|
|
| VIA_LVDS2,
|
|
|
|
[UNICHROME_CX700] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
|
|
|
|
[UNICHROME_CN750] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
|
|
|
|
[UNICHROME_K8M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
|
|
|
|
[UNICHROME_P4M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
|
|
|
|
[UNICHROME_P4M900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
|
|
|
|
[UNICHROME_VX800] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
|
|
|
|
[UNICHROME_VX855] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
|
2010-10-24 11:02:14 +07:00
|
|
|
[UNICHROME_VX900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
|
2010-09-19 11:20:55 +07:00
|
|
|
};
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-03-11 06:21:38 +07:00
|
|
|
static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
|
|
|
|
{
|
|
|
|
var->grayscale = 0;
|
|
|
|
var->red.msb_right = 0;
|
|
|
|
var->green.msb_right = 0;
|
|
|
|
var->blue.msb_right = 0;
|
|
|
|
var->transp.offset = 0;
|
|
|
|
var->transp.length = 0;
|
|
|
|
var->transp.msb_right = 0;
|
|
|
|
var->nonstd = 0;
|
|
|
|
switch (depth) {
|
|
|
|
case 8:
|
|
|
|
var->bits_per_pixel = 8;
|
|
|
|
var->red.offset = 0;
|
|
|
|
var->green.offset = 0;
|
|
|
|
var->blue.offset = 0;
|
2010-03-11 06:21:40 +07:00
|
|
|
var->red.length = 8;
|
|
|
|
var->green.length = 8;
|
|
|
|
var->blue.length = 8;
|
2010-03-11 06:21:38 +07:00
|
|
|
break;
|
2010-03-11 06:21:41 +07:00
|
|
|
case 15:
|
|
|
|
var->bits_per_pixel = 16;
|
|
|
|
var->red.offset = 10;
|
|
|
|
var->green.offset = 5;
|
|
|
|
var->blue.offset = 0;
|
|
|
|
var->red.length = 5;
|
|
|
|
var->green.length = 5;
|
|
|
|
var->blue.length = 5;
|
|
|
|
break;
|
2010-03-11 06:21:38 +07:00
|
|
|
case 16:
|
|
|
|
var->bits_per_pixel = 16;
|
|
|
|
var->red.offset = 11;
|
|
|
|
var->green.offset = 5;
|
|
|
|
var->blue.offset = 0;
|
|
|
|
var->red.length = 5;
|
|
|
|
var->green.length = 6;
|
|
|
|
var->blue.length = 5;
|
|
|
|
break;
|
|
|
|
case 24:
|
|
|
|
var->bits_per_pixel = 32;
|
|
|
|
var->red.offset = 16;
|
|
|
|
var->green.offset = 8;
|
|
|
|
var->blue.offset = 0;
|
|
|
|
var->red.length = 8;
|
|
|
|
var->green.length = 8;
|
|
|
|
var->blue.length = 8;
|
|
|
|
break;
|
2010-03-11 06:21:41 +07:00
|
|
|
case 30:
|
|
|
|
var->bits_per_pixel = 32;
|
|
|
|
var->red.offset = 20;
|
|
|
|
var->green.offset = 10;
|
|
|
|
var->blue.offset = 0;
|
|
|
|
var->red.length = 10;
|
|
|
|
var->green.length = 10;
|
|
|
|
var->blue.length = 10;
|
|
|
|
break;
|
2010-03-11 06:21:38 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:13 +07:00
|
|
|
static void viafb_update_fix(struct fb_info *info)
|
|
|
|
{
|
|
|
|
u32 bpp = info->var.bits_per_pixel;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:13 +07:00
|
|
|
info->fix.visual =
|
|
|
|
bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
|
2010-03-11 06:21:39 +07:00
|
|
|
info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
|
|
|
|
struct viafb_par *viaparinfo)
|
|
|
|
{
|
|
|
|
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
|
|
|
|
strcpy(fix->id, viafb_name);
|
|
|
|
|
|
|
|
fix->smem_start = viaparinfo->fbmem;
|
|
|
|
fix->smem_len = viaparinfo->fbmem_free;
|
|
|
|
|
|
|
|
fix->type = FB_TYPE_PACKED_PIXELS;
|
|
|
|
fix->type_aux = 0;
|
2010-03-11 06:21:38 +07:00
|
|
|
fix->visual = FB_VISUAL_TRUECOLOR;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
fix->xpanstep = fix->ywrapstep = 0;
|
|
|
|
fix->ypanstep = 1;
|
|
|
|
|
|
|
|
/* Just tell the accel name */
|
|
|
|
viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
|
|
|
|
}
|
|
|
|
static int viafb_open(struct fb_info *info, int user)
|
|
|
|
{
|
|
|
|
DEBUG_MSG(KERN_INFO "viafb_open!\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_release(struct fb_info *info, int user)
|
|
|
|
{
|
|
|
|
DEBUG_MSG(KERN_INFO "viafb_release!\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-03-16 23:31:32 +07:00
|
|
|
static inline int get_var_refresh(struct fb_var_screeninfo *var)
|
|
|
|
{
|
|
|
|
u32 htotal, vtotal;
|
|
|
|
|
|
|
|
htotal = var->left_margin + var->xres + var->right_margin
|
|
|
|
+ var->hsync_len;
|
|
|
|
vtotal = var->upper_margin + var->yres + var->lower_margin
|
|
|
|
+ var->vsync_len;
|
|
|
|
return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
|
|
|
|
}
|
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
static int viafb_check_var(struct fb_var_screeninfo *var,
|
|
|
|
struct fb_info *info)
|
|
|
|
{
|
2011-03-16 23:31:32 +07:00
|
|
|
int depth, refresh;
|
2010-03-11 06:21:28 +07:00
|
|
|
struct VideoModeTable *vmode_entry;
|
2009-09-23 06:47:26 +07:00
|
|
|
struct viafb_par *ppar = info->par;
|
2011-03-16 23:31:32 +07:00
|
|
|
u32 line;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
|
|
|
|
/* Sanity check */
|
|
|
|
/* HW neither support interlacte nor double-scaned mode */
|
|
|
|
if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2010-03-11 06:21:28 +07:00
|
|
|
vmode_entry = viafb_get_mode(var->xres, var->yres);
|
|
|
|
if (!vmode_entry) {
|
2008-10-16 12:03:27 +07:00
|
|
|
DEBUG_MSG(KERN_INFO
|
|
|
|
"viafb: Mode %dx%dx%d not supported!!\n",
|
|
|
|
var->xres, var->yres, var->bits_per_pixel);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2010-03-11 06:21:38 +07:00
|
|
|
depth = fb_get_color_depth(var, &info->fix);
|
|
|
|
if (!depth)
|
|
|
|
depth = var->bits_per_pixel;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-03-11 06:21:38 +07:00
|
|
|
if (depth < 0 || depth > 32)
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EINVAL;
|
2010-03-11 06:21:38 +07:00
|
|
|
else if (!depth)
|
|
|
|
depth = 24;
|
2010-03-11 06:21:41 +07:00
|
|
|
else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
|
|
|
|
depth = 15;
|
|
|
|
else if (depth == 30)
|
|
|
|
depth = 30;
|
2010-03-11 06:21:38 +07:00
|
|
|
else if (depth <= 8)
|
|
|
|
depth = 8;
|
|
|
|
else if (depth <= 16)
|
|
|
|
depth = 16;
|
|
|
|
else
|
|
|
|
depth = 24;
|
|
|
|
|
|
|
|
viafb_fill_var_color_info(var, depth);
|
2010-03-11 06:21:39 +07:00
|
|
|
line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7;
|
|
|
|
if (line * var->yres_virtual > ppar->memsize)
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Based on var passed in to calculate the refresh,
|
|
|
|
* because our driver use some modes special.
|
|
|
|
*/
|
2011-03-16 23:31:32 +07:00
|
|
|
refresh = viafb_get_refresh(var->xres, var->yres,
|
|
|
|
get_var_refresh(var));
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
/* Adjust var according to our driver's own table */
|
2011-03-16 23:31:32 +07:00
|
|
|
viafb_fill_var_timing_info(var, refresh, vmode_entry);
|
2010-07-23 18:32:25 +07:00
|
|
|
if (var->accel_flags & FB_ACCELF_TEXT &&
|
2010-04-23 02:48:09 +07:00
|
|
|
!ppar->shared->vdev->engine_mmio)
|
2010-07-23 18:32:25 +07:00
|
|
|
var->accel_flags = 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_set_par(struct fb_info *info)
|
|
|
|
{
|
2009-09-23 06:47:26 +07:00
|
|
|
struct viafb_par *viapar = info->par;
|
2010-03-11 06:21:28 +07:00
|
|
|
struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
|
2011-03-16 23:31:32 +07:00
|
|
|
int refresh;
|
2008-10-16 12:03:27 +07:00
|
|
|
DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
|
|
|
|
|
2010-07-14 00:58:06 +07:00
|
|
|
viafb_update_fix(info);
|
2009-09-23 06:47:26 +07:00
|
|
|
viapar->depth = fb_get_color_depth(&info->var, &info->fix);
|
2010-03-11 06:21:34 +07:00
|
|
|
viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
|
2011-03-16 23:31:32 +07:00
|
|
|
viafbinfo->var.bits_per_pixel, 0);
|
2010-03-11 06:21:34 +07:00
|
|
|
|
|
|
|
vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
|
|
|
|
if (viafb_dual_fb) {
|
|
|
|
vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres,
|
|
|
|
viafbinfo1->var.yres);
|
|
|
|
viafb_update_device_setting(viafbinfo1->var.xres,
|
|
|
|
viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
|
2011-03-16 23:31:32 +07:00
|
|
|
1);
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (viafb_SAMM_ON == 1) {
|
2008-10-16 12:03:27 +07:00
|
|
|
DEBUG_MSG(KERN_INFO
|
|
|
|
"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
|
|
|
|
viafb_second_xres, viafb_second_yres, viafb_bpp1);
|
2010-03-11 06:21:28 +07:00
|
|
|
vmode_entry1 = viafb_get_mode(viafb_second_xres,
|
2009-08-07 05:07:34 +07:00
|
|
|
viafb_second_yres);
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
viafb_update_device_setting(viafb_second_xres,
|
2011-03-16 23:31:32 +07:00
|
|
|
viafb_second_yres, viafb_bpp1, 1);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2011-03-16 23:31:32 +07:00
|
|
|
refresh = viafb_get_refresh(info->var.xres, info->var.yres,
|
|
|
|
get_var_refresh(&info->var));
|
2010-03-11 06:21:28 +07:00
|
|
|
if (vmode_entry) {
|
2011-03-16 23:31:32 +07:00
|
|
|
if (viafb_dual_fb && viapar->iga_path == IGA2) {
|
2010-03-11 06:21:34 +07:00
|
|
|
viafb_bpp1 = info->var.bits_per_pixel;
|
2011-03-16 23:31:32 +07:00
|
|
|
viafb_refresh1 = refresh;
|
|
|
|
} else {
|
2010-03-11 06:21:34 +07:00
|
|
|
viafb_bpp = info->var.bits_per_pixel;
|
2011-03-16 23:31:32 +07:00
|
|
|
viafb_refresh = refresh;
|
|
|
|
}
|
2010-03-11 06:21:34 +07:00
|
|
|
|
2009-09-23 06:47:31 +07:00
|
|
|
if (info->var.accel_flags & FB_ACCELF_TEXT)
|
|
|
|
info->flags &= ~FBINFO_HWACCEL_DISABLED;
|
|
|
|
else
|
|
|
|
info->flags |= FBINFO_HWACCEL_DISABLED;
|
2010-03-11 06:21:28 +07:00
|
|
|
viafb_setmode(vmode_entry, info->var.bits_per_pixel,
|
|
|
|
vmode_entry1, viafb_bpp1);
|
2010-03-11 06:21:32 +07:00
|
|
|
viafb_pan_display(&info->var, info);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set one color register */
|
|
|
|
static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|
|
|
unsigned blue, unsigned transp, struct fb_info *info)
|
|
|
|
{
|
2010-03-11 06:21:40 +07:00
|
|
|
struct viafb_par *viapar = info->par;
|
|
|
|
u32 r, g, b;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-03-11 06:21:40 +07:00
|
|
|
if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
|
|
|
|
if (regno > 255)
|
|
|
|
return -EINVAL;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-03-11 06:21:40 +07:00
|
|
|
if (!viafb_dual_fb || viapar->iga_path == IGA1)
|
|
|
|
viafb_set_primary_color_register(regno, red >> 8,
|
|
|
|
green >> 8, blue >> 8);
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-03-11 06:21:40 +07:00
|
|
|
if (!viafb_dual_fb || viapar->iga_path == IGA2)
|
|
|
|
viafb_set_secondary_color_register(regno, red >> 8,
|
|
|
|
green >> 8, blue >> 8);
|
|
|
|
} else {
|
|
|
|
if (regno > 15)
|
|
|
|
return -EINVAL;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-03-11 06:21:40 +07:00
|
|
|
r = (red >> (16 - info->var.red.length))
|
|
|
|
<< info->var.red.offset;
|
|
|
|
b = (blue >> (16 - info->var.blue.length))
|
|
|
|
<< info->var.blue.offset;
|
|
|
|
g = (green >> (16 - info->var.green.length))
|
|
|
|
<< info->var.green.offset;
|
|
|
|
((u32 *) info->pseudo_palette)[regno] = r | g | b;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2010-03-11 06:21:40 +07:00
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_pan_display(struct fb_var_screeninfo *var,
|
|
|
|
struct fb_info *info)
|
|
|
|
{
|
2010-03-11 06:21:32 +07:00
|
|
|
struct viafb_par *viapar = info->par;
|
|
|
|
u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset)
|
|
|
|
* (var->bits_per_pixel / 8) + viapar->vram_addr;
|
|
|
|
|
|
|
|
DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
|
|
|
|
if (!viafb_dual_fb) {
|
2010-04-18 02:44:52 +07:00
|
|
|
via_set_primary_address(vram_addr);
|
|
|
|
via_set_secondary_address(vram_addr);
|
2010-03-11 06:21:32 +07:00
|
|
|
} else if (viapar->iga_path == IGA1)
|
2010-04-18 02:44:52 +07:00
|
|
|
via_set_primary_address(vram_addr);
|
2010-03-11 06:21:32 +07:00
|
|
|
else
|
2010-04-18 02:44:52 +07:00
|
|
|
via_set_secondary_address(vram_addr);
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_blank(int blank_mode, struct fb_info *info)
|
|
|
|
{
|
|
|
|
DEBUG_MSG(KERN_INFO "viafb_blank!\n");
|
|
|
|
/* clear DPMS setting */
|
|
|
|
|
|
|
|
switch (blank_mode) {
|
|
|
|
case FB_BLANK_UNBLANK:
|
|
|
|
/* Screen: On, HSync: On, VSync: On */
|
|
|
|
/* control CRT monitor power management */
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(VIA_CRT, VIA_STATE_ON);
|
2008-10-16 12:03:27 +07:00
|
|
|
break;
|
|
|
|
case FB_BLANK_HSYNC_SUSPEND:
|
|
|
|
/* Screen: Off, HSync: Off, VSync: On */
|
|
|
|
/* control CRT monitor power management */
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(VIA_CRT, VIA_STATE_STANDBY);
|
2008-10-16 12:03:27 +07:00
|
|
|
break;
|
|
|
|
case FB_BLANK_VSYNC_SUSPEND:
|
|
|
|
/* Screen: Off, HSync: On, VSync: Off */
|
|
|
|
/* control CRT monitor power management */
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
|
2008-10-16 12:03:27 +07:00
|
|
|
break;
|
|
|
|
case FB_BLANK_POWERDOWN:
|
|
|
|
/* Screen: Off, HSync: Off, VSync: Off */
|
|
|
|
/* control CRT monitor power management */
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(VIA_CRT, VIA_STATE_OFF);
|
2008-10-16 12:03:27 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
|
|
|
|
{
|
2009-01-05 04:11:54 +07:00
|
|
|
union {
|
|
|
|
struct viafb_ioctl_mode viamode;
|
|
|
|
struct viafb_ioctl_samm viasamm;
|
|
|
|
struct viafb_driver_version driver_version;
|
|
|
|
struct fb_var_screeninfo sec_var;
|
|
|
|
struct _panel_size_pos_info panel_pos_size_para;
|
|
|
|
struct viafb_ioctl_setting viafb_setting;
|
|
|
|
struct device_t active_dev;
|
|
|
|
} u;
|
2008-10-16 12:03:27 +07:00
|
|
|
u32 state_info = 0;
|
|
|
|
u32 *viafb_gamma_table;
|
|
|
|
char driver_name[] = "viafb";
|
|
|
|
|
|
|
|
u32 __user *argp = (u32 __user *) arg;
|
|
|
|
u32 gpu32;
|
|
|
|
|
|
|
|
DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
|
2010-03-11 06:21:26 +07:00
|
|
|
printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n");
|
2009-01-05 04:11:54 +07:00
|
|
|
memset(&u, 0, sizeof(u));
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case VIAFB_GET_CHIP_INFO:
|
|
|
|
if (copy_to_user(argp, viaparinfo->chip_info,
|
|
|
|
sizeof(struct chip_information)))
|
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
case VIAFB_GET_INFO_SIZE:
|
2009-01-05 04:11:54 +07:00
|
|
|
return put_user((u32)sizeof(struct viafb_ioctl_info), argp);
|
2008-10-16 12:03:27 +07:00
|
|
|
case VIAFB_GET_INFO:
|
|
|
|
return viafb_ioctl_get_viafb_info(arg);
|
|
|
|
case VIAFB_HOTPLUG:
|
|
|
|
return put_user(viafb_ioctl_hotplug(info->var.xres,
|
|
|
|
info->var.yres,
|
|
|
|
info->var.bits_per_pixel), argp);
|
|
|
|
case VIAFB_SET_HOTPLUG_FLAG:
|
|
|
|
if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
|
|
|
|
return -EFAULT;
|
|
|
|
viafb_hotplug = (gpu32) ? 1 : 0;
|
|
|
|
break;
|
|
|
|
case VIAFB_GET_RESOLUTION:
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viamode.xres = (u32) viafb_hotplug_Xres;
|
|
|
|
u.viamode.yres = (u32) viafb_hotplug_Yres;
|
|
|
|
u.viamode.refresh = (u32) viafb_hotplug_refresh;
|
|
|
|
u.viamode.bpp = (u32) viafb_hotplug_bpp;
|
2008-10-16 12:03:27 +07:00
|
|
|
if (viafb_SAMM_ON == 1) {
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viamode.xres_sec = viafb_second_xres;
|
|
|
|
u.viamode.yres_sec = viafb_second_yres;
|
2011-03-27 09:54:32 +07:00
|
|
|
u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual;
|
|
|
|
u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual;
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viamode.refresh_sec = viafb_refresh1;
|
|
|
|
u.viamode.bpp_sec = viafb_bpp1;
|
2008-10-16 12:03:27 +07:00
|
|
|
} else {
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viamode.xres_sec = 0;
|
|
|
|
u.viamode.yres_sec = 0;
|
|
|
|
u.viamode.virtual_xres_sec = 0;
|
|
|
|
u.viamode.virtual_yres_sec = 0;
|
|
|
|
u.viamode.refresh_sec = 0;
|
|
|
|
u.viamode.bpp_sec = 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_to_user(argp, &u.viamode, sizeof(u.viamode)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
case VIAFB_GET_SAMM_INFO:
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.samm_status = viafb_SAMM_ON;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
if (viafb_SAMM_ON == 1) {
|
|
|
|
if (viafb_dual_fb) {
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.size_prim = viaparinfo->fbmem_free;
|
|
|
|
u.viasamm.size_sec = viaparinfo1->fbmem_free;
|
2008-10-16 12:03:27 +07:00
|
|
|
} else {
|
|
|
|
if (viafb_second_size) {
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.size_prim =
|
2008-10-16 12:03:27 +07:00
|
|
|
viaparinfo->fbmem_free -
|
|
|
|
viafb_second_size * 1024 * 1024;
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.size_sec =
|
2008-10-16 12:03:27 +07:00
|
|
|
viafb_second_size * 1024 * 1024;
|
|
|
|
} else {
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.size_prim =
|
2008-10-16 12:03:27 +07:00
|
|
|
viaparinfo->fbmem_free >> 1;
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.size_sec =
|
2008-10-16 12:03:27 +07:00
|
|
|
(viaparinfo->fbmem_free >> 1);
|
|
|
|
}
|
|
|
|
}
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.mem_base = viaparinfo->fbmem;
|
|
|
|
u.viasamm.offset_sec = viafb_second_offset;
|
2008-10-16 12:03:27 +07:00
|
|
|
} else {
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.size_prim =
|
2008-10-16 12:03:27 +07:00
|
|
|
viaparinfo->memsize - viaparinfo->fbmem_used;
|
2009-01-05 04:11:54 +07:00
|
|
|
u.viasamm.size_sec = 0;
|
|
|
|
u.viasamm.mem_base = viaparinfo->fbmem;
|
|
|
|
u.viasamm.offset_sec = 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case VIAFB_TURN_ON_OUTPUT_DEVICE:
|
|
|
|
if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
|
|
|
|
return -EFAULT;
|
|
|
|
if (gpu32 & CRT_Device)
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(VIA_CRT, VIA_STATE_ON);
|
2008-10-16 12:03:27 +07:00
|
|
|
if (gpu32 & DVI_Device)
|
|
|
|
viafb_dvi_enable();
|
|
|
|
if (gpu32 & LCD_Device)
|
|
|
|
viafb_lcd_enable();
|
|
|
|
break;
|
|
|
|
case VIAFB_TURN_OFF_OUTPUT_DEVICE:
|
|
|
|
if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
|
|
|
|
return -EFAULT;
|
|
|
|
if (gpu32 & CRT_Device)
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(VIA_CRT, VIA_STATE_OFF);
|
2008-10-16 12:03:27 +07:00
|
|
|
if (gpu32 & DVI_Device)
|
|
|
|
viafb_dvi_disable();
|
|
|
|
if (gpu32 & LCD_Device)
|
|
|
|
viafb_lcd_disable();
|
|
|
|
break;
|
|
|
|
case VIAFB_GET_DEVICE:
|
2009-01-05 04:11:54 +07:00
|
|
|
u.active_dev.crt = viafb_CRT_ON;
|
|
|
|
u.active_dev.dvi = viafb_DVI_ON;
|
|
|
|
u.active_dev.lcd = viafb_LCD_ON;
|
|
|
|
u.active_dev.samm = viafb_SAMM_ON;
|
|
|
|
u.active_dev.primary_dev = viafb_primary_dev;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
|
|
|
|
u.active_dev.lcd_panel_id = viafb_lcd_panel_id;
|
|
|
|
u.active_dev.lcd_mode = viafb_lcd_mode;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
u.active_dev.xres = viafb_hotplug_Xres;
|
|
|
|
u.active_dev.yres = viafb_hotplug_Yres;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
u.active_dev.xres1 = viafb_second_xres;
|
|
|
|
u.active_dev.yres1 = viafb_second_yres;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
u.active_dev.bpp = viafb_bpp;
|
|
|
|
u.active_dev.bpp1 = viafb_bpp1;
|
|
|
|
u.active_dev.refresh = viafb_refresh;
|
|
|
|
u.active_dev.refresh1 = viafb_refresh1;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
u.active_dev.epia_dvi = viafb_platform_epia_dvi;
|
|
|
|
u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
|
|
|
|
u.active_dev.bus_width = viafb_bus_width;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_DRIVER_VERSION:
|
2009-01-05 04:11:54 +07:00
|
|
|
u.driver_version.iMajorNum = VERSION_MAJOR;
|
|
|
|
u.driver_version.iKernelNum = VERSION_KERNEL;
|
|
|
|
u.driver_version.iOSNum = VERSION_OS;
|
|
|
|
u.driver_version.iMinorNum = VERSION_MINOR;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_to_user(argp, &u.driver_version,
|
|
|
|
sizeof(u.driver_version)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_DEVICE_INFO:
|
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
retrieve_device_setting(&u.viafb_setting);
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_to_user(argp, &u.viafb_setting,
|
|
|
|
sizeof(u.viafb_setting)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_DEVICE_SUPPORT:
|
|
|
|
viafb_get_device_support_state(&state_info);
|
|
|
|
if (put_user(state_info, argp))
|
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_DEVICE_CONNECT:
|
|
|
|
viafb_get_device_connect_state(&state_info);
|
|
|
|
if (put_user(state_info, argp))
|
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_PANEL_SUPPORT_EXPAND:
|
|
|
|
state_info =
|
|
|
|
viafb_lcd_get_support_expand_state(info->var.xres,
|
|
|
|
info->var.yres);
|
|
|
|
if (put_user(state_info, argp))
|
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_DRIVER_NAME:
|
|
|
|
if (copy_to_user(argp, driver_name, sizeof(driver_name)))
|
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_SET_GAMMA_LUT:
|
2010-05-27 04:42:29 +07:00
|
|
|
viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32));
|
|
|
|
if (IS_ERR(viafb_gamma_table))
|
|
|
|
return PTR_ERR(viafb_gamma_table);
|
2008-10-16 12:03:27 +07:00
|
|
|
viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
|
|
|
|
kfree(viafb_gamma_table);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_GAMMA_LUT:
|
|
|
|
viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
|
|
|
|
if (!viafb_gamma_table)
|
|
|
|
return -ENOMEM;
|
|
|
|
viafb_get_gamma_table(viafb_gamma_table);
|
|
|
|
if (copy_to_user(argp, viafb_gamma_table,
|
2009-12-18 06:27:09 +07:00
|
|
|
256 * sizeof(u32))) {
|
2008-10-16 12:03:27 +07:00
|
|
|
kfree(viafb_gamma_table);
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
kfree(viafb_gamma_table);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_GAMMA_SUPPORT_STATE:
|
|
|
|
viafb_get_gamma_support_state(viafb_bpp, &state_info);
|
|
|
|
if (put_user(state_info, argp))
|
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
case VIAFB_SYNC_SURFACE:
|
|
|
|
DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
|
|
|
|
break;
|
|
|
|
case VIAFB_GET_DRIVER_CAPS:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_PANEL_MAX_SIZE:
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_from_user(&u.panel_pos_size_para, argp,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
2009-01-05 04:11:54 +07:00
|
|
|
u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
|
|
|
|
if (copy_to_user(argp, &u.panel_pos_size_para,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
case VIAFB_GET_PANEL_MAX_POSITION:
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_from_user(&u.panel_pos_size_para, argp,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
2009-01-05 04:11:54 +07:00
|
|
|
u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
|
|
|
|
if (copy_to_user(argp, &u.panel_pos_size_para,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_GET_PANEL_POSITION:
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_from_user(&u.panel_pos_size_para, argp,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
2009-01-05 04:11:54 +07:00
|
|
|
u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
|
|
|
|
if (copy_to_user(argp, &u.panel_pos_size_para,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
case VIAFB_GET_PANEL_SIZE:
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_from_user(&u.panel_pos_size_para, argp,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
2009-01-05 04:11:54 +07:00
|
|
|
u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
|
|
|
|
if (copy_to_user(argp, &u.panel_pos_size_para,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIAFB_SET_PANEL_POSITION:
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_from_user(&u.panel_pos_size_para, argp,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
case VIAFB_SET_PANEL_SIZE:
|
2009-01-05 04:11:54 +07:00
|
|
|
if (copy_from_user(&u.panel_pos_size_para, argp,
|
|
|
|
sizeof(u.panel_pos_size_para)))
|
2008-10-16 12:03:27 +07:00
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void viafb_fillrect(struct fb_info *info,
|
|
|
|
const struct fb_fillrect *rect)
|
|
|
|
{
|
2009-09-23 06:47:26 +07:00
|
|
|
struct viafb_par *viapar = info->par;
|
2009-09-23 06:47:31 +07:00
|
|
|
struct viafb_shared *shared = viapar->shared;
|
2009-09-23 06:47:26 +07:00
|
|
|
u32 fg_color;
|
|
|
|
u8 rop;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:31 +07:00
|
|
|
if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
|
2009-01-07 05:42:32 +07:00
|
|
|
cfb_fillrect(info, rect);
|
|
|
|
return;
|
|
|
|
}
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
if (!rect->width || !rect->height)
|
|
|
|
return;
|
|
|
|
|
2009-09-23 06:47:26 +07:00
|
|
|
if (info->fix.visual == FB_VISUAL_TRUECOLOR)
|
|
|
|
fg_color = ((u32 *)info->pseudo_palette)[rect->color];
|
|
|
|
else
|
|
|
|
fg_color = rect->color;
|
|
|
|
|
|
|
|
if (rect->rop == ROP_XOR)
|
2008-10-16 12:03:27 +07:00
|
|
|
rop = 0x5A;
|
2009-09-23 06:47:26 +07:00
|
|
|
else
|
2008-10-16 12:03:27 +07:00
|
|
|
rop = 0xF0;
|
|
|
|
|
2009-09-23 06:47:26 +07:00
|
|
|
DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
|
2010-04-23 02:48:09 +07:00
|
|
|
if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL,
|
2009-09-23 06:47:26 +07:00
|
|
|
rect->width, rect->height, info->var.bits_per_pixel,
|
|
|
|
viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
|
|
|
|
NULL, 0, 0, 0, 0, fg_color, 0, rop))
|
|
|
|
cfb_fillrect(info, rect);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void viafb_copyarea(struct fb_info *info,
|
|
|
|
const struct fb_copyarea *area)
|
|
|
|
{
|
2009-09-23 06:47:26 +07:00
|
|
|
struct viafb_par *viapar = info->par;
|
2009-09-23 06:47:31 +07:00
|
|
|
struct viafb_shared *shared = viapar->shared;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:31 +07:00
|
|
|
if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
|
2009-01-07 05:42:32 +07:00
|
|
|
cfb_copyarea(info, area);
|
|
|
|
return;
|
|
|
|
}
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
if (!area->width || !area->height)
|
|
|
|
return;
|
|
|
|
|
2009-09-23 06:47:26 +07:00
|
|
|
DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n");
|
2010-04-23 02:48:09 +07:00
|
|
|
if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR,
|
2009-09-23 06:47:26 +07:00
|
|
|
area->width, area->height, info->var.bits_per_pixel,
|
|
|
|
viapar->vram_addr, info->fix.line_length, area->dx, area->dy,
|
|
|
|
NULL, viapar->vram_addr, info->fix.line_length,
|
|
|
|
area->sx, area->sy, 0, 0, 0))
|
|
|
|
cfb_copyarea(info, area);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void viafb_imageblit(struct fb_info *info,
|
|
|
|
const struct fb_image *image)
|
|
|
|
{
|
2009-09-23 06:47:26 +07:00
|
|
|
struct viafb_par *viapar = info->par;
|
2009-09-23 06:47:31 +07:00
|
|
|
struct viafb_shared *shared = viapar->shared;
|
2009-09-23 06:47:26 +07:00
|
|
|
u32 fg_color = 0, bg_color = 0;
|
|
|
|
u8 op;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:31 +07:00
|
|
|
if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt ||
|
2009-09-23 06:47:26 +07:00
|
|
|
(image->depth != 1 && image->depth != viapar->depth)) {
|
2009-01-07 05:42:32 +07:00
|
|
|
cfb_imageblit(info, image);
|
|
|
|
return;
|
|
|
|
}
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:26 +07:00
|
|
|
if (image->depth == 1) {
|
|
|
|
op = VIA_BITBLT_MONO;
|
|
|
|
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
|
|
|
|
fg_color =
|
|
|
|
((u32 *)info->pseudo_palette)[image->fg_color];
|
|
|
|
bg_color =
|
|
|
|
((u32 *)info->pseudo_palette)[image->bg_color];
|
|
|
|
} else {
|
|
|
|
fg_color = image->fg_color;
|
|
|
|
bg_color = image->bg_color;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
op = VIA_BITBLT_COLOR;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:26 +07:00
|
|
|
DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n");
|
2010-04-23 02:48:09 +07:00
|
|
|
if (shared->hw_bitblt(shared->vdev->engine_mmio, op,
|
2009-09-23 06:47:26 +07:00
|
|
|
image->width, image->height, info->var.bits_per_pixel,
|
|
|
|
viapar->vram_addr, info->fix.line_length, image->dx, image->dy,
|
|
|
|
(u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0))
|
|
|
|
cfb_imageblit(info, image);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
|
|
|
|
{
|
2009-09-23 06:47:28 +07:00
|
|
|
struct viafb_par *viapar = info->par;
|
2010-04-23 02:48:09 +07:00
|
|
|
void __iomem *engine = viapar->shared->vdev->engine_mmio;
|
2009-09-23 06:47:28 +07:00
|
|
|
u32 temp, xx, yy, bg_color = 0, fg_color = 0,
|
|
|
|
chip_name = viapar->shared->chip_info.gfx_chip_name;
|
|
|
|
int i, j = 0, cur_size = 64;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo)
|
2008-10-16 12:03:27 +07:00
|
|
|
return -ENODEV;
|
|
|
|
|
2010-01-16 08:01:03 +07:00
|
|
|
/* LCD ouput does not support hw cursors (at least on VN896) */
|
|
|
|
if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) ||
|
|
|
|
viafb_LCD_ON)
|
2008-10-16 12:03:27 +07:00
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
viafb_show_hw_cursor(info, HW_Cursor_OFF);
|
|
|
|
|
|
|
|
if (cursor->set & FB_CUR_SETHOT) {
|
2009-09-23 06:47:28 +07:00
|
|
|
temp = (cursor->hot.x << 16) + cursor->hot.y;
|
2009-09-23 06:47:31 +07:00
|
|
|
writel(temp, engine + VIA_REG_CURSOR_ORG);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cursor->set & FB_CUR_SETPOS) {
|
|
|
|
yy = cursor->image.dy - info->var.yoffset;
|
|
|
|
xx = cursor->image.dx - info->var.xoffset;
|
|
|
|
temp = yy & 0xFFFF;
|
|
|
|
temp |= (xx << 16);
|
2009-09-23 06:47:31 +07:00
|
|
|
writel(temp, engine + VIA_REG_CURSOR_POS);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
if (cursor->image.width <= 32 && cursor->image.height <= 32)
|
|
|
|
cur_size = 32;
|
|
|
|
else if (cursor->image.width <= 64 && cursor->image.height <= 64)
|
|
|
|
cur_size = 64;
|
|
|
|
else {
|
|
|
|
printk(KERN_WARNING "viafb_cursor: The cursor is too large "
|
|
|
|
"%dx%d", cursor->image.width, cursor->image.height);
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
if (cursor->set & FB_CUR_SETSIZE) {
|
2009-09-23 06:47:31 +07:00
|
|
|
temp = readl(engine + VIA_REG_CURSOR_MODE);
|
2009-09-23 06:47:28 +07:00
|
|
|
if (cur_size == 32)
|
2008-10-16 12:03:27 +07:00
|
|
|
temp |= 0x2;
|
2009-09-23 06:47:28 +07:00
|
|
|
else
|
|
|
|
temp &= ~0x2;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:31 +07:00
|
|
|
writel(temp, engine + VIA_REG_CURSOR_MODE);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cursor->set & FB_CUR_SETCMAP) {
|
2009-09-23 06:47:28 +07:00
|
|
|
fg_color = cursor->image.fg_color;
|
|
|
|
bg_color = cursor->image.bg_color;
|
|
|
|
if (chip_name == UNICHROME_CX700 ||
|
2009-09-23 06:47:35 +07:00
|
|
|
chip_name == UNICHROME_VX800 ||
|
2010-10-24 11:02:14 +07:00
|
|
|
chip_name == UNICHROME_VX855 ||
|
|
|
|
chip_name == UNICHROME_VX900) {
|
2009-09-23 06:47:28 +07:00
|
|
|
fg_color =
|
|
|
|
((info->cmap.red[fg_color] & 0xFFC0) << 14) |
|
|
|
|
((info->cmap.green[fg_color] & 0xFFC0) << 4) |
|
|
|
|
((info->cmap.blue[fg_color] & 0xFFC0) >> 6);
|
|
|
|
bg_color =
|
|
|
|
((info->cmap.red[bg_color] & 0xFFC0) << 14) |
|
|
|
|
((info->cmap.green[bg_color] & 0xFFC0) << 4) |
|
|
|
|
((info->cmap.blue[bg_color] & 0xFFC0) >> 6);
|
|
|
|
} else {
|
|
|
|
fg_color =
|
|
|
|
((info->cmap.red[fg_color] & 0xFF00) << 8) |
|
|
|
|
(info->cmap.green[fg_color] & 0xFF00) |
|
|
|
|
((info->cmap.blue[fg_color] & 0xFF00) >> 8);
|
|
|
|
bg_color =
|
|
|
|
((info->cmap.red[bg_color] & 0xFF00) << 8) |
|
|
|
|
(info->cmap.green[bg_color] & 0xFF00) |
|
|
|
|
((info->cmap.blue[bg_color] & 0xFF00) >> 8);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:31 +07:00
|
|
|
writel(bg_color, engine + VIA_REG_CURSOR_BG);
|
|
|
|
writel(fg_color, engine + VIA_REG_CURSOR_FG);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cursor->set & FB_CUR_SETSHAPE) {
|
2009-01-05 04:11:54 +07:00
|
|
|
struct {
|
2009-09-23 06:47:28 +07:00
|
|
|
u8 data[CURSOR_SIZE];
|
|
|
|
u32 bak[CURSOR_SIZE / 4];
|
2009-01-05 04:11:54 +07:00
|
|
|
} *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC);
|
2009-09-23 06:47:28 +07:00
|
|
|
int size = ((cursor->image.width + 7) >> 3) *
|
|
|
|
cursor->image.height;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
if (!cr_data)
|
|
|
|
return -ENOMEM;
|
2009-01-05 04:11:54 +07:00
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
if (cur_size == 32) {
|
|
|
|
for (i = 0; i < (CURSOR_SIZE / 4); i++) {
|
2009-01-05 04:11:54 +07:00
|
|
|
cr_data->bak[i] = 0x0;
|
|
|
|
cr_data->bak[i + 1] = 0xFFFFFFFF;
|
2008-10-16 12:03:27 +07:00
|
|
|
i += 1;
|
|
|
|
}
|
2009-09-23 06:47:28 +07:00
|
|
|
} else {
|
|
|
|
for (i = 0; i < (CURSOR_SIZE / 4); i++) {
|
2009-01-05 04:11:54 +07:00
|
|
|
cr_data->bak[i] = 0x0;
|
|
|
|
cr_data->bak[i + 1] = 0x0;
|
|
|
|
cr_data->bak[i + 2] = 0xFFFFFFFF;
|
|
|
|
cr_data->bak[i + 3] = 0xFFFFFFFF;
|
2008-10-16 12:03:27 +07:00
|
|
|
i += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
switch (cursor->rop) {
|
2008-10-16 12:03:27 +07:00
|
|
|
case ROP_XOR:
|
|
|
|
for (i = 0; i < size; i++)
|
2009-09-23 06:47:28 +07:00
|
|
|
cr_data->data[i] = cursor->mask[i];
|
2008-10-16 12:03:27 +07:00
|
|
|
break;
|
|
|
|
case ROP_COPY:
|
|
|
|
|
|
|
|
for (i = 0; i < size; i++)
|
2009-09-23 06:47:28 +07:00
|
|
|
cr_data->data[i] = cursor->mask[i];
|
2008-10-16 12:03:27 +07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
if (cur_size == 32) {
|
2008-10-16 12:03:27 +07:00
|
|
|
for (i = 0; i < size; i++) {
|
2009-01-05 04:11:54 +07:00
|
|
|
cr_data->bak[j] = (u32) cr_data->data[i];
|
|
|
|
cr_data->bak[j + 1] = ~cr_data->bak[j];
|
2008-10-16 12:03:27 +07:00
|
|
|
j += 2;
|
|
|
|
}
|
2009-09-23 06:47:28 +07:00
|
|
|
} else {
|
2008-10-16 12:03:27 +07:00
|
|
|
for (i = 0; i < size; i++) {
|
2009-01-05 04:11:54 +07:00
|
|
|
cr_data->bak[j] = (u32) cr_data->data[i];
|
|
|
|
cr_data->bak[j + 1] = 0x0;
|
|
|
|
cr_data->bak[j + 2] = ~cr_data->bak[j];
|
|
|
|
cr_data->bak[j + 3] = ~cr_data->bak[j + 1];
|
2008-10-16 12:03:27 +07:00
|
|
|
j += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
memcpy_toio(viafbinfo->screen_base + viapar->shared->
|
|
|
|
cursor_vram_addr, cr_data->bak, CURSOR_SIZE);
|
2009-01-05 04:11:54 +07:00
|
|
|
kfree(cr_data);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:28 +07:00
|
|
|
if (cursor->enable)
|
2008-10-16 12:03:27 +07:00
|
|
|
viafb_show_hw_cursor(info, HW_Cursor_ON);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_sync(struct fb_info *info)
|
|
|
|
{
|
2009-09-23 06:47:31 +07:00
|
|
|
if (!(info->flags & FBINFO_HWACCEL_DISABLED))
|
|
|
|
viafb_wait_engine_idle(info);
|
2008-10-16 12:03:27 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_primary_device(void)
|
|
|
|
{
|
|
|
|
int primary_device = 0;
|
|
|
|
/* Rule: device on iga1 path are the primary device. */
|
|
|
|
if (viafb_SAMM_ON) {
|
|
|
|
if (viafb_CRT_ON) {
|
2011-03-21 08:46:24 +07:00
|
|
|
if (viaparinfo->shared->iga1_devices & VIA_CRT) {
|
|
|
|
DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", IGA1);
|
2008-10-16 12:03:27 +07:00
|
|
|
primary_device = CRT_Device;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (viafb_DVI_ON) {
|
|
|
|
if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
|
|
|
|
DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
|
|
|
|
viaparinfo->
|
|
|
|
tmds_setting_info->iga_path);
|
|
|
|
primary_device = DVI_Device;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (viafb_LCD_ON) {
|
|
|
|
if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
|
|
|
|
DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
|
|
|
|
viaparinfo->
|
|
|
|
lvds_setting_info->iga_path);
|
|
|
|
primary_device = LCD_Device;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (viafb_LCD2_ON) {
|
|
|
|
if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
|
|
|
|
DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
|
|
|
|
viaparinfo->
|
|
|
|
lvds_setting_info2->iga_path);
|
|
|
|
primary_device = LCD2_Device;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return primary_device;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void retrieve_device_setting(struct viafb_ioctl_setting
|
|
|
|
*setting_info)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* get device status */
|
|
|
|
if (viafb_CRT_ON == 1)
|
|
|
|
setting_info->device_status = CRT_Device;
|
|
|
|
if (viafb_DVI_ON == 1)
|
|
|
|
setting_info->device_status |= DVI_Device;
|
|
|
|
if (viafb_LCD_ON == 1)
|
|
|
|
setting_info->device_status |= LCD_Device;
|
|
|
|
if (viafb_LCD2_ON == 1)
|
|
|
|
setting_info->device_status |= LCD2_Device;
|
|
|
|
|
|
|
|
setting_info->samm_status = viafb_SAMM_ON;
|
|
|
|
setting_info->primary_device = get_primary_device();
|
|
|
|
|
|
|
|
setting_info->first_dev_bpp = viafb_bpp;
|
|
|
|
setting_info->second_dev_bpp = viafb_bpp1;
|
|
|
|
|
|
|
|
setting_info->first_dev_refresh = viafb_refresh;
|
|
|
|
setting_info->second_dev_refresh = viafb_refresh1;
|
|
|
|
|
|
|
|
setting_info->first_dev_hor_res = viafb_hotplug_Xres;
|
|
|
|
setting_info->first_dev_ver_res = viafb_hotplug_Yres;
|
|
|
|
setting_info->second_dev_hor_res = viafb_second_xres;
|
|
|
|
setting_info->second_dev_ver_res = viafb_second_yres;
|
|
|
|
|
|
|
|
/* Get lcd attributes */
|
|
|
|
setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
|
|
|
|
setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
|
|
|
|
setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
|
|
|
|
}
|
|
|
|
|
2010-08-09 08:34:27 +07:00
|
|
|
static int __init parse_active_dev(void)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
viafb_CRT_ON = STATE_OFF;
|
|
|
|
viafb_DVI_ON = STATE_OFF;
|
|
|
|
viafb_LCD_ON = STATE_OFF;
|
|
|
|
viafb_LCD2_ON = STATE_OFF;
|
|
|
|
/* 1. Modify the active status of devices. */
|
|
|
|
/* 2. Keep the order of devices, so we can set corresponding
|
|
|
|
IGA path to devices in SAMM case. */
|
|
|
|
/* Note: The previous of active_dev is primary device,
|
|
|
|
and the following is secondary device. */
|
2010-03-11 06:21:34 +07:00
|
|
|
if (!viafb_active_dev) {
|
2011-05-11 04:34:11 +07:00
|
|
|
if (machine_is_olpc()) { /* LCD only */
|
|
|
|
viafb_LCD_ON = STATE_ON;
|
|
|
|
viafb_SAMM_ON = STATE_OFF;
|
|
|
|
} else {
|
|
|
|
viafb_CRT_ON = STATE_ON;
|
|
|
|
viafb_SAMM_ON = STATE_OFF;
|
|
|
|
}
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* CRT+DVI */
|
|
|
|
viafb_CRT_ON = STATE_ON;
|
|
|
|
viafb_DVI_ON = STATE_ON;
|
|
|
|
viafb_primary_dev = CRT_Device;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "DVI+CRT")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* DVI+CRT */
|
|
|
|
viafb_CRT_ON = STATE_ON;
|
|
|
|
viafb_DVI_ON = STATE_ON;
|
|
|
|
viafb_primary_dev = DVI_Device;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "CRT+LCD")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* CRT+LCD */
|
|
|
|
viafb_CRT_ON = STATE_ON;
|
|
|
|
viafb_LCD_ON = STATE_ON;
|
|
|
|
viafb_primary_dev = CRT_Device;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "LCD+CRT")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* LCD+CRT */
|
|
|
|
viafb_CRT_ON = STATE_ON;
|
|
|
|
viafb_LCD_ON = STATE_ON;
|
|
|
|
viafb_primary_dev = LCD_Device;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "DVI+LCD")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* DVI+LCD */
|
|
|
|
viafb_DVI_ON = STATE_ON;
|
|
|
|
viafb_LCD_ON = STATE_ON;
|
|
|
|
viafb_primary_dev = DVI_Device;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "LCD+DVI")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* LCD+DVI */
|
|
|
|
viafb_DVI_ON = STATE_ON;
|
|
|
|
viafb_LCD_ON = STATE_ON;
|
|
|
|
viafb_primary_dev = LCD_Device;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "LCD+LCD2")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
viafb_LCD_ON = STATE_ON;
|
|
|
|
viafb_LCD2_ON = STATE_ON;
|
|
|
|
viafb_primary_dev = LCD_Device;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "LCD2+LCD")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
viafb_LCD_ON = STATE_ON;
|
|
|
|
viafb_LCD2_ON = STATE_ON;
|
|
|
|
viafb_primary_dev = LCD2_Device;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "CRT")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* CRT only */
|
|
|
|
viafb_CRT_ON = STATE_ON;
|
|
|
|
viafb_SAMM_ON = STATE_OFF;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "DVI")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* DVI only */
|
|
|
|
viafb_DVI_ON = STATE_ON;
|
|
|
|
viafb_SAMM_ON = STATE_OFF;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else if (!strcmp(viafb_active_dev, "LCD")) {
|
2008-10-16 12:03:27 +07:00
|
|
|
/* LCD only */
|
|
|
|
viafb_LCD_ON = STATE_ON;
|
|
|
|
viafb_SAMM_ON = STATE_OFF;
|
2010-03-11 06:21:34 +07:00
|
|
|
} else
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2010-08-09 08:34:27 +07:00
|
|
|
static int __devinit parse_port(char *opt_str, int *output_interface)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
if (!strncmp(opt_str, "DVP0", 4))
|
|
|
|
*output_interface = INTERFACE_DVP0;
|
|
|
|
else if (!strncmp(opt_str, "DVP1", 4))
|
|
|
|
*output_interface = INTERFACE_DVP1;
|
|
|
|
else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
|
|
|
|
*output_interface = INTERFACE_DFP;
|
|
|
|
else if (!strncmp(opt_str, "DFP_HIGH", 8))
|
|
|
|
*output_interface = INTERFACE_DFP_HIGH;
|
|
|
|
else if (!strncmp(opt_str, "DFP_LOW", 7))
|
|
|
|
*output_interface = INTERFACE_DFP_LOW;
|
|
|
|
else
|
|
|
|
*output_interface = INTERFACE_NONE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-08-09 08:34:27 +07:00
|
|
|
static void __devinit parse_lcd_port(void)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
|
|
|
|
output_interface);
|
|
|
|
/*Initialize to avoid unexpected behavior */
|
|
|
|
viaparinfo->chip_info->lvds_chip_info2.output_interface =
|
|
|
|
INTERFACE_NONE;
|
|
|
|
|
|
|
|
DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
|
|
|
|
viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
|
|
|
|
output_interface);
|
|
|
|
}
|
|
|
|
|
2010-08-09 08:34:27 +07:00
|
|
|
static void __devinit parse_dvi_port(void)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
|
|
|
|
output_interface);
|
|
|
|
|
|
|
|
DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
|
|
|
|
viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
|
|
|
|
output_interface);
|
|
|
|
}
|
|
|
|
|
2010-04-18 02:44:57 +07:00
|
|
|
#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
|
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
/*
|
|
|
|
* The proc filesystem read/write function, a simple proc implement to
|
|
|
|
* get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
|
|
|
|
* DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2],
|
|
|
|
* CR9B, SR65, CR97, CR99
|
|
|
|
*/
|
2009-09-23 06:47:27 +07:00
|
|
|
static int viafb_dvp0_proc_show(struct seq_file *m, void *v)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
|
|
|
|
dvp0_data_dri =
|
|
|
|
(viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
|
|
|
|
(viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
|
|
|
|
dvp0_clk_dri =
|
|
|
|
(viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
|
|
|
|
(viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
|
|
|
|
dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
|
2009-09-23 06:47:27 +07:00
|
|
|
seq_printf(m, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
|
|
|
|
return 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
|
|
|
|
static int viafb_dvp0_proc_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, viafb_dvp0_proc_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t viafb_dvp0_proc_write(struct file *file,
|
|
|
|
const char __user *buffer, size_t count, loff_t *pos)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
char buf[20], *value, *pbuf;
|
|
|
|
u8 reg_val = 0;
|
|
|
|
unsigned long length, i;
|
|
|
|
if (count < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
length = count > 20 ? 20 : count;
|
|
|
|
if (copy_from_user(&buf[0], buffer, length))
|
|
|
|
return -EFAULT;
|
|
|
|
buf[length - 1] = '\0'; /*Ensure end string */
|
|
|
|
pbuf = &buf[0];
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
value = strsep(&pbuf, " ");
|
|
|
|
if (value != NULL) {
|
|
|
|
strict_strtoul(value, 0, (unsigned long *)®_val);
|
|
|
|
DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
|
|
|
|
reg_val);
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
viafb_write_reg_mask(CR96, VIACR,
|
|
|
|
reg_val, 0x0f);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
viafb_write_reg_mask(SR2A, VIASR,
|
|
|
|
reg_val << 4, BIT5);
|
|
|
|
viafb_write_reg_mask(SR1B, VIASR,
|
|
|
|
reg_val << 1, BIT1);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
viafb_write_reg_mask(SR2A, VIASR,
|
|
|
|
reg_val << 3, BIT4);
|
|
|
|
viafb_write_reg_mask(SR1E, VIASR,
|
|
|
|
reg_val << 2, BIT2);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
|
|
|
|
static const struct file_operations viafb_dvp0_proc_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.open = viafb_dvp0_proc_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
.write = viafb_dvp0_proc_write,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int viafb_dvp1_proc_show(struct seq_file *m, void *v)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
|
|
|
|
dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
|
|
|
|
dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
|
|
|
|
dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
|
2009-09-23 06:47:27 +07:00
|
|
|
seq_printf(m, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
|
|
|
|
return 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
|
|
|
|
static int viafb_dvp1_proc_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, viafb_dvp1_proc_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t viafb_dvp1_proc_write(struct file *file,
|
|
|
|
const char __user *buffer, size_t count, loff_t *pos)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
char buf[20], *value, *pbuf;
|
|
|
|
u8 reg_val = 0;
|
|
|
|
unsigned long length, i;
|
|
|
|
if (count < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
length = count > 20 ? 20 : count;
|
|
|
|
if (copy_from_user(&buf[0], buffer, length))
|
|
|
|
return -EFAULT;
|
|
|
|
buf[length - 1] = '\0'; /*Ensure end string */
|
|
|
|
pbuf = &buf[0];
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
value = strsep(&pbuf, " ");
|
|
|
|
if (value != NULL) {
|
|
|
|
strict_strtoul(value, 0, (unsigned long *)®_val);
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
viafb_write_reg_mask(CR9B, VIACR,
|
|
|
|
reg_val, 0x0f);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
viafb_write_reg_mask(SR65, VIASR,
|
|
|
|
reg_val << 2, 0x0c);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
viafb_write_reg_mask(SR65, VIASR,
|
|
|
|
reg_val, 0x03);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:27 +07:00
|
|
|
static const struct file_operations viafb_dvp1_proc_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.open = viafb_dvp1_proc_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
.write = viafb_dvp1_proc_write,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int viafb_dfph_proc_show(struct seq_file *m, void *v)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
u8 dfp_high = 0;
|
|
|
|
dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
|
2009-09-23 06:47:27 +07:00
|
|
|
seq_printf(m, "%x\n", dfp_high);
|
|
|
|
return 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
|
|
|
|
static int viafb_dfph_proc_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, viafb_dfph_proc_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t viafb_dfph_proc_write(struct file *file,
|
|
|
|
const char __user *buffer, size_t count, loff_t *pos)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
char buf[20];
|
|
|
|
u8 reg_val = 0;
|
|
|
|
unsigned long length;
|
|
|
|
if (count < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
length = count > 20 ? 20 : count;
|
|
|
|
if (copy_from_user(&buf[0], buffer, length))
|
|
|
|
return -EFAULT;
|
|
|
|
buf[length - 1] = '\0'; /*Ensure end string */
|
|
|
|
strict_strtoul(&buf[0], 0, (unsigned long *)®_val);
|
|
|
|
viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
|
|
|
|
return count;
|
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
|
|
|
|
static const struct file_operations viafb_dfph_proc_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.open = viafb_dfph_proc_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
.write = viafb_dfph_proc_write,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int viafb_dfpl_proc_show(struct seq_file *m, void *v)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
u8 dfp_low = 0;
|
|
|
|
dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
|
2009-09-23 06:47:27 +07:00
|
|
|
seq_printf(m, "%x\n", dfp_low);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_dfpl_proc_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, viafb_dfpl_proc_show, NULL);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
|
|
|
|
static ssize_t viafb_dfpl_proc_write(struct file *file,
|
|
|
|
const char __user *buffer, size_t count, loff_t *pos)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
char buf[20];
|
|
|
|
u8 reg_val = 0;
|
|
|
|
unsigned long length;
|
|
|
|
if (count < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
length = count > 20 ? 20 : count;
|
|
|
|
if (copy_from_user(&buf[0], buffer, length))
|
|
|
|
return -EFAULT;
|
|
|
|
buf[length - 1] = '\0'; /*Ensure end string */
|
|
|
|
strict_strtoul(&buf[0], 0, (unsigned long *)®_val);
|
|
|
|
viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
|
|
|
|
return count;
|
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
|
|
|
|
static const struct file_operations viafb_dfpl_proc_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.open = viafb_dfpl_proc_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
.write = viafb_dfpl_proc_write,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int viafb_vt1636_proc_show(struct seq_file *m, void *v)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
u8 vt1636_08 = 0, vt1636_09 = 0;
|
|
|
|
switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
|
|
|
|
case VT1636_LVDS:
|
|
|
|
vt1636_08 =
|
|
|
|
viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
|
|
|
|
&viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
|
|
|
|
vt1636_09 =
|
|
|
|
viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
|
|
|
|
&viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
|
2009-09-23 06:47:27 +07:00
|
|
|
seq_printf(m, "%x %x\n", vt1636_08, vt1636_09);
|
2008-10-16 12:03:27 +07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
|
|
|
|
case VT1636_LVDS:
|
|
|
|
vt1636_08 =
|
|
|
|
viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
|
|
|
|
&viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
|
|
|
|
vt1636_09 =
|
|
|
|
viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
|
|
|
|
&viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
|
2009-09-23 06:47:27 +07:00
|
|
|
seq_printf(m, " %x %x\n", vt1636_08, vt1636_09);
|
2008-10-16 12:03:27 +07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
return 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2009-09-23 06:47:27 +07:00
|
|
|
|
|
|
|
static int viafb_vt1636_proc_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, viafb_vt1636_proc_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t viafb_vt1636_proc_write(struct file *file,
|
|
|
|
const char __user *buffer, size_t count, loff_t *pos)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
char buf[30], *value, *pbuf;
|
|
|
|
struct IODATA reg_val;
|
|
|
|
unsigned long length, i;
|
|
|
|
if (count < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
length = count > 30 ? 30 : count;
|
|
|
|
if (copy_from_user(&buf[0], buffer, length))
|
|
|
|
return -EFAULT;
|
|
|
|
buf[length - 1] = '\0'; /*Ensure end string */
|
|
|
|
pbuf = &buf[0];
|
|
|
|
switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
|
|
|
|
case VT1636_LVDS:
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
value = strsep(&pbuf, " ");
|
|
|
|
if (value != NULL) {
|
|
|
|
strict_strtoul(value, 0,
|
|
|
|
(unsigned long *)®_val.Data);
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
reg_val.Index = 0x08;
|
|
|
|
reg_val.Mask = 0x0f;
|
|
|
|
viafb_gpio_i2c_write_mask_lvds
|
|
|
|
(viaparinfo->lvds_setting_info,
|
|
|
|
&viaparinfo->
|
|
|
|
chip_info->lvds_chip_info,
|
|
|
|
reg_val);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
reg_val.Index = 0x09;
|
|
|
|
reg_val.Mask = 0x1f;
|
|
|
|
viafb_gpio_i2c_write_mask_lvds
|
|
|
|
(viaparinfo->lvds_setting_info,
|
|
|
|
&viaparinfo->
|
|
|
|
chip_info->lvds_chip_info,
|
|
|
|
reg_val);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
|
|
|
|
case VT1636_LVDS:
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
value = strsep(&pbuf, " ");
|
|
|
|
if (value != NULL) {
|
|
|
|
strict_strtoul(value, 0,
|
|
|
|
(unsigned long *)®_val.Data);
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
reg_val.Index = 0x08;
|
|
|
|
reg_val.Mask = 0x0f;
|
|
|
|
viafb_gpio_i2c_write_mask_lvds
|
|
|
|
(viaparinfo->lvds_setting_info2,
|
|
|
|
&viaparinfo->
|
|
|
|
chip_info->lvds_chip_info2,
|
|
|
|
reg_val);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
reg_val.Index = 0x09;
|
|
|
|
reg_val.Mask = 0x1f;
|
|
|
|
viafb_gpio_i2c_write_mask_lvds
|
|
|
|
(viaparinfo->lvds_setting_info2,
|
|
|
|
&viaparinfo->
|
|
|
|
chip_info->lvds_chip_info2,
|
|
|
|
reg_val);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:27 +07:00
|
|
|
static const struct file_operations viafb_vt1636_proc_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.open = viafb_vt1636_proc_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
.write = viafb_vt1636_proc_write,
|
|
|
|
};
|
|
|
|
|
2010-09-05 08:33:28 +07:00
|
|
|
#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
|
|
|
|
|
2010-09-19 11:20:55 +07:00
|
|
|
static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
|
|
|
|
{
|
|
|
|
via_odev_to_seq(m, supported_odev_map[
|
|
|
|
viaparinfo->shared->chip_info.gfx_chip_name]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_sup_odev_proc_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, viafb_sup_odev_proc_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations viafb_sup_odev_proc_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.open = viafb_sup_odev_proc_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
};
|
|
|
|
|
2010-09-05 08:33:28 +07:00
|
|
|
static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
2010-09-05 08:33:28 +07:00
|
|
|
char buf[64], *ptr = buf;
|
|
|
|
u32 devices;
|
|
|
|
bool add, sub;
|
|
|
|
|
|
|
|
if (count < 1 || count > 63)
|
|
|
|
return -EINVAL;
|
|
|
|
if (copy_from_user(&buf[0], buffer, count))
|
|
|
|
return -EFAULT;
|
|
|
|
buf[count] = '\0';
|
|
|
|
add = buf[0] == '+';
|
|
|
|
sub = buf[0] == '-';
|
|
|
|
if (add || sub)
|
|
|
|
ptr++;
|
|
|
|
devices = via_parse_odev(ptr, &ptr);
|
|
|
|
if (*ptr == '\n')
|
|
|
|
ptr++;
|
|
|
|
if (*ptr != 0)
|
|
|
|
return -EINVAL;
|
|
|
|
if (add)
|
|
|
|
*odev |= devices;
|
|
|
|
else if (sub)
|
|
|
|
*odev &= ~devices;
|
|
|
|
else
|
|
|
|
*odev = devices;
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
|
|
|
|
{
|
|
|
|
via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, viafb_iga1_odev_proc_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t viafb_iga1_odev_proc_write(struct file *file,
|
|
|
|
const char __user *buffer, size_t count, loff_t *pos)
|
|
|
|
{
|
|
|
|
u32 dev_on, dev_off, dev_old, dev_new;
|
|
|
|
ssize_t res;
|
|
|
|
|
|
|
|
dev_old = dev_new = viaparinfo->shared->iga1_devices;
|
|
|
|
res = odev_update(buffer, count, &dev_new);
|
|
|
|
if (res != count)
|
|
|
|
return res;
|
|
|
|
dev_off = dev_old & ~dev_new;
|
|
|
|
dev_on = dev_new & ~dev_old;
|
|
|
|
viaparinfo->shared->iga1_devices = dev_new;
|
|
|
|
viaparinfo->shared->iga2_devices &= ~dev_new;
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(dev_off, VIA_STATE_OFF);
|
2010-09-05 08:33:28 +07:00
|
|
|
via_set_source(dev_new, IGA1);
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(dev_on, VIA_STATE_ON);
|
2010-09-05 08:33:28 +07:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations viafb_iga1_odev_proc_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.open = viafb_iga1_odev_proc_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
.write = viafb_iga1_odev_proc_write,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
|
|
|
|
{
|
|
|
|
via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, viafb_iga2_odev_proc_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t viafb_iga2_odev_proc_write(struct file *file,
|
|
|
|
const char __user *buffer, size_t count, loff_t *pos)
|
|
|
|
{
|
|
|
|
u32 dev_on, dev_off, dev_old, dev_new;
|
|
|
|
ssize_t res;
|
|
|
|
|
|
|
|
dev_old = dev_new = viaparinfo->shared->iga2_devices;
|
|
|
|
res = odev_update(buffer, count, &dev_new);
|
|
|
|
if (res != count)
|
|
|
|
return res;
|
|
|
|
dev_off = dev_old & ~dev_new;
|
|
|
|
dev_on = dev_new & ~dev_old;
|
|
|
|
viaparinfo->shared->iga2_devices = dev_new;
|
|
|
|
viaparinfo->shared->iga1_devices &= ~dev_new;
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(dev_off, VIA_STATE_OFF);
|
2010-09-05 08:33:28 +07:00
|
|
|
via_set_source(dev_new, IGA2);
|
2010-09-07 21:28:26 +07:00
|
|
|
via_set_state(dev_on, VIA_STATE_ON);
|
2010-09-05 08:33:28 +07:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations viafb_iga2_odev_proc_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.open = viafb_iga2_odev_proc_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
.write = viafb_iga2_odev_proc_write,
|
|
|
|
};
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-09-05 08:33:28 +07:00
|
|
|
#define IS_VT1636(lvds_chip) ((lvds_chip).lvds_chip_name == VT1636_LVDS)
|
|
|
|
static void viafb_init_proc(struct viafb_shared *shared)
|
|
|
|
{
|
|
|
|
struct proc_dir_entry *iga1_entry, *iga2_entry,
|
|
|
|
*viafb_entry = proc_mkdir("viafb", NULL);
|
|
|
|
|
|
|
|
shared->proc_entry = viafb_entry;
|
|
|
|
if (viafb_entry) {
|
|
|
|
#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
|
|
|
|
proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
|
|
|
|
proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
|
|
|
|
proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
|
|
|
|
proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
|
|
|
|
if (IS_VT1636(shared->chip_info.lvds_chip_info)
|
|
|
|
|| IS_VT1636(shared->chip_info.lvds_chip_info2))
|
|
|
|
proc_create("vt1636", 0, viafb_entry,
|
|
|
|
&viafb_vt1636_proc_fops);
|
|
|
|
#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
|
|
|
|
|
2010-09-19 11:20:55 +07:00
|
|
|
proc_create("supported_output_devices", 0, viafb_entry,
|
|
|
|
&viafb_sup_odev_proc_fops);
|
2010-09-05 08:33:28 +07:00
|
|
|
iga1_entry = proc_mkdir("iga1", viafb_entry);
|
|
|
|
shared->iga1_proc_entry = iga1_entry;
|
|
|
|
proc_create("output_devices", 0, iga1_entry,
|
|
|
|
&viafb_iga1_odev_proc_fops);
|
|
|
|
iga2_entry = proc_mkdir("iga2", viafb_entry);
|
|
|
|
shared->iga2_proc_entry = iga2_entry;
|
|
|
|
proc_create("output_devices", 0, iga2_entry,
|
|
|
|
&viafb_iga2_odev_proc_fops);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
}
|
2010-09-05 08:33:28 +07:00
|
|
|
static void viafb_remove_proc(struct viafb_shared *shared)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
2010-09-05 08:33:28 +07:00
|
|
|
struct proc_dir_entry *viafb_entry = shared->proc_entry,
|
|
|
|
*iga1_entry = shared->iga1_proc_entry,
|
|
|
|
*iga2_entry = shared->iga2_proc_entry;
|
|
|
|
|
|
|
|
if (!viafb_entry)
|
|
|
|
return;
|
2010-04-18 02:44:56 +07:00
|
|
|
|
2010-09-05 08:33:28 +07:00
|
|
|
remove_proc_entry("output_devices", iga2_entry);
|
|
|
|
remove_proc_entry("iga2", viafb_entry);
|
|
|
|
remove_proc_entry("output_devices", iga1_entry);
|
|
|
|
remove_proc_entry("iga1", viafb_entry);
|
2010-09-19 11:20:55 +07:00
|
|
|
remove_proc_entry("supported_output_devices", viafb_entry);
|
2010-09-05 08:33:28 +07:00
|
|
|
|
|
|
|
#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
|
2008-10-16 12:03:27 +07:00
|
|
|
remove_proc_entry("dvp0", viafb_entry);/* parent dir */
|
|
|
|
remove_proc_entry("dvp1", viafb_entry);
|
|
|
|
remove_proc_entry("dfph", viafb_entry);
|
|
|
|
remove_proc_entry("dfpl", viafb_entry);
|
2010-09-05 08:33:28 +07:00
|
|
|
if (IS_VT1636(shared->chip_info.lvds_chip_info)
|
|
|
|
|| IS_VT1636(shared->chip_info.lvds_chip_info2))
|
2010-04-18 02:44:56 +07:00
|
|
|
remove_proc_entry("vt1636", viafb_entry);
|
2010-09-05 08:33:28 +07:00
|
|
|
#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
|
2010-04-18 02:44:56 +07:00
|
|
|
|
2008-11-20 06:36:23 +07:00
|
|
|
remove_proc_entry("viafb", NULL);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2010-09-05 08:33:28 +07:00
|
|
|
#undef IS_VT1636
|
2010-04-18 02:44:57 +07:00
|
|
|
|
2010-03-11 06:21:34 +07:00
|
|
|
static int parse_mode(const char *str, u32 *xres, u32 *yres)
|
2009-09-23 06:47:34 +07:00
|
|
|
{
|
|
|
|
char *ptr;
|
|
|
|
|
2010-03-11 06:21:34 +07:00
|
|
|
if (!str) {
|
2011-05-11 04:34:11 +07:00
|
|
|
if (machine_is_olpc()) {
|
|
|
|
*xres = 1200;
|
|
|
|
*yres = 900;
|
|
|
|
} else {
|
|
|
|
*xres = 640;
|
|
|
|
*yres = 480;
|
|
|
|
}
|
2010-03-11 06:21:34 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:34 +07:00
|
|
|
*xres = simple_strtoul(str, &ptr, 10);
|
|
|
|
if (ptr[0] != 'x')
|
2010-03-11 06:21:34 +07:00
|
|
|
return -EINVAL;
|
2009-09-23 06:47:34 +07:00
|
|
|
|
|
|
|
*yres = simple_strtoul(&ptr[1], &ptr, 10);
|
|
|
|
if (ptr[0])
|
2010-03-11 06:21:34 +07:00
|
|
|
return -EINVAL;
|
2009-09-23 06:47:34 +07:00
|
|
|
|
2010-03-11 06:21:34 +07:00
|
|
|
return 0;
|
2009-09-23 06:47:34 +07:00
|
|
|
}
|
|
|
|
|
2009-12-02 10:29:39 +07:00
|
|
|
|
2010-04-09 00:15:41 +07:00
|
|
|
#ifdef CONFIG_PM
|
2010-10-29 00:23:01 +07:00
|
|
|
static int viafb_suspend(void *unused)
|
2010-04-09 00:15:41 +07:00
|
|
|
{
|
2011-01-26 06:07:35 +07:00
|
|
|
console_lock();
|
2010-10-29 00:23:01 +07:00
|
|
|
fb_set_suspend(viafbinfo, 1);
|
|
|
|
viafb_sync(viafbinfo);
|
2011-01-26 06:07:35 +07:00
|
|
|
console_unlock();
|
2010-04-09 00:15:41 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-10-29 00:23:01 +07:00
|
|
|
static int viafb_resume(void *unused)
|
2010-04-09 00:15:41 +07:00
|
|
|
{
|
2011-01-26 06:07:35 +07:00
|
|
|
console_lock();
|
2010-04-27 00:31:03 +07:00
|
|
|
if (viaparinfo->shared->vdev->engine_mmio)
|
|
|
|
viafb_reset_engine(viaparinfo);
|
2010-04-26 23:37:53 +07:00
|
|
|
viafb_set_par(viafbinfo);
|
|
|
|
if (viafb_dual_fb)
|
|
|
|
viafb_set_par(viafbinfo1);
|
2010-04-09 00:15:41 +07:00
|
|
|
fb_set_suspend(viafbinfo, 0);
|
|
|
|
|
2011-01-26 06:07:35 +07:00
|
|
|
console_unlock();
|
2010-04-09 00:15:41 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-10-29 00:23:01 +07:00
|
|
|
static struct viafb_pm_hooks viafb_fb_pm_hooks = {
|
|
|
|
.suspend = viafb_suspend,
|
|
|
|
.resume = viafb_resume
|
|
|
|
};
|
|
|
|
|
2010-04-09 00:15:41 +07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2010-04-23 02:48:09 +07:00
|
|
|
int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
2009-09-23 06:47:34 +07:00
|
|
|
u32 default_xres, default_yres;
|
2010-03-11 06:21:28 +07:00
|
|
|
struct VideoModeTable *vmode_entry;
|
2010-03-11 06:21:37 +07:00
|
|
|
struct fb_var_screeninfo default_var;
|
2009-05-19 16:12:58 +07:00
|
|
|
int rc;
|
2009-09-23 06:47:24 +07:00
|
|
|
u32 viafb_par_length;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
|
2010-03-11 06:21:37 +07:00
|
|
|
memset(&default_var, 0, sizeof(default_var));
|
2008-10-16 12:03:27 +07:00
|
|
|
viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
|
|
|
|
|
|
|
|
/* Allocate fb_info and ***_par here, also including some other needed
|
|
|
|
* variables
|
|
|
|
*/
|
2009-09-23 06:47:24 +07:00
|
|
|
viafbinfo = framebuffer_alloc(viafb_par_length +
|
2009-09-23 06:47:38 +07:00
|
|
|
ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8),
|
2010-04-23 02:48:09 +07:00
|
|
|
&vdev->pdev->dev);
|
2008-10-16 12:03:27 +07:00
|
|
|
if (!viafbinfo) {
|
|
|
|
printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
|
2009-05-19 16:12:58 +07:00
|
|
|
return -ENOMEM;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
viaparinfo = (struct viafb_par *)viafbinfo->par;
|
2009-09-23 06:47:24 +07:00
|
|
|
viaparinfo->shared = viafbinfo->par + viafb_par_length;
|
2010-04-23 02:48:09 +07:00
|
|
|
viaparinfo->shared->vdev = vdev;
|
2009-09-23 06:47:26 +07:00
|
|
|
viaparinfo->vram_addr = 0;
|
2009-09-23 06:47:24 +07:00
|
|
|
viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info;
|
|
|
|
viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
|
|
|
|
viaparinfo->lvds_setting_info2 =
|
|
|
|
&viaparinfo->shared->lvds_setting_info2;
|
|
|
|
viaparinfo->chip_info = &viaparinfo->shared->chip_info;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
if (viafb_dual_fb)
|
|
|
|
viafb_SAMM_ON = 1;
|
|
|
|
parse_lcd_port();
|
|
|
|
parse_dvi_port();
|
|
|
|
|
2010-04-23 02:48:09 +07:00
|
|
|
viafb_init_chip_info(vdev->chip_type);
|
|
|
|
/*
|
|
|
|
* The framebuffer will have been successfully mapped by
|
|
|
|
* the core (or we'd not be here), but we still need to
|
|
|
|
* set up our own accounting.
|
|
|
|
*/
|
|
|
|
viaparinfo->fbmem = vdev->fbmem_start;
|
|
|
|
viaparinfo->memsize = vdev->fbmem_len;
|
2008-10-16 12:03:27 +07:00
|
|
|
viaparinfo->fbmem_free = viaparinfo->memsize;
|
|
|
|
viaparinfo->fbmem_used = 0;
|
2010-04-23 02:48:09 +07:00
|
|
|
viafbinfo->screen_base = vdev->fbmem;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2010-04-23 02:48:09 +07:00
|
|
|
viafbinfo->fix.mmio_start = vdev->engine_start;
|
|
|
|
viafbinfo->fix.mmio_len = vdev->engine_len;
|
2008-10-16 12:03:27 +07:00
|
|
|
viafbinfo->node = 0;
|
|
|
|
viafbinfo->fbops = &viafb_ops;
|
|
|
|
viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
|
|
|
|
|
|
|
|
viafbinfo->pseudo_palette = pseudo_pal;
|
2010-04-27 00:31:03 +07:00
|
|
|
if (viafb_accel && !viafb_setup_engine(viafbinfo)) {
|
2009-09-23 06:47:31 +07:00
|
|
|
viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA |
|
|
|
|
FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT;
|
|
|
|
default_var.accel_flags = FB_ACCELF_TEXT;
|
|
|
|
} else {
|
|
|
|
viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
|
|
|
|
default_var.accel_flags = 0;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (viafb_second_size && (viafb_second_size < 8)) {
|
|
|
|
viafb_second_offset = viaparinfo->fbmem_free -
|
|
|
|
viafb_second_size * 1024 * 1024;
|
|
|
|
} else {
|
|
|
|
viafb_second_size = 8;
|
|
|
|
viafb_second_offset = viaparinfo->fbmem_free -
|
|
|
|
viafb_second_size * 1024 * 1024;
|
|
|
|
}
|
|
|
|
|
2009-09-23 06:47:34 +07:00
|
|
|
parse_mode(viafb_mode, &default_xres, &default_yres);
|
2010-03-11 06:21:28 +07:00
|
|
|
vmode_entry = viafb_get_mode(default_xres, default_yres);
|
2011-03-27 09:54:32 +07:00
|
|
|
if (viafb_SAMM_ON == 1)
|
2009-09-23 06:47:34 +07:00
|
|
|
parse_mode(viafb_mode1, &viafb_second_xres,
|
|
|
|
&viafb_second_yres);
|
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
default_var.xres = default_xres;
|
|
|
|
default_var.yres = default_yres;
|
2010-07-14 02:44:05 +07:00
|
|
|
default_var.xres_virtual = default_xres;
|
2008-10-16 12:03:27 +07:00
|
|
|
default_var.yres_virtual = default_yres;
|
|
|
|
default_var.bits_per_pixel = viafb_bpp;
|
2011-03-22 00:01:07 +07:00
|
|
|
viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
|
|
|
|
default_var.xres, default_var.yres, viafb_refresh),
|
|
|
|
viafb_get_mode(default_var.xres, default_var.yres));
|
2010-03-11 06:21:31 +07:00
|
|
|
viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
|
|
|
|
viafbinfo->var = default_var;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
if (viafb_dual_fb) {
|
2010-04-23 02:48:09 +07:00
|
|
|
viafbinfo1 = framebuffer_alloc(viafb_par_length,
|
|
|
|
&vdev->pdev->dev);
|
2008-10-16 12:03:27 +07:00
|
|
|
if (!viafbinfo1) {
|
|
|
|
printk(KERN_ERR
|
|
|
|
"allocate the second framebuffer struct error\n");
|
2009-05-19 16:12:58 +07:00
|
|
|
rc = -ENOMEM;
|
2010-04-23 02:48:09 +07:00
|
|
|
goto out_fb_release;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
viaparinfo1 = viafbinfo1->par;
|
|
|
|
memcpy(viaparinfo1, viaparinfo, viafb_par_length);
|
2009-09-23 06:47:26 +07:00
|
|
|
viaparinfo1->vram_addr = viafb_second_offset;
|
2008-10-16 12:03:27 +07:00
|
|
|
viaparinfo1->memsize = viaparinfo->memsize -
|
|
|
|
viafb_second_offset;
|
|
|
|
viaparinfo->memsize = viafb_second_offset;
|
|
|
|
viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
|
|
|
|
|
|
|
|
viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
|
|
|
|
viaparinfo1->fbmem_free = viaparinfo1->memsize -
|
|
|
|
viaparinfo1->fbmem_used;
|
|
|
|
viaparinfo->fbmem_free = viaparinfo->memsize;
|
|
|
|
viaparinfo->fbmem_used = 0;
|
|
|
|
|
2009-09-23 06:47:14 +07:00
|
|
|
viaparinfo->iga_path = IGA1;
|
|
|
|
viaparinfo1->iga_path = IGA2;
|
2008-10-16 12:03:27 +07:00
|
|
|
memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
|
2009-09-23 06:47:24 +07:00
|
|
|
viafbinfo1->par = viaparinfo1;
|
2008-10-16 12:03:27 +07:00
|
|
|
viafbinfo1->screen_base = viafbinfo->screen_base +
|
|
|
|
viafb_second_offset;
|
|
|
|
|
|
|
|
default_var.xres = viafb_second_xres;
|
|
|
|
default_var.yres = viafb_second_yres;
|
2011-03-27 09:54:32 +07:00
|
|
|
default_var.xres_virtual = viafb_second_xres;
|
|
|
|
default_var.yres_virtual = viafb_second_yres;
|
2008-10-16 12:03:27 +07:00
|
|
|
default_var.bits_per_pixel = viafb_bpp1;
|
2011-03-22 00:01:07 +07:00
|
|
|
viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
|
|
|
|
default_var.xres, default_var.yres, viafb_refresh1),
|
|
|
|
viafb_get_mode(default_var.xres, default_var.yres));
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
|
|
|
|
viafb_check_var(&default_var, viafbinfo1);
|
|
|
|
viafbinfo1->var = default_var;
|
2009-09-23 06:47:13 +07:00
|
|
|
viafb_update_fix(viafbinfo1);
|
2009-09-23 06:47:26 +07:00
|
|
|
viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var,
|
|
|
|
&viafbinfo1->fix);
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2010-03-11 06:21:41 +07:00
|
|
|
viafb_check_var(&viafbinfo->var, viafbinfo);
|
2009-09-23 06:47:13 +07:00
|
|
|
viafb_update_fix(viafbinfo);
|
2009-09-23 06:47:26 +07:00
|
|
|
viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
|
|
|
|
&viafbinfo->fix);
|
2008-10-16 12:03:27 +07:00
|
|
|
default_var.activate = FB_ACTIVATE_NOW;
|
2009-05-19 16:12:58 +07:00
|
|
|
rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
|
|
|
|
if (rc)
|
|
|
|
goto out_fb1_release;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
|
|
|
|
&& (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
|
2009-05-19 16:12:58 +07:00
|
|
|
rc = register_framebuffer(viafbinfo1);
|
|
|
|
if (rc)
|
|
|
|
goto out_dealloc_cmap;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
2009-05-19 16:12:58 +07:00
|
|
|
rc = register_framebuffer(viafbinfo);
|
|
|
|
if (rc)
|
|
|
|
goto out_fb1_unreg_lcd_cle266;
|
2008-10-16 12:03:27 +07:00
|
|
|
|
|
|
|
if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
|
|
|
|
|| (viaparinfo->chip_info->gfx_chip_name !=
|
|
|
|
UNICHROME_CLE266))) {
|
2009-05-19 16:12:58 +07:00
|
|
|
rc = register_framebuffer(viafbinfo1);
|
|
|
|
if (rc)
|
|
|
|
goto out_fb_unreg;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
|
|
|
|
viafbinfo->node, viafbinfo->fix.id, default_var.xres,
|
|
|
|
default_var.yres, default_var.bits_per_pixel);
|
|
|
|
|
2010-09-05 08:33:28 +07:00
|
|
|
viafb_init_proc(viaparinfo->shared);
|
2008-10-16 12:03:27 +07:00
|
|
|
viafb_init_dac(IGA2);
|
2010-10-29 00:23:01 +07:00
|
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
|
|
viafb_pm_register(&viafb_fb_pm_hooks);
|
|
|
|
#endif
|
2008-10-16 12:03:27 +07:00
|
|
|
return 0;
|
2009-05-19 16:12:58 +07:00
|
|
|
|
|
|
|
out_fb_unreg:
|
|
|
|
unregister_framebuffer(viafbinfo);
|
|
|
|
out_fb1_unreg_lcd_cle266:
|
|
|
|
if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
|
|
|
|
&& (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
|
|
|
|
unregister_framebuffer(viafbinfo1);
|
|
|
|
out_dealloc_cmap:
|
|
|
|
fb_dealloc_cmap(&viafbinfo->cmap);
|
|
|
|
out_fb1_release:
|
|
|
|
if (viafbinfo1)
|
|
|
|
framebuffer_release(viafbinfo1);
|
|
|
|
out_fb_release:
|
|
|
|
framebuffer_release(viafbinfo);
|
|
|
|
return rc;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2009-12-02 10:29:39 +07:00
|
|
|
void __devexit via_fb_pci_remove(struct pci_dev *pdev)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
|
|
|
|
fb_dealloc_cmap(&viafbinfo->cmap);
|
|
|
|
unregister_framebuffer(viafbinfo);
|
|
|
|
if (viafb_dual_fb)
|
|
|
|
unregister_framebuffer(viafbinfo1);
|
2010-09-05 08:33:28 +07:00
|
|
|
viafb_remove_proc(viaparinfo->shared);
|
2008-10-16 12:03:27 +07:00
|
|
|
framebuffer_release(viafbinfo);
|
|
|
|
if (viafb_dual_fb)
|
|
|
|
framebuffer_release(viafbinfo1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef MODULE
|
2011-05-11 04:34:11 +07:00
|
|
|
static int __init viafb_setup(void)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
char *this_opt;
|
2011-05-11 04:34:11 +07:00
|
|
|
char *options;
|
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
DEBUG_MSG(KERN_INFO "viafb_setup!\n");
|
|
|
|
|
2011-05-11 04:34:11 +07:00
|
|
|
if (fb_get_options("viafb", &options))
|
|
|
|
return -ENODEV;
|
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
if (!options || !*options)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while ((this_opt = strsep(&options, ",")) != NULL) {
|
|
|
|
if (!*this_opt)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!strncmp(this_opt, "viafb_mode1=", 12))
|
|
|
|
viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
|
|
|
|
else if (!strncmp(this_opt, "viafb_mode=", 11))
|
|
|
|
viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
|
|
|
|
else if (!strncmp(this_opt, "viafb_bpp1=", 11))
|
|
|
|
strict_strtoul(this_opt + 11, 0,
|
|
|
|
(unsigned long *)&viafb_bpp1);
|
|
|
|
else if (!strncmp(this_opt, "viafb_bpp=", 10))
|
|
|
|
strict_strtoul(this_opt + 10, 0,
|
|
|
|
(unsigned long *)&viafb_bpp);
|
|
|
|
else if (!strncmp(this_opt, "viafb_refresh1=", 15))
|
|
|
|
strict_strtoul(this_opt + 15, 0,
|
|
|
|
(unsigned long *)&viafb_refresh1);
|
|
|
|
else if (!strncmp(this_opt, "viafb_refresh=", 14))
|
|
|
|
strict_strtoul(this_opt + 14, 0,
|
|
|
|
(unsigned long *)&viafb_refresh);
|
|
|
|
else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21))
|
|
|
|
strict_strtoul(this_opt + 21, 0,
|
|
|
|
(unsigned long *)&viafb_lcd_dsp_method);
|
|
|
|
else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19))
|
|
|
|
strict_strtoul(this_opt + 19, 0,
|
|
|
|
(unsigned long *)&viafb_lcd_panel_id);
|
|
|
|
else if (!strncmp(this_opt, "viafb_accel=", 12))
|
|
|
|
strict_strtoul(this_opt + 12, 0,
|
|
|
|
(unsigned long *)&viafb_accel);
|
|
|
|
else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14))
|
|
|
|
strict_strtoul(this_opt + 14, 0,
|
|
|
|
(unsigned long *)&viafb_SAMM_ON);
|
|
|
|
else if (!strncmp(this_opt, "viafb_active_dev=", 17))
|
|
|
|
viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
|
|
|
|
else if (!strncmp(this_opt,
|
|
|
|
"viafb_display_hardware_layout=", 30))
|
|
|
|
strict_strtoul(this_opt + 30, 0,
|
|
|
|
(unsigned long *)&viafb_display_hardware_layout);
|
|
|
|
else if (!strncmp(this_opt, "viafb_second_size=", 18))
|
|
|
|
strict_strtoul(this_opt + 18, 0,
|
|
|
|
(unsigned long *)&viafb_second_size);
|
|
|
|
else if (!strncmp(this_opt,
|
|
|
|
"viafb_platform_epia_dvi=", 24))
|
|
|
|
strict_strtoul(this_opt + 24, 0,
|
|
|
|
(unsigned long *)&viafb_platform_epia_dvi);
|
|
|
|
else if (!strncmp(this_opt,
|
|
|
|
"viafb_device_lcd_dualedge=", 26))
|
|
|
|
strict_strtoul(this_opt + 26, 0,
|
|
|
|
(unsigned long *)&viafb_device_lcd_dualedge);
|
|
|
|
else if (!strncmp(this_opt, "viafb_bus_width=", 16))
|
|
|
|
strict_strtoul(this_opt + 16, 0,
|
|
|
|
(unsigned long *)&viafb_bus_width);
|
|
|
|
else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
|
|
|
|
strict_strtoul(this_opt + 15, 0,
|
|
|
|
(unsigned long *)&viafb_lcd_mode);
|
|
|
|
else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
|
|
|
|
viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
|
|
|
|
else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
|
|
|
|
viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-12-02 10:29:39 +07:00
|
|
|
/*
|
|
|
|
* These are called out of via-core for now.
|
|
|
|
*/
|
|
|
|
int __init viafb_init(void)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
2011-03-22 00:01:07 +07:00
|
|
|
u32 dummy_x, dummy_y;
|
2011-06-10 15:57:04 +07:00
|
|
|
int r = 0;
|
2011-05-11 04:34:11 +07:00
|
|
|
|
|
|
|
if (machine_is_olpc())
|
|
|
|
/* Apply XO-1.5-specific configuration. */
|
|
|
|
viafb_lcd_panel_id = 23;
|
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
#ifndef MODULE
|
2011-05-11 04:34:11 +07:00
|
|
|
r = viafb_setup();
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2008-10-16 12:03:27 +07:00
|
|
|
#endif
|
2011-03-22 00:01:07 +07:00
|
|
|
if (parse_mode(viafb_mode, &dummy_x, &dummy_y)
|
|
|
|
|| !viafb_get_mode(dummy_x, dummy_y)
|
|
|
|
|| parse_mode(viafb_mode1, &dummy_x, &dummy_y)
|
|
|
|
|| !viafb_get_mode(dummy_x, dummy_y)
|
2010-03-11 06:21:41 +07:00
|
|
|
|| viafb_bpp < 0 || viafb_bpp > 32
|
|
|
|
|| viafb_bpp1 < 0 || viafb_bpp1 > 32
|
2010-03-11 06:21:34 +07:00
|
|
|
|| parse_active_dev())
|
|
|
|
return -EINVAL;
|
|
|
|
|
2008-10-16 12:03:27 +07:00
|
|
|
printk(KERN_INFO
|
2011-03-31 08:57:33 +07:00
|
|
|
"VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
|
2008-10-16 12:03:27 +07:00
|
|
|
VERSION_MAJOR, VERSION_MINOR);
|
2011-06-10 15:57:04 +07:00
|
|
|
return r;
|
2008-10-16 12:03:27 +07:00
|
|
|
}
|
|
|
|
|
2009-12-02 10:29:39 +07:00
|
|
|
void __exit viafb_exit(void)
|
2008-10-16 12:03:27 +07:00
|
|
|
{
|
|
|
|
DEBUG_MSG(KERN_INFO "viafb_exit!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct fb_ops viafb_ops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.fb_open = viafb_open,
|
|
|
|
.fb_release = viafb_release,
|
|
|
|
.fb_check_var = viafb_check_var,
|
|
|
|
.fb_set_par = viafb_set_par,
|
|
|
|
.fb_setcolreg = viafb_setcolreg,
|
|
|
|
.fb_pan_display = viafb_pan_display,
|
|
|
|
.fb_blank = viafb_blank,
|
|
|
|
.fb_fillrect = viafb_fillrect,
|
|
|
|
.fb_copyarea = viafb_copyarea,
|
|
|
|
.fb_imageblit = viafb_imageblit,
|
|
|
|
.fb_cursor = viafb_cursor,
|
|
|
|
.fb_ioctl = viafb_ioctl,
|
|
|
|
.fb_sync = viafb_sync,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef MODULE
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_mode, charp, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_mode1, charp, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_bpp, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_bpp1, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_refresh, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_refresh,
|
|
|
|
"Set CRT viafb_refresh rate (default = 60)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_refresh1, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_refresh1,
|
|
|
|
"Set CRT refresh rate (default = 60)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_lcd_panel_id, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_lcd_panel_id,
|
|
|
|
"Set Flat Panel type(Default=1024x768)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_lcd_dsp_method, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_lcd_dsp_method,
|
|
|
|
"Set Flat Panel display scaling method.(Default=Expandsion)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_SAMM_ON, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_SAMM_ON,
|
|
|
|
"Turn on/off flag of SAMM(Default=OFF)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_accel, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_accel,
|
2009-09-23 06:47:31 +07:00
|
|
|
"Set 2D Hardware Acceleration: 0 = OFF, 1 = ON (default)");
|
2008-10-16 12:03:27 +07:00
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_active_dev, charp, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_display_hardware_layout, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_display_hardware_layout,
|
|
|
|
"Display Hardware Layout (LCD Only, DVI Only...,etc)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_second_size, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_second_size,
|
|
|
|
"Set secondary device memory size");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_dual_fb, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_dual_fb,
|
|
|
|
"Turn on/off flag of dual framebuffer devices.(Default = OFF)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_platform_epia_dvi, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_platform_epia_dvi,
|
|
|
|
"Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_device_lcd_dualedge, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_device_lcd_dualedge,
|
|
|
|
"Turn on/off flag of dual edge panel.(Default = OFF)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_bus_width, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_bus_width,
|
|
|
|
"Set bus width of panel.(Default = 12)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_lcd_mode, int, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_lcd_mode,
|
|
|
|
"Set Flat Panel mode(Default=OPENLDI)");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_lcd_port, charp, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
|
|
|
|
|
2009-09-23 06:47:32 +07:00
|
|
|
module_param(viafb_dvi_port, charp, S_IRUSR);
|
2008-10-16 12:03:27 +07:00
|
|
|
MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
|
|
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
#endif
|