// SPDX-License-Identifier: GPL-2.0-or-later/* * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. */ #include <linux/compiler.h>#include <linux/module.h>#include <linux/seq_file.h>#include <linux/slab.h>#include <linux/stat.h>#include <linux/via-core.h>#include <linux/via_i2c.h> #define _MASTER_FILE#include "global.h" static u32 pseudo_pal[17]; /* video mode */static char *viafb_mode;static char *viafb_mode1;static int viafb_bpp = 32;static int viafb_bpp1 = 32; static unsigned int viafb_second_offset;static int viafb_second_size; static int viafb_accel = 1; /* Added for specifying active devices.*/static char *viafb_active_dev; /*Added for specify lcd output port*/static char *viafb_lcd_port = "";static char *viafb_dvi_port = ""; static void retrieve_device_setting(struct viafb_ioctl_setting *setting_info);static int viafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static struct fb_ops viafb_ops; /* supported output devices on each IGP * only CX700, VX800, VX855, VX900 were documented * VIA_CRT should be everywhere * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL * source selection on CX700 and later * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c */static const u32 supported_odev_map[] = { [UNICHROME_CLE266] = VIA_CRT | VIA_LDVP0 | VIA_LDVP1, [UNICHROME_K400] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_K800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_PM800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_CN700] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_CX700] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_CN750] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_K8M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_P4M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_P4M900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_VX800] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_VX855] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_VX900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,}; static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth){ var->grayscale = 0; var->red.msb_right = 0; var->green.msb_right = 0; var->blue.msb_right = 0; var->transp.offset = 0; var->transp.length = 0; var->transp.msb_right = 0; var->nonstd = 0; switch (depth) { case 8: var->bits_per_pixel = 8; var->red.offset = 0; var->green.offset = 0; var->blue.offset = 0; var->red.length = 8; var->green.length = 8; var->blue.length = 8; break; case 15: var->bits_per_pixel = 16; var->red.offset = 10; var->green.offset = 5; var->blue.offset = 0; var->red.length = 5; var->green.length = 5; var->blue.length = 5; break; case 16: var->bits_per_pixel = 16; var->red.offset = 11; var->green.offset = 5; var->blue.offset = 0; var->red.length = 5; var->green.length = 6; var->blue.length = 5; break; case 24: var->bits_per_pixel = 32; var->red.offset = 16; var->green.offset = 8; var->blue.offset = 0; var->red.length = 8; var->green.length = 8; var->blue.length = 8; break; case 30: var->bits_per_pixel = 32; var->red.offset = 20; var->green.offset = 10; var->blue.offset = 0; var->red.length = 10; var->green.length = 10; var->blue.length = 10; break; }} static void viafb_update_fix(struct fb_info *info){ u32 bpp = info->var.bits_per_pixel; info->fix.visual = bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8, VIA_PITCH_SIZE);} static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, struct viafb_par *viaparinfo){ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, "Via"); fix->smem_start = viaparinfo->fbmem; fix->smem_len = viaparinfo->fbmem_free; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = FB_VISUAL_TRUECOLOR; fix->xpanstep = fix->ywrapstep = 0; fix->ypanstep = 1; /* Just tell the accel name */ viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;}static int viafb_open(struct fb_info *info, int user){ DEBUG_MSG(KERN_INFO "viafb_open!\n"); return 0;} static int viafb_release(struct fb_info *info, int user){ DEBUG_MSG(KERN_INFO "viafb_release!\n"); return 0;} static inline int get_var_refresh(struct fb_var_screeninfo *var){ u32 htotal, vtotal; htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);} static int viafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ int depth, refresh; struct viafb_par *ppar = info->par; u32 line; DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); /* Sanity check */ /* HW neither support interlacte nor double-scaned mode */ if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) return -EINVAL; /* the refresh rate is not important here, as we only want to know * whether the resolution exists */ if (!viafb_get_best_mode(var->xres, var->yres, 60)) { DEBUG_MSG(KERN_INFO "viafb: Mode %dx%dx%d not supported!!\n", var->xres, var->yres, var->bits_per_pixel); return -EINVAL; } depth = fb_get_color_depth(var, &info->fix); if (!depth) depth = var->bits_per_pixel; if (depth < 0 || depth > 32) return -EINVAL; else if (!depth) depth = 24; else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1) depth = 15; else if (depth == 30) depth = 30; else if (depth <= 8) depth = 8; else if (depth <= 16) depth = 16; else depth = 24; viafb_fill_var_color_info(var, depth); if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8, VIA_PITCH_SIZE); if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize) return -EINVAL; /* Based on var passed in to calculate the refresh, * because our driver use some modes special. */ refresh = viafb_get_refresh(var->xres, var->yres, get_var_refresh(var)); /* Adjust var according to our driver's own table */ viafb_fill_var_timing_info(var, viafb_get_best_mode(var->xres, var->yres, refresh)); if (var->accel_flags & FB_ACCELF_TEXT && !ppar->shared->vdev->engine_mmio) var->accel_flags = 0; return 0;} static int viafb_set_par(struct fb_info *info){ struct viafb_par *viapar = info->par; int refresh; DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); viafb_update_fix(info); viapar->depth = fb_get_color_depth(&info->var, &info->fix); viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, viafbinfo->var.bits_per_pixel, 0); if (viafb_dual_fb) { viafb_update_device_setting(viafbinfo1->var.xres, viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, 1); } else if (viafb_SAMM_ON == 1) { DEBUG_MSG(KERN_INFO "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", viafb_second_xres, viafb_second_yres, viafb_bpp1); viafb_update_device_setting(viafb_second_xres, viafb_second_yres, viafb_bpp1, 1); } refresh = get_var_refresh(&info->var); if (viafb_dual_fb && viapar->iga_path == IGA2) { viafb_bpp1 = info->var.bits_per_pixel; viafb_refresh1 = refresh; } else { viafb_bpp = info->var.bits_per_pixel; viafb_refresh = refresh; } if (info->var.accel_flags & FB_ACCELF_TEXT) info->flags &= ~FBINFO_HWACCEL_DISABLED; else info->flags |= FBINFO_HWACCEL_DISABLED; viafb_setmode(); viafb_pan_display(&info->var, info); return 0;} /* Set one color register */static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,unsigned blue, unsigned transp, struct fb_info *info){ struct viafb_par *viapar = info->par; u32 r, g, b; if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { if (regno > 255) return -EINVAL; if (!viafb_dual_fb || viapar->iga_path == IGA1) viafb_set_primary_color_register(regno, red >> 8, green >> 8, blue >> 8); if (!viafb_dual_fb || viapar->iga_path == IGA2) viafb_set_secondary_color_register(regno, red >> 8, green >> 8, blue >> 8); } else { if (regno > 15) return -EINVAL; r = (red >> (16 - info->var.red.length)) << info->var.red.offset; b = (blue >> (16 - info->var.blue.length)) << info->var.blue.offset; g = (green >> (16 - info->var.green.length)) << info->var.green.offset; ((u32 *) info->pseudo_palette)[regno] = r | g | b; } return 0;} static int viafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct viafb_par *viapar = info->par; u32 vram_addr = viapar->vram_addr + var->yoffset * info->fix.line_length + var->xoffset * info->var.bits_per_pixel / 8; DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); if (!viafb_dual_fb) { via_set_primary_address(vram_addr); via_set_secondary_address(vram_addr); } else if (viapar->iga_path == IGA1) via_set_primary_address(vram_addr); else via_set_secondary_address(vram_addr); return 0;} static int viafb_blank(int blank_mode, struct fb_info *info){ DEBUG_MSG(KERN_INFO "viafb_blank!\n"); /* clear DPMS setting */ switch (blank_mode) { case FB_BLANK_UNBLANK: /* Screen: On, HSync: On, VSync: On */ /* control CRT monitor power management */ via_set_state(VIA_CRT, VIA_STATE_ON); break; case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off, HSync: Off, VSync: On */ /* control CRT monitor power management */ via_set_state(VIA_CRT, VIA_STATE_STANDBY); break; case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off, HSync: On, VSync: Off */ /* control CRT monitor power management */ via_set_state(VIA_CRT, VIA_STATE_SUSPEND); break; case FB_BLANK_POWERDOWN: /* Screen: Off, HSync: Off, VSync: Off */ /* control CRT monitor power management */ via_set_state(VIA_CRT, VIA_STATE_OFF); break; } return 0;} static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg){ union { struct viafb_ioctl_mode viamode; struct viafb_ioctl_samm viasamm; struct viafb_driver_version driver_version; struct fb_var_screeninfo sec_var; struct _panel_size_pos_info panel_pos_size_para; struct viafb_ioctl_setting viafb_setting; struct device_t active_dev; } u; u32 state_info = 0; u32 *viafb_gamma_table; char driver_name[] = "viafb"; u32 __user *argp = (u32 __user *) arg; u32 gpu32; DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n"); memset(&u, 0, sizeof(u)); switch (cmd) { case VIAFB_GET_CHIP_INFO: if (copy_to_user(argp, viaparinfo->chip_info, sizeof(struct chip_information))) return -EFAULT; break; case VIAFB_GET_INFO_SIZE: return put_user((u32)sizeof(struct viafb_ioctl_info), argp); case VIAFB_GET_INFO: return viafb_ioctl_get_viafb_info(arg); case VIAFB_HOTPLUG: return put_user(viafb_ioctl_hotplug(info->var.xres, info->var.yres, info->var.bits_per_pixel), argp); case VIAFB_SET_HOTPLUG_FLAG: if (copy_from_user(&gpu32, argp, sizeof(gpu32))) return -EFAULT; viafb_hotplug = (gpu32) ? 1 : 0; break; case VIAFB_GET_RESOLUTION: u.viamode.xres = (u32) viafb_hotplug_Xres; u.viamode.yres = (u32) viafb_hotplug_Yres; u.viamode.refresh = (u32) viafb_hotplug_refresh; u.viamode.bpp = (u32) viafb_hotplug_bpp; if (viafb_SAMM_ON == 1) { u.viamode.xres_sec = viafb_second_xres; u.viamode.yres_sec = viafb_second_yres; u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual; u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual; u.viamode.refresh_sec = viafb_refresh1; u.viamode.bpp_sec = viafb_bpp1; } else { u.viamode.xres_sec = 0; u.viamode.yres_sec = 0; u.viamode.virtual_xres_sec = 0; u.viamode.virtual_yres_sec = 0; u.viamode.refresh_sec = 0; u.viamode.bpp_sec = 0; } if (copy_to_user(argp, &u.viamode, sizeof(u.viamode))) return -EFAULT; break; case VIAFB_GET_SAMM_INFO: u.viasamm.samm_status = viafb_SAMM_ON; if (viafb_SAMM_ON == 1) { if (viafb_dual_fb) { u.viasamm.size_prim = viaparinfo->fbmem_free; u.viasamm.size_sec = viaparinfo1->fbmem_free; } else { if (viafb_second_size) { u.viasamm.size_prim = viaparinfo->fbmem_free - viafb_second_size * 1024 * 1024; u.viasamm.size_sec = viafb_second_size * 1024 * 1024; } else { u.viasamm.size_prim = viaparinfo->fbmem_free >> 1; u.viasamm.size_sec = (viaparinfo->fbmem_free >> 1); } } u.viasamm.mem_base = viaparinfo->fbmem; u.viasamm.offset_sec = viafb_second_offset; } else { u.viasamm.size_prim = viaparinfo->memsize - viaparinfo->fbmem_used; u.viasamm.size_sec = 0; u.viasamm.mem_base = viaparinfo->fbmem; u.viasamm.offset_sec = 0; } if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm))) return -EFAULT; break; case VIAFB_TURN_ON_OUTPUT_DEVICE: if (copy_from_user(&gpu32, argp, sizeof(gpu32))) return -EFAULT; if (gpu32 & CRT_Device) via_set_state(VIA_CRT, VIA_STATE_ON); if (gpu32 & DVI_Device) viafb_dvi_enable(); if (gpu32 & LCD_Device) viafb_lcd_enable(); break; case VIAFB_TURN_OFF_OUTPUT_DEVICE: if (copy_from_user(&gpu32, argp, sizeof(gpu32))) return -EFAULT; if (gpu32 & CRT_Device) via_set_state(VIA_CRT, VIA_STATE_OFF); if (gpu32 & DVI_Device) viafb_dvi_disable(); if (gpu32 & LCD_Device) viafb_lcd_disable(); break; case VIAFB_GET_DEVICE: u.active_dev.crt = viafb_CRT_ON; u.active_dev.dvi = viafb_DVI_ON;Lines 1–500 of 2148. Load more
// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. */ #include <linux/compiler.h> #include <linux/module.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/stat.h> #include <linux/via-core.h> #include <linux/via_i2c.h> #define _MASTER_FILE #include "global.h" static u32 pseudo_pal[17]; /* video mode */ static char *viafb_mode; static char *viafb_mode1; static int viafb_bpp = 32; static int viafb_bpp1 = 32; static unsigned int viafb_second_offset; static int viafb_second_size; static int viafb_accel = 1; /* Added for specifying active devices.*/ static char *viafb_active_dev; /*Added for specify lcd output port*/ static char *viafb_lcd_port = ""; static char *viafb_dvi_port = ""; static void retrieve_device_setting(struct viafb_ioctl_setting *setting_info); static int viafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static struct fb_ops viafb_ops; /* supported output devices on each IGP * only CX700, VX800, VX855, VX900 were documented * VIA_CRT should be everywhere * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL * source selection on CX700 and later * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c */ static const u32 supported_odev_map[] = { [UNICHROME_CLE266] = VIA_CRT | VIA_LDVP0 | VIA_LDVP1, [UNICHROME_K400] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_K800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_PM800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_CN700] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_CX700] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_CN750] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_K8M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_P4M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_P4M900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_VX800] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_VX855] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, [UNICHROME_VX900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, }; static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth) { var->grayscale = 0; var->red.msb_right = 0; var->green.msb_right = 0; var->blue.msb_right = 0; var->transp.offset = 0; var->transp.length = 0; var->transp.msb_right = 0; var->nonstd = 0; switch (depth) { case 8: var->bits_per_pixel = 8; var->red.offset = 0; var->green.offset = 0; var->blue.offset = 0; var->red.length = 8; var->green.length = 8; var->blue.length = 8; break; case 15: var->bits_per_pixel = 16; var->red.offset = 10; var->green.offset = 5; var->blue.offset = 0; var->red.length = 5; var->green.length = 5; var->blue.length = 5; break; case 16: var->bits_per_pixel = 16; var->red.offset = 11; var->green.offset = 5; var->blue.offset = 0; var->red.length = 5; var->green.length = 6; var->blue.length = 5; break; case 24: var->bits_per_pixel = 32; var->red.offset = 16; var->green.offset = 8; var->blue.offset = 0; var->red.length = 8; var->green.length = 8; var->blue.length = 8; break; case 30: var->bits_per_pixel = 32; var->red.offset = 20; var->green.offset = 10; var->blue.offset = 0; var->red.length = 10; var->green.length = 10; var->blue.length = 10; break; } } static void viafb_update_fix(struct fb_info *info) { u32 bpp = info->var.bits_per_pixel; info->fix.visual = bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8, VIA_PITCH_SIZE); } static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, struct viafb_par *viaparinfo) { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, "Via"); fix->smem_start = viaparinfo->fbmem; fix->smem_len = viaparinfo->fbmem_free; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = FB_VISUAL_TRUECOLOR; fix->xpanstep = fix->ywrapstep = 0; fix->ypanstep = 1; /* Just tell the accel name */ viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME; } static int viafb_open(struct fb_info *info, int user) { DEBUG_MSG(KERN_INFO "viafb_open!\n"); return 0; } static int viafb_release(struct fb_info *info, int user) { DEBUG_MSG(KERN_INFO "viafb_release!\n"); return 0; } static inline int get_var_refresh(struct fb_var_screeninfo *var) { u32 htotal, vtotal; htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal); } static int viafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { int depth, refresh; struct viafb_par *ppar = info->par; u32 line; DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); /* Sanity check */ /* HW neither support interlacte nor double-scaned mode */ if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) return -EINVAL; /* the refresh rate is not important here, as we only want to know * whether the resolution exists */ if (!viafb_get_best_mode(var->xres, var->yres, 60)) { DEBUG_MSG(KERN_INFO "viafb: Mode %dx%dx%d not supported!!\n", var->xres, var->yres, var->bits_per_pixel); return -EINVAL; } depth = fb_get_color_depth(var, &info->fix); if (!depth) depth = var->bits_per_pixel; if (depth < 0 || depth > 32) return -EINVAL; else if (!depth) depth = 24; else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1) depth = 15; else if (depth == 30) depth = 30; else if (depth <= 8) depth = 8; else if (depth <= 16) depth = 16; else depth = 24; viafb_fill_var_color_info(var, depth); if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8, VIA_PITCH_SIZE); if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize) return -EINVAL; /* Based on var passed in to calculate the refresh, * because our driver use some modes special. */ refresh = viafb_get_refresh(var->xres, var->yres, get_var_refresh(var)); /* Adjust var according to our driver's own table */ viafb_fill_var_timing_info(var, viafb_get_best_mode(var->xres, var->yres, refresh)); if (var->accel_flags & FB_ACCELF_TEXT && !ppar->shared->vdev->engine_mmio) var->accel_flags = 0; return 0; } static int viafb_set_par(struct fb_info *info) { struct viafb_par *viapar = info->par; int refresh; DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); viafb_update_fix(info); viapar->depth = fb_get_color_depth(&info->var, &info->fix); viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, viafbinfo->var.bits_per_pixel, 0); if (viafb_dual_fb) { viafb_update_device_setting(viafbinfo1->var.xres, viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, 1); } else if (viafb_SAMM_ON == 1) { DEBUG_MSG(KERN_INFO "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", viafb_second_xres, viafb_second_yres, viafb_bpp1); viafb_update_device_setting(viafb_second_xres, viafb_second_yres, viafb_bpp1, 1); } refresh = get_var_refresh(&info->var); if (viafb_dual_fb && viapar->iga_path == IGA2) { viafb_bpp1 = info->var.bits_per_pixel; viafb_refresh1 = refresh; } else { viafb_bpp = info->var.bits_per_pixel; viafb_refresh = refresh; } if (info->var.accel_flags & FB_ACCELF_TEXT) info->flags &= ~FBINFO_HWACCEL_DISABLED; else info->flags |= FBINFO_HWACCEL_DISABLED; viafb_setmode(); viafb_pan_display(&info->var, info); return 0; } /* Set one color register */ static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { struct viafb_par *viapar = info->par; u32 r, g, b; if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { if (regno > 255) return -EINVAL; if (!viafb_dual_fb || viapar->iga_path == IGA1) viafb_set_primary_color_register(regno, red >> 8, green >> 8, blue >> 8); if (!viafb_dual_fb || viapar->iga_path == IGA2) viafb_set_secondary_color_register(regno, red >> 8, green >> 8, blue >> 8); } else { if (regno > 15) return -EINVAL; r = (red >> (16 - info->var.red.length)) << info->var.red.offset; b = (blue >> (16 - info->var.blue.length)) << info->var.blue.offset; g = (green >> (16 - info->var.green.length)) << info->var.green.offset; ((u32 *) info->pseudo_palette)[regno] = r | g | b; } return 0; } static int viafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct viafb_par *viapar = info->par; u32 vram_addr = viapar->vram_addr + var->yoffset * info->fix.line_length + var->xoffset * info->var.bits_per_pixel / 8; DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); if (!viafb_dual_fb) { via_set_primary_address(vram_addr); via_set_secondary_address(vram_addr); } else if (viapar->iga_path == IGA1) via_set_primary_address(vram_addr); else via_set_secondary_address(vram_addr); return 0; } static int viafb_blank(int blank_mode, struct fb_info *info) { DEBUG_MSG(KERN_INFO "viafb_blank!\n"); /* clear DPMS setting */ switch (blank_mode) { case FB_BLANK_UNBLANK: /* Screen: On, HSync: On, VSync: On */ /* control CRT monitor power management */ via_set_state(VIA_CRT, VIA_STATE_ON); break; case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off, HSync: Off, VSync: On */ /* control CRT monitor power management */ via_set_state(VIA_CRT, VIA_STATE_STANDBY); break; case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off, HSync: On, VSync: Off */ /* control CRT monitor power management */ via_set_state(VIA_CRT, VIA_STATE_SUSPEND); break; case FB_BLANK_POWERDOWN: /* Screen: Off, HSync: Off, VSync: Off */ /* control CRT monitor power management */ via_set_state(VIA_CRT, VIA_STATE_OFF); break; } return 0; } static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) { union { struct viafb_ioctl_mode viamode; struct viafb_ioctl_samm viasamm; struct viafb_driver_version driver_version; struct fb_var_screeninfo sec_var; struct _panel_size_pos_info panel_pos_size_para; struct viafb_ioctl_setting viafb_setting; struct device_t active_dev; } u; u32 state_info = 0; u32 *viafb_gamma_table; char driver_name[] = "viafb"; u32 __user *argp = (u32 __user *) arg; u32 gpu32; DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n"); memset(&u, 0, sizeof(u)); switch (cmd) { case VIAFB_GET_CHIP_INFO: if (copy_to_user(argp, viaparinfo->chip_info, sizeof(struct chip_information))) return -EFAULT; break; case VIAFB_GET_INFO_SIZE: return put_user((u32)sizeof(struct viafb_ioctl_info), argp); case VIAFB_GET_INFO: return viafb_ioctl_get_viafb_info(arg); case VIAFB_HOTPLUG: return put_user(viafb_ioctl_hotplug(info->var.xres, info->var.yres, info->var.bits_per_pixel), argp); case VIAFB_SET_HOTPLUG_FLAG: if (copy_from_user(&gpu32, argp, sizeof(gpu32))) return -EFAULT; viafb_hotplug = (gpu32) ? 1 : 0; break; case VIAFB_GET_RESOLUTION: u.viamode.xres = (u32) viafb_hotplug_Xres; u.viamode.yres = (u32) viafb_hotplug_Yres; u.viamode.refresh = (u32) viafb_hotplug_refresh; u.viamode.bpp = (u32) viafb_hotplug_bpp; if (viafb_SAMM_ON == 1) { u.viamode.xres_sec = viafb_second_xres; u.viamode.yres_sec = viafb_second_yres; u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual; u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual; u.viamode.refresh_sec = viafb_refresh1; u.viamode.bpp_sec = viafb_bpp1; } else { u.viamode.xres_sec = 0; u.viamode.yres_sec = 0; u.viamode.virtual_xres_sec = 0; u.viamode.virtual_yres_sec = 0; u.viamode.refresh_sec = 0; u.viamode.bpp_sec = 0; } if (copy_to_user(argp, &u.viamode, sizeof(u.viamode))) return -EFAULT; break; case VIAFB_GET_SAMM_INFO: u.viasamm.samm_status = viafb_SAMM_ON; if (viafb_SAMM_ON == 1) { if (viafb_dual_fb) { u.viasamm.size_prim = viaparinfo->fbmem_free; u.viasamm.size_sec = viaparinfo1->fbmem_free; } else { if (viafb_second_size) { u.viasamm.size_prim = viaparinfo->fbmem_free - viafb_second_size * 1024 * 1024; u.viasamm.size_sec = viafb_second_size * 1024 * 1024; } else { u.viasamm.size_prim = viaparinfo->fbmem_free >> 1; u.viasamm.size_sec = (viaparinfo->fbmem_free >> 1); } } u.viasamm.mem_base = viaparinfo->fbmem; u.viasamm.offset_sec = viafb_second_offset; } else { u.viasamm.size_prim = viaparinfo->memsize - viaparinfo->fbmem_used; u.viasamm.size_sec = 0; u.viasamm.mem_base = viaparinfo->fbmem; u.viasamm.offset_sec = 0; } if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm))) return -EFAULT; break; case VIAFB_TURN_ON_OUTPUT_DEVICE: if (copy_from_user(&gpu32, argp, sizeof(gpu32))) return -EFAULT; if (gpu32 & CRT_Device) via_set_state(VIA_CRT, VIA_STATE_ON); if (gpu32 & DVI_Device) viafb_dvi_enable(); if (gpu32 & LCD_Device) viafb_lcd_enable(); break; case VIAFB_TURN_OFF_OUTPUT_DEVICE: if (copy_from_user(&gpu32, argp, sizeof(gpu32))) return -EFAULT; if (gpu32 & CRT_Device) via_set_state(VIA_CRT, VIA_STATE_OFF); if (gpu32 & DVI_Device) viafb_dvi_disable(); if (gpu32 & LCD_Device) viafb_lcd_disable(); break; case VIAFB_GET_DEVICE: u.active_dev.crt = viafb_CRT_ON; u.active_dev.dvi = viafb_DVI_ON;