18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
48c2ecf20Sopenharmony_ci * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/compiler.h>
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci#include <linux/stat.h>
138c2ecf20Sopenharmony_ci#include <linux/via-core.h>
148c2ecf20Sopenharmony_ci#include <linux/via_i2c.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define _MASTER_FILE
178c2ecf20Sopenharmony_ci#include "global.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic char *viafb_name = "Via";
208c2ecf20Sopenharmony_cistatic u32 pseudo_pal[17];
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* video mode */
238c2ecf20Sopenharmony_cistatic char *viafb_mode;
248c2ecf20Sopenharmony_cistatic char *viafb_mode1;
258c2ecf20Sopenharmony_cistatic int viafb_bpp = 32;
268c2ecf20Sopenharmony_cistatic int viafb_bpp1 = 32;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic unsigned int viafb_second_offset;
298c2ecf20Sopenharmony_cistatic int viafb_second_size;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic int viafb_accel = 1;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* Added for specifying active devices.*/
348c2ecf20Sopenharmony_cistatic char *viafb_active_dev;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/*Added for specify lcd output port*/
378c2ecf20Sopenharmony_cistatic char *viafb_lcd_port = "";
388c2ecf20Sopenharmony_cistatic char *viafb_dvi_port = "";
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic void retrieve_device_setting(struct viafb_ioctl_setting
418c2ecf20Sopenharmony_ci	*setting_info);
428c2ecf20Sopenharmony_cistatic int viafb_pan_display(struct fb_var_screeninfo *var,
438c2ecf20Sopenharmony_ci	struct fb_info *info);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic struct fb_ops viafb_ops;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/* supported output devices on each IGP
488c2ecf20Sopenharmony_ci * only CX700, VX800, VX855, VX900 were documented
498c2ecf20Sopenharmony_ci * VIA_CRT should be everywhere
508c2ecf20Sopenharmony_ci * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL
518c2ecf20Sopenharmony_ci * source selection on CX700 and later
528c2ecf20Sopenharmony_ci * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
538c2ecf20Sopenharmony_ci */
548c2ecf20Sopenharmony_cistatic const u32 supported_odev_map[] = {
558c2ecf20Sopenharmony_ci	[UNICHROME_CLE266]	= VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
568c2ecf20Sopenharmony_ci	[UNICHROME_K400]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
578c2ecf20Sopenharmony_ci				| VIA_LVDS2,
588c2ecf20Sopenharmony_ci	[UNICHROME_K800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
598c2ecf20Sopenharmony_ci				| VIA_LVDS2,
608c2ecf20Sopenharmony_ci	[UNICHROME_PM800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
618c2ecf20Sopenharmony_ci				| VIA_LVDS2,
628c2ecf20Sopenharmony_ci	[UNICHROME_CN700]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
638c2ecf20Sopenharmony_ci				| VIA_LVDS2,
648c2ecf20Sopenharmony_ci	[UNICHROME_CX700]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
658c2ecf20Sopenharmony_ci	[UNICHROME_CN750]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
668c2ecf20Sopenharmony_ci	[UNICHROME_K8M890]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
678c2ecf20Sopenharmony_ci	[UNICHROME_P4M890]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
688c2ecf20Sopenharmony_ci	[UNICHROME_P4M900]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
698c2ecf20Sopenharmony_ci	[UNICHROME_VX800]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
708c2ecf20Sopenharmony_ci	[UNICHROME_VX855]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
718c2ecf20Sopenharmony_ci	[UNICHROME_VX900]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	var->grayscale = 0;
778c2ecf20Sopenharmony_ci	var->red.msb_right = 0;
788c2ecf20Sopenharmony_ci	var->green.msb_right = 0;
798c2ecf20Sopenharmony_ci	var->blue.msb_right = 0;
808c2ecf20Sopenharmony_ci	var->transp.offset = 0;
818c2ecf20Sopenharmony_ci	var->transp.length = 0;
828c2ecf20Sopenharmony_ci	var->transp.msb_right = 0;
838c2ecf20Sopenharmony_ci	var->nonstd = 0;
848c2ecf20Sopenharmony_ci	switch (depth) {
858c2ecf20Sopenharmony_ci	case 8:
868c2ecf20Sopenharmony_ci		var->bits_per_pixel = 8;
878c2ecf20Sopenharmony_ci		var->red.offset = 0;
888c2ecf20Sopenharmony_ci		var->green.offset = 0;
898c2ecf20Sopenharmony_ci		var->blue.offset = 0;
908c2ecf20Sopenharmony_ci		var->red.length = 8;
918c2ecf20Sopenharmony_ci		var->green.length = 8;
928c2ecf20Sopenharmony_ci		var->blue.length = 8;
938c2ecf20Sopenharmony_ci		break;
948c2ecf20Sopenharmony_ci	case 15:
958c2ecf20Sopenharmony_ci		var->bits_per_pixel = 16;
968c2ecf20Sopenharmony_ci		var->red.offset = 10;
978c2ecf20Sopenharmony_ci		var->green.offset = 5;
988c2ecf20Sopenharmony_ci		var->blue.offset = 0;
998c2ecf20Sopenharmony_ci		var->red.length = 5;
1008c2ecf20Sopenharmony_ci		var->green.length = 5;
1018c2ecf20Sopenharmony_ci		var->blue.length = 5;
1028c2ecf20Sopenharmony_ci		break;
1038c2ecf20Sopenharmony_ci	case 16:
1048c2ecf20Sopenharmony_ci		var->bits_per_pixel = 16;
1058c2ecf20Sopenharmony_ci		var->red.offset = 11;
1068c2ecf20Sopenharmony_ci		var->green.offset = 5;
1078c2ecf20Sopenharmony_ci		var->blue.offset = 0;
1088c2ecf20Sopenharmony_ci		var->red.length = 5;
1098c2ecf20Sopenharmony_ci		var->green.length = 6;
1108c2ecf20Sopenharmony_ci		var->blue.length = 5;
1118c2ecf20Sopenharmony_ci		break;
1128c2ecf20Sopenharmony_ci	case 24:
1138c2ecf20Sopenharmony_ci		var->bits_per_pixel = 32;
1148c2ecf20Sopenharmony_ci		var->red.offset = 16;
1158c2ecf20Sopenharmony_ci		var->green.offset = 8;
1168c2ecf20Sopenharmony_ci		var->blue.offset = 0;
1178c2ecf20Sopenharmony_ci		var->red.length = 8;
1188c2ecf20Sopenharmony_ci		var->green.length = 8;
1198c2ecf20Sopenharmony_ci		var->blue.length = 8;
1208c2ecf20Sopenharmony_ci		break;
1218c2ecf20Sopenharmony_ci	case 30:
1228c2ecf20Sopenharmony_ci		var->bits_per_pixel = 32;
1238c2ecf20Sopenharmony_ci		var->red.offset = 20;
1248c2ecf20Sopenharmony_ci		var->green.offset = 10;
1258c2ecf20Sopenharmony_ci		var->blue.offset = 0;
1268c2ecf20Sopenharmony_ci		var->red.length = 10;
1278c2ecf20Sopenharmony_ci		var->green.length = 10;
1288c2ecf20Sopenharmony_ci		var->blue.length = 10;
1298c2ecf20Sopenharmony_ci		break;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic void viafb_update_fix(struct fb_info *info)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	u32 bpp = info->var.bits_per_pixel;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	info->fix.visual =
1388c2ecf20Sopenharmony_ci		bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1398c2ecf20Sopenharmony_ci	info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
1408c2ecf20Sopenharmony_ci		VIA_PITCH_SIZE);
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
1448c2ecf20Sopenharmony_ci	struct viafb_par *viaparinfo)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1478c2ecf20Sopenharmony_ci	strcpy(fix->id, viafb_name);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	fix->smem_start = viaparinfo->fbmem;
1508c2ecf20Sopenharmony_ci	fix->smem_len = viaparinfo->fbmem_free;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	fix->type = FB_TYPE_PACKED_PIXELS;
1538c2ecf20Sopenharmony_ci	fix->type_aux = 0;
1548c2ecf20Sopenharmony_ci	fix->visual = FB_VISUAL_TRUECOLOR;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	fix->xpanstep = fix->ywrapstep = 0;
1578c2ecf20Sopenharmony_ci	fix->ypanstep = 1;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	/* Just tell the accel name */
1608c2ecf20Sopenharmony_ci	viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_cistatic int viafb_open(struct fb_info *info, int user)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_open!\n");
1658c2ecf20Sopenharmony_ci	return 0;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic int viafb_release(struct fb_info *info, int user)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_release!\n");
1718c2ecf20Sopenharmony_ci	return 0;
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic inline int get_var_refresh(struct fb_var_screeninfo *var)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	u32 htotal, vtotal;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	htotal = var->left_margin + var->xres + var->right_margin
1798c2ecf20Sopenharmony_ci		+ var->hsync_len;
1808c2ecf20Sopenharmony_ci	vtotal = var->upper_margin + var->yres + var->lower_margin
1818c2ecf20Sopenharmony_ci		+ var->vsync_len;
1828c2ecf20Sopenharmony_ci	return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic int viafb_check_var(struct fb_var_screeninfo *var,
1868c2ecf20Sopenharmony_ci	struct fb_info *info)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	int depth, refresh;
1898c2ecf20Sopenharmony_ci	struct viafb_par *ppar = info->par;
1908c2ecf20Sopenharmony_ci	u32 line;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
1938c2ecf20Sopenharmony_ci	/* Sanity check */
1948c2ecf20Sopenharmony_ci	/* HW neither support interlacte nor double-scaned mode */
1958c2ecf20Sopenharmony_ci	if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
1968c2ecf20Sopenharmony_ci		return -EINVAL;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	/* the refresh rate is not important here, as we only want to know
1998c2ecf20Sopenharmony_ci	 * whether the resolution exists
2008c2ecf20Sopenharmony_ci	 */
2018c2ecf20Sopenharmony_ci	if (!viafb_get_best_mode(var->xres, var->yres, 60)) {
2028c2ecf20Sopenharmony_ci		DEBUG_MSG(KERN_INFO
2038c2ecf20Sopenharmony_ci			  "viafb: Mode %dx%dx%d not supported!!\n",
2048c2ecf20Sopenharmony_ci			  var->xres, var->yres, var->bits_per_pixel);
2058c2ecf20Sopenharmony_ci		return -EINVAL;
2068c2ecf20Sopenharmony_ci	}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	depth = fb_get_color_depth(var, &info->fix);
2098c2ecf20Sopenharmony_ci	if (!depth)
2108c2ecf20Sopenharmony_ci		depth = var->bits_per_pixel;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	if (depth < 0 || depth > 32)
2138c2ecf20Sopenharmony_ci		return -EINVAL;
2148c2ecf20Sopenharmony_ci	else if (!depth)
2158c2ecf20Sopenharmony_ci		depth = 24;
2168c2ecf20Sopenharmony_ci	else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
2178c2ecf20Sopenharmony_ci		depth = 15;
2188c2ecf20Sopenharmony_ci	else if (depth == 30)
2198c2ecf20Sopenharmony_ci		depth = 30;
2208c2ecf20Sopenharmony_ci	else if (depth <= 8)
2218c2ecf20Sopenharmony_ci		depth = 8;
2228c2ecf20Sopenharmony_ci	else if (depth <= 16)
2238c2ecf20Sopenharmony_ci		depth = 16;
2248c2ecf20Sopenharmony_ci	else
2258c2ecf20Sopenharmony_ci		depth = 24;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	viafb_fill_var_color_info(var, depth);
2288c2ecf20Sopenharmony_ci	if (var->xres_virtual < var->xres)
2298c2ecf20Sopenharmony_ci		var->xres_virtual = var->xres;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
2328c2ecf20Sopenharmony_ci		VIA_PITCH_SIZE);
2338c2ecf20Sopenharmony_ci	if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
2348c2ecf20Sopenharmony_ci		return -EINVAL;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	/* Based on var passed in to calculate the refresh,
2378c2ecf20Sopenharmony_ci	 * because our driver use some modes special.
2388c2ecf20Sopenharmony_ci	 */
2398c2ecf20Sopenharmony_ci	refresh = viafb_get_refresh(var->xres, var->yres,
2408c2ecf20Sopenharmony_ci		get_var_refresh(var));
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	/* Adjust var according to our driver's own table */
2438c2ecf20Sopenharmony_ci	viafb_fill_var_timing_info(var,
2448c2ecf20Sopenharmony_ci		viafb_get_best_mode(var->xres, var->yres, refresh));
2458c2ecf20Sopenharmony_ci	if (var->accel_flags & FB_ACCELF_TEXT &&
2468c2ecf20Sopenharmony_ci		!ppar->shared->vdev->engine_mmio)
2478c2ecf20Sopenharmony_ci		var->accel_flags = 0;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	return 0;
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic int viafb_set_par(struct fb_info *info)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	struct viafb_par *viapar = info->par;
2558c2ecf20Sopenharmony_ci	int refresh;
2568c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	viafb_update_fix(info);
2598c2ecf20Sopenharmony_ci	viapar->depth = fb_get_color_depth(&info->var, &info->fix);
2608c2ecf20Sopenharmony_ci	viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
2618c2ecf20Sopenharmony_ci		viafbinfo->var.bits_per_pixel, 0);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	if (viafb_dual_fb) {
2648c2ecf20Sopenharmony_ci		viafb_update_device_setting(viafbinfo1->var.xres,
2658c2ecf20Sopenharmony_ci			viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
2668c2ecf20Sopenharmony_ci			1);
2678c2ecf20Sopenharmony_ci	} else if (viafb_SAMM_ON == 1) {
2688c2ecf20Sopenharmony_ci		DEBUG_MSG(KERN_INFO
2698c2ecf20Sopenharmony_ci		"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
2708c2ecf20Sopenharmony_ci			  viafb_second_xres, viafb_second_yres, viafb_bpp1);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		viafb_update_device_setting(viafb_second_xres,
2738c2ecf20Sopenharmony_ci			viafb_second_yres, viafb_bpp1, 1);
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	refresh = get_var_refresh(&info->var);
2778c2ecf20Sopenharmony_ci	if (viafb_dual_fb && viapar->iga_path == IGA2) {
2788c2ecf20Sopenharmony_ci		viafb_bpp1 = info->var.bits_per_pixel;
2798c2ecf20Sopenharmony_ci		viafb_refresh1 = refresh;
2808c2ecf20Sopenharmony_ci	} else {
2818c2ecf20Sopenharmony_ci		viafb_bpp = info->var.bits_per_pixel;
2828c2ecf20Sopenharmony_ci		viafb_refresh = refresh;
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	if (info->var.accel_flags & FB_ACCELF_TEXT)
2868c2ecf20Sopenharmony_ci		info->flags &= ~FBINFO_HWACCEL_DISABLED;
2878c2ecf20Sopenharmony_ci	else
2888c2ecf20Sopenharmony_ci		info->flags |= FBINFO_HWACCEL_DISABLED;
2898c2ecf20Sopenharmony_ci	viafb_setmode();
2908c2ecf20Sopenharmony_ci	viafb_pan_display(&info->var, info);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	return 0;
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci/* Set one color register */
2968c2ecf20Sopenharmony_cistatic int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
2978c2ecf20Sopenharmony_ciunsigned blue, unsigned transp, struct fb_info *info)
2988c2ecf20Sopenharmony_ci{
2998c2ecf20Sopenharmony_ci	struct viafb_par *viapar = info->par;
3008c2ecf20Sopenharmony_ci	u32 r, g, b;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
3038c2ecf20Sopenharmony_ci		if (regno > 255)
3048c2ecf20Sopenharmony_ci			return -EINVAL;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci		if (!viafb_dual_fb || viapar->iga_path == IGA1)
3078c2ecf20Sopenharmony_ci			viafb_set_primary_color_register(regno, red >> 8,
3088c2ecf20Sopenharmony_ci				green >> 8, blue >> 8);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci		if (!viafb_dual_fb || viapar->iga_path == IGA2)
3118c2ecf20Sopenharmony_ci			viafb_set_secondary_color_register(regno, red >> 8,
3128c2ecf20Sopenharmony_ci				green >> 8, blue >> 8);
3138c2ecf20Sopenharmony_ci	} else {
3148c2ecf20Sopenharmony_ci		if (regno > 15)
3158c2ecf20Sopenharmony_ci			return -EINVAL;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci		r = (red >> (16 - info->var.red.length))
3188c2ecf20Sopenharmony_ci			<< info->var.red.offset;
3198c2ecf20Sopenharmony_ci		b = (blue >> (16 - info->var.blue.length))
3208c2ecf20Sopenharmony_ci			<< info->var.blue.offset;
3218c2ecf20Sopenharmony_ci		g = (green >> (16 - info->var.green.length))
3228c2ecf20Sopenharmony_ci			<< info->var.green.offset;
3238c2ecf20Sopenharmony_ci		((u32 *) info->pseudo_palette)[regno] = r | g | b;
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	return 0;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic int viafb_pan_display(struct fb_var_screeninfo *var,
3308c2ecf20Sopenharmony_ci	struct fb_info *info)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	struct viafb_par *viapar = info->par;
3338c2ecf20Sopenharmony_ci	u32 vram_addr = viapar->vram_addr
3348c2ecf20Sopenharmony_ci		+ var->yoffset * info->fix.line_length
3358c2ecf20Sopenharmony_ci		+ var->xoffset * info->var.bits_per_pixel / 8;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
3388c2ecf20Sopenharmony_ci	if (!viafb_dual_fb) {
3398c2ecf20Sopenharmony_ci		via_set_primary_address(vram_addr);
3408c2ecf20Sopenharmony_ci		via_set_secondary_address(vram_addr);
3418c2ecf20Sopenharmony_ci	} else if (viapar->iga_path == IGA1)
3428c2ecf20Sopenharmony_ci		via_set_primary_address(vram_addr);
3438c2ecf20Sopenharmony_ci	else
3448c2ecf20Sopenharmony_ci		via_set_secondary_address(vram_addr);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	return 0;
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_cistatic int viafb_blank(int blank_mode, struct fb_info *info)
3508c2ecf20Sopenharmony_ci{
3518c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_blank!\n");
3528c2ecf20Sopenharmony_ci	/* clear DPMS setting */
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	switch (blank_mode) {
3558c2ecf20Sopenharmony_ci	case FB_BLANK_UNBLANK:
3568c2ecf20Sopenharmony_ci		/* Screen: On, HSync: On, VSync: On */
3578c2ecf20Sopenharmony_ci		/* control CRT monitor power management */
3588c2ecf20Sopenharmony_ci		via_set_state(VIA_CRT, VIA_STATE_ON);
3598c2ecf20Sopenharmony_ci		break;
3608c2ecf20Sopenharmony_ci	case FB_BLANK_HSYNC_SUSPEND:
3618c2ecf20Sopenharmony_ci		/* Screen: Off, HSync: Off, VSync: On */
3628c2ecf20Sopenharmony_ci		/* control CRT monitor power management */
3638c2ecf20Sopenharmony_ci		via_set_state(VIA_CRT, VIA_STATE_STANDBY);
3648c2ecf20Sopenharmony_ci		break;
3658c2ecf20Sopenharmony_ci	case FB_BLANK_VSYNC_SUSPEND:
3668c2ecf20Sopenharmony_ci		/* Screen: Off, HSync: On, VSync: Off */
3678c2ecf20Sopenharmony_ci		/* control CRT monitor power management */
3688c2ecf20Sopenharmony_ci		via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
3698c2ecf20Sopenharmony_ci		break;
3708c2ecf20Sopenharmony_ci	case FB_BLANK_POWERDOWN:
3718c2ecf20Sopenharmony_ci		/* Screen: Off, HSync: Off, VSync: Off */
3728c2ecf20Sopenharmony_ci		/* control CRT monitor power management */
3738c2ecf20Sopenharmony_ci		via_set_state(VIA_CRT, VIA_STATE_OFF);
3748c2ecf20Sopenharmony_ci		break;
3758c2ecf20Sopenharmony_ci	}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	return 0;
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_cistatic int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	union {
3838c2ecf20Sopenharmony_ci		struct viafb_ioctl_mode viamode;
3848c2ecf20Sopenharmony_ci		struct viafb_ioctl_samm viasamm;
3858c2ecf20Sopenharmony_ci		struct viafb_driver_version driver_version;
3868c2ecf20Sopenharmony_ci		struct fb_var_screeninfo sec_var;
3878c2ecf20Sopenharmony_ci		struct _panel_size_pos_info panel_pos_size_para;
3888c2ecf20Sopenharmony_ci		struct viafb_ioctl_setting viafb_setting;
3898c2ecf20Sopenharmony_ci		struct device_t active_dev;
3908c2ecf20Sopenharmony_ci	} u;
3918c2ecf20Sopenharmony_ci	u32 state_info = 0;
3928c2ecf20Sopenharmony_ci	u32 *viafb_gamma_table;
3938c2ecf20Sopenharmony_ci	char driver_name[] = "viafb";
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	u32 __user *argp = (u32 __user *) arg;
3968c2ecf20Sopenharmony_ci	u32 gpu32;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
3998c2ecf20Sopenharmony_ci	printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n");
4008c2ecf20Sopenharmony_ci	memset(&u, 0, sizeof(u));
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	switch (cmd) {
4038c2ecf20Sopenharmony_ci	case VIAFB_GET_CHIP_INFO:
4048c2ecf20Sopenharmony_ci		if (copy_to_user(argp, viaparinfo->chip_info,
4058c2ecf20Sopenharmony_ci				sizeof(struct chip_information)))
4068c2ecf20Sopenharmony_ci			return -EFAULT;
4078c2ecf20Sopenharmony_ci		break;
4088c2ecf20Sopenharmony_ci	case VIAFB_GET_INFO_SIZE:
4098c2ecf20Sopenharmony_ci		return put_user((u32)sizeof(struct viafb_ioctl_info), argp);
4108c2ecf20Sopenharmony_ci	case VIAFB_GET_INFO:
4118c2ecf20Sopenharmony_ci		return viafb_ioctl_get_viafb_info(arg);
4128c2ecf20Sopenharmony_ci	case VIAFB_HOTPLUG:
4138c2ecf20Sopenharmony_ci		return put_user(viafb_ioctl_hotplug(info->var.xres,
4148c2ecf20Sopenharmony_ci					      info->var.yres,
4158c2ecf20Sopenharmony_ci					      info->var.bits_per_pixel), argp);
4168c2ecf20Sopenharmony_ci	case VIAFB_SET_HOTPLUG_FLAG:
4178c2ecf20Sopenharmony_ci		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
4188c2ecf20Sopenharmony_ci			return -EFAULT;
4198c2ecf20Sopenharmony_ci		viafb_hotplug = (gpu32) ? 1 : 0;
4208c2ecf20Sopenharmony_ci		break;
4218c2ecf20Sopenharmony_ci	case VIAFB_GET_RESOLUTION:
4228c2ecf20Sopenharmony_ci		u.viamode.xres = (u32) viafb_hotplug_Xres;
4238c2ecf20Sopenharmony_ci		u.viamode.yres = (u32) viafb_hotplug_Yres;
4248c2ecf20Sopenharmony_ci		u.viamode.refresh = (u32) viafb_hotplug_refresh;
4258c2ecf20Sopenharmony_ci		u.viamode.bpp = (u32) viafb_hotplug_bpp;
4268c2ecf20Sopenharmony_ci		if (viafb_SAMM_ON == 1) {
4278c2ecf20Sopenharmony_ci			u.viamode.xres_sec = viafb_second_xres;
4288c2ecf20Sopenharmony_ci			u.viamode.yres_sec = viafb_second_yres;
4298c2ecf20Sopenharmony_ci			u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual;
4308c2ecf20Sopenharmony_ci			u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual;
4318c2ecf20Sopenharmony_ci			u.viamode.refresh_sec = viafb_refresh1;
4328c2ecf20Sopenharmony_ci			u.viamode.bpp_sec = viafb_bpp1;
4338c2ecf20Sopenharmony_ci		} else {
4348c2ecf20Sopenharmony_ci			u.viamode.xres_sec = 0;
4358c2ecf20Sopenharmony_ci			u.viamode.yres_sec = 0;
4368c2ecf20Sopenharmony_ci			u.viamode.virtual_xres_sec = 0;
4378c2ecf20Sopenharmony_ci			u.viamode.virtual_yres_sec = 0;
4388c2ecf20Sopenharmony_ci			u.viamode.refresh_sec = 0;
4398c2ecf20Sopenharmony_ci			u.viamode.bpp_sec = 0;
4408c2ecf20Sopenharmony_ci		}
4418c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.viamode, sizeof(u.viamode)))
4428c2ecf20Sopenharmony_ci			return -EFAULT;
4438c2ecf20Sopenharmony_ci		break;
4448c2ecf20Sopenharmony_ci	case VIAFB_GET_SAMM_INFO:
4458c2ecf20Sopenharmony_ci		u.viasamm.samm_status = viafb_SAMM_ON;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci		if (viafb_SAMM_ON == 1) {
4488c2ecf20Sopenharmony_ci			if (viafb_dual_fb) {
4498c2ecf20Sopenharmony_ci				u.viasamm.size_prim = viaparinfo->fbmem_free;
4508c2ecf20Sopenharmony_ci				u.viasamm.size_sec = viaparinfo1->fbmem_free;
4518c2ecf20Sopenharmony_ci			} else {
4528c2ecf20Sopenharmony_ci				if (viafb_second_size) {
4538c2ecf20Sopenharmony_ci					u.viasamm.size_prim =
4548c2ecf20Sopenharmony_ci					    viaparinfo->fbmem_free -
4558c2ecf20Sopenharmony_ci					    viafb_second_size * 1024 * 1024;
4568c2ecf20Sopenharmony_ci					u.viasamm.size_sec =
4578c2ecf20Sopenharmony_ci					    viafb_second_size * 1024 * 1024;
4588c2ecf20Sopenharmony_ci				} else {
4598c2ecf20Sopenharmony_ci					u.viasamm.size_prim =
4608c2ecf20Sopenharmony_ci					    viaparinfo->fbmem_free >> 1;
4618c2ecf20Sopenharmony_ci					u.viasamm.size_sec =
4628c2ecf20Sopenharmony_ci					    (viaparinfo->fbmem_free >> 1);
4638c2ecf20Sopenharmony_ci				}
4648c2ecf20Sopenharmony_ci			}
4658c2ecf20Sopenharmony_ci			u.viasamm.mem_base = viaparinfo->fbmem;
4668c2ecf20Sopenharmony_ci			u.viasamm.offset_sec = viafb_second_offset;
4678c2ecf20Sopenharmony_ci		} else {
4688c2ecf20Sopenharmony_ci			u.viasamm.size_prim =
4698c2ecf20Sopenharmony_ci			    viaparinfo->memsize - viaparinfo->fbmem_used;
4708c2ecf20Sopenharmony_ci			u.viasamm.size_sec = 0;
4718c2ecf20Sopenharmony_ci			u.viasamm.mem_base = viaparinfo->fbmem;
4728c2ecf20Sopenharmony_ci			u.viasamm.offset_sec = 0;
4738c2ecf20Sopenharmony_ci		}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm)))
4768c2ecf20Sopenharmony_ci			return -EFAULT;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci		break;
4798c2ecf20Sopenharmony_ci	case VIAFB_TURN_ON_OUTPUT_DEVICE:
4808c2ecf20Sopenharmony_ci		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
4818c2ecf20Sopenharmony_ci			return -EFAULT;
4828c2ecf20Sopenharmony_ci		if (gpu32 & CRT_Device)
4838c2ecf20Sopenharmony_ci			via_set_state(VIA_CRT, VIA_STATE_ON);
4848c2ecf20Sopenharmony_ci		if (gpu32 & DVI_Device)
4858c2ecf20Sopenharmony_ci			viafb_dvi_enable();
4868c2ecf20Sopenharmony_ci		if (gpu32 & LCD_Device)
4878c2ecf20Sopenharmony_ci			viafb_lcd_enable();
4888c2ecf20Sopenharmony_ci		break;
4898c2ecf20Sopenharmony_ci	case VIAFB_TURN_OFF_OUTPUT_DEVICE:
4908c2ecf20Sopenharmony_ci		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
4918c2ecf20Sopenharmony_ci			return -EFAULT;
4928c2ecf20Sopenharmony_ci		if (gpu32 & CRT_Device)
4938c2ecf20Sopenharmony_ci			via_set_state(VIA_CRT, VIA_STATE_OFF);
4948c2ecf20Sopenharmony_ci		if (gpu32 & DVI_Device)
4958c2ecf20Sopenharmony_ci			viafb_dvi_disable();
4968c2ecf20Sopenharmony_ci		if (gpu32 & LCD_Device)
4978c2ecf20Sopenharmony_ci			viafb_lcd_disable();
4988c2ecf20Sopenharmony_ci		break;
4998c2ecf20Sopenharmony_ci	case VIAFB_GET_DEVICE:
5008c2ecf20Sopenharmony_ci		u.active_dev.crt = viafb_CRT_ON;
5018c2ecf20Sopenharmony_ci		u.active_dev.dvi = viafb_DVI_ON;
5028c2ecf20Sopenharmony_ci		u.active_dev.lcd = viafb_LCD_ON;
5038c2ecf20Sopenharmony_ci		u.active_dev.samm = viafb_SAMM_ON;
5048c2ecf20Sopenharmony_ci		u.active_dev.primary_dev = viafb_primary_dev;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci		u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
5078c2ecf20Sopenharmony_ci		u.active_dev.lcd_panel_id = viafb_lcd_panel_id;
5088c2ecf20Sopenharmony_ci		u.active_dev.lcd_mode = viafb_lcd_mode;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci		u.active_dev.xres = viafb_hotplug_Xres;
5118c2ecf20Sopenharmony_ci		u.active_dev.yres = viafb_hotplug_Yres;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci		u.active_dev.xres1 = viafb_second_xres;
5148c2ecf20Sopenharmony_ci		u.active_dev.yres1 = viafb_second_yres;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci		u.active_dev.bpp = viafb_bpp;
5178c2ecf20Sopenharmony_ci		u.active_dev.bpp1 = viafb_bpp1;
5188c2ecf20Sopenharmony_ci		u.active_dev.refresh = viafb_refresh;
5198c2ecf20Sopenharmony_ci		u.active_dev.refresh1 = viafb_refresh1;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci		u.active_dev.epia_dvi = viafb_platform_epia_dvi;
5228c2ecf20Sopenharmony_ci		u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
5238c2ecf20Sopenharmony_ci		u.active_dev.bus_width = viafb_bus_width;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev)))
5268c2ecf20Sopenharmony_ci			return -EFAULT;
5278c2ecf20Sopenharmony_ci		break;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	case VIAFB_GET_DRIVER_VERSION:
5308c2ecf20Sopenharmony_ci		u.driver_version.iMajorNum = VERSION_MAJOR;
5318c2ecf20Sopenharmony_ci		u.driver_version.iKernelNum = VERSION_KERNEL;
5328c2ecf20Sopenharmony_ci		u.driver_version.iOSNum = VERSION_OS;
5338c2ecf20Sopenharmony_ci		u.driver_version.iMinorNum = VERSION_MINOR;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.driver_version,
5368c2ecf20Sopenharmony_ci			sizeof(u.driver_version)))
5378c2ecf20Sopenharmony_ci			return -EFAULT;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci		break;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	case VIAFB_GET_DEVICE_INFO:
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci		retrieve_device_setting(&u.viafb_setting);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.viafb_setting,
5468c2ecf20Sopenharmony_ci				 sizeof(u.viafb_setting)))
5478c2ecf20Sopenharmony_ci			return -EFAULT;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci		break;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	case VIAFB_GET_DEVICE_SUPPORT:
5528c2ecf20Sopenharmony_ci		viafb_get_device_support_state(&state_info);
5538c2ecf20Sopenharmony_ci		if (put_user(state_info, argp))
5548c2ecf20Sopenharmony_ci			return -EFAULT;
5558c2ecf20Sopenharmony_ci		break;
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	case VIAFB_GET_DEVICE_CONNECT:
5588c2ecf20Sopenharmony_ci		viafb_get_device_connect_state(&state_info);
5598c2ecf20Sopenharmony_ci		if (put_user(state_info, argp))
5608c2ecf20Sopenharmony_ci			return -EFAULT;
5618c2ecf20Sopenharmony_ci		break;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	case VIAFB_GET_PANEL_SUPPORT_EXPAND:
5648c2ecf20Sopenharmony_ci		state_info =
5658c2ecf20Sopenharmony_ci		    viafb_lcd_get_support_expand_state(info->var.xres,
5668c2ecf20Sopenharmony_ci						 info->var.yres);
5678c2ecf20Sopenharmony_ci		if (put_user(state_info, argp))
5688c2ecf20Sopenharmony_ci			return -EFAULT;
5698c2ecf20Sopenharmony_ci		break;
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	case VIAFB_GET_DRIVER_NAME:
5728c2ecf20Sopenharmony_ci		if (copy_to_user(argp, driver_name, sizeof(driver_name)))
5738c2ecf20Sopenharmony_ci			return -EFAULT;
5748c2ecf20Sopenharmony_ci		break;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	case VIAFB_SET_GAMMA_LUT:
5778c2ecf20Sopenharmony_ci		viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32));
5788c2ecf20Sopenharmony_ci		if (IS_ERR(viafb_gamma_table))
5798c2ecf20Sopenharmony_ci			return PTR_ERR(viafb_gamma_table);
5808c2ecf20Sopenharmony_ci		viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
5818c2ecf20Sopenharmony_ci		kfree(viafb_gamma_table);
5828c2ecf20Sopenharmony_ci		break;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	case VIAFB_GET_GAMMA_LUT:
5858c2ecf20Sopenharmony_ci		viafb_gamma_table = kmalloc_array(256, sizeof(u32),
5868c2ecf20Sopenharmony_ci						  GFP_KERNEL);
5878c2ecf20Sopenharmony_ci		if (!viafb_gamma_table)
5888c2ecf20Sopenharmony_ci			return -ENOMEM;
5898c2ecf20Sopenharmony_ci		viafb_get_gamma_table(viafb_gamma_table);
5908c2ecf20Sopenharmony_ci		if (copy_to_user(argp, viafb_gamma_table,
5918c2ecf20Sopenharmony_ci			256 * sizeof(u32))) {
5928c2ecf20Sopenharmony_ci			kfree(viafb_gamma_table);
5938c2ecf20Sopenharmony_ci			return -EFAULT;
5948c2ecf20Sopenharmony_ci		}
5958c2ecf20Sopenharmony_ci		kfree(viafb_gamma_table);
5968c2ecf20Sopenharmony_ci		break;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	case VIAFB_GET_GAMMA_SUPPORT_STATE:
5998c2ecf20Sopenharmony_ci		viafb_get_gamma_support_state(viafb_bpp, &state_info);
6008c2ecf20Sopenharmony_ci		if (put_user(state_info, argp))
6018c2ecf20Sopenharmony_ci			return -EFAULT;
6028c2ecf20Sopenharmony_ci		break;
6038c2ecf20Sopenharmony_ci	case VIAFB_SYNC_SURFACE:
6048c2ecf20Sopenharmony_ci		DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
6058c2ecf20Sopenharmony_ci		break;
6068c2ecf20Sopenharmony_ci	case VIAFB_GET_DRIVER_CAPS:
6078c2ecf20Sopenharmony_ci		break;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	case VIAFB_GET_PANEL_MAX_SIZE:
6108c2ecf20Sopenharmony_ci		if (copy_from_user(&u.panel_pos_size_para, argp,
6118c2ecf20Sopenharmony_ci				   sizeof(u.panel_pos_size_para)))
6128c2ecf20Sopenharmony_ci			return -EFAULT;
6138c2ecf20Sopenharmony_ci		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
6148c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.panel_pos_size_para,
6158c2ecf20Sopenharmony_ci		     sizeof(u.panel_pos_size_para)))
6168c2ecf20Sopenharmony_ci			return -EFAULT;
6178c2ecf20Sopenharmony_ci		break;
6188c2ecf20Sopenharmony_ci	case VIAFB_GET_PANEL_MAX_POSITION:
6198c2ecf20Sopenharmony_ci		if (copy_from_user(&u.panel_pos_size_para, argp,
6208c2ecf20Sopenharmony_ci				   sizeof(u.panel_pos_size_para)))
6218c2ecf20Sopenharmony_ci			return -EFAULT;
6228c2ecf20Sopenharmony_ci		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
6238c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.panel_pos_size_para,
6248c2ecf20Sopenharmony_ci				 sizeof(u.panel_pos_size_para)))
6258c2ecf20Sopenharmony_ci			return -EFAULT;
6268c2ecf20Sopenharmony_ci		break;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	case VIAFB_GET_PANEL_POSITION:
6298c2ecf20Sopenharmony_ci		if (copy_from_user(&u.panel_pos_size_para, argp,
6308c2ecf20Sopenharmony_ci				   sizeof(u.panel_pos_size_para)))
6318c2ecf20Sopenharmony_ci			return -EFAULT;
6328c2ecf20Sopenharmony_ci		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
6338c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.panel_pos_size_para,
6348c2ecf20Sopenharmony_ci				 sizeof(u.panel_pos_size_para)))
6358c2ecf20Sopenharmony_ci			return -EFAULT;
6368c2ecf20Sopenharmony_ci		break;
6378c2ecf20Sopenharmony_ci	case VIAFB_GET_PANEL_SIZE:
6388c2ecf20Sopenharmony_ci		if (copy_from_user(&u.panel_pos_size_para, argp,
6398c2ecf20Sopenharmony_ci				   sizeof(u.panel_pos_size_para)))
6408c2ecf20Sopenharmony_ci			return -EFAULT;
6418c2ecf20Sopenharmony_ci		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
6428c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &u.panel_pos_size_para,
6438c2ecf20Sopenharmony_ci				 sizeof(u.panel_pos_size_para)))
6448c2ecf20Sopenharmony_ci			return -EFAULT;
6458c2ecf20Sopenharmony_ci		break;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	case VIAFB_SET_PANEL_POSITION:
6488c2ecf20Sopenharmony_ci		if (copy_from_user(&u.panel_pos_size_para, argp,
6498c2ecf20Sopenharmony_ci				   sizeof(u.panel_pos_size_para)))
6508c2ecf20Sopenharmony_ci			return -EFAULT;
6518c2ecf20Sopenharmony_ci		break;
6528c2ecf20Sopenharmony_ci	case VIAFB_SET_PANEL_SIZE:
6538c2ecf20Sopenharmony_ci		if (copy_from_user(&u.panel_pos_size_para, argp,
6548c2ecf20Sopenharmony_ci				   sizeof(u.panel_pos_size_para)))
6558c2ecf20Sopenharmony_ci			return -EFAULT;
6568c2ecf20Sopenharmony_ci		break;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	default:
6598c2ecf20Sopenharmony_ci		return -EINVAL;
6608c2ecf20Sopenharmony_ci	}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	return 0;
6638c2ecf20Sopenharmony_ci}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_cistatic void viafb_fillrect(struct fb_info *info,
6668c2ecf20Sopenharmony_ci	const struct fb_fillrect *rect)
6678c2ecf20Sopenharmony_ci{
6688c2ecf20Sopenharmony_ci	struct viafb_par *viapar = info->par;
6698c2ecf20Sopenharmony_ci	struct viafb_shared *shared = viapar->shared;
6708c2ecf20Sopenharmony_ci	u32 fg_color;
6718c2ecf20Sopenharmony_ci	u8 rop;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
6748c2ecf20Sopenharmony_ci		cfb_fillrect(info, rect);
6758c2ecf20Sopenharmony_ci		return;
6768c2ecf20Sopenharmony_ci	}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	if (!rect->width || !rect->height)
6798c2ecf20Sopenharmony_ci		return;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	if (info->fix.visual == FB_VISUAL_TRUECOLOR)
6828c2ecf20Sopenharmony_ci		fg_color = ((u32 *)info->pseudo_palette)[rect->color];
6838c2ecf20Sopenharmony_ci	else
6848c2ecf20Sopenharmony_ci		fg_color = rect->color;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	if (rect->rop == ROP_XOR)
6878c2ecf20Sopenharmony_ci		rop = 0x5A;
6888c2ecf20Sopenharmony_ci	else
6898c2ecf20Sopenharmony_ci		rop = 0xF0;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
6928c2ecf20Sopenharmony_ci	if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL,
6938c2ecf20Sopenharmony_ci		rect->width, rect->height, info->var.bits_per_pixel,
6948c2ecf20Sopenharmony_ci		viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
6958c2ecf20Sopenharmony_ci		NULL, 0, 0, 0, 0, fg_color, 0, rop))
6968c2ecf20Sopenharmony_ci		cfb_fillrect(info, rect);
6978c2ecf20Sopenharmony_ci}
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_cistatic void viafb_copyarea(struct fb_info *info,
7008c2ecf20Sopenharmony_ci	const struct fb_copyarea *area)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	struct viafb_par *viapar = info->par;
7038c2ecf20Sopenharmony_ci	struct viafb_shared *shared = viapar->shared;
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
7068c2ecf20Sopenharmony_ci		cfb_copyarea(info, area);
7078c2ecf20Sopenharmony_ci		return;
7088c2ecf20Sopenharmony_ci	}
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	if (!area->width || !area->height)
7118c2ecf20Sopenharmony_ci		return;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n");
7148c2ecf20Sopenharmony_ci	if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR,
7158c2ecf20Sopenharmony_ci		area->width, area->height, info->var.bits_per_pixel,
7168c2ecf20Sopenharmony_ci		viapar->vram_addr, info->fix.line_length, area->dx, area->dy,
7178c2ecf20Sopenharmony_ci		NULL, viapar->vram_addr, info->fix.line_length,
7188c2ecf20Sopenharmony_ci		area->sx, area->sy, 0, 0, 0))
7198c2ecf20Sopenharmony_ci		cfb_copyarea(info, area);
7208c2ecf20Sopenharmony_ci}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_cistatic void viafb_imageblit(struct fb_info *info,
7238c2ecf20Sopenharmony_ci	const struct fb_image *image)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci	struct viafb_par *viapar = info->par;
7268c2ecf20Sopenharmony_ci	struct viafb_shared *shared = viapar->shared;
7278c2ecf20Sopenharmony_ci	u32 fg_color = 0, bg_color = 0;
7288c2ecf20Sopenharmony_ci	u8 op;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt ||
7318c2ecf20Sopenharmony_ci		(image->depth != 1 && image->depth != viapar->depth)) {
7328c2ecf20Sopenharmony_ci		cfb_imageblit(info, image);
7338c2ecf20Sopenharmony_ci		return;
7348c2ecf20Sopenharmony_ci	}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	if (image->depth == 1) {
7378c2ecf20Sopenharmony_ci		op = VIA_BITBLT_MONO;
7388c2ecf20Sopenharmony_ci		if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
7398c2ecf20Sopenharmony_ci			fg_color =
7408c2ecf20Sopenharmony_ci				((u32 *)info->pseudo_palette)[image->fg_color];
7418c2ecf20Sopenharmony_ci			bg_color =
7428c2ecf20Sopenharmony_ci				((u32 *)info->pseudo_palette)[image->bg_color];
7438c2ecf20Sopenharmony_ci		} else {
7448c2ecf20Sopenharmony_ci			fg_color = image->fg_color;
7458c2ecf20Sopenharmony_ci			bg_color = image->bg_color;
7468c2ecf20Sopenharmony_ci		}
7478c2ecf20Sopenharmony_ci	} else
7488c2ecf20Sopenharmony_ci		op = VIA_BITBLT_COLOR;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n");
7518c2ecf20Sopenharmony_ci	if (shared->hw_bitblt(shared->vdev->engine_mmio, op,
7528c2ecf20Sopenharmony_ci		image->width, image->height, info->var.bits_per_pixel,
7538c2ecf20Sopenharmony_ci		viapar->vram_addr, info->fix.line_length, image->dx, image->dy,
7548c2ecf20Sopenharmony_ci		(u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0))
7558c2ecf20Sopenharmony_ci		cfb_imageblit(info, image);
7568c2ecf20Sopenharmony_ci}
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_cistatic int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
7598c2ecf20Sopenharmony_ci{
7608c2ecf20Sopenharmony_ci	struct viafb_par *viapar = info->par;
7618c2ecf20Sopenharmony_ci	void __iomem *engine = viapar->shared->vdev->engine_mmio;
7628c2ecf20Sopenharmony_ci	u32 temp, xx, yy, bg_color = 0, fg_color = 0,
7638c2ecf20Sopenharmony_ci		chip_name = viapar->shared->chip_info.gfx_chip_name;
7648c2ecf20Sopenharmony_ci	int i, j = 0, cur_size = 64;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo)
7678c2ecf20Sopenharmony_ci		return -ENODEV;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	/* LCD ouput does not support hw cursors (at least on VN896) */
7708c2ecf20Sopenharmony_ci	if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) ||
7718c2ecf20Sopenharmony_ci		viafb_LCD_ON)
7728c2ecf20Sopenharmony_ci		return -ENODEV;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	viafb_show_hw_cursor(info, HW_Cursor_OFF);
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	if (cursor->set & FB_CUR_SETHOT) {
7778c2ecf20Sopenharmony_ci		temp = (cursor->hot.x << 16) + cursor->hot.y;
7788c2ecf20Sopenharmony_ci		writel(temp, engine + VIA_REG_CURSOR_ORG);
7798c2ecf20Sopenharmony_ci	}
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	if (cursor->set & FB_CUR_SETPOS) {
7828c2ecf20Sopenharmony_ci		yy = cursor->image.dy - info->var.yoffset;
7838c2ecf20Sopenharmony_ci		xx = cursor->image.dx - info->var.xoffset;
7848c2ecf20Sopenharmony_ci		temp = yy & 0xFFFF;
7858c2ecf20Sopenharmony_ci		temp |= (xx << 16);
7868c2ecf20Sopenharmony_ci		writel(temp, engine + VIA_REG_CURSOR_POS);
7878c2ecf20Sopenharmony_ci	}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	if (cursor->image.width <= 32 && cursor->image.height <= 32)
7908c2ecf20Sopenharmony_ci		cur_size = 32;
7918c2ecf20Sopenharmony_ci	else if (cursor->image.width <= 64 && cursor->image.height <= 64)
7928c2ecf20Sopenharmony_ci		cur_size = 64;
7938c2ecf20Sopenharmony_ci	else {
7948c2ecf20Sopenharmony_ci		printk(KERN_WARNING "viafb_cursor: The cursor is too large "
7958c2ecf20Sopenharmony_ci			"%dx%d", cursor->image.width, cursor->image.height);
7968c2ecf20Sopenharmony_ci		return -ENXIO;
7978c2ecf20Sopenharmony_ci	}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	if (cursor->set & FB_CUR_SETSIZE) {
8008c2ecf20Sopenharmony_ci		temp = readl(engine + VIA_REG_CURSOR_MODE);
8018c2ecf20Sopenharmony_ci		if (cur_size == 32)
8028c2ecf20Sopenharmony_ci			temp |= 0x2;
8038c2ecf20Sopenharmony_ci		else
8048c2ecf20Sopenharmony_ci			temp &= ~0x2;
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci		writel(temp, engine + VIA_REG_CURSOR_MODE);
8078c2ecf20Sopenharmony_ci	}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	if (cursor->set & FB_CUR_SETCMAP) {
8108c2ecf20Sopenharmony_ci		fg_color = cursor->image.fg_color;
8118c2ecf20Sopenharmony_ci		bg_color = cursor->image.bg_color;
8128c2ecf20Sopenharmony_ci		if (chip_name == UNICHROME_CX700 ||
8138c2ecf20Sopenharmony_ci			chip_name == UNICHROME_VX800 ||
8148c2ecf20Sopenharmony_ci			chip_name == UNICHROME_VX855 ||
8158c2ecf20Sopenharmony_ci			chip_name == UNICHROME_VX900) {
8168c2ecf20Sopenharmony_ci			fg_color =
8178c2ecf20Sopenharmony_ci				((info->cmap.red[fg_color] & 0xFFC0) << 14) |
8188c2ecf20Sopenharmony_ci				((info->cmap.green[fg_color] & 0xFFC0) << 4) |
8198c2ecf20Sopenharmony_ci				((info->cmap.blue[fg_color] & 0xFFC0) >> 6);
8208c2ecf20Sopenharmony_ci			bg_color =
8218c2ecf20Sopenharmony_ci				((info->cmap.red[bg_color] & 0xFFC0) << 14) |
8228c2ecf20Sopenharmony_ci				((info->cmap.green[bg_color] & 0xFFC0) << 4) |
8238c2ecf20Sopenharmony_ci				((info->cmap.blue[bg_color] & 0xFFC0) >> 6);
8248c2ecf20Sopenharmony_ci		} else {
8258c2ecf20Sopenharmony_ci			fg_color =
8268c2ecf20Sopenharmony_ci				((info->cmap.red[fg_color] & 0xFF00) << 8) |
8278c2ecf20Sopenharmony_ci				(info->cmap.green[fg_color] & 0xFF00) |
8288c2ecf20Sopenharmony_ci				((info->cmap.blue[fg_color] & 0xFF00) >> 8);
8298c2ecf20Sopenharmony_ci			bg_color =
8308c2ecf20Sopenharmony_ci				((info->cmap.red[bg_color] & 0xFF00) << 8) |
8318c2ecf20Sopenharmony_ci				(info->cmap.green[bg_color] & 0xFF00) |
8328c2ecf20Sopenharmony_ci				((info->cmap.blue[bg_color] & 0xFF00) >> 8);
8338c2ecf20Sopenharmony_ci		}
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci		writel(bg_color, engine + VIA_REG_CURSOR_BG);
8368c2ecf20Sopenharmony_ci		writel(fg_color, engine + VIA_REG_CURSOR_FG);
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	if (cursor->set & FB_CUR_SETSHAPE) {
8408c2ecf20Sopenharmony_ci		struct {
8418c2ecf20Sopenharmony_ci			u8 data[CURSOR_SIZE];
8428c2ecf20Sopenharmony_ci			u32 bak[CURSOR_SIZE / 4];
8438c2ecf20Sopenharmony_ci		} *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC);
8448c2ecf20Sopenharmony_ci		int size = ((cursor->image.width + 7) >> 3) *
8458c2ecf20Sopenharmony_ci			cursor->image.height;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci		if (!cr_data)
8488c2ecf20Sopenharmony_ci			return -ENOMEM;
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci		if (cur_size == 32) {
8518c2ecf20Sopenharmony_ci			for (i = 0; i < (CURSOR_SIZE / 4); i++) {
8528c2ecf20Sopenharmony_ci				cr_data->bak[i] = 0x0;
8538c2ecf20Sopenharmony_ci				cr_data->bak[i + 1] = 0xFFFFFFFF;
8548c2ecf20Sopenharmony_ci				i += 1;
8558c2ecf20Sopenharmony_ci			}
8568c2ecf20Sopenharmony_ci		} else {
8578c2ecf20Sopenharmony_ci			for (i = 0; i < (CURSOR_SIZE / 4); i++) {
8588c2ecf20Sopenharmony_ci				cr_data->bak[i] = 0x0;
8598c2ecf20Sopenharmony_ci				cr_data->bak[i + 1] = 0x0;
8608c2ecf20Sopenharmony_ci				cr_data->bak[i + 2] = 0xFFFFFFFF;
8618c2ecf20Sopenharmony_ci				cr_data->bak[i + 3] = 0xFFFFFFFF;
8628c2ecf20Sopenharmony_ci				i += 3;
8638c2ecf20Sopenharmony_ci			}
8648c2ecf20Sopenharmony_ci		}
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci		switch (cursor->rop) {
8678c2ecf20Sopenharmony_ci		case ROP_XOR:
8688c2ecf20Sopenharmony_ci			for (i = 0; i < size; i++)
8698c2ecf20Sopenharmony_ci				cr_data->data[i] = cursor->mask[i];
8708c2ecf20Sopenharmony_ci			break;
8718c2ecf20Sopenharmony_ci		case ROP_COPY:
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci			for (i = 0; i < size; i++)
8748c2ecf20Sopenharmony_ci				cr_data->data[i] = cursor->mask[i];
8758c2ecf20Sopenharmony_ci			break;
8768c2ecf20Sopenharmony_ci		default:
8778c2ecf20Sopenharmony_ci			break;
8788c2ecf20Sopenharmony_ci		}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci		if (cur_size == 32) {
8818c2ecf20Sopenharmony_ci			for (i = 0; i < size; i++) {
8828c2ecf20Sopenharmony_ci				cr_data->bak[j] = (u32) cr_data->data[i];
8838c2ecf20Sopenharmony_ci				cr_data->bak[j + 1] = ~cr_data->bak[j];
8848c2ecf20Sopenharmony_ci				j += 2;
8858c2ecf20Sopenharmony_ci			}
8868c2ecf20Sopenharmony_ci		} else {
8878c2ecf20Sopenharmony_ci			for (i = 0; i < size; i++) {
8888c2ecf20Sopenharmony_ci				cr_data->bak[j] = (u32) cr_data->data[i];
8898c2ecf20Sopenharmony_ci				cr_data->bak[j + 1] = 0x0;
8908c2ecf20Sopenharmony_ci				cr_data->bak[j + 2] = ~cr_data->bak[j];
8918c2ecf20Sopenharmony_ci				cr_data->bak[j + 3] = ~cr_data->bak[j + 1];
8928c2ecf20Sopenharmony_ci				j += 4;
8938c2ecf20Sopenharmony_ci			}
8948c2ecf20Sopenharmony_ci		}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci		memcpy_toio(viafbinfo->screen_base + viapar->shared->
8978c2ecf20Sopenharmony_ci			cursor_vram_addr, cr_data->bak, CURSOR_SIZE);
8988c2ecf20Sopenharmony_ci		kfree(cr_data);
8998c2ecf20Sopenharmony_ci	}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	if (cursor->enable)
9028c2ecf20Sopenharmony_ci		viafb_show_hw_cursor(info, HW_Cursor_ON);
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci	return 0;
9058c2ecf20Sopenharmony_ci}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_cistatic int viafb_sync(struct fb_info *info)
9088c2ecf20Sopenharmony_ci{
9098c2ecf20Sopenharmony_ci	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
9108c2ecf20Sopenharmony_ci		viafb_wait_engine_idle(info);
9118c2ecf20Sopenharmony_ci	return 0;
9128c2ecf20Sopenharmony_ci}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_cistatic int get_primary_device(void)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci	int primary_device = 0;
9178c2ecf20Sopenharmony_ci	/* Rule: device on iga1 path are the primary device. */
9188c2ecf20Sopenharmony_ci	if (viafb_SAMM_ON) {
9198c2ecf20Sopenharmony_ci		if (viafb_CRT_ON) {
9208c2ecf20Sopenharmony_ci			if (viaparinfo->shared->iga1_devices & VIA_CRT) {
9218c2ecf20Sopenharmony_ci				DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", IGA1);
9228c2ecf20Sopenharmony_ci				primary_device = CRT_Device;
9238c2ecf20Sopenharmony_ci			}
9248c2ecf20Sopenharmony_ci		}
9258c2ecf20Sopenharmony_ci		if (viafb_DVI_ON) {
9268c2ecf20Sopenharmony_ci			if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
9278c2ecf20Sopenharmony_ci				DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
9288c2ecf20Sopenharmony_ci					viaparinfo->
9298c2ecf20Sopenharmony_ci					tmds_setting_info->iga_path);
9308c2ecf20Sopenharmony_ci				primary_device = DVI_Device;
9318c2ecf20Sopenharmony_ci			}
9328c2ecf20Sopenharmony_ci		}
9338c2ecf20Sopenharmony_ci		if (viafb_LCD_ON) {
9348c2ecf20Sopenharmony_ci			if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
9358c2ecf20Sopenharmony_ci				DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
9368c2ecf20Sopenharmony_ci					viaparinfo->
9378c2ecf20Sopenharmony_ci					lvds_setting_info->iga_path);
9388c2ecf20Sopenharmony_ci				primary_device = LCD_Device;
9398c2ecf20Sopenharmony_ci			}
9408c2ecf20Sopenharmony_ci		}
9418c2ecf20Sopenharmony_ci		if (viafb_LCD2_ON) {
9428c2ecf20Sopenharmony_ci			if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
9438c2ecf20Sopenharmony_ci				DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
9448c2ecf20Sopenharmony_ci					viaparinfo->
9458c2ecf20Sopenharmony_ci					lvds_setting_info2->iga_path);
9468c2ecf20Sopenharmony_ci				primary_device = LCD2_Device;
9478c2ecf20Sopenharmony_ci			}
9488c2ecf20Sopenharmony_ci		}
9498c2ecf20Sopenharmony_ci	}
9508c2ecf20Sopenharmony_ci	return primary_device;
9518c2ecf20Sopenharmony_ci}
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_cistatic void retrieve_device_setting(struct viafb_ioctl_setting
9548c2ecf20Sopenharmony_ci	*setting_info)
9558c2ecf20Sopenharmony_ci{
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	/* get device status */
9588c2ecf20Sopenharmony_ci	if (viafb_CRT_ON == 1)
9598c2ecf20Sopenharmony_ci		setting_info->device_status = CRT_Device;
9608c2ecf20Sopenharmony_ci	if (viafb_DVI_ON == 1)
9618c2ecf20Sopenharmony_ci		setting_info->device_status |= DVI_Device;
9628c2ecf20Sopenharmony_ci	if (viafb_LCD_ON == 1)
9638c2ecf20Sopenharmony_ci		setting_info->device_status |= LCD_Device;
9648c2ecf20Sopenharmony_ci	if (viafb_LCD2_ON == 1)
9658c2ecf20Sopenharmony_ci		setting_info->device_status |= LCD2_Device;
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	setting_info->samm_status = viafb_SAMM_ON;
9688c2ecf20Sopenharmony_ci	setting_info->primary_device = get_primary_device();
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	setting_info->first_dev_bpp = viafb_bpp;
9718c2ecf20Sopenharmony_ci	setting_info->second_dev_bpp = viafb_bpp1;
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	setting_info->first_dev_refresh = viafb_refresh;
9748c2ecf20Sopenharmony_ci	setting_info->second_dev_refresh = viafb_refresh1;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	setting_info->first_dev_hor_res = viafb_hotplug_Xres;
9778c2ecf20Sopenharmony_ci	setting_info->first_dev_ver_res = viafb_hotplug_Yres;
9788c2ecf20Sopenharmony_ci	setting_info->second_dev_hor_res = viafb_second_xres;
9798c2ecf20Sopenharmony_ci	setting_info->second_dev_ver_res = viafb_second_yres;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	/* Get lcd attributes */
9828c2ecf20Sopenharmony_ci	setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
9838c2ecf20Sopenharmony_ci	setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
9848c2ecf20Sopenharmony_ci	setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
9858c2ecf20Sopenharmony_ci}
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_cistatic int __init parse_active_dev(void)
9888c2ecf20Sopenharmony_ci{
9898c2ecf20Sopenharmony_ci	viafb_CRT_ON = STATE_OFF;
9908c2ecf20Sopenharmony_ci	viafb_DVI_ON = STATE_OFF;
9918c2ecf20Sopenharmony_ci	viafb_LCD_ON = STATE_OFF;
9928c2ecf20Sopenharmony_ci	viafb_LCD2_ON = STATE_OFF;
9938c2ecf20Sopenharmony_ci	/* 1. Modify the active status of devices. */
9948c2ecf20Sopenharmony_ci	/* 2. Keep the order of devices, so we can set corresponding
9958c2ecf20Sopenharmony_ci	   IGA path to devices in SAMM case. */
9968c2ecf20Sopenharmony_ci	/*    Note: The previous of active_dev is primary device,
9978c2ecf20Sopenharmony_ci	   and the following is secondary device. */
9988c2ecf20Sopenharmony_ci	if (!viafb_active_dev) {
9998c2ecf20Sopenharmony_ci		if (machine_is_olpc()) { /* LCD only */
10008c2ecf20Sopenharmony_ci			viafb_LCD_ON = STATE_ON;
10018c2ecf20Sopenharmony_ci			viafb_SAMM_ON = STATE_OFF;
10028c2ecf20Sopenharmony_ci		} else {
10038c2ecf20Sopenharmony_ci			viafb_CRT_ON = STATE_ON;
10048c2ecf20Sopenharmony_ci			viafb_SAMM_ON = STATE_OFF;
10058c2ecf20Sopenharmony_ci		}
10068c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
10078c2ecf20Sopenharmony_ci		/* CRT+DVI */
10088c2ecf20Sopenharmony_ci		viafb_CRT_ON = STATE_ON;
10098c2ecf20Sopenharmony_ci		viafb_DVI_ON = STATE_ON;
10108c2ecf20Sopenharmony_ci		viafb_primary_dev = CRT_Device;
10118c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "DVI+CRT")) {
10128c2ecf20Sopenharmony_ci		/* DVI+CRT */
10138c2ecf20Sopenharmony_ci		viafb_CRT_ON = STATE_ON;
10148c2ecf20Sopenharmony_ci		viafb_DVI_ON = STATE_ON;
10158c2ecf20Sopenharmony_ci		viafb_primary_dev = DVI_Device;
10168c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "CRT+LCD")) {
10178c2ecf20Sopenharmony_ci		/* CRT+LCD */
10188c2ecf20Sopenharmony_ci		viafb_CRT_ON = STATE_ON;
10198c2ecf20Sopenharmony_ci		viafb_LCD_ON = STATE_ON;
10208c2ecf20Sopenharmony_ci		viafb_primary_dev = CRT_Device;
10218c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "LCD+CRT")) {
10228c2ecf20Sopenharmony_ci		/* LCD+CRT */
10238c2ecf20Sopenharmony_ci		viafb_CRT_ON = STATE_ON;
10248c2ecf20Sopenharmony_ci		viafb_LCD_ON = STATE_ON;
10258c2ecf20Sopenharmony_ci		viafb_primary_dev = LCD_Device;
10268c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "DVI+LCD")) {
10278c2ecf20Sopenharmony_ci		/* DVI+LCD */
10288c2ecf20Sopenharmony_ci		viafb_DVI_ON = STATE_ON;
10298c2ecf20Sopenharmony_ci		viafb_LCD_ON = STATE_ON;
10308c2ecf20Sopenharmony_ci		viafb_primary_dev = DVI_Device;
10318c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "LCD+DVI")) {
10328c2ecf20Sopenharmony_ci		/* LCD+DVI */
10338c2ecf20Sopenharmony_ci		viafb_DVI_ON = STATE_ON;
10348c2ecf20Sopenharmony_ci		viafb_LCD_ON = STATE_ON;
10358c2ecf20Sopenharmony_ci		viafb_primary_dev = LCD_Device;
10368c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "LCD+LCD2")) {
10378c2ecf20Sopenharmony_ci		viafb_LCD_ON = STATE_ON;
10388c2ecf20Sopenharmony_ci		viafb_LCD2_ON = STATE_ON;
10398c2ecf20Sopenharmony_ci		viafb_primary_dev = LCD_Device;
10408c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "LCD2+LCD")) {
10418c2ecf20Sopenharmony_ci		viafb_LCD_ON = STATE_ON;
10428c2ecf20Sopenharmony_ci		viafb_LCD2_ON = STATE_ON;
10438c2ecf20Sopenharmony_ci		viafb_primary_dev = LCD2_Device;
10448c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "CRT")) {
10458c2ecf20Sopenharmony_ci		/* CRT only */
10468c2ecf20Sopenharmony_ci		viafb_CRT_ON = STATE_ON;
10478c2ecf20Sopenharmony_ci		viafb_SAMM_ON = STATE_OFF;
10488c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "DVI")) {
10498c2ecf20Sopenharmony_ci		/* DVI only */
10508c2ecf20Sopenharmony_ci		viafb_DVI_ON = STATE_ON;
10518c2ecf20Sopenharmony_ci		viafb_SAMM_ON = STATE_OFF;
10528c2ecf20Sopenharmony_ci	} else if (!strcmp(viafb_active_dev, "LCD")) {
10538c2ecf20Sopenharmony_ci		/* LCD only */
10548c2ecf20Sopenharmony_ci		viafb_LCD_ON = STATE_ON;
10558c2ecf20Sopenharmony_ci		viafb_SAMM_ON = STATE_OFF;
10568c2ecf20Sopenharmony_ci	} else
10578c2ecf20Sopenharmony_ci		return -EINVAL;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	return 0;
10608c2ecf20Sopenharmony_ci}
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_cistatic int parse_port(char *opt_str, int *output_interface)
10638c2ecf20Sopenharmony_ci{
10648c2ecf20Sopenharmony_ci	if (!strncmp(opt_str, "DVP0", 4))
10658c2ecf20Sopenharmony_ci		*output_interface = INTERFACE_DVP0;
10668c2ecf20Sopenharmony_ci	else if (!strncmp(opt_str, "DVP1", 4))
10678c2ecf20Sopenharmony_ci		*output_interface = INTERFACE_DVP1;
10688c2ecf20Sopenharmony_ci	else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
10698c2ecf20Sopenharmony_ci		*output_interface = INTERFACE_DFP;
10708c2ecf20Sopenharmony_ci	else if (!strncmp(opt_str, "DFP_HIGH", 8))
10718c2ecf20Sopenharmony_ci		*output_interface = INTERFACE_DFP_HIGH;
10728c2ecf20Sopenharmony_ci	else if (!strncmp(opt_str, "DFP_LOW", 7))
10738c2ecf20Sopenharmony_ci		*output_interface = INTERFACE_DFP_LOW;
10748c2ecf20Sopenharmony_ci	else
10758c2ecf20Sopenharmony_ci		*output_interface = INTERFACE_NONE;
10768c2ecf20Sopenharmony_ci	return 0;
10778c2ecf20Sopenharmony_ci}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_cistatic void parse_lcd_port(void)
10808c2ecf20Sopenharmony_ci{
10818c2ecf20Sopenharmony_ci	parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
10828c2ecf20Sopenharmony_ci		output_interface);
10838c2ecf20Sopenharmony_ci	/*Initialize to avoid unexpected behavior */
10848c2ecf20Sopenharmony_ci	viaparinfo->chip_info->lvds_chip_info2.output_interface =
10858c2ecf20Sopenharmony_ci	INTERFACE_NONE;
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
10888c2ecf20Sopenharmony_ci		  viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
10898c2ecf20Sopenharmony_ci		  output_interface);
10908c2ecf20Sopenharmony_ci}
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_cistatic void parse_dvi_port(void)
10938c2ecf20Sopenharmony_ci{
10948c2ecf20Sopenharmony_ci	parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
10958c2ecf20Sopenharmony_ci		output_interface);
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
10988c2ecf20Sopenharmony_ci		  viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
10998c2ecf20Sopenharmony_ci		  output_interface);
11008c2ecf20Sopenharmony_ci}
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci/*
11058c2ecf20Sopenharmony_ci * The proc filesystem read/write function, a simple proc implement to
11068c2ecf20Sopenharmony_ci * get/set the value of DPA  DVP0,   DVP0DataDriving,  DVP0ClockDriving, DVP1,
11078c2ecf20Sopenharmony_ci * DVP1Driving, DFPHigh, DFPLow CR96,   SR2A[5], SR1B[1], SR2A[4], SR1E[2],
11088c2ecf20Sopenharmony_ci * CR9B,    SR65,    CR97,    CR99
11098c2ecf20Sopenharmony_ci */
11108c2ecf20Sopenharmony_cistatic int viafb_dvp0_proc_show(struct seq_file *m, void *v)
11118c2ecf20Sopenharmony_ci{
11128c2ecf20Sopenharmony_ci	u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
11138c2ecf20Sopenharmony_ci	dvp0_data_dri =
11148c2ecf20Sopenharmony_ci	    (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
11158c2ecf20Sopenharmony_ci	    (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
11168c2ecf20Sopenharmony_ci	dvp0_clk_dri =
11178c2ecf20Sopenharmony_ci	    (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
11188c2ecf20Sopenharmony_ci	    (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
11198c2ecf20Sopenharmony_ci	dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
11208c2ecf20Sopenharmony_ci	seq_printf(m, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
11218c2ecf20Sopenharmony_ci	return 0;
11228c2ecf20Sopenharmony_ci}
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_cistatic int viafb_dvp0_proc_open(struct inode *inode, struct file *file)
11258c2ecf20Sopenharmony_ci{
11268c2ecf20Sopenharmony_ci	return single_open(file, viafb_dvp0_proc_show, NULL);
11278c2ecf20Sopenharmony_ci}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_cistatic ssize_t viafb_dvp0_proc_write(struct file *file,
11308c2ecf20Sopenharmony_ci	const char __user *buffer, size_t count, loff_t *pos)
11318c2ecf20Sopenharmony_ci{
11328c2ecf20Sopenharmony_ci	char buf[20], *value, *pbuf;
11338c2ecf20Sopenharmony_ci	u8 reg_val = 0;
11348c2ecf20Sopenharmony_ci	unsigned long length, i;
11358c2ecf20Sopenharmony_ci	if (count < 1)
11368c2ecf20Sopenharmony_ci		return -EINVAL;
11378c2ecf20Sopenharmony_ci	length = count > 20 ? 20 : count;
11388c2ecf20Sopenharmony_ci	if (copy_from_user(&buf[0], buffer, length))
11398c2ecf20Sopenharmony_ci		return -EFAULT;
11408c2ecf20Sopenharmony_ci	buf[length - 1] = '\0';	/*Ensure end string */
11418c2ecf20Sopenharmony_ci	pbuf = &buf[0];
11428c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++) {
11438c2ecf20Sopenharmony_ci		value = strsep(&pbuf, " ");
11448c2ecf20Sopenharmony_ci		if (value != NULL) {
11458c2ecf20Sopenharmony_ci			if (kstrtou8(value, 0, &reg_val) < 0)
11468c2ecf20Sopenharmony_ci				return -EINVAL;
11478c2ecf20Sopenharmony_ci			DEBUG_MSG(KERN_INFO "DVP0:reg_val[%lu]=:%x\n", i,
11488c2ecf20Sopenharmony_ci				  reg_val);
11498c2ecf20Sopenharmony_ci			switch (i) {
11508c2ecf20Sopenharmony_ci			case 0:
11518c2ecf20Sopenharmony_ci				viafb_write_reg_mask(CR96, VIACR,
11528c2ecf20Sopenharmony_ci					reg_val, 0x0f);
11538c2ecf20Sopenharmony_ci				break;
11548c2ecf20Sopenharmony_ci			case 1:
11558c2ecf20Sopenharmony_ci				viafb_write_reg_mask(SR2A, VIASR,
11568c2ecf20Sopenharmony_ci					reg_val << 4, BIT5);
11578c2ecf20Sopenharmony_ci				viafb_write_reg_mask(SR1B, VIASR,
11588c2ecf20Sopenharmony_ci					reg_val << 1, BIT1);
11598c2ecf20Sopenharmony_ci				break;
11608c2ecf20Sopenharmony_ci			case 2:
11618c2ecf20Sopenharmony_ci				viafb_write_reg_mask(SR2A, VIASR,
11628c2ecf20Sopenharmony_ci					reg_val << 3, BIT4);
11638c2ecf20Sopenharmony_ci				viafb_write_reg_mask(SR1E, VIASR,
11648c2ecf20Sopenharmony_ci					reg_val << 2, BIT2);
11658c2ecf20Sopenharmony_ci				break;
11668c2ecf20Sopenharmony_ci			default:
11678c2ecf20Sopenharmony_ci				break;
11688c2ecf20Sopenharmony_ci			}
11698c2ecf20Sopenharmony_ci		} else {
11708c2ecf20Sopenharmony_ci			break;
11718c2ecf20Sopenharmony_ci		}
11728c2ecf20Sopenharmony_ci	}
11738c2ecf20Sopenharmony_ci	return count;
11748c2ecf20Sopenharmony_ci}
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_cistatic const struct proc_ops viafb_dvp0_proc_ops = {
11778c2ecf20Sopenharmony_ci	.proc_open	= viafb_dvp0_proc_open,
11788c2ecf20Sopenharmony_ci	.proc_read	= seq_read,
11798c2ecf20Sopenharmony_ci	.proc_lseek	= seq_lseek,
11808c2ecf20Sopenharmony_ci	.proc_release	= single_release,
11818c2ecf20Sopenharmony_ci	.proc_write	= viafb_dvp0_proc_write,
11828c2ecf20Sopenharmony_ci};
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_cistatic int viafb_dvp1_proc_show(struct seq_file *m, void *v)
11858c2ecf20Sopenharmony_ci{
11868c2ecf20Sopenharmony_ci	u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
11878c2ecf20Sopenharmony_ci	dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
11888c2ecf20Sopenharmony_ci	dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
11898c2ecf20Sopenharmony_ci	dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
11908c2ecf20Sopenharmony_ci	seq_printf(m, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
11918c2ecf20Sopenharmony_ci	return 0;
11928c2ecf20Sopenharmony_ci}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_cistatic int viafb_dvp1_proc_open(struct inode *inode, struct file *file)
11958c2ecf20Sopenharmony_ci{
11968c2ecf20Sopenharmony_ci	return single_open(file, viafb_dvp1_proc_show, NULL);
11978c2ecf20Sopenharmony_ci}
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_cistatic ssize_t viafb_dvp1_proc_write(struct file *file,
12008c2ecf20Sopenharmony_ci	const char __user *buffer, size_t count, loff_t *pos)
12018c2ecf20Sopenharmony_ci{
12028c2ecf20Sopenharmony_ci	char buf[20], *value, *pbuf;
12038c2ecf20Sopenharmony_ci	u8 reg_val = 0;
12048c2ecf20Sopenharmony_ci	unsigned long length, i;
12058c2ecf20Sopenharmony_ci	if (count < 1)
12068c2ecf20Sopenharmony_ci		return -EINVAL;
12078c2ecf20Sopenharmony_ci	length = count > 20 ? 20 : count;
12088c2ecf20Sopenharmony_ci	if (copy_from_user(&buf[0], buffer, length))
12098c2ecf20Sopenharmony_ci		return -EFAULT;
12108c2ecf20Sopenharmony_ci	buf[length - 1] = '\0';	/*Ensure end string */
12118c2ecf20Sopenharmony_ci	pbuf = &buf[0];
12128c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++) {
12138c2ecf20Sopenharmony_ci		value = strsep(&pbuf, " ");
12148c2ecf20Sopenharmony_ci		if (value != NULL) {
12158c2ecf20Sopenharmony_ci			if (kstrtou8(value, 0, &reg_val) < 0)
12168c2ecf20Sopenharmony_ci				return -EINVAL;
12178c2ecf20Sopenharmony_ci			switch (i) {
12188c2ecf20Sopenharmony_ci			case 0:
12198c2ecf20Sopenharmony_ci				viafb_write_reg_mask(CR9B, VIACR,
12208c2ecf20Sopenharmony_ci					reg_val, 0x0f);
12218c2ecf20Sopenharmony_ci				break;
12228c2ecf20Sopenharmony_ci			case 1:
12238c2ecf20Sopenharmony_ci				viafb_write_reg_mask(SR65, VIASR,
12248c2ecf20Sopenharmony_ci					reg_val << 2, 0x0c);
12258c2ecf20Sopenharmony_ci				break;
12268c2ecf20Sopenharmony_ci			case 2:
12278c2ecf20Sopenharmony_ci				viafb_write_reg_mask(SR65, VIASR,
12288c2ecf20Sopenharmony_ci					reg_val, 0x03);
12298c2ecf20Sopenharmony_ci				break;
12308c2ecf20Sopenharmony_ci			default:
12318c2ecf20Sopenharmony_ci				break;
12328c2ecf20Sopenharmony_ci			}
12338c2ecf20Sopenharmony_ci		} else {
12348c2ecf20Sopenharmony_ci			break;
12358c2ecf20Sopenharmony_ci		}
12368c2ecf20Sopenharmony_ci	}
12378c2ecf20Sopenharmony_ci	return count;
12388c2ecf20Sopenharmony_ci}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_cistatic const struct proc_ops viafb_dvp1_proc_ops = {
12418c2ecf20Sopenharmony_ci	.proc_open	= viafb_dvp1_proc_open,
12428c2ecf20Sopenharmony_ci	.proc_read	= seq_read,
12438c2ecf20Sopenharmony_ci	.proc_lseek	= seq_lseek,
12448c2ecf20Sopenharmony_ci	.proc_release	= single_release,
12458c2ecf20Sopenharmony_ci	.proc_write	= viafb_dvp1_proc_write,
12468c2ecf20Sopenharmony_ci};
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_cistatic int viafb_dfph_proc_show(struct seq_file *m, void *v)
12498c2ecf20Sopenharmony_ci{
12508c2ecf20Sopenharmony_ci	u8 dfp_high = 0;
12518c2ecf20Sopenharmony_ci	dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
12528c2ecf20Sopenharmony_ci	seq_printf(m, "%x\n", dfp_high);
12538c2ecf20Sopenharmony_ci	return 0;
12548c2ecf20Sopenharmony_ci}
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_cistatic int viafb_dfph_proc_open(struct inode *inode, struct file *file)
12578c2ecf20Sopenharmony_ci{
12588c2ecf20Sopenharmony_ci	return single_open(file, viafb_dfph_proc_show, NULL);
12598c2ecf20Sopenharmony_ci}
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_cistatic ssize_t viafb_dfph_proc_write(struct file *file,
12628c2ecf20Sopenharmony_ci	const char __user *buffer, size_t count, loff_t *pos)
12638c2ecf20Sopenharmony_ci{
12648c2ecf20Sopenharmony_ci	int err;
12658c2ecf20Sopenharmony_ci	u8 reg_val;
12668c2ecf20Sopenharmony_ci	err = kstrtou8_from_user(buffer, count, 0, &reg_val);
12678c2ecf20Sopenharmony_ci	if (err)
12688c2ecf20Sopenharmony_ci		return err;
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
12718c2ecf20Sopenharmony_ci	return count;
12728c2ecf20Sopenharmony_ci}
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_cistatic const struct proc_ops viafb_dfph_proc_ops = {
12758c2ecf20Sopenharmony_ci	.proc_open	= viafb_dfph_proc_open,
12768c2ecf20Sopenharmony_ci	.proc_read	= seq_read,
12778c2ecf20Sopenharmony_ci	.proc_lseek	= seq_lseek,
12788c2ecf20Sopenharmony_ci	.proc_release	= single_release,
12798c2ecf20Sopenharmony_ci	.proc_write	= viafb_dfph_proc_write,
12808c2ecf20Sopenharmony_ci};
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_cistatic int viafb_dfpl_proc_show(struct seq_file *m, void *v)
12838c2ecf20Sopenharmony_ci{
12848c2ecf20Sopenharmony_ci	u8 dfp_low = 0;
12858c2ecf20Sopenharmony_ci	dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
12868c2ecf20Sopenharmony_ci	seq_printf(m, "%x\n", dfp_low);
12878c2ecf20Sopenharmony_ci	return 0;
12888c2ecf20Sopenharmony_ci}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_cistatic int viafb_dfpl_proc_open(struct inode *inode, struct file *file)
12918c2ecf20Sopenharmony_ci{
12928c2ecf20Sopenharmony_ci	return single_open(file, viafb_dfpl_proc_show, NULL);
12938c2ecf20Sopenharmony_ci}
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_cistatic ssize_t viafb_dfpl_proc_write(struct file *file,
12968c2ecf20Sopenharmony_ci	const char __user *buffer, size_t count, loff_t *pos)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	int err;
12998c2ecf20Sopenharmony_ci	u8 reg_val;
13008c2ecf20Sopenharmony_ci	err = kstrtou8_from_user(buffer, count, 0, &reg_val);
13018c2ecf20Sopenharmony_ci	if (err)
13028c2ecf20Sopenharmony_ci		return err;
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
13058c2ecf20Sopenharmony_ci	return count;
13068c2ecf20Sopenharmony_ci}
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_cistatic const struct proc_ops viafb_dfpl_proc_ops = {
13098c2ecf20Sopenharmony_ci	.proc_open	= viafb_dfpl_proc_open,
13108c2ecf20Sopenharmony_ci	.proc_read	= seq_read,
13118c2ecf20Sopenharmony_ci	.proc_lseek	= seq_lseek,
13128c2ecf20Sopenharmony_ci	.proc_release	= single_release,
13138c2ecf20Sopenharmony_ci	.proc_write	= viafb_dfpl_proc_write,
13148c2ecf20Sopenharmony_ci};
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_cistatic int viafb_vt1636_proc_show(struct seq_file *m, void *v)
13178c2ecf20Sopenharmony_ci{
13188c2ecf20Sopenharmony_ci	u8 vt1636_08 = 0, vt1636_09 = 0;
13198c2ecf20Sopenharmony_ci	switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
13208c2ecf20Sopenharmony_ci	case VT1636_LVDS:
13218c2ecf20Sopenharmony_ci		vt1636_08 =
13228c2ecf20Sopenharmony_ci		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
13238c2ecf20Sopenharmony_ci		    &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
13248c2ecf20Sopenharmony_ci		vt1636_09 =
13258c2ecf20Sopenharmony_ci		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
13268c2ecf20Sopenharmony_ci		    &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
13278c2ecf20Sopenharmony_ci		seq_printf(m, "%x %x\n", vt1636_08, vt1636_09);
13288c2ecf20Sopenharmony_ci		break;
13298c2ecf20Sopenharmony_ci	default:
13308c2ecf20Sopenharmony_ci		break;
13318c2ecf20Sopenharmony_ci	}
13328c2ecf20Sopenharmony_ci	switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
13338c2ecf20Sopenharmony_ci	case VT1636_LVDS:
13348c2ecf20Sopenharmony_ci		vt1636_08 =
13358c2ecf20Sopenharmony_ci		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
13368c2ecf20Sopenharmony_ci			&viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
13378c2ecf20Sopenharmony_ci		vt1636_09 =
13388c2ecf20Sopenharmony_ci		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
13398c2ecf20Sopenharmony_ci			&viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
13408c2ecf20Sopenharmony_ci		seq_printf(m, " %x %x\n", vt1636_08, vt1636_09);
13418c2ecf20Sopenharmony_ci		break;
13428c2ecf20Sopenharmony_ci	default:
13438c2ecf20Sopenharmony_ci		break;
13448c2ecf20Sopenharmony_ci	}
13458c2ecf20Sopenharmony_ci	return 0;
13468c2ecf20Sopenharmony_ci}
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_cistatic int viafb_vt1636_proc_open(struct inode *inode, struct file *file)
13498c2ecf20Sopenharmony_ci{
13508c2ecf20Sopenharmony_ci	return single_open(file, viafb_vt1636_proc_show, NULL);
13518c2ecf20Sopenharmony_ci}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_cistatic ssize_t viafb_vt1636_proc_write(struct file *file,
13548c2ecf20Sopenharmony_ci	const char __user *buffer, size_t count, loff_t *pos)
13558c2ecf20Sopenharmony_ci{
13568c2ecf20Sopenharmony_ci	char buf[30], *value, *pbuf;
13578c2ecf20Sopenharmony_ci	struct IODATA reg_val;
13588c2ecf20Sopenharmony_ci	unsigned long length, i;
13598c2ecf20Sopenharmony_ci	if (count < 1)
13608c2ecf20Sopenharmony_ci		return -EINVAL;
13618c2ecf20Sopenharmony_ci	length = count > 30 ? 30 : count;
13628c2ecf20Sopenharmony_ci	if (copy_from_user(&buf[0], buffer, length))
13638c2ecf20Sopenharmony_ci		return -EFAULT;
13648c2ecf20Sopenharmony_ci	buf[length - 1] = '\0';	/*Ensure end string */
13658c2ecf20Sopenharmony_ci	pbuf = &buf[0];
13668c2ecf20Sopenharmony_ci	switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
13678c2ecf20Sopenharmony_ci	case VT1636_LVDS:
13688c2ecf20Sopenharmony_ci		for (i = 0; i < 2; i++) {
13698c2ecf20Sopenharmony_ci			value = strsep(&pbuf, " ");
13708c2ecf20Sopenharmony_ci			if (value != NULL) {
13718c2ecf20Sopenharmony_ci				if (kstrtou8(value, 0, &reg_val.Data) < 0)
13728c2ecf20Sopenharmony_ci					return -EINVAL;
13738c2ecf20Sopenharmony_ci				switch (i) {
13748c2ecf20Sopenharmony_ci				case 0:
13758c2ecf20Sopenharmony_ci					reg_val.Index = 0x08;
13768c2ecf20Sopenharmony_ci					reg_val.Mask = 0x0f;
13778c2ecf20Sopenharmony_ci					viafb_gpio_i2c_write_mask_lvds
13788c2ecf20Sopenharmony_ci					    (viaparinfo->lvds_setting_info,
13798c2ecf20Sopenharmony_ci					    &viaparinfo->
13808c2ecf20Sopenharmony_ci					    chip_info->lvds_chip_info,
13818c2ecf20Sopenharmony_ci					     reg_val);
13828c2ecf20Sopenharmony_ci					break;
13838c2ecf20Sopenharmony_ci				case 1:
13848c2ecf20Sopenharmony_ci					reg_val.Index = 0x09;
13858c2ecf20Sopenharmony_ci					reg_val.Mask = 0x1f;
13868c2ecf20Sopenharmony_ci					viafb_gpio_i2c_write_mask_lvds
13878c2ecf20Sopenharmony_ci					    (viaparinfo->lvds_setting_info,
13888c2ecf20Sopenharmony_ci					    &viaparinfo->
13898c2ecf20Sopenharmony_ci					    chip_info->lvds_chip_info,
13908c2ecf20Sopenharmony_ci					     reg_val);
13918c2ecf20Sopenharmony_ci					break;
13928c2ecf20Sopenharmony_ci				default:
13938c2ecf20Sopenharmony_ci					break;
13948c2ecf20Sopenharmony_ci				}
13958c2ecf20Sopenharmony_ci			} else {
13968c2ecf20Sopenharmony_ci				break;
13978c2ecf20Sopenharmony_ci			}
13988c2ecf20Sopenharmony_ci		}
13998c2ecf20Sopenharmony_ci		break;
14008c2ecf20Sopenharmony_ci	default:
14018c2ecf20Sopenharmony_ci		break;
14028c2ecf20Sopenharmony_ci	}
14038c2ecf20Sopenharmony_ci	switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
14048c2ecf20Sopenharmony_ci	case VT1636_LVDS:
14058c2ecf20Sopenharmony_ci		for (i = 0; i < 2; i++) {
14068c2ecf20Sopenharmony_ci			value = strsep(&pbuf, " ");
14078c2ecf20Sopenharmony_ci			if (value != NULL) {
14088c2ecf20Sopenharmony_ci				if (kstrtou8(value, 0, &reg_val.Data) < 0)
14098c2ecf20Sopenharmony_ci					return -EINVAL;
14108c2ecf20Sopenharmony_ci				switch (i) {
14118c2ecf20Sopenharmony_ci				case 0:
14128c2ecf20Sopenharmony_ci					reg_val.Index = 0x08;
14138c2ecf20Sopenharmony_ci					reg_val.Mask = 0x0f;
14148c2ecf20Sopenharmony_ci					viafb_gpio_i2c_write_mask_lvds
14158c2ecf20Sopenharmony_ci					    (viaparinfo->lvds_setting_info2,
14168c2ecf20Sopenharmony_ci					    &viaparinfo->
14178c2ecf20Sopenharmony_ci					    chip_info->lvds_chip_info2,
14188c2ecf20Sopenharmony_ci					     reg_val);
14198c2ecf20Sopenharmony_ci					break;
14208c2ecf20Sopenharmony_ci				case 1:
14218c2ecf20Sopenharmony_ci					reg_val.Index = 0x09;
14228c2ecf20Sopenharmony_ci					reg_val.Mask = 0x1f;
14238c2ecf20Sopenharmony_ci					viafb_gpio_i2c_write_mask_lvds
14248c2ecf20Sopenharmony_ci					    (viaparinfo->lvds_setting_info2,
14258c2ecf20Sopenharmony_ci					    &viaparinfo->
14268c2ecf20Sopenharmony_ci					    chip_info->lvds_chip_info2,
14278c2ecf20Sopenharmony_ci					     reg_val);
14288c2ecf20Sopenharmony_ci					break;
14298c2ecf20Sopenharmony_ci				default:
14308c2ecf20Sopenharmony_ci					break;
14318c2ecf20Sopenharmony_ci				}
14328c2ecf20Sopenharmony_ci			} else {
14338c2ecf20Sopenharmony_ci				break;
14348c2ecf20Sopenharmony_ci			}
14358c2ecf20Sopenharmony_ci		}
14368c2ecf20Sopenharmony_ci		break;
14378c2ecf20Sopenharmony_ci	default:
14388c2ecf20Sopenharmony_ci		break;
14398c2ecf20Sopenharmony_ci	}
14408c2ecf20Sopenharmony_ci	return count;
14418c2ecf20Sopenharmony_ci}
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_cistatic const struct proc_ops viafb_vt1636_proc_ops = {
14448c2ecf20Sopenharmony_ci	.proc_open	= viafb_vt1636_proc_open,
14458c2ecf20Sopenharmony_ci	.proc_read	= seq_read,
14468c2ecf20Sopenharmony_ci	.proc_lseek	= seq_lseek,
14478c2ecf20Sopenharmony_ci	.proc_release	= single_release,
14488c2ecf20Sopenharmony_ci	.proc_write	= viafb_vt1636_proc_write,
14498c2ecf20Sopenharmony_ci};
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_ci#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_cistatic int __maybe_unused viafb_sup_odev_proc_show(struct seq_file *m, void *v)
14548c2ecf20Sopenharmony_ci{
14558c2ecf20Sopenharmony_ci	via_odev_to_seq(m, supported_odev_map[
14568c2ecf20Sopenharmony_ci		viaparinfo->shared->chip_info.gfx_chip_name]);
14578c2ecf20Sopenharmony_ci	return 0;
14588c2ecf20Sopenharmony_ci}
14598c2ecf20Sopenharmony_ci
14608c2ecf20Sopenharmony_cistatic ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
14618c2ecf20Sopenharmony_ci{
14628c2ecf20Sopenharmony_ci	char buf[64], *ptr = buf;
14638c2ecf20Sopenharmony_ci	u32 devices;
14648c2ecf20Sopenharmony_ci	bool add, sub;
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	if (count < 1 || count > 63)
14678c2ecf20Sopenharmony_ci		return -EINVAL;
14688c2ecf20Sopenharmony_ci	if (copy_from_user(&buf[0], buffer, count))
14698c2ecf20Sopenharmony_ci		return -EFAULT;
14708c2ecf20Sopenharmony_ci	buf[count] = '\0';
14718c2ecf20Sopenharmony_ci	add = buf[0] == '+';
14728c2ecf20Sopenharmony_ci	sub = buf[0] == '-';
14738c2ecf20Sopenharmony_ci	if (add || sub)
14748c2ecf20Sopenharmony_ci		ptr++;
14758c2ecf20Sopenharmony_ci	devices = via_parse_odev(ptr, &ptr);
14768c2ecf20Sopenharmony_ci	if (*ptr == '\n')
14778c2ecf20Sopenharmony_ci		ptr++;
14788c2ecf20Sopenharmony_ci	if (*ptr != 0)
14798c2ecf20Sopenharmony_ci		return -EINVAL;
14808c2ecf20Sopenharmony_ci	if (add)
14818c2ecf20Sopenharmony_ci		*odev |= devices;
14828c2ecf20Sopenharmony_ci	else if (sub)
14838c2ecf20Sopenharmony_ci		*odev &= ~devices;
14848c2ecf20Sopenharmony_ci	else
14858c2ecf20Sopenharmony_ci		*odev = devices;
14868c2ecf20Sopenharmony_ci	return count;
14878c2ecf20Sopenharmony_ci}
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_cistatic int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
14908c2ecf20Sopenharmony_ci{
14918c2ecf20Sopenharmony_ci	via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
14928c2ecf20Sopenharmony_ci	return 0;
14938c2ecf20Sopenharmony_ci}
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_cistatic int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
14968c2ecf20Sopenharmony_ci{
14978c2ecf20Sopenharmony_ci	return single_open(file, viafb_iga1_odev_proc_show, NULL);
14988c2ecf20Sopenharmony_ci}
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_cistatic ssize_t viafb_iga1_odev_proc_write(struct file *file,
15018c2ecf20Sopenharmony_ci	const char __user *buffer, size_t count, loff_t *pos)
15028c2ecf20Sopenharmony_ci{
15038c2ecf20Sopenharmony_ci	u32 dev_on, dev_off, dev_old, dev_new;
15048c2ecf20Sopenharmony_ci	ssize_t res;
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	dev_old = dev_new = viaparinfo->shared->iga1_devices;
15078c2ecf20Sopenharmony_ci	res = odev_update(buffer, count, &dev_new);
15088c2ecf20Sopenharmony_ci	if (res != count)
15098c2ecf20Sopenharmony_ci		return res;
15108c2ecf20Sopenharmony_ci	dev_off = dev_old & ~dev_new;
15118c2ecf20Sopenharmony_ci	dev_on = dev_new & ~dev_old;
15128c2ecf20Sopenharmony_ci	viaparinfo->shared->iga1_devices = dev_new;
15138c2ecf20Sopenharmony_ci	viaparinfo->shared->iga2_devices &= ~dev_new;
15148c2ecf20Sopenharmony_ci	via_set_state(dev_off, VIA_STATE_OFF);
15158c2ecf20Sopenharmony_ci	via_set_source(dev_new, IGA1);
15168c2ecf20Sopenharmony_ci	via_set_state(dev_on, VIA_STATE_ON);
15178c2ecf20Sopenharmony_ci	return res;
15188c2ecf20Sopenharmony_ci}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_cistatic const struct proc_ops viafb_iga1_odev_proc_ops = {
15218c2ecf20Sopenharmony_ci	.proc_open	= viafb_iga1_odev_proc_open,
15228c2ecf20Sopenharmony_ci	.proc_read	= seq_read,
15238c2ecf20Sopenharmony_ci	.proc_lseek	= seq_lseek,
15248c2ecf20Sopenharmony_ci	.proc_release	= single_release,
15258c2ecf20Sopenharmony_ci	.proc_write	= viafb_iga1_odev_proc_write,
15268c2ecf20Sopenharmony_ci};
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_cistatic int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
15298c2ecf20Sopenharmony_ci{
15308c2ecf20Sopenharmony_ci	via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
15318c2ecf20Sopenharmony_ci	return 0;
15328c2ecf20Sopenharmony_ci}
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_cistatic int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
15358c2ecf20Sopenharmony_ci{
15368c2ecf20Sopenharmony_ci	return single_open(file, viafb_iga2_odev_proc_show, NULL);
15378c2ecf20Sopenharmony_ci}
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_cistatic ssize_t viafb_iga2_odev_proc_write(struct file *file,
15408c2ecf20Sopenharmony_ci	const char __user *buffer, size_t count, loff_t *pos)
15418c2ecf20Sopenharmony_ci{
15428c2ecf20Sopenharmony_ci	u32 dev_on, dev_off, dev_old, dev_new;
15438c2ecf20Sopenharmony_ci	ssize_t res;
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci	dev_old = dev_new = viaparinfo->shared->iga2_devices;
15468c2ecf20Sopenharmony_ci	res = odev_update(buffer, count, &dev_new);
15478c2ecf20Sopenharmony_ci	if (res != count)
15488c2ecf20Sopenharmony_ci		return res;
15498c2ecf20Sopenharmony_ci	dev_off = dev_old & ~dev_new;
15508c2ecf20Sopenharmony_ci	dev_on = dev_new & ~dev_old;
15518c2ecf20Sopenharmony_ci	viaparinfo->shared->iga2_devices = dev_new;
15528c2ecf20Sopenharmony_ci	viaparinfo->shared->iga1_devices &= ~dev_new;
15538c2ecf20Sopenharmony_ci	via_set_state(dev_off, VIA_STATE_OFF);
15548c2ecf20Sopenharmony_ci	via_set_source(dev_new, IGA2);
15558c2ecf20Sopenharmony_ci	via_set_state(dev_on, VIA_STATE_ON);
15568c2ecf20Sopenharmony_ci	return res;
15578c2ecf20Sopenharmony_ci}
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_cistatic const struct proc_ops viafb_iga2_odev_proc_ops = {
15608c2ecf20Sopenharmony_ci	.proc_open	= viafb_iga2_odev_proc_open,
15618c2ecf20Sopenharmony_ci	.proc_read	= seq_read,
15628c2ecf20Sopenharmony_ci	.proc_lseek	= seq_lseek,
15638c2ecf20Sopenharmony_ci	.proc_release	= single_release,
15648c2ecf20Sopenharmony_ci	.proc_write	= viafb_iga2_odev_proc_write,
15658c2ecf20Sopenharmony_ci};
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci#define IS_VT1636(lvds_chip)	((lvds_chip).lvds_chip_name == VT1636_LVDS)
15688c2ecf20Sopenharmony_cistatic void viafb_init_proc(struct viafb_shared *shared)
15698c2ecf20Sopenharmony_ci{
15708c2ecf20Sopenharmony_ci	struct proc_dir_entry *iga1_entry, *iga2_entry,
15718c2ecf20Sopenharmony_ci		*viafb_entry = proc_mkdir("viafb", NULL);
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	shared->proc_entry = viafb_entry;
15748c2ecf20Sopenharmony_ci	if (viafb_entry) {
15758c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
15768c2ecf20Sopenharmony_ci		proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_ops);
15778c2ecf20Sopenharmony_ci		proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_ops);
15788c2ecf20Sopenharmony_ci		proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_ops);
15798c2ecf20Sopenharmony_ci		proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_ops);
15808c2ecf20Sopenharmony_ci		if (IS_VT1636(shared->chip_info.lvds_chip_info)
15818c2ecf20Sopenharmony_ci			|| IS_VT1636(shared->chip_info.lvds_chip_info2))
15828c2ecf20Sopenharmony_ci			proc_create("vt1636", 0, viafb_entry,
15838c2ecf20Sopenharmony_ci				    &viafb_vt1636_proc_ops);
15848c2ecf20Sopenharmony_ci#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci		proc_create_single("supported_output_devices", 0, viafb_entry,
15878c2ecf20Sopenharmony_ci			viafb_sup_odev_proc_show);
15888c2ecf20Sopenharmony_ci		iga1_entry = proc_mkdir("iga1", viafb_entry);
15898c2ecf20Sopenharmony_ci		shared->iga1_proc_entry = iga1_entry;
15908c2ecf20Sopenharmony_ci		proc_create("output_devices", 0, iga1_entry,
15918c2ecf20Sopenharmony_ci			    &viafb_iga1_odev_proc_ops);
15928c2ecf20Sopenharmony_ci		iga2_entry = proc_mkdir("iga2", viafb_entry);
15938c2ecf20Sopenharmony_ci		shared->iga2_proc_entry = iga2_entry;
15948c2ecf20Sopenharmony_ci		proc_create("output_devices", 0, iga2_entry,
15958c2ecf20Sopenharmony_ci			    &viafb_iga2_odev_proc_ops);
15968c2ecf20Sopenharmony_ci	}
15978c2ecf20Sopenharmony_ci}
15988c2ecf20Sopenharmony_cistatic void viafb_remove_proc(struct viafb_shared *shared)
15998c2ecf20Sopenharmony_ci{
16008c2ecf20Sopenharmony_ci	struct proc_dir_entry *viafb_entry = shared->proc_entry;
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	if (!viafb_entry)
16038c2ecf20Sopenharmony_ci		return;
16048c2ecf20Sopenharmony_ci
16058c2ecf20Sopenharmony_ci	remove_proc_entry("output_devices", shared->iga2_proc_entry);
16068c2ecf20Sopenharmony_ci	remove_proc_entry("iga2", viafb_entry);
16078c2ecf20Sopenharmony_ci	remove_proc_entry("output_devices", shared->iga1_proc_entry);
16088c2ecf20Sopenharmony_ci	remove_proc_entry("iga1", viafb_entry);
16098c2ecf20Sopenharmony_ci	remove_proc_entry("supported_output_devices", viafb_entry);
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
16128c2ecf20Sopenharmony_ci	remove_proc_entry("dvp0", viafb_entry);/* parent dir */
16138c2ecf20Sopenharmony_ci	remove_proc_entry("dvp1", viafb_entry);
16148c2ecf20Sopenharmony_ci	remove_proc_entry("dfph", viafb_entry);
16158c2ecf20Sopenharmony_ci	remove_proc_entry("dfpl", viafb_entry);
16168c2ecf20Sopenharmony_ci	if (IS_VT1636(shared->chip_info.lvds_chip_info)
16178c2ecf20Sopenharmony_ci		|| IS_VT1636(shared->chip_info.lvds_chip_info2))
16188c2ecf20Sopenharmony_ci		remove_proc_entry("vt1636", viafb_entry);
16198c2ecf20Sopenharmony_ci#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	remove_proc_entry("viafb", NULL);
16228c2ecf20Sopenharmony_ci}
16238c2ecf20Sopenharmony_ci#undef IS_VT1636
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_cistatic int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres)
16268c2ecf20Sopenharmony_ci{
16278c2ecf20Sopenharmony_ci	const struct fb_videomode *mode = NULL;
16288c2ecf20Sopenharmony_ci	char *ptr;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	if (!str) {
16318c2ecf20Sopenharmony_ci		if (devices == VIA_CRT)
16328c2ecf20Sopenharmony_ci			mode = via_aux_get_preferred_mode(
16338c2ecf20Sopenharmony_ci				viaparinfo->shared->i2c_26);
16348c2ecf20Sopenharmony_ci		else if (devices == VIA_DVP1)
16358c2ecf20Sopenharmony_ci			mode = via_aux_get_preferred_mode(
16368c2ecf20Sopenharmony_ci				viaparinfo->shared->i2c_31);
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci		if (mode) {
16398c2ecf20Sopenharmony_ci			*xres = mode->xres;
16408c2ecf20Sopenharmony_ci			*yres = mode->yres;
16418c2ecf20Sopenharmony_ci		} else if (machine_is_olpc()) {
16428c2ecf20Sopenharmony_ci			*xres = 1200;
16438c2ecf20Sopenharmony_ci			*yres = 900;
16448c2ecf20Sopenharmony_ci		} else {
16458c2ecf20Sopenharmony_ci			*xres = 640;
16468c2ecf20Sopenharmony_ci			*yres = 480;
16478c2ecf20Sopenharmony_ci		}
16488c2ecf20Sopenharmony_ci		return 0;
16498c2ecf20Sopenharmony_ci	}
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	*xres = simple_strtoul(str, &ptr, 10);
16528c2ecf20Sopenharmony_ci	if (ptr[0] != 'x')
16538c2ecf20Sopenharmony_ci		return -EINVAL;
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci	*yres = simple_strtoul(&ptr[1], &ptr, 10);
16568c2ecf20Sopenharmony_ci	if (ptr[0])
16578c2ecf20Sopenharmony_ci		return -EINVAL;
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	return 0;
16608c2ecf20Sopenharmony_ci}
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
16648c2ecf20Sopenharmony_cistatic int viafb_suspend(void *unused)
16658c2ecf20Sopenharmony_ci{
16668c2ecf20Sopenharmony_ci	console_lock();
16678c2ecf20Sopenharmony_ci	fb_set_suspend(viafbinfo, 1);
16688c2ecf20Sopenharmony_ci	viafb_sync(viafbinfo);
16698c2ecf20Sopenharmony_ci	console_unlock();
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci	return 0;
16728c2ecf20Sopenharmony_ci}
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_cistatic int viafb_resume(void *unused)
16758c2ecf20Sopenharmony_ci{
16768c2ecf20Sopenharmony_ci	console_lock();
16778c2ecf20Sopenharmony_ci	if (viaparinfo->shared->vdev->engine_mmio)
16788c2ecf20Sopenharmony_ci		viafb_reset_engine(viaparinfo);
16798c2ecf20Sopenharmony_ci	viafb_set_par(viafbinfo);
16808c2ecf20Sopenharmony_ci	if (viafb_dual_fb)
16818c2ecf20Sopenharmony_ci		viafb_set_par(viafbinfo1);
16828c2ecf20Sopenharmony_ci	fb_set_suspend(viafbinfo, 0);
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci	console_unlock();
16858c2ecf20Sopenharmony_ci	return 0;
16868c2ecf20Sopenharmony_ci}
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_cistatic struct viafb_pm_hooks viafb_fb_pm_hooks = {
16898c2ecf20Sopenharmony_ci	.suspend = viafb_suspend,
16908c2ecf20Sopenharmony_ci	.resume = viafb_resume
16918c2ecf20Sopenharmony_ci};
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci#endif
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_cistatic void i2c_bus_probe(struct viafb_shared *shared)
16968c2ecf20Sopenharmony_ci{
16978c2ecf20Sopenharmony_ci	/* should be always CRT */
16988c2ecf20Sopenharmony_ci	printk(KERN_INFO "viafb: Probing I2C bus 0x26\n");
16998c2ecf20Sopenharmony_ci	shared->i2c_26 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_26));
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci	/* seems to be usually DVP1 */
17028c2ecf20Sopenharmony_ci	printk(KERN_INFO "viafb: Probing I2C bus 0x31\n");
17038c2ecf20Sopenharmony_ci	shared->i2c_31 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_31));
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci	/* FIXME: what is this? */
17068c2ecf20Sopenharmony_ci	if (!machine_is_olpc()) {
17078c2ecf20Sopenharmony_ci		printk(KERN_INFO "viafb: Probing I2C bus 0x2C\n");
17088c2ecf20Sopenharmony_ci		shared->i2c_2C = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_2C));
17098c2ecf20Sopenharmony_ci	}
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	printk(KERN_INFO "viafb: Finished I2C bus probing");
17128c2ecf20Sopenharmony_ci}
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_cistatic void i2c_bus_free(struct viafb_shared *shared)
17158c2ecf20Sopenharmony_ci{
17168c2ecf20Sopenharmony_ci	via_aux_free(shared->i2c_26);
17178c2ecf20Sopenharmony_ci	via_aux_free(shared->i2c_31);
17188c2ecf20Sopenharmony_ci	via_aux_free(shared->i2c_2C);
17198c2ecf20Sopenharmony_ci}
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ciint via_fb_pci_probe(struct viafb_dev *vdev)
17228c2ecf20Sopenharmony_ci{
17238c2ecf20Sopenharmony_ci	u32 default_xres, default_yres;
17248c2ecf20Sopenharmony_ci	struct fb_var_screeninfo default_var;
17258c2ecf20Sopenharmony_ci	int rc;
17268c2ecf20Sopenharmony_ci	u32 viafb_par_length;
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
17298c2ecf20Sopenharmony_ci	memset(&default_var, 0, sizeof(default_var));
17308c2ecf20Sopenharmony_ci	viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ci	/* Allocate fb_info and ***_par here, also including some other needed
17338c2ecf20Sopenharmony_ci	 * variables
17348c2ecf20Sopenharmony_ci	*/
17358c2ecf20Sopenharmony_ci	viafbinfo = framebuffer_alloc(viafb_par_length +
17368c2ecf20Sopenharmony_ci		ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8),
17378c2ecf20Sopenharmony_ci		&vdev->pdev->dev);
17388c2ecf20Sopenharmony_ci	if (!viafbinfo)
17398c2ecf20Sopenharmony_ci		return -ENOMEM;
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	viaparinfo = (struct viafb_par *)viafbinfo->par;
17428c2ecf20Sopenharmony_ci	viaparinfo->shared = viafbinfo->par + viafb_par_length;
17438c2ecf20Sopenharmony_ci	viaparinfo->shared->vdev = vdev;
17448c2ecf20Sopenharmony_ci	viaparinfo->vram_addr = 0;
17458c2ecf20Sopenharmony_ci	viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info;
17468c2ecf20Sopenharmony_ci	viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
17478c2ecf20Sopenharmony_ci	viaparinfo->lvds_setting_info2 =
17488c2ecf20Sopenharmony_ci		&viaparinfo->shared->lvds_setting_info2;
17498c2ecf20Sopenharmony_ci	viaparinfo->chip_info = &viaparinfo->shared->chip_info;
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	i2c_bus_probe(viaparinfo->shared);
17528c2ecf20Sopenharmony_ci	if (viafb_dual_fb)
17538c2ecf20Sopenharmony_ci		viafb_SAMM_ON = 1;
17548c2ecf20Sopenharmony_ci	parse_lcd_port();
17558c2ecf20Sopenharmony_ci	parse_dvi_port();
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci	viafb_init_chip_info(vdev->chip_type);
17588c2ecf20Sopenharmony_ci	/*
17598c2ecf20Sopenharmony_ci	 * The framebuffer will have been successfully mapped by
17608c2ecf20Sopenharmony_ci	 * the core (or we'd not be here), but we still need to
17618c2ecf20Sopenharmony_ci	 * set up our own accounting.
17628c2ecf20Sopenharmony_ci	 */
17638c2ecf20Sopenharmony_ci	viaparinfo->fbmem = vdev->fbmem_start;
17648c2ecf20Sopenharmony_ci	viaparinfo->memsize = vdev->fbmem_len;
17658c2ecf20Sopenharmony_ci	viaparinfo->fbmem_free = viaparinfo->memsize;
17668c2ecf20Sopenharmony_ci	viaparinfo->fbmem_used = 0;
17678c2ecf20Sopenharmony_ci	viafbinfo->screen_base = vdev->fbmem;
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci	viafbinfo->fix.mmio_start = vdev->engine_start;
17708c2ecf20Sopenharmony_ci	viafbinfo->fix.mmio_len = vdev->engine_len;
17718c2ecf20Sopenharmony_ci	viafbinfo->node = 0;
17728c2ecf20Sopenharmony_ci	viafbinfo->fbops = &viafb_ops;
17738c2ecf20Sopenharmony_ci	viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	viafbinfo->pseudo_palette = pseudo_pal;
17768c2ecf20Sopenharmony_ci	if (viafb_accel && !viafb_setup_engine(viafbinfo)) {
17778c2ecf20Sopenharmony_ci		viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA |
17788c2ecf20Sopenharmony_ci			FBINFO_HWACCEL_FILLRECT |  FBINFO_HWACCEL_IMAGEBLIT;
17798c2ecf20Sopenharmony_ci		default_var.accel_flags = FB_ACCELF_TEXT;
17808c2ecf20Sopenharmony_ci	} else {
17818c2ecf20Sopenharmony_ci		viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
17828c2ecf20Sopenharmony_ci		default_var.accel_flags = 0;
17838c2ecf20Sopenharmony_ci	}
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	if (viafb_second_size && (viafb_second_size < 8)) {
17868c2ecf20Sopenharmony_ci		viafb_second_offset = viaparinfo->fbmem_free -
17878c2ecf20Sopenharmony_ci			viafb_second_size * 1024 * 1024;
17888c2ecf20Sopenharmony_ci	} else {
17898c2ecf20Sopenharmony_ci		viafb_second_size = 8;
17908c2ecf20Sopenharmony_ci		viafb_second_offset = viaparinfo->fbmem_free -
17918c2ecf20Sopenharmony_ci			viafb_second_size * 1024 * 1024;
17928c2ecf20Sopenharmony_ci	}
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci	parse_mode(viafb_mode, viaparinfo->shared->iga1_devices,
17958c2ecf20Sopenharmony_ci		&default_xres, &default_yres);
17968c2ecf20Sopenharmony_ci	if (viafb_SAMM_ON == 1)
17978c2ecf20Sopenharmony_ci		parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices,
17988c2ecf20Sopenharmony_ci			&viafb_second_xres, &viafb_second_yres);
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	default_var.xres = default_xres;
18018c2ecf20Sopenharmony_ci	default_var.yres = default_yres;
18028c2ecf20Sopenharmony_ci	default_var.xres_virtual = default_xres;
18038c2ecf20Sopenharmony_ci	default_var.yres_virtual = default_yres;
18048c2ecf20Sopenharmony_ci	default_var.bits_per_pixel = viafb_bpp;
18058c2ecf20Sopenharmony_ci	viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
18068c2ecf20Sopenharmony_ci		default_var.xres, default_var.yres, viafb_refresh));
18078c2ecf20Sopenharmony_ci	viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
18088c2ecf20Sopenharmony_ci	viafbinfo->var = default_var;
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci	if (viafb_dual_fb) {
18118c2ecf20Sopenharmony_ci		viafbinfo1 = framebuffer_alloc(viafb_par_length,
18128c2ecf20Sopenharmony_ci				&vdev->pdev->dev);
18138c2ecf20Sopenharmony_ci		if (!viafbinfo1) {
18148c2ecf20Sopenharmony_ci			rc = -ENOMEM;
18158c2ecf20Sopenharmony_ci			goto out_fb_release;
18168c2ecf20Sopenharmony_ci		}
18178c2ecf20Sopenharmony_ci		viaparinfo1 = viafbinfo1->par;
18188c2ecf20Sopenharmony_ci		memcpy(viaparinfo1, viaparinfo, viafb_par_length);
18198c2ecf20Sopenharmony_ci		viaparinfo1->vram_addr = viafb_second_offset;
18208c2ecf20Sopenharmony_ci		viaparinfo1->memsize = viaparinfo->memsize -
18218c2ecf20Sopenharmony_ci			viafb_second_offset;
18228c2ecf20Sopenharmony_ci		viaparinfo->memsize = viafb_second_offset;
18238c2ecf20Sopenharmony_ci		viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci		viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
18268c2ecf20Sopenharmony_ci		viaparinfo1->fbmem_free = viaparinfo1->memsize -
18278c2ecf20Sopenharmony_ci			viaparinfo1->fbmem_used;
18288c2ecf20Sopenharmony_ci		viaparinfo->fbmem_free = viaparinfo->memsize;
18298c2ecf20Sopenharmony_ci		viaparinfo->fbmem_used = 0;
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci		viaparinfo->iga_path = IGA1;
18328c2ecf20Sopenharmony_ci		viaparinfo1->iga_path = IGA2;
18338c2ecf20Sopenharmony_ci		memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
18348c2ecf20Sopenharmony_ci		viafbinfo1->par = viaparinfo1;
18358c2ecf20Sopenharmony_ci		viafbinfo1->screen_base = viafbinfo->screen_base +
18368c2ecf20Sopenharmony_ci			viafb_second_offset;
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci		default_var.xres = viafb_second_xres;
18398c2ecf20Sopenharmony_ci		default_var.yres = viafb_second_yres;
18408c2ecf20Sopenharmony_ci		default_var.xres_virtual = viafb_second_xres;
18418c2ecf20Sopenharmony_ci		default_var.yres_virtual = viafb_second_yres;
18428c2ecf20Sopenharmony_ci		default_var.bits_per_pixel = viafb_bpp1;
18438c2ecf20Sopenharmony_ci		viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
18448c2ecf20Sopenharmony_ci			default_var.xres, default_var.yres, viafb_refresh1));
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci		viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
18478c2ecf20Sopenharmony_ci		viafb_check_var(&default_var, viafbinfo1);
18488c2ecf20Sopenharmony_ci		viafbinfo1->var = default_var;
18498c2ecf20Sopenharmony_ci		viafb_update_fix(viafbinfo1);
18508c2ecf20Sopenharmony_ci		viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var,
18518c2ecf20Sopenharmony_ci			&viafbinfo1->fix);
18528c2ecf20Sopenharmony_ci	}
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_ci	viafb_check_var(&viafbinfo->var, viafbinfo);
18558c2ecf20Sopenharmony_ci	viafb_update_fix(viafbinfo);
18568c2ecf20Sopenharmony_ci	viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
18578c2ecf20Sopenharmony_ci		&viafbinfo->fix);
18588c2ecf20Sopenharmony_ci	default_var.activate = FB_ACTIVATE_NOW;
18598c2ecf20Sopenharmony_ci	rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
18608c2ecf20Sopenharmony_ci	if (rc)
18618c2ecf20Sopenharmony_ci		goto out_fb1_release;
18628c2ecf20Sopenharmony_ci
18638c2ecf20Sopenharmony_ci	if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
18648c2ecf20Sopenharmony_ci	    && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
18658c2ecf20Sopenharmony_ci		rc = register_framebuffer(viafbinfo1);
18668c2ecf20Sopenharmony_ci		if (rc)
18678c2ecf20Sopenharmony_ci			goto out_dealloc_cmap;
18688c2ecf20Sopenharmony_ci	}
18698c2ecf20Sopenharmony_ci	rc = register_framebuffer(viafbinfo);
18708c2ecf20Sopenharmony_ci	if (rc)
18718c2ecf20Sopenharmony_ci		goto out_fb1_unreg_lcd_cle266;
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_ci	if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
18748c2ecf20Sopenharmony_ci			|| (viaparinfo->chip_info->gfx_chip_name !=
18758c2ecf20Sopenharmony_ci			UNICHROME_CLE266))) {
18768c2ecf20Sopenharmony_ci		rc = register_framebuffer(viafbinfo1);
18778c2ecf20Sopenharmony_ci		if (rc)
18788c2ecf20Sopenharmony_ci			goto out_fb_unreg;
18798c2ecf20Sopenharmony_ci	}
18808c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
18818c2ecf20Sopenharmony_ci		  viafbinfo->node, viafbinfo->fix.id, default_var.xres,
18828c2ecf20Sopenharmony_ci		  default_var.yres, default_var.bits_per_pixel);
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci	viafb_init_proc(viaparinfo->shared);
18858c2ecf20Sopenharmony_ci	viafb_init_dac(IGA2);
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
18888c2ecf20Sopenharmony_ci	viafb_pm_register(&viafb_fb_pm_hooks);
18898c2ecf20Sopenharmony_ci#endif
18908c2ecf20Sopenharmony_ci	return 0;
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_ciout_fb_unreg:
18938c2ecf20Sopenharmony_ci	unregister_framebuffer(viafbinfo);
18948c2ecf20Sopenharmony_ciout_fb1_unreg_lcd_cle266:
18958c2ecf20Sopenharmony_ci	if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
18968c2ecf20Sopenharmony_ci	    && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
18978c2ecf20Sopenharmony_ci		unregister_framebuffer(viafbinfo1);
18988c2ecf20Sopenharmony_ciout_dealloc_cmap:
18998c2ecf20Sopenharmony_ci	fb_dealloc_cmap(&viafbinfo->cmap);
19008c2ecf20Sopenharmony_ciout_fb1_release:
19018c2ecf20Sopenharmony_ci	framebuffer_release(viafbinfo1);
19028c2ecf20Sopenharmony_ciout_fb_release:
19038c2ecf20Sopenharmony_ci	i2c_bus_free(viaparinfo->shared);
19048c2ecf20Sopenharmony_ci	framebuffer_release(viafbinfo);
19058c2ecf20Sopenharmony_ci	return rc;
19068c2ecf20Sopenharmony_ci}
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_civoid via_fb_pci_remove(struct pci_dev *pdev)
19098c2ecf20Sopenharmony_ci{
19108c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
19118c2ecf20Sopenharmony_ci	fb_dealloc_cmap(&viafbinfo->cmap);
19128c2ecf20Sopenharmony_ci	unregister_framebuffer(viafbinfo);
19138c2ecf20Sopenharmony_ci	if (viafb_dual_fb)
19148c2ecf20Sopenharmony_ci		unregister_framebuffer(viafbinfo1);
19158c2ecf20Sopenharmony_ci	viafb_remove_proc(viaparinfo->shared);
19168c2ecf20Sopenharmony_ci	i2c_bus_free(viaparinfo->shared);
19178c2ecf20Sopenharmony_ci	framebuffer_release(viafbinfo);
19188c2ecf20Sopenharmony_ci	if (viafb_dual_fb)
19198c2ecf20Sopenharmony_ci		framebuffer_release(viafbinfo1);
19208c2ecf20Sopenharmony_ci}
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci#ifndef MODULE
19238c2ecf20Sopenharmony_cistatic int __init viafb_setup(void)
19248c2ecf20Sopenharmony_ci{
19258c2ecf20Sopenharmony_ci	char *this_opt;
19268c2ecf20Sopenharmony_ci	char *options;
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_setup!\n");
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	if (fb_get_options("viafb", &options))
19318c2ecf20Sopenharmony_ci		return -ENODEV;
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci	if (!options || !*options)
19348c2ecf20Sopenharmony_ci		return 0;
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	while ((this_opt = strsep(&options, ",")) != NULL) {
19378c2ecf20Sopenharmony_ci		if (!*this_opt)
19388c2ecf20Sopenharmony_ci			continue;
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci		if (!strncmp(this_opt, "viafb_mode1=", 12)) {
19418c2ecf20Sopenharmony_ci			viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
19428c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_mode=", 11)) {
19438c2ecf20Sopenharmony_ci			viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
19448c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_bpp1=", 11)) {
19458c2ecf20Sopenharmony_ci			if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0)
19468c2ecf20Sopenharmony_ci				return -EINVAL;
19478c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_bpp=", 10)) {
19488c2ecf20Sopenharmony_ci			if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0)
19498c2ecf20Sopenharmony_ci				return -EINVAL;
19508c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_refresh1=", 15)) {
19518c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0)
19528c2ecf20Sopenharmony_ci				return -EINVAL;
19538c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_refresh=", 14)) {
19548c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0)
19558c2ecf20Sopenharmony_ci				return -EINVAL;
19568c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) {
19578c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 21, 0,
19588c2ecf20Sopenharmony_ci				      &viafb_lcd_dsp_method) < 0)
19598c2ecf20Sopenharmony_ci				return -EINVAL;
19608c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) {
19618c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 19, 0,
19628c2ecf20Sopenharmony_ci				      &viafb_lcd_panel_id) < 0)
19638c2ecf20Sopenharmony_ci				return -EINVAL;
19648c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_accel=", 12)) {
19658c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0)
19668c2ecf20Sopenharmony_ci				return -EINVAL;
19678c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) {
19688c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0)
19698c2ecf20Sopenharmony_ci				return -EINVAL;
19708c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_active_dev=", 17)) {
19718c2ecf20Sopenharmony_ci			viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
19728c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt,
19738c2ecf20Sopenharmony_ci			"viafb_display_hardware_layout=", 30)) {
19748c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 30, 0,
19758c2ecf20Sopenharmony_ci				      &viafb_display_hardware_layout) < 0)
19768c2ecf20Sopenharmony_ci				return -EINVAL;
19778c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_second_size=", 18)) {
19788c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0)
19798c2ecf20Sopenharmony_ci				return -EINVAL;
19808c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt,
19818c2ecf20Sopenharmony_ci			"viafb_platform_epia_dvi=", 24)) {
19828c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 24, 0,
19838c2ecf20Sopenharmony_ci				      &viafb_platform_epia_dvi) < 0)
19848c2ecf20Sopenharmony_ci				return -EINVAL;
19858c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt,
19868c2ecf20Sopenharmony_ci			"viafb_device_lcd_dualedge=", 26)) {
19878c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 26, 0,
19888c2ecf20Sopenharmony_ci				      &viafb_device_lcd_dualedge) < 0)
19898c2ecf20Sopenharmony_ci				return -EINVAL;
19908c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_bus_width=", 16)) {
19918c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0)
19928c2ecf20Sopenharmony_ci				return -EINVAL;
19938c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) {
19948c2ecf20Sopenharmony_ci			if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0)
19958c2ecf20Sopenharmony_ci				return -EINVAL;
19968c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) {
19978c2ecf20Sopenharmony_ci			viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
19988c2ecf20Sopenharmony_ci		} else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) {
19998c2ecf20Sopenharmony_ci			viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
20008c2ecf20Sopenharmony_ci		}
20018c2ecf20Sopenharmony_ci	}
20028c2ecf20Sopenharmony_ci	return 0;
20038c2ecf20Sopenharmony_ci}
20048c2ecf20Sopenharmony_ci#endif
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci/*
20078c2ecf20Sopenharmony_ci * These are called out of via-core for now.
20088c2ecf20Sopenharmony_ci */
20098c2ecf20Sopenharmony_ciint __init viafb_init(void)
20108c2ecf20Sopenharmony_ci{
20118c2ecf20Sopenharmony_ci	u32 dummy_x, dummy_y;
20128c2ecf20Sopenharmony_ci	int r = 0;
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci	if (machine_is_olpc())
20158c2ecf20Sopenharmony_ci		/* Apply XO-1.5-specific configuration. */
20168c2ecf20Sopenharmony_ci		viafb_lcd_panel_id = 23;
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_ci#ifndef MODULE
20198c2ecf20Sopenharmony_ci	r = viafb_setup();
20208c2ecf20Sopenharmony_ci	if (r < 0)
20218c2ecf20Sopenharmony_ci		return r;
20228c2ecf20Sopenharmony_ci#endif
20238c2ecf20Sopenharmony_ci	if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y)
20248c2ecf20Sopenharmony_ci		|| !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
20258c2ecf20Sopenharmony_ci		|| parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y)
20268c2ecf20Sopenharmony_ci		|| !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
20278c2ecf20Sopenharmony_ci		|| viafb_bpp < 0 || viafb_bpp > 32
20288c2ecf20Sopenharmony_ci		|| viafb_bpp1 < 0 || viafb_bpp1 > 32
20298c2ecf20Sopenharmony_ci		|| parse_active_dev())
20308c2ecf20Sopenharmony_ci		return -EINVAL;
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci	printk(KERN_INFO
20338c2ecf20Sopenharmony_ci       "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
20348c2ecf20Sopenharmony_ci	       VERSION_MAJOR, VERSION_MINOR);
20358c2ecf20Sopenharmony_ci	return r;
20368c2ecf20Sopenharmony_ci}
20378c2ecf20Sopenharmony_ci
20388c2ecf20Sopenharmony_civoid __exit viafb_exit(void)
20398c2ecf20Sopenharmony_ci{
20408c2ecf20Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_exit!\n");
20418c2ecf20Sopenharmony_ci}
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_cistatic struct fb_ops viafb_ops = {
20448c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
20458c2ecf20Sopenharmony_ci	.fb_open = viafb_open,
20468c2ecf20Sopenharmony_ci	.fb_release = viafb_release,
20478c2ecf20Sopenharmony_ci	.fb_check_var = viafb_check_var,
20488c2ecf20Sopenharmony_ci	.fb_set_par = viafb_set_par,
20498c2ecf20Sopenharmony_ci	.fb_setcolreg = viafb_setcolreg,
20508c2ecf20Sopenharmony_ci	.fb_pan_display = viafb_pan_display,
20518c2ecf20Sopenharmony_ci	.fb_blank = viafb_blank,
20528c2ecf20Sopenharmony_ci	.fb_fillrect = viafb_fillrect,
20538c2ecf20Sopenharmony_ci	.fb_copyarea = viafb_copyarea,
20548c2ecf20Sopenharmony_ci	.fb_imageblit = viafb_imageblit,
20558c2ecf20Sopenharmony_ci	.fb_cursor = viafb_cursor,
20568c2ecf20Sopenharmony_ci	.fb_ioctl = viafb_ioctl,
20578c2ecf20Sopenharmony_ci	.fb_sync = viafb_sync,
20588c2ecf20Sopenharmony_ci};
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci#ifdef MODULE
20628c2ecf20Sopenharmony_cimodule_param(viafb_mode, charp, S_IRUSR);
20638c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_cimodule_param(viafb_mode1, charp, S_IRUSR);
20668c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_cimodule_param(viafb_bpp, int, S_IRUSR);
20698c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_cimodule_param(viafb_bpp1, int, S_IRUSR);
20728c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_cimodule_param(viafb_refresh, int, S_IRUSR);
20758c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_refresh,
20768c2ecf20Sopenharmony_ci	"Set CRT viafb_refresh rate (default = 60)");
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_cimodule_param(viafb_refresh1, int, S_IRUSR);
20798c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_refresh1,
20808c2ecf20Sopenharmony_ci	"Set CRT refresh rate (default = 60)");
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_cimodule_param(viafb_lcd_panel_id, int, S_IRUSR);
20838c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_lcd_panel_id,
20848c2ecf20Sopenharmony_ci	"Set Flat Panel type(Default=1024x768)");
20858c2ecf20Sopenharmony_ci
20868c2ecf20Sopenharmony_cimodule_param(viafb_lcd_dsp_method, int, S_IRUSR);
20878c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_lcd_dsp_method,
20888c2ecf20Sopenharmony_ci	"Set Flat Panel display scaling method.(Default=Expansion)");
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_cimodule_param(viafb_SAMM_ON, int, S_IRUSR);
20918c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_SAMM_ON,
20928c2ecf20Sopenharmony_ci	"Turn on/off flag of SAMM(Default=OFF)");
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_cimodule_param(viafb_accel, int, S_IRUSR);
20958c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_accel,
20968c2ecf20Sopenharmony_ci	"Set 2D Hardware Acceleration: 0 = OFF, 1 = ON (default)");
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_cimodule_param(viafb_active_dev, charp, S_IRUSR);
20998c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_cimodule_param(viafb_display_hardware_layout, int, S_IRUSR);
21028c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_display_hardware_layout,
21038c2ecf20Sopenharmony_ci	"Display Hardware Layout (LCD Only, DVI Only...,etc)");
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_cimodule_param(viafb_second_size, int, S_IRUSR);
21068c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_second_size,
21078c2ecf20Sopenharmony_ci	"Set secondary device memory size");
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_cimodule_param(viafb_dual_fb, int, S_IRUSR);
21108c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_dual_fb,
21118c2ecf20Sopenharmony_ci	"Turn on/off flag of dual framebuffer devices.(Default = OFF)");
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_cimodule_param(viafb_platform_epia_dvi, int, S_IRUSR);
21148c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_platform_epia_dvi,
21158c2ecf20Sopenharmony_ci	"Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_cimodule_param(viafb_device_lcd_dualedge, int, S_IRUSR);
21188c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_device_lcd_dualedge,
21198c2ecf20Sopenharmony_ci	"Turn on/off flag of dual edge panel.(Default = OFF)");
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_cimodule_param(viafb_bus_width, int, S_IRUSR);
21228c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_bus_width,
21238c2ecf20Sopenharmony_ci	"Set bus width of panel.(Default = 12)");
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_cimodule_param(viafb_lcd_mode, int, S_IRUSR);
21268c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_lcd_mode,
21278c2ecf20Sopenharmony_ci	"Set Flat Panel mode(Default=OPENLDI)");
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_cimodule_param(viafb_lcd_port, charp, S_IRUSR);
21308c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
21318c2ecf20Sopenharmony_ci
21328c2ecf20Sopenharmony_cimodule_param(viafb_dvi_port, charp, S_IRUSR);
21338c2ecf20Sopenharmony_ciMODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
21368c2ecf20Sopenharmony_ci#endif
2137