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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *      epson1356fb.c  --  Epson SED1356 Framebuffer Driver
  3.  *
  4.  * Copyright 2001, 2002 MontaVista Software Inc.
  5.  * Author: MontaVista Software, Inc.
  6.  *          stevel@mvista.com or source@mvista.com
  7.  *
  8.  *  This program is free software; you can redistribute  it and/or modify it
  9.  *  under  the terms of  the GNU General  Public License as published by the
  10.  *  Free Software Foundation;  either version 2 of the  License, or (at your
  11.  *  option) any later version.
  12.  *
  13.  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  14.  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  15.  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  16.  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  17.  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18.  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  19.  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20.  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  21.  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22.  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23.  *
  24.  *  You should have received a copy of the  GNU General Public License along
  25.  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  26.  *  675 Mass Ave, Cambridge, MA 02139, USA.
  27.  *
  28.  * 
  29.  * TODO:
  30.  *
  31.  *  Revision history
  32.  *    03.12.2001  0.1   Initial release
  33.  *
  34.  */
  35. #include <linux/config.h>
  36. #include <linux/version.h>
  37. #include <linux/module.h>
  38. #include <linux/kernel.h>
  39. #include <linux/errno.h>
  40. #include <linux/string.h>
  41. #include <linux/mm.h>
  42. #include <linux/tty.h>
  43. #include <linux/slab.h>
  44. #include <linux/vmalloc.h>
  45. #include <linux/delay.h>
  46. #include <linux/interrupt.h>
  47. #include <linux/fb.h>
  48. #include <linux/selection.h>
  49. #include <linux/console.h>
  50. #include <linux/init.h>
  51. #include <linux/pci.h>
  52. #include <linux/nvram.h>
  53. #include <linux/kd.h>
  54. #include <linux/vt_kern.h>
  55. #include <asm/io.h>
  56. #include <asm/uaccess.h>
  57. #include <linux/timer.h>
  58. #include <linux/pagemap.h>
  59. #include <asm/pgalloc.h>
  60. #include <asm/uaccess.h>
  61. #include <asm/tlb.h>
  62. #ifdef CONFIG_MTRR
  63. #include <asm/mtrr.h>
  64. #endif
  65. #include <video/fbcon.h>
  66. #include <video/fbcon-cfb8.h>
  67. #include <video/fbcon-cfb16.h>
  68. #include <video/fbcon-cfb24.h>
  69. #include <video/fbcon-cfb32.h>
  70. #include <linux/spinlock.h>
  71. #include <linux/e1356fb.h>
  72. #ifdef CONFIG_MIPS_AU1000
  73. #include <asm/au1000.h>
  74. #endif
  75. #define E1356FB_DEBUG 1
  76. #undef E1356FB_VERBOSE_DEBUG
  77. #undef SHADOW_FRAME_BUFFER
  78. #include "epson1356fb.h"
  79. static char *options;
  80. MODULE_PARM(options, "s");
  81. /*
  82.  *  Frame buffer device API
  83.  */
  84. static int e1356fb_open(struct fb_info *fb, int user);
  85. static int e1356fb_release(struct fb_info *fb, int user);
  86. static int e1356fb_get_fix(struct fb_fix_screeninfo* fix, 
  87.    int con,
  88.    struct fb_info* fb);
  89. static int e1356fb_get_var(struct fb_var_screeninfo* var, 
  90.    int con,
  91.    struct fb_info* fb);
  92. static int e1356fb_set_var(struct fb_var_screeninfo* var,
  93.    int con,
  94.    struct fb_info* fb);
  95. static int e1356fb_pan_display(struct fb_var_screeninfo* var, 
  96.        int con,
  97.        struct fb_info* fb);
  98. static int e1356fb_get_cmap(struct fb_cmap *cmap, 
  99.     int kspc, 
  100.     int con,
  101.     struct fb_info* info);
  102. static int e1356fb_set_cmap(struct fb_cmap* cmap, 
  103.     int kspc, 
  104.     int con,
  105.     struct fb_info* info);
  106. static int e1356fb_ioctl(struct inode* inode, 
  107.  struct file* file, 
  108.  u_int cmd,
  109.  u_long arg, 
  110.  int con, 
  111.  struct fb_info* info);
  112. static int e1356fb_mmap(struct fb_info *info,
  113. struct file *file,
  114. struct vm_area_struct *vma);
  115. /*
  116.  *  Interface to the low level console driver
  117.  */
  118. static int  e1356fb_switch_con(int con, 
  119.        struct fb_info* fb);
  120. static int  e1356fb_updatevar(int con, 
  121.       struct fb_info* fb);
  122. static void e1356fb_blank(int blank, 
  123.   struct fb_info* fb);
  124. /*
  125.  *  Internal routines
  126.  */
  127. static void e1356fb_set_par(const struct e1356fb_par* par,
  128.     struct fb_info_e1356* 
  129.     info);
  130. static int  e1356fb_var_to_par(const struct fb_var_screeninfo *var,
  131.        struct e1356fb_par* par,
  132.        const struct fb_info_e1356* info);
  133. static int  e1356fb_par_to_var(struct fb_var_screeninfo* var,
  134.        struct e1356fb_par* par,
  135.        const struct fb_info_e1356* info);
  136. static int  e1356fb_encode_fix(struct fb_fix_screeninfo* fix,
  137.        const struct e1356fb_par* par,
  138.        const struct fb_info_e1356* info);
  139. static void e1356fb_set_dispsw(struct display* disp, 
  140.        struct fb_info_e1356* info,
  141.        int bpp, 
  142.        int accel);
  143. static int  e1356fb_getcolreg(u_int regno,
  144.       u_int* red, 
  145.       u_int* green, 
  146.       u_int* blue,
  147.       u_int* transp, 
  148.       struct fb_info* fb);
  149. static int  e1356fb_setcolreg(u_int regno, 
  150.       u_int red, 
  151.       u_int green, 
  152.       u_int blue,
  153.       u_int transp, 
  154.       struct fb_info* fb);
  155. static void  e1356fb_install_cmap(struct display *d, 
  156.   struct fb_info *info);
  157. static void e1356fb_hwcursor_init(struct fb_info_e1356* info);
  158. static void e1356fb_createcursorshape(struct display* p);
  159. static void e1356fb_createcursor(struct display * p);  
  160. /*
  161.  * do_xxx: Hardware-specific functions
  162.  */
  163. static void  do_pan_var(struct fb_var_screeninfo* var,
  164. struct fb_info_e1356* i);
  165. static void  do_flashcursor(unsigned long ptr);
  166. static void  doBlt_Move(const struct e1356fb_par* par,
  167. struct fb_info_e1356* i,
  168. blt_info_t* blt);
  169. static void  doBlt_SolidFill(const struct e1356fb_par* par,
  170.      struct fb_info_e1356* i,
  171.      blt_info_t* blt);
  172. /*
  173.  *  Interface used by the world
  174.  */
  175. int e1356fb_init(void);
  176. void e1356fb_setup(char *options, int *ints);
  177. static int currcon = 0;
  178. static struct fb_ops e1356fb_ops = {
  179. owner: THIS_MODULE,
  180. fb_open:        e1356fb_open,
  181. fb_release:     e1356fb_release,
  182. fb_get_fix: e1356fb_get_fix,
  183. fb_get_var: e1356fb_get_var,
  184. fb_set_var: e1356fb_set_var,
  185. fb_get_cmap:    e1356fb_get_cmap,
  186. fb_set_cmap:    e1356fb_set_cmap,
  187. fb_pan_display: e1356fb_pan_display,
  188. fb_mmap:        e1356fb_mmap,
  189. };
  190. #define PCI_VENDOR_ID_EPSON         0x10f4
  191. #define PCI_DEVICE_ID_EPSON_SDU1356 0x1300
  192. static struct fb_info_e1356 fb_info;
  193. static struct e1356fb_fix boot_fix; // boot options
  194. static struct e1356fb_par boot_par; // boot options
  195. static int e1356_remap_page_range(unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot);
  196. /* ------------------------------------------------------------------------- 
  197.  *                      Hardware-specific funcions
  198.  * ------------------------------------------------------------------------- */
  199. /*
  200.  * The SED1356 has only a 16-bit wide data bus, so some embedded
  201.  * implementations with 32-bit CPU's (Alchemy Pb1000) may not
  202.  * correctly emulate a 32-bit write to the framebuffer by splitting
  203.  * the write into two seperate 16-bit writes. So it is safest to
  204.  * only do byte or half-word writes to the fb. This routine assumes
  205.  * fbaddr is atleast aligned on a half-word boundary.
  206.  */
  207. static inline void
  208. fbfill(u16* fbaddr, u8 val, int size)
  209. {
  210. u16 valw = (u16)val | ((u16)val << 8);
  211. for ( ; size >= 2; size -= 2)
  212. writew(valw, fbaddr++);
  213. if (size)
  214. writeb(val, (u8*)fbaddr);
  215. }
  216. static inline int
  217. e1356_wait_bitclr(u8* reg, u8 bit, int timeout)
  218. {
  219. while (readb(reg) & bit) {
  220. udelay(10);
  221. if (!--timeout)
  222. break;
  223. }
  224. return timeout;
  225. }
  226. static inline int
  227. e1356_wait_bitset(u8* reg, u8 bit, int timeout)
  228. {
  229. while (!(readb(reg) & bit)) {
  230. udelay(10);
  231. if (!--timeout)
  232. break;
  233. }
  234. return timeout;
  235. }
  236. static struct fb_videomode panel_modedb[] = {
  237. {
  238. /* 320x240 @ 109 Hz, 33.3 kHz hsync */
  239. NULL, 109, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/3),
  240. 16, 16, 32, 24, 48, 8,
  241. 0, FB_VMODE_NONINTERLACED
  242. }, {
  243. /* 640x480 @ 84 Hz, 48.1 kHz hsync */
  244. NULL, 84, 640, 480, KHZ2PICOS(MAX_PIXCLOCK/1),
  245. 96, 32, 32, 48, 64, 8,
  246. 0, FB_VMODE_NONINTERLACED
  247. }, {
  248. /* 800x600 @ 76 Hz, 46.3 kHz hsync */
  249. NULL, 76, 800, 600, KHZ2PICOS(MAX_PIXCLOCK/1),
  250. 32, 10, 1, 1, 22, 1,
  251. 0, FB_VMODE_NONINTERLACED
  252. }
  253. };
  254. static struct fb_videomode crt_modedb[] = {
  255. {
  256. /* 320x240 @ 84 Hz, 31.25 kHz hsync */
  257. NULL, 84, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/2),
  258. 128, 128, 60, 60, 64, 8,
  259. 0, FB_VMODE_NONINTERLACED
  260. }, {
  261. /* 320x240 @ 109 Hz, 33.3 kHz hsync */
  262. NULL, 109, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/3),
  263. 16, 16, 32, 24, 48, 8,
  264. 0, FB_VMODE_NONINTERLACED
  265. }, {
  266. /* 512x384 @ 77 Hz, 31.25 kHz hsync */
  267. NULL, 77, 512, 384, KHZ2PICOS(MAX_PIXCLOCK/2),
  268. 48, 16, 16, 1, 64, 3,
  269. 0, FB_VMODE_NONINTERLACED
  270. }, {
  271. /* 640x400 @ 88 Hz, 43.1 kHz hsync */
  272. NULL, 88, 640, 400, KHZ2PICOS(MAX_PIXCLOCK/1),
  273. 128, 96, 32, 48, 64, 8,
  274. 0, FB_VMODE_NONINTERLACED
  275. }, {
  276. /* 640x480 @ 84 Hz, 48.1 kHz hsync */
  277. NULL, 84, 640, 480, KHZ2PICOS(MAX_PIXCLOCK/1),
  278. 96, 32, 32, 48, 64, 8,
  279. 0, FB_VMODE_NONINTERLACED
  280. }, {
  281. /* 768x576 @ 62 Hz, 38.5 kHz hsync */
  282. NULL, 62, 768, 576, KHZ2PICOS(MAX_PIXCLOCK/1),
  283. 144, 16, 28, 6, 112, 4,
  284. 0, FB_VMODE_NONINTERLACED
  285. }, {
  286. /* 800x600 @ 60 Hz, 37.9 kHz hsync */
  287. NULL, 60, 800, 600, KHZ2PICOS(MAX_PIXCLOCK/1),
  288. 88, 40, 23, 1, 128, 4,
  289. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
  290. FB_VMODE_NONINTERLACED
  291. }
  292. };
  293. static struct fb_videomode ntsc_modedb[] = {
  294. {
  295. /* 640x480 @ 62 Hz, requires flicker filter */
  296. //NULL, 62, 640, 480, 34921, 213, 57, 20, 2, 0, 0,
  297. NULL, 62, 640, 480, KHZ2PICOS(2*NTSC_PIXCLOCK),
  298. 200, 70, 15, 7, 0, 0,
  299. FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
  300. }
  301. };
  302. static struct fb_videomode pal_modedb[] = {
  303. {
  304. /* 640x480 @ 56 Hz, requires flicker filter */
  305. NULL, 56, 640, 480, KHZ2PICOS(2*PAL_PIXCLOCK),
  306. 350, 145, 49, 23, 0, 0,
  307. FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
  308. }
  309. };
  310. static inline void
  311. fb_videomode_to_var(struct fb_videomode* mode,
  312.     struct fb_var_screeninfo*var)
  313. {
  314. var->xres = mode->xres;
  315. var->yres = mode->yres;
  316. var->pixclock = mode->pixclock;
  317. var->left_margin = mode->left_margin;
  318. var->right_margin = mode->right_margin;
  319. var->upper_margin = mode->upper_margin;
  320. var->lower_margin = mode->lower_margin;
  321. var->hsync_len = mode->hsync_len;
  322. var->vsync_len = mode->vsync_len;
  323. var->sync = mode->sync;
  324. var->vmode = mode->vmode;
  325. }
  326. static int
  327. e1356fb_get_mode(const struct fb_info_e1356 *info,
  328.  int xres,
  329.  int yres,
  330.  struct fb_videomode ** modedb,
  331.  struct fb_videomode ** mode)
  332. {
  333. struct fb_videomode * ret;
  334. int i, dbsize;
  335. if (IS_PANEL(info->fix.disp_type)) {
  336. ret = panel_modedb;
  337. dbsize = sizeof(panel_modedb)/sizeof(struct fb_videomode);
  338. } else if (info->fix.disp_type == DISP_TYPE_CRT) {
  339. ret = crt_modedb;
  340. dbsize = sizeof(crt_modedb)/sizeof(struct fb_videomode);
  341. } else if (info->fix.disp_type == DISP_TYPE_NTSC) {
  342. ret = ntsc_modedb;
  343. dbsize = sizeof(ntsc_modedb)/sizeof(struct fb_videomode);
  344. } else {
  345. ret = pal_modedb;
  346. dbsize = sizeof(pal_modedb)/sizeof(struct fb_videomode);
  347. }
  348. if (modedb)
  349. *modedb = ret;
  350. for (i=0; i<dbsize; i++) {
  351. if (xres == ret[i].xres && yres == ret[i].yres) {
  352. *mode = &ret[i];
  353. break;
  354. }
  355. }
  356. if (i == dbsize)
  357. return -EINVAL;
  358. return dbsize;
  359. }
  360. #ifdef E1356FB_VERBOSE_DEBUG
  361. static void
  362. dump_par(const struct e1356fb_par* par)
  363. {
  364. DPRINTK("width:       %dn", par->width);
  365. DPRINTK("height:      %dn", par->height);
  366. DPRINTK("width_virt:  %dn", par->width_virt);
  367. DPRINTK("height_virt: %dn", par->height_virt);
  368. DPRINTK("bpp:         %dn", par->bpp);
  369. DPRINTK("pixclock:    %dn", par->ipclk.pixclk);
  370. DPRINTK("horiz_ndp:   %dn", par->horiz_ndp);
  371. DPRINTK("vert_ndp:    %dn", par->vert_ndp);
  372. DPRINTK("hsync_pol:   %dn", par->hsync_pol);
  373. DPRINTK("hsync_start: %dn", par->hsync_start);
  374. DPRINTK("hsync_width: %dn", par->hsync_width);
  375. DPRINTK("vsync_pol:   %dn", par->vsync_pol);
  376. DPRINTK("vsync_start: %dn", par->vsync_start);
  377. DPRINTK("vsync_width: %dn", par->vsync_width);
  378. DPRINTK("cmap_len:    %dn", par->cmap_len);
  379. }
  380. static void
  381. dump_display_regs(reg_dispcfg_t* dispcfg, reg_dispmode_t* dispmode)
  382. {
  383. DPRINTK("hdw:            0x%02xn", readb(&dispcfg->hdw));
  384. DPRINTK("hndp:           0x%02xn", readb(&dispcfg->hndp));
  385. DPRINTK("hsync_start:    0x%02xn", readb(&dispcfg->hsync_start));
  386. DPRINTK("hsync_pulse:    0x%02xn", readb(&dispcfg->hsync_pulse));
  387. DPRINTK("vdh0:           0x%02xn", readb(&dispcfg->vdh0));
  388. DPRINTK("vdh1:           0x%02xn", readb(&dispcfg->vdh1));
  389. DPRINTK("vndp:           0x%02xn", readb(&dispcfg->vndp));
  390. DPRINTK("vsync_start:    0x%02xn", readb(&dispcfg->vsync_start));
  391. DPRINTK("vsync_pulse:    0x%02xn", readb(&dispcfg->vsync_pulse));
  392. DPRINTK("tv_output_ctrl: 0x%02xnn", readb(&dispcfg->tv_output_ctrl));
  393. DPRINTK("disp_mode:        0x%02xn", readb(&dispmode->disp_mode));
  394. DPRINTK("lcd_misc:         0x%02xn", readb(&dispmode->lcd_misc));
  395. DPRINTK("start_addr0:      0x%02xn", readb(&dispmode->start_addr0));
  396. DPRINTK("start_addr1:      0x%02xn", readb(&dispmode->start_addr1));
  397. DPRINTK("start_addr2:      0x%02xn", readb(&dispmode->start_addr2));
  398. DPRINTK("mem_addr_offset0: 0x%02xn", readb(&dispmode->mem_addr_offset0));
  399. DPRINTK("mem_addr_offset1: 0x%02xn", readb(&dispmode->mem_addr_offset1));
  400. DPRINTK("pixel_panning:    0x%02xn", readb(&dispmode->pixel_panning));
  401. DPRINTK("fifo_high_thresh: 0x%02xn", readb(&dispmode->fifo_high_thresh));
  402. DPRINTK("fifo_low_thresh:  0x%02xn", readb(&dispmode->fifo_low_thresh));
  403. }
  404. static void
  405. dump_fb(u8* base, int len)
  406. {
  407. int i;
  408. DPRINTK("FB memory dump, start 0x%p, len %d", base, len);
  409. for (i=0; i<len; i++) {
  410. if (!(i%16))
  411. printk("n%p: %02x ", &base[i], readb(&base[i]));
  412. else
  413. printk("%02x ", readb(&base[i]));
  414. }
  415. printk("n");
  416. }
  417. #endif // E1356FB_VERBOSE_DEBUG
  418. // Input:  ipclk->clksrc, ipclk->pixclk_d
  419. // Output: ipclk->pixclk, ipclk->error, and ipclk->divisor
  420. static int
  421. get_nearest_pixclk_div(pixclock_info_t* ipclk, int x2)
  422. {
  423. int pixclk_d = ipclk->pixclk_d;
  424. int clksrc = ipclk->clksrc;
  425. if (x2) clksrc *= 2;
  426. if (clksrc < (3*pixclk_d+1)/2)
  427. ipclk->divisor = 1;
  428. else if (clksrc < (5*pixclk_d+1)/2)
  429. ipclk->divisor = 2;
  430. else if (clksrc < (7*pixclk_d+1)/2)
  431. ipclk->divisor = 3;
  432. else if (clksrc < (9*pixclk_d+1)/2)
  433. ipclk->divisor = 4;
  434. else
  435. return -ENXIO;
  436. ipclk->pixclk = clksrc / ipclk->divisor;
  437. ipclk->error = (100*(pixclk_d - ipclk->pixclk)) / pixclk_d;
  438. return 0;
  439. }
  440. static int
  441. e1356_calc_pixclock(const struct fb_info_e1356 *info,
  442.     pixclock_info_t* ipclk)
  443. {
  444. int src_sel=-1, flicker_mult=0;
  445. pixclock_info_t test, ret;
  446.     
  447. if (ipclk->pixclk > info->max_pixclock)
  448. return -ENXIO;
  449. test.pixclk_d = ipclk->pixclk_d;
  450. ret.error = 100;
  451. if (IS_TV(info->fix.disp_type) &&
  452.     (info->fix.tv_filt & TV_FILT_FLICKER))
  453. flicker_mult = 0x80;
  454. test.clksrc = info->fix.busclk;
  455. if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
  456.     abs(test.error) < abs(ret.error)) {
  457. ret = test;
  458. src_sel = 0x01;
  459. }
  460. test.clksrc = info->fix.mclk;
  461. if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
  462.     abs(test.error) < abs(ret.error)) {
  463. ret = test;
  464. src_sel = 0x03;
  465. }
  466. test.clksrc = info->fix.clki;
  467. if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
  468.     abs(test.error) < abs(ret.error)) {
  469. ret = test;
  470. src_sel = 0x00;
  471. }
  472. test.clksrc = info->fix.clki2;
  473. if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&
  474.     abs(test.error) < abs(ret.error)) {
  475. ret = test;
  476. src_sel = 0x02;
  477. }
  478. if (ret.error > MAX_PCLK_ERROR_LOWER ||
  479.     ret.error < MAX_PCLK_ERROR_HIGHER)
  480. return -ENXIO;
  481.     
  482. ret.pixclk_bits = flicker_mult | ((ret.divisor-1)<<4) | src_sel;
  483. *ipclk = ret;
  484. return 0;
  485. }
  486. static inline int
  487. e1356_engine_wait_complete(reg_bitblt_t* bltreg)
  488. {
  489. return e1356_wait_bitclr(&bltreg->ctrl0, 0x80, 5000);
  490. }
  491. static inline int
  492. e1356_engine_wait_busy(reg_bitblt_t* bltreg)
  493. {
  494. return e1356_wait_bitset(&bltreg->ctrl0, 0x80, 5000);
  495. }
  496. static void
  497. e1356fb_engine_init(const struct e1356fb_par* par,
  498.     struct fb_info_e1356* info)
  499. {
  500. reg_bitblt_t* bltreg = info->reg.bitblt;
  501.     
  502. e1356_engine_wait_complete(bltreg);
  503. writeb(0, &bltreg->ctrl0);
  504. writeb(0, &bltreg->ctrl1);
  505. writeb(0, &bltreg->rop_code);
  506. writeb(0, &bltreg->operation);
  507. writeb(0, &bltreg->src_start_addr0);
  508. writeb(0, &bltreg->src_start_addr1);
  509. writeb(0, &bltreg->src_start_addr2);
  510. writeb(0, &bltreg->dest_start_addr0);
  511. writeb(0, &bltreg->dest_start_addr1);
  512. writeb(0, &bltreg->dest_start_addr2);
  513. writew(0, &bltreg->mem_addr_offset0);
  514. writew(0, &bltreg->width0);
  515. writew(0, &bltreg->height0);
  516. writew(0, &bltreg->bg_color0);
  517. writew(0, &bltreg->fg_color0);
  518. }
  519. static void doBlt_Write(const struct e1356fb_par* par,
  520. struct fb_info_e1356* info,
  521. blt_info_t* blt)
  522. {
  523. reg_bitblt_t* bltreg = info->reg.bitblt;
  524. int nWords, nTotalWords;
  525. u32 srcphase, dstAddr;
  526. u16* w16;
  527. u32 stride = par->width_virt * par->Bpp;
  528. dstAddr = blt->dst_x * par->Bpp + blt->dst_y * stride;
  529. srcphase = (u32)blt->src & 1;
  530.     
  531. if (blt->attribute & BLT_ATTR_TRANSPARENT)
  532. writew(blt->bg_color, &bltreg->bg_color0);
  533. else
  534. writeb(blt->rop, &bltreg->rop_code);
  535.     
  536. writeb(blt->operation, &bltreg->operation);
  537. writeb((u8)srcphase, &bltreg->src_start_addr0);
  538. writew(stride/2, &bltreg->mem_addr_offset0);
  539. writeb(dstAddr, &bltreg->dest_start_addr0);
  540. writeb(dstAddr>>8, &bltreg->dest_start_addr1);
  541. writeb(dstAddr>>16, &bltreg->dest_start_addr2);
  542. writew(blt->dst_width-1, &bltreg->width0);
  543. writew(blt->dst_height-1, &bltreg->height0);
  544. // program color format operation
  545. writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
  546. // start it up
  547. writeb(0x80, &bltreg->ctrl0);
  548. // wait for it to actually start
  549. e1356_engine_wait_busy(bltreg);
  550. // calculate the number of 16 bit words per one blt line
  551. nWords = srcphase + ((blt->dst_width - srcphase)*par->Bpp + 1) / 2;
  552. nTotalWords = nWords*blt->dst_height;
  553. w16 = (u16*)((u32)blt->src & 0xfffffffe);   // Word aligned
  554. while (nTotalWords > 0) {
  555. int j, nFIFO;
  556. u8 ctrl0;
  557. // read the FIFO status
  558. ctrl0 = readb(&bltreg->ctrl0);
  559. if ((ctrl0 & 0x30) == 0x20)
  560. // FIFO is at least half full, but not full
  561. nFIFO = 1;
  562. else if ((ctrl0 & 0x40) == 0)
  563. // FIFO is empty
  564. nFIFO = 16;
  565. else
  566. // FIFO is full
  567. continue;
  568. for (j = 0; j < nFIFO && nTotalWords > 0; j++,nTotalWords--)
  569. writew(*w16++, info->reg.bitblt_data);
  570. }
  571. e1356_engine_wait_complete(bltreg);
  572. }
  573. static void
  574. doBlt_SolidFill(const struct e1356fb_par* par,
  575. struct fb_info_e1356* info,
  576. blt_info_t* blt)
  577. {
  578. reg_bitblt_t* bltreg = info->reg.bitblt;
  579. u32 width = blt->dst_width, height = blt->dst_height;
  580. u32 stride = par->width_virt * par->Bpp;
  581. u32 dest_addr = (blt->dst_y * stride) + (blt->dst_x * par->Bpp);
  582. if (width == 0 || height == 0)
  583. return;
  584. // program dest address
  585. writeb(dest_addr & 0x00ff, &bltreg->dest_start_addr0);
  586. writeb((dest_addr>>8) & 0x00ff, &bltreg->dest_start_addr1);
  587. writeb((dest_addr>>16) & 0x00ff, &bltreg->dest_start_addr2);
  588. // program width and height of solid-fill blit
  589. writew(width-1, &bltreg->width0);
  590. writew(height-1, &bltreg->height0);
  591. // program color of fill
  592. writew(blt->fg_color, &bltreg->fg_color0);
  593. // select solid-fill BLIT
  594. writeb(BLT_SOLID_FILL, &bltreg->operation);
  595. // program color format operation
  596. writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
  597. // program BLIT memory offset
  598. writew(stride/2, &bltreg->mem_addr_offset0);
  599. // start it up (self completes)
  600. writeb(0x80, &bltreg->ctrl0);
  601. e1356_engine_wait_complete(bltreg);
  602. }
  603. static void
  604. doBlt_Move(const struct e1356fb_par* par,
  605.    struct fb_info_e1356* info,
  606.    blt_info_t* blt)
  607. {
  608. reg_bitblt_t* bltreg = info->reg.bitblt;
  609. int neg_dir=0;
  610. u32 dest_addr, src_addr;
  611. u32 bpp = par->bpp;
  612. u32 stride = par->width_virt * par->Bpp; // virt line length in bytes
  613. u32 srcx = blt->src_x, srcy = blt->src_y;
  614. u32 dstx = blt->dst_x, dsty = blt->dst_y;
  615. u32 width = blt->dst_width, height = blt->dst_height;
  616.     
  617. if (width == 0 || height == 0)
  618. return;
  619.    
  620. src_addr = srcx*par->Bpp + srcy*stride;
  621. dest_addr = dstx*par->Bpp + dsty*stride;
  622. /*
  623.  * See if regions overlap and dest region is beyond source region.
  624.  * If so, we need to do a move BLT in negative direction. Only applies
  625.  * if the BLT is not transparent.
  626.  */
  627. if (!(blt->attribute & BLT_ATTR_TRANSPARENT)) {
  628. if ((srcx + width  > dstx) && (srcx < dstx + width) &&
  629.     (srcy + height > dsty) && (srcy < dsty + height) &&
  630.     (dest_addr > src_addr)) {
  631. neg_dir = 1;
  632. // negative direction : get the coords of lower right corner
  633. src_addr += stride * (height-1) + par->Bpp * (width-1);
  634. dest_addr += stride * (height-1) + par->Bpp * (width-1);
  635. }
  636. }
  637.     
  638. // program BLIT memory offset
  639. writew(stride/2, &bltreg->mem_addr_offset0);
  640. // program src and dest addresses
  641. writeb(src_addr & 0x00ff, &bltreg->src_start_addr0);
  642. writeb((src_addr>>8) & 0x00ff, &bltreg->src_start_addr1);
  643. writeb((src_addr>>16) & 0x00ff, &bltreg->src_start_addr2);
  644. writeb(dest_addr & 0x00ff, &bltreg->dest_start_addr0);
  645. writeb((dest_addr>>8) & 0x00ff, &bltreg->dest_start_addr1);
  646. writeb((dest_addr>>16) & 0x00ff, &bltreg->dest_start_addr2);
  647. // program width and height of blit
  648. writew(width-1, &bltreg->width0);
  649. writew(height-1, &bltreg->height0);
  650. // program color format operation
  651. writeb(bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
  652. // set the blt type
  653. if (blt->attribute & BLT_ATTR_TRANSPARENT) {
  654. writew(blt->bg_color, &bltreg->bg_color0);
  655. writeb(BLT_MOVE_POS_TRANSP, &bltreg->operation); 
  656. } else {
  657. writeb(blt->rop, &bltreg->rop_code);
  658. // select pos/neg move BLIT
  659. writeb(neg_dir ? BLT_MOVE_NEG_ROP : BLT_MOVE_POS_ROP,
  660.        &bltreg->operation); 
  661. }
  662. // start it up (self completes)
  663. writeb(0x80, &bltreg->ctrl0);
  664. e1356_engine_wait_complete(bltreg);
  665. }
  666. static void doBlt_ColorExpand(const struct e1356fb_par* par,
  667.       struct fb_info_e1356* info,
  668.       blt_info_t* blt)
  669. {
  670. reg_bitblt_t* bltreg = info->reg.bitblt;
  671. int i, j, nWords, Sx, Sy;
  672. u32 dstAddr;
  673. u16* wpt, *wpt1;
  674. u32 stride = par->width_virt * par->Bpp;
  675. if (blt->dst_width == 0 || blt->dst_height == 0)
  676. return;
  677. Sx = blt->src_x;
  678. Sy = blt->src_y;
  679. writeb((7 - Sx%8), &bltreg->rop_code);
  680. writeb(blt->operation, &bltreg->operation);
  681. writeb((u8)(Sx & 1), &bltreg->src_start_addr0);
  682. dstAddr = blt->dst_x*par->Bpp + blt->dst_y * stride;
  683. writeb(dstAddr, &bltreg->dest_start_addr0);
  684. writeb(dstAddr>>8, &bltreg->dest_start_addr1);
  685. writeb(dstAddr>>16, &bltreg->dest_start_addr2);
  686. // program color format operation
  687. writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);
  688. writew(stride/2, &bltreg->mem_addr_offset0);
  689. writew(blt->dst_width-1, &bltreg->width0);
  690. writew(blt->dst_height-1, &bltreg->height0);
  691. writew(blt->bg_color, &bltreg->bg_color0);
  692. writew(blt->fg_color, &bltreg->fg_color0);
  693. // start it up
  694. writeb(0x80, &bltreg->ctrl0);
  695. // wait for it to actually start
  696. e1356_engine_wait_busy(bltreg);
  697. // calculate the number of 16 bit words per one blt line
  698. nWords = (Sx%16 + blt->dst_width + 15)/16;
  699. wpt = blt->src + (Sy*blt->srcstride + Sx/16)/2;
  700. for (i = 0; i < blt->dst_height; i++) {
  701. wpt1 = wpt;
  702. for (j = 0; j < nWords; j++) {
  703. // loop until FIFO becomes empty...
  704. e1356_wait_bitclr(&bltreg->ctrl0, 0x40, 10000);
  705. writew(*wpt1++, info->reg.bitblt_data);
  706. }
  707. wpt += blt->srcstride/2;
  708. }
  709. e1356_engine_wait_complete(bltreg);
  710. }
  711. /*
  712.  * The BitBLT operation dispatcher
  713.  */
  714. static int
  715. doBlt(const struct e1356fb_par* par,
  716.       struct fb_info_e1356* info,
  717.       blt_info_t* blt)
  718. {
  719. /*
  720.  * Make sure we're not reentering in the middle of an
  721.  * active BitBLT operation. ALWAYS call this dispatcher
  722.  * and not one of the above BLT routines directly, or you
  723.  * run the risk of overlapping BLT operations, which can
  724.  * cause complete system hangs.
  725.      */
  726. if (readb(&info->reg.bitblt->ctrl0) & 0x80)
  727. return -ENXIO;
  728.     
  729. switch (blt->operation) {
  730. case BLT_MOVE_POS_ROP:
  731. case BLT_MOVE_NEG_ROP:
  732. case BLT_MOVE_POS_TRANSP:
  733. doBlt_Move(par, info, blt);
  734. break;
  735. case BLT_COLOR_EXP:
  736. case BLT_COLOR_EXP_TRANSP:
  737. doBlt_ColorExpand(par, info, blt);
  738. break;
  739. case BLT_SOLID_FILL:
  740. doBlt_SolidFill(par, info, blt);
  741. break;
  742. case BLT_WRITE_ROP:
  743. case BLT_WRITE_TRANSP:
  744. doBlt_Write(par, info, blt);
  745. break;
  746. case BLT_READ:
  747. case BLT_PAT_FILL_ROP:
  748. case BLT_PAT_FILL_TRANSP:
  749. case BLT_MOVE_COLOR_EXP:
  750. case BLT_MOVE_COLOR_EXP_TRANSP:
  751. DPRINTK("BitBLT operation 0x%02x not implemented yetn",
  752. blt->operation);
  753. return -ENXIO;
  754. default:
  755. DPRINTK("Unknown BitBLT operation 0x%02xn", blt->operation);
  756. return -ENXIO;
  757. }
  758.     
  759. return 0;
  760. }
  761. // Initializes blt->src and blt->srcstride
  762. static void fill_putcs_buffer(struct display *p,
  763.       blt_info_t* blt,
  764.       const unsigned short* str,
  765.       int count)
  766. {   
  767. int row, i, j;
  768. u8* b1, *b2;
  769. u32 fw = fontwidth(p);
  770. u32 fwb = (fw + 7) >> 3;
  771. u32 fh = fontheight(p);
  772. int bytesPerChar = fwb * fh;
  773. if (count*bytesPerChar > PAGE_SIZE) {
  774. // Truncate the string if it overflows putcs_buffer, which is
  775. // one page in size.
  776. count = PAGE_SIZE/bytesPerChar - 1;
  777. }
  778. blt->srcstride = (fwb*count + 1) & ~1; //round up to be even
  779. b1 = (u8*)blt->src;
  780. for (row = 0; row < fh; row++) {
  781. b2 = b1;
  782. for (i = 0; i < count; i++) {
  783. for (j=0; j<fwb; j++)
  784. *b2++ = p->fontdata[(str[i] & p->charmask) *
  785.    bytesPerChar +
  786.    row*fwb + j];
  787. }
  788. b1 += blt->srcstride;
  789. }
  790. }
  791. /*
  792.  * Set the color of a palette entry in 8bpp mode 
  793.  */
  794. static inline void
  795. do_setpalentry(reg_lut_t* lut, unsigned regno,
  796.        u8 r, u8 g, u8 b)
  797. {
  798. writeb(0x00, &lut->mode);
  799. writeb((u8)regno, &lut->addr);
  800. writeb(r&0xf0, &lut->data);
  801. writeb(g&0xf0, &lut->data);
  802. writeb(b&0xf0, &lut->data);
  803. }
  804.    
  805. static void
  806. do_pan_var(struct fb_var_screeninfo* var, struct fb_info_e1356* info)
  807. {
  808. u32 pixel_start, start_addr;
  809. u8 pixel_pan;
  810. struct e1356fb_par* par = &info->current_par;
  811. reg_misc_t* misc = info->reg.misc;
  812. reg_dispmode_t* dispmode = (IS_PANEL(info->fix.disp_type)) ?
  813. info->reg.lcd_mode : info->reg.crttv_mode;
  814. pixel_start = var->yoffset * par->width_virt + var->xoffset;
  815. start_addr = (pixel_start * par->Bpp) / 2;
  816. pixel_pan = (par->bpp == 8) ? (u8)(pixel_start & 1) : 0;
  817.     
  818. if (readb(&misc->disp_mode) != 0) {
  819. reg_dispcfg_t* dispcfg = (IS_PANEL(info->fix.disp_type)) ?
  820. info->reg.lcd_cfg : info->reg.crttv_cfg;
  821. // wait for the end of the current VNDP
  822. e1356_wait_bitclr(&dispcfg->vndp, 0x80, 5000);
  823. // now wait for the start of a new VNDP
  824. e1356_wait_bitset(&dispcfg->vndp, 0x80, 5000);
  825. }
  826.     
  827. writeb((u8)(start_addr & 0xff), &dispmode->start_addr0);
  828. writeb((u8)((start_addr>>8) & 0xff), &dispmode->start_addr1);
  829. writeb((u8)((start_addr>>16) & 0xff), &dispmode->start_addr2);
  830. writeb(pixel_pan, &dispmode->pixel_panning);
  831. }
  832. /*
  833.  * Invert the hardware cursor image (timerfunc)  
  834.  */
  835. static void
  836. do_flashcursor(unsigned long ptr)
  837. {
  838. u8 curs_ctrl;
  839. struct fb_info_e1356* info = (struct fb_info_e1356 *)ptr;
  840. reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ?
  841. info->reg.lcd_inkcurs : info->reg.crttv_inkcurs;
  842. spin_lock(&info->cursor.lock);
  843. // toggle cursor enable bit
  844. curs_ctrl = readb(&inkcurs->ctrl);
  845. writeb((curs_ctrl ^ 0x01) & 0x01, &inkcurs->ctrl);
  846. info->cursor.timer.expires = jiffies+HZ/2;
  847. add_timer(&info->cursor.timer);
  848. spin_unlock(&info->cursor.lock);
  849. }
  850. #ifdef SHADOW_FRAME_BUFFER
  851. /*
  852.  * Write BLT the shadow frame buffer to the real fb (timerfunc)  
  853.  */
  854. static void
  855. do_write_shadow_fb(unsigned long ptr)
  856. {
  857. blt_info_t blt;
  858. struct fb_info_e1356 *info = (struct fb_info_e1356*)ptr;
  859. struct fb_info* fb = &info->fb_info;
  860. struct e1356fb_par* par = &info->current_par;
  861. u32 stride = par->width_virt * par->Bpp;
  862. unsigned long j_start = jiffies;
  863.     
  864. blt.src_x = blt.src_y = 0;
  865. blt.attribute = 0;
  866. blt.dst_width = par->width;
  867. blt.dst_height = par->height;
  868. blt.dst_y = fb->var.yoffset;
  869. blt.dst_x = fb->var.xoffset;
  870. blt.operation = BLT_WRITE_ROP;
  871. blt.rop = 0x0c; // ROP: destination = source
  872. blt.src = (u16*)(info->shadow.fb + blt.dst_x * par->Bpp +
  873.  blt.dst_y * stride);
  874. doBlt(par, info, &blt);
  875.     
  876. info->shadow.timer.expires = jiffies+HZ/2;
  877. add_timer(&info->shadow.timer);
  878. //DPRINTK("delta jiffies = %ldn", jiffies - j_start);
  879. }
  880. #endif
  881. /* ------------------------------------------------------------------------- 
  882.  *              Hardware independent part, interface to the world
  883.  * ------------------------------------------------------------------------- */
  884. static void
  885. e1356_cfbX_clear_margins(struct vc_data* conp, struct display* p,
  886.  int bottom_only)
  887. {
  888. blt_info_t blt;
  889. unsigned int cw=fontwidth(p);
  890. unsigned int ch=fontheight(p);
  891. unsigned int rw=p->var.xres % cw;
  892. unsigned int bh=p->var.yres % ch;
  893. unsigned int rs=p->var.xres - rw;
  894. unsigned int bs=p->var.yres - bh;
  895. //DPRINTK("n");
  896. if (!bottom_only && rw) { 
  897. blt.dst_x = p->var.xoffset+rs;
  898. blt.dst_y = p->var.yoffset;
  899. blt.dst_height = p->var.yres;
  900. blt.dst_width = rw;
  901. blt.attribute = 0;
  902. blt.fg_color = 0;
  903. blt.operation = BLT_SOLID_FILL;
  904. doBlt (&fb_info.current_par, &fb_info, &blt);
  905. }
  906.     
  907. if (bh) { 
  908. blt.dst_x = p->var.xoffset;
  909. blt.dst_y = p->var.yoffset+bs;
  910. blt.dst_height = bh;
  911. blt.dst_width = rs;
  912. blt.attribute = 0;
  913. blt.fg_color = 0;
  914. blt.operation = BLT_SOLID_FILL;
  915. doBlt (&fb_info.current_par, &fb_info, &blt);
  916. }
  917. }
  918. static void
  919. e1356_cfbX_bmove(struct display* p, 
  920.  int sy, 
  921.  int sx, 
  922.  int dy,
  923.  int dx, 
  924.  int height, 
  925.  int width)
  926. {
  927. blt_info_t blt;
  928.     
  929. //DPRINTK("(%d,%d) to (%d,%d) size (%d,%d)n", sx,sy,dx,dy,width,height);
  930. blt.src_x = fontwidth_x8(p)*sx;
  931. blt.src_y = fontheight(p)*sy;
  932. blt.dst_x = fontwidth_x8(p)*dx;
  933. blt.dst_y = fontheight(p)*dy;
  934. blt.src_height = blt.dst_height = fontheight(p)*height;
  935. blt.src_width = blt.dst_width = fontwidth_x8(p)*width;
  936. blt.attribute = 0;
  937. blt.rop = 0x0c;
  938. /*
  939.  * The move BLT routine will actually decide between a pos/neg
  940.  * move BLT. This is just so that the BLT dispatcher knows to
  941.  * call the move BLT routine.
  942.  */
  943. blt.operation = BLT_MOVE_POS_ROP;
  944. doBlt (&fb_info.current_par, &fb_info, &blt);
  945. }
  946. static void
  947. e1356_cfb8_putc(struct vc_data* conp,
  948. struct display* p,
  949. int c, int yy,int xx)
  950. {   
  951. blt_info_t blt;
  952. u32 fgx,bgx;
  953. u32 fw = fontwidth_x8(p);
  954. u32 fh = fontheight(p);
  955. u16 cs = (u16)c;
  956. fgx = attr_fgcol(p, c);
  957. bgx = attr_bgcol(p, c);
  958. blt.src_x = blt.src_y = 0;
  959. blt.attribute = 0;
  960. blt.dst_width = fw;
  961. blt.dst_height = fh;
  962. blt.dst_y = yy * fh;
  963. blt.dst_x = xx * fw;
  964. blt.bg_color = bgx;
  965. blt.fg_color = fgx;
  966. blt.operation = BLT_COLOR_EXP;
  967. blt.src = fb_info.putcs_buffer;
  968. fill_putcs_buffer(p, &blt, &cs, 1);
  969. doBlt(&fb_info.current_par, &fb_info, &blt);
  970. }
  971. static void
  972. e1356_cfb16_putc(struct vc_data* conp,
  973.  struct display* p,
  974.  int c, int yy,int xx)
  975. {   
  976. blt_info_t blt;
  977. u32 fgx,bgx;
  978. u32 fw = fontwidth_x8(p);
  979. u32 fh = fontheight(p);
  980. u16 cs = (u16)c;
  981.     
  982. fgx = ((u16*)p->dispsw_data)[attr_fgcol(p,c)];
  983. bgx = ((u16*)p->dispsw_data)[attr_bgcol(p,c)];
  984. blt.src_x = blt.src_y = 0;
  985. blt.attribute = 0;
  986. blt.dst_width = fw;
  987. blt.dst_height = fh;
  988. blt.dst_y = yy * fh;
  989. blt.dst_x = xx * fw;
  990. blt.bg_color = bgx;
  991. blt.fg_color = fgx;
  992. blt.operation = BLT_COLOR_EXP;
  993. blt.src = fb_info.putcs_buffer;
  994. fill_putcs_buffer(p, &blt, &cs, 1);
  995. doBlt(&fb_info.current_par, &fb_info, &blt);
  996. }
  997. static void
  998. e1356_cfb8_putcs(struct vc_data* conp,
  999.  struct display* p,
  1000.  const unsigned short *s,int count,int yy,int xx)
  1001. {
  1002. blt_info_t blt;
  1003. u32 fgx,bgx;
  1004. u32 fw = fontwidth_x8(p);
  1005. u32 fh = fontheight(p);
  1006. //DPRINTK("n");
  1007. fgx=attr_fgcol(p, *s);
  1008. bgx=attr_bgcol(p, *s);
  1009. blt.src_x = blt.src_y = 0;
  1010. blt.attribute = 0;
  1011. blt.dst_width = count * fw;
  1012. blt.dst_height = fh;
  1013. blt.dst_y = yy * fh;
  1014. blt.dst_x = xx * fw;
  1015. blt.bg_color = bgx;
  1016. blt.fg_color = fgx;
  1017. blt.operation = BLT_COLOR_EXP;
  1018. blt.src = fb_info.putcs_buffer;
  1019. fill_putcs_buffer(p, &blt, s, count);
  1020. doBlt(&fb_info.current_par, &fb_info, &blt);
  1021. }
  1022. static void
  1023. e1356_cfb16_putcs(struct vc_data* conp,
  1024.   struct display* p,
  1025.   const unsigned short *s,int count,int yy,int xx)
  1026. {
  1027. blt_info_t blt;
  1028. u32 fgx,bgx;
  1029. u32 fw = fontwidth_x8(p);
  1030. u32 fh = fontheight(p);
  1031. //DPRINTK("n");
  1032. fgx=((u16*)p->dispsw_data)[attr_fgcol(p,*s)];
  1033. bgx=((u16*)p->dispsw_data)[attr_bgcol(p,*s)];
  1034. blt.src_x = blt.src_y = 0;
  1035. blt.attribute = 0;
  1036. blt.dst_width = count * fw;
  1037. blt.dst_height = fh;
  1038. blt.dst_y = yy * fh;
  1039. blt.dst_x = xx * fw;
  1040. blt.bg_color = bgx;
  1041. blt.fg_color = fgx;
  1042. blt.operation = BLT_COLOR_EXP;
  1043. blt.src = fb_info.putcs_buffer;
  1044. fill_putcs_buffer(p, &blt, s, count);
  1045. doBlt(&fb_info.current_par, &fb_info, &blt);
  1046. }
  1047. static void
  1048. e1356_cfb8_clear(struct vc_data* conp, 
  1049.  struct display* p, 
  1050.  int sy,
  1051.  int sx, 
  1052.  int height, 
  1053.  int width)
  1054. {
  1055. blt_info_t blt;
  1056. u32 bg = attr_bgcol_ec(p,conp);
  1057. //DPRINTK("(%d,%d) size (%d,%d)n", sx,sy,width,height);
  1058. blt.dst_x = fontwidth_x8(p)*sx;
  1059. blt.dst_y = fontheight(p)*sy;
  1060. blt.dst_height = fontheight(p)*height;
  1061. blt.dst_width = fontwidth_x8(p)*width;
  1062. blt.attribute = 0;
  1063. blt.fg_color = bg;
  1064. blt.operation = BLT_SOLID_FILL;
  1065. doBlt (&fb_info.current_par, &fb_info, &blt);
  1066. }
  1067. static void
  1068. e1356_cfb16_clear(struct vc_data* conp, 
  1069.   struct display* p, 
  1070.   int sy,
  1071.   int sx, 
  1072.   int height, 
  1073.   int width)
  1074. {
  1075. blt_info_t blt;
  1076. u32 bg = ((u16*)p->dispsw_data)[attr_bgcol_ec(p,conp)];
  1077. //DPRINTK("(%d,%d) size (%d,%d)n", sx,sy,width,height);
  1078. blt.dst_x = fontwidth_x8(p)*sx;
  1079. blt.dst_y = fontheight(p)*sy;
  1080. blt.dst_height = fontheight(p)*height;
  1081. blt.dst_width = fontwidth_x8(p)*width;
  1082. blt.attribute = 0;
  1083. blt.fg_color = bg;
  1084. blt.operation = BLT_SOLID_FILL;
  1085. doBlt (&fb_info.current_par, &fb_info, &blt);
  1086. }
  1087. static void
  1088. e1356_cfbX_revc(struct display *p, int xx, int yy)
  1089. {
  1090. // not used if h/w cursor
  1091. //DPRINTK("n");
  1092. }
  1093. static void
  1094. e1356_cfbX_cursor(struct display *p, int mode, int x, int y) 
  1095. {
  1096. unsigned long flags;
  1097. struct fb_info_e1356 *info=(struct fb_info_e1356 *)p->fb_info;
  1098. reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ?
  1099. info->reg.lcd_inkcurs : info->reg.crttv_inkcurs;
  1100.     
  1101. //DPRINTK("n");
  1102. if (mode == CM_ERASE) {
  1103. if (info->cursor.state != CM_ERASE) {
  1104. spin_lock_irqsave(&info->cursor.lock,flags);
  1105. info->cursor.state = CM_ERASE;
  1106. del_timer(&(info->cursor.timer));
  1107. writeb(0x00, &inkcurs->ctrl);
  1108. spin_unlock_irqrestore(&info->cursor.lock,flags);
  1109. }
  1110. return;
  1111. }
  1112.     
  1113. if ((p->conp->vc_cursor_type & CUR_HWMASK) != info->cursor.type)
  1114. e1356fb_createcursor(p);
  1115.     
  1116. x *= fontwidth_x8(p);
  1117. y *= fontheight(p);
  1118. x -= p->var.xoffset;
  1119. y -= p->var.yoffset;
  1120.     
  1121. spin_lock_irqsave(&info->cursor.lock,flags);
  1122. if ((x != info->cursor.x) || (y != info->cursor.y) ||
  1123.     (info->cursor.redraw)) {
  1124. info->cursor.x = x;
  1125. info->cursor.y = y;
  1126. info->cursor.redraw = 0;
  1127. writeb(0x01, &inkcurs->ctrl);
  1128. writew(x, &inkcurs->x_pos0);
  1129. writew(y, &inkcurs->y_pos0);
  1130. /* fix cursor color - XFree86 forgets to restore it properly */
  1131. writeb(0x00, &inkcurs->blue0);
  1132. writeb(0x00, &inkcurs->green0);
  1133. writeb(0x00, &inkcurs->red0);
  1134. writeb(0x1f, &inkcurs->blue1);
  1135. writeb(0x3f, &inkcurs->green1);
  1136. writeb(0x1f, &inkcurs->red1);
  1137. }
  1138. info->cursor.state = CM_DRAW;
  1139. mod_timer(&info->cursor.timer, jiffies+HZ/2);
  1140. spin_unlock_irqrestore(&info->cursor.lock,flags);
  1141. }
  1142. #ifdef FBCON_HAS_CFB8
  1143. static struct display_switch fbcon_e1356_8 = {
  1144. setup: fbcon_cfb8_setup, 
  1145. bmove: e1356_cfbX_bmove, 
  1146. clear: e1356_cfb8_clear, 
  1147. putc: e1356_cfb8_putc,
  1148. putcs: e1356_cfb8_putcs, 
  1149. revc: e1356_cfbX_revc,   
  1150. cursor: e1356_cfbX_cursor, 
  1151. clear_margins: e1356_cfbX_clear_margins,
  1152. fontwidthmask: FONTWIDTHRANGE(6,16)
  1153. };
  1154. #endif
  1155. #ifdef FBCON_HAS_CFB16
  1156. static struct display_switch fbcon_e1356_16 = {
  1157. setup: fbcon_cfb16_setup, 
  1158. bmove: e1356_cfbX_bmove, 
  1159. clear: e1356_cfb16_clear, 
  1160. putc: e1356_cfb16_putc,
  1161. putcs: e1356_cfb16_putcs, 
  1162. revc: e1356_cfbX_revc, 
  1163. cursor: e1356_cfbX_cursor, 
  1164. clear_margins: e1356_cfbX_clear_margins,
  1165. fontwidthmask: FONTWIDTHRANGE(6,16)
  1166. };
  1167. #endif
  1168. /* ------------------------------------------------------------------------- */
  1169. static void
  1170. e1356fb_set_par(const struct e1356fb_par* par,
  1171. struct fb_info_e1356* info)
  1172. {
  1173. reg_dispcfg_t* dispcfg=NULL;
  1174. reg_dispmode_t* dispmode=NULL;
  1175. u8* pclk_cfg=NULL;
  1176. u8 width, hndp=0, hsync_start=0, hsync_width=0;
  1177. u8 vndp, vsync_start, vsync_width=0, display_mode;
  1178. u8 main_display_mode=0;
  1179. u16 height, addr_offset;
  1180. int disp_type = info->fix.disp_type;
  1181. DPRINTK("%dx%d-%dbpp @ %d Hz, %d kHz hsyncn",
  1182. par->width, par->height, par->bpp,
  1183. par->vsync_freq, (((2*par->hsync_freq)/1000)+1)/2);
  1184. #ifdef E1356FB_VERBOSE_DEBUG
  1185. dump_par(par);
  1186. #endif
  1187.     
  1188. info->current_par = *par;
  1189. width = (par->width >> 3) - 1;
  1190. display_mode = (par->bpp == 8) ? 0x03 : 0x05;
  1191. addr_offset = (par->width_virt * par->Bpp) / 2;
  1192. vsync_start = (disp_type == DISP_TYPE_LCD) ? 0 : par->vsync_start - 1;
  1193. height = par->height - 1;
  1194. vndp = par->vert_ndp - 1;
  1195. switch (disp_type) {
  1196. case DISP_TYPE_LCD:
  1197. dispcfg = info->reg.lcd_cfg;
  1198. dispmode = info->reg.lcd_mode;
  1199. pclk_cfg = &info->reg.clk_cfg->lcd_pclk_cfg;
  1200. hndp = (par->horiz_ndp >> 3) - 1;
  1201. hsync_start = 0;
  1202. hsync_width = par->hsync_pol ? 0x00 : 0x80;
  1203. vsync_width = par->vsync_pol ? 0x00 : 0x80;
  1204. main_display_mode = 0x01;
  1205. break;
  1206. case DISP_TYPE_TFT:
  1207. dispcfg = info->reg.lcd_cfg;
  1208. dispmode = info->reg.lcd_mode;
  1209. pclk_cfg = &info->reg.clk_cfg->lcd_pclk_cfg;
  1210. hndp = (par->horiz_ndp >> 3) - 1;
  1211. hsync_start = (par->bpp == 8) ?
  1212. (par->hsync_start - 4) >> 3 :
  1213. (par->hsync_start - 6) >> 3;
  1214. hsync_width =
  1215. (par->hsync_pol ? 0x80 : 0x00) |
  1216. ((par->hsync_width >> 3) - 1);
  1217. vsync_width =
  1218. (par->vsync_pol ? 0x80 : 0x00) |
  1219. (par->vsync_width - 1);
  1220. main_display_mode = 0x01;
  1221. break;
  1222. case DISP_TYPE_CRT:
  1223. dispcfg = info->reg.crttv_cfg;
  1224. dispmode = info->reg.crttv_mode;
  1225. pclk_cfg = &info->reg.clk_cfg->crttv_pclk_cfg;
  1226. hndp = (par->horiz_ndp >> 3) - 1;
  1227. hsync_start = (par->bpp == 8) ?
  1228. (par->hsync_start - 3) >> 3 :
  1229. (par->hsync_start - 5) >> 3;
  1230. hsync_width =
  1231. (par->hsync_pol ? 0x80 : 0x00) |
  1232. ((par->hsync_width >> 3) - 1);
  1233. vsync_width =
  1234. (par->vsync_pol ? 0x80 : 0x00) |
  1235. (par->vsync_width - 1);
  1236. main_display_mode = 0x02;
  1237. break;
  1238. case DISP_TYPE_NTSC:
  1239. case DISP_TYPE_PAL:
  1240. dispcfg = info->reg.crttv_cfg;
  1241. dispmode = info->reg.crttv_mode;
  1242. pclk_cfg = &info->reg.clk_cfg->crttv_pclk_cfg;
  1243. hndp = (disp_type == DISP_TYPE_PAL) ?
  1244. (par->horiz_ndp - 7) >> 3 :
  1245. (par->horiz_ndp - 6) >> 3;
  1246. hsync_start = (par->bpp == 8) ?
  1247. (par->hsync_start + 7) >> 3 :
  1248. (par->hsync_start + 5) >> 3;
  1249. hsync_width = 0;
  1250. vsync_width = 0;
  1251. main_display_mode = (info->fix.tv_filt & TV_FILT_FLICKER) ?
  1252. 0x06 : 0x04;
  1253. break;
  1254. }
  1255. // Blast the regs!
  1256. // note: reset panning/scrolling (set start-addr and
  1257. // pixel pan regs to 0). Panning is handled by pan_display.
  1258. e1356_engine_wait_complete(info->reg.bitblt);
  1259. // disable display while initializing
  1260. writeb(0, &info->reg.misc->disp_mode);
  1261. writeb(par->ipclk.pixclk_bits, pclk_cfg);
  1262. writeb(width, &dispcfg->hdw);
  1263. writeb(hndp, &dispcfg->hndp);
  1264. writeb(hsync_start, &dispcfg->hsync_start);
  1265. writeb(hsync_width, &dispcfg->hsync_pulse);
  1266. writew(height, &dispcfg->vdh0);
  1267. writeb(vndp, &dispcfg->vndp);
  1268. writeb(vsync_start, &dispcfg->vsync_start);
  1269. writeb(vsync_width, &dispcfg->vsync_pulse);
  1270. writeb(display_mode, &dispmode->disp_mode);
  1271. if (info->fix.mmunalign && info->mmaped)
  1272. writeb(1, &dispmode->start_addr0);
  1273. else
  1274. writeb(0, &dispmode->start_addr0);
  1275. writeb(0, &dispmode->start_addr1);
  1276. writeb(0, &dispmode->start_addr2);
  1277. writew(addr_offset, &dispmode->mem_addr_offset0);
  1278. writeb(0, &dispmode->pixel_panning);
  1279. // reset BitBlt engine
  1280. e1356fb_engine_init(par, info);
  1281. #ifdef E1356FB_VERBOSE_DEBUG
  1282. dump_display_regs(dispcfg, dispmode);
  1283. #endif
  1284. /* clear out framebuffer memory */
  1285. fbfill(fb_info.membase_virt, 0, fb_info.fb_size);
  1286. // finally, enable display!
  1287. writeb(main_display_mode, &info->reg.misc->disp_mode); 
  1288. }
  1289. static int
  1290. e1356fb_verify_timing(struct e1356fb_par* par,
  1291.       const struct fb_info_e1356* info)
  1292. {
  1293. int disp_type = info->fix.disp_type;
  1294. // timing boundary checks
  1295. if (par->horiz_ndp > max_hndp[disp_type]) {
  1296. DPRINTK("horiz_ndp too big: %dn", par->horiz_ndp);
  1297. return -EINVAL;
  1298. }
  1299. if (par->vert_ndp > max_vndp[disp_type]) {
  1300. DPRINTK("vert_ndp too big: %dn", par->vert_ndp);
  1301. return -EINVAL;
  1302. }
  1303. if (disp_type != DISP_TYPE_LCD) {
  1304. if (par->hsync_start >
  1305.     max_hsync_start[(par->bpp==16)][disp_type]) {
  1306. DPRINTK("hsync_start too big: %dn",
  1307. par->hsync_start);
  1308. return -EINVAL;
  1309. }
  1310. if (par->vsync_start > max_vsync_start[disp_type]) {
  1311. DPRINTK("vsync_start too big: %dn",
  1312. par->vsync_start);
  1313. return -EINVAL;
  1314. }
  1315. if (!IS_TV(disp_type)) {
  1316. if (par->hsync_width > max_hsync_width[disp_type]) {
  1317. DPRINTK("hsync_width too big: %dn",
  1318. par->hsync_width);
  1319. return -EINVAL;
  1320. }
  1321. if (par->vsync_width > max_vsync_width[disp_type]) {
  1322. DPRINTK("vsync_width too big: %dn",
  1323. par->vsync_width);
  1324. return -EINVAL;
  1325. }
  1326. }
  1327. }
  1328. if (IS_TV(disp_type)) {
  1329. int tv_pixclk = (disp_type == DISP_TYPE_NTSC) ?
  1330. NTSC_PIXCLOCK : PAL_PIXCLOCK;
  1331. if (info->fix.tv_filt & TV_FILT_FLICKER)
  1332. tv_pixclk *= 2;
  1333. if (par->ipclk.pixclk_d != tv_pixclk) {
  1334. DPRINTK("invalid TV pixel clock %u kHzn",
  1335. par->ipclk.pixclk_d);
  1336. return -EINVAL;
  1337. }
  1338. }
  1339. if (e1356_calc_pixclock(info, &par->ipclk) < 0) {
  1340. DPRINTK("can't set pixel clock %u kHzn",
  1341. par->ipclk.pixclk_d);
  1342. return -EINVAL;
  1343. }
  1344.  
  1345. #ifdef E1356FB_VERBOSE_DEBUG
  1346. DPRINTK("desired pixclock = %d kHz, actual = %d kHz, error = %d%%n",
  1347. par->ipclk.pixclk_d, par->ipclk.pixclk, par->ipclk.error);
  1348. #endif
  1349.     
  1350. if (disp_type != DISP_TYPE_LCD) {
  1351. if (par->horiz_ndp < par->hsync_start + par->hsync_width) {
  1352. DPRINTK("invalid horiz. timingn");
  1353. return -EINVAL;
  1354. }
  1355. if (par->vert_ndp < par->vsync_start + par->vsync_width) {
  1356. DPRINTK("invalid vert. timingn");
  1357. return -EINVAL;
  1358. }
  1359. // SED1356 Hardware Functional Spec, section 13.5
  1360. if (disp_type == DISP_TYPE_NTSC &&
  1361.     ((par->width + par->horiz_ndp != 910) ||
  1362.      (par->height + 2*par->vert_ndp+1 != 525))) {
  1363. DPRINTK("invalid NTSC timingn");
  1364. return -EINVAL;
  1365. } else if (disp_type == DISP_TYPE_PAL &&
  1366.    ((par->width + par->horiz_ndp != 1135) ||
  1367.     (par->height + 2*par->vert_ndp+1 != 625))) {
  1368. DPRINTK("invalid PAL timingn");
  1369. return -EINVAL;
  1370. }
  1371. }
  1372.     
  1373. par->hsync_freq = (1000 * par->ipclk.pixclk) /
  1374. (par->width + par->horiz_ndp);
  1375. par->vsync_freq = par->hsync_freq / (par->height + par->vert_ndp);
  1376. if (par->hsync_freq < 30000 || par->hsync_freq > 90000) {
  1377. DPRINTK("hsync freq too %s: %u Hzn",
  1378. par->hsync_freq < 30000 ? "low" : "high",
  1379. par->hsync_freq);
  1380. return -EINVAL;
  1381. }
  1382. if (par->vsync_freq < 50 || par->vsync_freq > 110) {
  1383. DPRINTK("vsync freq too %s: %u Hzn",
  1384. par->vsync_freq < 50 ? "low" : "high",
  1385. par->vsync_freq);
  1386. return -EINVAL;
  1387. }
  1388. return 0;
  1389. }
  1390. static int
  1391. e1356fb_verify_par(struct e1356fb_par* par,
  1392.    const struct fb_info_e1356* info)
  1393. {
  1394. int disp_type = info->fix.disp_type;
  1395.     
  1396. if (par->bpp != 8 && par->bpp != 16) {
  1397. DPRINTK("depth not supported: %u bppn", par->bpp);
  1398. return -EINVAL;
  1399. }
  1400. if (par->width > par->width_virt) {
  1401. DPRINTK("virtual x resolution < physical x resolution not possiblen");
  1402. return -EINVAL;
  1403. }
  1404. if (par->height > par->height_virt) {
  1405. DPRINTK("virtual y resolution < physical y resolution not possiblen");
  1406. return -EINVAL;
  1407. }
  1408. if (par->width < 320 || par->width > 1024) {
  1409. DPRINTK("width not supported: %un", par->width);
  1410. return -EINVAL;
  1411. }
  1412. if ((disp_type == DISP_TYPE_LCD && (par->width % 16)) ||
  1413.     (disp_type == DISP_TYPE_TFT && (par->width % 8))) {
  1414. DPRINTK("invalid width for panel type: %un", par->width);
  1415. return -EINVAL;
  1416. }
  1417. if (par->height < 200 || par->height > 1024) {
  1418. DPRINTK("height not supported: %un", par->height);
  1419. return -EINVAL;
  1420. }
  1421. if (par->width_virt * par->height_virt * par->Bpp >
  1422.     info->fb_size) {
  1423. DPRINTK("not enough memory for virtual screen (%ux%ux%u)n",
  1424. par->width_virt, par->height_virt, par->bpp);
  1425. return -EINVAL;
  1426. }
  1427. return e1356fb_verify_timing(par, info);
  1428. }
  1429. static int
  1430. e1356fb_var_to_par(const struct fb_var_screeninfo* var,
  1431.    struct e1356fb_par* par,
  1432.    const struct fb_info_e1356* info)
  1433. {
  1434. if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  1435. DPRINTK("interlace not supportedn");
  1436. return -EINVAL;
  1437. }
  1438. memset(par, 0, sizeof(struct e1356fb_par));
  1439. par->width       = (var->xres + 15) & ~15; /* could sometimes be 8 */
  1440. par->width_virt  = var->xres_virtual;
  1441. par->height      = var->yres;
  1442. par->height_virt = var->yres_virtual;
  1443. par->bpp         = var->bits_per_pixel;
  1444. par->Bpp         = (par->bpp + 7) >> 3;
  1445. par->ipclk.pixclk_d = PICOS2KHZ(var->pixclock);
  1446. par->hsync_start = var->right_margin;
  1447. par->hsync_width = var->hsync_len;
  1448. par->vsync_start = var->lower_margin;
  1449. par->vsync_width = var->vsync_len;
  1450. par->horiz_ndp = var->left_margin + var->right_margin + var->hsync_len;
  1451. par->vert_ndp = var->upper_margin + var->lower_margin + var->vsync_len;
  1452. par->hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0;
  1453. par->vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0;
  1454. par->cmap_len  = (par->bpp == 8) ? 256 : 16;
  1455. return e1356fb_verify_par(par, info);
  1456. }
  1457. static int
  1458. e1356fb_par_to_var(struct fb_var_screeninfo* var,
  1459.    struct e1356fb_par* par,
  1460.    const struct fb_info_e1356* info)
  1461. {
  1462. struct fb_var_screeninfo v;
  1463. int ret;
  1464.     
  1465. // First, make sure par is valid.
  1466. if ((ret = e1356fb_verify_par(par, info)))
  1467. return ret;
  1468. memset(&v, 0, sizeof(struct fb_var_screeninfo));
  1469. v.xres_virtual   = par->width_virt;
  1470. v.yres_virtual   = par->height_virt;
  1471. v.xres           = par->width;
  1472. v.yres           = par->height;
  1473. v.right_margin   = par->hsync_start;
  1474. v.hsync_len      = par->hsync_width;
  1475. v.left_margin    = par->horiz_ndp - par->hsync_start - par->hsync_width;
  1476. v.lower_margin   = par->vsync_start;
  1477. v.vsync_len      = par->vsync_width;
  1478. v.upper_margin   = par->vert_ndp - par->vsync_start - par->vsync_width;
  1479. v.bits_per_pixel = par->bpp;
  1480. switch(par->bpp) {
  1481. case 8:
  1482. v.red.offset = v.green.offset = v.blue.offset = 0;
  1483. v.red.length = v.green.length = v.blue.length = 4;
  1484. break;
  1485. case 16:
  1486. v.red.offset   = 11;
  1487. v.red.length   = 5;
  1488. v.green.offset = 5;
  1489. v.green.length = 6;
  1490. v.blue.offset  = 0;
  1491. v.blue.length  = 5;
  1492. break;
  1493. }
  1494. v.height = v.width = -1;
  1495. v.pixclock = KHZ2PICOS(par->ipclk.pixclk);
  1496. if (par->hsync_pol)
  1497. v.sync |= FB_SYNC_HOR_HIGH_ACT;
  1498. if (par->vsync_pol)
  1499. v.sync |= FB_SYNC_VERT_HIGH_ACT;
  1500. *var = v;
  1501. return 0;
  1502. }
  1503. static int
  1504. e1356fb_encode_fix(struct fb_fix_screeninfo*  fix,
  1505.    const struct e1356fb_par*   par,
  1506.    const struct fb_info_e1356* info)
  1507. {
  1508. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  1509.     
  1510. strcpy(fix->id, "Epson SED1356");
  1511. fix->smem_start  = info->fix.membase_phys;
  1512. fix->smem_len    = info->fb_size;
  1513. fix->mmio_start  = info->fix.regbase_phys;
  1514. fix->mmio_len    = info->regbase_size;
  1515. fix->accel       = FB_ACCEL_EPSON_SED1356;
  1516. fix->type        = FB_TYPE_PACKED_PIXELS;
  1517. fix->type_aux    = 0;
  1518. fix->line_length = par->width_virt * par->Bpp;
  1519. fix->visual      =
  1520. (par->bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
  1521.     
  1522. fix->xpanstep    = info->fix.nopan ? 0 : 1;
  1523. fix->ypanstep    = info->fix.nopan ? 0 : 1;
  1524. fix->ywrapstep   = 0;
  1525.     
  1526. return 0;
  1527. }
  1528. static int e1356fb_open(struct fb_info *fb, int user)
  1529. {
  1530. struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  1531.         if (user) {
  1532.                 info->open++;
  1533. }
  1534. MOD_INC_USE_COUNT;
  1535. return 0;
  1536. }
  1537. static int e1356fb_release(struct fb_info *fb, int user)
  1538. {
  1539. struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  1540.         if (user && info->open) {
  1541.                 info->open--;
  1542. if (info->open == 0)
  1543.                         info->mmaped = 0;
  1544. }
  1545. MOD_DEC_USE_COUNT;
  1546. return 0;
  1547. }
  1548. static int
  1549. e1356fb_get_fix(struct fb_fix_screeninfo *fix, 
  1550. int con,
  1551. struct fb_info *fb)
  1552. {
  1553. const struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  1554. struct e1356fb_par par;
  1555. //DPRINTK("n");
  1556. if (con == -1)
  1557. par = info->current_par;
  1558. else
  1559. e1356fb_var_to_par(&fb_display[con].var, &par, info);
  1560. e1356fb_encode_fix(fix, &par, info);
  1561. return 0;
  1562. }
  1563. static int
  1564. e1356fb_get_var(struct fb_var_screeninfo *var, 
  1565. int con,
  1566. struct fb_info *fb)
  1567. {
  1568. struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  1569. //DPRINTK("n");
  1570. if (con == -1)
  1571. e1356fb_par_to_var(var, &info->current_par, info);
  1572. else
  1573. *var = fb_display[con].var;
  1574. return 0;
  1575. }
  1576.  
  1577. static void
  1578. e1356fb_set_dispsw(struct display *disp, 
  1579.    struct fb_info_e1356 *info,
  1580.    int bpp, 
  1581.    int accel)
  1582. {
  1583. struct e1356fb_fix* fix = &info->fix;
  1584. //DPRINTK("n");
  1585. if (disp->dispsw && disp->conp) 
  1586. fb_con.con_cursor(disp->conp, CM_ERASE);
  1587. switch (bpp) {
  1588. #ifdef FBCON_HAS_CFB8
  1589. case 8:
  1590. disp->dispsw = fix->noaccel ? &fbcon_cfb8 : &fbcon_e1356_8;
  1591. if (fix->nohwcursor)
  1592. fbcon_e1356_8.cursor = NULL;
  1593. break;
  1594. #endif
  1595. #ifdef FBCON_HAS_CFB16
  1596. case 16:
  1597. disp->dispsw = fix->noaccel ? &fbcon_cfb16 : &fbcon_e1356_16;
  1598. disp->dispsw_data = info->fbcon_cmap16;
  1599. if (fix->nohwcursor)
  1600. fbcon_e1356_16.cursor = NULL;
  1601. break;
  1602. #endif
  1603. default:
  1604. disp->dispsw = &fbcon_dummy;
  1605. }
  1606.    
  1607. }
  1608. static int
  1609. e1356fb_set_var(struct fb_var_screeninfo *var, 
  1610. int con,
  1611. struct fb_info *fb)
  1612. {
  1613. struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  1614. struct e1356fb_par par;
  1615. struct display *display;
  1616. int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err;
  1617. int activate = var->activate;
  1618. int j,k;
  1619.     
  1620. DPRINTK("n");
  1621. if (con >= 0)
  1622. display = &fb_display[con];
  1623. else
  1624. display = fb->disp; /* used during initialization */
  1625.    
  1626. if ((err = e1356fb_var_to_par(var, &par, info))) {
  1627. struct fb_videomode *dm;
  1628. /*
  1629.  * this mode didn't pass the tests. Try the
  1630.  * corresponding mode from our own modedb.
  1631.  */
  1632. DPRINTK("req mode failed, trying SED1356 %dx%d moden",
  1633. var->xres, var->yres);
  1634. if (e1356fb_get_mode(info, var->xres,
  1635.      var->yres, NULL, &dm) < 0) {
  1636. DPRINTK("no SED1356 %dx%d mode found, failedn",
  1637. var->xres, var->yres);
  1638. return err;
  1639. }
  1640. fb_videomode_to_var(dm, var);
  1641. if ((err = e1356fb_var_to_par(var, &par, info))) {
  1642. DPRINTK("SED1356 %dx%d mode failedn",
  1643. var->xres, var->yres);
  1644. return err;
  1645. }
  1646. }
  1647. if (info->fix.tv_filt & TV_FILT_FLICKER)
  1648. printk("e1356fb: TV flicker filter enabledn");
  1649.     
  1650. e1356fb_par_to_var(var, &par, info);
  1651.    
  1652. if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
  1653. oldxres  = display->var.xres;
  1654. oldyres  = display->var.yres;
  1655. oldvxres = display->var.xres_virtual;
  1656. oldvyres = display->var.yres_virtual;
  1657. oldbpp   = display->var.bits_per_pixel;
  1658. oldaccel = display->var.accel_flags;
  1659. display->var = *var;
  1660. if (con < 0                         ||
  1661.     oldxres  != var->xres           || 
  1662.     oldyres  != var->yres           ||
  1663.     oldvxres != var->xres_virtual   || 
  1664.     oldvyres != var->yres_virtual   ||
  1665.     oldbpp   != var->bits_per_pixel || 
  1666.     oldaccel != var->accel_flags) {
  1667. struct fb_fix_screeninfo fix;
  1668.     
  1669. e1356fb_encode_fix(&fix, &par, info);
  1670. display->screen_base    = info->membase_virt;
  1671. display->visual         = fix.visual;
  1672. display->type           = fix.type;
  1673. display->type_aux       = fix.type_aux;
  1674. display->ypanstep       = fix.ypanstep;
  1675. display->ywrapstep      = fix.ywrapstep;
  1676. display->line_length    = fix.line_length;
  1677. display->next_line      = fix.line_length;
  1678. display->can_soft_blank = 1;
  1679. display->inverse        = 0;
  1680. accel = var->accel_flags & FB_ACCELF_TEXT;
  1681. e1356fb_set_dispsw(display, info, par.bpp, accel);
  1682.  
  1683. if (info->fix.nopan)
  1684. display->scrollmode = SCROLL_YREDRAW;
  1685. if (info->fb_info.changevar)
  1686. (*info->fb_info.changevar)(con);
  1687. }
  1688. if (var->bits_per_pixel==8)
  1689. for(j = 0; j < 16; j++) {
  1690. k = color_table[j];
  1691. fb_info.palette[j].red   = default_red[k];
  1692. fb_info.palette[j].green = default_grn[k];
  1693. fb_info.palette[j].blue  = default_blu[k];
  1694. }
  1695.       
  1696. del_timer(&(info->cursor.timer)); 
  1697. fb_info.cursor.state=CM_ERASE;
  1698. if (!info->fb_info.display_fg ||
  1699.     info->fb_info.display_fg->vc_num == con || con < 0)
  1700. e1356fb_set_par(&par, info);
  1701. if (!info->fix.nohwcursor) 
  1702. if (display && display->conp)
  1703. e1356fb_createcursor( display );
  1704. info->cursor.redraw = 1;
  1705. if (oldbpp != var->bits_per_pixel || con < 0) {
  1706. if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
  1707. return err;
  1708. e1356fb_install_cmap(display, &(info->fb_info));
  1709. }
  1710. }
  1711.   
  1712. return 0;
  1713. }
  1714. static int
  1715. e1356fb_pan_display(struct fb_var_screeninfo* var, 
  1716.     int con,
  1717.     struct fb_info* fb)
  1718. {
  1719. struct fb_info_e1356* info = (struct fb_info_e1356*)fb;
  1720. struct e1356fb_par* par = &info->current_par;
  1721.     
  1722. //DPRINTK("n");
  1723. if (info->fix.nopan)
  1724. return -EINVAL;
  1725. if ((int)var->xoffset < 0 ||
  1726.     var->xoffset + par->width > par->width_virt ||
  1727.     (int)var->yoffset < 0 ||
  1728.     var->yoffset + par->height > par->height_virt)
  1729. return -EINVAL;
  1730.     
  1731. if (con == currcon)
  1732. do_pan_var(var, info);
  1733.     
  1734. fb_display[con].var.xoffset = var->xoffset;
  1735. fb_display[con].var.yoffset = var->yoffset; 
  1736. return 0;
  1737. }
  1738. static int
  1739. e1356fb_get_cmap(struct fb_cmap *cmap, 
  1740.  int kspc, 
  1741.  int con,
  1742.  struct fb_info *fb)
  1743. {
  1744. struct fb_info_e1356* info = (struct fb_info_e1356*)fb;
  1745. struct display *d = (con<0) ? fb->disp : fb_display + con;
  1746.    
  1747. //DPRINTK("n");
  1748. if (con == currcon) {
  1749. /* current console? */
  1750. return fb_get_cmap(cmap, kspc, e1356fb_getcolreg, fb);
  1751. } else if (d->cmap.len) {
  1752. /* non default colormap? */
  1753. fb_copy_cmap(&d->cmap, cmap, kspc ? 0 : 2);
  1754. } else {
  1755. fb_copy_cmap(fb_default_cmap(info->current_par.cmap_len),
  1756.      cmap, kspc ? 0 : 2);
  1757. }
  1758. return 0;
  1759. }
  1760. static int
  1761. e1356fb_set_cmap(struct fb_cmap *cmap, 
  1762.  int kspc, 
  1763.  int con,
  1764.  struct fb_info *fb)
  1765. {
  1766. struct display *d = (con<0) ? fb->disp : fb_display + con;
  1767. struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  1768. int cmap_len = (info->current_par.bpp == 8) ? 256 : 16;
  1769. //DPRINTK("n");
  1770. if (d->cmap.len!=cmap_len) {
  1771. int err;
  1772. if ((err = fb_alloc_cmap(&d->cmap, cmap_len, 0)))
  1773. return err;
  1774. }
  1775.     
  1776. if (con == currcon) {
  1777. /* current console? */
  1778. return fb_set_cmap(cmap, kspc, e1356fb_setcolreg, fb);
  1779. } else {
  1780. fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1);
  1781. }
  1782. return 0;
  1783. }
  1784. static int
  1785. e1356fb_mmap(struct fb_info *fb,
  1786.      struct file *file,
  1787.      struct vm_area_struct *vma)
  1788. {
  1789. struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  1790. unsigned int len;
  1791. #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
  1792. u64 start=0, off;
  1793. #else
  1794. unsigned long start=0, off;
  1795. #endif
  1796. if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
  1797. DPRINTK("invalid vma->vm_pgoffn");
  1798. return -EINVAL;
  1799. }
  1800.     
  1801. #ifdef SHADOW_FRAME_BUFFER
  1802. if (!info->shadow.fb) {
  1803. int order = 0;
  1804. while (info->fb_size > (PAGE_SIZE * (1 << order)))
  1805. order++;
  1806. info->shadow.fb = (void*)__get_free_pages(GFP_KERNEL, order);
  1807. if (!info->shadow.fb) {
  1808. DPRINTK("shadow fb alloc failedn");
  1809. return -ENXIO;
  1810. }
  1811. memset(info->shadow.fb, 0, info->fb_size);
  1812. init_timer(&info->shadow.timer);
  1813. info->shadow.timer.function = do_write_shadow_fb;
  1814. info->shadow.timer.data = (unsigned long)info;
  1815. }
  1816. mod_timer(&info->shadow.timer, jiffies+HZ/2);
  1817. start = virt_to_phys(info->shadow.fb) & PAGE_MASK;
  1818. #else
  1819. start = info->fix.membase_phys & PAGE_MASK;
  1820. #endif
  1821. len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fb_size);
  1822. off = vma->vm_pgoff << PAGE_SHIFT;
  1823.     
  1824. if ((vma->vm_end - vma->vm_start + off) > len) {
  1825. DPRINTK("invalid vman");
  1826. return -EINVAL;
  1827. }
  1828. off += start;
  1829. vma->vm_pgoff = off >> PAGE_SHIFT;
  1830. pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
  1831. #ifdef SHADOW_FRAME_BUFFER
  1832. vma->vm_flags |= VM_RESERVED;
  1833. pgprot_val(vma->vm_page_prot) &= ~_CACHE_UNCACHED;
  1834. #else
  1835. pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
  1836. #endif
  1837. /* This is an IO map - tell maydump to skip this VMA */
  1838. vma->vm_flags |= VM_IO;
  1839. // FIXME: shouldn't have to do this. If the pages are marked writeable,
  1840. // the TLB fault handlers should set these.
  1841. pgprot_val(vma->vm_page_prot) |= (_PAGE_DIRTY | _PAGE_VALID);
  1842.     
  1843. /*
  1844.  * The SED1356 has only a 16-bit wide data bus, and some
  1845.  * embedded platforms, such as the Pb1000, do not automatically
  1846.  * split 32-bit word accesses to the framebuffer into
  1847.  * seperate half-word accesses. Hence the upper half-word
  1848.  * never gets to the framebuffer. The following solution is
  1849.  * to intentionally return a non-32-bit-aligned VA. As long
  1850.  * as the user app assumes (and doesn't check) that the returned
  1851.  * VA is 32-bit aligned, all (assumed aligned) 32-bit accesses
  1852.  * will actually be unaligned and will get trapped by the MIPS
  1853.  * unaligned exception handler. This handler will emulate the
  1854.  * load/store instructions by splitting up the load/store
  1855.  * into two 16-bit load/stores. (This emulation is currently
  1856.  * enabled by default, but may be disabled in the future, when
  1857.  * alignment problems in user-level programs get fixed. When
  1858.  * that happens, this solution won't work anymore, unless the
  1859.  * process that mmap's the fb also calls sysmips(MIPS_FIXADE, 1),
  1860.  * which turns address-error emulation back on).
  1861.  *
  1862.  * Furthermore, this solution only seems to work for TinyX
  1863.  * (Xfbdev). Others, like Qt/E, do snoop the returned VA
  1864.  * and compensate, or do originally unaligned 32-bit accesses
  1865.  * which then become aligned, hence breaking this solution.
  1866.  */
  1867. if (info->fix.mmunalign)
  1868. vma->vm_start += 2;
  1869. #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
  1870. if (e1356_remap_page_range(vma->vm_start, off,
  1871. vma->vm_end - vma->vm_start,
  1872. vma->vm_page_prot))
  1873. return -EAGAIN;
  1874. #else
  1875. if (io_remap_page_range(vma->vm_start, off,
  1876. vma->vm_end - vma->vm_start,
  1877. vma->vm_page_prot))
  1878. return -EAGAIN;
  1879. #endif
  1880. info->mmaped = 1;
  1881. return 0;
  1882. }
  1883. int __init
  1884. e1356fb_init(void)
  1885. {
  1886. struct fb_var_screeninfo var;
  1887. struct e1356fb_fix * epfix = &fb_info.fix;
  1888. e1356_reg_t* reg;
  1889. void* regbase;
  1890. char* name = "SED1356";
  1891. int periodMCLK, periodBCLK;
  1892. int dram_timing, rr_div, mclk_src;
  1893. u8 rev_code, btmp, mclk_cfg;
  1894. if (options) {
  1895. e1356fb_setup(options, 0);
  1896. }
  1897. // clear out fb_info
  1898. memset(&fb_info, 0, sizeof(struct fb_info_e1356));
  1899. // copy boot options
  1900. fb_info.fix = boot_fix;
  1901. fb_info.default_par = boot_par;
  1902. fb_info.regbase_size = E1356_REG_SIZE;
  1903. if (!epfix->system) {
  1904. printk(KERN_ERR "e1356/86fb: no valid system foundn");
  1905. return -ENODEV;
  1906. }
  1907. if (epfix->system == SYS_SDU1356) {
  1908. // it's the SDU1356B0C PCI eval card.
  1909. struct pci_dev *pdev = NULL;
  1910. if (!pci_present())   /* No PCI bus in this machine! */
  1911. return -ENODEV;
  1912. if (!(pdev = pci_find_device(PCI_VENDOR_ID_EPSON,
  1913.      PCI_DEVICE_ID_EPSON_SDU1356, pdev)))
  1914. return -ENODEV;
  1915. if (pci_enable_device(pdev))
  1916. return -ENODEV;
  1917. epfix->regbase_phys = pci_resource_start(pdev, 0);
  1918. epfix->membase_phys = epfix->regbase_phys + E1356_REG_SIZE;
  1919. }
  1920. fb_info.regbase_virt = ioremap_nocache(epfix->regbase_phys,
  1921.        E1356_REG_SIZE);
  1922. if (!fb_info.regbase_virt) {
  1923. printk("e1356fb: Can't remap %s register area.n", name);
  1924. return -ENXIO;
  1925. }
  1926. regbase = fb_info.regbase_virt;
  1927. reg = &fb_info.reg;
  1928.     
  1929. // Initialize the register pointers
  1930. reg->basic =         (reg_basic_t*)   (regbase + REG_BASE_BASIC);
  1931. reg->genio =         (reg_genio_t*)   (regbase + REG_BASE_GENIO);
  1932. reg->md_cfg =        (reg_mdcfg_t*)   (regbase + REG_BASE_MDCFG);
  1933. reg->clk_cfg =       (reg_clkcfg_t*)  (regbase + REG_BASE_CLKCFG);
  1934. reg->mem_cfg =       (reg_memcfg_t*)  (regbase + REG_BASE_MEMCFG);
  1935. reg->panel_cfg =     (reg_panelcfg_t*)(regbase + REG_BASE_PANELCFG);
  1936. reg->lcd_cfg =       (reg_dispcfg_t*) (regbase + REG_BASE_LCD_DISPCFG);
  1937. reg->crttv_cfg =     (reg_dispcfg_t*) (regbase + REG_BASE_CRTTV_DISPCFG);
  1938. reg->lcd_mode =      (reg_dispmode_t*)(regbase + REG_BASE_LCD_DISPMODE);
  1939. reg->crttv_mode =    (reg_dispmode_t*)(regbase + REG_BASE_CRTTV_DISPMODE);
  1940. reg->lcd_inkcurs =   (reg_inkcurs_t*) (regbase + REG_BASE_LCD_INKCURS);
  1941. reg->crttv_inkcurs = (reg_inkcurs_t*) (regbase + REG_BASE_CRTTV_INKCURS);
  1942. reg->bitblt =        (reg_bitblt_t*)  (regbase + REG_BASE_BITBLT);
  1943. reg->lut =           (reg_lut_t*)     (regbase + REG_BASE_LUT);
  1944. reg->pwr_save =      (reg_pwrsave_t*) (regbase + REG_BASE_PWRSAVE);
  1945. reg->misc =          (reg_misc_t*)    (regbase + REG_BASE_MISC);
  1946. reg->mediaplug =     (reg_mediaplug_t*)(regbase + REG_BASE_MEDIAPLUG);
  1947. reg->bitblt_data =   (u16*)           (regbase + REG_BASE_BITBLT_DATA);
  1948.     
  1949. // Enable all register access
  1950. writeb(0, &reg->basic->misc);
  1951. rev_code = readb(&reg->basic->rev_code);
  1952. if ((rev_code >> 2) == 0x04) {
  1953. printk("Found EPSON1356 Display Controllern");
  1954. }
  1955. else if ((rev_code >> 2) == 0x07) {
  1956. printk("Found EPSON13806 Display Controllern");
  1957. }
  1958. else {
  1959. iounmap(fb_info.regbase_virt);
  1960. printk("e1356/806fb: %s not found, rev_code=0x%02x.n",
  1961.        name, rev_code);
  1962. return -ENODEV;
  1963. }
  1964. fb_info.chip_rev = rev_code & 0x03;
  1965. // Determine frame-buffer size
  1966. switch (readb(&reg->md_cfg->md_cfg_stat0) >> 6) {
  1967. case 0:
  1968. case 2:
  1969. fb_info.fb_size = 0x80000;   /* 512K bytes */
  1970. break;
  1971. case 1:
  1972. if ((rev_code >> 2) == 7) /* 806 */
  1973. fb_info.fb_size = 0x140000;  /* 1.2M bytes */
  1974. else
  1975. fb_info.fb_size = 0x200000;  /* 2M bytes */
  1976. break;
  1977. default:
  1978. fb_info.fb_size = 0x200000;  /* 2M bytes */
  1979. break;
  1980. }
  1981. fb_info.membase_virt = ioremap_nocache(epfix->membase_phys,
  1982.        fb_info.fb_size);
  1983.     
  1984. if (!fb_info.membase_virt) {
  1985. printk("e1356fb: Can't remap %s framebuffer.n", name);
  1986. iounmap(fb_info.regbase_virt);
  1987. return -ENXIO;
  1988. }
  1989.     
  1990. printk("e1356/806fb: Detected  %dKB framebuffern", 
  1991. (unsigned)fb_info.fb_size/1000);
  1992. #ifdef CONFIG_MTRR
  1993. if (!epfix->nomtrr) {
  1994. fb_info.mtrr_idx = mtrr_add(epfix->membase_phys, fb_info.fb_size,
  1995.     MTRR_TYPE_WRCOMB, 1);
  1996. printk("e1356fb: MTRR's turned onn");
  1997. }
  1998. #endif
  1999.     
  2000. if (!boot_fix.noaccel) {
  2001. /*
  2002.   Allocate a page for string BLTs. A 4K page is
  2003.   enough for a 256 character string at an 8x16 font.
  2004. */
  2005. fb_info.putcs_buffer = (void*)__get_free_pages(GFP_KERNEL, 0);
  2006. if (fb_info.putcs_buffer == NULL) {
  2007. printk("e1356fb: Can't allocate putcs buffern");
  2008. goto unmap_ret_enxio;
  2009. }
  2010. }
  2011. // Begin SED1356 initialization
  2012. // disable display while initializing
  2013. writeb(0, &reg->misc->disp_mode);
  2014. // Set the GPIO1 and 2 to inputs
  2015. writeb(0, &reg->genio->gpio_cfg);
  2016. writeb(0, &reg->genio->gpio_ctrl);
  2017. if (fb_info.chip_rev == 7) /* 806 */
  2018. writeb(0, &reg->genio->gpio_ctrl2);
  2019. /*
  2020.  * Program the clocks
  2021.  */
  2022. #ifdef CONFIG_MIPS_AU1000
  2023. if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500))
  2024. epfix->busclk = get_au1000_lcd_clock();
  2025. #endif
  2026. if (epfix->busclk > 80000) {
  2027. printk("e1356fb: specified busclk too highn");
  2028. goto ret_enxio;
  2029. }
  2030. epfix->mclk = mclk_cfg = 0;
  2031. if (epfix->system == SYS_PB1500) {
  2032. epfix->mclk = epfix->busclk;
  2033. mclk_cfg = 0x01;
  2034. }
  2035. else {
  2036. // Find the highest allowable MCLK
  2037. if (epfix->busclk <= MAX_PIXCLOCK && 
  2038. epfix->busclk > epfix->mclk) {
  2039. epfix->mclk = epfix->busclk;
  2040. mclk_cfg = 0x01;
  2041. }
  2042. if (epfix->clki <= MAX_PIXCLOCK && epfix->clki > epfix->mclk) {
  2043. epfix->mclk = epfix->clki;
  2044. mclk_cfg = 0x00;
  2045. }
  2046. if (epfix->busclk/2 <= MAX_PIXCLOCK && 
  2047. epfix->busclk/2 > epfix->mclk) {
  2048. epfix->mclk = epfix->busclk/2;
  2049. mclk_cfg = 0x11;
  2050. }
  2051. if (epfix->clki/2 <= MAX_PIXCLOCK && 
  2052. epfix->clki/2 > epfix->mclk) {
  2053. epfix->mclk = epfix->clki/2;
  2054. mclk_cfg = 0x10;
  2055. }
  2056. }
  2057. if (!epfix->mclk) {
  2058. printk("e1356fb: couldn't find an allowable MCLK!n");
  2059. goto ret_enxio;
  2060. }
  2061. // When changing mclk src, you must first set bit 4 to 1.
  2062. writeb(readb(&reg->clk_cfg->mem_clk_cfg) | 0x10,
  2063.        &reg->clk_cfg->mem_clk_cfg);
  2064. writeb(mclk_cfg, &reg->clk_cfg->mem_clk_cfg);
  2065. printk("e1356fb: clocks (kHz): busclk=%d mclk=%d clki=%d clki2=%dn",
  2066.        epfix->busclk, epfix->mclk, epfix->clki, epfix->clki2);
  2067. // Set max pixel clock
  2068. switch (epfix->disp_type) {
  2069. case DISP_TYPE_LCD:
  2070. case DISP_TYPE_TFT:
  2071. case DISP_TYPE_CRT:
  2072. fb_info.max_pixclock = epfix->mclk;
  2073. break;
  2074. case DISP_TYPE_NTSC:
  2075. case DISP_TYPE_PAL:
  2076. fb_info.max_pixclock = (epfix->disp_type == DISP_TYPE_NTSC) ?
  2077. NTSC_PIXCLOCK : PAL_PIXCLOCK;
  2078. if (epfix->tv_filt & TV_FILT_FLICKER)
  2079. fb_info.max_pixclock *= 2;
  2080. break;
  2081. default:
  2082. printk("e1356fb: invalid specified display typen");
  2083. goto ret_enxio;
  2084. }
  2085. periodMCLK = 1000000L / epfix->mclk;   // in nano-seconds
  2086. periodBCLK = 1000000L / epfix->busclk; // in nano-seconds
  2087. if (readb(&reg->md_cfg->md_cfg_stat1) & (1<<4))
  2088. periodBCLK *= 2;
  2089.     
  2090. if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500))
  2091. writeb(0x00, &reg->clk_cfg->cpu2mem_wait_sel);
  2092. else if (periodMCLK - 4 > periodBCLK)
  2093. writeb(0x02, &reg->clk_cfg->cpu2mem_wait_sel);
  2094. else if (2*periodMCLK - 4 > periodBCLK)
  2095. writeb(0x01, &reg->clk_cfg->cpu2mem_wait_sel);
  2096. else
  2097. writeb(0x00, &reg->clk_cfg->cpu2mem_wait_sel);
  2098. // Program memory config
  2099. if (epfix->mem_type < MEM_TYPE_EDO_2CAS ||
  2100.     epfix->mem_type > MEM_TYPE_EMBEDDED_SDRAM) {
  2101. printk("e1356fb: bad memory type specifiedn");
  2102. goto ret_enxio;
  2103. }
  2104. writeb((u8)epfix->mem_type, &reg->mem_cfg->mem_cfg);
  2105. // calc closest refresh rate
  2106. rr_div = 7;
  2107. mclk_src = (mclk_cfg & 1) ? epfix->busclk : epfix->clki;
  2108. while ((mclk_src >> (6 + rr_div)) < epfix->mem_refresh)
  2109. if (--rr_div < 0) {
  2110. printk("e1356fb: can't set specified refresh raten");
  2111. goto ret_enxio;
  2112. }
  2113.     
  2114. DPRINTK("refresh rate = %d kHzn", (mclk_src >> (6 + rr_div)));
  2115. // add Suspend-Mode Refresh bits
  2116. if (epfix->mem_smr < MEM_SMR_CBR || epfix->mem_smr > MEM_SMR_NONE) {
  2117. printk("e1356fb: invalid specified suspend-mode refresh typen");
  2118. goto ret_enxio;
  2119. }
  2120. writeb(rr_div | (epfix->mem_smr << 6), &reg->mem_cfg->dram_refresh);
  2121. // set DRAM speed
  2122. switch (epfix->mem_speed) {
  2123. case 50:
  2124. dram_timing = epfix->mclk >= 33000 ? 0x0101 : 0x0212;
  2125. break;
  2126. case 60:
  2127. if (epfix->mclk >= 30000)
  2128. dram_timing = 0x0101;
  2129. else if (epfix->mclk >= 25000)
  2130. dram_timing =
  2131. (epfix->mem_type == MEM_TYPE_EDO_2CAS ||
  2132.  epfix->mem_type == MEM_TYPE_EDO_2WE) ?
  2133. 0x0212 : 0x0101;
  2134. else
  2135. dram_timing = 0x0212;
  2136. break;
  2137. case 70:
  2138. if (epfix->mclk >= 30000)
  2139. dram_timing = 0x0000;
  2140. else if (epfix->mclk >= 25000)
  2141. dram_timing = 0x0101;
  2142. else
  2143. dram_timing =
  2144. (epfix->mem_type == MEM_TYPE_EDO_2CAS ||
  2145.  epfix->mem_type == MEM_TYPE_EDO_2WE) ?
  2146. 0x0212 : 0x0211;
  2147. break;
  2148. case 80:
  2149. if (epfix->mclk >= 25000)
  2150. dram_timing = 0x0100;
  2151. else
  2152. dram_timing = 0x0101;
  2153. break;
  2154. default:
  2155. printk("e1356fb: invalid specified memory speedn");
  2156. goto ret_enxio;
  2157. }
  2158. writew(dram_timing, &reg->mem_cfg->dram_timings_ctrl0);
  2159.     
  2160. currcon = -1;
  2161. if (!epfix->nohwcursor)
  2162. e1356fb_hwcursor_init(&fb_info);
  2163.     
  2164. init_timer(&fb_info.cursor.timer);
  2165. fb_info.cursor.timer.function = do_flashcursor; 
  2166. fb_info.cursor.timer.data = (unsigned long)(&fb_info);
  2167. fb_info.cursor.state = CM_ERASE;
  2168. spin_lock_init(&fb_info.cursor.lock);
  2169.     
  2170. strcpy(fb_info.fb_info.modename, "Epson "); 
  2171. strcat(fb_info.fb_info.modename, name);
  2172. fb_info.fb_info.changevar  = NULL;
  2173. fb_info.fb_info.node       = -1;
  2174. fb_info.fb_info.fbops      = &e1356fb_ops;
  2175. fb_info.fb_info.disp       = &fb_info.disp;
  2176. strcpy(fb_info.fb_info.fontname, epfix->fontname);
  2177. fb_info.fb_info.switch_con = &e1356fb_switch_con;
  2178. fb_info.fb_info.updatevar  = &e1356fb_updatevar;
  2179. fb_info.fb_info.blank      = &e1356fb_blank;
  2180. fb_info.fb_info.flags      = FBINFO_FLAG_DEFAULT;
  2181.     
  2182. // Set-up display
  2183. // clear out unused stuff
  2184. writeb(0, &reg->panel_cfg->mod_rate);
  2185. writeb(0x01, &reg->lcd_mode->lcd_misc);
  2186. writeb(0, &reg->lcd_mode->fifo_high_thresh);
  2187. writeb(0, &reg->lcd_mode->fifo_low_thresh);
  2188. writeb(0, &reg->crttv_mode->fifo_high_thresh);
  2189. writeb(0, &reg->crttv_mode->fifo_low_thresh);
  2190.     
  2191. switch (epfix->disp_type) {
  2192. case DISP_TYPE_LCD:
  2193. switch (epfix->panel_width) {
  2194. case 4: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x04); break;
  2195. case 8: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x14); break;
  2196. case 16: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x24); break;
  2197. default:
  2198. printk("e1356fb: invalid specified LCD panel data widthn");
  2199. goto ret_enxio;
  2200. }
  2201. writeb(btmp, &reg->panel_cfg->panel_type);
  2202. break;
  2203. case DISP_TYPE_TFT:
  2204. switch (epfix->panel_width) {
  2205. case 9: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x05); break;
  2206. case 12: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x15); break;
  2207. case 18: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x25); break;
  2208. default:
  2209. printk("e1356fb: invalid specified TFT panel data widthn");
  2210. goto ret_enxio;
  2211. }
  2212. writeb(btmp, &reg->panel_cfg->panel_type);
  2213. break;
  2214. case DISP_TYPE_CRT:
  2215. writeb(0x00, &reg->crttv_cfg->tv_output_ctrl);
  2216. break;
  2217. case DISP_TYPE_NTSC:
  2218. case DISP_TYPE_PAL:
  2219. if (epfix->tv_fmt < TV_FMT_COMPOSITE ||
  2220.     epfix->tv_fmt > TV_FMT_S_VIDEO) {
  2221. printk("e1356fb: invalid specified TV output formatn");
  2222. goto ret_enxio;
  2223. }
  2224. btmp = epfix->disp_type == DISP_TYPE_PAL ? 0x01 : 0x00;
  2225. btmp |= (epfix->tv_fmt == TV_FMT_S_VIDEO ? 0x02 : 0x00);
  2226. btmp |= ((epfix->tv_filt & TV_FILT_LUM) ? 0x10 : 0x00);
  2227. btmp |= ((epfix->tv_filt & TV_FILT_CHROM) ? 0x20 : 0x00);
  2228. writeb(btmp, &reg->crttv_cfg->tv_output_ctrl);
  2229. break;
  2230. }
  2231. memset(&var, 0, sizeof(var));
  2232. /*
  2233.  * If mode_option wasn't given at boot, assume all the boot
  2234.  * option timing parameters were specified individually, in
  2235.  * which case we convert par_to_var instead of calling
  2236.  * fb_find_mode.
  2237.  */
  2238. if (epfix->mode_option) {
  2239. struct fb_videomode* modedb, *dm;
  2240. int dbsize = e1356fb_get_mode(&fb_info, 640, 480, &modedb, &dm);
  2241. // first try the generic modedb
  2242. if (!fb_find_mode(&var, &fb_info.fb_info, epfix->mode_option,
  2243.   NULL, 0, NULL, boot_par.bpp)) {
  2244. printk("e1356fb: mode %s failed, trying e1356 modedbn",
  2245.        epfix->mode_option);
  2246. // didn't work in generic modedb, try ours
  2247. if (!fb_find_mode(&var, &fb_info.fb_info,
  2248.   epfix->mode_option,
  2249.   modedb, dbsize, dm, boot_par.bpp)) {
  2250. printk("e1356fb: mode %s failed e1356 modedb too, sorryn",
  2251.        epfix->mode_option);
  2252. goto ret_enxio;
  2253. }
  2254. }
  2255. var.xres_virtual = boot_par.width_virt ?
  2256. boot_par.width_virt : boot_par.width;
  2257. var.yres_virtual = boot_par.height_virt ?
  2258. boot_par.height_virt : boot_par.height;
  2259. } else {
  2260. if (e1356fb_par_to_var(&var, &fb_info.default_par, &fb_info)) {
  2261. printk("e1356fb: boot option mode failedn");
  2262. goto ret_enxio;
  2263. }
  2264. }
  2265.     
  2266. if (boot_fix.noaccel)
  2267. var.accel_flags &= ~FB_ACCELF_TEXT;
  2268. else
  2269. var.accel_flags |= FB_ACCELF_TEXT;
  2270.     
  2271. if (e1356fb_var_to_par(&var, &fb_info.default_par, &fb_info)) {
  2272. /*
  2273.  * Can't use the mode from the mode db or the default
  2274.  * mode or the boot options - give up
  2275.  */
  2276. printk("e1356fb: mode failed var_to_parn");
  2277. goto ret_enxio;
  2278. }
  2279.     
  2280. fb_info.disp.screen_base    = fb_info.membase_virt;
  2281. fb_info.disp.var            = var; // struct copy
  2282.     
  2283. // here's where the screen is actually initialized and enabled
  2284. if (e1356fb_set_var(&var, -1, &fb_info.fb_info)) {
  2285. printk("e1356fb: can't set video moden");
  2286. goto ret_enxio;
  2287. }
  2288.     
  2289. writeb(0, &reg->pwr_save->cfg);     // disable power-save mode
  2290. writeb(0, &reg->misc->cpu2mem_watchdog); // disable watchdog timer
  2291. #ifdef E1356FB_VERBOSE_DEBUG
  2292. dump_fb(fb_info.membase_virt + 0x100000, 512);
  2293. #endif
  2294. if (register_framebuffer(&fb_info.fb_info) < 0) {
  2295. writeb(0, &reg->misc->disp_mode); 
  2296. printk("e1356fb: can't register framebuffern");
  2297. goto ret_enxio;
  2298. }
  2299.     
  2300. printk("fb%d: %s frame buffer devicen", 
  2301.        GET_FB_IDX(fb_info.fb_info.node),
  2302.        fb_info.fb_info.modename);
  2303.     
  2304.     
  2305. return 0;
  2306.  ret_enxio:
  2307. free_pages((unsigned long)fb_info.putcs_buffer, 0);
  2308.  unmap_ret_enxio:
  2309. iounmap(fb_info.regbase_virt);
  2310. iounmap(fb_info.membase_virt);
  2311. return -ENXIO;
  2312. }
  2313. /**
  2314.  * e1356fb_exit - Driver cleanup
  2315.  *
  2316.  * Releases all resources allocated during the
  2317.  * course of the driver's lifetime.
  2318.  *
  2319.  * FIXME - do results of fb_alloc_cmap need disposal?
  2320.  */
  2321. static void __exit
  2322. e1356fb_exit (void)
  2323. {
  2324. unregister_framebuffer(&fb_info.fb_info);
  2325. del_timer_sync(&fb_info.cursor.timer);
  2326. #ifdef CONFIG_MTRR
  2327. if (!fb_info.fix.nomtrr) {
  2328. mtrr_del(fb_info.mtrr_idx, fb_info.fix.membase_phys,
  2329.  fb_info.fb_size);
  2330. printk("fb: MTRR's  turned offn");
  2331. }
  2332. #endif
  2333. free_pages((unsigned long)fb_info.putcs_buffer, 0);
  2334. iounmap(fb_info.regbase_virt);
  2335. iounmap(fb_info.membase_virt);
  2336. }
  2337. MODULE_AUTHOR("Steve Longerbeam <stevel@mvista.com>");
  2338. MODULE_DESCRIPTION("SED1356 framebuffer device driver");
  2339. #ifdef MODULE
  2340. module_init(e1356fb_init);
  2341. #endif
  2342. module_exit(e1356fb_exit);
  2343. void
  2344. e1356fb_setup(char *options, int *ints)
  2345. {
  2346. char* this_opt;
  2347.     
  2348. memset(&boot_fix, 0, sizeof(struct e1356fb_fix));
  2349. memset(&boot_par, 0, sizeof(struct e1356fb_par));
  2350. boot_fix.system = -1;
  2351.     
  2352. if (!options || !*options)
  2353. return;
  2354.     
  2355. for(this_opt=strtok(options, ","); this_opt;
  2356.     this_opt=strtok(NULL, ",")) {
  2357. if (!strncmp(this_opt, "noaccel", 7)) {
  2358. boot_fix.noaccel = 1;
  2359. } else if (!strncmp(this_opt, "nopan", 5)) {
  2360. boot_fix.nopan = 1;
  2361. } else if (!strncmp(this_opt, "nohwcursor", 10)) {
  2362. boot_fix.nohwcursor = 1;
  2363. } else if (!strncmp(this_opt, "mmunalign:", 10)) {
  2364. boot_fix.mmunalign = simple_strtoul(this_opt+10,
  2365.     NULL, 0);
  2366. #ifdef CONFIG_MTRR
  2367. } else if (!strncmp(this_opt, "nomtrr", 6)) {
  2368. boot_fix.nomtrr = 1;
  2369. #endif
  2370. } else if (!strncmp(this_opt, "font:", 5)) {
  2371. strncpy(boot_fix.fontname, this_opt+5,
  2372. sizeof(boot_fix.fontname)-1);
  2373. } else if (!strncmp(this_opt, "regbase:", 8)) {
  2374. boot_fix.regbase_phys = simple_strtoul(this_opt+8,
  2375.        NULL, 0);
  2376. } else if (!strncmp(this_opt, "membase:", 8)) {
  2377. boot_fix.membase_phys = simple_strtoul(this_opt+8,
  2378.        NULL, 0);
  2379. } else if (!strncmp(this_opt, "memsp:", 6)) {
  2380. boot_fix.mem_speed = simple_strtoul(this_opt+6,
  2381.     NULL, 0);
  2382. } else if (!strncmp(this_opt, "memtyp:", 7)) {
  2383. boot_fix.mem_type = simple_strtoul(this_opt+7,
  2384.    NULL, 0);
  2385. } else if (!strncmp(this_opt, "memref:", 7)) {
  2386. boot_fix.mem_refresh = simple_strtoul(this_opt+7,
  2387.       NULL, 0);
  2388. } else if (!strncmp(this_opt, "memsmr:", 7)) {
  2389. boot_fix.mem_smr = simple_strtoul(this_opt+7, NULL, 0);
  2390. } else if (!strncmp(this_opt, "busclk:", 7)) {
  2391. boot_fix.busclk = simple_strtoul(this_opt+7, NULL, 0);
  2392. } else if (!strncmp(this_opt, "clki:", 5)) {
  2393. boot_fix.clki = simple_strtoul(this_opt+5, NULL, 0);
  2394. } else if (!strncmp(this_opt, "clki2:", 6)) {
  2395. boot_fix.clki2 = simple_strtoul(this_opt+6, NULL, 0);
  2396. } else if (!strncmp(this_opt, "display:", 8)) {
  2397. if (!strncmp(this_opt+8, "lcd", 3))
  2398. boot_fix.disp_type = DISP_TYPE_LCD;
  2399. else if (!strncmp(this_opt+8, "tft", 3))
  2400. boot_fix.disp_type = DISP_TYPE_TFT;
  2401. else if (!strncmp(this_opt+8, "crt", 3))
  2402. boot_fix.disp_type = DISP_TYPE_CRT;
  2403. else if (!strncmp(this_opt+8, "pal", 3))
  2404. boot_fix.disp_type = DISP_TYPE_PAL;
  2405. else if (!strncmp(this_opt+8, "ntsc", 4))
  2406. boot_fix.disp_type = DISP_TYPE_NTSC;
  2407. } else if (!strncmp(this_opt, "width:", 6)) {
  2408. boot_par.width = simple_strtoul(this_opt+6, NULL, 0);
  2409. } else if (!strncmp(this_opt, "height:", 7)) {
  2410. boot_par.height = simple_strtoul(this_opt+7, NULL, 0);
  2411. } else if (!strncmp(this_opt, "bpp:", 4)) {
  2412. boot_par.bpp = simple_strtoul(this_opt+4, NULL, 0);
  2413. boot_par.cmap_len = (boot_par.bpp == 8) ? 256 : 16;
  2414. } else if (!strncmp(this_opt, "elpanel:", 8)) {
  2415. boot_fix.panel_el = simple_strtoul(this_opt+8,
  2416.    NULL, 0);
  2417. } else if (!strncmp(this_opt, "pdataw:", 7)) {
  2418. boot_fix.panel_width = simple_strtoul(this_opt+7,
  2419.       NULL, 0);
  2420. } else if (!strncmp(this_opt, "hndp:", 5)) {
  2421. boot_par.horiz_ndp = simple_strtoul(this_opt+5,
  2422.     NULL, 0);
  2423. } else if (!strncmp(this_opt, "vndp:", 5)) {
  2424. boot_par.vert_ndp = simple_strtoul(this_opt+5,
  2425.    NULL, 0);
  2426. } else if (!strncmp(this_opt, "hspol:", 6)) {
  2427. boot_par.hsync_pol = simple_strtoul(this_opt+6,
  2428.     NULL, 0);
  2429. } else if (!strncmp(this_opt, "vspol:", 6)) {
  2430. boot_par.vsync_pol = simple_strtoul(this_opt+6,
  2431.     NULL, 0);
  2432. } else if (!strncmp(this_opt, "hsstart:", 8)) {
  2433. boot_par.hsync_start = simple_strtoul(this_opt+8,
  2434.       NULL, 0);
  2435. } else if (!strncmp(this_opt, "hswidth:", 8)) {
  2436. boot_par.hsync_width = simple_strtoul(this_opt+8,
  2437.       NULL, 0);
  2438. } else if (!strncmp(this_opt, "vsstart:", 8)) {
  2439. boot_par.vsync_start = simple_strtoul(this_opt+8,
  2440.       NULL, 0);
  2441. } else if (!strncmp(this_opt, "vswidth:", 8)) {
  2442. boot_par.vsync_width = simple_strtoul(this_opt+8,
  2443.       NULL, 0);
  2444. } else if (!strncmp(this_opt, "tvfilt:", 7)) {
  2445. boot_fix.tv_filt = simple_strtoul(this_opt+7, NULL, 0);
  2446. } else if (!strncmp(this_opt, "tvfmt:", 6)) {
  2447. boot_fix.tv_fmt = simple_strtoul(this_opt+6, NULL, 0);
  2448. } else if (!strncmp(this_opt, "system:", 7)) {
  2449. if (!strncmp(this_opt+7, "pb1000", 10)) {
  2450. boot_fix = systems[SYS_PB1000].fix;
  2451. boot_par = systems[SYS_PB1000].par;
  2452. } else if (!strncmp(this_opt+7, "pb1500", 7)) {
  2453. boot_fix = systems[SYS_PB1500].fix;
  2454. boot_par = systems[SYS_PB1500].par;
  2455. } else if (!strncmp(this_opt+7, "sdu1356", 7)) {
  2456. boot_fix = systems[SYS_SDU1356].fix;
  2457. boot_par = systems[SYS_SDU1356].par;
  2458. } else if (!strncmp(this_opt+7, "clio1050", 7)) {
  2459. boot_fix = systems[SYS_CLIO1050].fix;
  2460. boot_par = systems[SYS_CLIO1050].par;
  2461. }
  2462. } else {
  2463. boot_fix.mode_option = this_opt;
  2464. }
  2465. }
  2466. /*
  2467.  * FIXME: switching consoles could be dangerous. What if switching
  2468.  * from a panel to a CRT/TV, or vice versa? More needs to be
  2469.  * done here.
  2470.  */
  2471. static int
  2472. e1356fb_switch_con(int con, struct fb_info *fb)
  2473. {
  2474. struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  2475. struct e1356fb_par par;
  2476. int old_con = currcon;
  2477. int set_par = 1;
  2478. //DPRINTK("n");
  2479. /* Do we have to save the colormap? */
  2480. if (currcon>=0)
  2481. if (fb_display[currcon].cmap.len)
  2482. fb_get_cmap(&fb_display[currcon].cmap, 1,
  2483.     e1356fb_getcolreg, fb);
  2484.    
  2485. currcon = con;
  2486. fb_display[currcon].var.activate = FB_ACTIVATE_NOW; 
  2487. e1356fb_var_to_par(&fb_display[con].var, &par, info);
  2488. if (old_con>=0 && vt_cons[old_con]->vc_mode!=KD_GRAPHICS) {
  2489. /* check if we have to change video registers */
  2490. struct e1356fb_par old_par;
  2491. e1356fb_var_to_par(&fb_display[old_con].var, &old_par, info);
  2492. if (!memcmp(&par,&old_par,sizeof(par)))
  2493. set_par = 0; /* avoid flicker */
  2494. }
  2495. if (set_par)
  2496. e1356fb_set_par(&par, info);
  2497.     
  2498. if (fb_display[con].dispsw && fb_display[con].conp)
  2499. fb_con.con_cursor(fb_display[con].conp, CM_ERASE);
  2500.    
  2501. del_timer(&(info->cursor.timer));
  2502. fb_info.cursor.state=CM_ERASE; 
  2503.    
  2504. if (!info->fix.nohwcursor) 
  2505. if (fb_display[con].conp)
  2506. e1356fb_createcursor( &fb_display[con] );
  2507.    
  2508. info->cursor.redraw=1;
  2509.    
  2510. e1356fb_set_dispsw(&fb_display[con], 
  2511.    info, 
  2512.    par.bpp,
  2513.    fb_display[con].var.accel_flags & FB_ACCELF_TEXT);
  2514.    
  2515. e1356fb_install_cmap(&fb_display[con], fb);
  2516. e1356fb_updatevar(con, fb);
  2517.    
  2518. return 1;
  2519. }
  2520. /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
  2521. static void
  2522. e1356fb_blank(int blank, struct fb_info *fb)
  2523. {
  2524. struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;
  2525. reg_dispmode_t* dispmode = (IS_PANEL(info->fix.disp_type)) ?
  2526. info->reg.lcd_mode : info->reg.crttv_mode;
  2527. reg_pwrsave_t* pwrsave = info->reg.pwr_save;
  2528. //DPRINTK("n");
  2529. switch (blank) {
  2530. case 0:
  2531. // Get out of power save mode
  2532. writeb(0x00, &pwrsave->cfg);
  2533. writeb(readb(&dispmode->disp_mode) & ~0x80,
  2534.        &dispmode->disp_mode);
  2535. break;
  2536. case 1:
  2537. // Get out of power save mode
  2538. writeb(0x00, &pwrsave->cfg);
  2539. writeb(readb(&dispmode->disp_mode) | 0x80,
  2540.        &dispmode->disp_mode);
  2541. break;
  2542. // No support for turning off horiz or vert sync, so just treat
  2543. // it as a power off.
  2544. case 2:
  2545. case 3:
  2546. case 4:
  2547. writeb(0x01, &pwrsave->cfg);
  2548. break;
  2549. }
  2550. }
  2551. static int
  2552. e1356fb_updatevar(int con, struct fb_info* fb)
  2553. {
  2554. struct fb_info_e1356* i = (struct fb_info_e1356*)fb;
  2555. //DPRINTK("n");
  2556. if ((con==currcon) && (!i->fix.nopan)) 
  2557. do_pan_var(&fb_display[con].var,i);
  2558. return 0;
  2559. }
  2560. static int
  2561. e1356fb_getcolreg(unsigned        regno, 
  2562.   unsigned*       red, 
  2563.   unsigned*       green,
  2564.   unsigned*       blue, 
  2565.   unsigned*       transp,
  2566.   struct fb_info* fb)
  2567. {
  2568. struct fb_info_e1356* i = (struct fb_info_e1356*)fb;
  2569. if (regno > i->current_par.cmap_len)
  2570. return 1;
  2571.    
  2572. *red    = i->palette[regno].red; 
  2573. *green  = i->palette[regno].green; 
  2574. *blue   = i->palette[regno].blue; 
  2575. *transp = 0;
  2576.    
  2577. return 0;
  2578. }
  2579. static int
  2580. e1356fb_setcolreg(unsigned        regno, 
  2581.   unsigned        red, 
  2582.   unsigned        green,
  2583.   unsigned        blue, 
  2584.   unsigned        transp,
  2585.   struct fb_info* info)
  2586. {
  2587. struct fb_info_e1356* i = (struct fb_info_e1356*)info;
  2588. if (regno > 255)
  2589. return 1;
  2590. i->palette[regno].red    = red;
  2591. i->palette[regno].green  = green;
  2592. i->palette[regno].blue   = blue;
  2593.    
  2594. switch(i->current_par.bpp) {
  2595. #ifdef FBCON_HAS_CFB8
  2596. case 8:
  2597. do_setpalentry(i->reg.lut, regno,
  2598.        (u8)(red>>8), (u8)(green>>8), (u8)(blue>>8));
  2599. break;
  2600. #endif
  2601. #ifdef FBCON_HAS_CFB16
  2602. case 16:
  2603. i->fbcon_cmap16[regno] = (regno << 10) | (regno << 5) | regno;
  2604. break;
  2605. #endif
  2606. default:
  2607. DPRINTK("bad depth %un", i->current_par.bpp);
  2608. break;
  2609. }
  2610. return 0;
  2611. }
  2612. static void
  2613. e1356fb_install_cmap(struct display *d, struct fb_info *info) 
  2614. {
  2615. struct fb_info_e1356* i = (struct fb_info_e1356*)info;
  2616. //DPRINTK("n");
  2617. if (d->cmap.len) {
  2618. fb_set_cmap(&(d->cmap), 1, e1356fb_setcolreg, info);
  2619. } else {
  2620. fb_set_cmap(fb_default_cmap(i->current_par.cmap_len), 1,
  2621.     e1356fb_setcolreg, info);
  2622. }
  2623. }
  2624. static void
  2625. e1356fb_createcursorshape(struct display* p) 
  2626. {
  2627. int h,u;
  2628.    
  2629. h = fontheight(p);
  2630. fb_info.cursor.type = p->conp->vc_cursor_type & CUR_HWMASK;
  2631. switch (fb_info.cursor.type) {
  2632. case CUR_NONE: 
  2633. u = h; 
  2634. break;
  2635. case CUR_UNDERLINE: 
  2636. u = h - 2; 
  2637. break;
  2638. case CUR_LOWER_THIRD: 
  2639. u = (h * 2) / 3; 
  2640. break;
  2641. case CUR_LOWER_HALF: 
  2642. u = h / 2; 
  2643. break;
  2644. case CUR_TWO_THIRDS: 
  2645. u = h / 3; 
  2646. break;
  2647. case CUR_BLOCK:
  2648. default:
  2649. u = 0;
  2650. break;
  2651. }
  2652.     
  2653. fb_info.cursor.w = fontwidth_x8(p);
  2654. fb_info.cursor.u = u;
  2655. fb_info.cursor.h = h;
  2656. }
  2657.    
  2658. static void
  2659. e1356fb_createcursor(struct display *p)
  2660. {
  2661. void* memcursor;
  2662. int y, w, h, u;
  2663.     
  2664. e1356fb_createcursorshape(p);
  2665. h = fb_info.cursor.h;
  2666. w = fb_info.cursor.w;
  2667. u = fb_info.cursor.u;
  2668. memcursor = fb_info.membase_virt + fb_info.fb_size;
  2669. // write cursor to display memory
  2670. for (y=0; y<64; y++) {
  2671. if (y >= h || y < u) {
  2672. fbfill((u16*)memcursor, 0xaa, 16); // b/g
  2673. } else {
  2674. fbfill((u16*)memcursor, 0xff, w/4); // inverted b/g
  2675. fbfill((u16*)memcursor + w/4, 0xaa, (64 - w)/4); // b/g
  2676. }
  2677. memcursor += 16;
  2678. }
  2679. }
  2680.    
  2681. static void
  2682. e1356fb_hwcursor_init(struct fb_info_e1356* info)
  2683. {
  2684. reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ?
  2685. info->reg.lcd_inkcurs : info->reg.crttv_inkcurs;
  2686. fb_info.fb_size -= 1024;
  2687. // program cursor base address
  2688. writeb(0x00, &inkcurs->start_addr);
  2689. printk("e1356fb: reserving 1024 bytes for the hwcursor at %pn",
  2690.        fb_info.membase_virt + fb_info.fb_size);
  2691. }
  2692. #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
  2693. /*
  2694.  * Return indicates whether a page was freed so caller can adjust rss
  2695.  */
  2696. static inline void forget_pte(pte_t page)
  2697. {
  2698. if (!pte_none(page)) {
  2699. printk("forget_pte: old mapping existed!n");
  2700. BUG();
  2701. }
  2702. }
  2703. /*
  2704.  * maps a range of physical memory into the requested pages. the old
  2705.  * mappings are removed. any references to nonexistent pages results
  2706.  * in null mappings (currently treated as "copy-on-access")
  2707.  */
  2708. static inline void e1356_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
  2709. phys_t phys_addr, pgprot_t prot)
  2710. {
  2711. unsigned long end;
  2712. address &= ~PMD_MASK;
  2713. end = address + size;
  2714. if (end > PMD_SIZE)
  2715. end = PMD_SIZE;
  2716. do {
  2717. struct page *page;
  2718. pte_t oldpage;
  2719. oldpage = ptep_get_and_clear(pte);
  2720. page = virt_to_page(__va(phys_addr));
  2721. if ((!VALID_PAGE(page)) || PageReserved(page))
  2722.   set_pte(pte, mk_pte_phys(phys_addr, prot));
  2723. forget_pte(oldpage);
  2724. address += PAGE_SIZE;
  2725. phys_addr += PAGE_SIZE;
  2726. pte++;
  2727. } while (address && (address < end));
  2728. }
  2729. static inline int e1356_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
  2730. phys_t phys_addr, pgprot_t prot)
  2731. {
  2732. unsigned long end;
  2733. address &= ~PGDIR_MASK;
  2734. end = address + size;
  2735. if (end > PGDIR_SIZE)
  2736. end = PGDIR_SIZE;
  2737. phys_addr -= address;
  2738. do {
  2739. pte_t * pte = pte_alloc(mm, pmd, address);
  2740. if (!pte)
  2741. return -ENOMEM;
  2742. e1356_remap_pte_range(pte, address, end - address, address + phys_addr, prot);
  2743. address = (address + PMD_SIZE) & PMD_MASK;
  2744. pmd++;
  2745. } while (address && (address < end));
  2746. return 0;
  2747. }
  2748. /*  Note: this is only safe if the mm semaphore is held when called. */
  2749. static int e1356_remap_page_range(unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot)
  2750. {
  2751. int error = 0;
  2752. pgd_t * dir;
  2753. phys_t beg = from;
  2754. phys_t end = from + size;
  2755. struct mm_struct *mm = current->mm;
  2756. phys_addr -= from;
  2757. dir = pgd_offset(mm, from);
  2758. flush_cache_range(mm, beg, end);
  2759. if (from >= end)
  2760. BUG();
  2761. spin_lock(&mm->page_table_lock);
  2762. do {
  2763. pmd_t *pmd = pmd_alloc(mm, dir, from);
  2764. error = -ENOMEM;
  2765. if (!pmd)
  2766. break;
  2767. error = e1356_remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
  2768. if (error)
  2769. break;
  2770. from = (from + PGDIR_SIZE) & PGDIR_MASK;
  2771. dir++;
  2772. } while (from && (from < end));
  2773. spin_unlock(&mm->page_table_lock);
  2774. flush_tlb_range(mm, beg, end);
  2775. return error;
  2776. }
  2777. #endif