lcd.c 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821
  1. /*
  2. * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
  3. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public
  6. * License as published by the Free Software Foundation;
  7. * either version 2, or (at your option) any later version.
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
  10. * the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. * A PARTICULAR PURPOSE.See the GNU General Public License
  12. * for more details.
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software
  15. * Foundation, Inc.,
  16. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "global.h"
  19. #include "lcdtbl.h"
  20. static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = {
  21. /* IGA2 Shadow Horizontal Total */
  22. {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } },
  23. /* IGA2 Shadow Horizontal Blank End */
  24. {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } },
  25. /* IGA2 Shadow Vertical Total */
  26. {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } },
  27. /* IGA2 Shadow Vertical Addressable Video */
  28. {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } },
  29. /* IGA2 Shadow Vertical Blank Start */
  30. {IGA2_SHADOW_VER_BLANK_START_REG_NUM,
  31. {{CR72, 0, 7}, {CR74, 4, 6} } },
  32. /* IGA2 Shadow Vertical Blank End */
  33. {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } },
  34. /* IGA2 Shadow Vertical Sync Start */
  35. {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } },
  36. /* IGA2 Shadow Vertical Sync End */
  37. {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } }
  38. };
  39. static struct _lcd_scaling_factor lcd_scaling_factor = {
  40. /* LCD Horizontal Scaling Factor Register */
  41. {LCD_HOR_SCALING_FACTOR_REG_NUM,
  42. {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
  43. /* LCD Vertical Scaling Factor Register */
  44. {LCD_VER_SCALING_FACTOR_REG_NUM,
  45. {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
  46. };
  47. static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
  48. /* LCD Horizontal Scaling Factor Register */
  49. {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
  50. /* LCD Vertical Scaling Factor Register */
  51. {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
  52. };
  53. static int check_lvds_chip(int device_id_subaddr, int device_id);
  54. static bool lvds_identify_integratedlvds(void);
  55. static int fp_id_to_vindex(int panel_id);
  56. static int lvds_register_read(int index);
  57. static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
  58. int panel_vres);
  59. static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
  60. int panel_id);
  61. static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
  62. int panel_id);
  63. static void load_lcd_patch_regs(int set_hres, int set_vres,
  64. int panel_id, int set_iga);
  65. static void via_pitch_alignment_patch_lcd(
  66. struct lvds_setting_information *plvds_setting_info,
  67. struct lvds_chip_information
  68. *plvds_chip_info);
  69. static void lcd_patch_skew_dvp0(struct lvds_setting_information
  70. *plvds_setting_info,
  71. struct lvds_chip_information *plvds_chip_info);
  72. static void lcd_patch_skew_dvp1(struct lvds_setting_information
  73. *plvds_setting_info,
  74. struct lvds_chip_information *plvds_chip_info);
  75. static void lcd_patch_skew(struct lvds_setting_information
  76. *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
  77. static void integrated_lvds_disable(struct lvds_setting_information
  78. *plvds_setting_info,
  79. struct lvds_chip_information *plvds_chip_info);
  80. static void integrated_lvds_enable(struct lvds_setting_information
  81. *plvds_setting_info,
  82. struct lvds_chip_information *plvds_chip_info);
  83. static void lcd_powersequence_off(void);
  84. static void lcd_powersequence_on(void);
  85. static void fill_lcd_format(void);
  86. static void check_diport_of_integrated_lvds(
  87. struct lvds_chip_information *plvds_chip_info,
  88. struct lvds_setting_information
  89. *plvds_setting_info);
  90. static struct display_timing lcd_centering_timging(struct display_timing
  91. mode_crt_reg,
  92. struct display_timing panel_crt_reg);
  93. static void load_crtc_shadow_timing(struct display_timing mode_timing,
  94. struct display_timing panel_timing);
  95. static void viafb_load_scaling_factor_for_p4m900(int set_hres,
  96. int set_vres, int panel_hres, int panel_vres);
  97. static int check_lvds_chip(int device_id_subaddr, int device_id)
  98. {
  99. if (lvds_register_read(device_id_subaddr) == device_id)
  100. return OK;
  101. else
  102. return FAIL;
  103. }
  104. void viafb_init_lcd_size(void)
  105. {
  106. DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
  107. DEBUG_MSG(KERN_INFO
  108. "viaparinfo->lvds_setting_info->get_lcd_size_method %d\n",
  109. viaparinfo->lvds_setting_info->get_lcd_size_method);
  110. switch (viaparinfo->lvds_setting_info->get_lcd_size_method) {
  111. case GET_LCD_SIZE_BY_SYSTEM_BIOS:
  112. break;
  113. case GET_LCD_SZIE_BY_HW_STRAPPING:
  114. break;
  115. case GET_LCD_SIZE_BY_VGA_BIOS:
  116. DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
  117. viaparinfo->lvds_setting_info->lcd_panel_size =
  118. fp_id_to_vindex(viafb_lcd_panel_id);
  119. DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
  120. viaparinfo->lvds_setting_info->lcd_panel_id);
  121. DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
  122. viaparinfo->lvds_setting_info->lcd_panel_size);
  123. break;
  124. case GET_LCD_SIZE_BY_USER_SETTING:
  125. DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
  126. viaparinfo->lvds_setting_info->lcd_panel_size =
  127. fp_id_to_vindex(viafb_lcd_panel_id);
  128. DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
  129. viaparinfo->lvds_setting_info->lcd_panel_id);
  130. DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
  131. viaparinfo->lvds_setting_info->lcd_panel_size);
  132. break;
  133. default:
  134. DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
  135. viaparinfo->lvds_setting_info->lcd_panel_id =
  136. LCD_PANEL_ID1_800X600;
  137. viaparinfo->lvds_setting_info->lcd_panel_size =
  138. fp_id_to_vindex(LCD_PANEL_ID1_800X600);
  139. }
  140. viaparinfo->lvds_setting_info2->lcd_panel_id =
  141. viaparinfo->lvds_setting_info->lcd_panel_id;
  142. viaparinfo->lvds_setting_info2->lcd_panel_size =
  143. viaparinfo->lvds_setting_info->lcd_panel_size;
  144. viaparinfo->lvds_setting_info2->lcd_panel_hres =
  145. viaparinfo->lvds_setting_info->lcd_panel_hres;
  146. viaparinfo->lvds_setting_info2->lcd_panel_vres =
  147. viaparinfo->lvds_setting_info->lcd_panel_vres;
  148. viaparinfo->lvds_setting_info2->device_lcd_dualedge =
  149. viaparinfo->lvds_setting_info->device_lcd_dualedge;
  150. viaparinfo->lvds_setting_info2->LCDDithering =
  151. viaparinfo->lvds_setting_info->LCDDithering;
  152. }
  153. static bool lvds_identify_integratedlvds(void)
  154. {
  155. if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
  156. /* Two dual channel LCD (Internal LVDS + External LVDS): */
  157. /* If we have an external LVDS, such as VT1636, we should
  158. have its chip ID already. */
  159. if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
  160. viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
  161. INTEGRATED_LVDS;
  162. DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\
  163. (Internal LVDS + External LVDS)\n");
  164. } else {
  165. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
  166. INTEGRATED_LVDS;
  167. DEBUG_MSG(KERN_INFO "Not found external LVDS,\
  168. so can't support two dual channel LVDS!\n");
  169. }
  170. } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
  171. /* Two single channel LCD (Internal LVDS + Internal LVDS): */
  172. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
  173. INTEGRATED_LVDS;
  174. viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
  175. INTEGRATED_LVDS;
  176. DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\
  177. (Internal LVDS + Internal LVDS)\n");
  178. } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
  179. /* If we have found external LVDS, just use it,
  180. otherwise, we will use internal LVDS as default. */
  181. if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
  182. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
  183. INTEGRATED_LVDS;
  184. DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
  185. }
  186. } else {
  187. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
  188. NON_LVDS_TRANSMITTER;
  189. DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
  190. return false;
  191. }
  192. return true;
  193. }
  194. int viafb_lvds_trasmitter_identify(void)
  195. {
  196. viaparinfo->i2c_stuff.i2c_port = I2CPORTINDEX;
  197. if (viafb_lvds_identify_vt1636()) {
  198. viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX;
  199. DEBUG_MSG(KERN_INFO
  200. "Found VIA VT1636 LVDS on port i2c 0x31 \n");
  201. } else {
  202. viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX;
  203. if (viafb_lvds_identify_vt1636()) {
  204. viaparinfo->chip_info->lvds_chip_info.i2c_port =
  205. GPIOPORTINDEX;
  206. DEBUG_MSG(KERN_INFO
  207. "Found VIA VT1636 LVDS on port gpio 0x2c \n");
  208. }
  209. }
  210. if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
  211. lvds_identify_integratedlvds();
  212. if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
  213. return true;
  214. /* Check for VT1631: */
  215. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
  216. viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
  217. VT1631_LVDS_I2C_ADDR;
  218. if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID) != FAIL) {
  219. DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
  220. DEBUG_MSG(KERN_INFO "\n %2d",
  221. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
  222. DEBUG_MSG(KERN_INFO "\n %2d",
  223. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
  224. return OK;
  225. }
  226. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
  227. NON_LVDS_TRANSMITTER;
  228. viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
  229. VT1631_LVDS_I2C_ADDR;
  230. return FAIL;
  231. }
  232. static int fp_id_to_vindex(int panel_id)
  233. {
  234. DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
  235. if (panel_id > LCD_PANEL_ID_MAXIMUM)
  236. viafb_lcd_panel_id = panel_id =
  237. viafb_read_reg(VIACR, CR3F) & 0x0F;
  238. switch (panel_id) {
  239. case 0x0:
  240. viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
  241. viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
  242. viaparinfo->lvds_setting_info->lcd_panel_id =
  243. LCD_PANEL_ID0_640X480;
  244. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  245. viaparinfo->lvds_setting_info->LCDDithering = 1;
  246. return VIA_RES_640X480;
  247. break;
  248. case 0x1:
  249. viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
  250. viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
  251. viaparinfo->lvds_setting_info->lcd_panel_id =
  252. LCD_PANEL_ID1_800X600;
  253. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  254. viaparinfo->lvds_setting_info->LCDDithering = 1;
  255. return VIA_RES_800X600;
  256. break;
  257. case 0x2:
  258. viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
  259. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  260. viaparinfo->lvds_setting_info->lcd_panel_id =
  261. LCD_PANEL_ID2_1024X768;
  262. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  263. viaparinfo->lvds_setting_info->LCDDithering = 1;
  264. return VIA_RES_1024X768;
  265. break;
  266. case 0x3:
  267. viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
  268. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  269. viaparinfo->lvds_setting_info->lcd_panel_id =
  270. LCD_PANEL_ID3_1280X768;
  271. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  272. viaparinfo->lvds_setting_info->LCDDithering = 1;
  273. return VIA_RES_1280X768;
  274. break;
  275. case 0x4:
  276. viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
  277. viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
  278. viaparinfo->lvds_setting_info->lcd_panel_id =
  279. LCD_PANEL_ID4_1280X1024;
  280. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  281. viaparinfo->lvds_setting_info->LCDDithering = 1;
  282. return VIA_RES_1280X1024;
  283. break;
  284. case 0x5:
  285. viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
  286. viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
  287. viaparinfo->lvds_setting_info->lcd_panel_id =
  288. LCD_PANEL_ID5_1400X1050;
  289. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  290. viaparinfo->lvds_setting_info->LCDDithering = 1;
  291. return VIA_RES_1400X1050;
  292. break;
  293. case 0x6:
  294. viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
  295. viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
  296. viaparinfo->lvds_setting_info->lcd_panel_id =
  297. LCD_PANEL_ID6_1600X1200;
  298. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  299. viaparinfo->lvds_setting_info->LCDDithering = 1;
  300. return VIA_RES_1600X1200;
  301. break;
  302. case 0x8:
  303. viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
  304. viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
  305. viaparinfo->lvds_setting_info->lcd_panel_id =
  306. LCD_PANEL_IDA_800X480;
  307. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  308. viaparinfo->lvds_setting_info->LCDDithering = 1;
  309. return VIA_RES_800X480;
  310. break;
  311. case 0x9:
  312. viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
  313. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  314. viaparinfo->lvds_setting_info->lcd_panel_id =
  315. LCD_PANEL_ID2_1024X768;
  316. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  317. viaparinfo->lvds_setting_info->LCDDithering = 1;
  318. return VIA_RES_1024X768;
  319. break;
  320. case 0xA:
  321. viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
  322. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  323. viaparinfo->lvds_setting_info->lcd_panel_id =
  324. LCD_PANEL_ID2_1024X768;
  325. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  326. viaparinfo->lvds_setting_info->LCDDithering = 0;
  327. return VIA_RES_1024X768;
  328. break;
  329. case 0xB:
  330. viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
  331. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  332. viaparinfo->lvds_setting_info->lcd_panel_id =
  333. LCD_PANEL_ID2_1024X768;
  334. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  335. viaparinfo->lvds_setting_info->LCDDithering = 0;
  336. return VIA_RES_1024X768;
  337. break;
  338. case 0xC:
  339. viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
  340. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  341. viaparinfo->lvds_setting_info->lcd_panel_id =
  342. LCD_PANEL_ID3_1280X768;
  343. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  344. viaparinfo->lvds_setting_info->LCDDithering = 0;
  345. return VIA_RES_1280X768;
  346. break;
  347. case 0xD:
  348. viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
  349. viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
  350. viaparinfo->lvds_setting_info->lcd_panel_id =
  351. LCD_PANEL_ID4_1280X1024;
  352. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  353. viaparinfo->lvds_setting_info->LCDDithering = 0;
  354. return VIA_RES_1280X1024;
  355. break;
  356. case 0xE:
  357. viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
  358. viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
  359. viaparinfo->lvds_setting_info->lcd_panel_id =
  360. LCD_PANEL_ID5_1400X1050;
  361. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  362. viaparinfo->lvds_setting_info->LCDDithering = 0;
  363. return VIA_RES_1400X1050;
  364. break;
  365. case 0xF:
  366. viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
  367. viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
  368. viaparinfo->lvds_setting_info->lcd_panel_id =
  369. LCD_PANEL_ID6_1600X1200;
  370. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  371. viaparinfo->lvds_setting_info->LCDDithering = 0;
  372. return VIA_RES_1600X1200;
  373. break;
  374. case 0x10:
  375. viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
  376. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  377. viaparinfo->lvds_setting_info->lcd_panel_id =
  378. LCD_PANEL_ID7_1366X768;
  379. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  380. viaparinfo->lvds_setting_info->LCDDithering = 0;
  381. return VIA_RES_1368X768;
  382. break;
  383. case 0x11:
  384. viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
  385. viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
  386. viaparinfo->lvds_setting_info->lcd_panel_id =
  387. LCD_PANEL_ID8_1024X600;
  388. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  389. viaparinfo->lvds_setting_info->LCDDithering = 1;
  390. return VIA_RES_1024X600;
  391. break;
  392. case 0x12:
  393. viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
  394. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  395. viaparinfo->lvds_setting_info->lcd_panel_id =
  396. LCD_PANEL_ID3_1280X768;
  397. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  398. viaparinfo->lvds_setting_info->LCDDithering = 1;
  399. return VIA_RES_1280X768;
  400. break;
  401. case 0x13:
  402. viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
  403. viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
  404. viaparinfo->lvds_setting_info->lcd_panel_id =
  405. LCD_PANEL_ID9_1280X800;
  406. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  407. viaparinfo->lvds_setting_info->LCDDithering = 1;
  408. return VIA_RES_1280X800;
  409. break;
  410. case 0x14:
  411. viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
  412. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  413. viaparinfo->lvds_setting_info->lcd_panel_id =
  414. LCD_PANEL_IDB_1360X768;
  415. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  416. viaparinfo->lvds_setting_info->LCDDithering = 0;
  417. return VIA_RES_1360X768;
  418. break;
  419. case 0x15:
  420. viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
  421. viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
  422. viaparinfo->lvds_setting_info->lcd_panel_id =
  423. LCD_PANEL_ID3_1280X768;
  424. viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
  425. viaparinfo->lvds_setting_info->LCDDithering = 0;
  426. return VIA_RES_1280X768;
  427. break;
  428. case 0x16:
  429. viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
  430. viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
  431. viaparinfo->lvds_setting_info->lcd_panel_id =
  432. LCD_PANEL_IDC_480X640;
  433. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  434. viaparinfo->lvds_setting_info->LCDDithering = 1;
  435. return VIA_RES_480X640;
  436. break;
  437. default:
  438. viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
  439. viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
  440. viaparinfo->lvds_setting_info->lcd_panel_id =
  441. LCD_PANEL_ID1_800X600;
  442. viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
  443. viaparinfo->lvds_setting_info->LCDDithering = 1;
  444. return VIA_RES_800X600;
  445. }
  446. }
  447. static int lvds_register_read(int index)
  448. {
  449. u8 data;
  450. viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX;
  451. viafb_i2c_readbyte((u8) viaparinfo->chip_info->
  452. lvds_chip_info.lvds_chip_slave_addr,
  453. (u8) index, &data);
  454. return data;
  455. }
  456. static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
  457. int panel_vres)
  458. {
  459. int reg_value = 0;
  460. int viafb_load_reg_num;
  461. struct io_register *reg = NULL;
  462. DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
  463. /* LCD Scaling Enable */
  464. viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
  465. if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
  466. viafb_load_scaling_factor_for_p4m900(set_hres, set_vres,
  467. panel_hres, panel_vres);
  468. return;
  469. }
  470. /* Check if expansion for horizontal */
  471. if (set_hres != panel_hres) {
  472. /* Load Horizontal Scaling Factor */
  473. switch (viaparinfo->chip_info->gfx_chip_name) {
  474. case UNICHROME_CLE266:
  475. case UNICHROME_K400:
  476. reg_value =
  477. CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
  478. viafb_load_reg_num =
  479. lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
  480. reg_num;
  481. reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
  482. viafb_load_reg(reg_value,
  483. viafb_load_reg_num, reg, VIACR);
  484. break;
  485. case UNICHROME_K800:
  486. case UNICHROME_PM800:
  487. case UNICHROME_CN700:
  488. case UNICHROME_CX700:
  489. case UNICHROME_K8M890:
  490. case UNICHROME_P4M890:
  491. reg_value =
  492. K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
  493. /* Horizontal scaling enabled */
  494. viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
  495. viafb_load_reg_num =
  496. lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
  497. reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
  498. viafb_load_reg(reg_value,
  499. viafb_load_reg_num, reg, VIACR);
  500. break;
  501. }
  502. DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
  503. } else {
  504. /* Horizontal scaling disabled */
  505. viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
  506. }
  507. /* Check if expansion for vertical */
  508. if (set_vres != panel_vres) {
  509. /* Load Vertical Scaling Factor */
  510. switch (viaparinfo->chip_info->gfx_chip_name) {
  511. case UNICHROME_CLE266:
  512. case UNICHROME_K400:
  513. reg_value =
  514. CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
  515. viafb_load_reg_num =
  516. lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
  517. reg_num;
  518. reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
  519. viafb_load_reg(reg_value,
  520. viafb_load_reg_num, reg, VIACR);
  521. break;
  522. case UNICHROME_K800:
  523. case UNICHROME_PM800:
  524. case UNICHROME_CN700:
  525. case UNICHROME_CX700:
  526. case UNICHROME_K8M890:
  527. case UNICHROME_P4M890:
  528. reg_value =
  529. K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
  530. /* Vertical scaling enabled */
  531. viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
  532. viafb_load_reg_num =
  533. lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
  534. reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
  535. viafb_load_reg(reg_value,
  536. viafb_load_reg_num, reg, VIACR);
  537. break;
  538. }
  539. DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
  540. } else {
  541. /* Vertical scaling disabled */
  542. viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
  543. }
  544. }
  545. static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
  546. int panel_id)
  547. {
  548. int vmode_index;
  549. int reg_num = 0;
  550. struct io_reg *lcd_patch_reg = NULL;
  551. if (viaparinfo->lvds_setting_info->iga_path == IGA2)
  552. vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
  553. else
  554. vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
  555. switch (panel_id) {
  556. /* LCD 800x600 */
  557. case LCD_PANEL_ID1_800X600:
  558. switch (vmode_index) {
  559. case VIA_RES_640X400:
  560. case VIA_RES_640X480:
  561. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6;
  562. lcd_patch_reg = K400_LCD_RES_6X4_8X6;
  563. break;
  564. case VIA_RES_720X480:
  565. case VIA_RES_720X576:
  566. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6;
  567. lcd_patch_reg = K400_LCD_RES_7X4_8X6;
  568. break;
  569. }
  570. break;
  571. /* LCD 1024x768 */
  572. case LCD_PANEL_ID2_1024X768:
  573. switch (vmode_index) {
  574. case VIA_RES_640X400:
  575. case VIA_RES_640X480:
  576. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7;
  577. lcd_patch_reg = K400_LCD_RES_6X4_10X7;
  578. break;
  579. case VIA_RES_720X480:
  580. case VIA_RES_720X576:
  581. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7;
  582. lcd_patch_reg = K400_LCD_RES_7X4_10X7;
  583. break;
  584. case VIA_RES_800X600:
  585. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7;
  586. lcd_patch_reg = K400_LCD_RES_8X6_10X7;
  587. break;
  588. }
  589. break;
  590. /* LCD 1280x1024 */
  591. case LCD_PANEL_ID4_1280X1024:
  592. switch (vmode_index) {
  593. case VIA_RES_640X400:
  594. case VIA_RES_640X480:
  595. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10;
  596. lcd_patch_reg = K400_LCD_RES_6X4_12X10;
  597. break;
  598. case VIA_RES_720X480:
  599. case VIA_RES_720X576:
  600. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10;
  601. lcd_patch_reg = K400_LCD_RES_7X4_12X10;
  602. break;
  603. case VIA_RES_800X600:
  604. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10;
  605. lcd_patch_reg = K400_LCD_RES_8X6_12X10;
  606. break;
  607. case VIA_RES_1024X768:
  608. reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10;
  609. lcd_patch_reg = K400_LCD_RES_10X7_12X10;
  610. break;
  611. }
  612. break;
  613. /* LCD 1400x1050 */
  614. case LCD_PANEL_ID5_1400X1050:
  615. switch (vmode_index) {
  616. case VIA_RES_640X480:
  617. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10;
  618. lcd_patch_reg = K400_LCD_RES_6X4_14X10;
  619. break;
  620. case VIA_RES_800X600:
  621. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10;
  622. lcd_patch_reg = K400_LCD_RES_8X6_14X10;
  623. break;
  624. case VIA_RES_1024X768:
  625. reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10;
  626. lcd_patch_reg = K400_LCD_RES_10X7_14X10;
  627. break;
  628. case VIA_RES_1280X768:
  629. case VIA_RES_1280X800:
  630. case VIA_RES_1280X960:
  631. case VIA_RES_1280X1024:
  632. reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10;
  633. lcd_patch_reg = K400_LCD_RES_12X10_14X10;
  634. break;
  635. }
  636. break;
  637. /* LCD 1600x1200 */
  638. case LCD_PANEL_ID6_1600X1200:
  639. switch (vmode_index) {
  640. case VIA_RES_640X400:
  641. case VIA_RES_640X480:
  642. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12;
  643. lcd_patch_reg = K400_LCD_RES_6X4_16X12;
  644. break;
  645. case VIA_RES_720X480:
  646. case VIA_RES_720X576:
  647. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12;
  648. lcd_patch_reg = K400_LCD_RES_7X4_16X12;
  649. break;
  650. case VIA_RES_800X600:
  651. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12;
  652. lcd_patch_reg = K400_LCD_RES_8X6_16X12;
  653. break;
  654. case VIA_RES_1024X768:
  655. reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12;
  656. lcd_patch_reg = K400_LCD_RES_10X7_16X12;
  657. break;
  658. case VIA_RES_1280X768:
  659. case VIA_RES_1280X800:
  660. case VIA_RES_1280X960:
  661. case VIA_RES_1280X1024:
  662. reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12;
  663. lcd_patch_reg = K400_LCD_RES_12X10_16X12;
  664. break;
  665. }
  666. break;
  667. /* LCD 1366x768 */
  668. case LCD_PANEL_ID7_1366X768:
  669. switch (vmode_index) {
  670. case VIA_RES_640X480:
  671. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7;
  672. lcd_patch_reg = K400_LCD_RES_6X4_1366X7;
  673. break;
  674. case VIA_RES_720X480:
  675. case VIA_RES_720X576:
  676. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7;
  677. lcd_patch_reg = K400_LCD_RES_7X4_1366X7;
  678. break;
  679. case VIA_RES_800X600:
  680. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7;
  681. lcd_patch_reg = K400_LCD_RES_8X6_1366X7;
  682. break;
  683. case VIA_RES_1024X768:
  684. reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7;
  685. lcd_patch_reg = K400_LCD_RES_10X7_1366X7;
  686. break;
  687. case VIA_RES_1280X768:
  688. case VIA_RES_1280X800:
  689. case VIA_RES_1280X960:
  690. case VIA_RES_1280X1024:
  691. reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7;
  692. lcd_patch_reg = K400_LCD_RES_12X10_1366X7;
  693. break;
  694. }
  695. break;
  696. /* LCD 1360x768 */
  697. case LCD_PANEL_IDB_1360X768:
  698. break;
  699. }
  700. if (reg_num != 0) {
  701. /* H.W. Reset : ON */
  702. viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
  703. viafb_write_regx(lcd_patch_reg, reg_num);
  704. /* H.W. Reset : OFF */
  705. viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
  706. /* Reset PLL */
  707. viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
  708. viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
  709. /* Fire! */
  710. outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
  711. }
  712. }
  713. static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
  714. int panel_id)
  715. {
  716. int vmode_index;
  717. int reg_num = 0;
  718. struct io_reg *lcd_patch_reg = NULL;
  719. if (viaparinfo->lvds_setting_info->iga_path == IGA2)
  720. vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
  721. else
  722. vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
  723. switch (panel_id) {
  724. case LCD_PANEL_ID5_1400X1050:
  725. switch (vmode_index) {
  726. case VIA_RES_640X480:
  727. reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10;
  728. lcd_patch_reg = P880_LCD_RES_6X4_14X10;
  729. break;
  730. case VIA_RES_800X600:
  731. reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10;
  732. lcd_patch_reg = P880_LCD_RES_8X6_14X10;
  733. break;
  734. }
  735. break;
  736. case LCD_PANEL_ID6_1600X1200:
  737. switch (vmode_index) {
  738. case VIA_RES_640X400:
  739. case VIA_RES_640X480:
  740. reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12;
  741. lcd_patch_reg = P880_LCD_RES_6X4_16X12;
  742. break;
  743. case VIA_RES_720X480:
  744. case VIA_RES_720X576:
  745. reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12;
  746. lcd_patch_reg = P880_LCD_RES_7X4_16X12;
  747. break;
  748. case VIA_RES_800X600:
  749. reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12;
  750. lcd_patch_reg = P880_LCD_RES_8X6_16X12;
  751. break;
  752. case VIA_RES_1024X768:
  753. reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12;
  754. lcd_patch_reg = P880_LCD_RES_10X7_16X12;
  755. break;
  756. case VIA_RES_1280X768:
  757. case VIA_RES_1280X960:
  758. case VIA_RES_1280X1024:
  759. reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12;
  760. lcd_patch_reg = P880_LCD_RES_12X10_16X12;
  761. break;
  762. }
  763. break;
  764. }
  765. if (reg_num != 0) {
  766. /* H.W. Reset : ON */
  767. viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
  768. viafb_write_regx(lcd_patch_reg, reg_num);
  769. /* H.W. Reset : OFF */
  770. viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
  771. /* Reset PLL */
  772. viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
  773. viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
  774. /* Fire! */
  775. outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
  776. }
  777. }
  778. static void load_lcd_patch_regs(int set_hres, int set_vres,
  779. int panel_id, int set_iga)
  780. {
  781. int vmode_index;
  782. if (viaparinfo->lvds_setting_info->iga_path == IGA2)
  783. vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
  784. else
  785. vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
  786. viafb_unlock_crt();
  787. /* Patch for simultaneous & Expansion */
  788. if ((set_iga == IGA1_IGA2) &&
  789. (viaparinfo->lvds_setting_info->display_method ==
  790. LCD_EXPANDSION)) {
  791. switch (viaparinfo->chip_info->gfx_chip_name) {
  792. case UNICHROME_CLE266:
  793. case UNICHROME_K400:
  794. load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id);
  795. break;
  796. case UNICHROME_K800:
  797. break;
  798. case UNICHROME_PM800:
  799. case UNICHROME_CN700:
  800. case UNICHROME_CX700:
  801. load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id);
  802. }
  803. }
  804. viafb_lock_crt();
  805. }
  806. static void via_pitch_alignment_patch_lcd(
  807. struct lvds_setting_information *plvds_setting_info,
  808. struct lvds_chip_information
  809. *plvds_chip_info)
  810. {
  811. unsigned char cr13, cr35, cr65, cr66, cr67;
  812. unsigned long dwScreenPitch = 0;
  813. unsigned long dwPitch;
  814. dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3);
  815. if (dwPitch & 0x1F) {
  816. dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
  817. if (plvds_setting_info->iga_path == IGA2) {
  818. if (plvds_setting_info->bpp > 8) {
  819. cr66 = (unsigned char)(dwScreenPitch & 0xFF);
  820. viafb_write_reg(CR66, VIACR, cr66);
  821. cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
  822. cr67 |=
  823. (unsigned
  824. char)((dwScreenPitch & 0x300) >> 8);
  825. viafb_write_reg(CR67, VIACR, cr67);
  826. }
  827. /* Fetch Count */
  828. cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
  829. cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
  830. viafb_write_reg(CR67, VIACR, cr67);
  831. cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
  832. cr65 += 2;
  833. viafb_write_reg(CR65, VIACR, cr65);
  834. } else {
  835. if (plvds_setting_info->bpp > 8) {
  836. cr13 = (unsigned char)(dwScreenPitch & 0xFF);
  837. viafb_write_reg(CR13, VIACR, cr13);
  838. cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
  839. cr35 |=
  840. (unsigned
  841. char)((dwScreenPitch & 0x700) >> 3);
  842. viafb_write_reg(CR35, VIACR, cr35);
  843. }
  844. }
  845. }
  846. }
  847. static void lcd_patch_skew_dvp0(struct lvds_setting_information
  848. *plvds_setting_info,
  849. struct lvds_chip_information *plvds_chip_info)
  850. {
  851. if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
  852. switch (viaparinfo->chip_info->gfx_chip_name) {
  853. case UNICHROME_P4M900:
  854. viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
  855. plvds_chip_info);
  856. break;
  857. case UNICHROME_P4M890:
  858. viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
  859. plvds_chip_info);
  860. break;
  861. }
  862. }
  863. }
  864. static void lcd_patch_skew_dvp1(struct lvds_setting_information
  865. *plvds_setting_info,
  866. struct lvds_chip_information *plvds_chip_info)
  867. {
  868. if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
  869. switch (viaparinfo->chip_info->gfx_chip_name) {
  870. case UNICHROME_CX700:
  871. viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
  872. plvds_chip_info);
  873. break;
  874. }
  875. }
  876. }
  877. static void lcd_patch_skew(struct lvds_setting_information
  878. *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
  879. {
  880. DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
  881. switch (plvds_chip_info->output_interface) {
  882. case INTERFACE_DVP0:
  883. lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
  884. break;
  885. case INTERFACE_DVP1:
  886. lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
  887. break;
  888. case INTERFACE_DFP_LOW:
  889. if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
  890. viafb_write_reg_mask(CR99, VIACR, 0x08,
  891. BIT0 + BIT1 + BIT2 + BIT3);
  892. }
  893. break;
  894. }
  895. }
  896. /* LCD Set Mode */
  897. void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
  898. struct lvds_setting_information *plvds_setting_info,
  899. struct lvds_chip_information *plvds_chip_info)
  900. {
  901. int video_index = plvds_setting_info->lcd_panel_size;
  902. int set_iga = plvds_setting_info->iga_path;
  903. int mode_bpp = plvds_setting_info->bpp;
  904. int viafb_load_reg_num = 0;
  905. int reg_value = 0;
  906. int set_hres, set_vres;
  907. int panel_hres, panel_vres;
  908. u32 pll_D_N;
  909. int offset;
  910. struct io_register *reg = NULL;
  911. struct display_timing mode_crt_reg, panel_crt_reg;
  912. struct crt_mode_table *panel_crt_table = NULL;
  913. struct VideoModeTable *vmode_tbl = NULL;
  914. DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
  915. /* Get mode table */
  916. mode_crt_reg = mode_crt_table->crtc;
  917. /* Get panel table Pointer */
  918. vmode_tbl = viafb_get_modetbl_pointer(video_index);
  919. panel_crt_table = vmode_tbl->crtc;
  920. panel_crt_reg = panel_crt_table->crtc;
  921. DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
  922. set_hres = plvds_setting_info->h_active;
  923. set_vres = plvds_setting_info->v_active;
  924. panel_hres = plvds_setting_info->lcd_panel_hres;
  925. panel_vres = plvds_setting_info->lcd_panel_vres;
  926. if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
  927. viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
  928. plvds_setting_info->vclk = panel_crt_table->clk;
  929. if (set_iga == IGA1) {
  930. /* IGA1 doesn't have LCD scaling, so set it as centering. */
  931. viafb_load_crtc_timing(lcd_centering_timging
  932. (mode_crt_reg, panel_crt_reg), IGA1);
  933. } else {
  934. /* Expansion */
  935. if ((plvds_setting_info->display_method ==
  936. LCD_EXPANDSION) & ((set_hres != panel_hres)
  937. || (set_vres != panel_vres))) {
  938. /* expansion timing IGA2 loaded panel set timing*/
  939. viafb_load_crtc_timing(panel_crt_reg, IGA2);
  940. DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
  941. load_lcd_scaling(set_hres, set_vres, panel_hres,
  942. panel_vres);
  943. DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
  944. } else { /* Centering */
  945. /* centering timing IGA2 always loaded panel
  946. and mode releative timing */
  947. viafb_load_crtc_timing(lcd_centering_timging
  948. (mode_crt_reg, panel_crt_reg), IGA2);
  949. viafb_write_reg_mask(CR79, VIACR, 0x00,
  950. BIT0 + BIT1 + BIT2);
  951. /* LCD scaling disabled */
  952. }
  953. }
  954. if (set_iga == IGA1_IGA2) {
  955. load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg);
  956. /* Fill shadow registers */
  957. switch (plvds_setting_info->lcd_panel_id) {
  958. case LCD_PANEL_ID0_640X480:
  959. offset = 80;
  960. break;
  961. case LCD_PANEL_ID1_800X600:
  962. case LCD_PANEL_IDA_800X480:
  963. offset = 110;
  964. break;
  965. case LCD_PANEL_ID2_1024X768:
  966. offset = 150;
  967. break;
  968. case LCD_PANEL_ID3_1280X768:
  969. case LCD_PANEL_ID4_1280X1024:
  970. case LCD_PANEL_ID5_1400X1050:
  971. case LCD_PANEL_ID9_1280X800:
  972. offset = 190;
  973. break;
  974. case LCD_PANEL_ID6_1600X1200:
  975. offset = 250;
  976. break;
  977. case LCD_PANEL_ID7_1366X768:
  978. case LCD_PANEL_IDB_1360X768:
  979. offset = 212;
  980. break;
  981. default:
  982. offset = 140;
  983. break;
  984. }
  985. /* Offset for simultaneous */
  986. reg_value = offset;
  987. viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
  988. reg = offset_reg.iga2_offset_reg.reg;
  989. viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
  990. DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
  991. viafb_load_fetch_count_reg(set_hres, 4, IGA2);
  992. /* Fetch count for simultaneous */
  993. } else { /* SAMM */
  994. /* Offset for IGA2 only */
  995. viafb_load_offset_reg(set_hres, mode_bpp / 8, set_iga);
  996. /* Fetch count for IGA2 only */
  997. viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
  998. if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
  999. && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
  1000. viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
  1001. viafb_set_color_depth(mode_bpp / 8, set_iga);
  1002. }
  1003. fill_lcd_format();
  1004. pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
  1005. DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
  1006. viafb_set_vclock(pll_D_N, set_iga);
  1007. viafb_set_output_path(DEVICE_LCD, set_iga,
  1008. plvds_chip_info->output_interface);
  1009. lcd_patch_skew(plvds_setting_info, plvds_chip_info);
  1010. /* If K8M800, enable LCD Prefetch Mode. */
  1011. if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
  1012. || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
  1013. viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
  1014. load_lcd_patch_regs(set_hres, set_vres,
  1015. plvds_setting_info->lcd_panel_id, set_iga);
  1016. DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n");
  1017. /* Patch for non 32bit alignment mode */
  1018. via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
  1019. }
  1020. static void integrated_lvds_disable(struct lvds_setting_information
  1021. *plvds_setting_info,
  1022. struct lvds_chip_information *plvds_chip_info)
  1023. {
  1024. bool turn_off_first_powersequence = false;
  1025. bool turn_off_second_powersequence = false;
  1026. if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
  1027. turn_off_first_powersequence = true;
  1028. if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
  1029. turn_off_first_powersequence = true;
  1030. if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
  1031. turn_off_second_powersequence = true;
  1032. if (turn_off_second_powersequence) {
  1033. /* Use second power sequence control: */
  1034. /* Turn off power sequence. */
  1035. viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
  1036. /* Turn off back light. */
  1037. viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
  1038. }
  1039. if (turn_off_first_powersequence) {
  1040. /* Use first power sequence control: */
  1041. /* Turn off power sequence. */
  1042. viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
  1043. /* Turn off back light. */
  1044. viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
  1045. }
  1046. /* Turn DFP High/Low Pad off. */
  1047. viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
  1048. /* Power off LVDS channel. */
  1049. switch (plvds_chip_info->output_interface) {
  1050. case INTERFACE_LVDS0:
  1051. {
  1052. viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
  1053. break;
  1054. }
  1055. case INTERFACE_LVDS1:
  1056. {
  1057. viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
  1058. break;
  1059. }
  1060. case INTERFACE_LVDS0LVDS1:
  1061. {
  1062. viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
  1063. break;
  1064. }
  1065. }
  1066. }
  1067. static void integrated_lvds_enable(struct lvds_setting_information
  1068. *plvds_setting_info,
  1069. struct lvds_chip_information *plvds_chip_info)
  1070. {
  1071. bool turn_on_first_powersequence = false;
  1072. bool turn_on_second_powersequence = false;
  1073. DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
  1074. plvds_chip_info->output_interface);
  1075. if (plvds_setting_info->lcd_mode == LCD_SPWG)
  1076. viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
  1077. else
  1078. viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
  1079. if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
  1080. turn_on_first_powersequence = true;
  1081. if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
  1082. turn_on_first_powersequence = true;
  1083. if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
  1084. turn_on_second_powersequence = true;
  1085. if (turn_on_second_powersequence) {
  1086. /* Use second power sequence control: */
  1087. /* Use hardware control power sequence. */
  1088. viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
  1089. /* Turn on back light. */
  1090. viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
  1091. /* Turn on hardware power sequence. */
  1092. viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
  1093. }
  1094. if (turn_on_first_powersequence) {
  1095. /* Use first power sequence control: */
  1096. /* Use hardware control power sequence. */
  1097. viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
  1098. /* Turn on back light. */
  1099. viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
  1100. /* Turn on hardware power sequence. */
  1101. viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
  1102. }
  1103. /* Turn DFP High/Low pad on. */
  1104. viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
  1105. /* Power on LVDS channel. */
  1106. switch (plvds_chip_info->output_interface) {
  1107. case INTERFACE_LVDS0:
  1108. {
  1109. viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
  1110. break;
  1111. }
  1112. case INTERFACE_LVDS1:
  1113. {
  1114. viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
  1115. break;
  1116. }
  1117. case INTERFACE_LVDS0LVDS1:
  1118. {
  1119. viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
  1120. break;
  1121. }
  1122. }
  1123. }
  1124. void viafb_lcd_disable(void)
  1125. {
  1126. if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
  1127. lcd_powersequence_off();
  1128. /* DI1 pad off */
  1129. viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
  1130. } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
  1131. if (viafb_LCD2_ON
  1132. && (INTEGRATED_LVDS ==
  1133. viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
  1134. integrated_lvds_disable(viaparinfo->lvds_setting_info,
  1135. &viaparinfo->chip_info->lvds_chip_info2);
  1136. if (INTEGRATED_LVDS ==
  1137. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
  1138. integrated_lvds_disable(viaparinfo->lvds_setting_info,
  1139. &viaparinfo->chip_info->lvds_chip_info);
  1140. if (VT1636_LVDS == viaparinfo->chip_info->
  1141. lvds_chip_info.lvds_chip_name)
  1142. viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
  1143. &viaparinfo->chip_info->lvds_chip_info);
  1144. } else if (VT1636_LVDS ==
  1145. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
  1146. viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
  1147. &viaparinfo->chip_info->lvds_chip_info);
  1148. } else {
  1149. /* DFP-HL pad off */
  1150. viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
  1151. /* Backlight off */
  1152. viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
  1153. /* 24 bit DI data paht off */
  1154. viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
  1155. /* Simultaneout disabled */
  1156. viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
  1157. }
  1158. /* Disable expansion bit */
  1159. viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
  1160. /* CRT path set to IGA1 */
  1161. viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
  1162. /* Simultaneout disabled */
  1163. viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
  1164. /* IGA2 path disabled */
  1165. viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
  1166. }
  1167. void viafb_lcd_enable(void)
  1168. {
  1169. if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
  1170. /* DI1 pad on */
  1171. viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
  1172. lcd_powersequence_on();
  1173. } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
  1174. if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
  1175. viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
  1176. integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
  1177. &viaparinfo->chip_info->lvds_chip_info2);
  1178. if (INTEGRATED_LVDS ==
  1179. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
  1180. integrated_lvds_enable(viaparinfo->lvds_setting_info,
  1181. &viaparinfo->chip_info->lvds_chip_info);
  1182. if (VT1636_LVDS == viaparinfo->chip_info->
  1183. lvds_chip_info.lvds_chip_name)
  1184. viafb_enable_lvds_vt1636(viaparinfo->
  1185. lvds_setting_info, &viaparinfo->chip_info->
  1186. lvds_chip_info);
  1187. } else if (VT1636_LVDS ==
  1188. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
  1189. viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
  1190. &viaparinfo->chip_info->lvds_chip_info);
  1191. } else {
  1192. /* DFP-HL pad on */
  1193. viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
  1194. /* Backlight on */
  1195. viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
  1196. /* 24 bit DI data paht on */
  1197. viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
  1198. /* Set data source selection bit by iga path */
  1199. if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
  1200. /* DFP-H set to IGA1 */
  1201. viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
  1202. /* DFP-L set to IGA1 */
  1203. viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
  1204. } else {
  1205. /* DFP-H set to IGA2 */
  1206. viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
  1207. /* DFP-L set to IGA2 */
  1208. viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
  1209. }
  1210. /* LCD enabled */
  1211. viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
  1212. }
  1213. if ((viaparinfo->lvds_setting_info->iga_path == IGA1)
  1214. || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) {
  1215. /* CRT path set to IGA2 */
  1216. viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
  1217. /* IGA2 path disabled */
  1218. viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
  1219. /* IGA2 path enabled */
  1220. } else { /* IGA2 */
  1221. viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
  1222. }
  1223. }
  1224. static void lcd_powersequence_off(void)
  1225. {
  1226. int i, mask, data;
  1227. /* Software control power sequence */
  1228. viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
  1229. for (i = 0; i < 3; i++) {
  1230. mask = PowerSequenceOff[0][i];
  1231. data = PowerSequenceOff[1][i] & mask;
  1232. viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
  1233. udelay(PowerSequenceOff[2][i]);
  1234. }
  1235. /* Disable LCD */
  1236. viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
  1237. }
  1238. static void lcd_powersequence_on(void)
  1239. {
  1240. int i, mask, data;
  1241. /* Software control power sequence */
  1242. viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
  1243. /* Enable LCD */
  1244. viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
  1245. for (i = 0; i < 3; i++) {
  1246. mask = PowerSequenceOn[0][i];
  1247. data = PowerSequenceOn[1][i] & mask;
  1248. viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
  1249. udelay(PowerSequenceOn[2][i]);
  1250. }
  1251. udelay(1);
  1252. }
  1253. static void fill_lcd_format(void)
  1254. {
  1255. u8 bdithering = 0, bdual = 0;
  1256. if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
  1257. bdual = BIT4;
  1258. if (viaparinfo->lvds_setting_info->LCDDithering)
  1259. bdithering = BIT0;
  1260. /* Dual & Dithering */
  1261. viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
  1262. }
  1263. static void check_diport_of_integrated_lvds(
  1264. struct lvds_chip_information *plvds_chip_info,
  1265. struct lvds_setting_information
  1266. *plvds_setting_info)
  1267. {
  1268. /* Determine LCD DI Port by hardware layout. */
  1269. switch (viafb_display_hardware_layout) {
  1270. case HW_LAYOUT_LCD_ONLY:
  1271. {
  1272. if (plvds_setting_info->device_lcd_dualedge) {
  1273. plvds_chip_info->output_interface =
  1274. INTERFACE_LVDS0LVDS1;
  1275. } else {
  1276. plvds_chip_info->output_interface =
  1277. INTERFACE_LVDS0;
  1278. }
  1279. break;
  1280. }
  1281. case HW_LAYOUT_DVI_ONLY:
  1282. {
  1283. plvds_chip_info->output_interface = INTERFACE_NONE;
  1284. break;
  1285. }
  1286. case HW_LAYOUT_LCD1_LCD2:
  1287. case HW_LAYOUT_LCD_EXTERNAL_LCD2:
  1288. {
  1289. plvds_chip_info->output_interface =
  1290. INTERFACE_LVDS0LVDS1;
  1291. break;
  1292. }
  1293. case HW_LAYOUT_LCD_DVI:
  1294. {
  1295. plvds_chip_info->output_interface = INTERFACE_LVDS1;
  1296. break;
  1297. }
  1298. default:
  1299. {
  1300. plvds_chip_info->output_interface = INTERFACE_LVDS1;
  1301. break;
  1302. }
  1303. }
  1304. DEBUG_MSG(KERN_INFO
  1305. "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
  1306. viafb_display_hardware_layout,
  1307. plvds_chip_info->output_interface);
  1308. }
  1309. void viafb_init_lvds_output_interface(struct lvds_chip_information
  1310. *plvds_chip_info,
  1311. struct lvds_setting_information
  1312. *plvds_setting_info)
  1313. {
  1314. if (INTERFACE_NONE != plvds_chip_info->output_interface) {
  1315. /*Do nothing, lcd port is specified by module parameter */
  1316. return;
  1317. }
  1318. switch (plvds_chip_info->lvds_chip_name) {
  1319. case VT1636_LVDS:
  1320. switch (viaparinfo->chip_info->gfx_chip_name) {
  1321. case UNICHROME_CX700:
  1322. plvds_chip_info->output_interface = INTERFACE_DVP1;
  1323. break;
  1324. case UNICHROME_CN700:
  1325. plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
  1326. break;
  1327. default:
  1328. plvds_chip_info->output_interface = INTERFACE_DVP0;
  1329. break;
  1330. }
  1331. break;
  1332. case INTEGRATED_LVDS:
  1333. check_diport_of_integrated_lvds(plvds_chip_info,
  1334. plvds_setting_info);
  1335. break;
  1336. default:
  1337. switch (viaparinfo->chip_info->gfx_chip_name) {
  1338. case UNICHROME_K8M890:
  1339. case UNICHROME_P4M900:
  1340. case UNICHROME_P4M890:
  1341. plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
  1342. break;
  1343. default:
  1344. plvds_chip_info->output_interface = INTERFACE_DFP;
  1345. break;
  1346. }
  1347. break;
  1348. }
  1349. }
  1350. static struct display_timing lcd_centering_timging(struct display_timing
  1351. mode_crt_reg,
  1352. struct display_timing panel_crt_reg)
  1353. {
  1354. struct display_timing crt_reg;
  1355. crt_reg.hor_total = panel_crt_reg.hor_total;
  1356. crt_reg.hor_addr = mode_crt_reg.hor_addr;
  1357. crt_reg.hor_blank_start =
  1358. (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
  1359. crt_reg.hor_addr;
  1360. crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
  1361. crt_reg.hor_sync_start =
  1362. (panel_crt_reg.hor_sync_start -
  1363. panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
  1364. crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
  1365. crt_reg.ver_total = panel_crt_reg.ver_total;
  1366. crt_reg.ver_addr = mode_crt_reg.ver_addr;
  1367. crt_reg.ver_blank_start =
  1368. (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
  1369. crt_reg.ver_addr;
  1370. crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
  1371. crt_reg.ver_sync_start =
  1372. (panel_crt_reg.ver_sync_start -
  1373. panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
  1374. crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
  1375. return crt_reg;
  1376. }
  1377. static void load_crtc_shadow_timing(struct display_timing mode_timing,
  1378. struct display_timing panel_timing)
  1379. {
  1380. struct io_register *reg = NULL;
  1381. int i;
  1382. int viafb_load_reg_Num = 0;
  1383. int reg_value = 0;
  1384. if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) {
  1385. /* Expansion */
  1386. for (i = 12; i < 20; i++) {
  1387. switch (i) {
  1388. case H_TOTAL_SHADOW_INDEX:
  1389. reg_value =
  1390. IGA2_HOR_TOTAL_SHADOW_FORMULA
  1391. (panel_timing.hor_total);
  1392. viafb_load_reg_Num =
  1393. iga2_shadow_crtc_reg.hor_total_shadow.
  1394. reg_num;
  1395. reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
  1396. break;
  1397. case H_BLANK_END_SHADOW_INDEX:
  1398. reg_value =
  1399. IGA2_HOR_BLANK_END_SHADOW_FORMULA
  1400. (panel_timing.hor_blank_start,
  1401. panel_timing.hor_blank_end);
  1402. viafb_load_reg_Num =
  1403. iga2_shadow_crtc_reg.
  1404. hor_blank_end_shadow.reg_num;
  1405. reg =
  1406. iga2_shadow_crtc_reg.
  1407. hor_blank_end_shadow.reg;
  1408. break;
  1409. case V_TOTAL_SHADOW_INDEX:
  1410. reg_value =
  1411. IGA2_VER_TOTAL_SHADOW_FORMULA
  1412. (panel_timing.ver_total);
  1413. viafb_load_reg_Num =
  1414. iga2_shadow_crtc_reg.ver_total_shadow.
  1415. reg_num;
  1416. reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
  1417. break;
  1418. case V_ADDR_SHADOW_INDEX:
  1419. reg_value =
  1420. IGA2_VER_ADDR_SHADOW_FORMULA
  1421. (panel_timing.ver_addr);
  1422. viafb_load_reg_Num =
  1423. iga2_shadow_crtc_reg.ver_addr_shadow.
  1424. reg_num;
  1425. reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
  1426. break;
  1427. case V_BLANK_SATRT_SHADOW_INDEX:
  1428. reg_value =
  1429. IGA2_VER_BLANK_START_SHADOW_FORMULA
  1430. (panel_timing.ver_blank_start);
  1431. viafb_load_reg_Num =
  1432. iga2_shadow_crtc_reg.
  1433. ver_blank_start_shadow.reg_num;
  1434. reg =
  1435. iga2_shadow_crtc_reg.
  1436. ver_blank_start_shadow.reg;
  1437. break;
  1438. case V_BLANK_END_SHADOW_INDEX:
  1439. reg_value =
  1440. IGA2_VER_BLANK_END_SHADOW_FORMULA
  1441. (panel_timing.ver_blank_start,
  1442. panel_timing.ver_blank_end);
  1443. viafb_load_reg_Num =
  1444. iga2_shadow_crtc_reg.
  1445. ver_blank_end_shadow.reg_num;
  1446. reg =
  1447. iga2_shadow_crtc_reg.
  1448. ver_blank_end_shadow.reg;
  1449. break;
  1450. case V_SYNC_SATRT_SHADOW_INDEX:
  1451. reg_value =
  1452. IGA2_VER_SYNC_START_SHADOW_FORMULA
  1453. (panel_timing.ver_sync_start);
  1454. viafb_load_reg_Num =
  1455. iga2_shadow_crtc_reg.
  1456. ver_sync_start_shadow.reg_num;
  1457. reg =
  1458. iga2_shadow_crtc_reg.
  1459. ver_sync_start_shadow.reg;
  1460. break;
  1461. case V_SYNC_END_SHADOW_INDEX:
  1462. reg_value =
  1463. IGA2_VER_SYNC_END_SHADOW_FORMULA
  1464. (panel_timing.ver_sync_start,
  1465. panel_timing.ver_sync_end);
  1466. viafb_load_reg_Num =
  1467. iga2_shadow_crtc_reg.
  1468. ver_sync_end_shadow.reg_num;
  1469. reg =
  1470. iga2_shadow_crtc_reg.
  1471. ver_sync_end_shadow.reg;
  1472. break;
  1473. }
  1474. viafb_load_reg(reg_value,
  1475. viafb_load_reg_Num, reg, VIACR);
  1476. }
  1477. } else { /* Centering */
  1478. for (i = 12; i < 20; i++) {
  1479. switch (i) {
  1480. case H_TOTAL_SHADOW_INDEX:
  1481. reg_value =
  1482. IGA2_HOR_TOTAL_SHADOW_FORMULA
  1483. (panel_timing.hor_total);
  1484. viafb_load_reg_Num =
  1485. iga2_shadow_crtc_reg.hor_total_shadow.
  1486. reg_num;
  1487. reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
  1488. break;
  1489. case H_BLANK_END_SHADOW_INDEX:
  1490. reg_value =
  1491. IGA2_HOR_BLANK_END_SHADOW_FORMULA
  1492. (panel_timing.hor_blank_start,
  1493. panel_timing.hor_blank_end);
  1494. viafb_load_reg_Num =
  1495. iga2_shadow_crtc_reg.
  1496. hor_blank_end_shadow.reg_num;
  1497. reg =
  1498. iga2_shadow_crtc_reg.
  1499. hor_blank_end_shadow.reg;
  1500. break;
  1501. case V_TOTAL_SHADOW_INDEX:
  1502. reg_value =
  1503. IGA2_VER_TOTAL_SHADOW_FORMULA
  1504. (panel_timing.ver_total);
  1505. viafb_load_reg_Num =
  1506. iga2_shadow_crtc_reg.ver_total_shadow.
  1507. reg_num;
  1508. reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
  1509. break;
  1510. case V_ADDR_SHADOW_INDEX:
  1511. reg_value =
  1512. IGA2_VER_ADDR_SHADOW_FORMULA
  1513. (mode_timing.ver_addr);
  1514. viafb_load_reg_Num =
  1515. iga2_shadow_crtc_reg.ver_addr_shadow.
  1516. reg_num;
  1517. reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
  1518. break;
  1519. case V_BLANK_SATRT_SHADOW_INDEX:
  1520. reg_value =
  1521. IGA2_VER_BLANK_START_SHADOW_FORMULA
  1522. (mode_timing.ver_blank_start);
  1523. viafb_load_reg_Num =
  1524. iga2_shadow_crtc_reg.
  1525. ver_blank_start_shadow.reg_num;
  1526. reg =
  1527. iga2_shadow_crtc_reg.
  1528. ver_blank_start_shadow.reg;
  1529. break;
  1530. case V_BLANK_END_SHADOW_INDEX:
  1531. reg_value =
  1532. IGA2_VER_BLANK_END_SHADOW_FORMULA
  1533. (panel_timing.ver_blank_start,
  1534. panel_timing.ver_blank_end);
  1535. viafb_load_reg_Num =
  1536. iga2_shadow_crtc_reg.
  1537. ver_blank_end_shadow.reg_num;
  1538. reg =
  1539. iga2_shadow_crtc_reg.
  1540. ver_blank_end_shadow.reg;
  1541. break;
  1542. case V_SYNC_SATRT_SHADOW_INDEX:
  1543. reg_value =
  1544. IGA2_VER_SYNC_START_SHADOW_FORMULA(
  1545. (panel_timing.ver_sync_start -
  1546. panel_timing.ver_blank_start) +
  1547. (panel_timing.ver_addr -
  1548. mode_timing.ver_addr) / 2 +
  1549. mode_timing.ver_addr);
  1550. viafb_load_reg_Num =
  1551. iga2_shadow_crtc_reg.ver_sync_start_shadow.
  1552. reg_num;
  1553. reg =
  1554. iga2_shadow_crtc_reg.ver_sync_start_shadow.
  1555. reg;
  1556. break;
  1557. case V_SYNC_END_SHADOW_INDEX:
  1558. reg_value =
  1559. IGA2_VER_SYNC_END_SHADOW_FORMULA(
  1560. (panel_timing.ver_sync_start -
  1561. panel_timing.ver_blank_start) +
  1562. (panel_timing.ver_addr -
  1563. mode_timing.ver_addr) / 2 +
  1564. mode_timing.ver_addr,
  1565. panel_timing.ver_sync_end);
  1566. viafb_load_reg_Num =
  1567. iga2_shadow_crtc_reg.ver_sync_end_shadow.
  1568. reg_num;
  1569. reg =
  1570. iga2_shadow_crtc_reg.ver_sync_end_shadow.
  1571. reg;
  1572. break;
  1573. }
  1574. viafb_load_reg(reg_value,
  1575. viafb_load_reg_Num, reg, VIACR);
  1576. }
  1577. }
  1578. }
  1579. bool viafb_lcd_get_mobile_state(bool *mobile)
  1580. {
  1581. unsigned char *romptr, *tableptr;
  1582. u8 core_base;
  1583. unsigned char *biosptr;
  1584. /* Rom address */
  1585. u32 romaddr = 0x000C0000;
  1586. u16 start_pattern = 0;
  1587. biosptr = ioremap(romaddr, 0x10000);
  1588. memcpy(&start_pattern, biosptr, 2);
  1589. /* Compare pattern */
  1590. if (start_pattern == 0xAA55) {
  1591. /* Get the start of Table */
  1592. /* 0x1B means BIOS offset position */
  1593. romptr = biosptr + 0x1B;
  1594. tableptr = biosptr + *((u16 *) romptr);
  1595. /* Get the start of biosver structure */
  1596. /* 18 means BIOS version position. */
  1597. romptr = tableptr + 18;
  1598. romptr = biosptr + *((u16 *) romptr);
  1599. /* The offset should be 44, but the
  1600. actual image is less three char. */
  1601. /* pRom += 44; */
  1602. romptr += 41;
  1603. core_base = *romptr++;
  1604. if (core_base & 0x8)
  1605. *mobile = false;
  1606. else
  1607. *mobile = true;
  1608. /* release memory */
  1609. iounmap(biosptr);
  1610. return true;
  1611. } else {
  1612. iounmap(biosptr);
  1613. return false;
  1614. }
  1615. }
  1616. static void viafb_load_scaling_factor_for_p4m900(int set_hres,
  1617. int set_vres, int panel_hres, int panel_vres)
  1618. {
  1619. int h_scaling_factor;
  1620. int v_scaling_factor;
  1621. u8 cra2 = 0;
  1622. u8 cr77 = 0;
  1623. u8 cr78 = 0;
  1624. u8 cr79 = 0;
  1625. u8 cr9f = 0;
  1626. /* Check if expansion for horizontal */
  1627. if (set_hres < panel_hres) {
  1628. /* Load Horizontal Scaling Factor */
  1629. /* For VIA_K8M800 or later chipsets. */
  1630. h_scaling_factor =
  1631. K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
  1632. /* HSCaleFactor[1:0] at CR9F[1:0] */
  1633. cr9f = h_scaling_factor & 0x0003;
  1634. /* HSCaleFactor[9:2] at CR77[7:0] */
  1635. cr77 = (h_scaling_factor & 0x03FC) >> 2;
  1636. /* HSCaleFactor[11:10] at CR79[5:4] */
  1637. cr79 = (h_scaling_factor & 0x0C00) >> 10;
  1638. cr79 <<= 4;
  1639. /* Horizontal scaling enabled */
  1640. cra2 = 0xC0;
  1641. DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n",
  1642. h_scaling_factor);
  1643. } else {
  1644. /* Horizontal scaling disabled */
  1645. cra2 = 0x00;
  1646. }
  1647. /* Check if expansion for vertical */
  1648. if (set_vres < panel_vres) {
  1649. /* Load Vertical Scaling Factor */
  1650. /* For VIA_K8M800 or later chipsets. */
  1651. v_scaling_factor =
  1652. K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
  1653. /* Vertical scaling enabled */
  1654. cra2 |= 0x08;
  1655. /* VSCaleFactor[0] at CR79[3] */
  1656. cr79 |= ((v_scaling_factor & 0x0001) << 3);
  1657. /* VSCaleFactor[8:1] at CR78[7:0] */
  1658. cr78 |= (v_scaling_factor & 0x01FE) >> 1;
  1659. /* VSCaleFactor[10:9] at CR79[7:6] */
  1660. cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6;
  1661. DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n",
  1662. v_scaling_factor);
  1663. } else {
  1664. /* Vertical scaling disabled */
  1665. cra2 |= 0x00;
  1666. }
  1667. viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7);
  1668. viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF);
  1669. viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF);
  1670. viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8);
  1671. viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1);
  1672. }