intelfbhw.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776
  1. /*
  2. * intelfb
  3. *
  4. * Linux framebuffer driver for Intel(R) 865G integrated graphics chips.
  5. *
  6. * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
  7. * 2004 Sylvain Meyer
  8. *
  9. * This driver consists of two parts. The first part (intelfbdrv.c) provides
  10. * the basic fbdev interfaces, is derived in part from the radeonfb and
  11. * vesafb drivers, and is covered by the GPL. The second part (intelfbhw.c)
  12. * provides the code to program the hardware. Most of it is derived from
  13. * the i810/i830 XFree86 driver. The HW-specific code is covered here
  14. * under a dual license (GPL and MIT/XFree86 license).
  15. *
  16. * Author: David Dawes
  17. *
  18. */
  19. /* $DHD: intelfb/intelfbhw.c,v 1.9 2003/06/27 15:06:25 dawes Exp $ */
  20. #include <linux/config.h>
  21. #include <linux/module.h>
  22. #include <linux/kernel.h>
  23. #include <linux/errno.h>
  24. #include <linux/string.h>
  25. #include <linux/mm.h>
  26. #include <linux/tty.h>
  27. #include <linux/slab.h>
  28. #include <linux/delay.h>
  29. #include <linux/fb.h>
  30. #include <linux/ioport.h>
  31. #include <linux/init.h>
  32. #include <linux/pci.h>
  33. #include <linux/vmalloc.h>
  34. #include <linux/pagemap.h>
  35. #include <linux/version.h>
  36. #include <asm/io.h>
  37. #include "intelfb.h"
  38. #include "intelfbhw.h"
  39. int
  40. intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset,
  41. int *mobile)
  42. {
  43. u32 tmp;
  44. if (!pdev || !name || !chipset || !mobile)
  45. return 1;
  46. switch (pdev->device) {
  47. case PCI_DEVICE_ID_INTEL_830M:
  48. *name = "Intel(R) 830M";
  49. *chipset = INTEL_830M;
  50. *mobile = 1;
  51. return 0;
  52. case PCI_DEVICE_ID_INTEL_845G:
  53. *name = "Intel(R) 845G";
  54. *chipset = INTEL_845G;
  55. *mobile = 0;
  56. return 0;
  57. case PCI_DEVICE_ID_INTEL_85XGM:
  58. tmp = 0;
  59. *mobile = 1;
  60. pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
  61. switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
  62. INTEL_85X_VARIANT_MASK) {
  63. case INTEL_VAR_855GME:
  64. *name = "Intel(R) 855GME";
  65. *chipset = INTEL_855GME;
  66. return 0;
  67. case INTEL_VAR_855GM:
  68. *name = "Intel(R) 855GM";
  69. *chipset = INTEL_855GM;
  70. return 0;
  71. case INTEL_VAR_852GME:
  72. *name = "Intel(R) 852GME";
  73. *chipset = INTEL_852GME;
  74. return 0;
  75. case INTEL_VAR_852GM:
  76. *name = "Intel(R) 852GM";
  77. *chipset = INTEL_852GM;
  78. return 0;
  79. default:
  80. *name = "Intel(R) 852GM/855GM";
  81. *chipset = INTEL_85XGM;
  82. return 0;
  83. }
  84. break;
  85. case PCI_DEVICE_ID_INTEL_865G:
  86. *name = "Intel(R) 865G";
  87. *chipset = INTEL_865G;
  88. *mobile = 0;
  89. return 0;
  90. case PCI_DEVICE_ID_INTEL_915G:
  91. *name = "Intel(R) 915G";
  92. *chipset = INTEL_915G;
  93. *mobile = 0;
  94. return 0;
  95. default:
  96. return 1;
  97. }
  98. }
  99. int
  100. intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
  101. int *stolen_size)
  102. {
  103. struct pci_dev *bridge_dev;
  104. u16 tmp;
  105. if (!pdev || !aperture_size || !stolen_size)
  106. return 1;
  107. /* Find the bridge device. It is always 0:0.0 */
  108. if (!(bridge_dev = pci_find_slot(0, PCI_DEVFN(0, 0)))) {
  109. ERR_MSG("cannot find bridge device\n");
  110. return 1;
  111. }
  112. /* Get the fb aperture size and "stolen" memory amount. */
  113. tmp = 0;
  114. pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
  115. switch (pdev->device) {
  116. case PCI_DEVICE_ID_INTEL_830M:
  117. case PCI_DEVICE_ID_INTEL_845G:
  118. if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
  119. *aperture_size = MB(64);
  120. else
  121. *aperture_size = MB(128);
  122. switch (tmp & INTEL_830_GMCH_GMS_MASK) {
  123. case INTEL_830_GMCH_GMS_STOLEN_512:
  124. *stolen_size = KB(512) - KB(132);
  125. return 0;
  126. case INTEL_830_GMCH_GMS_STOLEN_1024:
  127. *stolen_size = MB(1) - KB(132);
  128. return 0;
  129. case INTEL_830_GMCH_GMS_STOLEN_8192:
  130. *stolen_size = MB(8) - KB(132);
  131. return 0;
  132. case INTEL_830_GMCH_GMS_LOCAL:
  133. ERR_MSG("only local memory found\n");
  134. return 1;
  135. case INTEL_830_GMCH_GMS_DISABLED:
  136. ERR_MSG("video memory is disabled\n");
  137. return 1;
  138. default:
  139. ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
  140. tmp & INTEL_830_GMCH_GMS_MASK);
  141. return 1;
  142. }
  143. break;
  144. default:
  145. *aperture_size = MB(128);
  146. switch (tmp & INTEL_855_GMCH_GMS_MASK) {
  147. case INTEL_855_GMCH_GMS_STOLEN_1M:
  148. *stolen_size = MB(1) - KB(132);
  149. return 0;
  150. case INTEL_855_GMCH_GMS_STOLEN_4M:
  151. *stolen_size = MB(4) - KB(132);
  152. return 0;
  153. case INTEL_855_GMCH_GMS_STOLEN_8M:
  154. *stolen_size = MB(8) - KB(132);
  155. return 0;
  156. case INTEL_855_GMCH_GMS_STOLEN_16M:
  157. *stolen_size = MB(16) - KB(132);
  158. return 0;
  159. case INTEL_855_GMCH_GMS_STOLEN_32M:
  160. *stolen_size = MB(32) - KB(132);
  161. return 0;
  162. case INTEL_915G_GMCH_GMS_STOLEN_48M:
  163. *stolen_size = MB(48) - KB(132);
  164. return 0;
  165. case INTEL_915G_GMCH_GMS_STOLEN_64M:
  166. *stolen_size = MB(64) - KB(132);
  167. return 0;
  168. case INTEL_855_GMCH_GMS_DISABLED:
  169. ERR_MSG("video memory is disabled\n");
  170. return 0;
  171. default:
  172. ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
  173. tmp & INTEL_855_GMCH_GMS_MASK);
  174. return 1;
  175. }
  176. }
  177. }
  178. int
  179. intelfbhw_check_non_crt(struct intelfb_info *dinfo)
  180. {
  181. int dvo = 0;
  182. if (INREG(LVDS) & PORT_ENABLE)
  183. dvo |= LVDS_PORT;
  184. if (INREG(DVOA) & PORT_ENABLE)
  185. dvo |= DVOA_PORT;
  186. if (INREG(DVOB) & PORT_ENABLE)
  187. dvo |= DVOB_PORT;
  188. if (INREG(DVOC) & PORT_ENABLE)
  189. dvo |= DVOC_PORT;
  190. return dvo;
  191. }
  192. const char *
  193. intelfbhw_dvo_to_string(int dvo)
  194. {
  195. if (dvo & DVOA_PORT)
  196. return "DVO port A";
  197. else if (dvo & DVOB_PORT)
  198. return "DVO port B";
  199. else if (dvo & DVOC_PORT)
  200. return "DVO port C";
  201. else if (dvo & LVDS_PORT)
  202. return "LVDS port";
  203. else
  204. return NULL;
  205. }
  206. int
  207. intelfbhw_validate_mode(struct intelfb_info *dinfo,
  208. struct fb_var_screeninfo *var)
  209. {
  210. int bytes_per_pixel;
  211. int tmp;
  212. #if VERBOSE > 0
  213. DBG_MSG("intelfbhw_validate_mode\n");
  214. #endif
  215. bytes_per_pixel = var->bits_per_pixel / 8;
  216. if (bytes_per_pixel == 3)
  217. bytes_per_pixel = 4;
  218. /* Check if enough video memory. */
  219. tmp = var->yres_virtual * var->xres_virtual * bytes_per_pixel;
  220. if (tmp > dinfo->fb.size) {
  221. WRN_MSG("Not enough video ram for mode "
  222. "(%d KByte vs %d KByte).\n",
  223. BtoKB(tmp), BtoKB(dinfo->fb.size));
  224. return 1;
  225. }
  226. /* Check if x/y limits are OK. */
  227. if (var->xres - 1 > HACTIVE_MASK) {
  228. WRN_MSG("X resolution too large (%d vs %d).\n",
  229. var->xres, HACTIVE_MASK + 1);
  230. return 1;
  231. }
  232. if (var->yres - 1 > VACTIVE_MASK) {
  233. WRN_MSG("Y resolution too large (%d vs %d).\n",
  234. var->yres, VACTIVE_MASK + 1);
  235. return 1;
  236. }
  237. /* Check for interlaced/doublescan modes. */
  238. if (var->vmode & FB_VMODE_INTERLACED) {
  239. WRN_MSG("Mode is interlaced.\n");
  240. return 1;
  241. }
  242. if (var->vmode & FB_VMODE_DOUBLE) {
  243. WRN_MSG("Mode is double-scan.\n");
  244. return 1;
  245. }
  246. /* Check if clock is OK. */
  247. tmp = 1000000000 / var->pixclock;
  248. if (tmp < MIN_CLOCK) {
  249. WRN_MSG("Pixel clock is too low (%d MHz vs %d MHz).\n",
  250. (tmp + 500) / 1000, MIN_CLOCK / 1000);
  251. return 1;
  252. }
  253. if (tmp > MAX_CLOCK) {
  254. WRN_MSG("Pixel clock is too high (%d MHz vs %d MHz).\n",
  255. (tmp + 500) / 1000, MAX_CLOCK / 1000);
  256. return 1;
  257. }
  258. return 0;
  259. }
  260. int
  261. intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
  262. {
  263. struct intelfb_info *dinfo = GET_DINFO(info);
  264. u32 offset, xoffset, yoffset;
  265. #if VERBOSE > 0
  266. DBG_MSG("intelfbhw_pan_display\n");
  267. #endif
  268. xoffset = ROUND_DOWN_TO(var->xoffset, 8);
  269. yoffset = var->yoffset;
  270. if ((xoffset + var->xres > var->xres_virtual) ||
  271. (yoffset + var->yres > var->yres_virtual))
  272. return -EINVAL;
  273. offset = (yoffset * dinfo->pitch) +
  274. (xoffset * var->bits_per_pixel) / 8;
  275. offset += dinfo->fb.offset << 12;
  276. OUTREG(DSPABASE, offset);
  277. return 0;
  278. }
  279. /* Blank the screen. */
  280. void
  281. intelfbhw_do_blank(int blank, struct fb_info *info)
  282. {
  283. struct intelfb_info *dinfo = GET_DINFO(info);
  284. u32 tmp;
  285. #if VERBOSE > 0
  286. DBG_MSG("intelfbhw_do_blank: blank is %d\n", blank);
  287. #endif
  288. /* Turn plane A on or off */
  289. tmp = INREG(DSPACNTR);
  290. if (blank)
  291. tmp &= ~DISPPLANE_PLANE_ENABLE;
  292. else
  293. tmp |= DISPPLANE_PLANE_ENABLE;
  294. OUTREG(DSPACNTR, tmp);
  295. /* Flush */
  296. tmp = INREG(DSPABASE);
  297. OUTREG(DSPABASE, tmp);
  298. /* Turn off/on the HW cursor */
  299. #if VERBOSE > 0
  300. DBG_MSG("cursor_on is %d\n", dinfo->cursor_on);
  301. #endif
  302. if (dinfo->cursor_on) {
  303. if (blank) {
  304. intelfbhw_cursor_hide(dinfo);
  305. } else {
  306. intelfbhw_cursor_show(dinfo);
  307. }
  308. dinfo->cursor_on = 1;
  309. }
  310. dinfo->cursor_blanked = blank;
  311. /* Set DPMS level */
  312. tmp = INREG(ADPA) & ~ADPA_DPMS_CONTROL_MASK;
  313. switch (blank) {
  314. case FB_BLANK_UNBLANK:
  315. case FB_BLANK_NORMAL:
  316. tmp |= ADPA_DPMS_D0;
  317. break;
  318. case FB_BLANK_VSYNC_SUSPEND:
  319. tmp |= ADPA_DPMS_D1;
  320. break;
  321. case FB_BLANK_HSYNC_SUSPEND:
  322. tmp |= ADPA_DPMS_D2;
  323. break;
  324. case FB_BLANK_POWERDOWN:
  325. tmp |= ADPA_DPMS_D3;
  326. break;
  327. }
  328. OUTREG(ADPA, tmp);
  329. return;
  330. }
  331. void
  332. intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
  333. unsigned red, unsigned green, unsigned blue,
  334. unsigned transp)
  335. {
  336. #if VERBOSE > 0
  337. DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",
  338. regno, red, green, blue);
  339. #endif
  340. u32 palette_reg = (dinfo->pipe == PIPE_A) ?
  341. PALETTE_A : PALETTE_B;
  342. OUTREG(palette_reg + (regno << 2),
  343. (red << PALETTE_8_RED_SHIFT) |
  344. (green << PALETTE_8_GREEN_SHIFT) |
  345. (blue << PALETTE_8_BLUE_SHIFT));
  346. }
  347. int
  348. intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
  349. int flag)
  350. {
  351. int i;
  352. #if VERBOSE > 0
  353. DBG_MSG("intelfbhw_read_hw_state\n");
  354. #endif
  355. if (!hw || !dinfo)
  356. return -1;
  357. /* Read in as much of the HW state as possible. */
  358. hw->vga0_divisor = INREG(VGA0_DIVISOR);
  359. hw->vga1_divisor = INREG(VGA1_DIVISOR);
  360. hw->vga_pd = INREG(VGAPD);
  361. hw->dpll_a = INREG(DPLL_A);
  362. hw->dpll_b = INREG(DPLL_B);
  363. hw->fpa0 = INREG(FPA0);
  364. hw->fpa1 = INREG(FPA1);
  365. hw->fpb0 = INREG(FPB0);
  366. hw->fpb1 = INREG(FPB1);
  367. if (flag == 1)
  368. return flag;
  369. #if 0
  370. /* This seems to be a problem with the 852GM/855GM */
  371. for (i = 0; i < PALETTE_8_ENTRIES; i++) {
  372. hw->palette_a[i] = INREG(PALETTE_A + (i << 2));
  373. hw->palette_b[i] = INREG(PALETTE_B + (i << 2));
  374. }
  375. #endif
  376. if (flag == 2)
  377. return flag;
  378. hw->htotal_a = INREG(HTOTAL_A);
  379. hw->hblank_a = INREG(HBLANK_A);
  380. hw->hsync_a = INREG(HSYNC_A);
  381. hw->vtotal_a = INREG(VTOTAL_A);
  382. hw->vblank_a = INREG(VBLANK_A);
  383. hw->vsync_a = INREG(VSYNC_A);
  384. hw->src_size_a = INREG(SRC_SIZE_A);
  385. hw->bclrpat_a = INREG(BCLRPAT_A);
  386. hw->htotal_b = INREG(HTOTAL_B);
  387. hw->hblank_b = INREG(HBLANK_B);
  388. hw->hsync_b = INREG(HSYNC_B);
  389. hw->vtotal_b = INREG(VTOTAL_B);
  390. hw->vblank_b = INREG(VBLANK_B);
  391. hw->vsync_b = INREG(VSYNC_B);
  392. hw->src_size_b = INREG(SRC_SIZE_B);
  393. hw->bclrpat_b = INREG(BCLRPAT_B);
  394. if (flag == 3)
  395. return flag;
  396. hw->adpa = INREG(ADPA);
  397. hw->dvoa = INREG(DVOA);
  398. hw->dvob = INREG(DVOB);
  399. hw->dvoc = INREG(DVOC);
  400. hw->dvoa_srcdim = INREG(DVOA_SRCDIM);
  401. hw->dvob_srcdim = INREG(DVOB_SRCDIM);
  402. hw->dvoc_srcdim = INREG(DVOC_SRCDIM);
  403. hw->lvds = INREG(LVDS);
  404. if (flag == 4)
  405. return flag;
  406. hw->pipe_a_conf = INREG(PIPEACONF);
  407. hw->pipe_b_conf = INREG(PIPEBCONF);
  408. hw->disp_arb = INREG(DISPARB);
  409. if (flag == 5)
  410. return flag;
  411. hw->cursor_a_control = INREG(CURSOR_A_CONTROL);
  412. hw->cursor_b_control = INREG(CURSOR_B_CONTROL);
  413. hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);
  414. hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);
  415. if (flag == 6)
  416. return flag;
  417. for (i = 0; i < 4; i++) {
  418. hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));
  419. hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));
  420. }
  421. if (flag == 7)
  422. return flag;
  423. hw->cursor_size = INREG(CURSOR_SIZE);
  424. if (flag == 8)
  425. return flag;
  426. hw->disp_a_ctrl = INREG(DSPACNTR);
  427. hw->disp_b_ctrl = INREG(DSPBCNTR);
  428. hw->disp_a_base = INREG(DSPABASE);
  429. hw->disp_b_base = INREG(DSPBBASE);
  430. hw->disp_a_stride = INREG(DSPASTRIDE);
  431. hw->disp_b_stride = INREG(DSPBSTRIDE);
  432. if (flag == 9)
  433. return flag;
  434. hw->vgacntrl = INREG(VGACNTRL);
  435. if (flag == 10)
  436. return flag;
  437. hw->add_id = INREG(ADD_ID);
  438. if (flag == 11)
  439. return flag;
  440. for (i = 0; i < 7; i++) {
  441. hw->swf0x[i] = INREG(SWF00 + (i << 2));
  442. hw->swf1x[i] = INREG(SWF10 + (i << 2));
  443. if (i < 3)
  444. hw->swf3x[i] = INREG(SWF30 + (i << 2));
  445. }
  446. for (i = 0; i < 8; i++)
  447. hw->fence[i] = INREG(FENCE + (i << 2));
  448. hw->instpm = INREG(INSTPM);
  449. hw->mem_mode = INREG(MEM_MODE);
  450. hw->fw_blc_0 = INREG(FW_BLC_0);
  451. hw->fw_blc_1 = INREG(FW_BLC_1);
  452. return 0;
  453. }
  454. void
  455. intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
  456. {
  457. #if REGDUMP
  458. int i, m1, m2, n, p1, p2;
  459. DBG_MSG("intelfbhw_print_hw_state\n");
  460. if (!hw || !dinfo)
  461. return;
  462. /* Read in as much of the HW state as possible. */
  463. printk("hw state dump start\n");
  464. printk(" VGA0_DIVISOR: 0x%08x\n", hw->vga0_divisor);
  465. printk(" VGA1_DIVISOR: 0x%08x\n", hw->vga1_divisor);
  466. printk(" VGAPD: 0x%08x\n", hw->vga_pd);
  467. n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  468. m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  469. m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  470. if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2)
  471. p1 = 0;
  472. else
  473. p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK;
  474. p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK;
  475. printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
  476. m1, m2, n, p1, p2);
  477. printk(" VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
  478. n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  479. m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  480. m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  481. if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2)
  482. p1 = 0;
  483. else
  484. p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK;
  485. p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK;
  486. printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
  487. m1, m2, n, p1, p2);
  488. printk(" VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
  489. printk(" DPLL_A: 0x%08x\n", hw->dpll_a);
  490. printk(" DPLL_B: 0x%08x\n", hw->dpll_b);
  491. printk(" FPA0: 0x%08x\n", hw->fpa0);
  492. printk(" FPA1: 0x%08x\n", hw->fpa1);
  493. printk(" FPB0: 0x%08x\n", hw->fpb0);
  494. printk(" FPB1: 0x%08x\n", hw->fpb1);
  495. n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  496. m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  497. m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  498. if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
  499. p1 = 0;
  500. else
  501. p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
  502. p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
  503. printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
  504. m1, m2, n, p1, p2);
  505. printk(" PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
  506. n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  507. m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  508. m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
  509. if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
  510. p1 = 0;
  511. else
  512. p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
  513. p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
  514. printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
  515. m1, m2, n, p1, p2);
  516. printk(" PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
  517. #if 0
  518. printk(" PALETTE_A:\n");
  519. for (i = 0; i < PALETTE_8_ENTRIES)
  520. printk(" %3d: 0x%08x\n", i, hw->palette_a[i];
  521. printk(" PALETTE_B:\n");
  522. for (i = 0; i < PALETTE_8_ENTRIES)
  523. printk(" %3d: 0x%08x\n", i, hw->palette_b[i];
  524. #endif
  525. printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a);
  526. printk(" HBLANK_A: 0x%08x\n", hw->hblank_a);
  527. printk(" HSYNC_A: 0x%08x\n", hw->hsync_a);
  528. printk(" VTOTAL_A: 0x%08x\n", hw->vtotal_a);
  529. printk(" VBLANK_A: 0x%08x\n", hw->vblank_a);
  530. printk(" VSYNC_A: 0x%08x\n", hw->vsync_a);
  531. printk(" SRC_SIZE_A: 0x%08x\n", hw->src_size_a);
  532. printk(" BCLRPAT_A: 0x%08x\n", hw->bclrpat_a);
  533. printk(" HTOTAL_B: 0x%08x\n", hw->htotal_b);
  534. printk(" HBLANK_B: 0x%08x\n", hw->hblank_b);
  535. printk(" HSYNC_B: 0x%08x\n", hw->hsync_b);
  536. printk(" VTOTAL_B: 0x%08x\n", hw->vtotal_b);
  537. printk(" VBLANK_B: 0x%08x\n", hw->vblank_b);
  538. printk(" VSYNC_B: 0x%08x\n", hw->vsync_b);
  539. printk(" SRC_SIZE_B: 0x%08x\n", hw->src_size_b);
  540. printk(" BCLRPAT_B: 0x%08x\n", hw->bclrpat_b);
  541. printk(" ADPA: 0x%08x\n", hw->adpa);
  542. printk(" DVOA: 0x%08x\n", hw->dvoa);
  543. printk(" DVOB: 0x%08x\n", hw->dvob);
  544. printk(" DVOC: 0x%08x\n", hw->dvoc);
  545. printk(" DVOA_SRCDIM: 0x%08x\n", hw->dvoa_srcdim);
  546. printk(" DVOB_SRCDIM: 0x%08x\n", hw->dvob_srcdim);
  547. printk(" DVOC_SRCDIM: 0x%08x\n", hw->dvoc_srcdim);
  548. printk(" LVDS: 0x%08x\n", hw->lvds);
  549. printk(" PIPEACONF: 0x%08x\n", hw->pipe_a_conf);
  550. printk(" PIPEBCONF: 0x%08x\n", hw->pipe_b_conf);
  551. printk(" DISPARB: 0x%08x\n", hw->disp_arb);
  552. printk(" CURSOR_A_CONTROL: 0x%08x\n", hw->cursor_a_control);
  553. printk(" CURSOR_B_CONTROL: 0x%08x\n", hw->cursor_b_control);
  554. printk(" CURSOR_A_BASEADDR: 0x%08x\n", hw->cursor_a_base);
  555. printk(" CURSOR_B_BASEADDR: 0x%08x\n", hw->cursor_b_base);
  556. printk(" CURSOR_A_PALETTE: ");
  557. for (i = 0; i < 4; i++) {
  558. printk("0x%08x", hw->cursor_a_palette[i]);
  559. if (i < 3)
  560. printk(", ");
  561. }
  562. printk("\n");
  563. printk(" CURSOR_B_PALETTE: ");
  564. for (i = 0; i < 4; i++) {
  565. printk("0x%08x", hw->cursor_b_palette[i]);
  566. if (i < 3)
  567. printk(", ");
  568. }
  569. printk("\n");
  570. printk(" CURSOR_SIZE: 0x%08x\n", hw->cursor_size);
  571. printk(" DSPACNTR: 0x%08x\n", hw->disp_a_ctrl);
  572. printk(" DSPBCNTR: 0x%08x\n", hw->disp_b_ctrl);
  573. printk(" DSPABASE: 0x%08x\n", hw->disp_a_base);
  574. printk(" DSPBBASE: 0x%08x\n", hw->disp_b_base);
  575. printk(" DSPASTRIDE: 0x%08x\n", hw->disp_a_stride);
  576. printk(" DSPBSTRIDE: 0x%08x\n", hw->disp_b_stride);
  577. printk(" VGACNTRL: 0x%08x\n", hw->vgacntrl);
  578. printk(" ADD_ID: 0x%08x\n", hw->add_id);
  579. for (i = 0; i < 7; i++) {
  580. printk(" SWF0%d 0x%08x\n", i,
  581. hw->swf0x[i]);
  582. }
  583. for (i = 0; i < 7; i++) {
  584. printk(" SWF1%d 0x%08x\n", i,
  585. hw->swf1x[i]);
  586. }
  587. for (i = 0; i < 3; i++) {
  588. printk(" SWF3%d 0x%08x\n", i,
  589. hw->swf3x[i]);
  590. }
  591. for (i = 0; i < 8; i++)
  592. printk(" FENCE%d 0x%08x\n", i,
  593. hw->fence[i]);
  594. printk(" INSTPM 0x%08x\n", hw->instpm);
  595. printk(" MEM_MODE 0x%08x\n", hw->mem_mode);
  596. printk(" FW_BLC_0 0x%08x\n", hw->fw_blc_0);
  597. printk(" FW_BLC_1 0x%08x\n", hw->fw_blc_1);
  598. printk("hw state dump end\n");
  599. #endif
  600. }
  601. /* Split the M parameter into M1 and M2. */
  602. static int
  603. splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2)
  604. {
  605. int m1, m2;
  606. m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2;
  607. if (m1 < MIN_M1)
  608. m1 = MIN_M1;
  609. if (m1 > MAX_M1)
  610. m1 = MAX_M1;
  611. m2 = m - 5 * (m1 + 2) - 2;
  612. if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) {
  613. return 1;
  614. } else {
  615. *retm1 = (unsigned int)m1;
  616. *retm2 = (unsigned int)m2;
  617. return 0;
  618. }
  619. }
  620. /* Split the P parameter into P1 and P2. */
  621. static int
  622. splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2)
  623. {
  624. int p1, p2;
  625. if (p % 4 == 0)
  626. p2 = 1;
  627. else
  628. p2 = 0;
  629. p1 = (p / (1 << (p2 + 1))) - 2;
  630. if (p % 4 == 0 && p1 < MIN_P1) {
  631. p2 = 0;
  632. p1 = (p / (1 << (p2 + 1))) - 2;
  633. }
  634. if (p1 < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) {
  635. return 1;
  636. } else {
  637. *retp1 = (unsigned int)p1;
  638. *retp2 = (unsigned int)p2;
  639. return 0;
  640. }
  641. }
  642. static int
  643. calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
  644. u32 *retp2, u32 *retclock)
  645. {
  646. u32 m1, m2, n, p1, p2, n1;
  647. u32 f_vco, p, p_best = 0, m, f_out;
  648. u32 err_max, err_target, err_best = 10000000;
  649. u32 n_best = 0, m_best = 0, f_best, f_err;
  650. u32 p_min, p_max, p_inc, div_min, div_max;
  651. /* Accept 0.5% difference, but aim for 0.1% */
  652. err_max = 5 * clock / 1000;
  653. err_target = clock / 1000;
  654. DBG_MSG("Clock is %d\n", clock);
  655. div_max = MAX_VCO_FREQ / clock;
  656. div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock;
  657. if (clock <= P_TRANSITION_CLOCK)
  658. p_inc = 4;
  659. else
  660. p_inc = 2;
  661. p_min = ROUND_UP_TO(div_min, p_inc);
  662. p_max = ROUND_DOWN_TO(div_max, p_inc);
  663. if (p_min < MIN_P)
  664. p_min = 4;
  665. if (p_max > MAX_P)
  666. p_max = 128;
  667. DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
  668. p = p_min;
  669. do {
  670. if (splitp(p, &p1, &p2)) {
  671. WRN_MSG("cannot split p = %d\n", p);
  672. p += p_inc;
  673. continue;
  674. }
  675. n = MIN_N;
  676. f_vco = clock * p;
  677. do {
  678. m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK;
  679. if (m < MIN_M)
  680. m = MIN_M;
  681. if (m > MAX_M)
  682. m = MAX_M;
  683. f_out = CALC_VCLOCK3(m, n, p);
  684. if (splitm(m, &m1, &m2)) {
  685. WRN_MSG("cannot split m = %d\n", m);
  686. n++;
  687. continue;
  688. }
  689. if (clock > f_out)
  690. f_err = clock - f_out;
  691. else
  692. f_err = f_out - clock;
  693. if (f_err < err_best) {
  694. m_best = m;
  695. n_best = n;
  696. p_best = p;
  697. f_best = f_out;
  698. err_best = f_err;
  699. }
  700. n++;
  701. } while ((n <= MAX_N) && (f_out >= clock));
  702. p += p_inc;
  703. } while ((p <= p_max));
  704. if (!m_best) {
  705. WRN_MSG("cannot find parameters for clock %d\n", clock);
  706. return 1;
  707. }
  708. m = m_best;
  709. n = n_best;
  710. p = p_best;
  711. splitm(m, &m1, &m2);
  712. splitp(p, &p1, &p2);
  713. n1 = n - 2;
  714. DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
  715. "f: %d (%d), VCO: %d\n",
  716. m, m1, m2, n, n1, p, p1, p2,
  717. CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2),
  718. CALC_VCLOCK3(m, n, p) * p);
  719. *retm1 = m1;
  720. *retm2 = m2;
  721. *retn = n1;
  722. *retp1 = p1;
  723. *retp2 = p2;
  724. *retclock = CALC_VCLOCK(m1, m2, n1, p1, p2);
  725. return 0;
  726. }
  727. static __inline__ int
  728. check_overflow(u32 value, u32 limit, const char *description)
  729. {
  730. if (value > limit) {
  731. WRN_MSG("%s value %d exceeds limit %d\n",
  732. description, value, limit);
  733. return 1;
  734. }
  735. return 0;
  736. }
  737. /* It is assumed that hw is filled in with the initial state information. */
  738. int
  739. intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
  740. struct fb_var_screeninfo *var)
  741. {
  742. int pipe = PIPE_A;
  743. u32 *dpll, *fp0, *fp1;
  744. u32 m1, m2, n, p1, p2, clock_target, clock;
  745. u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
  746. u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
  747. u32 vsync_pol, hsync_pol;
  748. u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
  749. DBG_MSG("intelfbhw_mode_to_hw\n");
  750. /* Disable VGA */
  751. hw->vgacntrl |= VGA_DISABLE;
  752. /* Check whether pipe A or pipe B is enabled. */
  753. if (hw->pipe_a_conf & PIPECONF_ENABLE)
  754. pipe = PIPE_A;
  755. else if (hw->pipe_b_conf & PIPECONF_ENABLE)
  756. pipe = PIPE_B;
  757. /* Set which pipe's registers will be set. */
  758. if (pipe == PIPE_B) {
  759. dpll = &hw->dpll_b;
  760. fp0 = &hw->fpb0;
  761. fp1 = &hw->fpb1;
  762. hs = &hw->hsync_b;
  763. hb = &hw->hblank_b;
  764. ht = &hw->htotal_b;
  765. vs = &hw->vsync_b;
  766. vb = &hw->vblank_b;
  767. vt = &hw->vtotal_b;
  768. ss = &hw->src_size_b;
  769. pipe_conf = &hw->pipe_b_conf;
  770. } else {
  771. dpll = &hw->dpll_a;
  772. fp0 = &hw->fpa0;
  773. fp1 = &hw->fpa1;
  774. hs = &hw->hsync_a;
  775. hb = &hw->hblank_a;
  776. ht = &hw->htotal_a;
  777. vs = &hw->vsync_a;
  778. vb = &hw->vblank_a;
  779. vt = &hw->vtotal_a;
  780. ss = &hw->src_size_a;
  781. pipe_conf = &hw->pipe_a_conf;
  782. }
  783. /* Use ADPA register for sync control. */
  784. hw->adpa &= ~ADPA_USE_VGA_HVPOLARITY;
  785. /* sync polarity */
  786. hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ?
  787. ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
  788. vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ?
  789. ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
  790. hw->adpa &= ~((ADPA_SYNC_ACTIVE_MASK << ADPA_VSYNC_ACTIVE_SHIFT) |
  791. (ADPA_SYNC_ACTIVE_MASK << ADPA_HSYNC_ACTIVE_SHIFT));
  792. hw->adpa |= (hsync_pol << ADPA_HSYNC_ACTIVE_SHIFT) |
  793. (vsync_pol << ADPA_VSYNC_ACTIVE_SHIFT);
  794. /* Connect correct pipe to the analog port DAC */
  795. hw->adpa &= ~(PIPE_MASK << ADPA_PIPE_SELECT_SHIFT);
  796. hw->adpa |= (pipe << ADPA_PIPE_SELECT_SHIFT);
  797. /* Set DPMS state to D0 (on) */
  798. hw->adpa &= ~ADPA_DPMS_CONTROL_MASK;
  799. hw->adpa |= ADPA_DPMS_D0;
  800. hw->adpa |= ADPA_DAC_ENABLE;
  801. *dpll |= (DPLL_VCO_ENABLE | DPLL_VGA_MODE_DISABLE);
  802. *dpll &= ~(DPLL_RATE_SELECT_MASK | DPLL_REFERENCE_SELECT_MASK);
  803. *dpll |= (DPLL_REFERENCE_DEFAULT | DPLL_RATE_SELECT_FP0);
  804. /* Desired clock in kHz */
  805. clock_target = 1000000000 / var->pixclock;
  806. if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) {
  807. WRN_MSG("calc_pll_params failed\n");
  808. return 1;
  809. }
  810. /* Check for overflow. */
  811. if (check_overflow(p1, DPLL_P1_MASK, "PLL P1 parameter"))
  812. return 1;
  813. if (check_overflow(p2, DPLL_P2_MASK, "PLL P2 parameter"))
  814. return 1;
  815. if (check_overflow(m1, FP_DIVISOR_MASK, "PLL M1 parameter"))
  816. return 1;
  817. if (check_overflow(m2, FP_DIVISOR_MASK, "PLL M2 parameter"))
  818. return 1;
  819. if (check_overflow(n, FP_DIVISOR_MASK, "PLL N parameter"))
  820. return 1;
  821. *dpll &= ~DPLL_P1_FORCE_DIV2;
  822. *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
  823. (DPLL_P1_MASK << DPLL_P1_SHIFT));
  824. *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
  825. *fp0 = (n << FP_N_DIVISOR_SHIFT) |
  826. (m1 << FP_M1_DIVISOR_SHIFT) |
  827. (m2 << FP_M2_DIVISOR_SHIFT);
  828. *fp1 = *fp0;
  829. hw->dvob &= ~PORT_ENABLE;
  830. hw->dvoc &= ~PORT_ENABLE;
  831. /* Use display plane A. */
  832. hw->disp_a_ctrl |= DISPPLANE_PLANE_ENABLE;
  833. hw->disp_a_ctrl &= ~DISPPLANE_GAMMA_ENABLE;
  834. hw->disp_a_ctrl &= ~DISPPLANE_PIXFORMAT_MASK;
  835. switch (intelfb_var_to_depth(var)) {
  836. case 8:
  837. hw->disp_a_ctrl |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
  838. break;
  839. case 15:
  840. hw->disp_a_ctrl |= DISPPLANE_15_16BPP;
  841. break;
  842. case 16:
  843. hw->disp_a_ctrl |= DISPPLANE_16BPP;
  844. break;
  845. case 24:
  846. hw->disp_a_ctrl |= DISPPLANE_32BPP_NO_ALPHA;
  847. break;
  848. }
  849. hw->disp_a_ctrl &= ~(PIPE_MASK << DISPPLANE_SEL_PIPE_SHIFT);
  850. hw->disp_a_ctrl |= (pipe << DISPPLANE_SEL_PIPE_SHIFT);
  851. /* Set CRTC registers. */
  852. hactive = var->xres;
  853. hsync_start = hactive + var->right_margin;
  854. hsync_end = hsync_start + var->hsync_len;
  855. htotal = hsync_end + var->left_margin;
  856. hblank_start = hactive;
  857. hblank_end = htotal;
  858. DBG_MSG("H: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
  859. hactive, hsync_start, hsync_end, htotal, hblank_start,
  860. hblank_end);
  861. vactive = var->yres;
  862. vsync_start = vactive + var->lower_margin;
  863. vsync_end = vsync_start + var->vsync_len;
  864. vtotal = vsync_end + var->upper_margin;
  865. vblank_start = vactive;
  866. vblank_end = vtotal;
  867. vblank_end = vsync_end + 1;
  868. DBG_MSG("V: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
  869. vactive, vsync_start, vsync_end, vtotal, vblank_start,
  870. vblank_end);
  871. /* Adjust for register values, and check for overflow. */
  872. hactive--;
  873. if (check_overflow(hactive, HACTIVE_MASK, "CRTC hactive"))
  874. return 1;
  875. hsync_start--;
  876. if (check_overflow(hsync_start, HSYNCSTART_MASK, "CRTC hsync_start"))
  877. return 1;
  878. hsync_end--;
  879. if (check_overflow(hsync_end, HSYNCEND_MASK, "CRTC hsync_end"))
  880. return 1;
  881. htotal--;
  882. if (check_overflow(htotal, HTOTAL_MASK, "CRTC htotal"))
  883. return 1;
  884. hblank_start--;
  885. if (check_overflow(hblank_start, HBLANKSTART_MASK, "CRTC hblank_start"))
  886. return 1;
  887. hblank_end--;
  888. if (check_overflow(hblank_end, HBLANKEND_MASK, "CRTC hblank_end"))
  889. return 1;
  890. vactive--;
  891. if (check_overflow(vactive, VACTIVE_MASK, "CRTC vactive"))
  892. return 1;
  893. vsync_start--;
  894. if (check_overflow(vsync_start, VSYNCSTART_MASK, "CRTC vsync_start"))
  895. return 1;
  896. vsync_end--;
  897. if (check_overflow(vsync_end, VSYNCEND_MASK, "CRTC vsync_end"))
  898. return 1;
  899. vtotal--;
  900. if (check_overflow(vtotal, VTOTAL_MASK, "CRTC vtotal"))
  901. return 1;
  902. vblank_start--;
  903. if (check_overflow(vblank_start, VBLANKSTART_MASK, "CRTC vblank_start"))
  904. return 1;
  905. vblank_end--;
  906. if (check_overflow(vblank_end, VBLANKEND_MASK, "CRTC vblank_end"))
  907. return 1;
  908. *ht = (htotal << HTOTAL_SHIFT) | (hactive << HACTIVE_SHIFT);
  909. *hb = (hblank_start << HBLANKSTART_SHIFT) |
  910. (hblank_end << HSYNCEND_SHIFT);
  911. *hs = (hsync_start << HSYNCSTART_SHIFT) | (hsync_end << HSYNCEND_SHIFT);
  912. *vt = (vtotal << VTOTAL_SHIFT) | (vactive << VACTIVE_SHIFT);
  913. *vb = (vblank_start << VBLANKSTART_SHIFT) |
  914. (vblank_end << VSYNCEND_SHIFT);
  915. *vs = (vsync_start << VSYNCSTART_SHIFT) | (vsync_end << VSYNCEND_SHIFT);
  916. *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
  917. (vactive << SRC_SIZE_VERT_SHIFT);
  918. hw->disp_a_stride = var->xres_virtual * var->bits_per_pixel / 8;
  919. DBG_MSG("pitch is %d\n", hw->disp_a_stride);
  920. hw->disp_a_base = hw->disp_a_stride * var->yoffset +
  921. var->xoffset * var->bits_per_pixel / 8;
  922. hw->disp_a_base += dinfo->fb.offset << 12;
  923. /* Check stride alignment. */
  924. if (hw->disp_a_stride % STRIDE_ALIGNMENT != 0) {
  925. WRN_MSG("display stride %d has bad alignment %d\n",
  926. hw->disp_a_stride, STRIDE_ALIGNMENT);
  927. return 1;
  928. }
  929. /* Set the palette to 8-bit mode. */
  930. *pipe_conf &= ~PIPECONF_GAMMA;
  931. return 0;
  932. }
  933. /* Program a (non-VGA) video mode. */
  934. int
  935. intelfbhw_program_mode(struct intelfb_info *dinfo,
  936. const struct intelfb_hwstate *hw, int blank)
  937. {
  938. int pipe = PIPE_A;
  939. u32 tmp;
  940. const u32 *dpll, *fp0, *fp1, *pipe_conf;
  941. const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
  942. u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg;
  943. u32 hsync_reg, htotal_reg, hblank_reg;
  944. u32 vsync_reg, vtotal_reg, vblank_reg;
  945. u32 src_size_reg;
  946. /* Assume single pipe, display plane A, analog CRT. */
  947. #if VERBOSE > 0
  948. DBG_MSG("intelfbhw_program_mode\n");
  949. #endif
  950. /* Disable VGA */
  951. tmp = INREG(VGACNTRL);
  952. tmp |= VGA_DISABLE;
  953. OUTREG(VGACNTRL, tmp);
  954. /* Check whether pipe A or pipe B is enabled. */
  955. if (hw->pipe_a_conf & PIPECONF_ENABLE)
  956. pipe = PIPE_A;
  957. else if (hw->pipe_b_conf & PIPECONF_ENABLE)
  958. pipe = PIPE_B;
  959. dinfo->pipe = pipe;
  960. if (pipe == PIPE_B) {
  961. dpll = &hw->dpll_b;
  962. fp0 = &hw->fpb0;
  963. fp1 = &hw->fpb1;
  964. pipe_conf = &hw->pipe_b_conf;
  965. hs = &hw->hsync_b;
  966. hb = &hw->hblank_b;
  967. ht = &hw->htotal_b;
  968. vs = &hw->vsync_b;
  969. vb = &hw->vblank_b;
  970. vt = &hw->vtotal_b;
  971. ss = &hw->src_size_b;
  972. dpll_reg = DPLL_B;
  973. fp0_reg = FPB0;
  974. fp1_reg = FPB1;
  975. pipe_conf_reg = PIPEBCONF;
  976. hsync_reg = HSYNC_B;
  977. htotal_reg = HTOTAL_B;
  978. hblank_reg = HBLANK_B;
  979. vsync_reg = VSYNC_B;
  980. vtotal_reg = VTOTAL_B;
  981. vblank_reg = VBLANK_B;
  982. src_size_reg = SRC_SIZE_B;
  983. } else {
  984. dpll = &hw->dpll_a;
  985. fp0 = &hw->fpa0;
  986. fp1 = &hw->fpa1;
  987. pipe_conf = &hw->pipe_a_conf;
  988. hs = &hw->hsync_a;
  989. hb = &hw->hblank_a;
  990. ht = &hw->htotal_a;
  991. vs = &hw->vsync_a;
  992. vb = &hw->vblank_a;
  993. vt = &hw->vtotal_a;
  994. ss = &hw->src_size_a;
  995. dpll_reg = DPLL_A;
  996. fp0_reg = FPA0;
  997. fp1_reg = FPA1;
  998. pipe_conf_reg = PIPEACONF;
  999. hsync_reg = HSYNC_A;
  1000. htotal_reg = HTOTAL_A;
  1001. hblank_reg = HBLANK_A;
  1002. vsync_reg = VSYNC_A;
  1003. vtotal_reg = VTOTAL_A;
  1004. vblank_reg = VBLANK_A;
  1005. src_size_reg = SRC_SIZE_A;
  1006. }
  1007. /* Disable planes A and B. */
  1008. tmp = INREG(DSPACNTR);
  1009. tmp &= ~DISPPLANE_PLANE_ENABLE;
  1010. OUTREG(DSPACNTR, tmp);
  1011. tmp = INREG(DSPBCNTR);
  1012. tmp &= ~DISPPLANE_PLANE_ENABLE;
  1013. OUTREG(DSPBCNTR, tmp);
  1014. /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
  1015. mdelay(20);
  1016. /* Disable Sync */
  1017. tmp = INREG(ADPA);
  1018. tmp &= ~ADPA_DPMS_CONTROL_MASK;
  1019. tmp |= ADPA_DPMS_D3;
  1020. OUTREG(ADPA, tmp);
  1021. /* turn off pipe */
  1022. tmp = INREG(pipe_conf_reg);
  1023. tmp &= ~PIPECONF_ENABLE;
  1024. OUTREG(pipe_conf_reg, tmp);
  1025. /* turn off PLL */
  1026. tmp = INREG(dpll_reg);
  1027. dpll_reg &= ~DPLL_VCO_ENABLE;
  1028. OUTREG(dpll_reg, tmp);
  1029. /* Set PLL parameters */
  1030. OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE);
  1031. OUTREG(fp0_reg, *fp0);
  1032. OUTREG(fp1_reg, *fp1);
  1033. /* Set pipe parameters */
  1034. OUTREG(hsync_reg, *hs);
  1035. OUTREG(hblank_reg, *hb);
  1036. OUTREG(htotal_reg, *ht);
  1037. OUTREG(vsync_reg, *vs);
  1038. OUTREG(vblank_reg, *vb);
  1039. OUTREG(vtotal_reg, *vt);
  1040. OUTREG(src_size_reg, *ss);
  1041. /* Set DVOs B/C */
  1042. OUTREG(DVOB, hw->dvob);
  1043. OUTREG(DVOC, hw->dvoc);
  1044. /* Set ADPA */
  1045. OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
  1046. /* Enable PLL */
  1047. tmp = INREG(dpll_reg);
  1048. tmp |= DPLL_VCO_ENABLE;
  1049. OUTREG(dpll_reg, tmp);
  1050. /* Enable pipe */
  1051. OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
  1052. /* Enable sync */
  1053. tmp = INREG(ADPA);
  1054. tmp &= ~ADPA_DPMS_CONTROL_MASK;
  1055. tmp |= ADPA_DPMS_D0;
  1056. OUTREG(ADPA, tmp);
  1057. /* setup display plane */
  1058. if (dinfo->pdev->device == PCI_DEVICE_ID_INTEL_830M) {
  1059. /*
  1060. * i830M errata: the display plane must be enabled
  1061. * to allow writes to the other bits in the plane
  1062. * control register.
  1063. */
  1064. tmp = INREG(DSPACNTR);
  1065. if ((tmp & DISPPLANE_PLANE_ENABLE) != DISPPLANE_PLANE_ENABLE) {
  1066. tmp |= DISPPLANE_PLANE_ENABLE;
  1067. OUTREG(DSPACNTR, tmp);
  1068. OUTREG(DSPACNTR,
  1069. hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
  1070. mdelay(1);
  1071. }
  1072. }
  1073. OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
  1074. OUTREG(DSPASTRIDE, hw->disp_a_stride);
  1075. OUTREG(DSPABASE, hw->disp_a_base);
  1076. /* Enable plane */
  1077. if (!blank) {
  1078. tmp = INREG(DSPACNTR);
  1079. tmp |= DISPPLANE_PLANE_ENABLE;
  1080. OUTREG(DSPACNTR, tmp);
  1081. OUTREG(DSPABASE, hw->disp_a_base);
  1082. }
  1083. return 0;
  1084. }
  1085. /* forward declarations */
  1086. static void refresh_ring(struct intelfb_info *dinfo);
  1087. static void reset_state(struct intelfb_info *dinfo);
  1088. static void do_flush(struct intelfb_info *dinfo);
  1089. static int
  1090. wait_ring(struct intelfb_info *dinfo, int n)
  1091. {
  1092. int i = 0;
  1093. unsigned long end;
  1094. u32 last_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
  1095. #if VERBOSE > 0
  1096. DBG_MSG("wait_ring: %d\n", n);
  1097. #endif
  1098. end = jiffies + (HZ * 3);
  1099. while (dinfo->ring_space < n) {
  1100. dinfo->ring_head = (u8 __iomem *)(INREG(PRI_RING_HEAD) &
  1101. RING_HEAD_MASK);
  1102. if (dinfo->ring_tail + RING_MIN_FREE <
  1103. (u32 __iomem) dinfo->ring_head)
  1104. dinfo->ring_space = (u32 __iomem) dinfo->ring_head
  1105. - (dinfo->ring_tail + RING_MIN_FREE);
  1106. else
  1107. dinfo->ring_space = (dinfo->ring.size +
  1108. (u32 __iomem) dinfo->ring_head)
  1109. - (dinfo->ring_tail + RING_MIN_FREE);
  1110. if ((u32 __iomem) dinfo->ring_head != last_head) {
  1111. end = jiffies + (HZ * 3);
  1112. last_head = (u32 __iomem) dinfo->ring_head;
  1113. }
  1114. i++;
  1115. if (time_before(end, jiffies)) {
  1116. if (!i) {
  1117. /* Try again */
  1118. reset_state(dinfo);
  1119. refresh_ring(dinfo);
  1120. do_flush(dinfo);
  1121. end = jiffies + (HZ * 3);
  1122. i = 1;
  1123. } else {
  1124. WRN_MSG("ring buffer : space: %d wanted %d\n",
  1125. dinfo->ring_space, n);
  1126. WRN_MSG("lockup - turning off hardware "
  1127. "acceleration\n");
  1128. dinfo->ring_lockup = 1;
  1129. break;
  1130. }
  1131. }
  1132. udelay(1);
  1133. }
  1134. return i;
  1135. }
  1136. static void
  1137. do_flush(struct intelfb_info *dinfo) {
  1138. START_RING(2);
  1139. OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
  1140. OUT_RING(MI_NOOP);
  1141. ADVANCE_RING();
  1142. }
  1143. void
  1144. intelfbhw_do_sync(struct intelfb_info *dinfo)
  1145. {
  1146. #if VERBOSE > 0
  1147. DBG_MSG("intelfbhw_do_sync\n");
  1148. #endif
  1149. if (!dinfo->accel)
  1150. return;
  1151. /*
  1152. * Send a flush, then wait until the ring is empty. This is what
  1153. * the XFree86 driver does, and actually it doesn't seem a lot worse
  1154. * than the recommended method (both have problems).
  1155. */
  1156. do_flush(dinfo);
  1157. wait_ring(dinfo, dinfo->ring.size - RING_MIN_FREE);
  1158. dinfo->ring_space = dinfo->ring.size - RING_MIN_FREE;
  1159. }
  1160. static void
  1161. refresh_ring(struct intelfb_info *dinfo)
  1162. {
  1163. #if VERBOSE > 0
  1164. DBG_MSG("refresh_ring\n");
  1165. #endif
  1166. dinfo->ring_head = (u8 __iomem *) (INREG(PRI_RING_HEAD) &
  1167. RING_HEAD_MASK);
  1168. dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
  1169. if (dinfo->ring_tail + RING_MIN_FREE < (u32 __iomem)dinfo->ring_head)
  1170. dinfo->ring_space = (u32 __iomem) dinfo->ring_head
  1171. - (dinfo->ring_tail + RING_MIN_FREE);
  1172. else
  1173. dinfo->ring_space = (dinfo->ring.size +
  1174. (u32 __iomem) dinfo->ring_head)
  1175. - (dinfo->ring_tail + RING_MIN_FREE);
  1176. }
  1177. static void
  1178. reset_state(struct intelfb_info *dinfo)
  1179. {
  1180. int i;
  1181. u32 tmp;
  1182. #if VERBOSE > 0
  1183. DBG_MSG("reset_state\n");
  1184. #endif
  1185. for (i = 0; i < FENCE_NUM; i++)
  1186. OUTREG(FENCE + (i << 2), 0);
  1187. /* Flush the ring buffer if it's enabled. */
  1188. tmp = INREG(PRI_RING_LENGTH);
  1189. if (tmp & RING_ENABLE) {
  1190. #if VERBOSE > 0
  1191. DBG_MSG("reset_state: ring was enabled\n");
  1192. #endif
  1193. refresh_ring(dinfo);
  1194. intelfbhw_do_sync(dinfo);
  1195. DO_RING_IDLE();
  1196. }
  1197. OUTREG(PRI_RING_LENGTH, 0);
  1198. OUTREG(PRI_RING_HEAD, 0);
  1199. OUTREG(PRI_RING_TAIL, 0);
  1200. OUTREG(PRI_RING_START, 0);
  1201. }
  1202. /* Stop the 2D engine, and turn off the ring buffer. */
  1203. void
  1204. intelfbhw_2d_stop(struct intelfb_info *dinfo)
  1205. {
  1206. #if VERBOSE > 0
  1207. DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n", dinfo->accel,
  1208. dinfo->ring_active);
  1209. #endif
  1210. if (!dinfo->accel)
  1211. return;
  1212. dinfo->ring_active = 0;
  1213. reset_state(dinfo);
  1214. }
  1215. /*
  1216. * Enable the ring buffer, and initialise the 2D engine.
  1217. * It is assumed that the graphics engine has been stopped by previously
  1218. * calling intelfb_2d_stop().
  1219. */
  1220. void
  1221. intelfbhw_2d_start(struct intelfb_info *dinfo)
  1222. {
  1223. #if VERBOSE > 0
  1224. DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",
  1225. dinfo->accel, dinfo->ring_active);
  1226. #endif
  1227. if (!dinfo->accel)
  1228. return;
  1229. /* Initialise the primary ring buffer. */
  1230. OUTREG(PRI_RING_LENGTH, 0);
  1231. OUTREG(PRI_RING_TAIL, 0);
  1232. OUTREG(PRI_RING_HEAD, 0);
  1233. OUTREG(PRI_RING_START, dinfo->ring.physical & RING_START_MASK);
  1234. OUTREG(PRI_RING_LENGTH,
  1235. ((dinfo->ring.size - GTT_PAGE_SIZE) & RING_LENGTH_MASK) |
  1236. RING_NO_REPORT | RING_ENABLE);
  1237. refresh_ring(dinfo);
  1238. dinfo->ring_active = 1;
  1239. }
  1240. /* 2D fillrect (solid fill or invert) */
  1241. void
  1242. intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w, u32 h,
  1243. u32 color, u32 pitch, u32 bpp, u32 rop)
  1244. {
  1245. u32 br00, br09, br13, br14, br16;
  1246. #if VERBOSE > 0
  1247. DBG_MSG("intelfbhw_do_fillrect: (%d,%d) %dx%d, c 0x%06x, p %d bpp %d, "
  1248. "rop 0x%02x\n", x, y, w, h, color, pitch, bpp, rop);
  1249. #endif
  1250. br00 = COLOR_BLT_CMD;
  1251. br09 = dinfo->fb_start + (y * pitch + x * (bpp / 8));
  1252. br13 = (rop << ROP_SHIFT) | pitch;
  1253. br14 = (h << HEIGHT_SHIFT) | ((w * (bpp / 8)) << WIDTH_SHIFT);
  1254. br16 = color;
  1255. switch (bpp) {
  1256. case 8:
  1257. br13 |= COLOR_DEPTH_8;
  1258. break;
  1259. case 16:
  1260. br13 |= COLOR_DEPTH_16;
  1261. break;
  1262. case 32:
  1263. br13 |= COLOR_DEPTH_32;
  1264. br00 |= WRITE_ALPHA | WRITE_RGB;
  1265. break;
  1266. }
  1267. START_RING(6);
  1268. OUT_RING(br00);
  1269. OUT_RING(br13);
  1270. OUT_RING(br14);
  1271. OUT_RING(br09);
  1272. OUT_RING(br16);
  1273. OUT_RING(MI_NOOP);
  1274. ADVANCE_RING();
  1275. #if VERBOSE > 0
  1276. DBG_MSG("ring = 0x%08x, 0x%08x (%d)\n", dinfo->ring_head,
  1277. dinfo->ring_tail, dinfo->ring_space);
  1278. #endif
  1279. }
  1280. void
  1281. intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
  1282. u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch, u32 bpp)
  1283. {
  1284. u32 br00, br09, br11, br12, br13, br22, br23, br26;
  1285. #if VERBOSE > 0
  1286. DBG_MSG("intelfbhw_do_bitblt: (%d,%d)->(%d,%d) %dx%d, p %d bpp %d\n",
  1287. curx, cury, dstx, dsty, w, h, pitch, bpp);
  1288. #endif
  1289. br00 = XY_SRC_COPY_BLT_CMD;
  1290. br09 = dinfo->fb_start;
  1291. br11 = (pitch << PITCH_SHIFT);
  1292. br12 = dinfo->fb_start;
  1293. br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
  1294. br22 = (dstx << WIDTH_SHIFT) | (dsty << HEIGHT_SHIFT);
  1295. br23 = ((dstx + w) << WIDTH_SHIFT) |
  1296. ((dsty + h) << HEIGHT_SHIFT);
  1297. br26 = (curx << WIDTH_SHIFT) | (cury << HEIGHT_SHIFT);
  1298. switch (bpp) {
  1299. case 8:
  1300. br13 |= COLOR_DEPTH_8;
  1301. break;
  1302. case 16:
  1303. br13 |= COLOR_DEPTH_16;
  1304. break;
  1305. case 32:
  1306. br13 |= COLOR_DEPTH_32;
  1307. br00 |= WRITE_ALPHA | WRITE_RGB;
  1308. break;
  1309. }
  1310. START_RING(8);
  1311. OUT_RING(br00);
  1312. OUT_RING(br13);
  1313. OUT_RING(br22);
  1314. OUT_RING(br23);
  1315. OUT_RING(br09);
  1316. OUT_RING(br26);
  1317. OUT_RING(br11);
  1318. OUT_RING(br12);
  1319. ADVANCE_RING();
  1320. }
  1321. int
  1322. intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
  1323. u32 h, const u8* cdat, u32 x, u32 y, u32 pitch, u32 bpp)
  1324. {
  1325. int nbytes, ndwords, pad, tmp;
  1326. u32 br00, br09, br13, br18, br19, br22, br23;
  1327. int dat, ix, iy, iw;
  1328. int i, j;
  1329. #if VERBOSE > 0
  1330. DBG_MSG("intelfbhw_do_drawglyph: (%d,%d) %dx%d\n", x, y, w, h);
  1331. #endif
  1332. /* size in bytes of a padded scanline */
  1333. nbytes = ROUND_UP_TO(w, 16) / 8;
  1334. /* Total bytes of padded scanline data to write out. */
  1335. nbytes = nbytes * h;
  1336. /*
  1337. * Check if the glyph data exceeds the immediate mode limit.
  1338. * It would take a large font (1K pixels) to hit this limit.
  1339. */
  1340. if (nbytes > MAX_MONO_IMM_SIZE)
  1341. return 0;
  1342. /* Src data is packaged a dword (32-bit) at a time. */
  1343. ndwords = ROUND_UP_TO(nbytes, 4) / 4;
  1344. /*
  1345. * Ring has to be padded to a quad word. But because the command starts
  1346. with 7 bytes, pad only if there is an even number of ndwords
  1347. */
  1348. pad = !(ndwords % 2);
  1349. tmp = (XY_MONO_SRC_IMM_BLT_CMD & DW_LENGTH_MASK) + ndwords;
  1350. br00 = (XY_MONO_SRC_IMM_BLT_CMD & ~DW_LENGTH_MASK) | tmp;
  1351. br09 = dinfo->fb_start;
  1352. br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
  1353. br18 = bg;
  1354. br19 = fg;
  1355. br22 = (x << WIDTH_SHIFT) | (y << HEIGHT_SHIFT);
  1356. br23 = ((x + w) << WIDTH_SHIFT) | ((y + h) << HEIGHT_SHIFT);
  1357. switch (bpp) {
  1358. case 8:
  1359. br13 |= COLOR_DEPTH_8;
  1360. break;
  1361. case 16:
  1362. br13 |= COLOR_DEPTH_16;
  1363. break;
  1364. case 32:
  1365. br13 |= COLOR_DEPTH_32;
  1366. br00 |= WRITE_ALPHA | WRITE_RGB;
  1367. break;
  1368. }
  1369. START_RING(8 + ndwords);
  1370. OUT_RING(br00);
  1371. OUT_RING(br13);
  1372. OUT_RING(br22);
  1373. OUT_RING(br23);
  1374. OUT_RING(br09);
  1375. OUT_RING(br18);
  1376. OUT_RING(br19);
  1377. ix = iy = 0;
  1378. iw = ROUND_UP_TO(w, 8) / 8;
  1379. while (ndwords--) {
  1380. dat = 0;
  1381. for (j = 0; j < 2; ++j) {
  1382. for (i = 0; i < 2; ++i) {
  1383. if (ix != iw || i == 0)
  1384. dat |= cdat[iy*iw + ix++] << (i+j*2)*8;
  1385. }
  1386. if (ix == iw && iy != (h-1)) {
  1387. ix = 0;
  1388. ++iy;
  1389. }
  1390. }
  1391. OUT_RING(dat);
  1392. }
  1393. if (pad)
  1394. OUT_RING(MI_NOOP);
  1395. ADVANCE_RING();
  1396. return 1;
  1397. }
  1398. /* HW cursor functions. */
  1399. void
  1400. intelfbhw_cursor_init(struct intelfb_info *dinfo)
  1401. {
  1402. u32 tmp;
  1403. #if VERBOSE > 0
  1404. DBG_MSG("intelfbhw_cursor_init\n");
  1405. #endif
  1406. if (dinfo->mobile) {
  1407. if (!dinfo->cursor.physical)
  1408. return;
  1409. tmp = INREG(CURSOR_A_CONTROL);
  1410. tmp &= ~(CURSOR_MODE_MASK | CURSOR_MOBILE_GAMMA_ENABLE |
  1411. CURSOR_MEM_TYPE_LOCAL |
  1412. (1 << CURSOR_PIPE_SELECT_SHIFT));
  1413. tmp |= CURSOR_MODE_DISABLE;
  1414. OUTREG(CURSOR_A_CONTROL, tmp);
  1415. OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
  1416. } else {
  1417. tmp = INREG(CURSOR_CONTROL);
  1418. tmp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
  1419. CURSOR_ENABLE | CURSOR_STRIDE_MASK);
  1420. tmp = CURSOR_FORMAT_3C;
  1421. OUTREG(CURSOR_CONTROL, tmp);
  1422. OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.offset << 12);
  1423. tmp = (64 << CURSOR_SIZE_H_SHIFT) |
  1424. (64 << CURSOR_SIZE_V_SHIFT);
  1425. OUTREG(CURSOR_SIZE, tmp);
  1426. }
  1427. }
  1428. void
  1429. intelfbhw_cursor_hide(struct intelfb_info *dinfo)
  1430. {
  1431. u32 tmp;
  1432. #if VERBOSE > 0
  1433. DBG_MSG("intelfbhw_cursor_hide\n");
  1434. #endif
  1435. dinfo->cursor_on = 0;
  1436. if (dinfo->mobile) {
  1437. if (!dinfo->cursor.physical)
  1438. return;
  1439. tmp = INREG(CURSOR_A_CONTROL);
  1440. tmp &= ~CURSOR_MODE_MASK;
  1441. tmp |= CURSOR_MODE_DISABLE;
  1442. OUTREG(CURSOR_A_CONTROL, tmp);
  1443. /* Flush changes */
  1444. OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
  1445. } else {
  1446. tmp = INREG(CURSOR_CONTROL);
  1447. tmp &= ~CURSOR_ENABLE;
  1448. OUTREG(CURSOR_CONTROL, tmp);
  1449. }
  1450. }
  1451. void
  1452. intelfbhw_cursor_show(struct intelfb_info *dinfo)
  1453. {
  1454. u32 tmp;
  1455. #if VERBOSE > 0
  1456. DBG_MSG("intelfbhw_cursor_show\n");
  1457. #endif
  1458. dinfo->cursor_on = 1;
  1459. if (dinfo->cursor_blanked)
  1460. return;
  1461. if (dinfo->mobile) {
  1462. if (!dinfo->cursor.physical)
  1463. return;
  1464. tmp = INREG(CURSOR_A_CONTROL);
  1465. tmp &= ~CURSOR_MODE_MASK;
  1466. tmp |= CURSOR_MODE_64_4C_AX;
  1467. OUTREG(CURSOR_A_CONTROL, tmp);
  1468. /* Flush changes */
  1469. OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
  1470. } else {
  1471. tmp = INREG(CURSOR_CONTROL);
  1472. tmp |= CURSOR_ENABLE;
  1473. OUTREG(CURSOR_CONTROL, tmp);
  1474. }
  1475. }
  1476. void
  1477. intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
  1478. {
  1479. u32 tmp;
  1480. #if VERBOSE > 0
  1481. DBG_MSG("intelfbhw_cursor_setpos: (%d, %d)\n", x, y);
  1482. #endif
  1483. /*
  1484. * Sets the position. The coordinates are assumed to already
  1485. * have any offset adjusted. Assume that the cursor is never
  1486. * completely off-screen, and that x, y are always >= 0.
  1487. */
  1488. tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
  1489. ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
  1490. OUTREG(CURSOR_A_POSITION, tmp);
  1491. }
  1492. void
  1493. intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
  1494. {
  1495. #if VERBOSE > 0
  1496. DBG_MSG("intelfbhw_cursor_setcolor\n");
  1497. #endif
  1498. OUTREG(CURSOR_A_PALETTE0, bg & CURSOR_PALETTE_MASK);
  1499. OUTREG(CURSOR_A_PALETTE1, fg & CURSOR_PALETTE_MASK);
  1500. OUTREG(CURSOR_A_PALETTE2, fg & CURSOR_PALETTE_MASK);
  1501. OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);
  1502. }
  1503. void
  1504. intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
  1505. u8 *data)
  1506. {
  1507. u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
  1508. int i, j, w = width / 8;
  1509. int mod = width % 8, t_mask, d_mask;
  1510. #if VERBOSE > 0
  1511. DBG_MSG("intelfbhw_cursor_load\n");
  1512. #endif
  1513. if (!dinfo->cursor.virtual)
  1514. return;
  1515. t_mask = 0xff >> mod;
  1516. d_mask = ~(0xff >> mod);
  1517. for (i = height; i--; ) {
  1518. for (j = 0; j < w; j++) {
  1519. writeb(0x00, addr + j);
  1520. writeb(*(data++), addr + j+8);
  1521. }
  1522. if (mod) {
  1523. writeb(t_mask, addr + j);
  1524. writeb(*(data++) & d_mask, addr + j+8);
  1525. }
  1526. addr += 16;
  1527. }
  1528. }
  1529. void
  1530. intelfbhw_cursor_reset(struct intelfb_info *dinfo) {
  1531. u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
  1532. int i, j;
  1533. #if VERBOSE > 0
  1534. DBG_MSG("intelfbhw_cursor_reset\n");
  1535. #endif
  1536. if (!dinfo->cursor.virtual)
  1537. return;
  1538. for (i = 64; i--; ) {
  1539. for (j = 0; j < 8; j++) {
  1540. writeb(0xff, addr + j+0);
  1541. writeb(0x00, addr + j+8);
  1542. }
  1543. addr += 16;
  1544. }
  1545. }