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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  drivers/video/chipsfb.c -- frame buffer device for
  3.  *  Chips & Technologies 65550 chip.
  4.  *
  5.  *  Copyright (C) 1998 Paul Mackerras
  6.  *
  7.  *  This file is derived from the Powermac "chips" driver:
  8.  *  Copyright (C) 1997 Fabio Riccardi.
  9.  *  And from the frame buffer device for Open Firmware-initialized devices:
  10.  *  Copyright (C) 1997 Geert Uytterhoeven.
  11.  *
  12.  *  This file is subject to the terms and conditions of the GNU General Public
  13.  *  License. See the file COPYING in the main directory of this archive for
  14.  *  more details.
  15.  */
  16. #include <linux/config.h>
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/errno.h>
  20. #include <linux/string.h>
  21. #include <linux/mm.h>
  22. #include <linux/tty.h>
  23. #include <linux/slab.h>
  24. #include <linux/vmalloc.h>
  25. #include <linux/delay.h>
  26. #include <linux/interrupt.h>
  27. #include <linux/fb.h>
  28. #include <linux/selection.h>
  29. #include <linux/init.h>
  30. #include <linux/pci.h>
  31. #include <asm/io.h>
  32. #ifdef CONFIG_FB_COMPAT_XPMAC
  33. #include <asm/vc_ioctl.h>
  34. #include <asm/pci-bridge.h>
  35. #endif
  36. #ifdef CONFIG_PMAC_BACKLIGHT
  37. #include <asm/backlight.h>
  38. #endif
  39. #ifdef CONFIG_PMAC_PBOOK
  40. #include <linux/adb.h>
  41. #include <linux/pmu.h>
  42. #endif
  43. #include <video/fbcon.h>
  44. #include <video/fbcon-cfb8.h>
  45. #include <video/fbcon-cfb16.h>
  46. #include <video/macmodes.h>
  47. static int currcon = 0;
  48. struct fb_info_chips {
  49. struct fb_info info;
  50. struct fb_fix_screeninfo fix;
  51. struct fb_var_screeninfo var;
  52. struct display disp;
  53. struct {
  54. __u8 red, green, blue;
  55. } palette[256];
  56. struct pci_dev *pdev;
  57. unsigned long frame_buffer_phys;
  58. __u8 *frame_buffer;
  59. unsigned long blitter_regs_phys;
  60. __u32 *blitter_regs;
  61. unsigned long blitter_data_phys;
  62. __u8 *blitter_data;
  63. struct fb_info_chips *next;
  64. #ifdef CONFIG_PMAC_PBOOK
  65. unsigned char *save_framebuffer;
  66. #endif
  67. #ifdef FBCON_HAS_CFB16
  68. u16 fbcon_cfb16_cmap[16];
  69. #endif
  70. };
  71. #define write_ind(num, val, ap, dp) do { 
  72. outb((num), (ap)); outb((val), (dp)); 
  73. } while (0)
  74. #define read_ind(num, var, ap, dp) do { 
  75. outb((num), (ap)); var = inb((dp)); 
  76. } while (0)
  77. /* extension registers */
  78. #define write_xr(num, val) write_ind(num, val, 0x3d6, 0x3d7)
  79. #define read_xr(num, var) read_ind(num, var, 0x3d6, 0x3d7)
  80. /* flat panel registers */
  81. #define write_fr(num, val) write_ind(num, val, 0x3d0, 0x3d1)
  82. #define read_fr(num, var) read_ind(num, var, 0x3d0, 0x3d1)
  83. /* CRTC registers */
  84. #define write_cr(num, val) write_ind(num, val, 0x3d4, 0x3d5)
  85. #define read_cr(num, var) read_ind(num, var, 0x3d4, 0x3d5)
  86. /* graphics registers */
  87. #define write_gr(num, val) write_ind(num, val, 0x3ce, 0x3cf)
  88. #define read_gr(num, var) read_ind(num, var, 0x3ce, 0x3cf)
  89. /* sequencer registers */
  90. #define write_sr(num, val) write_ind(num, val, 0x3c4, 0x3c5)
  91. #define read_sr(num, var) read_ind(num, var, 0x3c4, 0x3c5)
  92. /* attribute registers - slightly strange */
  93. #define write_ar(num, val) do { 
  94. inb(0x3da); write_ind(num, val, 0x3c0, 0x3c0); 
  95. } while (0)
  96. #define read_ar(num, var) do { 
  97. inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); 
  98. } while (0)
  99. static struct fb_info_chips *all_chips;
  100. #ifdef CONFIG_PMAC_PBOOK
  101. int chips_sleep_notify(struct pmu_sleep_notifier *self, int when);
  102. static struct pmu_sleep_notifier chips_sleep_notifier = {
  103. chips_sleep_notify, SLEEP_LEVEL_VIDEO,
  104. };
  105. #endif
  106. /*
  107.  * Exported functions
  108.  */
  109. int chips_init(void);
  110. static void chips_pci_init(struct pci_dev *dp);
  111. static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
  112.  struct fb_info *info);
  113. static int chips_get_var(struct fb_var_screeninfo *var, int con,
  114.  struct fb_info *info);
  115. static int chips_set_var(struct fb_var_screeninfo *var, int con,
  116.  struct fb_info *info);
  117. static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  118.   struct fb_info *info);
  119. static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  120.   struct fb_info *info);
  121. static struct fb_ops chipsfb_ops = {
  122. owner: THIS_MODULE,
  123. fb_get_fix: chips_get_fix,
  124. fb_get_var: chips_get_var,
  125. fb_set_var: chips_set_var,
  126. fb_get_cmap: chips_get_cmap,
  127. fb_set_cmap: chips_set_cmap,
  128. };
  129. static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
  130.      u_int *blue, u_int *transp, struct fb_info *info);
  131. static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  132.      u_int transp, struct fb_info *info);
  133. static void do_install_cmap(int con, struct fb_info *info);
  134. static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp);
  135. static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
  136.  struct fb_info *info)
  137. {
  138. struct fb_info_chips *cp = (struct fb_info_chips *) info;
  139. *fix = cp->fix;
  140. return 0;
  141. }
  142. static int chips_get_var(struct fb_var_screeninfo *var, int con,
  143.  struct fb_info *info)
  144. {
  145. struct fb_info_chips *cp = (struct fb_info_chips *) info;
  146. *var = cp->var;
  147. return 0;
  148. }
  149. static int chips_set_var(struct fb_var_screeninfo *var, int con,
  150.  struct fb_info *info)
  151. {
  152. struct fb_info_chips *cp = (struct fb_info_chips *) info;
  153. struct display *disp = (con >= 0)? &fb_display[con]: &cp->disp;
  154. if (var->xres > 800 || var->yres > 600
  155.     || var->xres_virtual > 800 || var->yres_virtual > 600
  156.     || (var->bits_per_pixel != 8 && var->bits_per_pixel != 16)
  157.     || var->nonstd
  158.     || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
  159. return -EINVAL;
  160. if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW &&
  161. var->bits_per_pixel != disp->var.bits_per_pixel) {
  162. chips_set_bitdepth(cp, disp, con, var->bits_per_pixel);
  163. }
  164. return 0;
  165. }
  166. static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  167.   struct fb_info *info)
  168. {
  169. if (con == currcon) /* current console? */
  170. return fb_get_cmap(cmap, kspc, chipsfb_getcolreg, info);
  171. if (fb_display[con].cmap.len) /* non default colormap? */
  172. fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  173. else {
  174. int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
  175. fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
  176. }
  177. return 0;
  178. }
  179. static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  180.  struct fb_info *info)
  181. {
  182. int err;
  183. if (!fb_display[con].cmap.len) { /* no colormap allocated? */
  184. int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
  185. if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
  186. return err;
  187. }
  188. if (con == currcon) /* current console? */
  189. return fb_set_cmap(cmap, kspc, chipsfb_setcolreg, info);
  190. else
  191. fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  192. return 0;
  193. }
  194. static int chipsfbcon_switch(int con, struct fb_info *info)
  195. {
  196. struct fb_info_chips *p = (struct fb_info_chips *) info;
  197. int new_bpp, old_bpp;
  198. /* Do we have to save the colormap? */
  199. if (fb_display[currcon].cmap.len)
  200. fb_get_cmap(&fb_display[currcon].cmap, 1, chipsfb_getcolreg, info);
  201. new_bpp = fb_display[con].var.bits_per_pixel;
  202. old_bpp = fb_display[currcon].var.bits_per_pixel;
  203. currcon = con;
  204. if (new_bpp != old_bpp)
  205. chips_set_bitdepth(p, &fb_display[con], con, new_bpp);
  206. do_install_cmap(con, info);
  207. return 0;
  208. }
  209. static int chipsfb_updatevar(int con, struct fb_info *info)
  210. {
  211. return 0;
  212. }
  213. static void chipsfb_blank(int blank, struct fb_info *info)
  214. {
  215. struct fb_info_chips *p = (struct fb_info_chips *) info;
  216. int i;
  217. // used to disable backlight only for blank > 1, but it seems
  218. // useful at blank = 1 too (saves battery, extends backlight life)
  219. if (blank) {
  220. #ifdef CONFIG_PMAC_BACKLIGHT
  221. set_backlight_enable(0);
  222. #endif /* CONFIG_PMAC_BACKLIGHT */
  223. /* get the palette from the chip */
  224. for (i = 0; i < 256; ++i) {
  225. outb(i, 0x3c7);
  226. udelay(1);
  227. p->palette[i].red = inb(0x3c9);
  228. p->palette[i].green = inb(0x3c9);
  229. p->palette[i].blue = inb(0x3c9);
  230. }
  231. for (i = 0; i < 256; ++i) {
  232. outb(i, 0x3c8);
  233. udelay(1);
  234. outb(0, 0x3c9);
  235. outb(0, 0x3c9);
  236. outb(0, 0x3c9);
  237. }
  238. } else {
  239. #ifdef CONFIG_PMAC_BACKLIGHT
  240. set_backlight_enable(1);
  241. #endif /* CONFIG_PMAC_BACKLIGHT */
  242. for (i = 0; i < 256; ++i) {
  243. outb(i, 0x3c8);
  244. udelay(1);
  245. outb(p->palette[i].red, 0x3c9);
  246. outb(p->palette[i].green, 0x3c9);
  247. outb(p->palette[i].blue, 0x3c9);
  248. }
  249. }
  250. }
  251. static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
  252.      u_int *blue, u_int *transp, struct fb_info *info)
  253. {
  254. struct fb_info_chips *p = (struct fb_info_chips *) info;
  255. if (regno > 255)
  256. return 1;
  257. *red = (p->palette[regno].red<<8) | p->palette[regno].red;
  258. *green = (p->palette[regno].green<<8) | p->palette[regno].green;
  259. *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
  260. *transp = 0;
  261. return 0;
  262. }
  263. static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  264.      u_int transp, struct fb_info *info)
  265. {
  266. struct fb_info_chips *p = (struct fb_info_chips *) info;
  267. if (regno > 255)
  268. return 1;
  269. red >>= 8;
  270. green >>= 8;
  271. blue >>= 8;
  272. p->palette[regno].red = red;
  273. p->palette[regno].green = green;
  274. p->palette[regno].blue = blue;
  275. outb(regno, 0x3c8);
  276. udelay(1);
  277. outb(red, 0x3c9);
  278. outb(green, 0x3c9);
  279. outb(blue, 0x3c9);
  280. #ifdef FBCON_HAS_CFB16
  281. if (regno < 16)
  282. p->fbcon_cfb16_cmap[regno] = ((red & 0xf8) << 7)
  283. | ((green & 0xf8) << 2) | ((blue & 0xf8) >> 3);
  284. #endif
  285. return 0;
  286. }
  287. static void do_install_cmap(int con, struct fb_info *info)
  288. {
  289. if (con != currcon)
  290. return;
  291. if (fb_display[con].cmap.len)
  292. fb_set_cmap(&fb_display[con].cmap, 1, chipsfb_setcolreg, info);
  293. else {
  294. int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
  295. fb_set_cmap(fb_default_cmap(size), 1, chipsfb_setcolreg, info);
  296. }
  297. }
  298. static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp)
  299. {
  300. int err;
  301. struct fb_fix_screeninfo* fix = &p->fix;
  302. struct fb_var_screeninfo* var = &p->var;
  303. if (bpp == 16) {
  304. if (con == currcon) {
  305. write_cr(0x13, 200); // Set line length (doublewords)
  306. write_xr(0x81, 0x14); // 15 bit (555) color mode
  307. write_xr(0x82, 0x00); // Disable palettes
  308. write_xr(0x20, 0x10); // 16 bit blitter mode
  309. }
  310. fix->line_length = 800*2;
  311. fix->visual = FB_VISUAL_TRUECOLOR;
  312. var->red.offset = 10;
  313. var->green.offset = 5;
  314. var->blue.offset = 0;
  315. var->red.length = var->green.length = var->blue.length = 5;
  316. #ifdef FBCON_HAS_CFB16
  317. disp->dispsw = &fbcon_cfb16;
  318. disp->dispsw_data = p->fbcon_cfb16_cmap;
  319. #else
  320. disp->dispsw = &fbcon_dummy;
  321. #endif
  322. } else if (bpp == 8) {
  323. if (con == currcon) {
  324. write_cr(0x13, 100); // Set line length (doublewords)
  325. write_xr(0x81, 0x12); // 8 bit color mode
  326. write_xr(0x82, 0x08); // Graphics gamma enable
  327. write_xr(0x20, 0x00); // 8 bit blitter mode
  328. }
  329. fix->line_length = 800;
  330. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  331.   var->red.offset = var->green.offset = var->blue.offset = 0;
  332. var->red.length = var->green.length = var->blue.length = 8;
  333. #ifdef FBCON_HAS_CFB8
  334. disp->dispsw = &fbcon_cfb8;
  335. #else
  336. disp->dispsw = &fbcon_dummy;
  337. #endif
  338. }
  339. var->bits_per_pixel = bpp;
  340. disp->line_length = p->fix.line_length;
  341. disp->visual = fix->visual;
  342. disp->var = *var;
  343. #ifdef CONFIG_FB_COMPAT_XPMAC
  344. display_info.depth = bpp;
  345. display_info.pitch = fix->line_length;
  346. #endif
  347. if (p->info.changevar)
  348. (*p->info.changevar)(con);
  349. if ((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
  350. return;
  351. do_install_cmap(con, (struct fb_info *)p);
  352. }
  353. struct chips_init_reg {
  354. unsigned char addr;
  355. unsigned char data;
  356. };
  357. #define N_ELTS(x) (sizeof(x) / sizeof(x[0]))
  358. static struct chips_init_reg chips_init_sr[] = {
  359. { 0x00, 0x03 },
  360. { 0x01, 0x01 },
  361. { 0x02, 0x0f },
  362. { 0x04, 0x0e }
  363. };
  364. static struct chips_init_reg chips_init_gr[] = {
  365. { 0x05, 0x00 },
  366. { 0x06, 0x0d },
  367. { 0x08, 0xff }
  368. };
  369. static struct chips_init_reg chips_init_ar[] = {
  370. { 0x10, 0x01 },
  371. { 0x12, 0x0f },
  372. { 0x13, 0x00 }
  373. };
  374. static struct chips_init_reg chips_init_cr[] = {
  375. { 0x00, 0x7f },
  376. { 0x01, 0x63 },
  377. { 0x02, 0x63 },
  378. { 0x03, 0x83 },
  379. { 0x04, 0x66 },
  380. { 0x05, 0x10 },
  381. { 0x06, 0x72 },
  382. { 0x07, 0x3e },
  383. { 0x08, 0x00 },
  384. { 0x09, 0x40 },
  385. { 0x0c, 0x00 },
  386. { 0x0d, 0x00 },
  387. { 0x10, 0x59 },
  388. { 0x11, 0x0d },
  389. { 0x12, 0x57 },
  390. { 0x13, 0x64 },
  391. { 0x14, 0x00 },
  392. { 0x15, 0x57 },
  393. { 0x16, 0x73 },
  394. { 0x17, 0xe3 },
  395. { 0x18, 0xff },
  396. { 0x30, 0x02 },
  397. { 0x31, 0x02 },
  398. { 0x32, 0x02 },
  399. { 0x33, 0x02 },
  400. { 0x40, 0x00 },
  401. { 0x41, 0x00 },
  402. { 0x40, 0x80 }
  403. };
  404. static struct chips_init_reg chips_init_fr[] = {
  405. { 0x01, 0x02 },
  406. { 0x03, 0x08 },
  407. { 0x04, 0x81 },
  408. { 0x05, 0x21 },
  409. { 0x08, 0x0c },
  410. { 0x0a, 0x74 },
  411. { 0x0b, 0x11 },
  412. { 0x10, 0x0c },
  413. { 0x11, 0xe0 },
  414. /* { 0x12, 0x40 }, -- 3400 needs 40, 2400 needs 48, no way to tell */
  415. { 0x20, 0x63 },
  416. { 0x21, 0x68 },
  417. { 0x22, 0x19 },
  418. { 0x23, 0x7f },
  419. { 0x24, 0x68 },
  420. { 0x26, 0x00 },
  421. { 0x27, 0x0f },
  422. { 0x30, 0x57 },
  423. { 0x31, 0x58 },
  424. { 0x32, 0x0d },
  425. { 0x33, 0x72 },
  426. { 0x34, 0x02 },
  427. { 0x35, 0x22 },
  428. { 0x36, 0x02 },
  429. { 0x37, 0x00 }
  430. };
  431. static struct chips_init_reg chips_init_xr[] = {
  432. { 0xce, 0x00 }, /* set default memory clock */
  433. { 0xcc, 0x43 }, /* memory clock ratio */
  434. { 0xcd, 0x18 },
  435. { 0xce, 0xa1 },
  436. { 0xc8, 0x84 },
  437. { 0xc9, 0x0a },
  438. { 0xca, 0x00 },
  439. { 0xcb, 0x20 },
  440. { 0xcf, 0x06 },
  441. { 0xd0, 0x0e },
  442. { 0x09, 0x01 },
  443. { 0x0a, 0x02 },
  444. { 0x0b, 0x01 },
  445. { 0x20, 0x00 },
  446. { 0x40, 0x03 },
  447. { 0x41, 0x01 },
  448. { 0x42, 0x00 },
  449. { 0x80, 0x82 },
  450. { 0x81, 0x12 },
  451. { 0x82, 0x08 },
  452. { 0xa0, 0x00 },
  453. { 0xa8, 0x00 }
  454. };
  455. static void __init chips_hw_init(struct fb_info_chips *p)
  456. {
  457. int i;
  458. for (i = 0; i < N_ELTS(chips_init_xr); ++i)
  459. write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
  460. outb(0x29, 0x3c2); /* set misc output reg */
  461. for (i = 0; i < N_ELTS(chips_init_sr); ++i)
  462. write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
  463. for (i = 0; i < N_ELTS(chips_init_gr); ++i)
  464. write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
  465. for (i = 0; i < N_ELTS(chips_init_ar); ++i)
  466. write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
  467. for (i = 0; i < N_ELTS(chips_init_cr); ++i)
  468. write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
  469. for (i = 0; i < N_ELTS(chips_init_fr); ++i)
  470. write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
  471. }
  472. static void __init init_chips(struct fb_info_chips *p)
  473. {
  474. int i;
  475. strcpy(p->fix.id, "C&T 65550");
  476. p->fix.smem_start = p->frame_buffer_phys;
  477. // FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB.
  478. // * "3500" PowerBook G3 (the original PB G3) has 2MB.
  479. // * 2400 has 1MB composed of 2 Mitsubishi M5M4V4265CTP DRAM chips.
  480. //   Motherboard actually supports 2MB -- there are two blank locations
  481. //   for a second pair of DRAMs.  (Thanks, Apple!)
  482. // * 3400 has 1MB (I think).  Don't know if it's expandable.
  483. // -- Tim Seufert
  484. p->fix.smem_len = 0x100000; // 1MB
  485. p->fix.type = FB_TYPE_PACKED_PIXELS;
  486. p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
  487. p->fix.line_length = 800;
  488. p->var.xres = 800;
  489. p->var.yres = 600;
  490. p->var.xres_virtual = 800;
  491. p->var.yres_virtual = 600;
  492. p->var.bits_per_pixel = 8;
  493. p->var.red.length = p->var.green.length = p->var.blue.length = 8;
  494. p->var.height = p->var.width = -1;
  495. p->var.vmode = FB_VMODE_NONINTERLACED;
  496. p->var.pixclock = 10000;
  497. p->var.left_margin = p->var.right_margin = 16;
  498. p->var.upper_margin = p->var.lower_margin = 16;
  499. p->var.hsync_len = p->var.vsync_len = 8;
  500. p->disp.var = p->var;
  501. p->disp.cmap.red = NULL;
  502. p->disp.cmap.green = NULL;
  503. p->disp.cmap.blue = NULL;
  504. p->disp.cmap.transp = NULL;
  505. p->disp.screen_base = p->frame_buffer;
  506. p->disp.visual = p->fix.visual;
  507. p->disp.type = p->fix.type;
  508. p->disp.type_aux = p->fix.type_aux;
  509. p->disp.line_length = p->fix.line_length;
  510. p->disp.can_soft_blank = 1;
  511. p->disp.dispsw = &fbcon_cfb8;
  512. p->disp.scrollmode = SCROLL_YREDRAW;
  513. strcpy(p->info.modename, p->fix.id);
  514. p->info.node = -1;
  515. p->info.fbops = &chipsfb_ops;
  516. p->info.disp = &p->disp;
  517. p->info.fontname[0] = 0;
  518. p->info.changevar = NULL;
  519. p->info.switch_con = &chipsfbcon_switch;
  520. p->info.updatevar = &chipsfb_updatevar;
  521. p->info.blank = &chipsfb_blank;
  522. p->info.flags = FBINFO_FLAG_DEFAULT;
  523. for (i = 0; i < 16; ++i) {
  524. int j = color_table[i];
  525. p->palette[i].red = default_red[j];
  526. p->palette[i].green = default_grn[j];
  527. p->palette[i].blue = default_blu[j];
  528. }
  529. if (register_framebuffer(&p->info) < 0) {
  530. kfree(p);
  531. return;
  532. }
  533. printk("fb%d: Chips 65550 frame buffer (%dK RAM detected)n",
  534. GET_FB_IDX(p->info.node), p->fix.smem_len / 1024);
  535. chips_hw_init(p);
  536. #ifdef CONFIG_FB_COMPAT_XPMAC
  537. if (!console_fb_info) {
  538. unsigned long iobase;
  539. display_info.height = p->var.yres;
  540. display_info.width = p->var.xres;
  541. display_info.depth = 8;
  542. display_info.pitch = p->fix.line_length;
  543. display_info.mode = VMODE_800_600_60;
  544. strncpy(display_info.name, "chips65550",
  545. sizeof(display_info.name));
  546. display_info.fb_address = p->frame_buffer_phys;
  547. iobase = pci_bus_io_base_phys(p->pdev->bus->number);
  548. display_info.cmap_adr_address = iobase + 0x3c8;
  549. display_info.cmap_data_address = iobase + 0x3c9;
  550. display_info.disp_reg_address = p->blitter_regs_phys;
  551. console_fb_info = &p->info;
  552. }
  553. #endif /* CONFIG_FB_COMPAT_XPMAC */
  554. #ifdef CONFIG_PMAC_PBOOK
  555. if (all_chips == NULL)
  556. pmu_register_sleep_notifier(&chips_sleep_notifier);
  557. #endif /* CONFIG_PMAC_PBOOK */
  558. p->next = all_chips;
  559. all_chips = p;
  560. }
  561. int __init chips_init(void)
  562. {
  563. struct pci_dev *dp = NULL;
  564. while ((dp = pci_find_device(PCI_VENDOR_ID_CT,
  565.      PCI_DEVICE_ID_CT_65550, dp)) != NULL)
  566. if ((dp->class >> 16) == PCI_BASE_CLASS_DISPLAY)
  567. chips_pci_init(dp);
  568. return all_chips? 0: -ENODEV;
  569. }
  570. static void __init chips_pci_init(struct pci_dev *dp)
  571. {
  572. struct fb_info_chips *p;
  573. unsigned long addr, size;
  574. unsigned short cmd;
  575. if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
  576. return;
  577. addr = dp->resource[0].start;
  578. size = dp->resource[0].end + 1 - addr;
  579. if (addr == 0)
  580. return;
  581. p = kmalloc(sizeof(*p), GFP_ATOMIC);
  582. if (p == 0)
  583. return;
  584. memset(p, 0, sizeof(*p));
  585. if (!request_mem_region(addr, size, "chipsfb")) {
  586. kfree(p);
  587. return;
  588. }
  589. #ifdef __BIG_ENDIAN
  590. addr += 0x800000; // Use big-endian aperture
  591. #endif
  592. p->pdev = dp;
  593. p->frame_buffer_phys = addr;
  594. p->frame_buffer = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
  595. p->blitter_regs_phys = addr + 0x400000;
  596. p->blitter_regs = ioremap(addr + 0x400000, 0x1000);
  597. p->blitter_data_phys = addr + 0x410000;
  598. p->blitter_data = ioremap(addr + 0x410000, 0x10000);
  599. /* we should use pci_enable_device here, but,
  600.    the device doesn't declare its I/O ports in its BARs
  601.    so pci_enable_device won't turn on I/O responses */
  602. pci_read_config_word(dp, PCI_COMMAND, &cmd);
  603. cmd |= 3; /* enable memory and IO space */
  604. pci_write_config_word(dp, PCI_COMMAND, cmd);
  605. /* Clear the entire framebuffer */
  606. memset(p->frame_buffer, 0, 0x100000);
  607. #ifdef CONFIG_PMAC_BACKLIGHT
  608. /* turn on the backlight */
  609. set_backlight_enable(1);
  610. #endif /* CONFIG_PMAC_BACKLIGHT */
  611. init_chips(p);
  612. }
  613. #ifdef CONFIG_PMAC_PBOOK
  614. /*
  615.  * Save the contents of the frame buffer when we go to sleep,
  616.  * and restore it when we wake up again.
  617.  */
  618. int
  619. chips_sleep_notify(struct pmu_sleep_notifier *self, int when)
  620. {
  621. struct fb_info_chips *p;
  622. for (p = all_chips; p != NULL; p = p->next) {
  623. int nb = p->var.yres * p->fix.line_length;
  624. switch (when) {
  625. case PBOOK_SLEEP_REQUEST:
  626. p->save_framebuffer = vmalloc(nb);
  627. if (p->save_framebuffer == NULL)
  628. return PBOOK_SLEEP_REFUSE;
  629. break;
  630. case PBOOK_SLEEP_REJECT:
  631. if (p->save_framebuffer) {
  632. vfree(p->save_framebuffer);
  633. p->save_framebuffer = 0;
  634. }
  635. break;
  636. case PBOOK_SLEEP_NOW:
  637. chipsfb_blank(1, (struct fb_info *)p);
  638. if (p->save_framebuffer)
  639. memcpy(p->save_framebuffer,
  640.        p->frame_buffer, nb);
  641. break;
  642. case PBOOK_WAKE:
  643. if (p->save_framebuffer) {
  644. memcpy(p->frame_buffer,
  645.        p->save_framebuffer, nb);
  646. vfree(p->save_framebuffer);
  647. p->save_framebuffer = 0;
  648. }
  649. chipsfb_blank(0, (struct fb_info *)p);
  650. break;
  651. }
  652. }
  653. return PBOOK_SLEEP_OK;
  654. }
  655. #endif /* CONFIG_PMAC_PBOOK */
  656. MODULE_LICENSE("GPL");