linux/drivers/video/fbdev/via/hw.c
<<
>>
Prefs
   1/*
   2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
   3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
   4
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public
   7 * License as published by the Free Software Foundation;
   8 * either version 2, or (at your option) any later version.
   9
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
  12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
  13 * A PARTICULAR PURPOSE.See the GNU General Public License
  14 * for more details.
  15
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc.,
  19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20 */
  21
  22#include <linux/via-core.h>
  23#include <asm/olpc.h>
  24#include "global.h"
  25#include "via_clock.h"
  26
  27static struct pll_limit cle266_pll_limits[] = {
  28        {19, 19, 4, 0},
  29        {26, 102, 5, 0},
  30        {53, 112, 6, 0},
  31        {41, 100, 7, 0},
  32        {83, 108, 8, 0},
  33        {87, 118, 9, 0},
  34        {95, 115, 12, 0},
  35        {108, 108, 13, 0},
  36        {83, 83, 17, 0},
  37        {67, 98, 20, 0},
  38        {121, 121, 24, 0},
  39        {99, 99, 29, 0},
  40        {33, 33, 3, 1},
  41        {15, 23, 4, 1},
  42        {37, 121, 5, 1},
  43        {82, 82, 6, 1},
  44        {31, 84, 7, 1},
  45        {83, 83, 8, 1},
  46        {76, 127, 9, 1},
  47        {33, 121, 4, 2},
  48        {91, 118, 5, 2},
  49        {83, 109, 6, 2},
  50        {90, 90, 7, 2},
  51        {93, 93, 2, 3},
  52        {53, 53, 3, 3},
  53        {73, 117, 4, 3},
  54        {101, 127, 5, 3},
  55        {99, 99, 7, 3}
  56};
  57
  58static struct pll_limit k800_pll_limits[] = {
  59        {22, 22, 2, 0},
  60        {28, 28, 3, 0},
  61        {81, 112, 3, 1},
  62        {86, 166, 4, 1},
  63        {109, 153, 5, 1},
  64        {66, 116, 3, 2},
  65        {93, 137, 4, 2},
  66        {117, 208, 5, 2},
  67        {30, 30, 2, 3},
  68        {69, 125, 3, 3},
  69        {89, 161, 4, 3},
  70        {121, 208, 5, 3},
  71        {66, 66, 2, 4},
  72        {85, 85, 3, 4},
  73        {141, 161, 4, 4},
  74        {177, 177, 5, 4}
  75};
  76
  77static struct pll_limit cx700_pll_limits[] = {
  78        {98, 98, 3, 1},
  79        {86, 86, 4, 1},
  80        {109, 208, 5, 1},
  81        {68, 68, 2, 2},
  82        {95, 116, 3, 2},
  83        {93, 166, 4, 2},
  84        {110, 206, 5, 2},
  85        {174, 174, 7, 2},
  86        {82, 109, 3, 3},
  87        {117, 161, 4, 3},
  88        {112, 208, 5, 3},
  89        {141, 202, 5, 4}
  90};
  91
  92static struct pll_limit vx855_pll_limits[] = {
  93        {86, 86, 4, 1},
  94        {108, 208, 5, 1},
  95        {110, 208, 5, 2},
  96        {83, 112, 3, 3},
  97        {103, 161, 4, 3},
  98        {112, 209, 5, 3},
  99        {142, 161, 4, 4},
 100        {141, 176, 5, 4}
 101};
 102
 103/* according to VIA Technologies these values are based on experiment */
 104static struct io_reg scaling_parameters[] = {
 105        {VIACR, CR7A, 0xFF, 0x01},      /* LCD Scaling Parameter 1 */
 106        {VIACR, CR7B, 0xFF, 0x02},      /* LCD Scaling Parameter 2 */
 107        {VIACR, CR7C, 0xFF, 0x03},      /* LCD Scaling Parameter 3 */
 108        {VIACR, CR7D, 0xFF, 0x04},      /* LCD Scaling Parameter 4 */
 109        {VIACR, CR7E, 0xFF, 0x07},      /* LCD Scaling Parameter 5 */
 110        {VIACR, CR7F, 0xFF, 0x0A},      /* LCD Scaling Parameter 6 */
 111        {VIACR, CR80, 0xFF, 0x0D},      /* LCD Scaling Parameter 7 */
 112        {VIACR, CR81, 0xFF, 0x13},      /* LCD Scaling Parameter 8 */
 113        {VIACR, CR82, 0xFF, 0x16},      /* LCD Scaling Parameter 9 */
 114        {VIACR, CR83, 0xFF, 0x19},      /* LCD Scaling Parameter 10 */
 115        {VIACR, CR84, 0xFF, 0x1C},      /* LCD Scaling Parameter 11 */
 116        {VIACR, CR85, 0xFF, 0x1D},      /* LCD Scaling Parameter 12 */
 117        {VIACR, CR86, 0xFF, 0x1E},      /* LCD Scaling Parameter 13 */
 118        {VIACR, CR87, 0xFF, 0x1F},      /* LCD Scaling Parameter 14 */
 119};
 120
 121static struct io_reg common_vga[] = {
 122        {VIACR, CR07, 0x10, 0x10}, /* [0] vertical total (bit 8)
 123                                        [1] vertical display end (bit 8)
 124                                        [2] vertical retrace start (bit 8)
 125                                        [3] start vertical blanking (bit 8)
 126                                        [4] line compare (bit 8)
 127                                        [5] vertical total (bit 9)
 128                                        [6] vertical display end (bit 9)
 129                                        [7] vertical retrace start (bit 9) */
 130        {VIACR, CR08, 0xFF, 0x00}, /* [0-4] preset row scan
 131                                        [5-6] byte panning */
 132        {VIACR, CR09, 0xDF, 0x40}, /* [0-4] max scan line
 133                                        [5] start vertical blanking (bit 9)
 134                                        [6] line compare (bit 9)
 135                                        [7] scan doubling */
 136        {VIACR, CR0A, 0xFF, 0x1E}, /* [0-4] cursor start
 137                                        [5] cursor disable */
 138        {VIACR, CR0B, 0xFF, 0x00}, /* [0-4] cursor end
 139                                        [5-6] cursor skew */
 140        {VIACR, CR0E, 0xFF, 0x00}, /* [0-7] cursor location (high) */
 141        {VIACR, CR0F, 0xFF, 0x00}, /* [0-7] cursor location (low) */
 142        {VIACR, CR11, 0xF0, 0x80}, /* [0-3] vertical retrace end
 143                                        [6] memory refresh bandwidth
 144                                        [7] CRTC register protect enable */
 145        {VIACR, CR14, 0xFF, 0x00}, /* [0-4] underline location
 146                                        [5] divide memory address clock by 4
 147                                        [6] double word addressing */
 148        {VIACR, CR17, 0xFF, 0x63}, /* [0-1] mapping of display address 13-14
 149                                        [2] divide scan line clock by 2
 150                                        [3] divide memory address clock by 2
 151                                        [5] address wrap
 152                                        [6] byte mode select
 153                                        [7] sync enable */
 154        {VIACR, CR18, 0xFF, 0xFF}, /* [0-7] line compare */
 155};
 156
 157static struct fifo_depth_select display_fifo_depth_reg = {
 158        /* IGA1 FIFO Depth_Select */
 159        {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
 160        /* IGA2 FIFO Depth_Select */
 161        {IGA2_FIFO_DEPTH_SELECT_REG_NUM,
 162         {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
 163};
 164
 165static struct fifo_threshold_select fifo_threshold_select_reg = {
 166        /* IGA1 FIFO Threshold Select */
 167        {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
 168        /* IGA2 FIFO Threshold Select */
 169        {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
 170};
 171
 172static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
 173        /* IGA1 FIFO High Threshold Select */
 174        {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
 175        /* IGA2 FIFO High Threshold Select */
 176        {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
 177};
 178
 179static struct display_queue_expire_num display_queue_expire_num_reg = {
 180        /* IGA1 Display Queue Expire Num */
 181        {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
 182        /* IGA2 Display Queue Expire Num */
 183        {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
 184};
 185
 186/* Definition Fetch Count Registers*/
 187static struct fetch_count fetch_count_reg = {
 188        /* IGA1 Fetch Count Register */
 189        {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
 190        /* IGA2 Fetch Count Register */
 191        {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
 192};
 193
 194static struct rgbLUT palLUT_table[] = {
 195        /* {R,G,B} */
 196        /* Index 0x00~0x03 */
 197        {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
 198                                                                     0x2A,
 199                                                                     0x2A},
 200        /* Index 0x04~0x07 */
 201        {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
 202                                                                     0x2A,
 203                                                                     0x2A},
 204        /* Index 0x08~0x0B */
 205        {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
 206                                                                     0x3F,
 207                                                                     0x3F},
 208        /* Index 0x0C~0x0F */
 209        {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
 210                                                                     0x3F,
 211                                                                     0x3F},
 212        /* Index 0x10~0x13 */
 213        {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
 214                                                                     0x0B,
 215                                                                     0x0B},
 216        /* Index 0x14~0x17 */
 217        {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
 218                                                                     0x18,
 219                                                                     0x18},
 220        /* Index 0x18~0x1B */
 221        {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
 222                                                                     0x28,
 223                                                                     0x28},
 224        /* Index 0x1C~0x1F */
 225        {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
 226                                                                     0x3F,
 227                                                                     0x3F},
 228        /* Index 0x20~0x23 */
 229        {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
 230                                                                     0x00,
 231                                                                     0x3F},
 232        /* Index 0x24~0x27 */
 233        {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
 234                                                                     0x00,
 235                                                                     0x10},
 236        /* Index 0x28~0x2B */
 237        {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
 238                                                                     0x2F,
 239                                                                     0x00},
 240        /* Index 0x2C~0x2F */
 241        {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
 242                                                                     0x3F,
 243                                                                     0x00},
 244        /* Index 0x30~0x33 */
 245        {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
 246                                                                     0x3F,
 247                                                                     0x2F},
 248        /* Index 0x34~0x37 */
 249        {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
 250                                                                     0x10,
 251                                                                     0x3F},
 252        /* Index 0x38~0x3B */
 253        {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
 254                                                                     0x1F,
 255                                                                     0x3F},
 256        /* Index 0x3C~0x3F */
 257        {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
 258                                                                     0x1F,
 259                                                                     0x27},
 260        /* Index 0x40~0x43 */
 261        {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
 262                                                                     0x3F,
 263                                                                     0x1F},
 264        /* Index 0x44~0x47 */
 265        {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
 266                                                                     0x3F,
 267                                                                     0x1F},
 268        /* Index 0x48~0x4B */
 269        {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
 270                                                                     0x3F,
 271                                                                     0x37},
 272        /* Index 0x4C~0x4F */
 273        {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
 274                                                                     0x27,
 275                                                                     0x3F},
 276        /* Index 0x50~0x53 */
 277        {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
 278                                                                     0x2D,
 279                                                                     0x3F},
 280        /* Index 0x54~0x57 */
 281        {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
 282                                                                     0x2D,
 283                                                                     0x31},
 284        /* Index 0x58~0x5B */
 285        {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
 286                                                                     0x3A,
 287                                                                     0x2D},
 288        /* Index 0x5C~0x5F */
 289        {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
 290                                                                     0x3F,
 291                                                                     0x2D},
 292        /* Index 0x60~0x63 */
 293        {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
 294                                                                     0x3F,
 295                                                                     0x3A},
 296        /* Index 0x64~0x67 */
 297        {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
 298                                                                     0x31,
 299                                                                     0x3F},
 300        /* Index 0x68~0x6B */
 301        {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
 302                                                                     0x00,
 303                                                                     0x1C},
 304        /* Index 0x6C~0x6F */
 305        {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
 306                                                                     0x00,
 307                                                                     0x07},
 308        /* Index 0x70~0x73 */
 309        {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
 310                                                                     0x15,
 311                                                                     0x00},
 312        /* Index 0x74~0x77 */
 313        {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
 314                                                                     0x1C,
 315                                                                     0x00},
 316        /* Index 0x78~0x7B */
 317        {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
 318                                                                     0x1C,
 319                                                                     0x15},
 320        /* Index 0x7C~0x7F */
 321        {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
 322                                                                     0x07,
 323                                                                     0x1C},
 324        /* Index 0x80~0x83 */
 325        {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
 326                                                                     0x0E,
 327                                                                     0x1C},
 328        /* Index 0x84~0x87 */
 329        {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
 330                                                                     0x0E,
 331                                                                     0x11},
 332        /* Index 0x88~0x8B */
 333        {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
 334                                                                     0x18,
 335                                                                     0x0E},
 336        /* Index 0x8C~0x8F */
 337        {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
 338                                                                     0x1C,
 339                                                                     0x0E},
 340        /* Index 0x90~0x93 */
 341        {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
 342                                                                     0x1C,
 343                                                                     0x18},
 344        /* Index 0x94~0x97 */
 345        {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
 346                                                                     0x11,
 347                                                                     0x1C},
 348        /* Index 0x98~0x9B */
 349        {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
 350                                                                     0x14,
 351                                                                     0x1C},
 352        /* Index 0x9C~0x9F */
 353        {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
 354                                                                     0x14,
 355                                                                     0x16},
 356        /* Index 0xA0~0xA3 */
 357        {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
 358                                                                     0x1A,
 359                                                                     0x14},
 360        /* Index 0xA4~0xA7 */
 361        {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
 362                                                                     0x1C,
 363                                                                     0x14},
 364        /* Index 0xA8~0xAB */
 365        {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
 366                                                                     0x1C,
 367                                                                     0x1A},
 368        /* Index 0xAC~0xAF */
 369        {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
 370                                                                     0x16,
 371                                                                     0x1C},
 372        /* Index 0xB0~0xB3 */
 373        {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
 374                                                                     0x00,
 375                                                                     0x10},
 376        /* Index 0xB4~0xB7 */
 377        {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
 378                                                                     0x00,
 379                                                                     0x04},
 380        /* Index 0xB8~0xBB */
 381        {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
 382                                                                     0x0C,
 383                                                                     0x00},
 384        /* Index 0xBC~0xBF */
 385        {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
 386                                                                     0x10,
 387                                                                     0x00},
 388        /* Index 0xC0~0xC3 */
 389        {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
 390                                                                     0x10,
 391                                                                     0x0C},
 392        /* Index 0xC4~0xC7 */
 393        {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
 394                                                                     0x04,
 395                                                                     0x10},
 396        /* Index 0xC8~0xCB */
 397        {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
 398                                                                     0x08,
 399                                                                     0x10},
 400        /* Index 0xCC~0xCF */
 401        {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
 402                                                                     0x08,
 403                                                                     0x0A},
 404        /* Index 0xD0~0xD3 */
 405        {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
 406                                                                     0x0E,
 407                                                                     0x08},
 408        /* Index 0xD4~0xD7 */
 409        {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
 410                                                                     0x10,
 411                                                                     0x08},
 412        /* Index 0xD8~0xDB */
 413        {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
 414                                                                     0x10,
 415                                                                     0x0E},
 416        /* Index 0xDC~0xDF */
 417        {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
 418                                                                     0x0A,
 419                                                                     0x10},
 420        /* Index 0xE0~0xE3 */
 421        {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
 422                                                                     0x0B,
 423                                                                     0x10},
 424        /* Index 0xE4~0xE7 */
 425        {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
 426                                                                     0x0B,
 427                                                                     0x0C},
 428        /* Index 0xE8~0xEB */
 429        {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
 430                                                                     0x0F,
 431                                                                     0x0B},
 432        /* Index 0xEC~0xEF */
 433        {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
 434                                                                     0x10,
 435                                                                     0x0B},
 436        /* Index 0xF0~0xF3 */
 437        {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
 438                                                                     0x10,
 439                                                                     0x0F},
 440        /* Index 0xF4~0xF7 */
 441        {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
 442                                                                     0x0C,
 443                                                                     0x10},
 444        /* Index 0xF8~0xFB */
 445        {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
 446                                                                     0x00,
 447                                                                     0x00},
 448        /* Index 0xFC~0xFF */
 449        {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
 450                                                                     0x00,
 451                                                                     0x00}
 452};
 453
 454static struct via_device_mapping device_mapping[] = {
 455        {VIA_LDVP0, "LDVP0"},
 456        {VIA_LDVP1, "LDVP1"},
 457        {VIA_DVP0, "DVP0"},
 458        {VIA_CRT, "CRT"},
 459        {VIA_DVP1, "DVP1"},
 460        {VIA_LVDS1, "LVDS1"},
 461        {VIA_LVDS2, "LVDS2"}
 462};
 463
 464/* structure with function pointers to support clock control */
 465static struct via_clock clock;
 466
 467static void load_fix_bit_crtc_reg(void);
 468static void init_gfx_chip_info(int chip_type);
 469static void init_tmds_chip_info(void);
 470static void init_lvds_chip_info(void);
 471static void device_screen_off(void);
 472static void device_screen_on(void);
 473static void set_display_channel(void);
 474static void device_off(void);
 475static void device_on(void);
 476static void enable_second_display_channel(void);
 477static void disable_second_display_channel(void);
 478
 479void viafb_lock_crt(void)
 480{
 481        viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
 482}
 483
 484void viafb_unlock_crt(void)
 485{
 486        viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
 487        viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
 488}
 489
 490static void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
 491{
 492        outb(index, LUT_INDEX_WRITE);
 493        outb(r, LUT_DATA);
 494        outb(g, LUT_DATA);
 495        outb(b, LUT_DATA);
 496}
 497
 498static u32 get_dvi_devices(int output_interface)
 499{
 500        switch (output_interface) {
 501        case INTERFACE_DVP0:
 502                return VIA_DVP0 | VIA_LDVP0;
 503
 504        case INTERFACE_DVP1:
 505                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 506                        return VIA_LDVP1;
 507                else
 508                        return VIA_DVP1;
 509
 510        case INTERFACE_DFP_HIGH:
 511                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 512                        return 0;
 513                else
 514                        return VIA_LVDS2 | VIA_DVP0;
 515
 516        case INTERFACE_DFP_LOW:
 517                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 518                        return 0;
 519                else
 520                        return VIA_DVP1 | VIA_LVDS1;
 521
 522        case INTERFACE_TMDS:
 523                return VIA_LVDS1;
 524        }
 525
 526        return 0;
 527}
 528
 529static u32 get_lcd_devices(int output_interface)
 530{
 531        switch (output_interface) {
 532        case INTERFACE_DVP0:
 533                return VIA_DVP0;
 534
 535        case INTERFACE_DVP1:
 536                return VIA_DVP1;
 537
 538        case INTERFACE_DFP_HIGH:
 539                return VIA_LVDS2 | VIA_DVP0;
 540
 541        case INTERFACE_DFP_LOW:
 542                return VIA_LVDS1 | VIA_DVP1;
 543
 544        case INTERFACE_DFP:
 545                return VIA_LVDS1 | VIA_LVDS2;
 546
 547        case INTERFACE_LVDS0:
 548        case INTERFACE_LVDS0LVDS1:
 549                return VIA_LVDS1;
 550
 551        case INTERFACE_LVDS1:
 552                return VIA_LVDS2;
 553        }
 554
 555        return 0;
 556}
 557
 558/*Set IGA path for each device*/
 559void viafb_set_iga_path(void)
 560{
 561        int crt_iga_path = 0;
 562
 563        if (viafb_SAMM_ON == 1) {
 564                if (viafb_CRT_ON) {
 565                        if (viafb_primary_dev == CRT_Device)
 566                                crt_iga_path = IGA1;
 567                        else
 568                                crt_iga_path = IGA2;
 569                }
 570
 571                if (viafb_DVI_ON) {
 572                        if (viafb_primary_dev == DVI_Device)
 573                                viaparinfo->tmds_setting_info->iga_path = IGA1;
 574                        else
 575                                viaparinfo->tmds_setting_info->iga_path = IGA2;
 576                }
 577
 578                if (viafb_LCD_ON) {
 579                        if (viafb_primary_dev == LCD_Device) {
 580                                if (viafb_dual_fb &&
 581                                        (viaparinfo->chip_info->gfx_chip_name ==
 582                                        UNICHROME_CLE266)) {
 583                                        viaparinfo->
 584                                        lvds_setting_info->iga_path = IGA2;
 585                                        crt_iga_path = IGA1;
 586                                        viaparinfo->
 587                                        tmds_setting_info->iga_path = IGA1;
 588                                } else
 589                                        viaparinfo->
 590                                        lvds_setting_info->iga_path = IGA1;
 591                        } else {
 592                                viaparinfo->lvds_setting_info->iga_path = IGA2;
 593                        }
 594                }
 595                if (viafb_LCD2_ON) {
 596                        if (LCD2_Device == viafb_primary_dev)
 597                                viaparinfo->lvds_setting_info2->iga_path = IGA1;
 598                        else
 599                                viaparinfo->lvds_setting_info2->iga_path = IGA2;
 600                }
 601        } else {
 602                viafb_SAMM_ON = 0;
 603
 604                if (viafb_CRT_ON && viafb_LCD_ON) {
 605                        crt_iga_path = IGA1;
 606                        viaparinfo->lvds_setting_info->iga_path = IGA2;
 607                } else if (viafb_CRT_ON && viafb_DVI_ON) {
 608                        crt_iga_path = IGA1;
 609                        viaparinfo->tmds_setting_info->iga_path = IGA2;
 610                } else if (viafb_LCD_ON && viafb_DVI_ON) {
 611                        viaparinfo->tmds_setting_info->iga_path = IGA1;
 612                        viaparinfo->lvds_setting_info->iga_path = IGA2;
 613                } else if (viafb_LCD_ON && viafb_LCD2_ON) {
 614                        viaparinfo->lvds_setting_info->iga_path = IGA2;
 615                        viaparinfo->lvds_setting_info2->iga_path = IGA2;
 616                } else if (viafb_CRT_ON) {
 617                        crt_iga_path = IGA1;
 618                } else if (viafb_LCD_ON) {
 619                        viaparinfo->lvds_setting_info->iga_path = IGA2;
 620                } else if (viafb_DVI_ON) {
 621                        viaparinfo->tmds_setting_info->iga_path = IGA1;
 622                }
 623        }
 624
 625        viaparinfo->shared->iga1_devices = 0;
 626        viaparinfo->shared->iga2_devices = 0;
 627        if (viafb_CRT_ON) {
 628                if (crt_iga_path == IGA1)
 629                        viaparinfo->shared->iga1_devices |= VIA_CRT;
 630                else
 631                        viaparinfo->shared->iga2_devices |= VIA_CRT;
 632        }
 633
 634        if (viafb_DVI_ON) {
 635                if (viaparinfo->tmds_setting_info->iga_path == IGA1)
 636                        viaparinfo->shared->iga1_devices |= get_dvi_devices(
 637                                viaparinfo->chip_info->
 638                                tmds_chip_info.output_interface);
 639                else
 640                        viaparinfo->shared->iga2_devices |= get_dvi_devices(
 641                                viaparinfo->chip_info->
 642                                tmds_chip_info.output_interface);
 643        }
 644
 645        if (viafb_LCD_ON) {
 646                if (viaparinfo->lvds_setting_info->iga_path == IGA1)
 647                        viaparinfo->shared->iga1_devices |= get_lcd_devices(
 648                                viaparinfo->chip_info->
 649                                lvds_chip_info.output_interface);
 650                else
 651                        viaparinfo->shared->iga2_devices |= get_lcd_devices(
 652                                viaparinfo->chip_info->
 653                                lvds_chip_info.output_interface);
 654        }
 655
 656        if (viafb_LCD2_ON) {
 657                if (viaparinfo->lvds_setting_info2->iga_path == IGA1)
 658                        viaparinfo->shared->iga1_devices |= get_lcd_devices(
 659                                viaparinfo->chip_info->
 660                                lvds_chip_info2.output_interface);
 661                else
 662                        viaparinfo->shared->iga2_devices |= get_lcd_devices(
 663                                viaparinfo->chip_info->
 664                                lvds_chip_info2.output_interface);
 665        }
 666
 667        /* looks like the OLPC has its display wired to DVP1 and LVDS2 */
 668        if (machine_is_olpc())
 669                viaparinfo->shared->iga2_devices = VIA_DVP1 | VIA_LVDS2;
 670}
 671
 672static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
 673{
 674        outb(0xFF, 0x3C6); /* bit mask of palette */
 675        outb(index, 0x3C8);
 676        outb(red, 0x3C9);
 677        outb(green, 0x3C9);
 678        outb(blue, 0x3C9);
 679}
 680
 681void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
 682{
 683        viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
 684        set_color_register(index, red, green, blue);
 685}
 686
 687void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
 688{
 689        viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
 690        set_color_register(index, red, green, blue);
 691}
 692
 693static void set_source_common(u8 index, u8 offset, u8 iga)
 694{
 695        u8 value, mask = 1 << offset;
 696
 697        switch (iga) {
 698        case IGA1:
 699                value = 0x00;
 700                break;
 701        case IGA2:
 702                value = mask;
 703                break;
 704        default:
 705                printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
 706                return;
 707        }
 708
 709        via_write_reg_mask(VIACR, index, value, mask);
 710}
 711
 712static void set_crt_source(u8 iga)
 713{
 714        u8 value;
 715
 716        switch (iga) {
 717        case IGA1:
 718                value = 0x00;
 719                break;
 720        case IGA2:
 721                value = 0x40;
 722                break;
 723        default:
 724                printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
 725                return;
 726        }
 727
 728        via_write_reg_mask(VIASR, 0x16, value, 0x40);
 729}
 730
 731static inline void set_ldvp0_source(u8 iga)
 732{
 733        set_source_common(0x6C, 7, iga);
 734}
 735
 736static inline void set_ldvp1_source(u8 iga)
 737{
 738        set_source_common(0x93, 7, iga);
 739}
 740
 741static inline void set_dvp0_source(u8 iga)
 742{
 743        set_source_common(0x96, 4, iga);
 744}
 745
 746static inline void set_dvp1_source(u8 iga)
 747{
 748        set_source_common(0x9B, 4, iga);
 749}
 750
 751static inline void set_lvds1_source(u8 iga)
 752{
 753        set_source_common(0x99, 4, iga);
 754}
 755
 756static inline void set_lvds2_source(u8 iga)
 757{
 758        set_source_common(0x97, 4, iga);
 759}
 760
 761void via_set_source(u32 devices, u8 iga)
 762{
 763        if (devices & VIA_LDVP0)
 764                set_ldvp0_source(iga);
 765        if (devices & VIA_LDVP1)
 766                set_ldvp1_source(iga);
 767        if (devices & VIA_DVP0)
 768                set_dvp0_source(iga);
 769        if (devices & VIA_CRT)
 770                set_crt_source(iga);
 771        if (devices & VIA_DVP1)
 772                set_dvp1_source(iga);
 773        if (devices & VIA_LVDS1)
 774                set_lvds1_source(iga);
 775        if (devices & VIA_LVDS2)
 776                set_lvds2_source(iga);
 777}
 778
 779static void set_crt_state(u8 state)
 780{
 781        u8 value;
 782
 783        switch (state) {
 784        case VIA_STATE_ON:
 785                value = 0x00;
 786                break;
 787        case VIA_STATE_STANDBY:
 788                value = 0x10;
 789                break;
 790        case VIA_STATE_SUSPEND:
 791                value = 0x20;
 792                break;
 793        case VIA_STATE_OFF:
 794                value = 0x30;
 795                break;
 796        default:
 797                return;
 798        }
 799
 800        via_write_reg_mask(VIACR, 0x36, value, 0x30);
 801}
 802
 803static void set_dvp0_state(u8 state)
 804{
 805        u8 value;
 806
 807        switch (state) {
 808        case VIA_STATE_ON:
 809                value = 0xC0;
 810                break;
 811        case VIA_STATE_OFF:
 812                value = 0x00;
 813                break;
 814        default:
 815                return;
 816        }
 817
 818        via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
 819}
 820
 821static void set_dvp1_state(u8 state)
 822{
 823        u8 value;
 824
 825        switch (state) {
 826        case VIA_STATE_ON:
 827                value = 0x30;
 828                break;
 829        case VIA_STATE_OFF:
 830                value = 0x00;
 831                break;
 832        default:
 833                return;
 834        }
 835
 836        via_write_reg_mask(VIASR, 0x1E, value, 0x30);
 837}
 838
 839static void set_lvds1_state(u8 state)
 840{
 841        u8 value;
 842
 843        switch (state) {
 844        case VIA_STATE_ON:
 845                value = 0x03;
 846                break;
 847        case VIA_STATE_OFF:
 848                value = 0x00;
 849                break;
 850        default:
 851                return;
 852        }
 853
 854        via_write_reg_mask(VIASR, 0x2A, value, 0x03);
 855}
 856
 857static void set_lvds2_state(u8 state)
 858{
 859        u8 value;
 860
 861        switch (state) {
 862        case VIA_STATE_ON:
 863                value = 0x0C;
 864                break;
 865        case VIA_STATE_OFF:
 866                value = 0x00;
 867                break;
 868        default:
 869                return;
 870        }
 871
 872        via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
 873}
 874
 875void via_set_state(u32 devices, u8 state)
 876{
 877        /*
 878        TODO: Can we enable/disable these devices? How?
 879        if (devices & VIA_LDVP0)
 880        if (devices & VIA_LDVP1)
 881        */
 882        if (devices & VIA_DVP0)
 883                set_dvp0_state(state);
 884        if (devices & VIA_CRT)
 885                set_crt_state(state);
 886        if (devices & VIA_DVP1)
 887                set_dvp1_state(state);
 888        if (devices & VIA_LVDS1)
 889                set_lvds1_state(state);
 890        if (devices & VIA_LVDS2)
 891                set_lvds2_state(state);
 892}
 893
 894void via_set_sync_polarity(u32 devices, u8 polarity)
 895{
 896        if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
 897                printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
 898                        polarity);
 899                return;
 900        }
 901
 902        if (devices & VIA_CRT)
 903                via_write_misc_reg_mask(polarity << 6, 0xC0);
 904        if (devices & VIA_DVP1)
 905                via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
 906        if (devices & VIA_LVDS1)
 907                via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
 908        if (devices & VIA_LVDS2)
 909                via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
 910}
 911
 912u32 via_parse_odev(char *input, char **end)
 913{
 914        char *ptr = input;
 915        u32 odev = 0;
 916        bool next = true;
 917        int i, len;
 918
 919        while (next) {
 920                next = false;
 921                for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
 922                        len = strlen(device_mapping[i].name);
 923                        if (!strncmp(ptr, device_mapping[i].name, len)) {
 924                                odev |= device_mapping[i].device;
 925                                ptr += len;
 926                                if (*ptr == ',') {
 927                                        ptr++;
 928                                        next = true;
 929                                }
 930                        }
 931                }
 932        }
 933
 934        *end = ptr;
 935        return odev;
 936}
 937
 938void via_odev_to_seq(struct seq_file *m, u32 odev)
 939{
 940        int i, count = 0;
 941
 942        for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
 943                if (odev & device_mapping[i].device) {
 944                        if (count > 0)
 945                                seq_putc(m, ',');
 946
 947                        seq_puts(m, device_mapping[i].name);
 948                        count++;
 949                }
 950        }
 951
 952        seq_putc(m, '\n');
 953}
 954
 955static void load_fix_bit_crtc_reg(void)
 956{
 957        viafb_unlock_crt();
 958
 959        /* always set to 1 */
 960        viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
 961        /* line compare should set all bits = 1 (extend modes) */
 962        viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
 963        /* line compare should set all bits = 1 (extend modes) */
 964        viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
 965        /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
 966
 967        viafb_lock_crt();
 968
 969        /* If K8M800, enable Prefetch Mode. */
 970        if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
 971                || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
 972                viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
 973        if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
 974            && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
 975                viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
 976
 977}
 978
 979void viafb_load_reg(int timing_value, int viafb_load_reg_num,
 980        struct io_register *reg,
 981              int io_type)
 982{
 983        int reg_mask;
 984        int bit_num = 0;
 985        int data;
 986        int i, j;
 987        int shift_next_reg;
 988        int start_index, end_index, cr_index;
 989        u16 get_bit;
 990
 991        for (i = 0; i < viafb_load_reg_num; i++) {
 992                reg_mask = 0;
 993                data = 0;
 994                start_index = reg[i].start_bit;
 995                end_index = reg[i].end_bit;
 996                cr_index = reg[i].io_addr;
 997
 998                shift_next_reg = bit_num;
 999                for (j = start_index; j <= end_index; j++) {
1000                        /*if (bit_num==8) timing_value = timing_value >>8; */
1001                        reg_mask = reg_mask | (BIT0 << j);
1002                        get_bit = (timing_value & (BIT0 << bit_num));
1003                        data =
1004                            data | ((get_bit >> shift_next_reg) << start_index);
1005                        bit_num++;
1006                }
1007                if (io_type == VIACR)
1008                        viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
1009                else
1010                        viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
1011        }
1012
1013}
1014
1015/* Write Registers */
1016void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
1017{
1018        int i;
1019
1020        /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
1021
1022        for (i = 0; i < ItemNum; i++)
1023                via_write_reg_mask(RegTable[i].port, RegTable[i].index,
1024                        RegTable[i].value, RegTable[i].mask);
1025}
1026
1027void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
1028{
1029        int reg_value;
1030        int viafb_load_reg_num;
1031        struct io_register *reg = NULL;
1032
1033        switch (set_iga) {
1034        case IGA1:
1035                reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1036                viafb_load_reg_num = fetch_count_reg.
1037                        iga1_fetch_count_reg.reg_num;
1038                reg = fetch_count_reg.iga1_fetch_count_reg.reg;
1039                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1040                break;
1041        case IGA2:
1042                reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1043                viafb_load_reg_num = fetch_count_reg.
1044                        iga2_fetch_count_reg.reg_num;
1045                reg = fetch_count_reg.iga2_fetch_count_reg.reg;
1046                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1047                break;
1048        }
1049
1050}
1051
1052void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1053{
1054        int reg_value;
1055        int viafb_load_reg_num;
1056        struct io_register *reg = NULL;
1057        int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
1058            0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
1059        int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
1060            0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
1061
1062        if (set_iga == IGA1) {
1063                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1064                        iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
1065                        iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
1066                        iga1_fifo_high_threshold =
1067                            K800_IGA1_FIFO_HIGH_THRESHOLD;
1068                        /* If resolution > 1280x1024, expire length = 64, else
1069                           expire length = 128 */
1070                        if ((hor_active > 1280) && (ver_active > 1024))
1071                                iga1_display_queue_expire_num = 16;
1072                        else
1073                                iga1_display_queue_expire_num =
1074                                    K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1075
1076                }
1077
1078                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1079                        iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
1080                        iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
1081                        iga1_fifo_high_threshold =
1082                            P880_IGA1_FIFO_HIGH_THRESHOLD;
1083                        iga1_display_queue_expire_num =
1084                            P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1085
1086                        /* If resolution > 1280x1024, expire length = 64, else
1087                           expire length = 128 */
1088                        if ((hor_active > 1280) && (ver_active > 1024))
1089                                iga1_display_queue_expire_num = 16;
1090                        else
1091                                iga1_display_queue_expire_num =
1092                                    P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1093                }
1094
1095                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1096                        iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
1097                        iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
1098                        iga1_fifo_high_threshold =
1099                            CN700_IGA1_FIFO_HIGH_THRESHOLD;
1100
1101                        /* If resolution > 1280x1024, expire length = 64,
1102                           else expire length = 128 */
1103                        if ((hor_active > 1280) && (ver_active > 1024))
1104                                iga1_display_queue_expire_num = 16;
1105                        else
1106                                iga1_display_queue_expire_num =
1107                                    CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1108                }
1109
1110                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1111                        iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
1112                        iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
1113                        iga1_fifo_high_threshold =
1114                            CX700_IGA1_FIFO_HIGH_THRESHOLD;
1115                        iga1_display_queue_expire_num =
1116                            CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1117                }
1118
1119                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1120                        iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
1121                        iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
1122                        iga1_fifo_high_threshold =
1123                            K8M890_IGA1_FIFO_HIGH_THRESHOLD;
1124                        iga1_display_queue_expire_num =
1125                            K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1126                }
1127
1128                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1129                        iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
1130                        iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
1131                        iga1_fifo_high_threshold =
1132                            P4M890_IGA1_FIFO_HIGH_THRESHOLD;
1133                        iga1_display_queue_expire_num =
1134                            P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1135                }
1136
1137                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1138                        iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
1139                        iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
1140                        iga1_fifo_high_threshold =
1141                            P4M900_IGA1_FIFO_HIGH_THRESHOLD;
1142                        iga1_display_queue_expire_num =
1143                            P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1144                }
1145
1146                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1147                        iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
1148                        iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
1149                        iga1_fifo_high_threshold =
1150                            VX800_IGA1_FIFO_HIGH_THRESHOLD;
1151                        iga1_display_queue_expire_num =
1152                            VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1153                }
1154
1155                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1156                        iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH;
1157                        iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD;
1158                        iga1_fifo_high_threshold =
1159                            VX855_IGA1_FIFO_HIGH_THRESHOLD;
1160                        iga1_display_queue_expire_num =
1161                            VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1162                }
1163
1164                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1165                        iga1_fifo_max_depth = VX900_IGA1_FIFO_MAX_DEPTH;
1166                        iga1_fifo_threshold = VX900_IGA1_FIFO_THRESHOLD;
1167                        iga1_fifo_high_threshold =
1168                            VX900_IGA1_FIFO_HIGH_THRESHOLD;
1169                        iga1_display_queue_expire_num =
1170                            VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1171                }
1172
1173                /* Set Display FIFO Depath Select */
1174                reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
1175                viafb_load_reg_num =
1176                    display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
1177                reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
1178                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1179
1180                /* Set Display FIFO Threshold Select */
1181                reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
1182                viafb_load_reg_num =
1183                    fifo_threshold_select_reg.
1184                    iga1_fifo_threshold_select_reg.reg_num;
1185                reg =
1186                    fifo_threshold_select_reg.
1187                    iga1_fifo_threshold_select_reg.reg;
1188                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1189
1190                /* Set FIFO High Threshold Select */
1191                reg_value =
1192                    IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
1193                viafb_load_reg_num =
1194                    fifo_high_threshold_select_reg.
1195                    iga1_fifo_high_threshold_select_reg.reg_num;
1196                reg =
1197                    fifo_high_threshold_select_reg.
1198                    iga1_fifo_high_threshold_select_reg.reg;
1199                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1200
1201                /* Set Display Queue Expire Num */
1202                reg_value =
1203                    IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1204                    (iga1_display_queue_expire_num);
1205                viafb_load_reg_num =
1206                    display_queue_expire_num_reg.
1207                    iga1_display_queue_expire_num_reg.reg_num;
1208                reg =
1209                    display_queue_expire_num_reg.
1210                    iga1_display_queue_expire_num_reg.reg;
1211                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1212
1213        } else {
1214                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1215                        iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
1216                        iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
1217                        iga2_fifo_high_threshold =
1218                            K800_IGA2_FIFO_HIGH_THRESHOLD;
1219
1220                        /* If resolution > 1280x1024, expire length = 64,
1221                           else  expire length = 128 */
1222                        if ((hor_active > 1280) && (ver_active > 1024))
1223                                iga2_display_queue_expire_num = 16;
1224                        else
1225                                iga2_display_queue_expire_num =
1226                                    K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1227                }
1228
1229                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1230                        iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
1231                        iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
1232                        iga2_fifo_high_threshold =
1233                            P880_IGA2_FIFO_HIGH_THRESHOLD;
1234
1235                        /* If resolution > 1280x1024, expire length = 64,
1236                           else  expire length = 128 */
1237                        if ((hor_active > 1280) && (ver_active > 1024))
1238                                iga2_display_queue_expire_num = 16;
1239                        else
1240                                iga2_display_queue_expire_num =
1241                                    P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1242                }
1243
1244                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1245                        iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
1246                        iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
1247                        iga2_fifo_high_threshold =
1248                            CN700_IGA2_FIFO_HIGH_THRESHOLD;
1249
1250                        /* If resolution > 1280x1024, expire length = 64,
1251                           else expire length = 128 */
1252                        if ((hor_active > 1280) && (ver_active > 1024))
1253                                iga2_display_queue_expire_num = 16;
1254                        else
1255                                iga2_display_queue_expire_num =
1256                                    CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1257                }
1258
1259                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1260                        iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
1261                        iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
1262                        iga2_fifo_high_threshold =
1263                            CX700_IGA2_FIFO_HIGH_THRESHOLD;
1264                        iga2_display_queue_expire_num =
1265                            CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1266                }
1267
1268                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1269                        iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
1270                        iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
1271                        iga2_fifo_high_threshold =
1272                            K8M890_IGA2_FIFO_HIGH_THRESHOLD;
1273                        iga2_display_queue_expire_num =
1274                            K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1275                }
1276
1277                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1278                        iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
1279                        iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
1280                        iga2_fifo_high_threshold =
1281                            P4M890_IGA2_FIFO_HIGH_THRESHOLD;
1282                        iga2_display_queue_expire_num =
1283                            P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1284                }
1285
1286                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1287                        iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
1288                        iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
1289                        iga2_fifo_high_threshold =
1290                            P4M900_IGA2_FIFO_HIGH_THRESHOLD;
1291                        iga2_display_queue_expire_num =
1292                            P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1293                }
1294
1295                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1296                        iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
1297                        iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
1298                        iga2_fifo_high_threshold =
1299                            VX800_IGA2_FIFO_HIGH_THRESHOLD;
1300                        iga2_display_queue_expire_num =
1301                            VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1302                }
1303
1304                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1305                        iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH;
1306                        iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD;
1307                        iga2_fifo_high_threshold =
1308                            VX855_IGA2_FIFO_HIGH_THRESHOLD;
1309                        iga2_display_queue_expire_num =
1310                            VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1311                }
1312
1313                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1314                        iga2_fifo_max_depth = VX900_IGA2_FIFO_MAX_DEPTH;
1315                        iga2_fifo_threshold = VX900_IGA2_FIFO_THRESHOLD;
1316                        iga2_fifo_high_threshold =
1317                            VX900_IGA2_FIFO_HIGH_THRESHOLD;
1318                        iga2_display_queue_expire_num =
1319                            VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1320                }
1321
1322                if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1323                        /* Set Display FIFO Depath Select */
1324                        reg_value =
1325                            IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
1326                            - 1;
1327                        /* Patch LCD in IGA2 case */
1328                        viafb_load_reg_num =
1329                            display_fifo_depth_reg.
1330                            iga2_fifo_depth_select_reg.reg_num;
1331                        reg =
1332                            display_fifo_depth_reg.
1333                            iga2_fifo_depth_select_reg.reg;
1334                        viafb_load_reg(reg_value,
1335                                viafb_load_reg_num, reg, VIACR);
1336                } else {
1337
1338                        /* Set Display FIFO Depath Select */
1339                        reg_value =
1340                            IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
1341                        viafb_load_reg_num =
1342                            display_fifo_depth_reg.
1343                            iga2_fifo_depth_select_reg.reg_num;
1344                        reg =
1345                            display_fifo_depth_reg.
1346                            iga2_fifo_depth_select_reg.reg;
1347                        viafb_load_reg(reg_value,
1348                                viafb_load_reg_num, reg, VIACR);
1349                }
1350
1351                /* Set Display FIFO Threshold Select */
1352                reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
1353                viafb_load_reg_num =
1354                    fifo_threshold_select_reg.
1355                    iga2_fifo_threshold_select_reg.reg_num;
1356                reg =
1357                    fifo_threshold_select_reg.
1358                    iga2_fifo_threshold_select_reg.reg;
1359                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1360
1361                /* Set FIFO High Threshold Select */
1362                reg_value =
1363                    IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
1364                viafb_load_reg_num =
1365                    fifo_high_threshold_select_reg.
1366                    iga2_fifo_high_threshold_select_reg.reg_num;
1367                reg =
1368                    fifo_high_threshold_select_reg.
1369                    iga2_fifo_high_threshold_select_reg.reg;
1370                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1371
1372                /* Set Display Queue Expire Num */
1373                reg_value =
1374                    IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1375                    (iga2_display_queue_expire_num);
1376                viafb_load_reg_num =
1377                    display_queue_expire_num_reg.
1378                    iga2_display_queue_expire_num_reg.reg_num;
1379                reg =
1380                    display_queue_expire_num_reg.
1381                    iga2_display_queue_expire_num_reg.reg;
1382                viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1383
1384        }
1385
1386}
1387
1388static struct via_pll_config get_pll_config(struct pll_limit *limits, int size,
1389        int clk)
1390{
1391        struct via_pll_config cur, up, down, best = {0, 1, 0};
1392        const u32 f0 = 14318180; /* X1 frequency */
1393        int i, f;
1394
1395        for (i = 0; i < size; i++) {
1396                cur.rshift = limits[i].rshift;
1397                cur.divisor = limits[i].divisor;
1398                cur.multiplier = clk / ((f0 / cur.divisor)>>cur.rshift);
1399                f = abs(get_pll_output_frequency(f0, cur) - clk);
1400                up = down = cur;
1401                up.multiplier++;
1402                down.multiplier--;
1403                if (abs(get_pll_output_frequency(f0, up) - clk) < f)
1404                        cur = up;
1405                else if (abs(get_pll_output_frequency(f0, down) - clk) < f)
1406                        cur = down;
1407
1408                if (cur.multiplier < limits[i].multiplier_min)
1409                        cur.multiplier = limits[i].multiplier_min;
1410                else if (cur.multiplier > limits[i].multiplier_max)
1411                        cur.multiplier = limits[i].multiplier_max;
1412
1413                f = abs(get_pll_output_frequency(f0, cur) - clk);
1414                if (f < abs(get_pll_output_frequency(f0, best) - clk))
1415                        best = cur;
1416        }
1417
1418        return best;
1419}
1420
1421static struct via_pll_config get_best_pll_config(int clk)
1422{
1423        struct via_pll_config config;
1424
1425        switch (viaparinfo->chip_info->gfx_chip_name) {
1426        case UNICHROME_CLE266:
1427        case UNICHROME_K400:
1428                config = get_pll_config(cle266_pll_limits,
1429                        ARRAY_SIZE(cle266_pll_limits), clk);
1430                break;
1431        case UNICHROME_K800:
1432        case UNICHROME_PM800:
1433        case UNICHROME_CN700:
1434                config = get_pll_config(k800_pll_limits,
1435                        ARRAY_SIZE(k800_pll_limits), clk);
1436                break;
1437        case UNICHROME_CX700:
1438        case UNICHROME_CN750:
1439        case UNICHROME_K8M890:
1440        case UNICHROME_P4M890:
1441        case UNICHROME_P4M900:
1442        case UNICHROME_VX800:
1443                config = get_pll_config(cx700_pll_limits,
1444                        ARRAY_SIZE(cx700_pll_limits), clk);
1445                break;
1446        case UNICHROME_VX855:
1447        case UNICHROME_VX900:
1448                config = get_pll_config(vx855_pll_limits,
1449                        ARRAY_SIZE(vx855_pll_limits), clk);
1450                break;
1451        }
1452
1453        return config;
1454}
1455
1456/* Set VCLK*/
1457void viafb_set_vclock(u32 clk, int set_iga)
1458{
1459        struct via_pll_config config = get_best_pll_config(clk);
1460
1461        if (set_iga == IGA1)
1462                clock.set_primary_pll(config);
1463        if (set_iga == IGA2)
1464                clock.set_secondary_pll(config);
1465
1466        /* Fire! */
1467        via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
1468}
1469
1470struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
1471        u16 cxres, u16 cyres)
1472{
1473        struct via_display_timing timing;
1474        u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
1475
1476        timing.hor_addr = cxres;
1477        timing.hor_sync_start = timing.hor_addr + var->right_margin + dx;
1478        timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
1479        timing.hor_total = timing.hor_sync_end + var->left_margin + dx;
1480        timing.hor_blank_start = timing.hor_addr + dx;
1481        timing.hor_blank_end = timing.hor_total - dx;
1482        timing.ver_addr = cyres;
1483        timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy;
1484        timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
1485        timing.ver_total = timing.ver_sync_end + var->upper_margin + dy;
1486        timing.ver_blank_start = timing.ver_addr + dy;
1487        timing.ver_blank_end = timing.ver_total - dy;
1488        return timing;
1489}
1490
1491void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
1492        u16 cxres, u16 cyres, int iga)
1493{
1494        struct via_display_timing crt_reg = var_to_timing(var,
1495                cxres ? cxres : var->xres, cyres ? cyres : var->yres);
1496
1497        if (iga == IGA1)
1498                via_set_primary_timing(&crt_reg);
1499        else if (iga == IGA2)
1500                via_set_secondary_timing(&crt_reg);
1501
1502        viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga);
1503        if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266
1504                && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)
1505                viafb_load_FIFO_reg(iga, var->xres, var->yres);
1506
1507        viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
1508}
1509
1510void viafb_init_chip_info(int chip_type)
1511{
1512        via_clock_init(&clock, chip_type);
1513        init_gfx_chip_info(chip_type);
1514        init_tmds_chip_info();
1515        init_lvds_chip_info();
1516
1517        /*Set IGA path for each device */
1518        viafb_set_iga_path();
1519
1520        viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
1521        viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
1522        viaparinfo->lvds_setting_info2->display_method =
1523                viaparinfo->lvds_setting_info->display_method;
1524        viaparinfo->lvds_setting_info2->lcd_mode =
1525                viaparinfo->lvds_setting_info->lcd_mode;
1526}
1527
1528void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
1529{
1530        if (flag == 0) {
1531                viaparinfo->tmds_setting_info->h_active = hres;
1532                viaparinfo->tmds_setting_info->v_active = vres;
1533        } else {
1534
1535                if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
1536                        viaparinfo->tmds_setting_info->h_active = hres;
1537                        viaparinfo->tmds_setting_info->v_active = vres;
1538                }
1539
1540        }
1541}
1542
1543static void init_gfx_chip_info(int chip_type)
1544{
1545        u8 tmp;
1546
1547        viaparinfo->chip_info->gfx_chip_name = chip_type;
1548
1549        /* Check revision of CLE266 Chip */
1550        if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
1551                /* CR4F only define in CLE266.CX chip */
1552                tmp = viafb_read_reg(VIACR, CR4F);
1553                viafb_write_reg(CR4F, VIACR, 0x55);
1554                if (viafb_read_reg(VIACR, CR4F) != 0x55)
1555                        viaparinfo->chip_info->gfx_chip_revision =
1556                        CLE266_REVISION_AX;
1557                else
1558                        viaparinfo->chip_info->gfx_chip_revision =
1559                        CLE266_REVISION_CX;
1560                /* restore orignal CR4F value */
1561                viafb_write_reg(CR4F, VIACR, tmp);
1562        }
1563
1564        if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1565                tmp = viafb_read_reg(VIASR, SR43);
1566                DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
1567                if (tmp & 0x02) {
1568                        viaparinfo->chip_info->gfx_chip_revision =
1569                                CX700_REVISION_700M2;
1570                } else if (tmp & 0x40) {
1571                        viaparinfo->chip_info->gfx_chip_revision =
1572                                CX700_REVISION_700M;
1573                } else {
1574                        viaparinfo->chip_info->gfx_chip_revision =
1575                                CX700_REVISION_700;
1576                }
1577        }
1578
1579        /* Determine which 2D engine we have */
1580        switch (viaparinfo->chip_info->gfx_chip_name) {
1581        case UNICHROME_VX800:
1582        case UNICHROME_VX855:
1583        case UNICHROME_VX900:
1584                viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1;
1585                break;
1586        case UNICHROME_K8M890:
1587        case UNICHROME_P4M900:
1588                viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5;
1589                break;
1590        default:
1591                viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2;
1592                break;
1593        }
1594}
1595
1596static void init_tmds_chip_info(void)
1597{
1598        viafb_tmds_trasmitter_identify();
1599
1600        if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
1601                output_interface) {
1602                switch (viaparinfo->chip_info->gfx_chip_name) {
1603                case UNICHROME_CX700:
1604                        {
1605                                /* we should check support by hardware layout.*/
1606                                if ((viafb_display_hardware_layout ==
1607                                     HW_LAYOUT_DVI_ONLY)
1608                                    || (viafb_display_hardware_layout ==
1609                                        HW_LAYOUT_LCD_DVI)) {
1610                                        viaparinfo->chip_info->tmds_chip_info.
1611                                            output_interface = INTERFACE_TMDS;
1612                                } else {
1613                                        viaparinfo->chip_info->tmds_chip_info.
1614                                                output_interface =
1615                                                INTERFACE_NONE;
1616                                }
1617                                break;
1618                        }
1619                case UNICHROME_K8M890:
1620                case UNICHROME_P4M900:
1621                case UNICHROME_P4M890:
1622                        /* TMDS on PCIE, we set DFPLOW as default. */
1623                        viaparinfo->chip_info->tmds_chip_info.output_interface =
1624                            INTERFACE_DFP_LOW;
1625                        break;
1626                default:
1627                        {
1628                                /* set DVP1 default for DVI */
1629                                viaparinfo->chip_info->tmds_chip_info
1630                                .output_interface = INTERFACE_DVP1;
1631                        }
1632                }
1633        }
1634
1635        DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
1636                  viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
1637        viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info,
1638                &viaparinfo->shared->tmds_setting_info);
1639}
1640
1641static void init_lvds_chip_info(void)
1642{
1643        viafb_lvds_trasmitter_identify();
1644        viafb_init_lcd_size();
1645        viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
1646                                   viaparinfo->lvds_setting_info);
1647        if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
1648                viafb_init_lvds_output_interface(&viaparinfo->chip_info->
1649                        lvds_chip_info2, viaparinfo->lvds_setting_info2);
1650        }
1651        /*If CX700,two singel LCD, we need to reassign
1652           LCD interface to different LVDS port */
1653        if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
1654            && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
1655                if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
1656                        lvds_chip_name) && (INTEGRATED_LVDS ==
1657                        viaparinfo->chip_info->
1658                        lvds_chip_info2.lvds_chip_name)) {
1659                        viaparinfo->chip_info->lvds_chip_info.output_interface =
1660                                INTERFACE_LVDS0;
1661                        viaparinfo->chip_info->lvds_chip_info2.
1662                                output_interface =
1663                            INTERFACE_LVDS1;
1664                }
1665        }
1666
1667        DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
1668                  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
1669        DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
1670                  viaparinfo->chip_info->lvds_chip_info.output_interface);
1671        DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
1672                  viaparinfo->chip_info->lvds_chip_info.output_interface);
1673}
1674
1675void viafb_init_dac(int set_iga)
1676{
1677        int i;
1678        u8 tmp;
1679
1680        if (set_iga == IGA1) {
1681                /* access Primary Display's LUT */
1682                viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
1683                /* turn off LCK */
1684                viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
1685                for (i = 0; i < 256; i++) {
1686                        write_dac_reg(i, palLUT_table[i].red,
1687                                      palLUT_table[i].green,
1688                                      palLUT_table[i].blue);
1689                }
1690                /* turn on LCK */
1691                viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
1692        } else {
1693                tmp = viafb_read_reg(VIACR, CR6A);
1694                /* access Secondary Display's LUT */
1695                viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
1696                viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
1697                for (i = 0; i < 256; i++) {
1698                        write_dac_reg(i, palLUT_table[i].red,
1699                                      palLUT_table[i].green,
1700                                      palLUT_table[i].blue);
1701                }
1702                /* set IGA1 DAC for default */
1703                viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
1704                viafb_write_reg(CR6A, VIACR, tmp);
1705        }
1706}
1707
1708static void device_screen_off(void)
1709{
1710        /* turn off CRT screen (IGA1) */
1711        viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
1712}
1713
1714static void device_screen_on(void)
1715{
1716        /* turn on CRT screen (IGA1) */
1717        viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
1718}
1719
1720static void set_display_channel(void)
1721{
1722        /*If viafb_LCD2_ON, on cx700, internal lvds's information
1723        is keeped on lvds_setting_info2 */
1724        if (viafb_LCD2_ON &&
1725                viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
1726                /* For dual channel LCD: */
1727                /* Set to Dual LVDS channel. */
1728                viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
1729        } else if (viafb_LCD_ON && viafb_DVI_ON) {
1730                /* For LCD+DFP: */
1731                /* Set to LVDS1 + TMDS channel. */
1732                viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
1733        } else if (viafb_DVI_ON) {
1734                /* Set to single TMDS channel. */
1735                viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
1736        } else if (viafb_LCD_ON) {
1737                if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
1738                        /* For dual channel LCD: */
1739                        /* Set to Dual LVDS channel. */
1740                        viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
1741                } else {
1742                        /* Set to LVDS0 + LVDS1 channel. */
1743                        viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
1744                }
1745        }
1746}
1747
1748static u8 get_sync(struct fb_var_screeninfo *var)
1749{
1750        u8 polarity = 0;
1751
1752        if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
1753                polarity |= VIA_HSYNC_NEGATIVE;
1754        if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
1755                polarity |= VIA_VSYNC_NEGATIVE;
1756        return polarity;
1757}
1758
1759static void hw_init(void)
1760{
1761        int i;
1762
1763        inb(VIAStatus);
1764        outb(0x00, VIAAR);
1765
1766        /* Write Common Setting for Video Mode */
1767        viafb_write_regx(common_vga, ARRAY_SIZE(common_vga));
1768        switch (viaparinfo->chip_info->gfx_chip_name) {
1769        case UNICHROME_CLE266:
1770                viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
1771                break;
1772
1773        case UNICHROME_K400:
1774                viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
1775                break;
1776
1777        case UNICHROME_K800:
1778        case UNICHROME_PM800:
1779                viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
1780                break;
1781
1782        case UNICHROME_CN700:
1783        case UNICHROME_K8M890:
1784        case UNICHROME_P4M890:
1785        case UNICHROME_P4M900:
1786                viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
1787                break;
1788
1789        case UNICHROME_CX700:
1790        case UNICHROME_VX800:
1791                viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
1792                break;
1793
1794        case UNICHROME_VX855:
1795        case UNICHROME_VX900:
1796                viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
1797                break;
1798        }
1799
1800        /* magic required on VX900 for correct modesetting on IGA1 */
1801        via_write_reg_mask(VIACR, 0x45, 0x00, 0x01);
1802
1803        /* probably this should go to the scaling code one day */
1804        via_write_reg_mask(VIACR, 0xFD, 0, 0x80); /* VX900 hw scale on IGA2 */
1805        viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
1806
1807        /* Fill VPIT Parameters */
1808        /* Write Misc Register */
1809        outb(VPIT.Misc, VIA_MISC_REG_WRITE);
1810
1811        /* Write Sequencer */
1812        for (i = 1; i <= StdSR; i++)
1813                via_write_reg(VIASR, i, VPIT.SR[i - 1]);
1814
1815        viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
1816
1817        /* Write Graphic Controller */
1818        for (i = 0; i < StdGR; i++)
1819                via_write_reg(VIAGR, i, VPIT.GR[i]);
1820
1821        /* Write Attribute Controller */
1822        for (i = 0; i < StdAR; i++) {
1823                inb(VIAStatus);
1824                outb(i, VIAAR);
1825                outb(VPIT.AR[i], VIAAR);
1826        }
1827
1828        inb(VIAStatus);
1829        outb(0x20, VIAAR);
1830
1831        load_fix_bit_crtc_reg();
1832}
1833
1834int viafb_setmode(void)
1835{
1836        int j, cxres = 0, cyres = 0;
1837        int port;
1838        u32 devices = viaparinfo->shared->iga1_devices
1839                | viaparinfo->shared->iga2_devices;
1840        u8 value, index, mask;
1841        struct fb_var_screeninfo var2;
1842
1843        device_screen_off();
1844        device_off();
1845        via_set_state(devices, VIA_STATE_OFF);
1846
1847        hw_init();
1848
1849        /* Update Patch Register */
1850
1851        if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
1852                || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
1853                && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) {
1854                for (j = 0; j < res_patch_table[0].table_length; j++) {
1855                        index = res_patch_table[0].io_reg_table[j].index;
1856                        port = res_patch_table[0].io_reg_table[j].port;
1857                        value = res_patch_table[0].io_reg_table[j].value;
1858                        mask = res_patch_table[0].io_reg_table[j].mask;
1859                        viafb_write_reg_mask(index, port, value, mask);
1860                }
1861        }
1862
1863        via_set_primary_pitch(viafbinfo->fix.line_length);
1864        via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
1865                : viafbinfo->fix.line_length);
1866        via_set_primary_color_depth(viaparinfo->depth);
1867        via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
1868                : viaparinfo->depth);
1869        via_set_source(viaparinfo->shared->iga1_devices, IGA1);
1870        via_set_source(viaparinfo->shared->iga2_devices, IGA2);
1871        if (viaparinfo->shared->iga2_devices)
1872                enable_second_display_channel();
1873        else
1874                disable_second_display_channel();
1875
1876        /* Update Refresh Rate Setting */
1877
1878        /* Clear On Screen */
1879
1880        if (viafb_dual_fb) {
1881                var2 = viafbinfo1->var;
1882        } else if (viafb_SAMM_ON) {
1883                viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
1884                        viafb_second_xres, viafb_second_yres, viafb_refresh1));
1885                cxres = viafbinfo->var.xres;
1886                cyres = viafbinfo->var.yres;
1887                var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
1888        }
1889
1890        /* CRT set mode */
1891        if (viafb_CRT_ON) {
1892                if (viaparinfo->shared->iga2_devices & VIA_CRT
1893                        && viafb_SAMM_ON)
1894                        viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2);
1895                else
1896                        viafb_fill_crtc_timing(&viafbinfo->var, 0, 0,
1897                                (viaparinfo->shared->iga1_devices & VIA_CRT)
1898                                ? IGA1 : IGA2);
1899
1900                /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
1901                to 8 alignment (1368),there is several pixels (2 pixels)
1902                on right side of screen. */
1903                if (viafbinfo->var.xres % 8) {
1904                        viafb_unlock_crt();
1905                        viafb_write_reg(CR02, VIACR,
1906                                viafb_read_reg(VIACR, CR02) - 1);
1907                        viafb_lock_crt();
1908                }
1909        }
1910
1911        if (viafb_DVI_ON) {
1912                if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
1913                        && viafb_SAMM_ON)
1914                        viafb_dvi_set_mode(&var2, cxres, cyres, IGA2);
1915                else
1916                        viafb_dvi_set_mode(&viafbinfo->var, 0, 0,
1917                                viaparinfo->tmds_setting_info->iga_path);
1918        }
1919
1920        if (viafb_LCD_ON) {
1921                if (viafb_SAMM_ON &&
1922                        (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
1923                        viafb_lcd_set_mode(&var2, cxres, cyres,
1924                                viaparinfo->lvds_setting_info,
1925                                &viaparinfo->chip_info->lvds_chip_info);
1926                } else {
1927                        /* IGA1 doesn't have LCD scaling, so set it center. */
1928                        if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
1929                                viaparinfo->lvds_setting_info->display_method =
1930                                    LCD_CENTERING;
1931                        }
1932                        viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
1933                                viaparinfo->lvds_setting_info,
1934                                &viaparinfo->chip_info->lvds_chip_info);
1935                }
1936        }
1937        if (viafb_LCD2_ON) {
1938                if (viafb_SAMM_ON &&
1939                        (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
1940                        viafb_lcd_set_mode(&var2, cxres, cyres,
1941                                viaparinfo->lvds_setting_info2,
1942                                &viaparinfo->chip_info->lvds_chip_info2);
1943                } else {
1944                        /* IGA1 doesn't have LCD scaling, so set it center. */
1945                        if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
1946                                viaparinfo->lvds_setting_info2->display_method =
1947                                    LCD_CENTERING;
1948                        }
1949                        viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
1950                                viaparinfo->lvds_setting_info2,
1951                                &viaparinfo->chip_info->lvds_chip_info2);
1952                }
1953        }
1954
1955        if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
1956            && (viafb_LCD_ON || viafb_DVI_ON))
1957                set_display_channel();
1958
1959        /* If set mode normally, save resolution information for hot-plug . */
1960        if (!viafb_hotplug) {
1961                viafb_hotplug_Xres = viafbinfo->var.xres;
1962                viafb_hotplug_Yres = viafbinfo->var.yres;
1963                viafb_hotplug_bpp = viafbinfo->var.bits_per_pixel;
1964                viafb_hotplug_refresh = viafb_refresh;
1965
1966                if (viafb_DVI_ON)
1967                        viafb_DeviceStatus = DVI_Device;
1968                else
1969                        viafb_DeviceStatus = CRT_Device;
1970        }
1971        device_on();
1972        if (!viafb_SAMM_ON)
1973                via_set_sync_polarity(devices, get_sync(&viafbinfo->var));
1974        else {
1975                via_set_sync_polarity(viaparinfo->shared->iga1_devices,
1976                        get_sync(&viafbinfo->var));
1977                via_set_sync_polarity(viaparinfo->shared->iga2_devices,
1978                        get_sync(&var2));
1979        }
1980
1981        clock.set_engine_pll_state(VIA_STATE_ON);
1982        clock.set_primary_clock_source(VIA_CLKSRC_X1, true);
1983        clock.set_secondary_clock_source(VIA_CLKSRC_X1, true);
1984
1985#ifdef CONFIG_FB_VIA_X_COMPATIBILITY
1986        clock.set_primary_pll_state(VIA_STATE_ON);
1987        clock.set_primary_clock_state(VIA_STATE_ON);
1988        clock.set_secondary_pll_state(VIA_STATE_ON);
1989        clock.set_secondary_clock_state(VIA_STATE_ON);
1990#else
1991        if (viaparinfo->shared->iga1_devices) {
1992                clock.set_primary_pll_state(VIA_STATE_ON);
1993                clock.set_primary_clock_state(VIA_STATE_ON);
1994        } else {
1995                clock.set_primary_pll_state(VIA_STATE_OFF);
1996                clock.set_primary_clock_state(VIA_STATE_OFF);
1997        }
1998
1999        if (viaparinfo->shared->iga2_devices) {
2000                clock.set_secondary_pll_state(VIA_STATE_ON);
2001                clock.set_secondary_clock_state(VIA_STATE_ON);
2002        } else {
2003                clock.set_secondary_pll_state(VIA_STATE_OFF);
2004                clock.set_secondary_clock_state(VIA_STATE_OFF);
2005        }
2006#endif /*CONFIG_FB_VIA_X_COMPATIBILITY*/
2007
2008        via_set_state(devices, VIA_STATE_ON);
2009        device_screen_on();
2010        return 1;
2011}
2012
2013int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2014{
2015        const struct fb_videomode *best;
2016
2017        best = viafb_get_best_mode(hres, vres, long_refresh);
2018        if (!best)
2019                return 60;
2020
2021        if (abs(best->refresh - long_refresh) > 3) {
2022                if (hres == 1200 && vres == 900)
2023                        return 49; /* OLPC DCON only supports 50 Hz */
2024                else
2025                        return 60;
2026        }
2027
2028        return best->refresh;
2029}
2030
2031static void device_off(void)
2032{
2033        viafb_dvi_disable();
2034        viafb_lcd_disable();
2035}
2036
2037static void device_on(void)
2038{
2039        if (viafb_DVI_ON == 1)
2040                viafb_dvi_enable();
2041        if (viafb_LCD_ON == 1)
2042                viafb_lcd_enable();
2043}
2044
2045static void enable_second_display_channel(void)
2046{
2047        /* to enable second display channel. */
2048        viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2049        viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
2050        viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2051}
2052
2053static void disable_second_display_channel(void)
2054{
2055        /* to disable second display channel. */
2056        viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2057        viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
2058        viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2059}
2060
2061void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2062                                        *p_gfx_dpa_setting)
2063{
2064        switch (output_interface) {
2065        case INTERFACE_DVP0:
2066                {
2067                        /* DVP0 Clock Polarity and Adjust: */
2068                        viafb_write_reg_mask(CR96, VIACR,
2069                                       p_gfx_dpa_setting->DVP0, 0x0F);
2070
2071                        /* DVP0 Clock and Data Pads Driving: */
2072                        viafb_write_reg_mask(SR1E, VIASR,
2073                                       p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
2074                        viafb_write_reg_mask(SR2A, VIASR,
2075                                       p_gfx_dpa_setting->DVP0ClockDri_S1,
2076                                       BIT4);
2077                        viafb_write_reg_mask(SR1B, VIASR,
2078                                       p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
2079                        viafb_write_reg_mask(SR2A, VIASR,
2080                                       p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
2081                        break;
2082                }
2083
2084        case INTERFACE_DVP1:
2085                {
2086                        /* DVP1 Clock Polarity and Adjust: */
2087                        viafb_write_reg_mask(CR9B, VIACR,
2088                                       p_gfx_dpa_setting->DVP1, 0x0F);
2089
2090                        /* DVP1 Clock and Data Pads Driving: */
2091                        viafb_write_reg_mask(SR65, VIASR,
2092                                       p_gfx_dpa_setting->DVP1Driving, 0x0F);
2093                        break;
2094                }
2095
2096        case INTERFACE_DFP_HIGH:
2097                {
2098                        viafb_write_reg_mask(CR97, VIACR,
2099                                       p_gfx_dpa_setting->DFPHigh, 0x0F);
2100                        break;
2101                }
2102
2103        case INTERFACE_DFP_LOW:
2104                {
2105                        viafb_write_reg_mask(CR99, VIACR,
2106                                       p_gfx_dpa_setting->DFPLow, 0x0F);
2107                        break;
2108                }
2109
2110        case INTERFACE_DFP:
2111                {
2112                        viafb_write_reg_mask(CR97, VIACR,
2113                                       p_gfx_dpa_setting->DFPHigh, 0x0F);
2114                        viafb_write_reg_mask(CR99, VIACR,
2115                                       p_gfx_dpa_setting->DFPLow, 0x0F);
2116                        break;
2117                }
2118        }
2119}
2120
2121void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
2122        const struct fb_videomode *mode)
2123{
2124        var->pixclock = mode->pixclock;
2125        var->xres = mode->xres;
2126        var->yres = mode->yres;
2127        var->left_margin = mode->left_margin;
2128        var->right_margin = mode->right_margin;
2129        var->hsync_len = mode->hsync_len;
2130        var->upper_margin = mode->upper_margin;
2131        var->lower_margin = mode->lower_margin;
2132        var->vsync_len = mode->vsync_len;
2133        var->sync = mode->sync;
2134}
2135