leofb.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:21k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $
  2.  * leofb.c: Leo (ZX) 24/8bit frame buffer driver
  3.  *
  4.  * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
  5.  * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
  6.  */
  7. #include <linux/module.h>
  8. #include <linux/sched.h>
  9. #include <linux/kernel.h>
  10. #include <linux/errno.h>
  11. #include <linux/string.h>
  12. #include <linux/mm.h>
  13. #include <linux/tty.h>
  14. #include <linux/slab.h>
  15. #include <linux/vmalloc.h>
  16. #include <linux/delay.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/fb.h>
  19. #include <linux/init.h>
  20. #include <linux/selection.h>
  21. #include <video/sbusfb.h>
  22. #include <asm/io.h>
  23. #define LEO_OFF_LC_SS0_KRN 0x00200000UL
  24. #define LEO_OFF_LC_SS0_USR 0x00201000UL
  25. #define LEO_OFF_LC_SS1_KRN 0x01200000UL
  26. #define LEO_OFF_LC_SS1_USR 0x01201000UL
  27. #define LEO_OFF_LD_SS0 0x00400000UL
  28. #define LEO_OFF_LD_SS1 0x01400000UL
  29. #define LEO_OFF_LD_GBL 0x00401000UL
  30. #define LEO_OFF_LX_KRN 0x00600000UL
  31. #define LEO_OFF_LX_CURSOR 0x00601000UL
  32. #define LEO_OFF_SS0 0x00800000UL
  33. #define LEO_OFF_SS1 0x01800000UL
  34. #define LEO_OFF_UNK 0x00602000UL
  35. #define LEO_OFF_UNK2 0x00000000UL
  36. #define LEO_CUR_ENABLE 0x00000080
  37. #define LEO_CUR_UPDATE 0x00000030
  38. #define LEO_CUR_PROGRESS 0x00000006
  39. #define LEO_CUR_UPDATECMAP 0x00000003
  40. #define LEO_CUR_TYPE_MASK 0x00000000
  41. #define LEO_CUR_TYPE_IMAGE 0x00000020
  42. #define LEO_CUR_TYPE_CMAP 0x00000050
  43. struct leo_cursor {
  44. u8 xxx0[16];
  45. volatile u32 cur_type;
  46. volatile u32 cur_misc;
  47. volatile u32 cur_cursxy;
  48. volatile u32 cur_data;
  49. };
  50. #define LEO_KRN_TYPE_CLUT0 0x00001000
  51. #define LEO_KRN_TYPE_CLUT1 0x00001001
  52. #define LEO_KRN_TYPE_CLUT2 0x00001002
  53. #define LEO_KRN_TYPE_WID 0x00001003
  54. #define LEO_KRN_TYPE_UNK 0x00001006
  55. #define LEO_KRN_TYPE_VIDEO 0x00002003
  56. #define LEO_KRN_TYPE_CLUTDATA 0x00004000
  57. #define LEO_KRN_CSR_ENABLE 0x00000008
  58. #define LEO_KRN_CSR_PROGRESS 0x00000004
  59. #define LEO_KRN_CSR_UNK 0x00000002
  60. #define LEO_KRN_CSR_UNK2 0x00000001
  61. struct leo_lx_krn {
  62. volatile u32 krn_type;
  63. volatile u32 krn_csr;
  64. volatile u32 krn_value;
  65. };
  66. struct leo_lc_ss0_krn {
  67. volatile u32  misc;
  68. u8 xxx0[0x800-4];
  69. volatile u32 rev;
  70. };
  71. struct leo_lc_ss0_usr {
  72. volatile u32 csr;
  73. volatile u32 addrspace;
  74. volatile u32  fontmsk;
  75. volatile u32 fontt;
  76. volatile u32 extent;
  77. volatile u32 src;
  78. u32 dst;
  79. volatile u32 copy;
  80. volatile u32 fill;
  81. };
  82. struct leo_lc_ss1_krn {
  83. u8 unknown;
  84. };
  85. struct leo_lc_ss1_usr {
  86. u8 unknown;
  87. };
  88. struct leo_ld {
  89. u8 xxx0[0xe00];
  90. volatile u32 csr;
  91. volatile u32 wid;
  92. volatile u32 wmask;
  93. volatile u32 widclip;
  94. volatile u32 vclipmin;
  95. volatile u32 vclipmax;
  96. volatile u32 pickmin; /* SS1 only */
  97. volatile u32 pickmax; /* SS1 only */
  98. volatile u32 fg;
  99. volatile u32 bg;
  100. volatile u32 src; /* Copy/Scroll (SS0 only) */
  101. volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */
  102. volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */
  103. u32 xxx1[3];
  104. volatile u32 setsem; /* SS1 only */
  105. volatile u32 clrsem; /* SS1 only */
  106. volatile u32 clrpick; /* SS1 only */
  107. volatile u32 clrdat; /* SS1 only */
  108. volatile u32 alpha; /* SS1 only */
  109. u8 xxx2[0x2c];
  110. volatile u32 winbg;
  111. volatile u32 planemask;
  112. volatile u32 rop;
  113. volatile u32 z;
  114. volatile u32 dczf; /* SS1 only */
  115. volatile u32 dczb; /* SS1 only */
  116. volatile u32 dcs; /* SS1 only */
  117. volatile u32 dczs; /* SS1 only */
  118. volatile u32 pickfb; /* SS1 only */
  119. volatile u32 pickbb; /* SS1 only */
  120. volatile u32 dcfc; /* SS1 only */
  121. volatile u32 forcecol; /* SS1 only */
  122. volatile u32 door[8]; /* SS1 only */
  123. volatile u32 pick[5]; /* SS1 only */
  124. };
  125. #define LEO_SS1_MISC_ENABLE 0x00000001
  126. #define LEO_SS1_MISC_STEREO 0x00000002
  127. struct leo_ld_ss1 {
  128. u8 xxx0[0xef4];
  129. volatile u32 ss1_misc;
  130. };
  131. struct leo_ld_gbl {
  132. u8 unknown;
  133. };
  134. static struct sbus_mmap_map leo_mmap_map[] = {
  135. { LEO_SS0_MAP, LEO_OFF_SS0, 0x800000 },
  136. { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, 0x1000 },
  137. { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, 0x1000 },
  138. { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, 0x1000 },
  139. { LEO_SS1_MAP, LEO_OFF_SS1, 0x800000 },
  140. { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, 0x1000 },
  141. { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, 0x1000 },
  142. { LEO_UNK_MAP, LEO_OFF_UNK, 0x1000 },
  143. { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, 0x1000 },
  144. { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, 0x1000 },
  145. { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, 0x1000 },
  146. { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, 0x1000 },
  147. { LEO_UNK2_MAP, LEO_OFF_UNK2, 0x100000 },
  148. { 0, 0, 0    }
  149. };
  150. static void leo_setup(struct display *p)
  151. {
  152. p->next_line = 8192;
  153. p->next_plane = 0;
  154. }
  155. static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
  156.       int height, int width)
  157. {
  158. struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
  159. register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
  160. register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
  161. unsigned long flags;
  162. int x, y, w, h;
  163. int i;
  164. spin_lock_irqsave(&fb->lock, flags);
  165. do {
  166. i = sbus_readl(&us->csr);
  167. } while (i & 0x20000000);
  168. sbus_writel((attr_bgcol_ec(p,conp)<<24), &ss->fg);
  169. if (fontheightlog(p)) {
  170. y = sy << fontheightlog(p); h = height << fontheightlog(p);
  171. } else {
  172. y = sy * fontheight(p); h = height * fontheight(p);
  173. }
  174. if (fontwidthlog(p)) {
  175. x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
  176. } else {
  177. x = sx * fontwidth(p); w = width * fontwidth(p);
  178. }
  179. sbus_writel((w - 1) | ((h - 1) << 11), &us->extent);
  180. sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000,
  181.     &us->fill);
  182. spin_unlock_irqrestore(&fb->lock, flags);
  183. }
  184. static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
  185.      int count, unsigned short *boxes)
  186. {
  187. int i;
  188. register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
  189. register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
  190. unsigned long flags;
  191. spin_lock_irqsave(&fb->lock, flags);
  192. sbus_writel((attr_bgcol(p,s)<<24), &ss->fg);
  193. while (count-- > 0) {
  194. do {
  195. i = sbus_readl(&us->csr);
  196. } while (i & 0x20000000);
  197. sbus_writel((boxes[2] - boxes[0] - 1) | 
  198.     ((boxes[3] - boxes[1] - 1) << 11),
  199.     &us->extent);
  200. sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000,
  201.     &us->fill);
  202. boxes += 4;
  203. }
  204. spin_unlock_irqrestore(&fb->lock, flags);
  205. }
  206. static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
  207. {
  208. struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
  209. register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
  210. register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
  211. unsigned long flags;
  212. int i, x, y;
  213. u8 *fd;
  214. u32 *u;
  215. spin_lock_irqsave(&fb->lock, flags);
  216. if (fontheightlog(p)) {
  217. y = yy << (fontheightlog(p) + 11);
  218. i = (c & p->charmask) << fontheightlog(p);
  219. } else {
  220. y = (yy * fontheight(p)) << 11;
  221. i = (c & p->charmask) * fontheight(p);
  222. }
  223. if (fontwidth(p) <= 8)
  224. fd = p->fontdata + i;
  225. else
  226. fd = p->fontdata + (i << 1);
  227. if (fontwidthlog(p))
  228. x = xx << fontwidthlog(p);
  229. else
  230. x = xx * fontwidth(p);
  231. do {
  232. i = sbus_readl(&us->csr);
  233. } while (i & 0x20000000);
  234. sbus_writel(attr_fgcol(p,c) << 24, &ss->fg);
  235. sbus_writel(attr_bgcol(p,c) << 24, &ss->bg);
  236. sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)),
  237.     &us->fontmsk);
  238. u = ((u32 *)p->screen_base) + y + x;
  239. if (fontwidth(p) <= 8) {
  240. for (i = 0; i < fontheight(p); i++, u += 2048) {
  241. u32 val = *fd++ << 24;
  242. sbus_writel(val, u);
  243. }
  244. } else {
  245. for (i = 0; i < fontheight(p); i++, u += 2048) {
  246. u32 val = *(u16 *)fd << 16;
  247. sbus_writel(val, u);
  248. fd += 2;
  249. }
  250. }
  251. spin_unlock_irqrestore(&fb->lock, flags);
  252. }
  253. static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
  254.       int count, int yy, int xx)
  255. {
  256. struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
  257. register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
  258. register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
  259. unsigned long flags;
  260. int i, x, y;
  261. u8 *fd1, *fd2, *fd3, *fd4;
  262. u16 c;
  263. u32 *u;
  264. spin_lock_irqsave(&fb->lock, flags);
  265. do {
  266. i = sbus_readl(&us->csr);
  267. } while (i & 0x20000000);
  268. c = scr_readw(s);
  269. sbus_writel(attr_fgcol(p, c) << 24, &ss->fg);
  270. sbus_writel(attr_bgcol(p, c) << 24, &ss->bg);
  271. sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
  272. if (fontwidthlog(p))
  273. x = (xx << fontwidthlog(p));
  274. else
  275. x = xx * fontwidth(p);
  276. if (fontheightlog(p))
  277. y = yy << (fontheightlog(p) + 11);
  278. else
  279. y = (yy * fontheight(p)) << 11;
  280. u = ((u32 *)p->screen_base) + y + x;
  281. if (fontwidth(p) <= 8) {
  282. sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk);
  283. x = 4*fontwidth(p) - fontheight(p)*2048;
  284. while (count >= 4) {
  285. count -= 4;
  286. if (fontheightlog(p)) {
  287. fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
  288. fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
  289. fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
  290. fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
  291. } else {
  292. fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
  293. fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
  294. fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
  295. fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
  296. }
  297. if (fontwidth(p) == 8) {
  298. for (i = 0; i < fontheight(p); i++, u += 2048) {
  299. u32 val;
  300. val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
  301. << 8)) << 8)) << 8);
  302. sbus_writel(val, u);
  303. }
  304. u += x;
  305. } else {
  306. for (i = 0; i < fontheight(p); i++, u += 2048) {
  307. u32 val;
  308. val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
  309. << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
  310. sbus_writel(val, u);
  311. }
  312. u += x;
  313. }
  314. }
  315. } else {
  316. sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk);
  317. x = 2*fontwidth(p) - fontheight(p)*2048;
  318. while (count >= 2) {
  319. count -= 2;
  320. if (fontheightlog(p)) {
  321. fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
  322. fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
  323. } else {
  324. fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
  325. fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
  326. }
  327. for (i = 0; i < fontheight(p); i++, u += 2048) {
  328. u32 val;
  329. val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
  330. sbus_writel(val, u);
  331. fd1 += 2; fd2 += 2;
  332. }
  333. u += x;
  334. }
  335. }
  336. sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
  337. x = fontwidth(p) - fontheight(p)*2048;
  338. while (count) {
  339. count--;
  340. if (fontheightlog(p))
  341. i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
  342. else
  343. i = ((scr_readw(s++) & p->charmask) * fontheight(p));
  344. if (fontwidth(p) <= 8) {
  345. fd1 = p->fontdata + i;
  346. for (i = 0; i < fontheight(p); i++, u += 2048) {
  347. u32 val = *fd1++ << 24;
  348. sbus_writel(val, u);
  349. }
  350. } else {
  351. fd1 = p->fontdata + (i << 1);
  352. for (i = 0; i < fontheight(p); i++, u += 2048) {
  353. u32 val = *(u16 *)fd1 << 16;
  354. sbus_writel(val, u);
  355. fd1 += 2;
  356. }
  357. }
  358. u += x;
  359. }
  360. spin_unlock_irqrestore(&fb->lock, flags);
  361. }
  362. static void leo_revc(struct display *p, int xx, int yy)
  363. {
  364. /* Not used if hw cursor */
  365. }
  366. static int leo_wait (struct leo_lx_krn *lx_krn)
  367. {
  368. int i;
  369. for (i = 0; (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
  370. udelay (1); /* Busy wait at most 0.3 sec */
  371. if (i == 300000)
  372. return -EFAULT; /* Timed out - should we print some message? */
  373. return 0;
  374. }
  375. static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
  376. {
  377.         struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
  378. unsigned long flags;
  379. u32 tmp;
  380. int i;
  381. spin_lock_irqsave(&fb->lock, flags);
  382. sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
  383. i = leo_wait (lx_krn);
  384. if (i)
  385. goto out;
  386. sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
  387. for (i = 0; i < 256; i++) {
  388. u32 val;
  389. val = fb->color_map CM(i,0) |
  390. (fb->color_map CM(i,1) << 8) |
  391. (fb->color_map CM(i,2) << 16);
  392. sbus_writel(val, &lx_krn->krn_value); /* Throw colors there :)) */
  393. }
  394. sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
  395. tmp = sbus_readl(&lx_krn->krn_csr);
  396. tmp |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
  397. sbus_writel(tmp, &lx_krn->krn_csr);
  398. out:
  399. spin_unlock_irqrestore(&fb->lock, flags);
  400. }
  401. static void leo_restore_palette (struct fb_info_sbusfb *fb)
  402. {
  403. u32 tmp;
  404. unsigned long flags;
  405. spin_lock_irqsave(&fb->lock, flags);
  406. tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
  407. tmp &= ~(LEO_SS1_MISC_ENABLE);
  408. sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
  409. spin_unlock_irqrestore(&fb->lock, flags);
  410. }
  411. static struct display_switch leo_dispsw __initdata = {
  412. setup: leo_setup,
  413. bmove: fbcon_redraw_bmove,
  414. clear: leo_clear,
  415. putc: leo_putc,
  416. putcs: leo_putcs,
  417. revc: leo_revc, 
  418. fontwidthmask: FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
  419. };
  420. static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
  421. {
  422.         struct leo_cursor *l = fb->s.leo.cursor;
  423. unsigned long flags;
  424. int i;
  425. spin_lock_irqsave(&fb->lock, flags);
  426. for (i = 0; (sbus_readl(&l->cur_misc) & LEO_CUR_PROGRESS) && i < 300000; i++)
  427. udelay (1); /* Busy wait at most 0.3 sec */
  428. if (i == 300000)
  429. goto out; /* Timed out - should we print some message? */
  430. sbus_writel(LEO_CUR_TYPE_CMAP, &l->cur_type);
  431. sbus_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &l->cur_data);
  432. sbus_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &l->cur_data);
  433. sbus_writel(LEO_CUR_UPDATECMAP, &l->cur_misc);
  434. out:
  435. spin_unlock_irqrestore(&fb->lock, flags);
  436. }
  437. /* Set cursor shape */
  438. static void leo_setcurshape (struct fb_info_sbusfb *fb)
  439. {
  440. int i, j, k;
  441. u32 m, n, mask;
  442. struct leo_cursor *l = fb->s.leo.cursor;
  443. u32 tmp;
  444. unsigned long flags;
  445. spin_lock_irqsave(&fb->lock, flags);
  446. tmp = sbus_readl(&l->cur_misc);
  447. tmp &= ~LEO_CUR_ENABLE;
  448. sbus_writel(tmp, &l->cur_misc);
  449. for (k = 0; k < 2; k ++) {
  450. sbus_writel((k * LEO_CUR_TYPE_IMAGE), &l->cur_type);
  451. for (i = 0; i < 32; i++) {
  452. mask = 0;
  453. m = fb->cursor.bits[k][i];
  454. /* mask = m with reversed bit order */
  455. for (j = 0, n = 1; j < 32; j++, n <<= 1)
  456. if (m & n)
  457. mask |= (0x80000000 >> j);
  458. sbus_writel(mask, &l->cur_data);
  459. }
  460. }
  461. tmp = sbus_readl(&l->cur_misc);
  462. tmp |= LEO_CUR_ENABLE;
  463. sbus_writel(tmp, &l->cur_misc);
  464. spin_unlock_irqrestore(&fb->lock, flags);
  465. }
  466. /* Load cursor information */
  467. static void leo_setcursor (struct fb_info_sbusfb *fb)
  468. {
  469. struct cg_cursor *c = &fb->cursor;
  470. struct leo_cursor *l = fb->s.leo.cursor;
  471. unsigned long flags;
  472. u32 tmp;
  473. spin_lock_irqsave(&fb->lock, flags);
  474. tmp = sbus_readl(&l->cur_misc);
  475. tmp &= ~LEO_CUR_ENABLE;
  476. sbus_writel(tmp, &l->cur_misc);
  477. sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) |
  478.     (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11),
  479.     &l->cur_cursxy);
  480. tmp = sbus_readl(&l->cur_misc);
  481. tmp |= LEO_CUR_UPDATE;
  482. if (c->enable)
  483. tmp |= LEO_CUR_ENABLE;
  484. sbus_writel(tmp, &l->cur_misc);
  485. spin_unlock_irqrestore(&fb->lock, flags);
  486. }
  487. static void leo_blank (struct fb_info_sbusfb *fb)
  488. {
  489. unsigned long flags;
  490. u32 tmp;
  491. spin_lock_irqsave(&fb->lock, flags);
  492. sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
  493. tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
  494. tmp &= ~LEO_KRN_CSR_ENABLE;
  495. sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
  496. spin_unlock_irqrestore(&fb->lock, flags);
  497. }
  498. static void leo_unblank (struct fb_info_sbusfb *fb)
  499. {
  500. unsigned long flags;
  501. u32 tmp;
  502. spin_lock_irqsave(&fb->lock, flags);
  503. sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
  504. tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
  505. if (!(tmp & LEO_KRN_CSR_ENABLE)) {
  506. tmp |= LEO_KRN_CSR_ENABLE;
  507. sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
  508. }
  509. spin_unlock_irqrestore(&fb->lock, flags);
  510. }
  511. static int __init
  512. leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)
  513. {
  514. struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
  515. struct fb_wid_item *wi;
  516. int i, j;
  517. sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
  518. i = leo_wait (lx_krn);
  519. if (i)
  520. return i;
  521. for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
  522. switch (wi->wi_type) {
  523. case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break;
  524. case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break;
  525. default: return -EINVAL;
  526. }
  527. sbus_writel(0x5800 + j, &lx_krn->krn_type);
  528. sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
  529. }
  530. sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
  531. sbus_writel(3, &lx_krn->krn_csr);
  532. return 0;
  533. }
  534. static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
  535. {
  536. p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
  537. }
  538. static void leo_switch_from_graph (struct fb_info_sbusfb *fb)
  539. {
  540. register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
  541. register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
  542. unsigned long flags;
  543. spin_lock_irqsave(&fb->lock, flags);
  544. sbus_writel(0xffffffff, &ss->wid);
  545. sbus_writel(0xffff, &ss->wmask);
  546. sbus_writel(0, &ss->vclipmin);
  547. sbus_writel(fb->s.leo.extent, &ss->vclipmax);
  548. sbus_writel(0xff000000, &ss->planemask);
  549. sbus_writel(0x310850, &ss->rop);
  550. sbus_writel(0, &ss->widclip);
  551. sbus_writel(4, &us->addrspace);
  552. sbus_writel(0, &us->fontt);
  553. spin_unlock_irqrestore(&fb->lock, flags);
  554. }
  555. static int __init leo_rasterimg (struct fb_info *info, int start)
  556. {
  557. struct fb_info_sbusfb *fb = sbusfbinfo(info);
  558. register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
  559. register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
  560. if (start) {
  561. sbus_writel(1, &ss->wid);
  562. sbus_writel(0xffffff, &ss->planemask); 
  563. sbus_writel(0x310b90, &ss->rop);
  564. sbus_writel(0, &us->addrspace);
  565. } else {
  566. sbus_writel(0xffffffff, &ss->wid);
  567. sbus_writel(0xff000000, &ss->planemask);
  568. sbus_writel(0x310850, &ss->rop);
  569. sbus_writel(4, &us->addrspace);
  570. }
  571. return 0;
  572. }
  573. static char idstring[40] __initdata = { 0 };
  574. char * __init leofb_init(struct fb_info_sbusfb *fb)
  575. {
  576. struct fb_fix_screeninfo *fix = &fb->fix;
  577. struct fb_var_screeninfo *var = &fb->var;
  578. struct display *disp = &fb->disp;
  579. struct fbtype *type = &fb->type;
  580. struct sbus_dev *sdev = fb->sbdp;
  581. unsigned long phys = sdev->reg_addrs[0].phys_addr;
  582. struct fb_wid_item wi;
  583. struct fb_wid_list wl;
  584. int i;
  585. register struct leo_lc_ss0_usr *us;
  586. register struct leo_ld *ss;
  587. struct fb_ops *fbops;
  588. u32 tmp;
  589. strcpy(fb->info.modename, "Leo");
  590. strcpy(fix->id, "Leo");
  591. fix->visual = FB_VISUAL_TRUECOLOR;
  592. fix->line_length = 8192;
  593. fix->accel = FB_ACCEL_SUN_LEO;
  594. var->bits_per_pixel = 32;
  595. var->green.offset = 8;
  596. var->blue.offset = 16;
  597. var->accel_flags = FB_ACCELF_TEXT;
  598. fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
  599. if (fbops == NULL)
  600. return NULL;
  601. *fbops = *fb->info.fbops;
  602. fbops->fb_rasterimg = leo_rasterimg;
  603. fb->info.fbops = fbops;
  604. disp->scrollmode = SCROLL_YREDRAW;
  605. if (!disp->screen_base) {
  606. disp->screen_base = (char *)
  607. sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
  608.      0x800000, "leo ram");
  609. }
  610. disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
  611. us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
  612. sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
  613.      0x1000, "leolc ss0usr");
  614. fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
  615. sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
  616.      0x1000, "leold ss0");
  617. ss = (struct leo_ld *) fb->s.leo.ld_ss0;
  618. fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
  619. sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
  620.      0x1000, "leold ss1");
  621. fb->s.leo.lx_krn = (struct leo_lx_krn *)
  622. sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
  623.      0x1000, "leolx krn");
  624. fb->s.leo.cursor = (struct leo_cursor *)
  625. sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
  626.      sizeof(struct leo_cursor), "leolx cursor");
  627. fb->dispsw = leo_dispsw;
  628. fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
  629. wl.wl_count = 1;
  630. wl.wl_list = &wi;
  631. wi.wi_type = FB_WID_DBL_8;
  632. wi.wi_index = 0;
  633. wi.wi_values [0] = 0x2c0;
  634. leo_wid_put (fb, &wl);
  635. wi.wi_index = 1;
  636. wi.wi_values [0] = 0x30;
  637. leo_wid_put (fb, &wl);
  638. wi.wi_index = 2;
  639. wi.wi_values [0] = 0x20;
  640. leo_wid_put (fb, &wl);
  641. wi.wi_type = FB_WID_DBL_24;
  642. wi.wi_index = 1;
  643. wi.wi_values [0] = 0x30;
  644. leo_wid_put (fb, &wl);
  645. tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
  646. tmp |= LEO_SS1_MISC_ENABLE;
  647. sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
  648. sbus_writel(0xffffffff, &ss->wid);
  649. sbus_writel(0xffff, &ss->wmask);
  650. sbus_writel(0, &ss->vclipmin);
  651. sbus_writel(fb->s.leo.extent, &ss->vclipmax);
  652. sbus_writel(0, &ss->fg);
  653. sbus_writel(0xff000000, &ss->planemask);
  654. sbus_writel(0x310850, &ss->rop);
  655. sbus_writel(0, &ss->widclip);
  656. sbus_writel((type->fb_width-1) | ((type->fb_height-1) << 11), &us->extent);
  657. sbus_writel(4, &us->addrspace);
  658. sbus_writel(0x80000000, &us->fill);
  659. sbus_writel(0, &us->fontt);
  660. do {
  661. i = sbus_readl(&us->csr);
  662. } while (i & 0x20000000);
  663. fb->margins = leo_margins;
  664. fb->loadcmap = leo_loadcmap;
  665. fb->setcursor = leo_setcursor;
  666. fb->setcursormap = leo_setcursormap;
  667. fb->setcurshape = leo_setcurshape;
  668. fb->restore_palette = leo_restore_palette;
  669. fb->switch_from_graph = leo_switch_from_graph;
  670. fb->fill = leo_fill;
  671. fb->blank = leo_blank;
  672. fb->unblank = leo_unblank;
  673. fb->physbase = phys;
  674. fb->mmap_map = leo_mmap_map;
  675. #ifdef __sparc_v9__
  676. sprintf(idstring, "leo at %016lx", phys);
  677. #else
  678. sprintf(idstring, "leo at %x.%08lx", fb->iospace, phys);
  679. #endif
  680.     
  681. return idstring;
  682. }
  683. MODULE_LICENSE("GPL");