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