1f7018c21STomi Valkeinen /* 2f7018c21STomi Valkeinen * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. 3f7018c21STomi Valkeinen * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. 4f7018c21STomi Valkeinen 5f7018c21STomi Valkeinen * This program is free software; you can redistribute it and/or 6f7018c21STomi Valkeinen * modify it under the terms of the GNU General Public 7f7018c21STomi Valkeinen * License as published by the Free Software Foundation; 8f7018c21STomi Valkeinen * either version 2, or (at your option) any later version. 9f7018c21STomi Valkeinen 10f7018c21STomi Valkeinen * This program is distributed in the hope that it will be useful, 11f7018c21STomi Valkeinen * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even 12f7018c21STomi Valkeinen * the implied warranty of MERCHANTABILITY or FITNESS FOR 13f7018c21STomi Valkeinen * A PARTICULAR PURPOSE.See the GNU General Public License 14f7018c21STomi Valkeinen * for more details. 15f7018c21STomi Valkeinen 16f7018c21STomi Valkeinen * You should have received a copy of the GNU General Public License 17f7018c21STomi Valkeinen * along with this program; if not, write to the Free Software 18f7018c21STomi Valkeinen * Foundation, Inc., 19f7018c21STomi Valkeinen * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20f7018c21STomi Valkeinen */ 21f7018c21STomi Valkeinen 22b6566b47SRandy Dunlap #include <linux/compiler.h> 23f7018c21STomi Valkeinen #include <linux/module.h> 24f7018c21STomi Valkeinen #include <linux/seq_file.h> 25f7018c21STomi Valkeinen #include <linux/slab.h> 26f7018c21STomi Valkeinen #include <linux/stat.h> 27f7018c21STomi Valkeinen #include <linux/via-core.h> 28f7018c21STomi Valkeinen #include <linux/via_i2c.h> 29f7018c21STomi Valkeinen 30f7018c21STomi Valkeinen #define _MASTER_FILE 31f7018c21STomi Valkeinen #include "global.h" 32f7018c21STomi Valkeinen 33f7018c21STomi Valkeinen static char *viafb_name = "Via"; 34f7018c21STomi Valkeinen static u32 pseudo_pal[17]; 35f7018c21STomi Valkeinen 36f7018c21STomi Valkeinen /* video mode */ 37f7018c21STomi Valkeinen static char *viafb_mode; 38f7018c21STomi Valkeinen static char *viafb_mode1; 39f7018c21STomi Valkeinen static int viafb_bpp = 32; 40f7018c21STomi Valkeinen static int viafb_bpp1 = 32; 41f7018c21STomi Valkeinen 42f7018c21STomi Valkeinen static unsigned int viafb_second_offset; 43f7018c21STomi Valkeinen static int viafb_second_size; 44f7018c21STomi Valkeinen 45f7018c21STomi Valkeinen static int viafb_accel = 1; 46f7018c21STomi Valkeinen 47f7018c21STomi Valkeinen /* Added for specifying active devices.*/ 48f7018c21STomi Valkeinen static char *viafb_active_dev; 49f7018c21STomi Valkeinen 50f7018c21STomi Valkeinen /*Added for specify lcd output port*/ 51f7018c21STomi Valkeinen static char *viafb_lcd_port = ""; 52f7018c21STomi Valkeinen static char *viafb_dvi_port = ""; 53f7018c21STomi Valkeinen 54f7018c21STomi Valkeinen static void retrieve_device_setting(struct viafb_ioctl_setting 55f7018c21STomi Valkeinen *setting_info); 56f7018c21STomi Valkeinen static int viafb_pan_display(struct fb_var_screeninfo *var, 57f7018c21STomi Valkeinen struct fb_info *info); 58f7018c21STomi Valkeinen 59f7018c21STomi Valkeinen static struct fb_ops viafb_ops; 60f7018c21STomi Valkeinen 61f7018c21STomi Valkeinen /* supported output devices on each IGP 62f7018c21STomi Valkeinen * only CX700, VX800, VX855, VX900 were documented 63f7018c21STomi Valkeinen * VIA_CRT should be everywhere 64f7018c21STomi Valkeinen * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL 65f7018c21STomi Valkeinen * source selection on CX700 and later 66f7018c21STomi Valkeinen * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c 67f7018c21STomi Valkeinen */ 68f7018c21STomi Valkeinen static const u32 supported_odev_map[] = { 69f7018c21STomi Valkeinen [UNICHROME_CLE266] = VIA_CRT | VIA_LDVP0 | VIA_LDVP1, 70f7018c21STomi Valkeinen [UNICHROME_K400] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 71f7018c21STomi Valkeinen | VIA_LVDS2, 72f7018c21STomi Valkeinen [UNICHROME_K800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 73f7018c21STomi Valkeinen | VIA_LVDS2, 74f7018c21STomi Valkeinen [UNICHROME_PM800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 75f7018c21STomi Valkeinen | VIA_LVDS2, 76f7018c21STomi Valkeinen [UNICHROME_CN700] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1 77f7018c21STomi Valkeinen | VIA_LVDS2, 78f7018c21STomi Valkeinen [UNICHROME_CX700] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, 79f7018c21STomi Valkeinen [UNICHROME_CN750] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, 80f7018c21STomi Valkeinen [UNICHROME_K8M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, 81f7018c21STomi Valkeinen [UNICHROME_P4M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, 82f7018c21STomi Valkeinen [UNICHROME_P4M900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, 83f7018c21STomi Valkeinen [UNICHROME_VX800] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, 84f7018c21STomi Valkeinen [UNICHROME_VX855] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, 85f7018c21STomi Valkeinen [UNICHROME_VX900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2, 86f7018c21STomi Valkeinen }; 87f7018c21STomi Valkeinen 88f7018c21STomi Valkeinen static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth) 89f7018c21STomi Valkeinen { 90f7018c21STomi Valkeinen var->grayscale = 0; 91f7018c21STomi Valkeinen var->red.msb_right = 0; 92f7018c21STomi Valkeinen var->green.msb_right = 0; 93f7018c21STomi Valkeinen var->blue.msb_right = 0; 94f7018c21STomi Valkeinen var->transp.offset = 0; 95f7018c21STomi Valkeinen var->transp.length = 0; 96f7018c21STomi Valkeinen var->transp.msb_right = 0; 97f7018c21STomi Valkeinen var->nonstd = 0; 98f7018c21STomi Valkeinen switch (depth) { 99f7018c21STomi Valkeinen case 8: 100f7018c21STomi Valkeinen var->bits_per_pixel = 8; 101f7018c21STomi Valkeinen var->red.offset = 0; 102f7018c21STomi Valkeinen var->green.offset = 0; 103f7018c21STomi Valkeinen var->blue.offset = 0; 104f7018c21STomi Valkeinen var->red.length = 8; 105f7018c21STomi Valkeinen var->green.length = 8; 106f7018c21STomi Valkeinen var->blue.length = 8; 107f7018c21STomi Valkeinen break; 108f7018c21STomi Valkeinen case 15: 109f7018c21STomi Valkeinen var->bits_per_pixel = 16; 110f7018c21STomi Valkeinen var->red.offset = 10; 111f7018c21STomi Valkeinen var->green.offset = 5; 112f7018c21STomi Valkeinen var->blue.offset = 0; 113f7018c21STomi Valkeinen var->red.length = 5; 114f7018c21STomi Valkeinen var->green.length = 5; 115f7018c21STomi Valkeinen var->blue.length = 5; 116f7018c21STomi Valkeinen break; 117f7018c21STomi Valkeinen case 16: 118f7018c21STomi Valkeinen var->bits_per_pixel = 16; 119f7018c21STomi Valkeinen var->red.offset = 11; 120f7018c21STomi Valkeinen var->green.offset = 5; 121f7018c21STomi Valkeinen var->blue.offset = 0; 122f7018c21STomi Valkeinen var->red.length = 5; 123f7018c21STomi Valkeinen var->green.length = 6; 124f7018c21STomi Valkeinen var->blue.length = 5; 125f7018c21STomi Valkeinen break; 126f7018c21STomi Valkeinen case 24: 127f7018c21STomi Valkeinen var->bits_per_pixel = 32; 128f7018c21STomi Valkeinen var->red.offset = 16; 129f7018c21STomi Valkeinen var->green.offset = 8; 130f7018c21STomi Valkeinen var->blue.offset = 0; 131f7018c21STomi Valkeinen var->red.length = 8; 132f7018c21STomi Valkeinen var->green.length = 8; 133f7018c21STomi Valkeinen var->blue.length = 8; 134f7018c21STomi Valkeinen break; 135f7018c21STomi Valkeinen case 30: 136f7018c21STomi Valkeinen var->bits_per_pixel = 32; 137f7018c21STomi Valkeinen var->red.offset = 20; 138f7018c21STomi Valkeinen var->green.offset = 10; 139f7018c21STomi Valkeinen var->blue.offset = 0; 140f7018c21STomi Valkeinen var->red.length = 10; 141f7018c21STomi Valkeinen var->green.length = 10; 142f7018c21STomi Valkeinen var->blue.length = 10; 143f7018c21STomi Valkeinen break; 144f7018c21STomi Valkeinen } 145f7018c21STomi Valkeinen } 146f7018c21STomi Valkeinen 147f7018c21STomi Valkeinen static void viafb_update_fix(struct fb_info *info) 148f7018c21STomi Valkeinen { 149f7018c21STomi Valkeinen u32 bpp = info->var.bits_per_pixel; 150f7018c21STomi Valkeinen 151f7018c21STomi Valkeinen info->fix.visual = 152f7018c21STomi Valkeinen bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 153f7018c21STomi Valkeinen info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8, 154f7018c21STomi Valkeinen VIA_PITCH_SIZE); 155f7018c21STomi Valkeinen } 156f7018c21STomi Valkeinen 157f7018c21STomi Valkeinen static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, 158f7018c21STomi Valkeinen struct viafb_par *viaparinfo) 159f7018c21STomi Valkeinen { 160f7018c21STomi Valkeinen memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 161f7018c21STomi Valkeinen strcpy(fix->id, viafb_name); 162f7018c21STomi Valkeinen 163f7018c21STomi Valkeinen fix->smem_start = viaparinfo->fbmem; 164f7018c21STomi Valkeinen fix->smem_len = viaparinfo->fbmem_free; 165f7018c21STomi Valkeinen 166f7018c21STomi Valkeinen fix->type = FB_TYPE_PACKED_PIXELS; 167f7018c21STomi Valkeinen fix->type_aux = 0; 168f7018c21STomi Valkeinen fix->visual = FB_VISUAL_TRUECOLOR; 169f7018c21STomi Valkeinen 170f7018c21STomi Valkeinen fix->xpanstep = fix->ywrapstep = 0; 171f7018c21STomi Valkeinen fix->ypanstep = 1; 172f7018c21STomi Valkeinen 173f7018c21STomi Valkeinen /* Just tell the accel name */ 174f7018c21STomi Valkeinen viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME; 175f7018c21STomi Valkeinen } 176f7018c21STomi Valkeinen static int viafb_open(struct fb_info *info, int user) 177f7018c21STomi Valkeinen { 178f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_open!\n"); 179f7018c21STomi Valkeinen return 0; 180f7018c21STomi Valkeinen } 181f7018c21STomi Valkeinen 182f7018c21STomi Valkeinen static int viafb_release(struct fb_info *info, int user) 183f7018c21STomi Valkeinen { 184f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_release!\n"); 185f7018c21STomi Valkeinen return 0; 186f7018c21STomi Valkeinen } 187f7018c21STomi Valkeinen 188f7018c21STomi Valkeinen static inline int get_var_refresh(struct fb_var_screeninfo *var) 189f7018c21STomi Valkeinen { 190f7018c21STomi Valkeinen u32 htotal, vtotal; 191f7018c21STomi Valkeinen 192f7018c21STomi Valkeinen htotal = var->left_margin + var->xres + var->right_margin 193f7018c21STomi Valkeinen + var->hsync_len; 194f7018c21STomi Valkeinen vtotal = var->upper_margin + var->yres + var->lower_margin 195f7018c21STomi Valkeinen + var->vsync_len; 196f7018c21STomi Valkeinen return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal); 197f7018c21STomi Valkeinen } 198f7018c21STomi Valkeinen 199f7018c21STomi Valkeinen static int viafb_check_var(struct fb_var_screeninfo *var, 200f7018c21STomi Valkeinen struct fb_info *info) 201f7018c21STomi Valkeinen { 202f7018c21STomi Valkeinen int depth, refresh; 203f7018c21STomi Valkeinen struct viafb_par *ppar = info->par; 204f7018c21STomi Valkeinen u32 line; 205f7018c21STomi Valkeinen 206f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); 207f7018c21STomi Valkeinen /* Sanity check */ 208f7018c21STomi Valkeinen /* HW neither support interlacte nor double-scaned mode */ 209f7018c21STomi Valkeinen if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) 210f7018c21STomi Valkeinen return -EINVAL; 211f7018c21STomi Valkeinen 212f7018c21STomi Valkeinen /* the refresh rate is not important here, as we only want to know 213f7018c21STomi Valkeinen * whether the resolution exists 214f7018c21STomi Valkeinen */ 215f7018c21STomi Valkeinen if (!viafb_get_best_mode(var->xres, var->yres, 60)) { 216f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO 217f7018c21STomi Valkeinen "viafb: Mode %dx%dx%d not supported!!\n", 218f7018c21STomi Valkeinen var->xres, var->yres, var->bits_per_pixel); 219f7018c21STomi Valkeinen return -EINVAL; 220f7018c21STomi Valkeinen } 221f7018c21STomi Valkeinen 222f7018c21STomi Valkeinen depth = fb_get_color_depth(var, &info->fix); 223f7018c21STomi Valkeinen if (!depth) 224f7018c21STomi Valkeinen depth = var->bits_per_pixel; 225f7018c21STomi Valkeinen 226f7018c21STomi Valkeinen if (depth < 0 || depth > 32) 227f7018c21STomi Valkeinen return -EINVAL; 228f7018c21STomi Valkeinen else if (!depth) 229f7018c21STomi Valkeinen depth = 24; 230f7018c21STomi Valkeinen else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1) 231f7018c21STomi Valkeinen depth = 15; 232f7018c21STomi Valkeinen else if (depth == 30) 233f7018c21STomi Valkeinen depth = 30; 234f7018c21STomi Valkeinen else if (depth <= 8) 235f7018c21STomi Valkeinen depth = 8; 236f7018c21STomi Valkeinen else if (depth <= 16) 237f7018c21STomi Valkeinen depth = 16; 238f7018c21STomi Valkeinen else 239f7018c21STomi Valkeinen depth = 24; 240f7018c21STomi Valkeinen 241f7018c21STomi Valkeinen viafb_fill_var_color_info(var, depth); 242f7018c21STomi Valkeinen if (var->xres_virtual < var->xres) 243f7018c21STomi Valkeinen var->xres_virtual = var->xres; 244f7018c21STomi Valkeinen 245f7018c21STomi Valkeinen line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8, 246f7018c21STomi Valkeinen VIA_PITCH_SIZE); 247f7018c21STomi Valkeinen if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize) 248f7018c21STomi Valkeinen return -EINVAL; 249f7018c21STomi Valkeinen 250f7018c21STomi Valkeinen /* Based on var passed in to calculate the refresh, 251f7018c21STomi Valkeinen * because our driver use some modes special. 252f7018c21STomi Valkeinen */ 253f7018c21STomi Valkeinen refresh = viafb_get_refresh(var->xres, var->yres, 254f7018c21STomi Valkeinen get_var_refresh(var)); 255f7018c21STomi Valkeinen 256f7018c21STomi Valkeinen /* Adjust var according to our driver's own table */ 257f7018c21STomi Valkeinen viafb_fill_var_timing_info(var, 258f7018c21STomi Valkeinen viafb_get_best_mode(var->xres, var->yres, refresh)); 259f7018c21STomi Valkeinen if (var->accel_flags & FB_ACCELF_TEXT && 260f7018c21STomi Valkeinen !ppar->shared->vdev->engine_mmio) 261f7018c21STomi Valkeinen var->accel_flags = 0; 262f7018c21STomi Valkeinen 263f7018c21STomi Valkeinen return 0; 264f7018c21STomi Valkeinen } 265f7018c21STomi Valkeinen 266f7018c21STomi Valkeinen static int viafb_set_par(struct fb_info *info) 267f7018c21STomi Valkeinen { 268f7018c21STomi Valkeinen struct viafb_par *viapar = info->par; 269f7018c21STomi Valkeinen int refresh; 270f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); 271f7018c21STomi Valkeinen 272f7018c21STomi Valkeinen viafb_update_fix(info); 273f7018c21STomi Valkeinen viapar->depth = fb_get_color_depth(&info->var, &info->fix); 274f7018c21STomi Valkeinen viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, 275f7018c21STomi Valkeinen viafbinfo->var.bits_per_pixel, 0); 276f7018c21STomi Valkeinen 277f7018c21STomi Valkeinen if (viafb_dual_fb) { 278f7018c21STomi Valkeinen viafb_update_device_setting(viafbinfo1->var.xres, 279f7018c21STomi Valkeinen viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, 280f7018c21STomi Valkeinen 1); 281f7018c21STomi Valkeinen } else if (viafb_SAMM_ON == 1) { 282f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO 283f7018c21STomi Valkeinen "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", 284f7018c21STomi Valkeinen viafb_second_xres, viafb_second_yres, viafb_bpp1); 285f7018c21STomi Valkeinen 286f7018c21STomi Valkeinen viafb_update_device_setting(viafb_second_xres, 287f7018c21STomi Valkeinen viafb_second_yres, viafb_bpp1, 1); 288f7018c21STomi Valkeinen } 289f7018c21STomi Valkeinen 290f7018c21STomi Valkeinen refresh = get_var_refresh(&info->var); 291f7018c21STomi Valkeinen if (viafb_dual_fb && viapar->iga_path == IGA2) { 292f7018c21STomi Valkeinen viafb_bpp1 = info->var.bits_per_pixel; 293f7018c21STomi Valkeinen viafb_refresh1 = refresh; 294f7018c21STomi Valkeinen } else { 295f7018c21STomi Valkeinen viafb_bpp = info->var.bits_per_pixel; 296f7018c21STomi Valkeinen viafb_refresh = refresh; 297f7018c21STomi Valkeinen } 298f7018c21STomi Valkeinen 299f7018c21STomi Valkeinen if (info->var.accel_flags & FB_ACCELF_TEXT) 300f7018c21STomi Valkeinen info->flags &= ~FBINFO_HWACCEL_DISABLED; 301f7018c21STomi Valkeinen else 302f7018c21STomi Valkeinen info->flags |= FBINFO_HWACCEL_DISABLED; 303f7018c21STomi Valkeinen viafb_setmode(); 304f7018c21STomi Valkeinen viafb_pan_display(&info->var, info); 305f7018c21STomi Valkeinen 306f7018c21STomi Valkeinen return 0; 307f7018c21STomi Valkeinen } 308f7018c21STomi Valkeinen 309f7018c21STomi Valkeinen /* Set one color register */ 310f7018c21STomi Valkeinen static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, 311f7018c21STomi Valkeinen unsigned blue, unsigned transp, struct fb_info *info) 312f7018c21STomi Valkeinen { 313f7018c21STomi Valkeinen struct viafb_par *viapar = info->par; 314f7018c21STomi Valkeinen u32 r, g, b; 315f7018c21STomi Valkeinen 316f7018c21STomi Valkeinen if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { 317f7018c21STomi Valkeinen if (regno > 255) 318f7018c21STomi Valkeinen return -EINVAL; 319f7018c21STomi Valkeinen 320f7018c21STomi Valkeinen if (!viafb_dual_fb || viapar->iga_path == IGA1) 321f7018c21STomi Valkeinen viafb_set_primary_color_register(regno, red >> 8, 322f7018c21STomi Valkeinen green >> 8, blue >> 8); 323f7018c21STomi Valkeinen 324f7018c21STomi Valkeinen if (!viafb_dual_fb || viapar->iga_path == IGA2) 325f7018c21STomi Valkeinen viafb_set_secondary_color_register(regno, red >> 8, 326f7018c21STomi Valkeinen green >> 8, blue >> 8); 327f7018c21STomi Valkeinen } else { 328f7018c21STomi Valkeinen if (regno > 15) 329f7018c21STomi Valkeinen return -EINVAL; 330f7018c21STomi Valkeinen 331f7018c21STomi Valkeinen r = (red >> (16 - info->var.red.length)) 332f7018c21STomi Valkeinen << info->var.red.offset; 333f7018c21STomi Valkeinen b = (blue >> (16 - info->var.blue.length)) 334f7018c21STomi Valkeinen << info->var.blue.offset; 335f7018c21STomi Valkeinen g = (green >> (16 - info->var.green.length)) 336f7018c21STomi Valkeinen << info->var.green.offset; 337f7018c21STomi Valkeinen ((u32 *) info->pseudo_palette)[regno] = r | g | b; 338f7018c21STomi Valkeinen } 339f7018c21STomi Valkeinen 340f7018c21STomi Valkeinen return 0; 341f7018c21STomi Valkeinen } 342f7018c21STomi Valkeinen 343f7018c21STomi Valkeinen static int viafb_pan_display(struct fb_var_screeninfo *var, 344f7018c21STomi Valkeinen struct fb_info *info) 345f7018c21STomi Valkeinen { 346f7018c21STomi Valkeinen struct viafb_par *viapar = info->par; 347f7018c21STomi Valkeinen u32 vram_addr = viapar->vram_addr 348f7018c21STomi Valkeinen + var->yoffset * info->fix.line_length 349f7018c21STomi Valkeinen + var->xoffset * info->var.bits_per_pixel / 8; 350f7018c21STomi Valkeinen 351f7018c21STomi Valkeinen DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); 352f7018c21STomi Valkeinen if (!viafb_dual_fb) { 353f7018c21STomi Valkeinen via_set_primary_address(vram_addr); 354f7018c21STomi Valkeinen via_set_secondary_address(vram_addr); 355f7018c21STomi Valkeinen } else if (viapar->iga_path == IGA1) 356f7018c21STomi Valkeinen via_set_primary_address(vram_addr); 357f7018c21STomi Valkeinen else 358f7018c21STomi Valkeinen via_set_secondary_address(vram_addr); 359f7018c21STomi Valkeinen 360f7018c21STomi Valkeinen return 0; 361f7018c21STomi Valkeinen } 362f7018c21STomi Valkeinen 363f7018c21STomi Valkeinen static int viafb_blank(int blank_mode, struct fb_info *info) 364f7018c21STomi Valkeinen { 365f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_blank!\n"); 366f7018c21STomi Valkeinen /* clear DPMS setting */ 367f7018c21STomi Valkeinen 368f7018c21STomi Valkeinen switch (blank_mode) { 369f7018c21STomi Valkeinen case FB_BLANK_UNBLANK: 370f7018c21STomi Valkeinen /* Screen: On, HSync: On, VSync: On */ 371f7018c21STomi Valkeinen /* control CRT monitor power management */ 372f7018c21STomi Valkeinen via_set_state(VIA_CRT, VIA_STATE_ON); 373f7018c21STomi Valkeinen break; 374f7018c21STomi Valkeinen case FB_BLANK_HSYNC_SUSPEND: 375f7018c21STomi Valkeinen /* Screen: Off, HSync: Off, VSync: On */ 376f7018c21STomi Valkeinen /* control CRT monitor power management */ 377f7018c21STomi Valkeinen via_set_state(VIA_CRT, VIA_STATE_STANDBY); 378f7018c21STomi Valkeinen break; 379f7018c21STomi Valkeinen case FB_BLANK_VSYNC_SUSPEND: 380f7018c21STomi Valkeinen /* Screen: Off, HSync: On, VSync: Off */ 381f7018c21STomi Valkeinen /* control CRT monitor power management */ 382f7018c21STomi Valkeinen via_set_state(VIA_CRT, VIA_STATE_SUSPEND); 383f7018c21STomi Valkeinen break; 384f7018c21STomi Valkeinen case FB_BLANK_POWERDOWN: 385f7018c21STomi Valkeinen /* Screen: Off, HSync: Off, VSync: Off */ 386f7018c21STomi Valkeinen /* control CRT monitor power management */ 387f7018c21STomi Valkeinen via_set_state(VIA_CRT, VIA_STATE_OFF); 388f7018c21STomi Valkeinen break; 389f7018c21STomi Valkeinen } 390f7018c21STomi Valkeinen 391f7018c21STomi Valkeinen return 0; 392f7018c21STomi Valkeinen } 393f7018c21STomi Valkeinen 394f7018c21STomi Valkeinen static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) 395f7018c21STomi Valkeinen { 396f7018c21STomi Valkeinen union { 397f7018c21STomi Valkeinen struct viafb_ioctl_mode viamode; 398f7018c21STomi Valkeinen struct viafb_ioctl_samm viasamm; 399f7018c21STomi Valkeinen struct viafb_driver_version driver_version; 400f7018c21STomi Valkeinen struct fb_var_screeninfo sec_var; 401f7018c21STomi Valkeinen struct _panel_size_pos_info panel_pos_size_para; 402f7018c21STomi Valkeinen struct viafb_ioctl_setting viafb_setting; 403f7018c21STomi Valkeinen struct device_t active_dev; 404f7018c21STomi Valkeinen } u; 405f7018c21STomi Valkeinen u32 state_info = 0; 406f7018c21STomi Valkeinen u32 *viafb_gamma_table; 407f7018c21STomi Valkeinen char driver_name[] = "viafb"; 408f7018c21STomi Valkeinen 409f7018c21STomi Valkeinen u32 __user *argp = (u32 __user *) arg; 410f7018c21STomi Valkeinen u32 gpu32; 411f7018c21STomi Valkeinen 412f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); 413f7018c21STomi Valkeinen printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n"); 414f7018c21STomi Valkeinen memset(&u, 0, sizeof(u)); 415f7018c21STomi Valkeinen 416f7018c21STomi Valkeinen switch (cmd) { 417f7018c21STomi Valkeinen case VIAFB_GET_CHIP_INFO: 418f7018c21STomi Valkeinen if (copy_to_user(argp, viaparinfo->chip_info, 419f7018c21STomi Valkeinen sizeof(struct chip_information))) 420f7018c21STomi Valkeinen return -EFAULT; 421f7018c21STomi Valkeinen break; 422f7018c21STomi Valkeinen case VIAFB_GET_INFO_SIZE: 423f7018c21STomi Valkeinen return put_user((u32)sizeof(struct viafb_ioctl_info), argp); 424f7018c21STomi Valkeinen case VIAFB_GET_INFO: 425f7018c21STomi Valkeinen return viafb_ioctl_get_viafb_info(arg); 426f7018c21STomi Valkeinen case VIAFB_HOTPLUG: 427f7018c21STomi Valkeinen return put_user(viafb_ioctl_hotplug(info->var.xres, 428f7018c21STomi Valkeinen info->var.yres, 429f7018c21STomi Valkeinen info->var.bits_per_pixel), argp); 430f7018c21STomi Valkeinen case VIAFB_SET_HOTPLUG_FLAG: 431f7018c21STomi Valkeinen if (copy_from_user(&gpu32, argp, sizeof(gpu32))) 432f7018c21STomi Valkeinen return -EFAULT; 433f7018c21STomi Valkeinen viafb_hotplug = (gpu32) ? 1 : 0; 434f7018c21STomi Valkeinen break; 435f7018c21STomi Valkeinen case VIAFB_GET_RESOLUTION: 436f7018c21STomi Valkeinen u.viamode.xres = (u32) viafb_hotplug_Xres; 437f7018c21STomi Valkeinen u.viamode.yres = (u32) viafb_hotplug_Yres; 438f7018c21STomi Valkeinen u.viamode.refresh = (u32) viafb_hotplug_refresh; 439f7018c21STomi Valkeinen u.viamode.bpp = (u32) viafb_hotplug_bpp; 440f7018c21STomi Valkeinen if (viafb_SAMM_ON == 1) { 441f7018c21STomi Valkeinen u.viamode.xres_sec = viafb_second_xres; 442f7018c21STomi Valkeinen u.viamode.yres_sec = viafb_second_yres; 443f7018c21STomi Valkeinen u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual; 444f7018c21STomi Valkeinen u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual; 445f7018c21STomi Valkeinen u.viamode.refresh_sec = viafb_refresh1; 446f7018c21STomi Valkeinen u.viamode.bpp_sec = viafb_bpp1; 447f7018c21STomi Valkeinen } else { 448f7018c21STomi Valkeinen u.viamode.xres_sec = 0; 449f7018c21STomi Valkeinen u.viamode.yres_sec = 0; 450f7018c21STomi Valkeinen u.viamode.virtual_xres_sec = 0; 451f7018c21STomi Valkeinen u.viamode.virtual_yres_sec = 0; 452f7018c21STomi Valkeinen u.viamode.refresh_sec = 0; 453f7018c21STomi Valkeinen u.viamode.bpp_sec = 0; 454f7018c21STomi Valkeinen } 455f7018c21STomi Valkeinen if (copy_to_user(argp, &u.viamode, sizeof(u.viamode))) 456f7018c21STomi Valkeinen return -EFAULT; 457f7018c21STomi Valkeinen break; 458f7018c21STomi Valkeinen case VIAFB_GET_SAMM_INFO: 459f7018c21STomi Valkeinen u.viasamm.samm_status = viafb_SAMM_ON; 460f7018c21STomi Valkeinen 461f7018c21STomi Valkeinen if (viafb_SAMM_ON == 1) { 462f7018c21STomi Valkeinen if (viafb_dual_fb) { 463f7018c21STomi Valkeinen u.viasamm.size_prim = viaparinfo->fbmem_free; 464f7018c21STomi Valkeinen u.viasamm.size_sec = viaparinfo1->fbmem_free; 465f7018c21STomi Valkeinen } else { 466f7018c21STomi Valkeinen if (viafb_second_size) { 467f7018c21STomi Valkeinen u.viasamm.size_prim = 468f7018c21STomi Valkeinen viaparinfo->fbmem_free - 469f7018c21STomi Valkeinen viafb_second_size * 1024 * 1024; 470f7018c21STomi Valkeinen u.viasamm.size_sec = 471f7018c21STomi Valkeinen viafb_second_size * 1024 * 1024; 472f7018c21STomi Valkeinen } else { 473f7018c21STomi Valkeinen u.viasamm.size_prim = 474f7018c21STomi Valkeinen viaparinfo->fbmem_free >> 1; 475f7018c21STomi Valkeinen u.viasamm.size_sec = 476f7018c21STomi Valkeinen (viaparinfo->fbmem_free >> 1); 477f7018c21STomi Valkeinen } 478f7018c21STomi Valkeinen } 479f7018c21STomi Valkeinen u.viasamm.mem_base = viaparinfo->fbmem; 480f7018c21STomi Valkeinen u.viasamm.offset_sec = viafb_second_offset; 481f7018c21STomi Valkeinen } else { 482f7018c21STomi Valkeinen u.viasamm.size_prim = 483f7018c21STomi Valkeinen viaparinfo->memsize - viaparinfo->fbmem_used; 484f7018c21STomi Valkeinen u.viasamm.size_sec = 0; 485f7018c21STomi Valkeinen u.viasamm.mem_base = viaparinfo->fbmem; 486f7018c21STomi Valkeinen u.viasamm.offset_sec = 0; 487f7018c21STomi Valkeinen } 488f7018c21STomi Valkeinen 489f7018c21STomi Valkeinen if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm))) 490f7018c21STomi Valkeinen return -EFAULT; 491f7018c21STomi Valkeinen 492f7018c21STomi Valkeinen break; 493f7018c21STomi Valkeinen case VIAFB_TURN_ON_OUTPUT_DEVICE: 494f7018c21STomi Valkeinen if (copy_from_user(&gpu32, argp, sizeof(gpu32))) 495f7018c21STomi Valkeinen return -EFAULT; 496f7018c21STomi Valkeinen if (gpu32 & CRT_Device) 497f7018c21STomi Valkeinen via_set_state(VIA_CRT, VIA_STATE_ON); 498f7018c21STomi Valkeinen if (gpu32 & DVI_Device) 499f7018c21STomi Valkeinen viafb_dvi_enable(); 500f7018c21STomi Valkeinen if (gpu32 & LCD_Device) 501f7018c21STomi Valkeinen viafb_lcd_enable(); 502f7018c21STomi Valkeinen break; 503f7018c21STomi Valkeinen case VIAFB_TURN_OFF_OUTPUT_DEVICE: 504f7018c21STomi Valkeinen if (copy_from_user(&gpu32, argp, sizeof(gpu32))) 505f7018c21STomi Valkeinen return -EFAULT; 506f7018c21STomi Valkeinen if (gpu32 & CRT_Device) 507f7018c21STomi Valkeinen via_set_state(VIA_CRT, VIA_STATE_OFF); 508f7018c21STomi Valkeinen if (gpu32 & DVI_Device) 509f7018c21STomi Valkeinen viafb_dvi_disable(); 510f7018c21STomi Valkeinen if (gpu32 & LCD_Device) 511f7018c21STomi Valkeinen viafb_lcd_disable(); 512f7018c21STomi Valkeinen break; 513f7018c21STomi Valkeinen case VIAFB_GET_DEVICE: 514f7018c21STomi Valkeinen u.active_dev.crt = viafb_CRT_ON; 515f7018c21STomi Valkeinen u.active_dev.dvi = viafb_DVI_ON; 516f7018c21STomi Valkeinen u.active_dev.lcd = viafb_LCD_ON; 517f7018c21STomi Valkeinen u.active_dev.samm = viafb_SAMM_ON; 518f7018c21STomi Valkeinen u.active_dev.primary_dev = viafb_primary_dev; 519f7018c21STomi Valkeinen 520f7018c21STomi Valkeinen u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method; 521f7018c21STomi Valkeinen u.active_dev.lcd_panel_id = viafb_lcd_panel_id; 522f7018c21STomi Valkeinen u.active_dev.lcd_mode = viafb_lcd_mode; 523f7018c21STomi Valkeinen 524f7018c21STomi Valkeinen u.active_dev.xres = viafb_hotplug_Xres; 525f7018c21STomi Valkeinen u.active_dev.yres = viafb_hotplug_Yres; 526f7018c21STomi Valkeinen 527f7018c21STomi Valkeinen u.active_dev.xres1 = viafb_second_xres; 528f7018c21STomi Valkeinen u.active_dev.yres1 = viafb_second_yres; 529f7018c21STomi Valkeinen 530f7018c21STomi Valkeinen u.active_dev.bpp = viafb_bpp; 531f7018c21STomi Valkeinen u.active_dev.bpp1 = viafb_bpp1; 532f7018c21STomi Valkeinen u.active_dev.refresh = viafb_refresh; 533f7018c21STomi Valkeinen u.active_dev.refresh1 = viafb_refresh1; 534f7018c21STomi Valkeinen 535f7018c21STomi Valkeinen u.active_dev.epia_dvi = viafb_platform_epia_dvi; 536f7018c21STomi Valkeinen u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge; 537f7018c21STomi Valkeinen u.active_dev.bus_width = viafb_bus_width; 538f7018c21STomi Valkeinen 539f7018c21STomi Valkeinen if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev))) 540f7018c21STomi Valkeinen return -EFAULT; 541f7018c21STomi Valkeinen break; 542f7018c21STomi Valkeinen 543f7018c21STomi Valkeinen case VIAFB_GET_DRIVER_VERSION: 544f7018c21STomi Valkeinen u.driver_version.iMajorNum = VERSION_MAJOR; 545f7018c21STomi Valkeinen u.driver_version.iKernelNum = VERSION_KERNEL; 546f7018c21STomi Valkeinen u.driver_version.iOSNum = VERSION_OS; 547f7018c21STomi Valkeinen u.driver_version.iMinorNum = VERSION_MINOR; 548f7018c21STomi Valkeinen 549f7018c21STomi Valkeinen if (copy_to_user(argp, &u.driver_version, 550f7018c21STomi Valkeinen sizeof(u.driver_version))) 551f7018c21STomi Valkeinen return -EFAULT; 552f7018c21STomi Valkeinen 553f7018c21STomi Valkeinen break; 554f7018c21STomi Valkeinen 555f7018c21STomi Valkeinen case VIAFB_GET_DEVICE_INFO: 556f7018c21STomi Valkeinen 557f7018c21STomi Valkeinen retrieve_device_setting(&u.viafb_setting); 558f7018c21STomi Valkeinen 559f7018c21STomi Valkeinen if (copy_to_user(argp, &u.viafb_setting, 560f7018c21STomi Valkeinen sizeof(u.viafb_setting))) 561f7018c21STomi Valkeinen return -EFAULT; 562f7018c21STomi Valkeinen 563f7018c21STomi Valkeinen break; 564f7018c21STomi Valkeinen 565f7018c21STomi Valkeinen case VIAFB_GET_DEVICE_SUPPORT: 566f7018c21STomi Valkeinen viafb_get_device_support_state(&state_info); 567f7018c21STomi Valkeinen if (put_user(state_info, argp)) 568f7018c21STomi Valkeinen return -EFAULT; 569f7018c21STomi Valkeinen break; 570f7018c21STomi Valkeinen 571f7018c21STomi Valkeinen case VIAFB_GET_DEVICE_CONNECT: 572f7018c21STomi Valkeinen viafb_get_device_connect_state(&state_info); 573f7018c21STomi Valkeinen if (put_user(state_info, argp)) 574f7018c21STomi Valkeinen return -EFAULT; 575f7018c21STomi Valkeinen break; 576f7018c21STomi Valkeinen 577f7018c21STomi Valkeinen case VIAFB_GET_PANEL_SUPPORT_EXPAND: 578f7018c21STomi Valkeinen state_info = 579f7018c21STomi Valkeinen viafb_lcd_get_support_expand_state(info->var.xres, 580f7018c21STomi Valkeinen info->var.yres); 581f7018c21STomi Valkeinen if (put_user(state_info, argp)) 582f7018c21STomi Valkeinen return -EFAULT; 583f7018c21STomi Valkeinen break; 584f7018c21STomi Valkeinen 585f7018c21STomi Valkeinen case VIAFB_GET_DRIVER_NAME: 586f7018c21STomi Valkeinen if (copy_to_user(argp, driver_name, sizeof(driver_name))) 587f7018c21STomi Valkeinen return -EFAULT; 588f7018c21STomi Valkeinen break; 589f7018c21STomi Valkeinen 590f7018c21STomi Valkeinen case VIAFB_SET_GAMMA_LUT: 591f7018c21STomi Valkeinen viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32)); 592f7018c21STomi Valkeinen if (IS_ERR(viafb_gamma_table)) 593f7018c21STomi Valkeinen return PTR_ERR(viafb_gamma_table); 594f7018c21STomi Valkeinen viafb_set_gamma_table(viafb_bpp, viafb_gamma_table); 595f7018c21STomi Valkeinen kfree(viafb_gamma_table); 596f7018c21STomi Valkeinen break; 597f7018c21STomi Valkeinen 598f7018c21STomi Valkeinen case VIAFB_GET_GAMMA_LUT: 5996da2ec56SKees Cook viafb_gamma_table = kmalloc_array(256, sizeof(u32), 6006da2ec56SKees Cook GFP_KERNEL); 601f7018c21STomi Valkeinen if (!viafb_gamma_table) 602f7018c21STomi Valkeinen return -ENOMEM; 603f7018c21STomi Valkeinen viafb_get_gamma_table(viafb_gamma_table); 604f7018c21STomi Valkeinen if (copy_to_user(argp, viafb_gamma_table, 605f7018c21STomi Valkeinen 256 * sizeof(u32))) { 606f7018c21STomi Valkeinen kfree(viafb_gamma_table); 607f7018c21STomi Valkeinen return -EFAULT; 608f7018c21STomi Valkeinen } 609f7018c21STomi Valkeinen kfree(viafb_gamma_table); 610f7018c21STomi Valkeinen break; 611f7018c21STomi Valkeinen 612f7018c21STomi Valkeinen case VIAFB_GET_GAMMA_SUPPORT_STATE: 613f7018c21STomi Valkeinen viafb_get_gamma_support_state(viafb_bpp, &state_info); 614f7018c21STomi Valkeinen if (put_user(state_info, argp)) 615f7018c21STomi Valkeinen return -EFAULT; 616f7018c21STomi Valkeinen break; 617f7018c21STomi Valkeinen case VIAFB_SYNC_SURFACE: 618f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n"); 619f7018c21STomi Valkeinen break; 620f7018c21STomi Valkeinen case VIAFB_GET_DRIVER_CAPS: 621f7018c21STomi Valkeinen break; 622f7018c21STomi Valkeinen 623f7018c21STomi Valkeinen case VIAFB_GET_PANEL_MAX_SIZE: 624f7018c21STomi Valkeinen if (copy_from_user(&u.panel_pos_size_para, argp, 625f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 626f7018c21STomi Valkeinen return -EFAULT; 627f7018c21STomi Valkeinen u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; 628f7018c21STomi Valkeinen if (copy_to_user(argp, &u.panel_pos_size_para, 629f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 630f7018c21STomi Valkeinen return -EFAULT; 631f7018c21STomi Valkeinen break; 632f7018c21STomi Valkeinen case VIAFB_GET_PANEL_MAX_POSITION: 633f7018c21STomi Valkeinen if (copy_from_user(&u.panel_pos_size_para, argp, 634f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 635f7018c21STomi Valkeinen return -EFAULT; 636f7018c21STomi Valkeinen u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; 637f7018c21STomi Valkeinen if (copy_to_user(argp, &u.panel_pos_size_para, 638f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 639f7018c21STomi Valkeinen return -EFAULT; 640f7018c21STomi Valkeinen break; 641f7018c21STomi Valkeinen 642f7018c21STomi Valkeinen case VIAFB_GET_PANEL_POSITION: 643f7018c21STomi Valkeinen if (copy_from_user(&u.panel_pos_size_para, argp, 644f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 645f7018c21STomi Valkeinen return -EFAULT; 646f7018c21STomi Valkeinen u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; 647f7018c21STomi Valkeinen if (copy_to_user(argp, &u.panel_pos_size_para, 648f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 649f7018c21STomi Valkeinen return -EFAULT; 650f7018c21STomi Valkeinen break; 651f7018c21STomi Valkeinen case VIAFB_GET_PANEL_SIZE: 652f7018c21STomi Valkeinen if (copy_from_user(&u.panel_pos_size_para, argp, 653f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 654f7018c21STomi Valkeinen return -EFAULT; 655f7018c21STomi Valkeinen u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; 656f7018c21STomi Valkeinen if (copy_to_user(argp, &u.panel_pos_size_para, 657f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 658f7018c21STomi Valkeinen return -EFAULT; 659f7018c21STomi Valkeinen break; 660f7018c21STomi Valkeinen 661f7018c21STomi Valkeinen case VIAFB_SET_PANEL_POSITION: 662f7018c21STomi Valkeinen if (copy_from_user(&u.panel_pos_size_para, argp, 663f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 664f7018c21STomi Valkeinen return -EFAULT; 665f7018c21STomi Valkeinen break; 666f7018c21STomi Valkeinen case VIAFB_SET_PANEL_SIZE: 667f7018c21STomi Valkeinen if (copy_from_user(&u.panel_pos_size_para, argp, 668f7018c21STomi Valkeinen sizeof(u.panel_pos_size_para))) 669f7018c21STomi Valkeinen return -EFAULT; 670f7018c21STomi Valkeinen break; 671f7018c21STomi Valkeinen 672f7018c21STomi Valkeinen default: 673f7018c21STomi Valkeinen return -EINVAL; 674f7018c21STomi Valkeinen } 675f7018c21STomi Valkeinen 676f7018c21STomi Valkeinen return 0; 677f7018c21STomi Valkeinen } 678f7018c21STomi Valkeinen 679f7018c21STomi Valkeinen static void viafb_fillrect(struct fb_info *info, 680f7018c21STomi Valkeinen const struct fb_fillrect *rect) 681f7018c21STomi Valkeinen { 682f7018c21STomi Valkeinen struct viafb_par *viapar = info->par; 683f7018c21STomi Valkeinen struct viafb_shared *shared = viapar->shared; 684f7018c21STomi Valkeinen u32 fg_color; 685f7018c21STomi Valkeinen u8 rop; 686f7018c21STomi Valkeinen 687f7018c21STomi Valkeinen if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) { 688f7018c21STomi Valkeinen cfb_fillrect(info, rect); 689f7018c21STomi Valkeinen return; 690f7018c21STomi Valkeinen } 691f7018c21STomi Valkeinen 692f7018c21STomi Valkeinen if (!rect->width || !rect->height) 693f7018c21STomi Valkeinen return; 694f7018c21STomi Valkeinen 695f7018c21STomi Valkeinen if (info->fix.visual == FB_VISUAL_TRUECOLOR) 696f7018c21STomi Valkeinen fg_color = ((u32 *)info->pseudo_palette)[rect->color]; 697f7018c21STomi Valkeinen else 698f7018c21STomi Valkeinen fg_color = rect->color; 699f7018c21STomi Valkeinen 700f7018c21STomi Valkeinen if (rect->rop == ROP_XOR) 701f7018c21STomi Valkeinen rop = 0x5A; 702f7018c21STomi Valkeinen else 703f7018c21STomi Valkeinen rop = 0xF0; 704f7018c21STomi Valkeinen 705f7018c21STomi Valkeinen DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n"); 706f7018c21STomi Valkeinen if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL, 707f7018c21STomi Valkeinen rect->width, rect->height, info->var.bits_per_pixel, 708f7018c21STomi Valkeinen viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy, 709f7018c21STomi Valkeinen NULL, 0, 0, 0, 0, fg_color, 0, rop)) 710f7018c21STomi Valkeinen cfb_fillrect(info, rect); 711f7018c21STomi Valkeinen } 712f7018c21STomi Valkeinen 713f7018c21STomi Valkeinen static void viafb_copyarea(struct fb_info *info, 714f7018c21STomi Valkeinen const struct fb_copyarea *area) 715f7018c21STomi Valkeinen { 716f7018c21STomi Valkeinen struct viafb_par *viapar = info->par; 717f7018c21STomi Valkeinen struct viafb_shared *shared = viapar->shared; 718f7018c21STomi Valkeinen 719f7018c21STomi Valkeinen if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) { 720f7018c21STomi Valkeinen cfb_copyarea(info, area); 721f7018c21STomi Valkeinen return; 722f7018c21STomi Valkeinen } 723f7018c21STomi Valkeinen 724f7018c21STomi Valkeinen if (!area->width || !area->height) 725f7018c21STomi Valkeinen return; 726f7018c21STomi Valkeinen 727f7018c21STomi Valkeinen DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n"); 728f7018c21STomi Valkeinen if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR, 729f7018c21STomi Valkeinen area->width, area->height, info->var.bits_per_pixel, 730f7018c21STomi Valkeinen viapar->vram_addr, info->fix.line_length, area->dx, area->dy, 731f7018c21STomi Valkeinen NULL, viapar->vram_addr, info->fix.line_length, 732f7018c21STomi Valkeinen area->sx, area->sy, 0, 0, 0)) 733f7018c21STomi Valkeinen cfb_copyarea(info, area); 734f7018c21STomi Valkeinen } 735f7018c21STomi Valkeinen 736f7018c21STomi Valkeinen static void viafb_imageblit(struct fb_info *info, 737f7018c21STomi Valkeinen const struct fb_image *image) 738f7018c21STomi Valkeinen { 739f7018c21STomi Valkeinen struct viafb_par *viapar = info->par; 740f7018c21STomi Valkeinen struct viafb_shared *shared = viapar->shared; 741f7018c21STomi Valkeinen u32 fg_color = 0, bg_color = 0; 742f7018c21STomi Valkeinen u8 op; 743f7018c21STomi Valkeinen 744f7018c21STomi Valkeinen if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt || 745f7018c21STomi Valkeinen (image->depth != 1 && image->depth != viapar->depth)) { 746f7018c21STomi Valkeinen cfb_imageblit(info, image); 747f7018c21STomi Valkeinen return; 748f7018c21STomi Valkeinen } 749f7018c21STomi Valkeinen 750f7018c21STomi Valkeinen if (image->depth == 1) { 751f7018c21STomi Valkeinen op = VIA_BITBLT_MONO; 752f7018c21STomi Valkeinen if (info->fix.visual == FB_VISUAL_TRUECOLOR) { 753f7018c21STomi Valkeinen fg_color = 754f7018c21STomi Valkeinen ((u32 *)info->pseudo_palette)[image->fg_color]; 755f7018c21STomi Valkeinen bg_color = 756f7018c21STomi Valkeinen ((u32 *)info->pseudo_palette)[image->bg_color]; 757f7018c21STomi Valkeinen } else { 758f7018c21STomi Valkeinen fg_color = image->fg_color; 759f7018c21STomi Valkeinen bg_color = image->bg_color; 760f7018c21STomi Valkeinen } 761f7018c21STomi Valkeinen } else 762f7018c21STomi Valkeinen op = VIA_BITBLT_COLOR; 763f7018c21STomi Valkeinen 764f7018c21STomi Valkeinen DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n"); 765f7018c21STomi Valkeinen if (shared->hw_bitblt(shared->vdev->engine_mmio, op, 766f7018c21STomi Valkeinen image->width, image->height, info->var.bits_per_pixel, 767f7018c21STomi Valkeinen viapar->vram_addr, info->fix.line_length, image->dx, image->dy, 768f7018c21STomi Valkeinen (u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0)) 769f7018c21STomi Valkeinen cfb_imageblit(info, image); 770f7018c21STomi Valkeinen } 771f7018c21STomi Valkeinen 772f7018c21STomi Valkeinen static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) 773f7018c21STomi Valkeinen { 774f7018c21STomi Valkeinen struct viafb_par *viapar = info->par; 775f7018c21STomi Valkeinen void __iomem *engine = viapar->shared->vdev->engine_mmio; 776f7018c21STomi Valkeinen u32 temp, xx, yy, bg_color = 0, fg_color = 0, 777f7018c21STomi Valkeinen chip_name = viapar->shared->chip_info.gfx_chip_name; 778f7018c21STomi Valkeinen int i, j = 0, cur_size = 64; 779f7018c21STomi Valkeinen 780f7018c21STomi Valkeinen if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo) 781f7018c21STomi Valkeinen return -ENODEV; 782f7018c21STomi Valkeinen 783f7018c21STomi Valkeinen /* LCD ouput does not support hw cursors (at least on VN896) */ 784f7018c21STomi Valkeinen if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) || 785f7018c21STomi Valkeinen viafb_LCD_ON) 786f7018c21STomi Valkeinen return -ENODEV; 787f7018c21STomi Valkeinen 788f7018c21STomi Valkeinen viafb_show_hw_cursor(info, HW_Cursor_OFF); 789f7018c21STomi Valkeinen 790f7018c21STomi Valkeinen if (cursor->set & FB_CUR_SETHOT) { 791f7018c21STomi Valkeinen temp = (cursor->hot.x << 16) + cursor->hot.y; 792f7018c21STomi Valkeinen writel(temp, engine + VIA_REG_CURSOR_ORG); 793f7018c21STomi Valkeinen } 794f7018c21STomi Valkeinen 795f7018c21STomi Valkeinen if (cursor->set & FB_CUR_SETPOS) { 796f7018c21STomi Valkeinen yy = cursor->image.dy - info->var.yoffset; 797f7018c21STomi Valkeinen xx = cursor->image.dx - info->var.xoffset; 798f7018c21STomi Valkeinen temp = yy & 0xFFFF; 799f7018c21STomi Valkeinen temp |= (xx << 16); 800f7018c21STomi Valkeinen writel(temp, engine + VIA_REG_CURSOR_POS); 801f7018c21STomi Valkeinen } 802f7018c21STomi Valkeinen 803f7018c21STomi Valkeinen if (cursor->image.width <= 32 && cursor->image.height <= 32) 804f7018c21STomi Valkeinen cur_size = 32; 805f7018c21STomi Valkeinen else if (cursor->image.width <= 64 && cursor->image.height <= 64) 806f7018c21STomi Valkeinen cur_size = 64; 807f7018c21STomi Valkeinen else { 808f7018c21STomi Valkeinen printk(KERN_WARNING "viafb_cursor: The cursor is too large " 809f7018c21STomi Valkeinen "%dx%d", cursor->image.width, cursor->image.height); 810f7018c21STomi Valkeinen return -ENXIO; 811f7018c21STomi Valkeinen } 812f7018c21STomi Valkeinen 813f7018c21STomi Valkeinen if (cursor->set & FB_CUR_SETSIZE) { 814f7018c21STomi Valkeinen temp = readl(engine + VIA_REG_CURSOR_MODE); 815f7018c21STomi Valkeinen if (cur_size == 32) 816f7018c21STomi Valkeinen temp |= 0x2; 817f7018c21STomi Valkeinen else 818f7018c21STomi Valkeinen temp &= ~0x2; 819f7018c21STomi Valkeinen 820f7018c21STomi Valkeinen writel(temp, engine + VIA_REG_CURSOR_MODE); 821f7018c21STomi Valkeinen } 822f7018c21STomi Valkeinen 823f7018c21STomi Valkeinen if (cursor->set & FB_CUR_SETCMAP) { 824f7018c21STomi Valkeinen fg_color = cursor->image.fg_color; 825f7018c21STomi Valkeinen bg_color = cursor->image.bg_color; 826f7018c21STomi Valkeinen if (chip_name == UNICHROME_CX700 || 827f7018c21STomi Valkeinen chip_name == UNICHROME_VX800 || 828f7018c21STomi Valkeinen chip_name == UNICHROME_VX855 || 829f7018c21STomi Valkeinen chip_name == UNICHROME_VX900) { 830f7018c21STomi Valkeinen fg_color = 831f7018c21STomi Valkeinen ((info->cmap.red[fg_color] & 0xFFC0) << 14) | 832f7018c21STomi Valkeinen ((info->cmap.green[fg_color] & 0xFFC0) << 4) | 833f7018c21STomi Valkeinen ((info->cmap.blue[fg_color] & 0xFFC0) >> 6); 834f7018c21STomi Valkeinen bg_color = 835f7018c21STomi Valkeinen ((info->cmap.red[bg_color] & 0xFFC0) << 14) | 836f7018c21STomi Valkeinen ((info->cmap.green[bg_color] & 0xFFC0) << 4) | 837f7018c21STomi Valkeinen ((info->cmap.blue[bg_color] & 0xFFC0) >> 6); 838f7018c21STomi Valkeinen } else { 839f7018c21STomi Valkeinen fg_color = 840f7018c21STomi Valkeinen ((info->cmap.red[fg_color] & 0xFF00) << 8) | 841f7018c21STomi Valkeinen (info->cmap.green[fg_color] & 0xFF00) | 842f7018c21STomi Valkeinen ((info->cmap.blue[fg_color] & 0xFF00) >> 8); 843f7018c21STomi Valkeinen bg_color = 844f7018c21STomi Valkeinen ((info->cmap.red[bg_color] & 0xFF00) << 8) | 845f7018c21STomi Valkeinen (info->cmap.green[bg_color] & 0xFF00) | 846f7018c21STomi Valkeinen ((info->cmap.blue[bg_color] & 0xFF00) >> 8); 847f7018c21STomi Valkeinen } 848f7018c21STomi Valkeinen 849f7018c21STomi Valkeinen writel(bg_color, engine + VIA_REG_CURSOR_BG); 850f7018c21STomi Valkeinen writel(fg_color, engine + VIA_REG_CURSOR_FG); 851f7018c21STomi Valkeinen } 852f7018c21STomi Valkeinen 853f7018c21STomi Valkeinen if (cursor->set & FB_CUR_SETSHAPE) { 854f7018c21STomi Valkeinen struct { 855f7018c21STomi Valkeinen u8 data[CURSOR_SIZE]; 856f7018c21STomi Valkeinen u32 bak[CURSOR_SIZE / 4]; 857f7018c21STomi Valkeinen } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC); 858f7018c21STomi Valkeinen int size = ((cursor->image.width + 7) >> 3) * 859f7018c21STomi Valkeinen cursor->image.height; 860f7018c21STomi Valkeinen 861f7018c21STomi Valkeinen if (!cr_data) 862f7018c21STomi Valkeinen return -ENOMEM; 863f7018c21STomi Valkeinen 864f7018c21STomi Valkeinen if (cur_size == 32) { 865f7018c21STomi Valkeinen for (i = 0; i < (CURSOR_SIZE / 4); i++) { 866f7018c21STomi Valkeinen cr_data->bak[i] = 0x0; 867f7018c21STomi Valkeinen cr_data->bak[i + 1] = 0xFFFFFFFF; 868f7018c21STomi Valkeinen i += 1; 869f7018c21STomi Valkeinen } 870f7018c21STomi Valkeinen } else { 871f7018c21STomi Valkeinen for (i = 0; i < (CURSOR_SIZE / 4); i++) { 872f7018c21STomi Valkeinen cr_data->bak[i] = 0x0; 873f7018c21STomi Valkeinen cr_data->bak[i + 1] = 0x0; 874f7018c21STomi Valkeinen cr_data->bak[i + 2] = 0xFFFFFFFF; 875f7018c21STomi Valkeinen cr_data->bak[i + 3] = 0xFFFFFFFF; 876f7018c21STomi Valkeinen i += 3; 877f7018c21STomi Valkeinen } 878f7018c21STomi Valkeinen } 879f7018c21STomi Valkeinen 880f7018c21STomi Valkeinen switch (cursor->rop) { 881f7018c21STomi Valkeinen case ROP_XOR: 882f7018c21STomi Valkeinen for (i = 0; i < size; i++) 883f7018c21STomi Valkeinen cr_data->data[i] = cursor->mask[i]; 884f7018c21STomi Valkeinen break; 885f7018c21STomi Valkeinen case ROP_COPY: 886f7018c21STomi Valkeinen 887f7018c21STomi Valkeinen for (i = 0; i < size; i++) 888f7018c21STomi Valkeinen cr_data->data[i] = cursor->mask[i]; 889f7018c21STomi Valkeinen break; 890f7018c21STomi Valkeinen default: 891f7018c21STomi Valkeinen break; 892f7018c21STomi Valkeinen } 893f7018c21STomi Valkeinen 894f7018c21STomi Valkeinen if (cur_size == 32) { 895f7018c21STomi Valkeinen for (i = 0; i < size; i++) { 896f7018c21STomi Valkeinen cr_data->bak[j] = (u32) cr_data->data[i]; 897f7018c21STomi Valkeinen cr_data->bak[j + 1] = ~cr_data->bak[j]; 898f7018c21STomi Valkeinen j += 2; 899f7018c21STomi Valkeinen } 900f7018c21STomi Valkeinen } else { 901f7018c21STomi Valkeinen for (i = 0; i < size; i++) { 902f7018c21STomi Valkeinen cr_data->bak[j] = (u32) cr_data->data[i]; 903f7018c21STomi Valkeinen cr_data->bak[j + 1] = 0x0; 904f7018c21STomi Valkeinen cr_data->bak[j + 2] = ~cr_data->bak[j]; 905f7018c21STomi Valkeinen cr_data->bak[j + 3] = ~cr_data->bak[j + 1]; 906f7018c21STomi Valkeinen j += 4; 907f7018c21STomi Valkeinen } 908f7018c21STomi Valkeinen } 909f7018c21STomi Valkeinen 910f7018c21STomi Valkeinen memcpy_toio(viafbinfo->screen_base + viapar->shared-> 911f7018c21STomi Valkeinen cursor_vram_addr, cr_data->bak, CURSOR_SIZE); 912f7018c21STomi Valkeinen kfree(cr_data); 913f7018c21STomi Valkeinen } 914f7018c21STomi Valkeinen 915f7018c21STomi Valkeinen if (cursor->enable) 916f7018c21STomi Valkeinen viafb_show_hw_cursor(info, HW_Cursor_ON); 917f7018c21STomi Valkeinen 918f7018c21STomi Valkeinen return 0; 919f7018c21STomi Valkeinen } 920f7018c21STomi Valkeinen 921f7018c21STomi Valkeinen static int viafb_sync(struct fb_info *info) 922f7018c21STomi Valkeinen { 923f7018c21STomi Valkeinen if (!(info->flags & FBINFO_HWACCEL_DISABLED)) 924f7018c21STomi Valkeinen viafb_wait_engine_idle(info); 925f7018c21STomi Valkeinen return 0; 926f7018c21STomi Valkeinen } 927f7018c21STomi Valkeinen 928f7018c21STomi Valkeinen static int get_primary_device(void) 929f7018c21STomi Valkeinen { 930f7018c21STomi Valkeinen int primary_device = 0; 931f7018c21STomi Valkeinen /* Rule: device on iga1 path are the primary device. */ 932f7018c21STomi Valkeinen if (viafb_SAMM_ON) { 933f7018c21STomi Valkeinen if (viafb_CRT_ON) { 934f7018c21STomi Valkeinen if (viaparinfo->shared->iga1_devices & VIA_CRT) { 935f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", IGA1); 936f7018c21STomi Valkeinen primary_device = CRT_Device; 937f7018c21STomi Valkeinen } 938f7018c21STomi Valkeinen } 939f7018c21STomi Valkeinen if (viafb_DVI_ON) { 940f7018c21STomi Valkeinen if (viaparinfo->tmds_setting_info->iga_path == IGA1) { 941f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n", 942f7018c21STomi Valkeinen viaparinfo-> 943f7018c21STomi Valkeinen tmds_setting_info->iga_path); 944f7018c21STomi Valkeinen primary_device = DVI_Device; 945f7018c21STomi Valkeinen } 946f7018c21STomi Valkeinen } 947f7018c21STomi Valkeinen if (viafb_LCD_ON) { 948f7018c21STomi Valkeinen if (viaparinfo->lvds_setting_info->iga_path == IGA1) { 949f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n", 950f7018c21STomi Valkeinen viaparinfo-> 951f7018c21STomi Valkeinen lvds_setting_info->iga_path); 952f7018c21STomi Valkeinen primary_device = LCD_Device; 953f7018c21STomi Valkeinen } 954f7018c21STomi Valkeinen } 955f7018c21STomi Valkeinen if (viafb_LCD2_ON) { 956f7018c21STomi Valkeinen if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { 957f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n", 958f7018c21STomi Valkeinen viaparinfo-> 959f7018c21STomi Valkeinen lvds_setting_info2->iga_path); 960f7018c21STomi Valkeinen primary_device = LCD2_Device; 961f7018c21STomi Valkeinen } 962f7018c21STomi Valkeinen } 963f7018c21STomi Valkeinen } 964f7018c21STomi Valkeinen return primary_device; 965f7018c21STomi Valkeinen } 966f7018c21STomi Valkeinen 967f7018c21STomi Valkeinen static void retrieve_device_setting(struct viafb_ioctl_setting 968f7018c21STomi Valkeinen *setting_info) 969f7018c21STomi Valkeinen { 970f7018c21STomi Valkeinen 971f7018c21STomi Valkeinen /* get device status */ 972f7018c21STomi Valkeinen if (viafb_CRT_ON == 1) 973f7018c21STomi Valkeinen setting_info->device_status = CRT_Device; 974f7018c21STomi Valkeinen if (viafb_DVI_ON == 1) 975f7018c21STomi Valkeinen setting_info->device_status |= DVI_Device; 976f7018c21STomi Valkeinen if (viafb_LCD_ON == 1) 977f7018c21STomi Valkeinen setting_info->device_status |= LCD_Device; 978f7018c21STomi Valkeinen if (viafb_LCD2_ON == 1) 979f7018c21STomi Valkeinen setting_info->device_status |= LCD2_Device; 980f7018c21STomi Valkeinen 981f7018c21STomi Valkeinen setting_info->samm_status = viafb_SAMM_ON; 982f7018c21STomi Valkeinen setting_info->primary_device = get_primary_device(); 983f7018c21STomi Valkeinen 984f7018c21STomi Valkeinen setting_info->first_dev_bpp = viafb_bpp; 985f7018c21STomi Valkeinen setting_info->second_dev_bpp = viafb_bpp1; 986f7018c21STomi Valkeinen 987f7018c21STomi Valkeinen setting_info->first_dev_refresh = viafb_refresh; 988f7018c21STomi Valkeinen setting_info->second_dev_refresh = viafb_refresh1; 989f7018c21STomi Valkeinen 990f7018c21STomi Valkeinen setting_info->first_dev_hor_res = viafb_hotplug_Xres; 991f7018c21STomi Valkeinen setting_info->first_dev_ver_res = viafb_hotplug_Yres; 992f7018c21STomi Valkeinen setting_info->second_dev_hor_res = viafb_second_xres; 993f7018c21STomi Valkeinen setting_info->second_dev_ver_res = viafb_second_yres; 994f7018c21STomi Valkeinen 995f7018c21STomi Valkeinen /* Get lcd attributes */ 996f7018c21STomi Valkeinen setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method; 997f7018c21STomi Valkeinen setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id; 998f7018c21STomi Valkeinen setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; 999f7018c21STomi Valkeinen } 1000f7018c21STomi Valkeinen 1001f7018c21STomi Valkeinen static int __init parse_active_dev(void) 1002f7018c21STomi Valkeinen { 1003f7018c21STomi Valkeinen viafb_CRT_ON = STATE_OFF; 1004f7018c21STomi Valkeinen viafb_DVI_ON = STATE_OFF; 1005f7018c21STomi Valkeinen viafb_LCD_ON = STATE_OFF; 1006f7018c21STomi Valkeinen viafb_LCD2_ON = STATE_OFF; 1007f7018c21STomi Valkeinen /* 1. Modify the active status of devices. */ 1008f7018c21STomi Valkeinen /* 2. Keep the order of devices, so we can set corresponding 1009f7018c21STomi Valkeinen IGA path to devices in SAMM case. */ 1010f7018c21STomi Valkeinen /* Note: The previous of active_dev is primary device, 1011f7018c21STomi Valkeinen and the following is secondary device. */ 1012f7018c21STomi Valkeinen if (!viafb_active_dev) { 1013f7018c21STomi Valkeinen if (machine_is_olpc()) { /* LCD only */ 1014f7018c21STomi Valkeinen viafb_LCD_ON = STATE_ON; 1015f7018c21STomi Valkeinen viafb_SAMM_ON = STATE_OFF; 1016f7018c21STomi Valkeinen } else { 1017f7018c21STomi Valkeinen viafb_CRT_ON = STATE_ON; 1018f7018c21STomi Valkeinen viafb_SAMM_ON = STATE_OFF; 1019f7018c21STomi Valkeinen } 1020f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "CRT+DVI")) { 1021f7018c21STomi Valkeinen /* CRT+DVI */ 1022f7018c21STomi Valkeinen viafb_CRT_ON = STATE_ON; 1023f7018c21STomi Valkeinen viafb_DVI_ON = STATE_ON; 1024f7018c21STomi Valkeinen viafb_primary_dev = CRT_Device; 1025f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "DVI+CRT")) { 1026f7018c21STomi Valkeinen /* DVI+CRT */ 1027f7018c21STomi Valkeinen viafb_CRT_ON = STATE_ON; 1028f7018c21STomi Valkeinen viafb_DVI_ON = STATE_ON; 1029f7018c21STomi Valkeinen viafb_primary_dev = DVI_Device; 1030f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "CRT+LCD")) { 1031f7018c21STomi Valkeinen /* CRT+LCD */ 1032f7018c21STomi Valkeinen viafb_CRT_ON = STATE_ON; 1033f7018c21STomi Valkeinen viafb_LCD_ON = STATE_ON; 1034f7018c21STomi Valkeinen viafb_primary_dev = CRT_Device; 1035f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "LCD+CRT")) { 1036f7018c21STomi Valkeinen /* LCD+CRT */ 1037f7018c21STomi Valkeinen viafb_CRT_ON = STATE_ON; 1038f7018c21STomi Valkeinen viafb_LCD_ON = STATE_ON; 1039f7018c21STomi Valkeinen viafb_primary_dev = LCD_Device; 1040f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "DVI+LCD")) { 1041f7018c21STomi Valkeinen /* DVI+LCD */ 1042f7018c21STomi Valkeinen viafb_DVI_ON = STATE_ON; 1043f7018c21STomi Valkeinen viafb_LCD_ON = STATE_ON; 1044f7018c21STomi Valkeinen viafb_primary_dev = DVI_Device; 1045f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "LCD+DVI")) { 1046f7018c21STomi Valkeinen /* LCD+DVI */ 1047f7018c21STomi Valkeinen viafb_DVI_ON = STATE_ON; 1048f7018c21STomi Valkeinen viafb_LCD_ON = STATE_ON; 1049f7018c21STomi Valkeinen viafb_primary_dev = LCD_Device; 1050f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "LCD+LCD2")) { 1051f7018c21STomi Valkeinen viafb_LCD_ON = STATE_ON; 1052f7018c21STomi Valkeinen viafb_LCD2_ON = STATE_ON; 1053f7018c21STomi Valkeinen viafb_primary_dev = LCD_Device; 1054f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "LCD2+LCD")) { 1055f7018c21STomi Valkeinen viafb_LCD_ON = STATE_ON; 1056f7018c21STomi Valkeinen viafb_LCD2_ON = STATE_ON; 1057f7018c21STomi Valkeinen viafb_primary_dev = LCD2_Device; 1058f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "CRT")) { 1059f7018c21STomi Valkeinen /* CRT only */ 1060f7018c21STomi Valkeinen viafb_CRT_ON = STATE_ON; 1061f7018c21STomi Valkeinen viafb_SAMM_ON = STATE_OFF; 1062f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "DVI")) { 1063f7018c21STomi Valkeinen /* DVI only */ 1064f7018c21STomi Valkeinen viafb_DVI_ON = STATE_ON; 1065f7018c21STomi Valkeinen viafb_SAMM_ON = STATE_OFF; 1066f7018c21STomi Valkeinen } else if (!strcmp(viafb_active_dev, "LCD")) { 1067f7018c21STomi Valkeinen /* LCD only */ 1068f7018c21STomi Valkeinen viafb_LCD_ON = STATE_ON; 1069f7018c21STomi Valkeinen viafb_SAMM_ON = STATE_OFF; 1070f7018c21STomi Valkeinen } else 1071f7018c21STomi Valkeinen return -EINVAL; 1072f7018c21STomi Valkeinen 1073f7018c21STomi Valkeinen return 0; 1074f7018c21STomi Valkeinen } 1075f7018c21STomi Valkeinen 1076f7018c21STomi Valkeinen static int parse_port(char *opt_str, int *output_interface) 1077f7018c21STomi Valkeinen { 1078f7018c21STomi Valkeinen if (!strncmp(opt_str, "DVP0", 4)) 1079f7018c21STomi Valkeinen *output_interface = INTERFACE_DVP0; 1080f7018c21STomi Valkeinen else if (!strncmp(opt_str, "DVP1", 4)) 1081f7018c21STomi Valkeinen *output_interface = INTERFACE_DVP1; 1082f7018c21STomi Valkeinen else if (!strncmp(opt_str, "DFP_HIGHLOW", 11)) 1083f7018c21STomi Valkeinen *output_interface = INTERFACE_DFP; 1084f7018c21STomi Valkeinen else if (!strncmp(opt_str, "DFP_HIGH", 8)) 1085f7018c21STomi Valkeinen *output_interface = INTERFACE_DFP_HIGH; 1086f7018c21STomi Valkeinen else if (!strncmp(opt_str, "DFP_LOW", 7)) 1087f7018c21STomi Valkeinen *output_interface = INTERFACE_DFP_LOW; 1088f7018c21STomi Valkeinen else 1089f7018c21STomi Valkeinen *output_interface = INTERFACE_NONE; 1090f7018c21STomi Valkeinen return 0; 1091f7018c21STomi Valkeinen } 1092f7018c21STomi Valkeinen 1093f7018c21STomi Valkeinen static void parse_lcd_port(void) 1094f7018c21STomi Valkeinen { 1095f7018c21STomi Valkeinen parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info. 1096f7018c21STomi Valkeinen output_interface); 1097f7018c21STomi Valkeinen /*Initialize to avoid unexpected behavior */ 1098f7018c21STomi Valkeinen viaparinfo->chip_info->lvds_chip_info2.output_interface = 1099f7018c21STomi Valkeinen INTERFACE_NONE; 1100f7018c21STomi Valkeinen 1101f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n", 1102f7018c21STomi Valkeinen viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info. 1103f7018c21STomi Valkeinen output_interface); 1104f7018c21STomi Valkeinen } 1105f7018c21STomi Valkeinen 1106f7018c21STomi Valkeinen static void parse_dvi_port(void) 1107f7018c21STomi Valkeinen { 1108f7018c21STomi Valkeinen parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info. 1109f7018c21STomi Valkeinen output_interface); 1110f7018c21STomi Valkeinen 1111f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n", 1112f7018c21STomi Valkeinen viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info. 1113f7018c21STomi Valkeinen output_interface); 1114f7018c21STomi Valkeinen } 1115f7018c21STomi Valkeinen 1116f7018c21STomi Valkeinen #ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1117f7018c21STomi Valkeinen 1118f7018c21STomi Valkeinen /* 1119f7018c21STomi Valkeinen * The proc filesystem read/write function, a simple proc implement to 1120f7018c21STomi Valkeinen * get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, 1121f7018c21STomi Valkeinen * DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], 1122f7018c21STomi Valkeinen * CR9B, SR65, CR97, CR99 1123f7018c21STomi Valkeinen */ 1124f7018c21STomi Valkeinen static int viafb_dvp0_proc_show(struct seq_file *m, void *v) 1125f7018c21STomi Valkeinen { 1126f7018c21STomi Valkeinen u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0; 1127f7018c21STomi Valkeinen dvp0_data_dri = 1128f7018c21STomi Valkeinen (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 | 1129f7018c21STomi Valkeinen (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1; 1130f7018c21STomi Valkeinen dvp0_clk_dri = 1131f7018c21STomi Valkeinen (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 | 1132f7018c21STomi Valkeinen (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2; 1133f7018c21STomi Valkeinen dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f; 1134f7018c21STomi Valkeinen seq_printf(m, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri); 1135f7018c21STomi Valkeinen return 0; 1136f7018c21STomi Valkeinen } 1137f7018c21STomi Valkeinen 1138f7018c21STomi Valkeinen static int viafb_dvp0_proc_open(struct inode *inode, struct file *file) 1139f7018c21STomi Valkeinen { 1140f7018c21STomi Valkeinen return single_open(file, viafb_dvp0_proc_show, NULL); 1141f7018c21STomi Valkeinen } 1142f7018c21STomi Valkeinen 1143f7018c21STomi Valkeinen static ssize_t viafb_dvp0_proc_write(struct file *file, 1144f7018c21STomi Valkeinen const char __user *buffer, size_t count, loff_t *pos) 1145f7018c21STomi Valkeinen { 1146f7018c21STomi Valkeinen char buf[20], *value, *pbuf; 1147f7018c21STomi Valkeinen u8 reg_val = 0; 1148f7018c21STomi Valkeinen unsigned long length, i; 1149f7018c21STomi Valkeinen if (count < 1) 1150f7018c21STomi Valkeinen return -EINVAL; 1151f7018c21STomi Valkeinen length = count > 20 ? 20 : count; 1152f7018c21STomi Valkeinen if (copy_from_user(&buf[0], buffer, length)) 1153f7018c21STomi Valkeinen return -EFAULT; 1154f7018c21STomi Valkeinen buf[length - 1] = '\0'; /*Ensure end string */ 1155f7018c21STomi Valkeinen pbuf = &buf[0]; 1156f7018c21STomi Valkeinen for (i = 0; i < 3; i++) { 1157f7018c21STomi Valkeinen value = strsep(&pbuf, " "); 1158f7018c21STomi Valkeinen if (value != NULL) { 1159f7018c21STomi Valkeinen if (kstrtou8(value, 0, ®_val) < 0) 1160f7018c21STomi Valkeinen return -EINVAL; 1161f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i, 1162f7018c21STomi Valkeinen reg_val); 1163f7018c21STomi Valkeinen switch (i) { 1164f7018c21STomi Valkeinen case 0: 1165f7018c21STomi Valkeinen viafb_write_reg_mask(CR96, VIACR, 1166f7018c21STomi Valkeinen reg_val, 0x0f); 1167f7018c21STomi Valkeinen break; 1168f7018c21STomi Valkeinen case 1: 1169f7018c21STomi Valkeinen viafb_write_reg_mask(SR2A, VIASR, 1170f7018c21STomi Valkeinen reg_val << 4, BIT5); 1171f7018c21STomi Valkeinen viafb_write_reg_mask(SR1B, VIASR, 1172f7018c21STomi Valkeinen reg_val << 1, BIT1); 1173f7018c21STomi Valkeinen break; 1174f7018c21STomi Valkeinen case 2: 1175f7018c21STomi Valkeinen viafb_write_reg_mask(SR2A, VIASR, 1176f7018c21STomi Valkeinen reg_val << 3, BIT4); 1177f7018c21STomi Valkeinen viafb_write_reg_mask(SR1E, VIASR, 1178f7018c21STomi Valkeinen reg_val << 2, BIT2); 1179f7018c21STomi Valkeinen break; 1180f7018c21STomi Valkeinen default: 1181f7018c21STomi Valkeinen break; 1182f7018c21STomi Valkeinen } 1183f7018c21STomi Valkeinen } else { 1184f7018c21STomi Valkeinen break; 1185f7018c21STomi Valkeinen } 1186f7018c21STomi Valkeinen } 1187f7018c21STomi Valkeinen return count; 1188f7018c21STomi Valkeinen } 1189f7018c21STomi Valkeinen 1190f7018c21STomi Valkeinen static const struct file_operations viafb_dvp0_proc_fops = { 1191f7018c21STomi Valkeinen .owner = THIS_MODULE, 1192f7018c21STomi Valkeinen .open = viafb_dvp0_proc_open, 1193f7018c21STomi Valkeinen .read = seq_read, 1194f7018c21STomi Valkeinen .llseek = seq_lseek, 1195f7018c21STomi Valkeinen .release = single_release, 1196f7018c21STomi Valkeinen .write = viafb_dvp0_proc_write, 1197f7018c21STomi Valkeinen }; 1198f7018c21STomi Valkeinen 1199f7018c21STomi Valkeinen static int viafb_dvp1_proc_show(struct seq_file *m, void *v) 1200f7018c21STomi Valkeinen { 1201f7018c21STomi Valkeinen u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0; 1202f7018c21STomi Valkeinen dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f; 1203f7018c21STomi Valkeinen dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2; 1204f7018c21STomi Valkeinen dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03; 1205f7018c21STomi Valkeinen seq_printf(m, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri); 1206f7018c21STomi Valkeinen return 0; 1207f7018c21STomi Valkeinen } 1208f7018c21STomi Valkeinen 1209f7018c21STomi Valkeinen static int viafb_dvp1_proc_open(struct inode *inode, struct file *file) 1210f7018c21STomi Valkeinen { 1211f7018c21STomi Valkeinen return single_open(file, viafb_dvp1_proc_show, NULL); 1212f7018c21STomi Valkeinen } 1213f7018c21STomi Valkeinen 1214f7018c21STomi Valkeinen static ssize_t viafb_dvp1_proc_write(struct file *file, 1215f7018c21STomi Valkeinen const char __user *buffer, size_t count, loff_t *pos) 1216f7018c21STomi Valkeinen { 1217f7018c21STomi Valkeinen char buf[20], *value, *pbuf; 1218f7018c21STomi Valkeinen u8 reg_val = 0; 1219f7018c21STomi Valkeinen unsigned long length, i; 1220f7018c21STomi Valkeinen if (count < 1) 1221f7018c21STomi Valkeinen return -EINVAL; 1222f7018c21STomi Valkeinen length = count > 20 ? 20 : count; 1223f7018c21STomi Valkeinen if (copy_from_user(&buf[0], buffer, length)) 1224f7018c21STomi Valkeinen return -EFAULT; 1225f7018c21STomi Valkeinen buf[length - 1] = '\0'; /*Ensure end string */ 1226f7018c21STomi Valkeinen pbuf = &buf[0]; 1227f7018c21STomi Valkeinen for (i = 0; i < 3; i++) { 1228f7018c21STomi Valkeinen value = strsep(&pbuf, " "); 1229f7018c21STomi Valkeinen if (value != NULL) { 1230f7018c21STomi Valkeinen if (kstrtou8(value, 0, ®_val) < 0) 1231f7018c21STomi Valkeinen return -EINVAL; 1232f7018c21STomi Valkeinen switch (i) { 1233f7018c21STomi Valkeinen case 0: 1234f7018c21STomi Valkeinen viafb_write_reg_mask(CR9B, VIACR, 1235f7018c21STomi Valkeinen reg_val, 0x0f); 1236f7018c21STomi Valkeinen break; 1237f7018c21STomi Valkeinen case 1: 1238f7018c21STomi Valkeinen viafb_write_reg_mask(SR65, VIASR, 1239f7018c21STomi Valkeinen reg_val << 2, 0x0c); 1240f7018c21STomi Valkeinen break; 1241f7018c21STomi Valkeinen case 2: 1242f7018c21STomi Valkeinen viafb_write_reg_mask(SR65, VIASR, 1243f7018c21STomi Valkeinen reg_val, 0x03); 1244f7018c21STomi Valkeinen break; 1245f7018c21STomi Valkeinen default: 1246f7018c21STomi Valkeinen break; 1247f7018c21STomi Valkeinen } 1248f7018c21STomi Valkeinen } else { 1249f7018c21STomi Valkeinen break; 1250f7018c21STomi Valkeinen } 1251f7018c21STomi Valkeinen } 1252f7018c21STomi Valkeinen return count; 1253f7018c21STomi Valkeinen } 1254f7018c21STomi Valkeinen 1255f7018c21STomi Valkeinen static const struct file_operations viafb_dvp1_proc_fops = { 1256f7018c21STomi Valkeinen .owner = THIS_MODULE, 1257f7018c21STomi Valkeinen .open = viafb_dvp1_proc_open, 1258f7018c21STomi Valkeinen .read = seq_read, 1259f7018c21STomi Valkeinen .llseek = seq_lseek, 1260f7018c21STomi Valkeinen .release = single_release, 1261f7018c21STomi Valkeinen .write = viafb_dvp1_proc_write, 1262f7018c21STomi Valkeinen }; 1263f7018c21STomi Valkeinen 1264f7018c21STomi Valkeinen static int viafb_dfph_proc_show(struct seq_file *m, void *v) 1265f7018c21STomi Valkeinen { 1266f7018c21STomi Valkeinen u8 dfp_high = 0; 1267f7018c21STomi Valkeinen dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f; 1268f7018c21STomi Valkeinen seq_printf(m, "%x\n", dfp_high); 1269f7018c21STomi Valkeinen return 0; 1270f7018c21STomi Valkeinen } 1271f7018c21STomi Valkeinen 1272f7018c21STomi Valkeinen static int viafb_dfph_proc_open(struct inode *inode, struct file *file) 1273f7018c21STomi Valkeinen { 1274f7018c21STomi Valkeinen return single_open(file, viafb_dfph_proc_show, NULL); 1275f7018c21STomi Valkeinen } 1276f7018c21STomi Valkeinen 1277f7018c21STomi Valkeinen static ssize_t viafb_dfph_proc_write(struct file *file, 1278f7018c21STomi Valkeinen const char __user *buffer, size_t count, loff_t *pos) 1279f7018c21STomi Valkeinen { 1280f7018c21STomi Valkeinen int err; 1281f7018c21STomi Valkeinen u8 reg_val; 1282f7018c21STomi Valkeinen err = kstrtou8_from_user(buffer, count, 0, ®_val); 1283f7018c21STomi Valkeinen if (err) 1284f7018c21STomi Valkeinen return err; 1285f7018c21STomi Valkeinen 1286f7018c21STomi Valkeinen viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); 1287f7018c21STomi Valkeinen return count; 1288f7018c21STomi Valkeinen } 1289f7018c21STomi Valkeinen 1290f7018c21STomi Valkeinen static const struct file_operations viafb_dfph_proc_fops = { 1291f7018c21STomi Valkeinen .owner = THIS_MODULE, 1292f7018c21STomi Valkeinen .open = viafb_dfph_proc_open, 1293f7018c21STomi Valkeinen .read = seq_read, 1294f7018c21STomi Valkeinen .llseek = seq_lseek, 1295f7018c21STomi Valkeinen .release = single_release, 1296f7018c21STomi Valkeinen .write = viafb_dfph_proc_write, 1297f7018c21STomi Valkeinen }; 1298f7018c21STomi Valkeinen 1299f7018c21STomi Valkeinen static int viafb_dfpl_proc_show(struct seq_file *m, void *v) 1300f7018c21STomi Valkeinen { 1301f7018c21STomi Valkeinen u8 dfp_low = 0; 1302f7018c21STomi Valkeinen dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f; 1303f7018c21STomi Valkeinen seq_printf(m, "%x\n", dfp_low); 1304f7018c21STomi Valkeinen return 0; 1305f7018c21STomi Valkeinen } 1306f7018c21STomi Valkeinen 1307f7018c21STomi Valkeinen static int viafb_dfpl_proc_open(struct inode *inode, struct file *file) 1308f7018c21STomi Valkeinen { 1309f7018c21STomi Valkeinen return single_open(file, viafb_dfpl_proc_show, NULL); 1310f7018c21STomi Valkeinen } 1311f7018c21STomi Valkeinen 1312f7018c21STomi Valkeinen static ssize_t viafb_dfpl_proc_write(struct file *file, 1313f7018c21STomi Valkeinen const char __user *buffer, size_t count, loff_t *pos) 1314f7018c21STomi Valkeinen { 1315f7018c21STomi Valkeinen int err; 1316f7018c21STomi Valkeinen u8 reg_val; 1317f7018c21STomi Valkeinen err = kstrtou8_from_user(buffer, count, 0, ®_val); 1318f7018c21STomi Valkeinen if (err) 1319f7018c21STomi Valkeinen return err; 1320f7018c21STomi Valkeinen 1321f7018c21STomi Valkeinen viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); 1322f7018c21STomi Valkeinen return count; 1323f7018c21STomi Valkeinen } 1324f7018c21STomi Valkeinen 1325f7018c21STomi Valkeinen static const struct file_operations viafb_dfpl_proc_fops = { 1326f7018c21STomi Valkeinen .owner = THIS_MODULE, 1327f7018c21STomi Valkeinen .open = viafb_dfpl_proc_open, 1328f7018c21STomi Valkeinen .read = seq_read, 1329f7018c21STomi Valkeinen .llseek = seq_lseek, 1330f7018c21STomi Valkeinen .release = single_release, 1331f7018c21STomi Valkeinen .write = viafb_dfpl_proc_write, 1332f7018c21STomi Valkeinen }; 1333f7018c21STomi Valkeinen 1334f7018c21STomi Valkeinen static int viafb_vt1636_proc_show(struct seq_file *m, void *v) 1335f7018c21STomi Valkeinen { 1336f7018c21STomi Valkeinen u8 vt1636_08 = 0, vt1636_09 = 0; 1337f7018c21STomi Valkeinen switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { 1338f7018c21STomi Valkeinen case VT1636_LVDS: 1339f7018c21STomi Valkeinen vt1636_08 = 1340f7018c21STomi Valkeinen viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info, 1341f7018c21STomi Valkeinen &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f; 1342f7018c21STomi Valkeinen vt1636_09 = 1343f7018c21STomi Valkeinen viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info, 1344f7018c21STomi Valkeinen &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f; 1345f7018c21STomi Valkeinen seq_printf(m, "%x %x\n", vt1636_08, vt1636_09); 1346f7018c21STomi Valkeinen break; 1347f7018c21STomi Valkeinen default: 1348f7018c21STomi Valkeinen break; 1349f7018c21STomi Valkeinen } 1350f7018c21STomi Valkeinen switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { 1351f7018c21STomi Valkeinen case VT1636_LVDS: 1352f7018c21STomi Valkeinen vt1636_08 = 1353f7018c21STomi Valkeinen viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2, 1354f7018c21STomi Valkeinen &viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f; 1355f7018c21STomi Valkeinen vt1636_09 = 1356f7018c21STomi Valkeinen viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2, 1357f7018c21STomi Valkeinen &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f; 1358f7018c21STomi Valkeinen seq_printf(m, " %x %x\n", vt1636_08, vt1636_09); 1359f7018c21STomi Valkeinen break; 1360f7018c21STomi Valkeinen default: 1361f7018c21STomi Valkeinen break; 1362f7018c21STomi Valkeinen } 1363f7018c21STomi Valkeinen return 0; 1364f7018c21STomi Valkeinen } 1365f7018c21STomi Valkeinen 1366f7018c21STomi Valkeinen static int viafb_vt1636_proc_open(struct inode *inode, struct file *file) 1367f7018c21STomi Valkeinen { 1368f7018c21STomi Valkeinen return single_open(file, viafb_vt1636_proc_show, NULL); 1369f7018c21STomi Valkeinen } 1370f7018c21STomi Valkeinen 1371f7018c21STomi Valkeinen static ssize_t viafb_vt1636_proc_write(struct file *file, 1372f7018c21STomi Valkeinen const char __user *buffer, size_t count, loff_t *pos) 1373f7018c21STomi Valkeinen { 1374f7018c21STomi Valkeinen char buf[30], *value, *pbuf; 1375f7018c21STomi Valkeinen struct IODATA reg_val; 1376f7018c21STomi Valkeinen unsigned long length, i; 1377f7018c21STomi Valkeinen if (count < 1) 1378f7018c21STomi Valkeinen return -EINVAL; 1379f7018c21STomi Valkeinen length = count > 30 ? 30 : count; 1380f7018c21STomi Valkeinen if (copy_from_user(&buf[0], buffer, length)) 1381f7018c21STomi Valkeinen return -EFAULT; 1382f7018c21STomi Valkeinen buf[length - 1] = '\0'; /*Ensure end string */ 1383f7018c21STomi Valkeinen pbuf = &buf[0]; 1384f7018c21STomi Valkeinen switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { 1385f7018c21STomi Valkeinen case VT1636_LVDS: 1386f7018c21STomi Valkeinen for (i = 0; i < 2; i++) { 1387f7018c21STomi Valkeinen value = strsep(&pbuf, " "); 1388f7018c21STomi Valkeinen if (value != NULL) { 1389f7018c21STomi Valkeinen if (kstrtou8(value, 0, ®_val.Data) < 0) 1390f7018c21STomi Valkeinen return -EINVAL; 1391f7018c21STomi Valkeinen switch (i) { 1392f7018c21STomi Valkeinen case 0: 1393f7018c21STomi Valkeinen reg_val.Index = 0x08; 1394f7018c21STomi Valkeinen reg_val.Mask = 0x0f; 1395f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds 1396f7018c21STomi Valkeinen (viaparinfo->lvds_setting_info, 1397f7018c21STomi Valkeinen &viaparinfo-> 1398f7018c21STomi Valkeinen chip_info->lvds_chip_info, 1399f7018c21STomi Valkeinen reg_val); 1400f7018c21STomi Valkeinen break; 1401f7018c21STomi Valkeinen case 1: 1402f7018c21STomi Valkeinen reg_val.Index = 0x09; 1403f7018c21STomi Valkeinen reg_val.Mask = 0x1f; 1404f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds 1405f7018c21STomi Valkeinen (viaparinfo->lvds_setting_info, 1406f7018c21STomi Valkeinen &viaparinfo-> 1407f7018c21STomi Valkeinen chip_info->lvds_chip_info, 1408f7018c21STomi Valkeinen reg_val); 1409f7018c21STomi Valkeinen break; 1410f7018c21STomi Valkeinen default: 1411f7018c21STomi Valkeinen break; 1412f7018c21STomi Valkeinen } 1413f7018c21STomi Valkeinen } else { 1414f7018c21STomi Valkeinen break; 1415f7018c21STomi Valkeinen } 1416f7018c21STomi Valkeinen } 1417f7018c21STomi Valkeinen break; 1418f7018c21STomi Valkeinen default: 1419f7018c21STomi Valkeinen break; 1420f7018c21STomi Valkeinen } 1421f7018c21STomi Valkeinen switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { 1422f7018c21STomi Valkeinen case VT1636_LVDS: 1423f7018c21STomi Valkeinen for (i = 0; i < 2; i++) { 1424f7018c21STomi Valkeinen value = strsep(&pbuf, " "); 1425f7018c21STomi Valkeinen if (value != NULL) { 1426f7018c21STomi Valkeinen if (kstrtou8(value, 0, ®_val.Data) < 0) 1427f7018c21STomi Valkeinen return -EINVAL; 1428f7018c21STomi Valkeinen switch (i) { 1429f7018c21STomi Valkeinen case 0: 1430f7018c21STomi Valkeinen reg_val.Index = 0x08; 1431f7018c21STomi Valkeinen reg_val.Mask = 0x0f; 1432f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds 1433f7018c21STomi Valkeinen (viaparinfo->lvds_setting_info2, 1434f7018c21STomi Valkeinen &viaparinfo-> 1435f7018c21STomi Valkeinen chip_info->lvds_chip_info2, 1436f7018c21STomi Valkeinen reg_val); 1437f7018c21STomi Valkeinen break; 1438f7018c21STomi Valkeinen case 1: 1439f7018c21STomi Valkeinen reg_val.Index = 0x09; 1440f7018c21STomi Valkeinen reg_val.Mask = 0x1f; 1441f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds 1442f7018c21STomi Valkeinen (viaparinfo->lvds_setting_info2, 1443f7018c21STomi Valkeinen &viaparinfo-> 1444f7018c21STomi Valkeinen chip_info->lvds_chip_info2, 1445f7018c21STomi Valkeinen reg_val); 1446f7018c21STomi Valkeinen break; 1447f7018c21STomi Valkeinen default: 1448f7018c21STomi Valkeinen break; 1449f7018c21STomi Valkeinen } 1450f7018c21STomi Valkeinen } else { 1451f7018c21STomi Valkeinen break; 1452f7018c21STomi Valkeinen } 1453f7018c21STomi Valkeinen } 1454f7018c21STomi Valkeinen break; 1455f7018c21STomi Valkeinen default: 1456f7018c21STomi Valkeinen break; 1457f7018c21STomi Valkeinen } 1458f7018c21STomi Valkeinen return count; 1459f7018c21STomi Valkeinen } 1460f7018c21STomi Valkeinen 1461f7018c21STomi Valkeinen static const struct file_operations viafb_vt1636_proc_fops = { 1462f7018c21STomi Valkeinen .owner = THIS_MODULE, 1463f7018c21STomi Valkeinen .open = viafb_vt1636_proc_open, 1464f7018c21STomi Valkeinen .read = seq_read, 1465f7018c21STomi Valkeinen .llseek = seq_lseek, 1466f7018c21STomi Valkeinen .release = single_release, 1467f7018c21STomi Valkeinen .write = viafb_vt1636_proc_write, 1468f7018c21STomi Valkeinen }; 1469f7018c21STomi Valkeinen 1470f7018c21STomi Valkeinen #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */ 1471f7018c21STomi Valkeinen 1472b6566b47SRandy Dunlap static int __maybe_unused viafb_sup_odev_proc_show(struct seq_file *m, void *v) 1473f7018c21STomi Valkeinen { 1474f7018c21STomi Valkeinen via_odev_to_seq(m, supported_odev_map[ 1475f7018c21STomi Valkeinen viaparinfo->shared->chip_info.gfx_chip_name]); 1476f7018c21STomi Valkeinen return 0; 1477f7018c21STomi Valkeinen } 1478f7018c21STomi Valkeinen 1479f7018c21STomi Valkeinen static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev) 1480f7018c21STomi Valkeinen { 1481f7018c21STomi Valkeinen char buf[64], *ptr = buf; 1482f7018c21STomi Valkeinen u32 devices; 1483f7018c21STomi Valkeinen bool add, sub; 1484f7018c21STomi Valkeinen 1485f7018c21STomi Valkeinen if (count < 1 || count > 63) 1486f7018c21STomi Valkeinen return -EINVAL; 1487f7018c21STomi Valkeinen if (copy_from_user(&buf[0], buffer, count)) 1488f7018c21STomi Valkeinen return -EFAULT; 1489f7018c21STomi Valkeinen buf[count] = '\0'; 1490f7018c21STomi Valkeinen add = buf[0] == '+'; 1491f7018c21STomi Valkeinen sub = buf[0] == '-'; 1492f7018c21STomi Valkeinen if (add || sub) 1493f7018c21STomi Valkeinen ptr++; 1494f7018c21STomi Valkeinen devices = via_parse_odev(ptr, &ptr); 1495f7018c21STomi Valkeinen if (*ptr == '\n') 1496f7018c21STomi Valkeinen ptr++; 1497f7018c21STomi Valkeinen if (*ptr != 0) 1498f7018c21STomi Valkeinen return -EINVAL; 1499f7018c21STomi Valkeinen if (add) 1500f7018c21STomi Valkeinen *odev |= devices; 1501f7018c21STomi Valkeinen else if (sub) 1502f7018c21STomi Valkeinen *odev &= ~devices; 1503f7018c21STomi Valkeinen else 1504f7018c21STomi Valkeinen *odev = devices; 1505f7018c21STomi Valkeinen return count; 1506f7018c21STomi Valkeinen } 1507f7018c21STomi Valkeinen 1508f7018c21STomi Valkeinen static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v) 1509f7018c21STomi Valkeinen { 1510f7018c21STomi Valkeinen via_odev_to_seq(m, viaparinfo->shared->iga1_devices); 1511f7018c21STomi Valkeinen return 0; 1512f7018c21STomi Valkeinen } 1513f7018c21STomi Valkeinen 1514f7018c21STomi Valkeinen static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file) 1515f7018c21STomi Valkeinen { 1516f7018c21STomi Valkeinen return single_open(file, viafb_iga1_odev_proc_show, NULL); 1517f7018c21STomi Valkeinen } 1518f7018c21STomi Valkeinen 1519f7018c21STomi Valkeinen static ssize_t viafb_iga1_odev_proc_write(struct file *file, 1520f7018c21STomi Valkeinen const char __user *buffer, size_t count, loff_t *pos) 1521f7018c21STomi Valkeinen { 1522f7018c21STomi Valkeinen u32 dev_on, dev_off, dev_old, dev_new; 1523f7018c21STomi Valkeinen ssize_t res; 1524f7018c21STomi Valkeinen 1525f7018c21STomi Valkeinen dev_old = dev_new = viaparinfo->shared->iga1_devices; 1526f7018c21STomi Valkeinen res = odev_update(buffer, count, &dev_new); 1527f7018c21STomi Valkeinen if (res != count) 1528f7018c21STomi Valkeinen return res; 1529f7018c21STomi Valkeinen dev_off = dev_old & ~dev_new; 1530f7018c21STomi Valkeinen dev_on = dev_new & ~dev_old; 1531f7018c21STomi Valkeinen viaparinfo->shared->iga1_devices = dev_new; 1532f7018c21STomi Valkeinen viaparinfo->shared->iga2_devices &= ~dev_new; 1533f7018c21STomi Valkeinen via_set_state(dev_off, VIA_STATE_OFF); 1534f7018c21STomi Valkeinen via_set_source(dev_new, IGA1); 1535f7018c21STomi Valkeinen via_set_state(dev_on, VIA_STATE_ON); 1536f7018c21STomi Valkeinen return res; 1537f7018c21STomi Valkeinen } 1538f7018c21STomi Valkeinen 1539f7018c21STomi Valkeinen static const struct file_operations viafb_iga1_odev_proc_fops = { 1540f7018c21STomi Valkeinen .owner = THIS_MODULE, 1541f7018c21STomi Valkeinen .open = viafb_iga1_odev_proc_open, 1542f7018c21STomi Valkeinen .read = seq_read, 1543f7018c21STomi Valkeinen .llseek = seq_lseek, 1544f7018c21STomi Valkeinen .release = single_release, 1545f7018c21STomi Valkeinen .write = viafb_iga1_odev_proc_write, 1546f7018c21STomi Valkeinen }; 1547f7018c21STomi Valkeinen 1548f7018c21STomi Valkeinen static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v) 1549f7018c21STomi Valkeinen { 1550f7018c21STomi Valkeinen via_odev_to_seq(m, viaparinfo->shared->iga2_devices); 1551f7018c21STomi Valkeinen return 0; 1552f7018c21STomi Valkeinen } 1553f7018c21STomi Valkeinen 1554f7018c21STomi Valkeinen static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file) 1555f7018c21STomi Valkeinen { 1556f7018c21STomi Valkeinen return single_open(file, viafb_iga2_odev_proc_show, NULL); 1557f7018c21STomi Valkeinen } 1558f7018c21STomi Valkeinen 1559f7018c21STomi Valkeinen static ssize_t viafb_iga2_odev_proc_write(struct file *file, 1560f7018c21STomi Valkeinen const char __user *buffer, size_t count, loff_t *pos) 1561f7018c21STomi Valkeinen { 1562f7018c21STomi Valkeinen u32 dev_on, dev_off, dev_old, dev_new; 1563f7018c21STomi Valkeinen ssize_t res; 1564f7018c21STomi Valkeinen 1565f7018c21STomi Valkeinen dev_old = dev_new = viaparinfo->shared->iga2_devices; 1566f7018c21STomi Valkeinen res = odev_update(buffer, count, &dev_new); 1567f7018c21STomi Valkeinen if (res != count) 1568f7018c21STomi Valkeinen return res; 1569f7018c21STomi Valkeinen dev_off = dev_old & ~dev_new; 1570f7018c21STomi Valkeinen dev_on = dev_new & ~dev_old; 1571f7018c21STomi Valkeinen viaparinfo->shared->iga2_devices = dev_new; 1572f7018c21STomi Valkeinen viaparinfo->shared->iga1_devices &= ~dev_new; 1573f7018c21STomi Valkeinen via_set_state(dev_off, VIA_STATE_OFF); 1574f7018c21STomi Valkeinen via_set_source(dev_new, IGA2); 1575f7018c21STomi Valkeinen via_set_state(dev_on, VIA_STATE_ON); 1576f7018c21STomi Valkeinen return res; 1577f7018c21STomi Valkeinen } 1578f7018c21STomi Valkeinen 1579f7018c21STomi Valkeinen static const struct file_operations viafb_iga2_odev_proc_fops = { 1580f7018c21STomi Valkeinen .owner = THIS_MODULE, 1581f7018c21STomi Valkeinen .open = viafb_iga2_odev_proc_open, 1582f7018c21STomi Valkeinen .read = seq_read, 1583f7018c21STomi Valkeinen .llseek = seq_lseek, 1584f7018c21STomi Valkeinen .release = single_release, 1585f7018c21STomi Valkeinen .write = viafb_iga2_odev_proc_write, 1586f7018c21STomi Valkeinen }; 1587f7018c21STomi Valkeinen 1588f7018c21STomi Valkeinen #define IS_VT1636(lvds_chip) ((lvds_chip).lvds_chip_name == VT1636_LVDS) 1589f7018c21STomi Valkeinen static void viafb_init_proc(struct viafb_shared *shared) 1590f7018c21STomi Valkeinen { 1591f7018c21STomi Valkeinen struct proc_dir_entry *iga1_entry, *iga2_entry, 1592f7018c21STomi Valkeinen *viafb_entry = proc_mkdir("viafb", NULL); 1593f7018c21STomi Valkeinen 1594f7018c21STomi Valkeinen shared->proc_entry = viafb_entry; 1595f7018c21STomi Valkeinen if (viafb_entry) { 1596f7018c21STomi Valkeinen #ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1597f7018c21STomi Valkeinen proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops); 1598f7018c21STomi Valkeinen proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops); 1599f7018c21STomi Valkeinen proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops); 1600f7018c21STomi Valkeinen proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops); 1601f7018c21STomi Valkeinen if (IS_VT1636(shared->chip_info.lvds_chip_info) 1602f7018c21STomi Valkeinen || IS_VT1636(shared->chip_info.lvds_chip_info2)) 1603f7018c21STomi Valkeinen proc_create("vt1636", 0, viafb_entry, 1604f7018c21STomi Valkeinen &viafb_vt1636_proc_fops); 1605f7018c21STomi Valkeinen #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */ 1606f7018c21STomi Valkeinen 16073f3942acSChristoph Hellwig proc_create_single("supported_output_devices", 0, viafb_entry, 16083f3942acSChristoph Hellwig viafb_sup_odev_proc_show); 1609f7018c21STomi Valkeinen iga1_entry = proc_mkdir("iga1", viafb_entry); 1610f7018c21STomi Valkeinen shared->iga1_proc_entry = iga1_entry; 1611f7018c21STomi Valkeinen proc_create("output_devices", 0, iga1_entry, 1612f7018c21STomi Valkeinen &viafb_iga1_odev_proc_fops); 1613f7018c21STomi Valkeinen iga2_entry = proc_mkdir("iga2", viafb_entry); 1614f7018c21STomi Valkeinen shared->iga2_proc_entry = iga2_entry; 1615f7018c21STomi Valkeinen proc_create("output_devices", 0, iga2_entry, 1616f7018c21STomi Valkeinen &viafb_iga2_odev_proc_fops); 1617f7018c21STomi Valkeinen } 1618f7018c21STomi Valkeinen } 1619f7018c21STomi Valkeinen static void viafb_remove_proc(struct viafb_shared *shared) 1620f7018c21STomi Valkeinen { 1621484c7bbfSArnd Bergmann struct proc_dir_entry *viafb_entry = shared->proc_entry; 1622f7018c21STomi Valkeinen 1623f7018c21STomi Valkeinen if (!viafb_entry) 1624f7018c21STomi Valkeinen return; 1625f7018c21STomi Valkeinen 1626484c7bbfSArnd Bergmann remove_proc_entry("output_devices", shared->iga2_proc_entry); 1627f7018c21STomi Valkeinen remove_proc_entry("iga2", viafb_entry); 1628484c7bbfSArnd Bergmann remove_proc_entry("output_devices", shared->iga1_proc_entry); 1629f7018c21STomi Valkeinen remove_proc_entry("iga1", viafb_entry); 1630f7018c21STomi Valkeinen remove_proc_entry("supported_output_devices", viafb_entry); 1631f7018c21STomi Valkeinen 1632f7018c21STomi Valkeinen #ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1633f7018c21STomi Valkeinen remove_proc_entry("dvp0", viafb_entry);/* parent dir */ 1634f7018c21STomi Valkeinen remove_proc_entry("dvp1", viafb_entry); 1635f7018c21STomi Valkeinen remove_proc_entry("dfph", viafb_entry); 1636f7018c21STomi Valkeinen remove_proc_entry("dfpl", viafb_entry); 1637f7018c21STomi Valkeinen if (IS_VT1636(shared->chip_info.lvds_chip_info) 1638f7018c21STomi Valkeinen || IS_VT1636(shared->chip_info.lvds_chip_info2)) 1639f7018c21STomi Valkeinen remove_proc_entry("vt1636", viafb_entry); 1640f7018c21STomi Valkeinen #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */ 1641f7018c21STomi Valkeinen 1642f7018c21STomi Valkeinen remove_proc_entry("viafb", NULL); 1643f7018c21STomi Valkeinen } 1644f7018c21STomi Valkeinen #undef IS_VT1636 1645f7018c21STomi Valkeinen 1646f7018c21STomi Valkeinen static int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres) 1647f7018c21STomi Valkeinen { 1648f7018c21STomi Valkeinen const struct fb_videomode *mode = NULL; 1649f7018c21STomi Valkeinen char *ptr; 1650f7018c21STomi Valkeinen 1651f7018c21STomi Valkeinen if (!str) { 1652f7018c21STomi Valkeinen if (devices == VIA_CRT) 1653f7018c21STomi Valkeinen mode = via_aux_get_preferred_mode( 1654f7018c21STomi Valkeinen viaparinfo->shared->i2c_26); 1655f7018c21STomi Valkeinen else if (devices == VIA_DVP1) 1656f7018c21STomi Valkeinen mode = via_aux_get_preferred_mode( 1657f7018c21STomi Valkeinen viaparinfo->shared->i2c_31); 1658f7018c21STomi Valkeinen 1659f7018c21STomi Valkeinen if (mode) { 1660f7018c21STomi Valkeinen *xres = mode->xres; 1661f7018c21STomi Valkeinen *yres = mode->yres; 1662f7018c21STomi Valkeinen } else if (machine_is_olpc()) { 1663f7018c21STomi Valkeinen *xres = 1200; 1664f7018c21STomi Valkeinen *yres = 900; 1665f7018c21STomi Valkeinen } else { 1666f7018c21STomi Valkeinen *xres = 640; 1667f7018c21STomi Valkeinen *yres = 480; 1668f7018c21STomi Valkeinen } 1669f7018c21STomi Valkeinen return 0; 1670f7018c21STomi Valkeinen } 1671f7018c21STomi Valkeinen 1672f7018c21STomi Valkeinen *xres = simple_strtoul(str, &ptr, 10); 1673f7018c21STomi Valkeinen if (ptr[0] != 'x') 1674f7018c21STomi Valkeinen return -EINVAL; 1675f7018c21STomi Valkeinen 1676f7018c21STomi Valkeinen *yres = simple_strtoul(&ptr[1], &ptr, 10); 1677f7018c21STomi Valkeinen if (ptr[0]) 1678f7018c21STomi Valkeinen return -EINVAL; 1679f7018c21STomi Valkeinen 1680f7018c21STomi Valkeinen return 0; 1681f7018c21STomi Valkeinen } 1682f7018c21STomi Valkeinen 1683f7018c21STomi Valkeinen 1684f7018c21STomi Valkeinen #ifdef CONFIG_PM 1685f7018c21STomi Valkeinen static int viafb_suspend(void *unused) 1686f7018c21STomi Valkeinen { 1687f7018c21STomi Valkeinen console_lock(); 1688f7018c21STomi Valkeinen fb_set_suspend(viafbinfo, 1); 1689f7018c21STomi Valkeinen viafb_sync(viafbinfo); 1690f7018c21STomi Valkeinen console_unlock(); 1691f7018c21STomi Valkeinen 1692f7018c21STomi Valkeinen return 0; 1693f7018c21STomi Valkeinen } 1694f7018c21STomi Valkeinen 1695f7018c21STomi Valkeinen static int viafb_resume(void *unused) 1696f7018c21STomi Valkeinen { 1697f7018c21STomi Valkeinen console_lock(); 1698f7018c21STomi Valkeinen if (viaparinfo->shared->vdev->engine_mmio) 1699f7018c21STomi Valkeinen viafb_reset_engine(viaparinfo); 1700f7018c21STomi Valkeinen viafb_set_par(viafbinfo); 1701f7018c21STomi Valkeinen if (viafb_dual_fb) 1702f7018c21STomi Valkeinen viafb_set_par(viafbinfo1); 1703f7018c21STomi Valkeinen fb_set_suspend(viafbinfo, 0); 1704f7018c21STomi Valkeinen 1705f7018c21STomi Valkeinen console_unlock(); 1706f7018c21STomi Valkeinen return 0; 1707f7018c21STomi Valkeinen } 1708f7018c21STomi Valkeinen 1709f7018c21STomi Valkeinen static struct viafb_pm_hooks viafb_fb_pm_hooks = { 1710f7018c21STomi Valkeinen .suspend = viafb_suspend, 1711f7018c21STomi Valkeinen .resume = viafb_resume 1712f7018c21STomi Valkeinen }; 1713f7018c21STomi Valkeinen 1714f7018c21STomi Valkeinen #endif 1715f7018c21STomi Valkeinen 1716f7018c21STomi Valkeinen static void i2c_bus_probe(struct viafb_shared *shared) 1717f7018c21STomi Valkeinen { 1718f7018c21STomi Valkeinen /* should be always CRT */ 1719f7018c21STomi Valkeinen printk(KERN_INFO "viafb: Probing I2C bus 0x26\n"); 1720f7018c21STomi Valkeinen shared->i2c_26 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_26)); 1721f7018c21STomi Valkeinen 1722f7018c21STomi Valkeinen /* seems to be usually DVP1 */ 1723f7018c21STomi Valkeinen printk(KERN_INFO "viafb: Probing I2C bus 0x31\n"); 1724f7018c21STomi Valkeinen shared->i2c_31 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_31)); 1725f7018c21STomi Valkeinen 1726f7018c21STomi Valkeinen /* FIXME: what is this? */ 1727f7018c21STomi Valkeinen if (!machine_is_olpc()) { 1728f7018c21STomi Valkeinen printk(KERN_INFO "viafb: Probing I2C bus 0x2C\n"); 1729f7018c21STomi Valkeinen shared->i2c_2C = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_2C)); 1730f7018c21STomi Valkeinen } 1731f7018c21STomi Valkeinen 1732f7018c21STomi Valkeinen printk(KERN_INFO "viafb: Finished I2C bus probing"); 1733f7018c21STomi Valkeinen } 1734f7018c21STomi Valkeinen 1735f7018c21STomi Valkeinen static void i2c_bus_free(struct viafb_shared *shared) 1736f7018c21STomi Valkeinen { 1737f7018c21STomi Valkeinen via_aux_free(shared->i2c_26); 1738f7018c21STomi Valkeinen via_aux_free(shared->i2c_31); 1739f7018c21STomi Valkeinen via_aux_free(shared->i2c_2C); 1740f7018c21STomi Valkeinen } 1741f7018c21STomi Valkeinen 1742f7018c21STomi Valkeinen int via_fb_pci_probe(struct viafb_dev *vdev) 1743f7018c21STomi Valkeinen { 1744f7018c21STomi Valkeinen u32 default_xres, default_yres; 1745f7018c21STomi Valkeinen struct fb_var_screeninfo default_var; 1746f7018c21STomi Valkeinen int rc; 1747f7018c21STomi Valkeinen u32 viafb_par_length; 1748f7018c21STomi Valkeinen 1749f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); 1750f7018c21STomi Valkeinen memset(&default_var, 0, sizeof(default_var)); 1751f7018c21STomi Valkeinen viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); 1752f7018c21STomi Valkeinen 1753f7018c21STomi Valkeinen /* Allocate fb_info and ***_par here, also including some other needed 1754f7018c21STomi Valkeinen * variables 1755f7018c21STomi Valkeinen */ 1756f7018c21STomi Valkeinen viafbinfo = framebuffer_alloc(viafb_par_length + 1757f7018c21STomi Valkeinen ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8), 1758f7018c21STomi Valkeinen &vdev->pdev->dev); 1759f7018c21STomi Valkeinen if (!viafbinfo) { 1760f7018c21STomi Valkeinen printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); 1761f7018c21STomi Valkeinen return -ENOMEM; 1762f7018c21STomi Valkeinen } 1763f7018c21STomi Valkeinen 1764f7018c21STomi Valkeinen viaparinfo = (struct viafb_par *)viafbinfo->par; 1765f7018c21STomi Valkeinen viaparinfo->shared = viafbinfo->par + viafb_par_length; 1766f7018c21STomi Valkeinen viaparinfo->shared->vdev = vdev; 1767f7018c21STomi Valkeinen viaparinfo->vram_addr = 0; 1768f7018c21STomi Valkeinen viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info; 1769f7018c21STomi Valkeinen viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info; 1770f7018c21STomi Valkeinen viaparinfo->lvds_setting_info2 = 1771f7018c21STomi Valkeinen &viaparinfo->shared->lvds_setting_info2; 1772f7018c21STomi Valkeinen viaparinfo->chip_info = &viaparinfo->shared->chip_info; 1773f7018c21STomi Valkeinen 1774f7018c21STomi Valkeinen i2c_bus_probe(viaparinfo->shared); 1775f7018c21STomi Valkeinen if (viafb_dual_fb) 1776f7018c21STomi Valkeinen viafb_SAMM_ON = 1; 1777f7018c21STomi Valkeinen parse_lcd_port(); 1778f7018c21STomi Valkeinen parse_dvi_port(); 1779f7018c21STomi Valkeinen 1780f7018c21STomi Valkeinen viafb_init_chip_info(vdev->chip_type); 1781f7018c21STomi Valkeinen /* 1782f7018c21STomi Valkeinen * The framebuffer will have been successfully mapped by 1783f7018c21STomi Valkeinen * the core (or we'd not be here), but we still need to 1784f7018c21STomi Valkeinen * set up our own accounting. 1785f7018c21STomi Valkeinen */ 1786f7018c21STomi Valkeinen viaparinfo->fbmem = vdev->fbmem_start; 1787f7018c21STomi Valkeinen viaparinfo->memsize = vdev->fbmem_len; 1788f7018c21STomi Valkeinen viaparinfo->fbmem_free = viaparinfo->memsize; 1789f7018c21STomi Valkeinen viaparinfo->fbmem_used = 0; 1790f7018c21STomi Valkeinen viafbinfo->screen_base = vdev->fbmem; 1791f7018c21STomi Valkeinen 1792f7018c21STomi Valkeinen viafbinfo->fix.mmio_start = vdev->engine_start; 1793f7018c21STomi Valkeinen viafbinfo->fix.mmio_len = vdev->engine_len; 1794f7018c21STomi Valkeinen viafbinfo->node = 0; 1795f7018c21STomi Valkeinen viafbinfo->fbops = &viafb_ops; 1796f7018c21STomi Valkeinen viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1797f7018c21STomi Valkeinen 1798f7018c21STomi Valkeinen viafbinfo->pseudo_palette = pseudo_pal; 1799f7018c21STomi Valkeinen if (viafb_accel && !viafb_setup_engine(viafbinfo)) { 1800f7018c21STomi Valkeinen viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA | 1801f7018c21STomi Valkeinen FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; 1802f7018c21STomi Valkeinen default_var.accel_flags = FB_ACCELF_TEXT; 1803f7018c21STomi Valkeinen } else { 1804f7018c21STomi Valkeinen viafbinfo->flags |= FBINFO_HWACCEL_DISABLED; 1805f7018c21STomi Valkeinen default_var.accel_flags = 0; 1806f7018c21STomi Valkeinen } 1807f7018c21STomi Valkeinen 1808f7018c21STomi Valkeinen if (viafb_second_size && (viafb_second_size < 8)) { 1809f7018c21STomi Valkeinen viafb_second_offset = viaparinfo->fbmem_free - 1810f7018c21STomi Valkeinen viafb_second_size * 1024 * 1024; 1811f7018c21STomi Valkeinen } else { 1812f7018c21STomi Valkeinen viafb_second_size = 8; 1813f7018c21STomi Valkeinen viafb_second_offset = viaparinfo->fbmem_free - 1814f7018c21STomi Valkeinen viafb_second_size * 1024 * 1024; 1815f7018c21STomi Valkeinen } 1816f7018c21STomi Valkeinen 1817f7018c21STomi Valkeinen parse_mode(viafb_mode, viaparinfo->shared->iga1_devices, 1818f7018c21STomi Valkeinen &default_xres, &default_yres); 1819f7018c21STomi Valkeinen if (viafb_SAMM_ON == 1) 1820f7018c21STomi Valkeinen parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices, 1821f7018c21STomi Valkeinen &viafb_second_xres, &viafb_second_yres); 1822f7018c21STomi Valkeinen 1823f7018c21STomi Valkeinen default_var.xres = default_xres; 1824f7018c21STomi Valkeinen default_var.yres = default_yres; 1825f7018c21STomi Valkeinen default_var.xres_virtual = default_xres; 1826f7018c21STomi Valkeinen default_var.yres_virtual = default_yres; 1827f7018c21STomi Valkeinen default_var.bits_per_pixel = viafb_bpp; 1828f7018c21STomi Valkeinen viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( 1829f7018c21STomi Valkeinen default_var.xres, default_var.yres, viafb_refresh)); 1830f7018c21STomi Valkeinen viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); 1831f7018c21STomi Valkeinen viafbinfo->var = default_var; 1832f7018c21STomi Valkeinen 1833f7018c21STomi Valkeinen if (viafb_dual_fb) { 1834f7018c21STomi Valkeinen viafbinfo1 = framebuffer_alloc(viafb_par_length, 1835f7018c21STomi Valkeinen &vdev->pdev->dev); 1836f7018c21STomi Valkeinen if (!viafbinfo1) { 1837f7018c21STomi Valkeinen printk(KERN_ERR 1838f7018c21STomi Valkeinen "allocate the second framebuffer struct error\n"); 1839f7018c21STomi Valkeinen rc = -ENOMEM; 1840f7018c21STomi Valkeinen goto out_fb_release; 1841f7018c21STomi Valkeinen } 1842f7018c21STomi Valkeinen viaparinfo1 = viafbinfo1->par; 1843f7018c21STomi Valkeinen memcpy(viaparinfo1, viaparinfo, viafb_par_length); 1844f7018c21STomi Valkeinen viaparinfo1->vram_addr = viafb_second_offset; 1845f7018c21STomi Valkeinen viaparinfo1->memsize = viaparinfo->memsize - 1846f7018c21STomi Valkeinen viafb_second_offset; 1847f7018c21STomi Valkeinen viaparinfo->memsize = viafb_second_offset; 1848f7018c21STomi Valkeinen viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset; 1849f7018c21STomi Valkeinen 1850f7018c21STomi Valkeinen viaparinfo1->fbmem_used = viaparinfo->fbmem_used; 1851f7018c21STomi Valkeinen viaparinfo1->fbmem_free = viaparinfo1->memsize - 1852f7018c21STomi Valkeinen viaparinfo1->fbmem_used; 1853f7018c21STomi Valkeinen viaparinfo->fbmem_free = viaparinfo->memsize; 1854f7018c21STomi Valkeinen viaparinfo->fbmem_used = 0; 1855f7018c21STomi Valkeinen 1856f7018c21STomi Valkeinen viaparinfo->iga_path = IGA1; 1857f7018c21STomi Valkeinen viaparinfo1->iga_path = IGA2; 1858f7018c21STomi Valkeinen memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info)); 1859f7018c21STomi Valkeinen viafbinfo1->par = viaparinfo1; 1860f7018c21STomi Valkeinen viafbinfo1->screen_base = viafbinfo->screen_base + 1861f7018c21STomi Valkeinen viafb_second_offset; 1862f7018c21STomi Valkeinen 1863f7018c21STomi Valkeinen default_var.xres = viafb_second_xres; 1864f7018c21STomi Valkeinen default_var.yres = viafb_second_yres; 1865f7018c21STomi Valkeinen default_var.xres_virtual = viafb_second_xres; 1866f7018c21STomi Valkeinen default_var.yres_virtual = viafb_second_yres; 1867f7018c21STomi Valkeinen default_var.bits_per_pixel = viafb_bpp1; 1868f7018c21STomi Valkeinen viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( 1869f7018c21STomi Valkeinen default_var.xres, default_var.yres, viafb_refresh1)); 1870f7018c21STomi Valkeinen 1871f7018c21STomi Valkeinen viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); 1872f7018c21STomi Valkeinen viafb_check_var(&default_var, viafbinfo1); 1873f7018c21STomi Valkeinen viafbinfo1->var = default_var; 1874f7018c21STomi Valkeinen viafb_update_fix(viafbinfo1); 1875f7018c21STomi Valkeinen viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var, 1876f7018c21STomi Valkeinen &viafbinfo1->fix); 1877f7018c21STomi Valkeinen } 1878f7018c21STomi Valkeinen 1879f7018c21STomi Valkeinen viafb_check_var(&viafbinfo->var, viafbinfo); 1880f7018c21STomi Valkeinen viafb_update_fix(viafbinfo); 1881f7018c21STomi Valkeinen viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, 1882f7018c21STomi Valkeinen &viafbinfo->fix); 1883f7018c21STomi Valkeinen default_var.activate = FB_ACTIVATE_NOW; 1884f7018c21STomi Valkeinen rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0); 1885f7018c21STomi Valkeinen if (rc) 1886f7018c21STomi Valkeinen goto out_fb1_release; 1887f7018c21STomi Valkeinen 1888f7018c21STomi Valkeinen if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) 1889f7018c21STomi Valkeinen && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) { 1890f7018c21STomi Valkeinen rc = register_framebuffer(viafbinfo1); 1891f7018c21STomi Valkeinen if (rc) 1892f7018c21STomi Valkeinen goto out_dealloc_cmap; 1893f7018c21STomi Valkeinen } 1894f7018c21STomi Valkeinen rc = register_framebuffer(viafbinfo); 1895f7018c21STomi Valkeinen if (rc) 1896f7018c21STomi Valkeinen goto out_fb1_unreg_lcd_cle266; 1897f7018c21STomi Valkeinen 1898f7018c21STomi Valkeinen if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device) 1899f7018c21STomi Valkeinen || (viaparinfo->chip_info->gfx_chip_name != 1900f7018c21STomi Valkeinen UNICHROME_CLE266))) { 1901f7018c21STomi Valkeinen rc = register_framebuffer(viafbinfo1); 1902f7018c21STomi Valkeinen if (rc) 1903f7018c21STomi Valkeinen goto out_fb_unreg; 1904f7018c21STomi Valkeinen } 1905f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n", 1906f7018c21STomi Valkeinen viafbinfo->node, viafbinfo->fix.id, default_var.xres, 1907f7018c21STomi Valkeinen default_var.yres, default_var.bits_per_pixel); 1908f7018c21STomi Valkeinen 1909f7018c21STomi Valkeinen viafb_init_proc(viaparinfo->shared); 1910f7018c21STomi Valkeinen viafb_init_dac(IGA2); 1911f7018c21STomi Valkeinen 1912f7018c21STomi Valkeinen #ifdef CONFIG_PM 1913f7018c21STomi Valkeinen viafb_pm_register(&viafb_fb_pm_hooks); 1914f7018c21STomi Valkeinen #endif 1915f7018c21STomi Valkeinen return 0; 1916f7018c21STomi Valkeinen 1917f7018c21STomi Valkeinen out_fb_unreg: 1918f7018c21STomi Valkeinen unregister_framebuffer(viafbinfo); 1919f7018c21STomi Valkeinen out_fb1_unreg_lcd_cle266: 1920f7018c21STomi Valkeinen if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) 1921f7018c21STomi Valkeinen && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) 1922f7018c21STomi Valkeinen unregister_framebuffer(viafbinfo1); 1923f7018c21STomi Valkeinen out_dealloc_cmap: 1924f7018c21STomi Valkeinen fb_dealloc_cmap(&viafbinfo->cmap); 1925f7018c21STomi Valkeinen out_fb1_release: 1926f7018c21STomi Valkeinen framebuffer_release(viafbinfo1); 1927f7018c21STomi Valkeinen out_fb_release: 1928f7018c21STomi Valkeinen i2c_bus_free(viaparinfo->shared); 1929f7018c21STomi Valkeinen framebuffer_release(viafbinfo); 1930f7018c21STomi Valkeinen return rc; 1931f7018c21STomi Valkeinen } 1932f7018c21STomi Valkeinen 1933f7018c21STomi Valkeinen void via_fb_pci_remove(struct pci_dev *pdev) 1934f7018c21STomi Valkeinen { 1935f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "via_pci_remove!\n"); 1936f7018c21STomi Valkeinen fb_dealloc_cmap(&viafbinfo->cmap); 1937f7018c21STomi Valkeinen unregister_framebuffer(viafbinfo); 1938f7018c21STomi Valkeinen if (viafb_dual_fb) 1939f7018c21STomi Valkeinen unregister_framebuffer(viafbinfo1); 1940f7018c21STomi Valkeinen viafb_remove_proc(viaparinfo->shared); 1941f7018c21STomi Valkeinen i2c_bus_free(viaparinfo->shared); 1942f7018c21STomi Valkeinen framebuffer_release(viafbinfo); 1943f7018c21STomi Valkeinen if (viafb_dual_fb) 1944f7018c21STomi Valkeinen framebuffer_release(viafbinfo1); 1945f7018c21STomi Valkeinen } 1946f7018c21STomi Valkeinen 1947f7018c21STomi Valkeinen #ifndef MODULE 1948f7018c21STomi Valkeinen static int __init viafb_setup(void) 1949f7018c21STomi Valkeinen { 1950f7018c21STomi Valkeinen char *this_opt; 1951f7018c21STomi Valkeinen char *options; 1952f7018c21STomi Valkeinen 1953f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_setup!\n"); 1954f7018c21STomi Valkeinen 1955f7018c21STomi Valkeinen if (fb_get_options("viafb", &options)) 1956f7018c21STomi Valkeinen return -ENODEV; 1957f7018c21STomi Valkeinen 1958f7018c21STomi Valkeinen if (!options || !*options) 1959f7018c21STomi Valkeinen return 0; 1960f7018c21STomi Valkeinen 1961f7018c21STomi Valkeinen while ((this_opt = strsep(&options, ",")) != NULL) { 1962f7018c21STomi Valkeinen if (!*this_opt) 1963f7018c21STomi Valkeinen continue; 1964f7018c21STomi Valkeinen 1965f7018c21STomi Valkeinen if (!strncmp(this_opt, "viafb_mode1=", 12)) { 1966f7018c21STomi Valkeinen viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL); 1967f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_mode=", 11)) { 1968f7018c21STomi Valkeinen viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL); 1969f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_bpp1=", 11)) { 1970f7018c21STomi Valkeinen if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0) 1971f7018c21STomi Valkeinen return -EINVAL; 1972f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_bpp=", 10)) { 1973f7018c21STomi Valkeinen if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0) 1974f7018c21STomi Valkeinen return -EINVAL; 1975f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_refresh1=", 15)) { 1976f7018c21STomi Valkeinen if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0) 1977f7018c21STomi Valkeinen return -EINVAL; 1978f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_refresh=", 14)) { 1979f7018c21STomi Valkeinen if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0) 1980f7018c21STomi Valkeinen return -EINVAL; 1981f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) { 1982f7018c21STomi Valkeinen if (kstrtoint(this_opt + 21, 0, 1983f7018c21STomi Valkeinen &viafb_lcd_dsp_method) < 0) 1984f7018c21STomi Valkeinen return -EINVAL; 1985f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) { 1986f7018c21STomi Valkeinen if (kstrtoint(this_opt + 19, 0, 1987f7018c21STomi Valkeinen &viafb_lcd_panel_id) < 0) 1988f7018c21STomi Valkeinen return -EINVAL; 1989f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_accel=", 12)) { 1990f7018c21STomi Valkeinen if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0) 1991f7018c21STomi Valkeinen return -EINVAL; 1992f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) { 1993f7018c21STomi Valkeinen if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0) 1994f7018c21STomi Valkeinen return -EINVAL; 1995f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_active_dev=", 17)) { 1996f7018c21STomi Valkeinen viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL); 1997f7018c21STomi Valkeinen } else if (!strncmp(this_opt, 1998f7018c21STomi Valkeinen "viafb_display_hardware_layout=", 30)) { 1999f7018c21STomi Valkeinen if (kstrtoint(this_opt + 30, 0, 2000f7018c21STomi Valkeinen &viafb_display_hardware_layout) < 0) 2001f7018c21STomi Valkeinen return -EINVAL; 2002f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_second_size=", 18)) { 2003f7018c21STomi Valkeinen if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0) 2004f7018c21STomi Valkeinen return -EINVAL; 2005f7018c21STomi Valkeinen } else if (!strncmp(this_opt, 2006f7018c21STomi Valkeinen "viafb_platform_epia_dvi=", 24)) { 2007f7018c21STomi Valkeinen if (kstrtoint(this_opt + 24, 0, 2008f7018c21STomi Valkeinen &viafb_platform_epia_dvi) < 0) 2009f7018c21STomi Valkeinen return -EINVAL; 2010f7018c21STomi Valkeinen } else if (!strncmp(this_opt, 2011f7018c21STomi Valkeinen "viafb_device_lcd_dualedge=", 26)) { 2012f7018c21STomi Valkeinen if (kstrtoint(this_opt + 26, 0, 2013f7018c21STomi Valkeinen &viafb_device_lcd_dualedge) < 0) 2014f7018c21STomi Valkeinen return -EINVAL; 2015f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_bus_width=", 16)) { 2016f7018c21STomi Valkeinen if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0) 2017f7018c21STomi Valkeinen return -EINVAL; 2018f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) { 2019f7018c21STomi Valkeinen if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0) 2020f7018c21STomi Valkeinen return -EINVAL; 2021f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) { 2022f7018c21STomi Valkeinen viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); 2023f7018c21STomi Valkeinen } else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) { 2024f7018c21STomi Valkeinen viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL); 2025f7018c21STomi Valkeinen } 2026f7018c21STomi Valkeinen } 2027f7018c21STomi Valkeinen return 0; 2028f7018c21STomi Valkeinen } 2029f7018c21STomi Valkeinen #endif 2030f7018c21STomi Valkeinen 2031f7018c21STomi Valkeinen /* 2032f7018c21STomi Valkeinen * These are called out of via-core for now. 2033f7018c21STomi Valkeinen */ 2034f7018c21STomi Valkeinen int __init viafb_init(void) 2035f7018c21STomi Valkeinen { 2036f7018c21STomi Valkeinen u32 dummy_x, dummy_y; 2037f7018c21STomi Valkeinen int r = 0; 2038f7018c21STomi Valkeinen 2039f7018c21STomi Valkeinen if (machine_is_olpc()) 2040f7018c21STomi Valkeinen /* Apply XO-1.5-specific configuration. */ 2041f7018c21STomi Valkeinen viafb_lcd_panel_id = 23; 2042f7018c21STomi Valkeinen 2043f7018c21STomi Valkeinen #ifndef MODULE 2044f7018c21STomi Valkeinen r = viafb_setup(); 2045f7018c21STomi Valkeinen if (r < 0) 2046f7018c21STomi Valkeinen return r; 2047f7018c21STomi Valkeinen #endif 2048f7018c21STomi Valkeinen if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y) 2049f7018c21STomi Valkeinen || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) 2050f7018c21STomi Valkeinen || parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y) 2051f7018c21STomi Valkeinen || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) 2052f7018c21STomi Valkeinen || viafb_bpp < 0 || viafb_bpp > 32 2053f7018c21STomi Valkeinen || viafb_bpp1 < 0 || viafb_bpp1 > 32 2054f7018c21STomi Valkeinen || parse_active_dev()) 2055f7018c21STomi Valkeinen return -EINVAL; 2056f7018c21STomi Valkeinen 2057f7018c21STomi Valkeinen printk(KERN_INFO 2058f7018c21STomi Valkeinen "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n", 2059f7018c21STomi Valkeinen VERSION_MAJOR, VERSION_MINOR); 2060f7018c21STomi Valkeinen return r; 2061f7018c21STomi Valkeinen } 2062f7018c21STomi Valkeinen 2063f7018c21STomi Valkeinen void __exit viafb_exit(void) 2064f7018c21STomi Valkeinen { 2065f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_exit!\n"); 2066f7018c21STomi Valkeinen } 2067f7018c21STomi Valkeinen 2068f7018c21STomi Valkeinen static struct fb_ops viafb_ops = { 2069f7018c21STomi Valkeinen .owner = THIS_MODULE, 2070f7018c21STomi Valkeinen .fb_open = viafb_open, 2071f7018c21STomi Valkeinen .fb_release = viafb_release, 2072f7018c21STomi Valkeinen .fb_check_var = viafb_check_var, 2073f7018c21STomi Valkeinen .fb_set_par = viafb_set_par, 2074f7018c21STomi Valkeinen .fb_setcolreg = viafb_setcolreg, 2075f7018c21STomi Valkeinen .fb_pan_display = viafb_pan_display, 2076f7018c21STomi Valkeinen .fb_blank = viafb_blank, 2077f7018c21STomi Valkeinen .fb_fillrect = viafb_fillrect, 2078f7018c21STomi Valkeinen .fb_copyarea = viafb_copyarea, 2079f7018c21STomi Valkeinen .fb_imageblit = viafb_imageblit, 2080f7018c21STomi Valkeinen .fb_cursor = viafb_cursor, 2081f7018c21STomi Valkeinen .fb_ioctl = viafb_ioctl, 2082f7018c21STomi Valkeinen .fb_sync = viafb_sync, 2083f7018c21STomi Valkeinen }; 2084f7018c21STomi Valkeinen 2085f7018c21STomi Valkeinen 2086f7018c21STomi Valkeinen #ifdef MODULE 2087f7018c21STomi Valkeinen module_param(viafb_mode, charp, S_IRUSR); 2088f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); 2089f7018c21STomi Valkeinen 2090f7018c21STomi Valkeinen module_param(viafb_mode1, charp, S_IRUSR); 2091f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)"); 2092f7018c21STomi Valkeinen 2093f7018c21STomi Valkeinen module_param(viafb_bpp, int, S_IRUSR); 2094f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)"); 2095f7018c21STomi Valkeinen 2096f7018c21STomi Valkeinen module_param(viafb_bpp1, int, S_IRUSR); 2097f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)"); 2098f7018c21STomi Valkeinen 2099f7018c21STomi Valkeinen module_param(viafb_refresh, int, S_IRUSR); 2100f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_refresh, 2101f7018c21STomi Valkeinen "Set CRT viafb_refresh rate (default = 60)"); 2102f7018c21STomi Valkeinen 2103f7018c21STomi Valkeinen module_param(viafb_refresh1, int, S_IRUSR); 2104f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_refresh1, 2105f7018c21STomi Valkeinen "Set CRT refresh rate (default = 60)"); 2106f7018c21STomi Valkeinen 2107f7018c21STomi Valkeinen module_param(viafb_lcd_panel_id, int, S_IRUSR); 2108f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_lcd_panel_id, 2109f7018c21STomi Valkeinen "Set Flat Panel type(Default=1024x768)"); 2110f7018c21STomi Valkeinen 2111f7018c21STomi Valkeinen module_param(viafb_lcd_dsp_method, int, S_IRUSR); 2112f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_lcd_dsp_method, 2113f7018c21STomi Valkeinen "Set Flat Panel display scaling method.(Default=Expandsion)"); 2114f7018c21STomi Valkeinen 2115f7018c21STomi Valkeinen module_param(viafb_SAMM_ON, int, S_IRUSR); 2116f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_SAMM_ON, 2117f7018c21STomi Valkeinen "Turn on/off flag of SAMM(Default=OFF)"); 2118f7018c21STomi Valkeinen 2119f7018c21STomi Valkeinen module_param(viafb_accel, int, S_IRUSR); 2120f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_accel, 2121f7018c21STomi Valkeinen "Set 2D Hardware Acceleration: 0 = OFF, 1 = ON (default)"); 2122f7018c21STomi Valkeinen 2123f7018c21STomi Valkeinen module_param(viafb_active_dev, charp, S_IRUSR); 2124f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_active_dev, "Specify active devices."); 2125f7018c21STomi Valkeinen 2126f7018c21STomi Valkeinen module_param(viafb_display_hardware_layout, int, S_IRUSR); 2127f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_display_hardware_layout, 2128f7018c21STomi Valkeinen "Display Hardware Layout (LCD Only, DVI Only...,etc)"); 2129f7018c21STomi Valkeinen 2130f7018c21STomi Valkeinen module_param(viafb_second_size, int, S_IRUSR); 2131f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_second_size, 2132f7018c21STomi Valkeinen "Set secondary device memory size"); 2133f7018c21STomi Valkeinen 2134f7018c21STomi Valkeinen module_param(viafb_dual_fb, int, S_IRUSR); 2135f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_dual_fb, 2136f7018c21STomi Valkeinen "Turn on/off flag of dual framebuffer devices.(Default = OFF)"); 2137f7018c21STomi Valkeinen 2138f7018c21STomi Valkeinen module_param(viafb_platform_epia_dvi, int, S_IRUSR); 2139f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_platform_epia_dvi, 2140f7018c21STomi Valkeinen "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)"); 2141f7018c21STomi Valkeinen 2142f7018c21STomi Valkeinen module_param(viafb_device_lcd_dualedge, int, S_IRUSR); 2143f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_device_lcd_dualedge, 2144f7018c21STomi Valkeinen "Turn on/off flag of dual edge panel.(Default = OFF)"); 2145f7018c21STomi Valkeinen 2146f7018c21STomi Valkeinen module_param(viafb_bus_width, int, S_IRUSR); 2147f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_bus_width, 2148f7018c21STomi Valkeinen "Set bus width of panel.(Default = 12)"); 2149f7018c21STomi Valkeinen 2150f7018c21STomi Valkeinen module_param(viafb_lcd_mode, int, S_IRUSR); 2151f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_lcd_mode, 2152f7018c21STomi Valkeinen "Set Flat Panel mode(Default=OPENLDI)"); 2153f7018c21STomi Valkeinen 2154f7018c21STomi Valkeinen module_param(viafb_lcd_port, charp, S_IRUSR); 2155f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port."); 2156f7018c21STomi Valkeinen 2157f7018c21STomi Valkeinen module_param(viafb_dvi_port, charp, S_IRUSR); 2158f7018c21STomi Valkeinen MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port."); 2159f7018c21STomi Valkeinen 2160f7018c21STomi Valkeinen MODULE_LICENSE("GPL"); 2161f7018c21STomi Valkeinen #endif 2162