s1d13xxxfb.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. /* drivers/video/s1d13xxxfb.c
  2. *
  3. * (c) 2004 Simtec Electronics
  4. * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
  5. * (c) 2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
  6. *
  7. * Driver for Epson S1D13xxx series framebuffer chips
  8. *
  9. * Adapted from
  10. * linux/drivers/video/skeletonfb.c
  11. * linux/drivers/video/epson1355fb.c
  12. * linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson)
  13. *
  14. * TODO: - handle dual screen display (CRT and LCD at the same time).
  15. * - check_var(), mode change, etc.
  16. * - probably not SMP safe :)
  17. * - support all bitblt operations on all cards
  18. *
  19. * This file is subject to the terms and conditions of the GNU General Public
  20. * License. See the file COPYING in the main directory of this archive for
  21. * more details.
  22. */
  23. #include <linux/module.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/delay.h>
  26. #include <linux/types.h>
  27. #include <linux/errno.h>
  28. #include <linux/mm.h>
  29. #include <linux/mman.h>
  30. #include <linux/fb.h>
  31. #include <linux/spinlock_types.h>
  32. #include <linux/spinlock.h>
  33. #include <asm/io.h>
  34. #include <video/s1d13xxxfb.h>
  35. #define PFX "s1d13xxxfb: "
  36. #define BLIT "s1d13xxxfb_bitblt: "
  37. /*
  38. * set this to enable debugging on general functions
  39. */
  40. #if 0
  41. #define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0)
  42. #else
  43. #define dbg(fmt, args...) do { } while (0)
  44. #endif
  45. /*
  46. * set this to enable debugging on 2D acceleration
  47. */
  48. #if 0
  49. #define dbg_blit(fmt, args...) do { printk(KERN_INFO BLIT fmt, ## args); } while (0)
  50. #else
  51. #define dbg_blit(fmt, args...) do { } while (0)
  52. #endif
  53. /*
  54. * we make sure only one bitblt operation is running
  55. */
  56. static DEFINE_SPINLOCK(s1d13xxxfb_bitblt_lock);
  57. /*
  58. * list of card production ids
  59. */
  60. static const int s1d13xxxfb_prod_ids[] = {
  61. S1D13505_PROD_ID,
  62. S1D13506_PROD_ID,
  63. S1D13806_PROD_ID,
  64. };
  65. /*
  66. * List of card strings
  67. */
  68. static const char *s1d13xxxfb_prod_names[] = {
  69. "S1D13505",
  70. "S1D13506",
  71. "S1D13806",
  72. };
  73. /*
  74. * here we define the default struct fb_fix_screeninfo
  75. */
  76. static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = {
  77. .id = S1D_FBID,
  78. .type = FB_TYPE_PACKED_PIXELS,
  79. .visual = FB_VISUAL_PSEUDOCOLOR,
  80. .xpanstep = 0,
  81. .ypanstep = 1,
  82. .ywrapstep = 0,
  83. .accel = FB_ACCEL_NONE,
  84. };
  85. static inline u8
  86. s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno)
  87. {
  88. #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
  89. regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
  90. #endif
  91. return readb(par->regs + regno);
  92. }
  93. static inline void
  94. s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value)
  95. {
  96. #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
  97. regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
  98. #endif
  99. writeb(value, par->regs + regno);
  100. }
  101. static inline void
  102. s1d13xxxfb_runinit(struct s1d13xxxfb_par *par,
  103. const struct s1d13xxxfb_regval *initregs,
  104. const unsigned int size)
  105. {
  106. int i;
  107. for (i = 0; i < size; i++) {
  108. if ((initregs[i].addr == S1DREG_DELAYOFF) ||
  109. (initregs[i].addr == S1DREG_DELAYON))
  110. mdelay((int)initregs[i].value);
  111. else {
  112. s1d13xxxfb_writereg(par, initregs[i].addr, initregs[i].value);
  113. }
  114. }
  115. /* make sure the hardware can cope with us */
  116. mdelay(1);
  117. }
  118. static inline void
  119. lcd_enable(struct s1d13xxxfb_par *par, int enable)
  120. {
  121. u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
  122. if (enable)
  123. mode |= 0x01;
  124. else
  125. mode &= ~0x01;
  126. s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
  127. }
  128. static inline void
  129. crt_enable(struct s1d13xxxfb_par *par, int enable)
  130. {
  131. u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
  132. if (enable)
  133. mode |= 0x02;
  134. else
  135. mode &= ~0x02;
  136. s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
  137. }
  138. /*************************************************************
  139. framebuffer control functions
  140. *************************************************************/
  141. static inline void
  142. s1d13xxxfb_setup_pseudocolour(struct fb_info *info)
  143. {
  144. info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
  145. info->var.red.length = 4;
  146. info->var.green.length = 4;
  147. info->var.blue.length = 4;
  148. }
  149. static inline void
  150. s1d13xxxfb_setup_truecolour(struct fb_info *info)
  151. {
  152. info->fix.visual = FB_VISUAL_TRUECOLOR;
  153. info->var.bits_per_pixel = 16;
  154. info->var.red.length = 5;
  155. info->var.red.offset = 11;
  156. info->var.green.length = 6;
  157. info->var.green.offset = 5;
  158. info->var.blue.length = 5;
  159. info->var.blue.offset = 0;
  160. }
  161. /**
  162. * s1d13xxxfb_set_par - Alters the hardware state.
  163. * @info: frame buffer structure
  164. *
  165. * Using the fb_var_screeninfo in fb_info we set the depth of the
  166. * framebuffer. This function alters the par AND the
  167. * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
  168. * fb_info since we are using that data. This means we depend on the
  169. * data in var inside fb_info to be supported by the hardware.
  170. * xxxfb_check_var is always called before xxxfb_set_par to ensure this.
  171. *
  172. * XXX TODO: write proper s1d13xxxfb_check_var(), without which that
  173. * function is quite useless.
  174. */
  175. static int
  176. s1d13xxxfb_set_par(struct fb_info *info)
  177. {
  178. struct s1d13xxxfb_par *s1dfb = info->par;
  179. unsigned int val;
  180. dbg("s1d13xxxfb_set_par: bpp=%d\n", info->var.bits_per_pixel);
  181. if ((s1dfb->display & 0x01)) /* LCD */
  182. val = s1d13xxxfb_readreg(s1dfb, S1DREG_LCD_DISP_MODE); /* read colour control */
  183. else /* CRT */
  184. val = s1d13xxxfb_readreg(s1dfb, S1DREG_CRT_DISP_MODE); /* read colour control */
  185. val &= ~0x07;
  186. switch (info->var.bits_per_pixel) {
  187. case 4:
  188. dbg("pseudo colour 4\n");
  189. s1d13xxxfb_setup_pseudocolour(info);
  190. val |= 2;
  191. break;
  192. case 8:
  193. dbg("pseudo colour 8\n");
  194. s1d13xxxfb_setup_pseudocolour(info);
  195. val |= 3;
  196. break;
  197. case 16:
  198. dbg("true colour\n");
  199. s1d13xxxfb_setup_truecolour(info);
  200. val |= 5;
  201. break;
  202. default:
  203. dbg("bpp not supported!\n");
  204. return -EINVAL;
  205. }
  206. dbg("writing %02x to display mode register\n", val);
  207. if ((s1dfb->display & 0x01)) /* LCD */
  208. s1d13xxxfb_writereg(s1dfb, S1DREG_LCD_DISP_MODE, val);
  209. else /* CRT */
  210. s1d13xxxfb_writereg(s1dfb, S1DREG_CRT_DISP_MODE, val);
  211. info->fix.line_length = info->var.xres * info->var.bits_per_pixel;
  212. info->fix.line_length /= 8;
  213. dbg("setting line_length to %d\n", info->fix.line_length);
  214. dbg("done setup\n");
  215. return 0;
  216. }
  217. /**
  218. * s1d13xxxfb_setcolreg - sets a color register.
  219. * @regno: Which register in the CLUT we are programming
  220. * @red: The red value which can be up to 16 bits wide
  221. * @green: The green value which can be up to 16 bits wide
  222. * @blue: The blue value which can be up to 16 bits wide.
  223. * @transp: If supported the alpha value which can be up to 16 bits wide.
  224. * @info: frame buffer info structure
  225. *
  226. * Returns negative errno on error, or zero on success.
  227. */
  228. static int
  229. s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  230. u_int transp, struct fb_info *info)
  231. {
  232. struct s1d13xxxfb_par *s1dfb = info->par;
  233. unsigned int pseudo_val;
  234. if (regno >= S1D_PALETTE_SIZE)
  235. return -EINVAL;
  236. dbg("s1d13xxxfb_setcolreg: %d: rgb=%d,%d,%d, tr=%d\n",
  237. regno, red, green, blue, transp);
  238. if (info->var.grayscale)
  239. red = green = blue = (19595*red + 38470*green + 7471*blue) >> 16;
  240. switch (info->fix.visual) {
  241. case FB_VISUAL_TRUECOLOR:
  242. if (regno >= 16)
  243. return -EINVAL;
  244. /* deal with creating pseudo-palette entries */
  245. pseudo_val = (red >> 11) << info->var.red.offset;
  246. pseudo_val |= (green >> 10) << info->var.green.offset;
  247. pseudo_val |= (blue >> 11) << info->var.blue.offset;
  248. dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",
  249. regno, pseudo_val);
  250. #if defined(CONFIG_PLAT_MAPPI)
  251. ((u32 *)info->pseudo_palette)[regno] = cpu_to_le16(pseudo_val);
  252. #else
  253. ((u32 *)info->pseudo_palette)[regno] = pseudo_val;
  254. #endif
  255. break;
  256. case FB_VISUAL_PSEUDOCOLOR:
  257. s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_ADDR, regno);
  258. s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, red);
  259. s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, green);
  260. s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, blue);
  261. break;
  262. default:
  263. return -ENOSYS;
  264. }
  265. dbg("s1d13xxxfb_setcolreg: done\n");
  266. return 0;
  267. }
  268. /**
  269. * s1d13xxxfb_blank - blanks the display.
  270. * @blank_mode: the blank mode we want.
  271. * @info: frame buffer structure that represents a single frame buffer
  272. *
  273. * Blank the screen if blank_mode != 0, else unblank. Return 0 if
  274. * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
  275. * video mode which doesn't support it. Implements VESA suspend
  276. * and powerdown modes on hardware that supports disabling hsync/vsync:
  277. * blank_mode == 2: suspend vsync
  278. * blank_mode == 3: suspend hsync
  279. * blank_mode == 4: powerdown
  280. *
  281. * Returns negative errno on error, or zero on success.
  282. */
  283. static int
  284. s1d13xxxfb_blank(int blank_mode, struct fb_info *info)
  285. {
  286. struct s1d13xxxfb_par *par = info->par;
  287. dbg("s1d13xxxfb_blank: blank=%d, info=%p\n", blank_mode, info);
  288. switch (blank_mode) {
  289. case FB_BLANK_UNBLANK:
  290. case FB_BLANK_NORMAL:
  291. if ((par->display & 0x01) != 0)
  292. lcd_enable(par, 1);
  293. if ((par->display & 0x02) != 0)
  294. crt_enable(par, 1);
  295. break;
  296. case FB_BLANK_VSYNC_SUSPEND:
  297. case FB_BLANK_HSYNC_SUSPEND:
  298. break;
  299. case FB_BLANK_POWERDOWN:
  300. lcd_enable(par, 0);
  301. crt_enable(par, 0);
  302. break;
  303. default:
  304. return -EINVAL;
  305. }
  306. /* let fbcon do a soft blank for us */
  307. return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
  308. }
  309. /**
  310. * s1d13xxxfb_pan_display - Pans the display.
  311. * @var: frame buffer variable screen structure
  312. * @info: frame buffer structure that represents a single frame buffer
  313. *
  314. * Pan (or wrap, depending on the `vmode' field) the display using the
  315. * `yoffset' field of the `var' structure (`xoffset' not yet supported).
  316. * If the values don't fit, return -EINVAL.
  317. *
  318. * Returns negative errno on error, or zero on success.
  319. */
  320. static int
  321. s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
  322. {
  323. struct s1d13xxxfb_par *par = info->par;
  324. u32 start;
  325. if (var->xoffset != 0) /* not yet ... */
  326. return -EINVAL;
  327. if (var->yoffset + info->var.yres > info->var.yres_virtual)
  328. return -EINVAL;
  329. start = (info->fix.line_length >> 1) * var->yoffset;
  330. if ((par->display & 0x01)) {
  331. /* LCD */
  332. s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START0, (start & 0xff));
  333. s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START1, ((start >> 8) & 0xff));
  334. s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START2, ((start >> 16) & 0x0f));
  335. } else {
  336. /* CRT */
  337. s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START0, (start & 0xff));
  338. s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START1, ((start >> 8) & 0xff));
  339. s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START2, ((start >> 16) & 0x0f));
  340. }
  341. return 0;
  342. }
  343. /************************************************************
  344. functions to handle bitblt acceleration
  345. ************************************************************/
  346. /**
  347. * bltbit_wait_bitset - waits for change in register value
  348. * @info : framebuffer structure
  349. * @bit : value expected in register
  350. * @timeout : ...
  351. *
  352. * waits until value changes INTO bit
  353. */
  354. static u8
  355. bltbit_wait_bitset(struct fb_info *info, u8 bit, int timeout)
  356. {
  357. while (!(s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit)) {
  358. udelay(10);
  359. if (!--timeout) {
  360. dbg_blit("wait_bitset timeout\n");
  361. break;
  362. }
  363. }
  364. return timeout;
  365. }
  366. /**
  367. * bltbit_wait_bitclear - waits for change in register value
  368. * @info : frambuffer structure
  369. * @bit : value currently in register
  370. * @timeout : ...
  371. *
  372. * waits until value changes FROM bit
  373. *
  374. */
  375. static u8
  376. bltbit_wait_bitclear(struct fb_info *info, u8 bit, int timeout)
  377. {
  378. while (s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit) {
  379. udelay(10);
  380. if (!--timeout) {
  381. dbg_blit("wait_bitclear timeout\n");
  382. break;
  383. }
  384. }
  385. return timeout;
  386. }
  387. /**
  388. * bltbit_fifo_status - checks the current status of the fifo
  389. * @info : framebuffer structure
  390. *
  391. * returns number of free words in buffer
  392. */
  393. static u8
  394. bltbit_fifo_status(struct fb_info *info)
  395. {
  396. u8 status;
  397. status = s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0);
  398. /* its empty so room for 16 words */
  399. if (status & BBLT_FIFO_EMPTY)
  400. return 16;
  401. /* its full so we dont want to add */
  402. if (status & BBLT_FIFO_FULL)
  403. return 0;
  404. /* its atleast half full but we can add one atleast */
  405. if (status & BBLT_FIFO_NOT_FULL)
  406. return 1;
  407. return 0;
  408. }
  409. /*
  410. * s1d13xxxfb_bitblt_copyarea - accelerated copyarea function
  411. * @info : framebuffer structure
  412. * @area : fb_copyarea structure
  413. *
  414. * supports (atleast) S1D13506
  415. *
  416. */
  417. static void
  418. s1d13xxxfb_bitblt_copyarea(struct fb_info *info, const struct fb_copyarea *area)
  419. {
  420. u32 dst, src;
  421. u32 stride;
  422. u16 reverse = 0;
  423. u16 sx = area->sx, sy = area->sy;
  424. u16 dx = area->dx, dy = area->dy;
  425. u16 width = area->width, height = area->height;
  426. u16 bpp;
  427. spin_lock(&s1d13xxxfb_bitblt_lock);
  428. /* bytes per xres line */
  429. bpp = (info->var.bits_per_pixel >> 3);
  430. stride = bpp * info->var.xres;
  431. /* reverse, calculate the last pixel in rectangle */
  432. if ((dy > sy) || ((dy == sy) && (dx >= sx))) {
  433. dst = (((dy + height - 1) * stride) + (bpp * (dx + width - 1)));
  434. src = (((sy + height - 1) * stride) + (bpp * (sx + width - 1)));
  435. reverse = 1;
  436. /* not reverse, calculate the first pixel in rectangle */
  437. } else { /* (y * xres) + (bpp * x) */
  438. dst = (dy * stride) + (bpp * dx);
  439. src = (sy * stride) + (bpp * sx);
  440. }
  441. /* set source adress */
  442. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff));
  443. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff);
  444. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff);
  445. /* set destination adress */
  446. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff));
  447. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff);
  448. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff);
  449. /* program height and width */
  450. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, (width & 0xff) - 1);
  451. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (width >> 8));
  452. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, (height & 0xff) - 1);
  453. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (height >> 8));
  454. /* negative direction ROP */
  455. if (reverse == 1) {
  456. dbg_blit("(copyarea) negative rop\n");
  457. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x03);
  458. } else /* positive direction ROP */ {
  459. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x02);
  460. dbg_blit("(copyarea) positive rop\n");
  461. }
  462. /* set for rectangel mode and not linear */
  463. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0);
  464. /* setup the bpp 1 = 16bpp, 0 = 8bpp*/
  465. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (bpp >> 1));
  466. /* set words per xres */
  467. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (stride >> 1) & 0xff);
  468. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (stride >> 9));
  469. dbg_blit("(copyarea) dx=%d, dy=%d\n", dx, dy);
  470. dbg_blit("(copyarea) sx=%d, sy=%d\n", sx, sy);
  471. dbg_blit("(copyarea) width=%d, height=%d\n", width - 1, height - 1);
  472. dbg_blit("(copyarea) stride=%d\n", stride);
  473. dbg_blit("(copyarea) bpp=%d=0x0%d, mem_offset1=%d, mem_offset2=%d\n", bpp, (bpp >> 1),
  474. (stride >> 1) & 0xff, stride >> 9);
  475. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CC_EXP, 0x0c);
  476. /* initialize the engine */
  477. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80);
  478. /* wait to complete */
  479. bltbit_wait_bitclear(info, 0x80, 8000);
  480. spin_unlock(&s1d13xxxfb_bitblt_lock);
  481. }
  482. /**
  483. *
  484. * s1d13xxxfb_bitblt_solidfill - accelerated solidfill function
  485. * @info : framebuffer structure
  486. * @rect : fb_fillrect structure
  487. *
  488. * supports (atleast 13506)
  489. *
  490. **/
  491. static void
  492. s1d13xxxfb_bitblt_solidfill(struct fb_info *info, const struct fb_fillrect *rect)
  493. {
  494. u32 screen_stride, dest;
  495. u32 fg;
  496. u16 bpp = (info->var.bits_per_pixel >> 3);
  497. /* grab spinlock */
  498. spin_lock(&s1d13xxxfb_bitblt_lock);
  499. /* bytes per x width */
  500. screen_stride = (bpp * info->var.xres);
  501. /* bytes to starting point */
  502. dest = ((rect->dy * screen_stride) + (bpp * rect->dx));
  503. dbg_blit("(solidfill) dx=%d, dy=%d, stride=%d, dest=%d\n"
  504. "(solidfill) : rect_width=%d, rect_height=%d\n",
  505. rect->dx, rect->dy, screen_stride, dest,
  506. rect->width - 1, rect->height - 1);
  507. dbg_blit("(solidfill) : xres=%d, yres=%d, bpp=%d\n",
  508. info->var.xres, info->var.yres,
  509. info->var.bits_per_pixel);
  510. dbg_blit("(solidfill) : rop=%d\n", rect->rop);
  511. /* We split the destination into the three registers */
  512. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dest & 0x00ff));
  513. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, ((dest >> 8) & 0x00ff));
  514. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, ((dest >> 16) & 0x00ff));
  515. /* give information regarding rectangel width */
  516. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, ((rect->width) & 0x00ff) - 1);
  517. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (rect->width >> 8));
  518. /* give information regarding rectangel height */
  519. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, ((rect->height) & 0x00ff) - 1);
  520. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (rect->height >> 8));
  521. if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
  522. info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
  523. fg = ((u32 *)info->pseudo_palette)[rect->color];
  524. dbg_blit("(solidfill) truecolor/directcolor\n");
  525. dbg_blit("(solidfill) pseudo_palette[%d] = %d\n", rect->color, fg);
  526. } else {
  527. fg = rect->color;
  528. dbg_blit("(solidfill) color = %d\n", rect->color);
  529. }
  530. /* set foreground color */
  531. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC0, (fg & 0xff));
  532. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC1, (fg >> 8) & 0xff);
  533. /* set rectangual region of memory (rectangle and not linear) */
  534. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0);
  535. /* set operation mode SOLID_FILL */
  536. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, BBLT_SOLID_FILL);
  537. /* set bits per pixel (1 = 16bpp, 0 = 8bpp) */
  538. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (info->var.bits_per_pixel >> 4));
  539. /* set the memory offset for the bblt in word sizes */
  540. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (screen_stride >> 1) & 0x00ff);
  541. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (screen_stride >> 9));
  542. /* and away we go.... */
  543. s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80);
  544. /* wait until its done */
  545. bltbit_wait_bitclear(info, 0x80, 8000);
  546. /* let others play */
  547. spin_unlock(&s1d13xxxfb_bitblt_lock);
  548. }
  549. /* framebuffer information structures */
  550. static struct fb_ops s1d13xxxfb_fbops = {
  551. .owner = THIS_MODULE,
  552. .fb_set_par = s1d13xxxfb_set_par,
  553. .fb_setcolreg = s1d13xxxfb_setcolreg,
  554. .fb_blank = s1d13xxxfb_blank,
  555. .fb_pan_display = s1d13xxxfb_pan_display,
  556. /* gets replaced at chip detection time */
  557. .fb_fillrect = cfb_fillrect,
  558. .fb_copyarea = cfb_copyarea,
  559. .fb_imageblit = cfb_imageblit,
  560. };
  561. static int s1d13xxxfb_width_tab[2][4] __devinitdata = {
  562. {4, 8, 16, -1},
  563. {9, 12, 18, -1},
  564. };
  565. /**
  566. * s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to
  567. * hardware setup.
  568. * @info: frame buffer structure
  569. *
  570. * We setup the framebuffer structures according to the current
  571. * hardware setup. On some machines, the BIOS will have filled
  572. * the chip registers with such info, on others, these values will
  573. * have been written in some init procedure. In any case, the
  574. * software values needs to match the hardware ones. This is what
  575. * this function ensures.
  576. *
  577. * Note: some of the hardcoded values here might need some love to
  578. * work on various chips, and might need to no longer be hardcoded.
  579. */
  580. static void __devinit
  581. s1d13xxxfb_fetch_hw_state(struct fb_info *info)
  582. {
  583. struct fb_var_screeninfo *var = &info->var;
  584. struct fb_fix_screeninfo *fix = &info->fix;
  585. struct s1d13xxxfb_par *par = info->par;
  586. u8 panel, display;
  587. u16 offset;
  588. u32 xres, yres;
  589. u32 xres_virtual, yres_virtual;
  590. int bpp, lcd_bpp;
  591. int is_color, is_dual, is_tft;
  592. int lcd_enabled, crt_enabled;
  593. fix->type = FB_TYPE_PACKED_PIXELS;
  594. /* general info */
  595. par->display = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
  596. crt_enabled = (par->display & 0x02) != 0;
  597. lcd_enabled = (par->display & 0x01) != 0;
  598. if (lcd_enabled && crt_enabled)
  599. printk(KERN_WARNING PFX "Warning: LCD and CRT detected, using LCD\n");
  600. if (lcd_enabled)
  601. display = s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_MODE);
  602. else /* CRT */
  603. display = s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_MODE);
  604. bpp = display & 0x07;
  605. switch (bpp) {
  606. case 2: /* 4 bpp */
  607. case 3: /* 8 bpp */
  608. var->bits_per_pixel = 8;
  609. var->red.offset = var->green.offset = var->blue.offset = 0;
  610. var->red.length = var->green.length = var->blue.length = 8;
  611. break;
  612. case 5: /* 16 bpp */
  613. s1d13xxxfb_setup_truecolour(info);
  614. break;
  615. default:
  616. dbg("bpp: %i\n", bpp);
  617. }
  618. fb_alloc_cmap(&info->cmap, 256, 0);
  619. /* LCD info */
  620. panel = s1d13xxxfb_readreg(par, S1DREG_PANEL_TYPE);
  621. is_color = (panel & 0x04) != 0;
  622. is_dual = (panel & 0x02) != 0;
  623. is_tft = (panel & 0x01) != 0;
  624. lcd_bpp = s1d13xxxfb_width_tab[is_tft][(panel >> 4) & 3];
  625. if (lcd_enabled) {
  626. xres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_HWIDTH) + 1) * 8;
  627. yres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT0) +
  628. ((s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT1) & 0x03) << 8) + 1);
  629. offset = (s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF0) +
  630. ((s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF1) & 0x7) << 8));
  631. } else { /* crt */
  632. xres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_HWIDTH) + 1) * 8;
  633. yres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT0) +
  634. ((s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT1) & 0x03) << 8) + 1);
  635. offset = (s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF0) +
  636. ((s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF1) & 0x7) << 8));
  637. }
  638. xres_virtual = offset * 16 / var->bits_per_pixel;
  639. yres_virtual = fix->smem_len / (offset * 2);
  640. var->xres = xres;
  641. var->yres = yres;
  642. var->xres_virtual = xres_virtual;
  643. var->yres_virtual = yres_virtual;
  644. var->xoffset = var->yoffset = 0;
  645. fix->line_length = offset * 2;
  646. var->grayscale = !is_color;
  647. var->activate = FB_ACTIVATE_NOW;
  648. dbg(PFX "bpp=%d, lcd_bpp=%d, "
  649. "crt_enabled=%d, lcd_enabled=%d\n",
  650. var->bits_per_pixel, lcd_bpp, crt_enabled, lcd_enabled);
  651. dbg(PFX "xres=%d, yres=%d, vxres=%d, vyres=%d "
  652. "is_color=%d, is_dual=%d, is_tft=%d\n",
  653. xres, yres, xres_virtual, yres_virtual, is_color, is_dual, is_tft);
  654. }
  655. static int
  656. s1d13xxxfb_remove(struct platform_device *pdev)
  657. {
  658. struct fb_info *info = platform_get_drvdata(pdev);
  659. struct s1d13xxxfb_par *par = NULL;
  660. if (info) {
  661. par = info->par;
  662. if (par && par->regs) {
  663. /* disable output & enable powersave */
  664. s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, 0x00);
  665. s1d13xxxfb_writereg(par, S1DREG_PS_CNF, 0x11);
  666. iounmap(par->regs);
  667. }
  668. fb_dealloc_cmap(&info->cmap);
  669. if (info->screen_base)
  670. iounmap(info->screen_base);
  671. framebuffer_release(info);
  672. }
  673. release_mem_region(pdev->resource[0].start,
  674. pdev->resource[0].end - pdev->resource[0].start +1);
  675. release_mem_region(pdev->resource[1].start,
  676. pdev->resource[1].end - pdev->resource[1].start +1);
  677. return 0;
  678. }
  679. static int __devinit
  680. s1d13xxxfb_probe(struct platform_device *pdev)
  681. {
  682. struct s1d13xxxfb_par *default_par;
  683. struct fb_info *info;
  684. struct s1d13xxxfb_pdata *pdata = NULL;
  685. int ret = 0;
  686. int i;
  687. u8 revision, prod_id;
  688. dbg("probe called: device is %p\n", pdev);
  689. printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
  690. /* enable platform-dependent hardware glue, if any */
  691. if (pdev->dev.platform_data)
  692. pdata = pdev->dev.platform_data;
  693. if (pdata && pdata->platform_init_video)
  694. pdata->platform_init_video();
  695. if (pdev->num_resources != 2) {
  696. dev_err(&pdev->dev, "invalid num_resources: %i\n",
  697. pdev->num_resources);
  698. ret = -ENODEV;
  699. goto bail;
  700. }
  701. /* resource[0] is VRAM, resource[1] is registers */
  702. if (pdev->resource[0].flags != IORESOURCE_MEM
  703. || pdev->resource[1].flags != IORESOURCE_MEM) {
  704. dev_err(&pdev->dev, "invalid resource type\n");
  705. ret = -ENODEV;
  706. goto bail;
  707. }
  708. if (!request_mem_region(pdev->resource[0].start,
  709. pdev->resource[0].end - pdev->resource[0].start +1, "s1d13xxxfb mem")) {
  710. dev_dbg(&pdev->dev, "request_mem_region failed\n");
  711. ret = -EBUSY;
  712. goto bail;
  713. }
  714. if (!request_mem_region(pdev->resource[1].start,
  715. pdev->resource[1].end - pdev->resource[1].start +1, "s1d13xxxfb regs")) {
  716. dev_dbg(&pdev->dev, "request_mem_region failed\n");
  717. ret = -EBUSY;
  718. goto bail;
  719. }
  720. info = framebuffer_alloc(sizeof(struct s1d13xxxfb_par) + sizeof(u32) * 256, &pdev->dev);
  721. if (!info) {
  722. ret = -ENOMEM;
  723. goto bail;
  724. }
  725. platform_set_drvdata(pdev, info);
  726. default_par = info->par;
  727. default_par->regs = ioremap_nocache(pdev->resource[1].start,
  728. pdev->resource[1].end - pdev->resource[1].start +1);
  729. if (!default_par->regs) {
  730. printk(KERN_ERR PFX "unable to map registers\n");
  731. ret = -ENOMEM;
  732. goto bail;
  733. }
  734. info->pseudo_palette = default_par->pseudo_palette;
  735. info->screen_base = ioremap_nocache(pdev->resource[0].start,
  736. pdev->resource[0].end - pdev->resource[0].start +1);
  737. if (!info->screen_base) {
  738. printk(KERN_ERR PFX "unable to map framebuffer\n");
  739. ret = -ENOMEM;
  740. goto bail;
  741. }
  742. /* production id is top 6 bits */
  743. prod_id = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
  744. /* revision id is lower 2 bits */
  745. revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) & 0x3;
  746. ret = -ENODEV;
  747. for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_prod_ids); i++) {
  748. if (prod_id == s1d13xxxfb_prod_ids[i]) {
  749. /* looks like we got it in our list */
  750. default_par->prod_id = prod_id;
  751. default_par->revision = revision;
  752. ret = 0;
  753. break;
  754. }
  755. }
  756. if (!ret) {
  757. printk(KERN_INFO PFX "chip production id %i = %s\n",
  758. prod_id, s1d13xxxfb_prod_names[i]);
  759. printk(KERN_INFO PFX "chip revision %i\n", revision);
  760. } else {
  761. printk(KERN_INFO PFX
  762. "unknown chip production id %i, revision %i\n",
  763. prod_id, revision);
  764. printk(KERN_INFO PFX "please contant maintainer\n");
  765. goto bail;
  766. }
  767. info->fix = s1d13xxxfb_fix;
  768. info->fix.mmio_start = pdev->resource[1].start;
  769. info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start + 1;
  770. info->fix.smem_start = pdev->resource[0].start;
  771. info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start + 1;
  772. printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n",
  773. default_par->regs, info->fix.smem_len / 1024, info->screen_base);
  774. info->par = default_par;
  775. info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
  776. info->fbops = &s1d13xxxfb_fbops;
  777. switch(prod_id) {
  778. case S1D13506_PROD_ID: /* activate acceleration */
  779. s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill;
  780. s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea;
  781. info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
  782. FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
  783. break;
  784. default:
  785. break;
  786. }
  787. /* perform "manual" chip initialization, if needed */
  788. if (pdata && pdata->initregs)
  789. s1d13xxxfb_runinit(info->par, pdata->initregs, pdata->initregssize);
  790. s1d13xxxfb_fetch_hw_state(info);
  791. if (register_framebuffer(info) < 0) {
  792. ret = -EINVAL;
  793. goto bail;
  794. }
  795. printk(KERN_INFO "fb%d: %s frame buffer device\n",
  796. info->node, info->fix.id);
  797. return 0;
  798. bail:
  799. s1d13xxxfb_remove(pdev);
  800. return ret;
  801. }
  802. #ifdef CONFIG_PM
  803. static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state)
  804. {
  805. struct fb_info *info = platform_get_drvdata(dev);
  806. struct s1d13xxxfb_par *s1dfb = info->par;
  807. struct s1d13xxxfb_pdata *pdata = NULL;
  808. /* disable display */
  809. lcd_enable(s1dfb, 0);
  810. crt_enable(s1dfb, 0);
  811. if (dev->dev.platform_data)
  812. pdata = dev->dev.platform_data;
  813. #if 0
  814. if (!s1dfb->disp_save)
  815. s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL);
  816. if (!s1dfb->disp_save) {
  817. printk(KERN_ERR PFX "no memory to save screen");
  818. return -ENOMEM;
  819. }
  820. memcpy_fromio(s1dfb->disp_save, info->screen_base, info->fix.smem_len);
  821. #else
  822. s1dfb->disp_save = NULL;
  823. #endif
  824. if (!s1dfb->regs_save)
  825. s1dfb->regs_save = kmalloc(info->fix.mmio_len, GFP_KERNEL);
  826. if (!s1dfb->regs_save) {
  827. printk(KERN_ERR PFX "no memory to save registers");
  828. return -ENOMEM;
  829. }
  830. /* backup all registers */
  831. memcpy_fromio(s1dfb->regs_save, s1dfb->regs, info->fix.mmio_len);
  832. /* now activate power save mode */
  833. s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x11);
  834. if (pdata && pdata->platform_suspend_video)
  835. return pdata->platform_suspend_video();
  836. else
  837. return 0;
  838. }
  839. static int s1d13xxxfb_resume(struct platform_device *dev)
  840. {
  841. struct fb_info *info = platform_get_drvdata(dev);
  842. struct s1d13xxxfb_par *s1dfb = info->par;
  843. struct s1d13xxxfb_pdata *pdata = NULL;
  844. /* awaken the chip */
  845. s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
  846. /* do not let go until SDRAM "wakes up" */
  847. while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01))
  848. udelay(10);
  849. if (dev->dev.platform_data)
  850. pdata = dev->dev.platform_data;
  851. if (s1dfb->regs_save) {
  852. /* will write RO regs, *should* get away with it :) */
  853. memcpy_toio(s1dfb->regs, s1dfb->regs_save, info->fix.mmio_len);
  854. kfree(s1dfb->regs_save);
  855. }
  856. if (s1dfb->disp_save) {
  857. memcpy_toio(info->screen_base, s1dfb->disp_save,
  858. info->fix.smem_len);
  859. kfree(s1dfb->disp_save); /* XXX kmalloc()'d when? */
  860. }
  861. if ((s1dfb->display & 0x01) != 0)
  862. lcd_enable(s1dfb, 1);
  863. if ((s1dfb->display & 0x02) != 0)
  864. crt_enable(s1dfb, 1);
  865. if (pdata && pdata->platform_resume_video)
  866. return pdata->platform_resume_video();
  867. else
  868. return 0;
  869. }
  870. #endif /* CONFIG_PM */
  871. static struct platform_driver s1d13xxxfb_driver = {
  872. .probe = s1d13xxxfb_probe,
  873. .remove = s1d13xxxfb_remove,
  874. #ifdef CONFIG_PM
  875. .suspend = s1d13xxxfb_suspend,
  876. .resume = s1d13xxxfb_resume,
  877. #endif
  878. .driver = {
  879. .name = S1D_DEVICENAME,
  880. },
  881. };
  882. static int __init
  883. s1d13xxxfb_init(void)
  884. {
  885. #ifndef MODULE
  886. if (fb_get_options("s1d13xxxfb", NULL))
  887. return -ENODEV;
  888. #endif
  889. return platform_driver_register(&s1d13xxxfb_driver);
  890. }
  891. static void __exit
  892. s1d13xxxfb_exit(void)
  893. {
  894. platform_driver_unregister(&s1d13xxxfb_driver);
  895. }
  896. module_init(s1d13xxxfb_init);
  897. module_exit(s1d13xxxfb_exit);
  898. MODULE_LICENSE("GPL");
  899. MODULE_DESCRIPTION("Framebuffer driver for S1D13xxx devices");
  900. MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Thibaut VARENE <varenet@parisc-linux.org>");