lcd.c 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804
  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->shared->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->shared->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->shared->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. vmode_index = viafb_get_mode_index(set_hres, set_vres);
  552. switch (panel_id) {
  553. /* LCD 800x600 */
  554. case LCD_PANEL_ID1_800X600:
  555. switch (vmode_index) {
  556. case VIA_RES_640X400:
  557. case VIA_RES_640X480:
  558. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6;
  559. lcd_patch_reg = K400_LCD_RES_6X4_8X6;
  560. break;
  561. case VIA_RES_720X480:
  562. case VIA_RES_720X576:
  563. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6;
  564. lcd_patch_reg = K400_LCD_RES_7X4_8X6;
  565. break;
  566. }
  567. break;
  568. /* LCD 1024x768 */
  569. case LCD_PANEL_ID2_1024X768:
  570. switch (vmode_index) {
  571. case VIA_RES_640X400:
  572. case VIA_RES_640X480:
  573. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7;
  574. lcd_patch_reg = K400_LCD_RES_6X4_10X7;
  575. break;
  576. case VIA_RES_720X480:
  577. case VIA_RES_720X576:
  578. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7;
  579. lcd_patch_reg = K400_LCD_RES_7X4_10X7;
  580. break;
  581. case VIA_RES_800X600:
  582. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7;
  583. lcd_patch_reg = K400_LCD_RES_8X6_10X7;
  584. break;
  585. }
  586. break;
  587. /* LCD 1280x1024 */
  588. case LCD_PANEL_ID4_1280X1024:
  589. switch (vmode_index) {
  590. case VIA_RES_640X400:
  591. case VIA_RES_640X480:
  592. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10;
  593. lcd_patch_reg = K400_LCD_RES_6X4_12X10;
  594. break;
  595. case VIA_RES_720X480:
  596. case VIA_RES_720X576:
  597. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10;
  598. lcd_patch_reg = K400_LCD_RES_7X4_12X10;
  599. break;
  600. case VIA_RES_800X600:
  601. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10;
  602. lcd_patch_reg = K400_LCD_RES_8X6_12X10;
  603. break;
  604. case VIA_RES_1024X768:
  605. reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10;
  606. lcd_patch_reg = K400_LCD_RES_10X7_12X10;
  607. break;
  608. }
  609. break;
  610. /* LCD 1400x1050 */
  611. case LCD_PANEL_ID5_1400X1050:
  612. switch (vmode_index) {
  613. case VIA_RES_640X480:
  614. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10;
  615. lcd_patch_reg = K400_LCD_RES_6X4_14X10;
  616. break;
  617. case VIA_RES_800X600:
  618. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10;
  619. lcd_patch_reg = K400_LCD_RES_8X6_14X10;
  620. break;
  621. case VIA_RES_1024X768:
  622. reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10;
  623. lcd_patch_reg = K400_LCD_RES_10X7_14X10;
  624. break;
  625. case VIA_RES_1280X768:
  626. case VIA_RES_1280X800:
  627. case VIA_RES_1280X960:
  628. case VIA_RES_1280X1024:
  629. reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10;
  630. lcd_patch_reg = K400_LCD_RES_12X10_14X10;
  631. break;
  632. }
  633. break;
  634. /* LCD 1600x1200 */
  635. case LCD_PANEL_ID6_1600X1200:
  636. switch (vmode_index) {
  637. case VIA_RES_640X400:
  638. case VIA_RES_640X480:
  639. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12;
  640. lcd_patch_reg = K400_LCD_RES_6X4_16X12;
  641. break;
  642. case VIA_RES_720X480:
  643. case VIA_RES_720X576:
  644. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12;
  645. lcd_patch_reg = K400_LCD_RES_7X4_16X12;
  646. break;
  647. case VIA_RES_800X600:
  648. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12;
  649. lcd_patch_reg = K400_LCD_RES_8X6_16X12;
  650. break;
  651. case VIA_RES_1024X768:
  652. reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12;
  653. lcd_patch_reg = K400_LCD_RES_10X7_16X12;
  654. break;
  655. case VIA_RES_1280X768:
  656. case VIA_RES_1280X800:
  657. case VIA_RES_1280X960:
  658. case VIA_RES_1280X1024:
  659. reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12;
  660. lcd_patch_reg = K400_LCD_RES_12X10_16X12;
  661. break;
  662. }
  663. break;
  664. /* LCD 1366x768 */
  665. case LCD_PANEL_ID7_1366X768:
  666. switch (vmode_index) {
  667. case VIA_RES_640X480:
  668. reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7;
  669. lcd_patch_reg = K400_LCD_RES_6X4_1366X7;
  670. break;
  671. case VIA_RES_720X480:
  672. case VIA_RES_720X576:
  673. reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7;
  674. lcd_patch_reg = K400_LCD_RES_7X4_1366X7;
  675. break;
  676. case VIA_RES_800X600:
  677. reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7;
  678. lcd_patch_reg = K400_LCD_RES_8X6_1366X7;
  679. break;
  680. case VIA_RES_1024X768:
  681. reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7;
  682. lcd_patch_reg = K400_LCD_RES_10X7_1366X7;
  683. break;
  684. case VIA_RES_1280X768:
  685. case VIA_RES_1280X800:
  686. case VIA_RES_1280X960:
  687. case VIA_RES_1280X1024:
  688. reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7;
  689. lcd_patch_reg = K400_LCD_RES_12X10_1366X7;
  690. break;
  691. }
  692. break;
  693. /* LCD 1360x768 */
  694. case LCD_PANEL_IDB_1360X768:
  695. break;
  696. }
  697. if (reg_num != 0) {
  698. /* H.W. Reset : ON */
  699. viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
  700. viafb_write_regx(lcd_patch_reg, reg_num);
  701. /* H.W. Reset : OFF */
  702. viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
  703. /* Reset PLL */
  704. viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
  705. viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
  706. /* Fire! */
  707. outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
  708. }
  709. }
  710. static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
  711. int panel_id)
  712. {
  713. int vmode_index;
  714. int reg_num = 0;
  715. struct io_reg *lcd_patch_reg = NULL;
  716. vmode_index = viafb_get_mode_index(set_hres, set_vres);
  717. switch (panel_id) {
  718. case LCD_PANEL_ID5_1400X1050:
  719. switch (vmode_index) {
  720. case VIA_RES_640X480:
  721. reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10;
  722. lcd_patch_reg = P880_LCD_RES_6X4_14X10;
  723. break;
  724. case VIA_RES_800X600:
  725. reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10;
  726. lcd_patch_reg = P880_LCD_RES_8X6_14X10;
  727. break;
  728. }
  729. break;
  730. case LCD_PANEL_ID6_1600X1200:
  731. switch (vmode_index) {
  732. case VIA_RES_640X400:
  733. case VIA_RES_640X480:
  734. reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12;
  735. lcd_patch_reg = P880_LCD_RES_6X4_16X12;
  736. break;
  737. case VIA_RES_720X480:
  738. case VIA_RES_720X576:
  739. reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12;
  740. lcd_patch_reg = P880_LCD_RES_7X4_16X12;
  741. break;
  742. case VIA_RES_800X600:
  743. reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12;
  744. lcd_patch_reg = P880_LCD_RES_8X6_16X12;
  745. break;
  746. case VIA_RES_1024X768:
  747. reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12;
  748. lcd_patch_reg = P880_LCD_RES_10X7_16X12;
  749. break;
  750. case VIA_RES_1280X768:
  751. case VIA_RES_1280X960:
  752. case VIA_RES_1280X1024:
  753. reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12;
  754. lcd_patch_reg = P880_LCD_RES_12X10_16X12;
  755. break;
  756. }
  757. break;
  758. }
  759. if (reg_num != 0) {
  760. /* H.W. Reset : ON */
  761. viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
  762. viafb_write_regx(lcd_patch_reg, reg_num);
  763. /* H.W. Reset : OFF */
  764. viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
  765. /* Reset PLL */
  766. viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
  767. viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
  768. /* Fire! */
  769. outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
  770. }
  771. }
  772. static void load_lcd_patch_regs(int set_hres, int set_vres,
  773. int panel_id, int set_iga)
  774. {
  775. int vmode_index;
  776. vmode_index = viafb_get_mode_index(set_hres, set_vres);
  777. viafb_unlock_crt();
  778. /* Patch for simultaneous & Expansion */
  779. if ((set_iga == IGA1_IGA2) &&
  780. (viaparinfo->lvds_setting_info->display_method ==
  781. LCD_EXPANDSION)) {
  782. switch (viaparinfo->chip_info->gfx_chip_name) {
  783. case UNICHROME_CLE266:
  784. case UNICHROME_K400:
  785. load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id);
  786. break;
  787. case UNICHROME_K800:
  788. break;
  789. case UNICHROME_PM800:
  790. case UNICHROME_CN700:
  791. case UNICHROME_CX700:
  792. load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id);
  793. }
  794. }
  795. viafb_lock_crt();
  796. }
  797. static void via_pitch_alignment_patch_lcd(
  798. struct lvds_setting_information *plvds_setting_info,
  799. struct lvds_chip_information
  800. *plvds_chip_info)
  801. {
  802. unsigned char cr13, cr35, cr65, cr66, cr67;
  803. unsigned long dwScreenPitch = 0;
  804. unsigned long dwPitch;
  805. dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3);
  806. if (dwPitch & 0x1F) {
  807. dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
  808. if (plvds_setting_info->iga_path == IGA2) {
  809. if (plvds_setting_info->bpp > 8) {
  810. cr66 = (unsigned char)(dwScreenPitch & 0xFF);
  811. viafb_write_reg(CR66, VIACR, cr66);
  812. cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
  813. cr67 |=
  814. (unsigned
  815. char)((dwScreenPitch & 0x300) >> 8);
  816. viafb_write_reg(CR67, VIACR, cr67);
  817. }
  818. /* Fetch Count */
  819. cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
  820. cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
  821. viafb_write_reg(CR67, VIACR, cr67);
  822. cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
  823. cr65 += 2;
  824. viafb_write_reg(CR65, VIACR, cr65);
  825. } else {
  826. if (plvds_setting_info->bpp > 8) {
  827. cr13 = (unsigned char)(dwScreenPitch & 0xFF);
  828. viafb_write_reg(CR13, VIACR, cr13);
  829. cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
  830. cr35 |=
  831. (unsigned
  832. char)((dwScreenPitch & 0x700) >> 3);
  833. viafb_write_reg(CR35, VIACR, cr35);
  834. }
  835. }
  836. }
  837. }
  838. static void lcd_patch_skew_dvp0(struct lvds_setting_information
  839. *plvds_setting_info,
  840. struct lvds_chip_information *plvds_chip_info)
  841. {
  842. if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
  843. switch (viaparinfo->chip_info->gfx_chip_name) {
  844. case UNICHROME_P4M900:
  845. viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
  846. plvds_chip_info);
  847. break;
  848. case UNICHROME_P4M890:
  849. viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
  850. plvds_chip_info);
  851. break;
  852. }
  853. }
  854. }
  855. static void lcd_patch_skew_dvp1(struct lvds_setting_information
  856. *plvds_setting_info,
  857. struct lvds_chip_information *plvds_chip_info)
  858. {
  859. if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
  860. switch (viaparinfo->chip_info->gfx_chip_name) {
  861. case UNICHROME_CX700:
  862. viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
  863. plvds_chip_info);
  864. break;
  865. }
  866. }
  867. }
  868. static void lcd_patch_skew(struct lvds_setting_information
  869. *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
  870. {
  871. DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
  872. switch (plvds_chip_info->output_interface) {
  873. case INTERFACE_DVP0:
  874. lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
  875. break;
  876. case INTERFACE_DVP1:
  877. lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
  878. break;
  879. case INTERFACE_DFP_LOW:
  880. if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
  881. viafb_write_reg_mask(CR99, VIACR, 0x08,
  882. BIT0 + BIT1 + BIT2 + BIT3);
  883. }
  884. break;
  885. }
  886. }
  887. /* LCD Set Mode */
  888. void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
  889. struct lvds_setting_information *plvds_setting_info,
  890. struct lvds_chip_information *plvds_chip_info)
  891. {
  892. int video_index = plvds_setting_info->lcd_panel_size;
  893. int set_iga = plvds_setting_info->iga_path;
  894. int mode_bpp = plvds_setting_info->bpp;
  895. int set_hres, set_vres;
  896. int panel_hres, panel_vres;
  897. u32 pll_D_N;
  898. int offset;
  899. struct display_timing mode_crt_reg, panel_crt_reg;
  900. struct crt_mode_table *panel_crt_table = NULL;
  901. struct VideoModeTable *vmode_tbl = NULL;
  902. DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
  903. /* Get mode table */
  904. mode_crt_reg = mode_crt_table->crtc;
  905. /* Get panel table Pointer */
  906. vmode_tbl = viafb_get_modetbl_pointer(video_index);
  907. panel_crt_table = vmode_tbl->crtc;
  908. panel_crt_reg = panel_crt_table->crtc;
  909. DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
  910. set_hres = plvds_setting_info->h_active;
  911. set_vres = plvds_setting_info->v_active;
  912. panel_hres = plvds_setting_info->lcd_panel_hres;
  913. panel_vres = plvds_setting_info->lcd_panel_vres;
  914. if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
  915. viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
  916. plvds_setting_info->vclk = panel_crt_table->clk;
  917. if (set_iga == IGA1) {
  918. /* IGA1 doesn't have LCD scaling, so set it as centering. */
  919. viafb_load_crtc_timing(lcd_centering_timging
  920. (mode_crt_reg, panel_crt_reg), IGA1);
  921. } else {
  922. /* Expansion */
  923. if ((plvds_setting_info->display_method ==
  924. LCD_EXPANDSION) & ((set_hres != panel_hres)
  925. || (set_vres != panel_vres))) {
  926. /* expansion timing IGA2 loaded panel set timing*/
  927. viafb_load_crtc_timing(panel_crt_reg, IGA2);
  928. DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
  929. load_lcd_scaling(set_hres, set_vres, panel_hres,
  930. panel_vres);
  931. DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
  932. } else { /* Centering */
  933. /* centering timing IGA2 always loaded panel
  934. and mode releative timing */
  935. viafb_load_crtc_timing(lcd_centering_timging
  936. (mode_crt_reg, panel_crt_reg), IGA2);
  937. viafb_write_reg_mask(CR79, VIACR, 0x00,
  938. BIT0 + BIT1 + BIT2);
  939. /* LCD scaling disabled */
  940. }
  941. }
  942. if (set_iga == IGA1_IGA2) {
  943. load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg);
  944. /* Fill shadow registers */
  945. switch (plvds_setting_info->lcd_panel_id) {
  946. case LCD_PANEL_ID0_640X480:
  947. offset = 80;
  948. break;
  949. case LCD_PANEL_ID1_800X600:
  950. case LCD_PANEL_IDA_800X480:
  951. offset = 110;
  952. break;
  953. case LCD_PANEL_ID2_1024X768:
  954. offset = 150;
  955. break;
  956. case LCD_PANEL_ID3_1280X768:
  957. case LCD_PANEL_ID4_1280X1024:
  958. case LCD_PANEL_ID5_1400X1050:
  959. case LCD_PANEL_ID9_1280X800:
  960. offset = 190;
  961. break;
  962. case LCD_PANEL_ID6_1600X1200:
  963. offset = 250;
  964. break;
  965. case LCD_PANEL_ID7_1366X768:
  966. case LCD_PANEL_IDB_1360X768:
  967. offset = 212;
  968. break;
  969. default:
  970. offset = 140;
  971. break;
  972. }
  973. /* Offset for simultaneous */
  974. viafb_set_secondary_pitch(offset << 3);
  975. DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
  976. viafb_load_fetch_count_reg(set_hres, 4, IGA2);
  977. /* Fetch count for simultaneous */
  978. } else { /* SAMM */
  979. /* Fetch count for IGA2 only */
  980. viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
  981. if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
  982. && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
  983. viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
  984. viafb_set_color_depth(mode_bpp / 8, set_iga);
  985. }
  986. fill_lcd_format();
  987. pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
  988. DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
  989. viafb_set_vclock(pll_D_N, set_iga);
  990. viafb_set_output_path(DEVICE_LCD, set_iga,
  991. plvds_chip_info->output_interface);
  992. lcd_patch_skew(plvds_setting_info, plvds_chip_info);
  993. /* If K8M800, enable LCD Prefetch Mode. */
  994. if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
  995. || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
  996. viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
  997. load_lcd_patch_regs(set_hres, set_vres,
  998. plvds_setting_info->lcd_panel_id, set_iga);
  999. DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n");
  1000. /* Patch for non 32bit alignment mode */
  1001. via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
  1002. }
  1003. static void integrated_lvds_disable(struct lvds_setting_information
  1004. *plvds_setting_info,
  1005. struct lvds_chip_information *plvds_chip_info)
  1006. {
  1007. bool turn_off_first_powersequence = false;
  1008. bool turn_off_second_powersequence = false;
  1009. if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
  1010. turn_off_first_powersequence = true;
  1011. if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
  1012. turn_off_first_powersequence = true;
  1013. if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
  1014. turn_off_second_powersequence = true;
  1015. if (turn_off_second_powersequence) {
  1016. /* Use second power sequence control: */
  1017. /* Turn off power sequence. */
  1018. viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
  1019. /* Turn off back light. */
  1020. viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
  1021. }
  1022. if (turn_off_first_powersequence) {
  1023. /* Use first power sequence control: */
  1024. /* Turn off power sequence. */
  1025. viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
  1026. /* Turn off back light. */
  1027. viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
  1028. }
  1029. /* Turn DFP High/Low Pad off. */
  1030. viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
  1031. /* Power off LVDS channel. */
  1032. switch (plvds_chip_info->output_interface) {
  1033. case INTERFACE_LVDS0:
  1034. {
  1035. viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
  1036. break;
  1037. }
  1038. case INTERFACE_LVDS1:
  1039. {
  1040. viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
  1041. break;
  1042. }
  1043. case INTERFACE_LVDS0LVDS1:
  1044. {
  1045. viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
  1046. break;
  1047. }
  1048. }
  1049. }
  1050. static void integrated_lvds_enable(struct lvds_setting_information
  1051. *plvds_setting_info,
  1052. struct lvds_chip_information *plvds_chip_info)
  1053. {
  1054. bool turn_on_first_powersequence = false;
  1055. bool turn_on_second_powersequence = false;
  1056. DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
  1057. plvds_chip_info->output_interface);
  1058. if (plvds_setting_info->lcd_mode == LCD_SPWG)
  1059. viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
  1060. else
  1061. viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
  1062. if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
  1063. turn_on_first_powersequence = true;
  1064. if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
  1065. turn_on_first_powersequence = true;
  1066. if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
  1067. turn_on_second_powersequence = true;
  1068. if (turn_on_second_powersequence) {
  1069. /* Use second power sequence control: */
  1070. /* Use hardware control power sequence. */
  1071. viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
  1072. /* Turn on back light. */
  1073. viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
  1074. /* Turn on hardware power sequence. */
  1075. viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
  1076. }
  1077. if (turn_on_first_powersequence) {
  1078. /* Use first power sequence control: */
  1079. /* Use hardware control power sequence. */
  1080. viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
  1081. /* Turn on back light. */
  1082. viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
  1083. /* Turn on hardware power sequence. */
  1084. viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
  1085. }
  1086. /* Turn DFP High/Low pad on. */
  1087. viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
  1088. /* Power on LVDS channel. */
  1089. switch (plvds_chip_info->output_interface) {
  1090. case INTERFACE_LVDS0:
  1091. {
  1092. viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
  1093. break;
  1094. }
  1095. case INTERFACE_LVDS1:
  1096. {
  1097. viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
  1098. break;
  1099. }
  1100. case INTERFACE_LVDS0LVDS1:
  1101. {
  1102. viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
  1103. break;
  1104. }
  1105. }
  1106. }
  1107. void viafb_lcd_disable(void)
  1108. {
  1109. if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
  1110. lcd_powersequence_off();
  1111. /* DI1 pad off */
  1112. viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
  1113. } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
  1114. if (viafb_LCD2_ON
  1115. && (INTEGRATED_LVDS ==
  1116. viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
  1117. integrated_lvds_disable(viaparinfo->lvds_setting_info,
  1118. &viaparinfo->chip_info->lvds_chip_info2);
  1119. if (INTEGRATED_LVDS ==
  1120. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
  1121. integrated_lvds_disable(viaparinfo->lvds_setting_info,
  1122. &viaparinfo->chip_info->lvds_chip_info);
  1123. if (VT1636_LVDS == viaparinfo->chip_info->
  1124. lvds_chip_info.lvds_chip_name)
  1125. viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
  1126. &viaparinfo->chip_info->lvds_chip_info);
  1127. } else if (VT1636_LVDS ==
  1128. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
  1129. viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
  1130. &viaparinfo->chip_info->lvds_chip_info);
  1131. } else {
  1132. /* DFP-HL pad off */
  1133. viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
  1134. /* Backlight off */
  1135. viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
  1136. /* 24 bit DI data paht off */
  1137. viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
  1138. /* Simultaneout disabled */
  1139. viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
  1140. }
  1141. /* Disable expansion bit */
  1142. viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
  1143. /* CRT path set to IGA1 */
  1144. viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
  1145. /* Simultaneout disabled */
  1146. viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
  1147. /* IGA2 path disabled */
  1148. viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
  1149. }
  1150. void viafb_lcd_enable(void)
  1151. {
  1152. if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
  1153. /* DI1 pad on */
  1154. viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
  1155. lcd_powersequence_on();
  1156. } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
  1157. if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
  1158. viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
  1159. integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
  1160. &viaparinfo->chip_info->lvds_chip_info2);
  1161. if (INTEGRATED_LVDS ==
  1162. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
  1163. integrated_lvds_enable(viaparinfo->lvds_setting_info,
  1164. &viaparinfo->chip_info->lvds_chip_info);
  1165. if (VT1636_LVDS == viaparinfo->chip_info->
  1166. lvds_chip_info.lvds_chip_name)
  1167. viafb_enable_lvds_vt1636(viaparinfo->
  1168. lvds_setting_info, &viaparinfo->chip_info->
  1169. lvds_chip_info);
  1170. } else if (VT1636_LVDS ==
  1171. viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
  1172. viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
  1173. &viaparinfo->chip_info->lvds_chip_info);
  1174. } else {
  1175. /* DFP-HL pad on */
  1176. viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
  1177. /* Backlight on */
  1178. viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
  1179. /* 24 bit DI data paht on */
  1180. viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
  1181. /* Set data source selection bit by iga path */
  1182. if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
  1183. /* DFP-H set to IGA1 */
  1184. viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
  1185. /* DFP-L set to IGA1 */
  1186. viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
  1187. } else {
  1188. /* DFP-H set to IGA2 */
  1189. viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
  1190. /* DFP-L set to IGA2 */
  1191. viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
  1192. }
  1193. /* LCD enabled */
  1194. viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
  1195. }
  1196. if ((viaparinfo->lvds_setting_info->iga_path == IGA1)
  1197. || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) {
  1198. /* CRT path set to IGA2 */
  1199. viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
  1200. /* IGA2 path disabled */
  1201. viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
  1202. /* IGA2 path enabled */
  1203. } else { /* IGA2 */
  1204. viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
  1205. }
  1206. }
  1207. static void lcd_powersequence_off(void)
  1208. {
  1209. int i, mask, data;
  1210. /* Software control power sequence */
  1211. viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
  1212. for (i = 0; i < 3; i++) {
  1213. mask = PowerSequenceOff[0][i];
  1214. data = PowerSequenceOff[1][i] & mask;
  1215. viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
  1216. udelay(PowerSequenceOff[2][i]);
  1217. }
  1218. /* Disable LCD */
  1219. viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
  1220. }
  1221. static void lcd_powersequence_on(void)
  1222. {
  1223. int i, mask, data;
  1224. /* Software control power sequence */
  1225. viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
  1226. /* Enable LCD */
  1227. viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
  1228. for (i = 0; i < 3; i++) {
  1229. mask = PowerSequenceOn[0][i];
  1230. data = PowerSequenceOn[1][i] & mask;
  1231. viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
  1232. udelay(PowerSequenceOn[2][i]);
  1233. }
  1234. udelay(1);
  1235. }
  1236. static void fill_lcd_format(void)
  1237. {
  1238. u8 bdithering = 0, bdual = 0;
  1239. if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
  1240. bdual = BIT4;
  1241. if (viaparinfo->lvds_setting_info->LCDDithering)
  1242. bdithering = BIT0;
  1243. /* Dual & Dithering */
  1244. viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
  1245. }
  1246. static void check_diport_of_integrated_lvds(
  1247. struct lvds_chip_information *plvds_chip_info,
  1248. struct lvds_setting_information
  1249. *plvds_setting_info)
  1250. {
  1251. /* Determine LCD DI Port by hardware layout. */
  1252. switch (viafb_display_hardware_layout) {
  1253. case HW_LAYOUT_LCD_ONLY:
  1254. {
  1255. if (plvds_setting_info->device_lcd_dualedge) {
  1256. plvds_chip_info->output_interface =
  1257. INTERFACE_LVDS0LVDS1;
  1258. } else {
  1259. plvds_chip_info->output_interface =
  1260. INTERFACE_LVDS0;
  1261. }
  1262. break;
  1263. }
  1264. case HW_LAYOUT_DVI_ONLY:
  1265. {
  1266. plvds_chip_info->output_interface = INTERFACE_NONE;
  1267. break;
  1268. }
  1269. case HW_LAYOUT_LCD1_LCD2:
  1270. case HW_LAYOUT_LCD_EXTERNAL_LCD2:
  1271. {
  1272. plvds_chip_info->output_interface =
  1273. INTERFACE_LVDS0LVDS1;
  1274. break;
  1275. }
  1276. case HW_LAYOUT_LCD_DVI:
  1277. {
  1278. plvds_chip_info->output_interface = INTERFACE_LVDS1;
  1279. break;
  1280. }
  1281. default:
  1282. {
  1283. plvds_chip_info->output_interface = INTERFACE_LVDS1;
  1284. break;
  1285. }
  1286. }
  1287. DEBUG_MSG(KERN_INFO
  1288. "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
  1289. viafb_display_hardware_layout,
  1290. plvds_chip_info->output_interface);
  1291. }
  1292. void viafb_init_lvds_output_interface(struct lvds_chip_information
  1293. *plvds_chip_info,
  1294. struct lvds_setting_information
  1295. *plvds_setting_info)
  1296. {
  1297. if (INTERFACE_NONE != plvds_chip_info->output_interface) {
  1298. /*Do nothing, lcd port is specified by module parameter */
  1299. return;
  1300. }
  1301. switch (plvds_chip_info->lvds_chip_name) {
  1302. case VT1636_LVDS:
  1303. switch (viaparinfo->chip_info->gfx_chip_name) {
  1304. case UNICHROME_CX700:
  1305. plvds_chip_info->output_interface = INTERFACE_DVP1;
  1306. break;
  1307. case UNICHROME_CN700:
  1308. plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
  1309. break;
  1310. default:
  1311. plvds_chip_info->output_interface = INTERFACE_DVP0;
  1312. break;
  1313. }
  1314. break;
  1315. case INTEGRATED_LVDS:
  1316. check_diport_of_integrated_lvds(plvds_chip_info,
  1317. plvds_setting_info);
  1318. break;
  1319. default:
  1320. switch (viaparinfo->chip_info->gfx_chip_name) {
  1321. case UNICHROME_K8M890:
  1322. case UNICHROME_P4M900:
  1323. case UNICHROME_P4M890:
  1324. plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
  1325. break;
  1326. default:
  1327. plvds_chip_info->output_interface = INTERFACE_DFP;
  1328. break;
  1329. }
  1330. break;
  1331. }
  1332. }
  1333. static struct display_timing lcd_centering_timging(struct display_timing
  1334. mode_crt_reg,
  1335. struct display_timing panel_crt_reg)
  1336. {
  1337. struct display_timing crt_reg;
  1338. crt_reg.hor_total = panel_crt_reg.hor_total;
  1339. crt_reg.hor_addr = mode_crt_reg.hor_addr;
  1340. crt_reg.hor_blank_start =
  1341. (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
  1342. crt_reg.hor_addr;
  1343. crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
  1344. crt_reg.hor_sync_start =
  1345. (panel_crt_reg.hor_sync_start -
  1346. panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
  1347. crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
  1348. crt_reg.ver_total = panel_crt_reg.ver_total;
  1349. crt_reg.ver_addr = mode_crt_reg.ver_addr;
  1350. crt_reg.ver_blank_start =
  1351. (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
  1352. crt_reg.ver_addr;
  1353. crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
  1354. crt_reg.ver_sync_start =
  1355. (panel_crt_reg.ver_sync_start -
  1356. panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
  1357. crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
  1358. return crt_reg;
  1359. }
  1360. static void load_crtc_shadow_timing(struct display_timing mode_timing,
  1361. struct display_timing panel_timing)
  1362. {
  1363. struct io_register *reg = NULL;
  1364. int i;
  1365. int viafb_load_reg_Num = 0;
  1366. int reg_value = 0;
  1367. if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) {
  1368. /* Expansion */
  1369. for (i = 12; i < 20; i++) {
  1370. switch (i) {
  1371. case H_TOTAL_SHADOW_INDEX:
  1372. reg_value =
  1373. IGA2_HOR_TOTAL_SHADOW_FORMULA
  1374. (panel_timing.hor_total);
  1375. viafb_load_reg_Num =
  1376. iga2_shadow_crtc_reg.hor_total_shadow.
  1377. reg_num;
  1378. reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
  1379. break;
  1380. case H_BLANK_END_SHADOW_INDEX:
  1381. reg_value =
  1382. IGA2_HOR_BLANK_END_SHADOW_FORMULA
  1383. (panel_timing.hor_blank_start,
  1384. panel_timing.hor_blank_end);
  1385. viafb_load_reg_Num =
  1386. iga2_shadow_crtc_reg.
  1387. hor_blank_end_shadow.reg_num;
  1388. reg =
  1389. iga2_shadow_crtc_reg.
  1390. hor_blank_end_shadow.reg;
  1391. break;
  1392. case V_TOTAL_SHADOW_INDEX:
  1393. reg_value =
  1394. IGA2_VER_TOTAL_SHADOW_FORMULA
  1395. (panel_timing.ver_total);
  1396. viafb_load_reg_Num =
  1397. iga2_shadow_crtc_reg.ver_total_shadow.
  1398. reg_num;
  1399. reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
  1400. break;
  1401. case V_ADDR_SHADOW_INDEX:
  1402. reg_value =
  1403. IGA2_VER_ADDR_SHADOW_FORMULA
  1404. (panel_timing.ver_addr);
  1405. viafb_load_reg_Num =
  1406. iga2_shadow_crtc_reg.ver_addr_shadow.
  1407. reg_num;
  1408. reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
  1409. break;
  1410. case V_BLANK_SATRT_SHADOW_INDEX:
  1411. reg_value =
  1412. IGA2_VER_BLANK_START_SHADOW_FORMULA
  1413. (panel_timing.ver_blank_start);
  1414. viafb_load_reg_Num =
  1415. iga2_shadow_crtc_reg.
  1416. ver_blank_start_shadow.reg_num;
  1417. reg =
  1418. iga2_shadow_crtc_reg.
  1419. ver_blank_start_shadow.reg;
  1420. break;
  1421. case V_BLANK_END_SHADOW_INDEX:
  1422. reg_value =
  1423. IGA2_VER_BLANK_END_SHADOW_FORMULA
  1424. (panel_timing.ver_blank_start,
  1425. panel_timing.ver_blank_end);
  1426. viafb_load_reg_Num =
  1427. iga2_shadow_crtc_reg.
  1428. ver_blank_end_shadow.reg_num;
  1429. reg =
  1430. iga2_shadow_crtc_reg.
  1431. ver_blank_end_shadow.reg;
  1432. break;
  1433. case V_SYNC_SATRT_SHADOW_INDEX:
  1434. reg_value =
  1435. IGA2_VER_SYNC_START_SHADOW_FORMULA
  1436. (panel_timing.ver_sync_start);
  1437. viafb_load_reg_Num =
  1438. iga2_shadow_crtc_reg.
  1439. ver_sync_start_shadow.reg_num;
  1440. reg =
  1441. iga2_shadow_crtc_reg.
  1442. ver_sync_start_shadow.reg;
  1443. break;
  1444. case V_SYNC_END_SHADOW_INDEX:
  1445. reg_value =
  1446. IGA2_VER_SYNC_END_SHADOW_FORMULA
  1447. (panel_timing.ver_sync_start,
  1448. panel_timing.ver_sync_end);
  1449. viafb_load_reg_Num =
  1450. iga2_shadow_crtc_reg.
  1451. ver_sync_end_shadow.reg_num;
  1452. reg =
  1453. iga2_shadow_crtc_reg.
  1454. ver_sync_end_shadow.reg;
  1455. break;
  1456. }
  1457. viafb_load_reg(reg_value,
  1458. viafb_load_reg_Num, reg, VIACR);
  1459. }
  1460. } else { /* Centering */
  1461. for (i = 12; i < 20; i++) {
  1462. switch (i) {
  1463. case H_TOTAL_SHADOW_INDEX:
  1464. reg_value =
  1465. IGA2_HOR_TOTAL_SHADOW_FORMULA
  1466. (panel_timing.hor_total);
  1467. viafb_load_reg_Num =
  1468. iga2_shadow_crtc_reg.hor_total_shadow.
  1469. reg_num;
  1470. reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
  1471. break;
  1472. case H_BLANK_END_SHADOW_INDEX:
  1473. reg_value =
  1474. IGA2_HOR_BLANK_END_SHADOW_FORMULA
  1475. (panel_timing.hor_blank_start,
  1476. panel_timing.hor_blank_end);
  1477. viafb_load_reg_Num =
  1478. iga2_shadow_crtc_reg.
  1479. hor_blank_end_shadow.reg_num;
  1480. reg =
  1481. iga2_shadow_crtc_reg.
  1482. hor_blank_end_shadow.reg;
  1483. break;
  1484. case V_TOTAL_SHADOW_INDEX:
  1485. reg_value =
  1486. IGA2_VER_TOTAL_SHADOW_FORMULA
  1487. (panel_timing.ver_total);
  1488. viafb_load_reg_Num =
  1489. iga2_shadow_crtc_reg.ver_total_shadow.
  1490. reg_num;
  1491. reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
  1492. break;
  1493. case V_ADDR_SHADOW_INDEX:
  1494. reg_value =
  1495. IGA2_VER_ADDR_SHADOW_FORMULA
  1496. (mode_timing.ver_addr);
  1497. viafb_load_reg_Num =
  1498. iga2_shadow_crtc_reg.ver_addr_shadow.
  1499. reg_num;
  1500. reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
  1501. break;
  1502. case V_BLANK_SATRT_SHADOW_INDEX:
  1503. reg_value =
  1504. IGA2_VER_BLANK_START_SHADOW_FORMULA
  1505. (mode_timing.ver_blank_start);
  1506. viafb_load_reg_Num =
  1507. iga2_shadow_crtc_reg.
  1508. ver_blank_start_shadow.reg_num;
  1509. reg =
  1510. iga2_shadow_crtc_reg.
  1511. ver_blank_start_shadow.reg;
  1512. break;
  1513. case V_BLANK_END_SHADOW_INDEX:
  1514. reg_value =
  1515. IGA2_VER_BLANK_END_SHADOW_FORMULA
  1516. (panel_timing.ver_blank_start,
  1517. panel_timing.ver_blank_end);
  1518. viafb_load_reg_Num =
  1519. iga2_shadow_crtc_reg.
  1520. ver_blank_end_shadow.reg_num;
  1521. reg =
  1522. iga2_shadow_crtc_reg.
  1523. ver_blank_end_shadow.reg;
  1524. break;
  1525. case V_SYNC_SATRT_SHADOW_INDEX:
  1526. reg_value =
  1527. IGA2_VER_SYNC_START_SHADOW_FORMULA(
  1528. (panel_timing.ver_sync_start -
  1529. panel_timing.ver_blank_start) +
  1530. (panel_timing.ver_addr -
  1531. mode_timing.ver_addr) / 2 +
  1532. mode_timing.ver_addr);
  1533. viafb_load_reg_Num =
  1534. iga2_shadow_crtc_reg.ver_sync_start_shadow.
  1535. reg_num;
  1536. reg =
  1537. iga2_shadow_crtc_reg.ver_sync_start_shadow.
  1538. reg;
  1539. break;
  1540. case V_SYNC_END_SHADOW_INDEX:
  1541. reg_value =
  1542. IGA2_VER_SYNC_END_SHADOW_FORMULA(
  1543. (panel_timing.ver_sync_start -
  1544. panel_timing.ver_blank_start) +
  1545. (panel_timing.ver_addr -
  1546. mode_timing.ver_addr) / 2 +
  1547. mode_timing.ver_addr,
  1548. panel_timing.ver_sync_end);
  1549. viafb_load_reg_Num =
  1550. iga2_shadow_crtc_reg.ver_sync_end_shadow.
  1551. reg_num;
  1552. reg =
  1553. iga2_shadow_crtc_reg.ver_sync_end_shadow.
  1554. reg;
  1555. break;
  1556. }
  1557. viafb_load_reg(reg_value,
  1558. viafb_load_reg_Num, reg, VIACR);
  1559. }
  1560. }
  1561. }
  1562. bool viafb_lcd_get_mobile_state(bool *mobile)
  1563. {
  1564. unsigned char *romptr, *tableptr;
  1565. u8 core_base;
  1566. unsigned char *biosptr;
  1567. /* Rom address */
  1568. u32 romaddr = 0x000C0000;
  1569. u16 start_pattern = 0;
  1570. biosptr = ioremap(romaddr, 0x10000);
  1571. memcpy(&start_pattern, biosptr, 2);
  1572. /* Compare pattern */
  1573. if (start_pattern == 0xAA55) {
  1574. /* Get the start of Table */
  1575. /* 0x1B means BIOS offset position */
  1576. romptr = biosptr + 0x1B;
  1577. tableptr = biosptr + *((u16 *) romptr);
  1578. /* Get the start of biosver structure */
  1579. /* 18 means BIOS version position. */
  1580. romptr = tableptr + 18;
  1581. romptr = biosptr + *((u16 *) romptr);
  1582. /* The offset should be 44, but the
  1583. actual image is less three char. */
  1584. /* pRom += 44; */
  1585. romptr += 41;
  1586. core_base = *romptr++;
  1587. if (core_base & 0x8)
  1588. *mobile = false;
  1589. else
  1590. *mobile = true;
  1591. /* release memory */
  1592. iounmap(biosptr);
  1593. return true;
  1594. } else {
  1595. iounmap(biosptr);
  1596. return false;
  1597. }
  1598. }
  1599. static void viafb_load_scaling_factor_for_p4m900(int set_hres,
  1600. int set_vres, int panel_hres, int panel_vres)
  1601. {
  1602. int h_scaling_factor;
  1603. int v_scaling_factor;
  1604. u8 cra2 = 0;
  1605. u8 cr77 = 0;
  1606. u8 cr78 = 0;
  1607. u8 cr79 = 0;
  1608. u8 cr9f = 0;
  1609. /* Check if expansion for horizontal */
  1610. if (set_hres < panel_hres) {
  1611. /* Load Horizontal Scaling Factor */
  1612. /* For VIA_K8M800 or later chipsets. */
  1613. h_scaling_factor =
  1614. K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
  1615. /* HSCaleFactor[1:0] at CR9F[1:0] */
  1616. cr9f = h_scaling_factor & 0x0003;
  1617. /* HSCaleFactor[9:2] at CR77[7:0] */
  1618. cr77 = (h_scaling_factor & 0x03FC) >> 2;
  1619. /* HSCaleFactor[11:10] at CR79[5:4] */
  1620. cr79 = (h_scaling_factor & 0x0C00) >> 10;
  1621. cr79 <<= 4;
  1622. /* Horizontal scaling enabled */
  1623. cra2 = 0xC0;
  1624. DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n",
  1625. h_scaling_factor);
  1626. } else {
  1627. /* Horizontal scaling disabled */
  1628. cra2 = 0x00;
  1629. }
  1630. /* Check if expansion for vertical */
  1631. if (set_vres < panel_vres) {
  1632. /* Load Vertical Scaling Factor */
  1633. /* For VIA_K8M800 or later chipsets. */
  1634. v_scaling_factor =
  1635. K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
  1636. /* Vertical scaling enabled */
  1637. cra2 |= 0x08;
  1638. /* VSCaleFactor[0] at CR79[3] */
  1639. cr79 |= ((v_scaling_factor & 0x0001) << 3);
  1640. /* VSCaleFactor[8:1] at CR78[7:0] */
  1641. cr78 |= (v_scaling_factor & 0x01FE) >> 1;
  1642. /* VSCaleFactor[10:9] at CR79[7:6] */
  1643. cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6;
  1644. DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n",
  1645. v_scaling_factor);
  1646. } else {
  1647. /* Vertical scaling disabled */
  1648. cra2 |= 0x00;
  1649. }
  1650. viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7);
  1651. viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF);
  1652. viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF);
  1653. viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8);
  1654. viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1);
  1655. }