pm2fb.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. /*
  2. * Permedia2 framebuffer driver.
  3. *
  4. * 2.5/2.6 driver:
  5. * Copyright (c) 2003 Jim Hague (jim.hague@acm.org)
  6. *
  7. * based on 2.4 driver:
  8. * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
  9. * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com)
  10. *
  11. * and additional input from James Simmon's port of Hannu Mallat's tdfx
  12. * driver.
  13. *
  14. * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86. I
  15. * have no access to other pm2fb implementations. Sparc (and thus
  16. * hopefully other big-endian) devices now work, thanks to a lot of
  17. * testing work by Ron Murray. I have no access to CVision hardware,
  18. * and therefore for now I am omitting the CVision code.
  19. *
  20. * Multiple boards support has been on the TODO list for ages.
  21. * Don't expect this to change.
  22. *
  23. * This file is subject to the terms and conditions of the GNU General Public
  24. * License. See the file COPYING in the main directory of this archive for
  25. * more details.
  26. *
  27. *
  28. */
  29. #include <linux/module.h>
  30. #include <linux/moduleparam.h>
  31. #include <linux/kernel.h>
  32. #include <linux/errno.h>
  33. #include <linux/string.h>
  34. #include <linux/mm.h>
  35. #include <linux/slab.h>
  36. #include <linux/delay.h>
  37. #include <linux/fb.h>
  38. #include <linux/init.h>
  39. #include <linux/pci.h>
  40. #include <video/permedia2.h>
  41. #include <video/cvisionppc.h>
  42. #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
  43. #error "The endianness of the target host has not been defined."
  44. #endif
  45. #if !defined(CONFIG_PCI)
  46. #error "Only generic PCI cards supported."
  47. #endif
  48. #undef PM2FB_MASTER_DEBUG
  49. #ifdef PM2FB_MASTER_DEBUG
  50. #define DPRINTK(a,b...) printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)
  51. #else
  52. #define DPRINTK(a,b...)
  53. #endif
  54. /*
  55. * Driver data
  56. */
  57. static char *mode __devinitdata = NULL;
  58. /*
  59. * The XFree GLINT driver will (I think to implement hardware cursor
  60. * support on TVP4010 and similar where there is no RAMDAC - see
  61. * comment in set_video) always request +ve sync regardless of what
  62. * the mode requires. This screws me because I have a Sun
  63. * fixed-frequency monitor which absolutely has to have -ve sync. So
  64. * these flags allow the user to specify that requests for +ve sync
  65. * should be silently turned in -ve sync.
  66. */
  67. static int lowhsync;
  68. static int lowvsync;
  69. /*
  70. * The hardware state of the graphics card that isn't part of the
  71. * screeninfo.
  72. */
  73. struct pm2fb_par
  74. {
  75. pm2type_t type; /* Board type */
  76. u32 fb_size; /* framebuffer memory size */
  77. unsigned char __iomem *v_fb; /* virtual address of frame buffer */
  78. unsigned char __iomem *v_regs;/* virtual address of p_regs */
  79. u32 memclock; /* memclock */
  80. u32 video; /* video flags before blanking */
  81. u32 mem_config; /* MemConfig reg at probe */
  82. u32 mem_control; /* MemControl reg at probe */
  83. u32 boot_address; /* BootAddress reg at probe */
  84. u32 palette[16];
  85. };
  86. /*
  87. * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
  88. * if we don't use modedb.
  89. */
  90. static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
  91. .id = "",
  92. .type = FB_TYPE_PACKED_PIXELS,
  93. .visual = FB_VISUAL_PSEUDOCOLOR,
  94. .xpanstep = 1,
  95. .ypanstep = 1,
  96. .ywrapstep = 0,
  97. .accel = FB_ACCEL_NONE,
  98. };
  99. /*
  100. * Default video mode. In case the modedb doesn't work.
  101. */
  102. static struct fb_var_screeninfo pm2fb_var __devinitdata = {
  103. /* "640x480, 8 bpp @ 60 Hz */
  104. .xres = 640,
  105. .yres = 480,
  106. .xres_virtual = 640,
  107. .yres_virtual = 480,
  108. .bits_per_pixel =8,
  109. .red = {0, 8, 0},
  110. .blue = {0, 8, 0},
  111. .green = {0, 8, 0},
  112. .activate = FB_ACTIVATE_NOW,
  113. .height = -1,
  114. .width = -1,
  115. .accel_flags = 0,
  116. .pixclock = 39721,
  117. .left_margin = 40,
  118. .right_margin = 24,
  119. .upper_margin = 32,
  120. .lower_margin = 11,
  121. .hsync_len = 96,
  122. .vsync_len = 2,
  123. .vmode = FB_VMODE_NONINTERLACED
  124. };
  125. /*
  126. * Utility functions
  127. */
  128. static inline u32 RD32(unsigned char __iomem *base, s32 off)
  129. {
  130. return fb_readl(base + off);
  131. }
  132. static inline void WR32(unsigned char __iomem *base, s32 off, u32 v)
  133. {
  134. fb_writel(v, base + off);
  135. }
  136. static inline u32 pm2_RD(struct pm2fb_par* p, s32 off)
  137. {
  138. return RD32(p->v_regs, off);
  139. }
  140. static inline void pm2_WR(struct pm2fb_par* p, s32 off, u32 v)
  141. {
  142. WR32(p->v_regs, off, v);
  143. }
  144. static inline u32 pm2_RDAC_RD(struct pm2fb_par* p, s32 idx)
  145. {
  146. int index = PM2R_RD_INDEXED_DATA;
  147. switch (p->type) {
  148. case PM2_TYPE_PERMEDIA2:
  149. pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
  150. break;
  151. case PM2_TYPE_PERMEDIA2V:
  152. pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
  153. index = PM2VR_RD_INDEXED_DATA;
  154. break;
  155. }
  156. mb();
  157. return pm2_RD(p, index);
  158. }
  159. static inline void pm2_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
  160. {
  161. int index = PM2R_RD_INDEXED_DATA;
  162. switch (p->type) {
  163. case PM2_TYPE_PERMEDIA2:
  164. pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
  165. break;
  166. case PM2_TYPE_PERMEDIA2V:
  167. pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
  168. index = PM2VR_RD_INDEXED_DATA;
  169. break;
  170. }
  171. mb();
  172. pm2_WR(p, index, v);
  173. }
  174. static inline void pm2v_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
  175. {
  176. pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
  177. mb();
  178. pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
  179. }
  180. #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
  181. #define WAIT_FIFO(p,a)
  182. #else
  183. static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a)
  184. {
  185. while( pm2_RD(p, PM2R_IN_FIFO_SPACE) < a );
  186. mb();
  187. }
  188. #endif
  189. /*
  190. * partial products for the supported horizontal resolutions.
  191. */
  192. #define PACKPP(p0,p1,p2) (((p2) << 6) | ((p1) << 3) | (p0))
  193. static const struct {
  194. u16 width;
  195. u16 pp;
  196. } pp_table[] = {
  197. { 32, PACKPP(1, 0, 0) }, { 64, PACKPP(1, 1, 0) },
  198. { 96, PACKPP(1, 1, 1) }, { 128, PACKPP(2, 1, 1) },
  199. { 160, PACKPP(2, 2, 1) }, { 192, PACKPP(2, 2, 2) },
  200. { 224, PACKPP(3, 2, 1) }, { 256, PACKPP(3, 2, 2) },
  201. { 288, PACKPP(3, 3, 1) }, { 320, PACKPP(3, 3, 2) },
  202. { 384, PACKPP(3, 3, 3) }, { 416, PACKPP(4, 3, 1) },
  203. { 448, PACKPP(4, 3, 2) }, { 512, PACKPP(4, 3, 3) },
  204. { 544, PACKPP(4, 4, 1) }, { 576, PACKPP(4, 4, 2) },
  205. { 640, PACKPP(4, 4, 3) }, { 768, PACKPP(4, 4, 4) },
  206. { 800, PACKPP(5, 4, 1) }, { 832, PACKPP(5, 4, 2) },
  207. { 896, PACKPP(5, 4, 3) }, { 1024, PACKPP(5, 4, 4) },
  208. { 1056, PACKPP(5, 5, 1) }, { 1088, PACKPP(5, 5, 2) },
  209. { 1152, PACKPP(5, 5, 3) }, { 1280, PACKPP(5, 5, 4) },
  210. { 1536, PACKPP(5, 5, 5) }, { 1568, PACKPP(6, 5, 1) },
  211. { 1600, PACKPP(6, 5, 2) }, { 1664, PACKPP(6, 5, 3) },
  212. { 1792, PACKPP(6, 5, 4) }, { 2048, PACKPP(6, 5, 5) },
  213. { 0, 0 } };
  214. static u32 partprod(u32 xres)
  215. {
  216. int i;
  217. for (i = 0; pp_table[i].width && pp_table[i].width != xres; i++)
  218. ;
  219. if ( pp_table[i].width == 0 )
  220. DPRINTK("invalid width %u\n", xres);
  221. return pp_table[i].pp;
  222. }
  223. static u32 to3264(u32 timing, int bpp, int is64)
  224. {
  225. switch (bpp) {
  226. case 8:
  227. timing >>= 2 + is64;
  228. break;
  229. case 16:
  230. timing >>= 1 + is64;
  231. break;
  232. case 24:
  233. timing = (timing * 3) >> (2 + is64);
  234. break;
  235. case 32:
  236. if (is64)
  237. timing >>= 1;
  238. break;
  239. }
  240. return timing;
  241. }
  242. static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
  243. unsigned char* pp)
  244. {
  245. unsigned char m;
  246. unsigned char n;
  247. unsigned char p;
  248. u32 f;
  249. s32 curr;
  250. s32 delta = 100000;
  251. *mm = *nn = *pp = 0;
  252. for (n = 2; n < 15; n++) {
  253. for (m = 2; m; m++) {
  254. f = PM2_REFERENCE_CLOCK * m / n;
  255. if (f >= 150000 && f <= 300000) {
  256. for ( p = 0; p < 5; p++, f >>= 1) {
  257. curr = ( clk > f ) ? clk - f : f - clk;
  258. if ( curr < delta ) {
  259. delta=curr;
  260. *mm=m;
  261. *nn=n;
  262. *pp=p;
  263. }
  264. }
  265. }
  266. }
  267. }
  268. }
  269. static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
  270. unsigned char* pp)
  271. {
  272. unsigned char m;
  273. unsigned char n;
  274. unsigned char p;
  275. u32 f;
  276. s32 delta = 1000;
  277. *mm = *nn = *pp = 0;
  278. for (n = 1; n; n++) {
  279. for ( m = 1; m; m++) {
  280. for ( p = 0; p < 2; p++) {
  281. f = PM2_REFERENCE_CLOCK * n / (m * (1 << (p + 1)));
  282. if ( clk > f - delta && clk < f + delta ) {
  283. delta = ( clk > f ) ? clk - f : f - clk;
  284. *mm=m;
  285. *nn=n;
  286. *pp=p;
  287. }
  288. }
  289. }
  290. }
  291. }
  292. static void clear_palette(struct pm2fb_par* p) {
  293. int i=256;
  294. WAIT_FIFO(p, 1);
  295. pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
  296. wmb();
  297. while (i--) {
  298. WAIT_FIFO(p, 3);
  299. pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
  300. pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
  301. pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
  302. }
  303. }
  304. static void reset_card(struct pm2fb_par* p)
  305. {
  306. if (p->type == PM2_TYPE_PERMEDIA2V)
  307. pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
  308. pm2_WR(p, PM2R_RESET_STATUS, 0);
  309. mb();
  310. while (pm2_RD(p, PM2R_RESET_STATUS) & PM2F_BEING_RESET)
  311. ;
  312. mb();
  313. #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
  314. DPRINTK("FIFO disconnect enabled\n");
  315. pm2_WR(p, PM2R_FIFO_DISCON, 1);
  316. mb();
  317. #endif
  318. /* Restore stashed memory config information from probe */
  319. WAIT_FIFO(p, 3);
  320. pm2_WR(p, PM2R_MEM_CONTROL, p->mem_control);
  321. pm2_WR(p, PM2R_BOOT_ADDRESS, p->boot_address);
  322. wmb();
  323. pm2_WR(p, PM2R_MEM_CONFIG, p->mem_config);
  324. }
  325. static void reset_config(struct pm2fb_par* p)
  326. {
  327. WAIT_FIFO(p, 52);
  328. pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
  329. ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
  330. pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
  331. pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
  332. pm2_WR(p, PM2R_FIFO_CONTROL, 0);
  333. pm2_WR(p, PM2R_APERTURE_ONE, 0);
  334. pm2_WR(p, PM2R_APERTURE_TWO, 0);
  335. pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
  336. pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
  337. pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
  338. pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
  339. pm2_WR(p, PM2R_LB_READ_MODE, 0);
  340. pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
  341. pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
  342. pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0);
  343. pm2_WR(p, PM2R_FB_WINDOW_BASE, 0);
  344. pm2_WR(p, PM2R_LB_WINDOW_BASE, 0);
  345. pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L));
  346. pm2_WR(p, PM2R_FB_HARD_WRITE_MASK, ~(0L));
  347. pm2_WR(p, PM2R_FB_READ_PIXEL, 0);
  348. pm2_WR(p, PM2R_DITHER_MODE, 0);
  349. pm2_WR(p, PM2R_AREA_STIPPLE_MODE, 0);
  350. pm2_WR(p, PM2R_DEPTH_MODE, 0);
  351. pm2_WR(p, PM2R_STENCIL_MODE, 0);
  352. pm2_WR(p, PM2R_TEXTURE_ADDRESS_MODE, 0);
  353. pm2_WR(p, PM2R_TEXTURE_READ_MODE, 0);
  354. pm2_WR(p, PM2R_TEXEL_LUT_MODE, 0);
  355. pm2_WR(p, PM2R_YUV_MODE, 0);
  356. pm2_WR(p, PM2R_COLOR_DDA_MODE, 0);
  357. pm2_WR(p, PM2R_TEXTURE_COLOR_MODE, 0);
  358. pm2_WR(p, PM2R_FOG_MODE, 0);
  359. pm2_WR(p, PM2R_ALPHA_BLEND_MODE, 0);
  360. pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
  361. pm2_WR(p, PM2R_STATISTICS_MODE, 0);
  362. pm2_WR(p, PM2R_SCISSOR_MODE, 0);
  363. pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
  364. switch (p->type) {
  365. case PM2_TYPE_PERMEDIA2:
  366. pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */
  367. pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
  368. pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
  369. break;
  370. case PM2_TYPE_PERMEDIA2V:
  371. pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */
  372. break;
  373. }
  374. pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
  375. pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
  376. pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
  377. pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
  378. pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
  379. }
  380. static void set_aperture(struct pm2fb_par* p, u32 depth)
  381. {
  382. /*
  383. * The hardware is little-endian. When used in big-endian
  384. * hosts, the on-chip aperture settings are used where
  385. * possible to translate from host to card byte order.
  386. */
  387. WAIT_FIFO(p, 4);
  388. #ifdef __LITTLE_ENDIAN
  389. pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
  390. #else
  391. switch (depth) {
  392. case 24: /* RGB->BGR */
  393. /*
  394. * We can't use the aperture to translate host to
  395. * card byte order here, so we switch to BGR mode
  396. * in pm2fb_set_par().
  397. */
  398. case 8: /* B->B */
  399. pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
  400. break;
  401. case 16: /* HL->LH */
  402. pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_HALFWORDSWAP);
  403. break;
  404. case 32: /* RGBA->ABGR */
  405. pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_BYTESWAP);
  406. break;
  407. }
  408. #endif
  409. // We don't use aperture two, so this may be superflous
  410. pm2_WR(p, PM2R_APERTURE_TWO, PM2F_APERTURE_STANDARD);
  411. }
  412. static void set_color(struct pm2fb_par* p, unsigned char regno,
  413. unsigned char r, unsigned char g, unsigned char b)
  414. {
  415. WAIT_FIFO(p, 4);
  416. pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
  417. wmb();
  418. pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
  419. wmb();
  420. pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
  421. wmb();
  422. pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
  423. }
  424. static void set_memclock(struct pm2fb_par* par, u32 clk)
  425. {
  426. int i;
  427. unsigned char m, n, p;
  428. pm2_mnp(clk, &m, &n, &p);
  429. WAIT_FIFO(par, 10);
  430. pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
  431. wmb();
  432. pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
  433. pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
  434. wmb();
  435. pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
  436. wmb();
  437. pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
  438. rmb();
  439. for (i = 256;
  440. i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
  441. i--)
  442. ;
  443. }
  444. static void set_pixclock(struct pm2fb_par* par, u32 clk)
  445. {
  446. int i;
  447. unsigned char m, n, p;
  448. switch (par->type) {
  449. case PM2_TYPE_PERMEDIA2:
  450. pm2_mnp(clk, &m, &n, &p);
  451. WAIT_FIFO(par, 8);
  452. pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
  453. wmb();
  454. pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
  455. pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
  456. wmb();
  457. pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
  458. wmb();
  459. pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
  460. rmb();
  461. for (i = 256;
  462. i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
  463. i--)
  464. ;
  465. break;
  466. case PM2_TYPE_PERMEDIA2V:
  467. pm2v_mnp(clk/2, &m, &n, &p);
  468. WAIT_FIFO(par, 8);
  469. pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8);
  470. pm2v_RDAC_WR(par, PM2VI_RD_CLK0_PRESCALE, m);
  471. pm2v_RDAC_WR(par, PM2VI_RD_CLK0_FEEDBACK, n);
  472. pm2v_RDAC_WR(par, PM2VI_RD_CLK0_POSTSCALE, p);
  473. pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
  474. break;
  475. }
  476. }
  477. static void set_video(struct pm2fb_par* p, u32 video) {
  478. u32 tmp;
  479. u32 vsync;
  480. vsync = video;
  481. DPRINTK("video = 0x%x\n", video);
  482. /*
  483. * The hardware cursor needs +vsync to recognise vert retrace.
  484. * We may not be using the hardware cursor, but the X Glint
  485. * driver may well. So always set +hsync/+vsync and then set
  486. * the RAMDAC to invert the sync if necessary.
  487. */
  488. vsync &= ~(PM2F_HSYNC_MASK|PM2F_VSYNC_MASK);
  489. vsync |= PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH;
  490. WAIT_FIFO(p, 5);
  491. pm2_WR(p, PM2R_VIDEO_CONTROL, vsync);
  492. switch (p->type) {
  493. case PM2_TYPE_PERMEDIA2:
  494. tmp = PM2F_RD_PALETTE_WIDTH_8;
  495. if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
  496. tmp |= 4; /* invert hsync */
  497. if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
  498. tmp |= 8; /* invert vsync */
  499. pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, tmp);
  500. break;
  501. case PM2_TYPE_PERMEDIA2V:
  502. tmp = 0;
  503. if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
  504. tmp |= 1; /* invert hsync */
  505. if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
  506. tmp |= 4; /* invert vsync */
  507. pm2v_RDAC_WR(p, PM2VI_RD_SYNC_CONTROL, tmp);
  508. pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1);
  509. break;
  510. }
  511. }
  512. /*
  513. *
  514. */
  515. /**
  516. * pm2fb_check_var - Optional function. Validates a var passed in.
  517. * @var: frame buffer variable screen structure
  518. * @info: frame buffer structure that represents a single frame buffer
  519. *
  520. * Checks to see if the hardware supports the state requested by
  521. * var passed in.
  522. *
  523. * Returns negative errno on error, or zero on success.
  524. */
  525. static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  526. {
  527. u32 lpitch;
  528. if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
  529. var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
  530. DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
  531. return -EINVAL;
  532. }
  533. if (var->xres != var->xres_virtual) {
  534. DPRINTK("virtual x resolution != physical x resolution not supported\n");
  535. return -EINVAL;
  536. }
  537. if (var->yres > var->yres_virtual) {
  538. DPRINTK("virtual y resolution < physical y resolution not possible\n");
  539. return -EINVAL;
  540. }
  541. if (var->xoffset) {
  542. DPRINTK("xoffset not supported\n");
  543. return -EINVAL;
  544. }
  545. if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  546. DPRINTK("interlace not supported\n");
  547. return -EINVAL;
  548. }
  549. var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
  550. lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
  551. if (var->xres < 320 || var->xres > 1600) {
  552. DPRINTK("width not supported: %u\n", var->xres);
  553. return -EINVAL;
  554. }
  555. if (var->yres < 200 || var->yres > 1200) {
  556. DPRINTK("height not supported: %u\n", var->yres);
  557. return -EINVAL;
  558. }
  559. if (lpitch * var->yres_virtual > info->fix.smem_len) {
  560. DPRINTK("no memory for screen (%ux%ux%u)\n",
  561. var->xres, var->yres_virtual, var->bits_per_pixel);
  562. return -EINVAL;
  563. }
  564. if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
  565. DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
  566. return -EINVAL;
  567. }
  568. switch(var->bits_per_pixel) {
  569. case 8:
  570. var->red.length = var->green.length = var->blue.length = 8;
  571. break;
  572. case 16:
  573. var->red.offset = 11;
  574. var->red.length = 5;
  575. var->green.offset = 5;
  576. var->green.length = 6;
  577. var->blue.offset = 0;
  578. var->blue.length = 5;
  579. break;
  580. case 32:
  581. var->transp.offset = 24;
  582. var->transp.length = 8;
  583. var->red.offset = 16;
  584. var->green.offset = 8;
  585. var->blue.offset = 0;
  586. var->red.length = var->green.length = var->blue.length = 8;
  587. break;
  588. case 24:
  589. #ifdef __BIG_ENDIAN
  590. var->red.offset = 0;
  591. var->blue.offset = 16;
  592. #else
  593. var->red.offset = 16;
  594. var->blue.offset = 0;
  595. #endif
  596. var->green.offset = 8;
  597. var->red.length = var->green.length = var->blue.length = 8;
  598. break;
  599. }
  600. var->height = var->width = -1;
  601. var->accel_flags = 0; /* Can't mmap if this is on */
  602. DPRINTK("Checking graphics mode at %dx%d depth %d\n",
  603. var->xres, var->yres, var->bits_per_pixel);
  604. return 0;
  605. }
  606. /**
  607. * pm2fb_set_par - Alters the hardware state.
  608. * @info: frame buffer structure that represents a single frame buffer
  609. *
  610. * Using the fb_var_screeninfo in fb_info we set the resolution of the
  611. * this particular framebuffer.
  612. */
  613. static int pm2fb_set_par(struct fb_info *info)
  614. {
  615. struct pm2fb_par *par = info->par;
  616. u32 pixclock;
  617. u32 width, height, depth;
  618. u32 hsstart, hsend, hbend, htotal;
  619. u32 vsstart, vsend, vbend, vtotal;
  620. u32 stride;
  621. u32 base;
  622. u32 video = 0;
  623. u32 clrmode = PM2F_RD_COLOR_MODE_RGB | PM2F_RD_GUI_ACTIVE;
  624. u32 txtmap = 0;
  625. u32 pixsize = 0;
  626. u32 clrformat = 0;
  627. u32 xres;
  628. int data64;
  629. reset_card(par);
  630. reset_config(par);
  631. clear_palette(par);
  632. if ( par->memclock )
  633. set_memclock(par, par->memclock);
  634. width = (info->var.xres_virtual + 7) & ~7;
  635. height = info->var.yres_virtual;
  636. depth = (info->var.bits_per_pixel + 7) & ~7;
  637. depth = (depth > 32) ? 32 : depth;
  638. data64 = depth > 8 || par->type == PM2_TYPE_PERMEDIA2V;
  639. xres = (info->var.xres + 31) & ~31;
  640. pixclock = PICOS2KHZ(info->var.pixclock);
  641. if (pixclock > PM2_MAX_PIXCLOCK) {
  642. DPRINTK("pixclock too high (%uKHz)\n", pixclock);
  643. return -EINVAL;
  644. }
  645. hsstart = to3264(info->var.right_margin, depth, data64);
  646. hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
  647. hbend = hsend + to3264(info->var.left_margin, depth, data64);
  648. htotal = to3264(xres, depth, data64) + hbend - 1;
  649. vsstart = (info->var.lower_margin)
  650. ? info->var.lower_margin - 1
  651. : 0; /* FIXME! */
  652. vsend = info->var.lower_margin + info->var.vsync_len - 1;
  653. vbend = info->var.lower_margin + info->var.vsync_len + info->var.upper_margin;
  654. vtotal = info->var.yres + vbend - 1;
  655. stride = to3264(width, depth, 1);
  656. base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
  657. if (data64)
  658. video |= PM2F_DATA_64_ENABLE;
  659. if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
  660. if (lowhsync) {
  661. DPRINTK("ignoring +hsync, using -hsync.\n");
  662. video |= PM2F_HSYNC_ACT_LOW;
  663. } else
  664. video |= PM2F_HSYNC_ACT_HIGH;
  665. }
  666. else
  667. video |= PM2F_HSYNC_ACT_LOW;
  668. if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) {
  669. if (lowvsync) {
  670. DPRINTK("ignoring +vsync, using -vsync.\n");
  671. video |= PM2F_VSYNC_ACT_LOW;
  672. } else
  673. video |= PM2F_VSYNC_ACT_HIGH;
  674. }
  675. else
  676. video |= PM2F_VSYNC_ACT_LOW;
  677. if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) {
  678. DPRINTK("interlaced not supported\n");
  679. return -EINVAL;
  680. }
  681. if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
  682. video |= PM2F_LINE_DOUBLE;
  683. if ((info->var.activate & FB_ACTIVATE_MASK)==FB_ACTIVATE_NOW)
  684. video |= PM2F_VIDEO_ENABLE;
  685. par->video = video;
  686. info->fix.visual =
  687. (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
  688. info->fix.line_length = info->var.xres * depth / 8;
  689. info->cmap.len = 256;
  690. /*
  691. * Settings calculated. Now write them out.
  692. */
  693. if (par->type == PM2_TYPE_PERMEDIA2V) {
  694. WAIT_FIFO(par, 1);
  695. pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
  696. }
  697. set_aperture(par, depth);
  698. mb();
  699. WAIT_FIFO(par, 19);
  700. pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
  701. ( depth == 8 ) ? 0 : PM2F_COLOR_KEY_TEST_OFF);
  702. switch (depth) {
  703. case 8:
  704. pm2_WR(par, PM2R_FB_READ_PIXEL, 0);
  705. clrformat = 0x0e;
  706. break;
  707. case 16:
  708. pm2_WR(par, PM2R_FB_READ_PIXEL, 1);
  709. clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB565;
  710. txtmap = PM2F_TEXTEL_SIZE_16;
  711. pixsize = 1;
  712. clrformat = 0x70;
  713. break;
  714. case 32:
  715. pm2_WR(par, PM2R_FB_READ_PIXEL, 2);
  716. clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGBA8888;
  717. txtmap = PM2F_TEXTEL_SIZE_32;
  718. pixsize = 2;
  719. clrformat = 0x20;
  720. break;
  721. case 24:
  722. pm2_WR(par, PM2R_FB_READ_PIXEL, 4);
  723. clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB888;
  724. txtmap = PM2F_TEXTEL_SIZE_24;
  725. pixsize = 4;
  726. clrformat = 0x20;
  727. break;
  728. }
  729. pm2_WR(par, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
  730. pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
  731. pm2_WR(par, PM2R_LB_READ_MODE, partprod(xres));
  732. pm2_WR(par, PM2R_TEXTURE_MAP_FORMAT, txtmap | partprod(xres));
  733. pm2_WR(par, PM2R_H_TOTAL, htotal);
  734. pm2_WR(par, PM2R_HS_START, hsstart);
  735. pm2_WR(par, PM2R_HS_END, hsend);
  736. pm2_WR(par, PM2R_HG_END, hbend);
  737. pm2_WR(par, PM2R_HB_END, hbend);
  738. pm2_WR(par, PM2R_V_TOTAL, vtotal);
  739. pm2_WR(par, PM2R_VS_START, vsstart);
  740. pm2_WR(par, PM2R_VS_END, vsend);
  741. pm2_WR(par, PM2R_VB_END, vbend);
  742. pm2_WR(par, PM2R_SCREEN_STRIDE, stride);
  743. wmb();
  744. pm2_WR(par, PM2R_WINDOW_ORIGIN, 0);
  745. pm2_WR(par, PM2R_SCREEN_SIZE, (height << 16) | width);
  746. pm2_WR(par, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
  747. wmb();
  748. pm2_WR(par, PM2R_SCREEN_BASE, base);
  749. wmb();
  750. set_video(par, video);
  751. WAIT_FIFO(par, 4);
  752. switch (par->type) {
  753. case PM2_TYPE_PERMEDIA2:
  754. pm2_RDAC_WR(par, PM2I_RD_COLOR_MODE, clrmode);
  755. break;
  756. case PM2_TYPE_PERMEDIA2V:
  757. pm2v_RDAC_WR(par, PM2VI_RD_PIXEL_SIZE, pixsize);
  758. pm2v_RDAC_WR(par, PM2VI_RD_COLOR_FORMAT, clrformat);
  759. break;
  760. }
  761. set_pixclock(par, pixclock);
  762. DPRINTK("Setting graphics mode at %dx%d depth %d\n",
  763. info->var.xres, info->var.yres, info->var.bits_per_pixel);
  764. return 0;
  765. }
  766. /**
  767. * pm2fb_setcolreg - Sets a color register.
  768. * @regno: boolean, 0 copy local, 1 get_user() function
  769. * @red: frame buffer colormap structure
  770. * @green: The green value which can be up to 16 bits wide
  771. * @blue: The blue value which can be up to 16 bits wide.
  772. * @transp: If supported the alpha value which can be up to 16 bits wide.
  773. * @info: frame buffer info structure
  774. *
  775. * Set a single color register. The values supplied have a 16 bit
  776. * magnitude which needs to be scaled in this function for the hardware.
  777. * Pretty much a direct lift from tdfxfb.c.
  778. *
  779. * Returns negative errno on error, or zero on success.
  780. */
  781. static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
  782. unsigned blue, unsigned transp,
  783. struct fb_info *info)
  784. {
  785. struct pm2fb_par *par = info->par;
  786. if (regno >= info->cmap.len) /* no. of hw registers */
  787. return 1;
  788. /*
  789. * Program hardware... do anything you want with transp
  790. */
  791. /* grayscale works only partially under directcolor */
  792. if (info->var.grayscale) {
  793. /* grayscale = 0.30*R + 0.59*G + 0.11*B */
  794. red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
  795. }
  796. /* Directcolor:
  797. * var->{color}.offset contains start of bitfield
  798. * var->{color}.length contains length of bitfield
  799. * {hardwarespecific} contains width of DAC
  800. * cmap[X] is programmed to
  801. * (X << red.offset) | (X << green.offset) | (X << blue.offset)
  802. * RAMDAC[X] is programmed to (red, green, blue)
  803. *
  804. * Pseudocolor:
  805. * uses offset = 0 && length = DAC register width.
  806. * var->{color}.offset is 0
  807. * var->{color}.length contains widht of DAC
  808. * cmap is not used
  809. * DAC[X] is programmed to (red, green, blue)
  810. * Truecolor:
  811. * does not use RAMDAC (usually has 3 of them).
  812. * var->{color}.offset contains start of bitfield
  813. * var->{color}.length contains length of bitfield
  814. * cmap is programmed to
  815. * (red << red.offset) | (green << green.offset) |
  816. * (blue << blue.offset) | (transp << transp.offset)
  817. * RAMDAC does not exist
  818. */
  819. #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
  820. switch (info->fix.visual) {
  821. case FB_VISUAL_TRUECOLOR:
  822. case FB_VISUAL_PSEUDOCOLOR:
  823. red = CNVT_TOHW(red, info->var.red.length);
  824. green = CNVT_TOHW(green, info->var.green.length);
  825. blue = CNVT_TOHW(blue, info->var.blue.length);
  826. transp = CNVT_TOHW(transp, info->var.transp.length);
  827. break;
  828. case FB_VISUAL_DIRECTCOLOR:
  829. /* example here assumes 8 bit DAC. Might be different
  830. * for your hardware */
  831. red = CNVT_TOHW(red, 8);
  832. green = CNVT_TOHW(green, 8);
  833. blue = CNVT_TOHW(blue, 8);
  834. /* hey, there is bug in transp handling... */
  835. transp = CNVT_TOHW(transp, 8);
  836. break;
  837. }
  838. #undef CNVT_TOHW
  839. /* Truecolor has hardware independent palette */
  840. if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
  841. u32 v;
  842. if (regno >= 16)
  843. return 1;
  844. v = (red << info->var.red.offset) |
  845. (green << info->var.green.offset) |
  846. (blue << info->var.blue.offset) |
  847. (transp << info->var.transp.offset);
  848. switch (info->var.bits_per_pixel) {
  849. case 8:
  850. break;
  851. case 16:
  852. case 24:
  853. case 32:
  854. par->palette[regno] = v;
  855. break;
  856. }
  857. return 0;
  858. }
  859. else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
  860. set_color(par, regno, red, green, blue);
  861. return 0;
  862. }
  863. /**
  864. * pm2fb_pan_display - Pans the display.
  865. * @var: frame buffer variable screen structure
  866. * @info: frame buffer structure that represents a single frame buffer
  867. *
  868. * Pan (or wrap, depending on the `vmode' field) the display using the
  869. * `xoffset' and `yoffset' fields of the `var' structure.
  870. * If the values don't fit, return -EINVAL.
  871. *
  872. * Returns negative errno on error, or zero on success.
  873. *
  874. */
  875. static int pm2fb_pan_display(struct fb_var_screeninfo *var,
  876. struct fb_info *info)
  877. {
  878. struct pm2fb_par *p = info->par;
  879. u32 base;
  880. u32 depth;
  881. u32 xres;
  882. xres = (var->xres + 31) & ~31;
  883. depth = (var->bits_per_pixel + 7) & ~7;
  884. depth = (depth > 32) ? 32 : depth;
  885. base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
  886. WAIT_FIFO(p, 1);
  887. pm2_WR(p, PM2R_SCREEN_BASE, base);
  888. return 0;
  889. }
  890. /**
  891. * pm2fb_blank - Blanks the display.
  892. * @blank_mode: the blank mode we want.
  893. * @info: frame buffer structure that represents a single frame buffer
  894. *
  895. * Blank the screen if blank_mode != 0, else unblank. Return 0 if
  896. * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
  897. * video mode which doesn't support it. Implements VESA suspend
  898. * and powerdown modes on hardware that supports disabling hsync/vsync:
  899. * blank_mode == 2: suspend vsync
  900. * blank_mode == 3: suspend hsync
  901. * blank_mode == 4: powerdown
  902. *
  903. * Returns negative errno on error, or zero on success.
  904. *
  905. */
  906. static int pm2fb_blank(int blank_mode, struct fb_info *info)
  907. {
  908. struct pm2fb_par *par = info->par;
  909. u32 video = par->video;
  910. DPRINTK("blank_mode %d\n", blank_mode);
  911. switch (blank_mode) {
  912. case FB_BLANK_UNBLANK:
  913. /* Screen: On */
  914. video |= PM2F_VIDEO_ENABLE;
  915. break;
  916. case FB_BLANK_NORMAL:
  917. /* Screen: Off */
  918. video &= ~PM2F_VIDEO_ENABLE;
  919. break;
  920. case FB_BLANK_VSYNC_SUSPEND:
  921. /* VSync: Off */
  922. video &= ~(PM2F_VSYNC_MASK | PM2F_BLANK_LOW );
  923. break;
  924. case FB_BLANK_HSYNC_SUSPEND:
  925. /* HSync: Off */
  926. video &= ~(PM2F_HSYNC_MASK | PM2F_BLANK_LOW );
  927. break;
  928. case FB_BLANK_POWERDOWN:
  929. /* HSync: Off, VSync: Off */
  930. video &= ~(PM2F_VSYNC_MASK | PM2F_HSYNC_MASK| PM2F_BLANK_LOW);
  931. break;
  932. }
  933. set_video(par, video);
  934. return 0;
  935. }
  936. /* ------------ Hardware Independent Functions ------------ */
  937. /*
  938. * Frame buffer operations
  939. */
  940. static struct fb_ops pm2fb_ops = {
  941. .owner = THIS_MODULE,
  942. .fb_check_var = pm2fb_check_var,
  943. .fb_set_par = pm2fb_set_par,
  944. .fb_setcolreg = pm2fb_setcolreg,
  945. .fb_blank = pm2fb_blank,
  946. .fb_pan_display = pm2fb_pan_display,
  947. .fb_fillrect = cfb_fillrect,
  948. .fb_copyarea = cfb_copyarea,
  949. .fb_imageblit = cfb_imageblit,
  950. };
  951. /*
  952. * PCI stuff
  953. */
  954. /**
  955. * Device initialisation
  956. *
  957. * Initialise and allocate resource for PCI device.
  958. *
  959. * @param pdev PCI device.
  960. * @param id PCI device ID.
  961. */
  962. static int __devinit pm2fb_probe(struct pci_dev *pdev,
  963. const struct pci_device_id *id)
  964. {
  965. struct pm2fb_par *default_par;
  966. struct fb_info *info;
  967. int err, err_retval = -ENXIO;
  968. err = pci_enable_device(pdev);
  969. if ( err ) {
  970. printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);
  971. return err;
  972. }
  973. info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
  974. if ( !info )
  975. return -ENOMEM;
  976. default_par = info->par;
  977. switch (pdev->device) {
  978. case PCI_DEVICE_ID_TI_TVP4020:
  979. strcpy(pm2fb_fix.id, "TVP4020");
  980. default_par->type = PM2_TYPE_PERMEDIA2;
  981. break;
  982. case PCI_DEVICE_ID_3DLABS_PERMEDIA2:
  983. strcpy(pm2fb_fix.id, "Permedia2");
  984. default_par->type = PM2_TYPE_PERMEDIA2;
  985. break;
  986. case PCI_DEVICE_ID_3DLABS_PERMEDIA2V:
  987. strcpy(pm2fb_fix.id, "Permedia2v");
  988. default_par->type = PM2_TYPE_PERMEDIA2V;
  989. break;
  990. }
  991. pm2fb_fix.mmio_start = pci_resource_start(pdev, 0);
  992. pm2fb_fix.mmio_len = PM2_REGS_SIZE;
  993. #if defined(__BIG_ENDIAN)
  994. /*
  995. * PM2 has a 64k register file, mapped twice in 128k. Lower
  996. * map is little-endian, upper map is big-endian.
  997. */
  998. pm2fb_fix.mmio_start += PM2_REGS_SIZE;
  999. DPRINTK("Adjusting register base for big-endian.\n");
  1000. #endif
  1001. DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
  1002. /* Registers - request region and map it. */
  1003. if ( !request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
  1004. "pm2fb regbase") ) {
  1005. printk(KERN_WARNING "pm2fb: Can't reserve regbase.\n");
  1006. goto err_exit_neither;
  1007. }
  1008. default_par->v_regs =
  1009. ioremap_nocache(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
  1010. if ( !default_par->v_regs ) {
  1011. printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n",
  1012. pm2fb_fix.id);
  1013. release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
  1014. goto err_exit_neither;
  1015. }
  1016. /* Stash away memory register info for use when we reset the board */
  1017. default_par->mem_control = pm2_RD(default_par, PM2R_MEM_CONTROL);
  1018. default_par->boot_address = pm2_RD(default_par, PM2R_BOOT_ADDRESS);
  1019. default_par->mem_config = pm2_RD(default_par, PM2R_MEM_CONFIG);
  1020. DPRINTK("MemControl 0x%x BootAddress 0x%x MemConfig 0x%x\n",
  1021. default_par->mem_control, default_par->boot_address,
  1022. default_par->mem_config);
  1023. if(default_par->mem_control == 0 &&
  1024. default_par->boot_address == 0x31 &&
  1025. default_par->mem_config == 0x259fffff &&
  1026. pdev->subsystem_vendor == 0x1048 &&
  1027. pdev->subsystem_device == 0x0a31) {
  1028. DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
  1029. pdev->subsystem_vendor, pdev->subsystem_device);
  1030. DPRINTK("We have not been initialized by VGA BIOS "
  1031. "and are running on an Elsa Winner 2000 Office\n");
  1032. DPRINTK("Initializing card timings manually...\n");
  1033. default_par->mem_control=0;
  1034. default_par->boot_address=0x20;
  1035. default_par->mem_config=0xe6002021;
  1036. default_par->memclock=100000;
  1037. }
  1038. /* Now work out how big lfb is going to be. */
  1039. switch(default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
  1040. case PM2F_MEM_BANKS_1:
  1041. default_par->fb_size=0x200000;
  1042. break;
  1043. case PM2F_MEM_BANKS_2:
  1044. default_par->fb_size=0x400000;
  1045. break;
  1046. case PM2F_MEM_BANKS_3:
  1047. default_par->fb_size=0x600000;
  1048. break;
  1049. case PM2F_MEM_BANKS_4:
  1050. default_par->fb_size=0x800000;
  1051. break;
  1052. }
  1053. default_par->memclock = CVPPC_MEMCLOCK;
  1054. pm2fb_fix.smem_start = pci_resource_start(pdev, 1);
  1055. pm2fb_fix.smem_len = default_par->fb_size;
  1056. /* Linear frame buffer - request region and map it. */
  1057. if ( !request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
  1058. "pm2fb smem") ) {
  1059. printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");
  1060. goto err_exit_mmio;
  1061. }
  1062. info->screen_base = default_par->v_fb =
  1063. ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
  1064. if ( !default_par->v_fb ) {
  1065. printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");
  1066. release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
  1067. goto err_exit_mmio;
  1068. }
  1069. info->fbops = &pm2fb_ops;
  1070. info->fix = pm2fb_fix;
  1071. info->pseudo_palette = default_par->palette;
  1072. info->flags = FBINFO_DEFAULT |
  1073. FBINFO_HWACCEL_YPAN;
  1074. if (!mode)
  1075. mode = "640x480@60";
  1076. err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8);
  1077. if (!err || err == 4)
  1078. info->var = pm2fb_var;
  1079. if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
  1080. goto err_exit_all;
  1081. if (register_framebuffer(info) < 0)
  1082. goto err_exit_both;
  1083. printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n",
  1084. info->node, info->fix.id, default_par->fb_size / 1024);
  1085. /*
  1086. * Our driver data
  1087. */
  1088. pci_set_drvdata(pdev, info);
  1089. return 0;
  1090. err_exit_all:
  1091. fb_dealloc_cmap(&info->cmap);
  1092. err_exit_both:
  1093. iounmap(info->screen_base);
  1094. release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
  1095. err_exit_mmio:
  1096. iounmap(default_par->v_regs);
  1097. release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
  1098. err_exit_neither:
  1099. framebuffer_release(info);
  1100. return err_retval;
  1101. }
  1102. /**
  1103. * Device removal.
  1104. *
  1105. * Release all device resources.
  1106. *
  1107. * @param pdev PCI device to clean up.
  1108. */
  1109. static void __devexit pm2fb_remove(struct pci_dev *pdev)
  1110. {
  1111. struct fb_info* info = pci_get_drvdata(pdev);
  1112. struct fb_fix_screeninfo* fix = &info->fix;
  1113. struct pm2fb_par *par = info->par;
  1114. unregister_framebuffer(info);
  1115. iounmap(info->screen_base);
  1116. release_mem_region(fix->smem_start, fix->smem_len);
  1117. iounmap(par->v_regs);
  1118. release_mem_region(fix->mmio_start, fix->mmio_len);
  1119. pci_set_drvdata(pdev, NULL);
  1120. kfree(info);
  1121. }
  1122. static struct pci_device_id pm2fb_id_table[] = {
  1123. { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,
  1124. PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
  1125. 0xff0000, 0 },
  1126. { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,
  1127. PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
  1128. 0xff0000, 0 },
  1129. { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
  1130. PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
  1131. 0xff0000, 0 },
  1132. { 0, }
  1133. };
  1134. static struct pci_driver pm2fb_driver = {
  1135. .name = "pm2fb",
  1136. .id_table = pm2fb_id_table,
  1137. .probe = pm2fb_probe,
  1138. .remove = __devexit_p(pm2fb_remove),
  1139. };
  1140. MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
  1141. #ifndef MODULE
  1142. /**
  1143. * Parse user speficied options.
  1144. *
  1145. * This is, comma-separated options following `video=pm2fb:'.
  1146. */
  1147. static int __init pm2fb_setup(char *options)
  1148. {
  1149. char* this_opt;
  1150. if (!options || !*options)
  1151. return 0;
  1152. while ((this_opt = strsep(&options, ",")) != NULL) {
  1153. if (!*this_opt)
  1154. continue;
  1155. if(!strcmp(this_opt, "lowhsync")) {
  1156. lowhsync = 1;
  1157. } else if(!strcmp(this_opt, "lowvsync")) {
  1158. lowvsync = 1;
  1159. } else {
  1160. mode = this_opt;
  1161. }
  1162. }
  1163. return 0;
  1164. }
  1165. #endif
  1166. static int __init pm2fb_init(void)
  1167. {
  1168. #ifndef MODULE
  1169. char *option = NULL;
  1170. if (fb_get_options("pm2fb", &option))
  1171. return -ENODEV;
  1172. pm2fb_setup(option);
  1173. #endif
  1174. return pci_register_driver(&pm2fb_driver);
  1175. }
  1176. module_init(pm2fb_init);
  1177. #ifdef MODULE
  1178. /*
  1179. * Cleanup
  1180. */
  1181. static void __exit pm2fb_exit(void)
  1182. {
  1183. pci_unregister_driver(&pm2fb_driver);
  1184. }
  1185. #endif
  1186. #ifdef MODULE
  1187. module_exit(pm2fb_exit);
  1188. module_param(mode, charp, 0);
  1189. MODULE_PARM_DESC(mode, "Preferred video mode e.g. '648x480-8@60'");
  1190. module_param(lowhsync, bool, 0);
  1191. MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode");
  1192. module_param(lowvsync, bool, 0);
  1193. MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode");
  1194. MODULE_AUTHOR("Jim Hague <jim.hague@acm.org>");
  1195. MODULE_DESCRIPTION("Permedia2 framebuffer device driver");
  1196. MODULE_LICENSE("GPL");
  1197. #endif