pxafb.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:40k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/video/pxafb.c
  3.  *
  4.  *  Copyright (C) 1999 Eric A. Thomas
  5.  *   Based on acornfb.c Copyright (C) Russell King.
  6.  *
  7.  * This file is subject to the terms and conditions of the GNU General Public
  8.  * License.  See the file COPYING in the main directory of this archive for
  9.  * more details.
  10.  *
  11.  *         Intel PXA250/210 LCD Controller Frame Buffer Driver
  12.  *
  13.  * Please direct your questions and comments on this driver to the following
  14.  * email address:
  15.  *
  16.  * linux-arm-kernel@lists.arm.linux.org.uk
  17.  *
  18.  * Clean patches should be sent to the ARM Linux Patch System.  Please see the
  19.  * following web page for more information:
  20.  *
  21.  * http://www.arm.linux.org.uk/developer/patches/info.shtml
  22.  *
  23.  * Thank you.
  24.  *
  25.  *
  26.  * Code Status:
  27.  * 1999/04/01:
  28.  * - Driver appears to be working for Brutus 320x200x8bpp mode.  Other
  29.  *   resolutions are working, but only the 8bpp mode is supported.
  30.  *   Changes need to be made to the palette encode and decode routines
  31.  *   to support 4 and 16 bpp modes.  
  32.  *   Driver is not designed to be a module.  The FrameBuffer is statically
  33.  *   allocated since dynamic allocation of a 300k buffer cannot be 
  34.  *   guaranteed. 
  35.  *
  36.  * 1999/06/17:
  37.  * - FrameBuffer memory is now allocated at run-time when the
  38.  *   driver is initialized.    
  39.  *
  40.  * 2000/04/10: Nicolas Pitre <nico@cam.org>
  41.  * - Big cleanup for dynamic selection of machine type at run time.
  42.  *
  43.  * 2000/07/19: Jamey Hicks <jamey@crl.dec.com>
  44.  * - Support for Bitsy aka Compaq iPAQ H3600 added.
  45.  *
  46.  * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com>
  47.  *        Jeff Sutherland <jsutherland@accelent.com>
  48.  * - Resolved an issue caused by a change made to the Assabet's PLD 
  49.  *   earlier this year which broke the framebuffer driver for newer 
  50.  *   Phase 4 Assabets.  Some other parameters were changed to optimize
  51.  *   for the Sharp display.
  52.  *
  53.  * 2000/08/09: Cliff Brake <cbrake@accelent.com>
  54.  *      - modified for Accelent
  55.  * 
  56.  * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp>
  57.  * - XP860 support added
  58.  *
  59.  * 2000/08/19: Mark Huang <mhuang@livetoy.com>
  60.  * - Allows standard options to be passed on the kernel command line
  61.  *   for most common passive displays.
  62.  *
  63.  * 2000/08/29:
  64.  * - s/save_flags_cli/local_irq_save/
  65.  * - remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller
  66.  *
  67.  * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
  68.  * - Updated LART stuff. Fixed some minor bugs.
  69.  *
  70.  * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw>
  71.  * - Pangolin support added
  72.  *
  73.  * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de>
  74.  * - Huw Webpanel support added
  75.  *
  76.  * 2000/11/23: Eric Peng <ericpeng@coventive.com>
  77.  * - Freebird add
  78.  *
  79.  * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com> 
  80.  *        Cliff Brake <cbrake@accelent.com>
  81.  * - Added PM callback
  82.  *
  83.  * 2001/05/26: <rmk@arm.linux.org.uk>
  84.  * - Fix 16bpp so that (a) we use the right colours rather than some
  85.  *   totally random colour depending on what was in page 0, and (b)
  86.  *   we don't de-reference a NULL pointer.
  87.  * - remove duplicated implementation of consistent_alloc()
  88.  * - convert dma address types to dma_addr_t
  89.  * - remove unused 'montype' stuff
  90.  * - remove redundant zero inits of init_var after the initial
  91.  *   memzero.
  92.  * - remove allow_modeset (acornfb idea does not belong here)
  93.  *
  94.  * 2001/05/28: <rmk@arm.linux.org.uk>
  95.  * - massive cleanup - move machine dependent data into structures
  96.  * - I've left various #warnings in - if you see one, and know
  97.  *   the hardware concerned, please get in contact with me.
  98.  *
  99.  * 2001/05/31: <rmk@arm.linux.org.uk>
  100.  * - Fix LCCR1 HSW value, fix all machine type specifications to
  101.  *   keep values in line.  (Please check your machine type specs)
  102.  *
  103.  * 2001/06/10: <rmk@arm.linux.org.uk>
  104.  * - Fiddle with the LCD controller from task context only; mainly
  105.  *   so that we can run with interrupts on, and sleep.
  106.  * - Convert #warnings into #errors.  No pain, no gain. ;)
  107.  *
  108.  * 2001/06/14: <rmk@arm.linux.org.uk>
  109.  * - Make the palette BPS value for 12bpp come out correctly.
  110.  * - Take notice of "greyscale" on any colour depth.
  111.  * - Make truecolor visuals use the RGB channel encoding information.
  112.  *
  113.  * 2001/07/02: <rmk@arm.linux.org.uk>
  114.  * - Fix colourmap problems.
  115.  *
  116.  * 2001/08/03: <cbrake@accelent.com>
  117.  *      - Ported from SA1100 to PXA250
  118.  */
  119. #include <linux/config.h>
  120. #include <linux/module.h>
  121. #include <linux/kernel.h>
  122. #include <linux/sched.h>
  123. #include <linux/errno.h>
  124. #include <linux/string.h>
  125. #include <linux/interrupt.h>
  126. #include <linux/slab.h>
  127. #include <linux/fb.h>
  128. #include <linux/delay.h>
  129. #include <linux/pm.h>
  130. #include <linux/init.h>
  131. #include <asm/hardware.h>
  132. #include <asm/io.h>
  133. #include <asm/irq.h>
  134. #include <asm/mach-types.h>
  135. #include <asm/uaccess.h>
  136. #include <video/fbcon.h>
  137. #include <video/fbcon-mfb.h>
  138. #include <video/fbcon-cfb4.h>
  139. #include <video/fbcon-cfb8.h>
  140. #include <video/fbcon-cfb16.h>
  141. /*
  142.  * debugging?
  143.  */
  144. #define DEBUG 0
  145. /*
  146.  * Complain if VAR is out of range.
  147.  */
  148. #define DEBUG_VAR 1
  149. #undef ASSABET_PAL_VIDEO
  150. #include "pxafb.h"
  151. void (*pxafb_blank_helper)(int blank);
  152. EXPORT_SYMBOL(pxafb_blank_helper);
  153. /*
  154.  * IMHO this looks wrong.  In 8BPP, length should be 8.
  155.  */
  156. static struct pxafb_rgb rgb_8 = {
  157. red: { offset: 0,  length: 4, },
  158. green: { offset: 0,  length: 4, },
  159. blue: { offset: 0,  length: 4, },
  160. transp: { offset: 0,  length: 0, },
  161. };
  162. static struct pxafb_rgb def_rgb_16 = {
  163. red: { offset: 11, length: 5, },
  164. green: { offset: 5,  length: 6, },
  165. blue: { offset: 0,  length: 5, },
  166. transp: { offset: 0,  length: 0, },
  167. };
  168. static struct pxafb_mach_info lubbock_info __initdata = {
  169. pixclock: 150000, /* clock period in ps */
  170. bpp: 8,
  171. xres: 640,
  172. yres: 480,
  173. hsync_len: 1, // LCD_HORIZONTAL_SYNC_PULSE_WIDTH,
  174. vsync_len: 1, // LCD_VERTICAL_SYNC_PULSE_WIDTH,
  175. left_margin: 3, // LCD_BEGIN_OF_LINE_WAIT_COUNT,
  176. upper_margin: 0, //LCD_BEGIN_FRAME_WAIT_COUNT,
  177. right_margin: 3, //LCD_END_OF_LINE_WAIT_COUNT,
  178. lower_margin: 0, //LCD_END_OF_FRAME_WAIT_COUNT,
  179. sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  180. lccr0: 0x0030087C, //LCD_CTL0_VALUE,
  181. lccr3: 0x0340FF0C  //LCD_CTL3_VALUE,
  182. };
  183. static struct pxafb_mach_info idp_info __initdata = {
  184. pixclock: 150000, /* clock period in ps */
  185. bpp: 8,
  186. xres: 640,
  187. yres: 480,
  188. hsync_len: 1, // LCD_HORIZONTAL_SYNC_PULSE_WIDTH,
  189. vsync_len: 1, // LCD_VERTICAL_SYNC_PULSE_WIDTH,
  190. left_margin: 3, // LCD_BEGIN_OF_LINE_WAIT_COUNT,
  191. upper_margin: 0, //LCD_BEGIN_FRAME_WAIT_COUNT,
  192. right_margin: 3, //LCD_END_OF_LINE_WAIT_COUNT,
  193. lower_margin: 0, //LCD_END_OF_FRAME_WAIT_COUNT,
  194. sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  195. lccr0: 0x0030087C, //LCD_CTL0_VALUE,
  196. lccr3: 0x0340FF0C  //LCD_CTL3_VALUE,
  197. };
  198. static struct pxafb_mach_info * __init
  199. pxafb_get_machine_info(struct pxafb_info *fbi)
  200. {
  201. struct pxafb_mach_info *inf = NULL;
  202. /*
  203.  *            R        G       B       T
  204.  * default  {11,5}, { 5,6}, { 0,5}, { 0,0}
  205.  * bitsy    {12,4}, { 7,4}, { 1,4}, { 0,0}
  206.  * freebird { 8,4}, { 4,4}, { 0,4}, {12,4}
  207.  */
  208. if (machine_is_lubbock()) {
  209. inf = &lubbock_info;
  210. } else if (machine_is_pxa_idp()) {
  211. inf = &idp_info;
  212. }
  213. return inf;
  214. }
  215. static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);
  216. static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
  217. static inline void pxafb_schedule_task(struct pxafb_info *fbi, u_int state)
  218. {
  219. unsigned long flags;
  220. local_irq_save(flags);
  221. /*
  222.  * We need to handle two requests being made at the same time.
  223.  * There are two important cases:
  224.  *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
  225.  *     We must perform the unblanking, which will do our REENABLE for us.
  226.  *  2. When we are blanking, but immediately unblank before we have
  227.  *     blanked.  We do the "REENABLE" thing here as well, just to be sure.
  228.  */
  229. if (fbi->task_state == C_ENABLE && state == C_REENABLE)
  230. state = (u_int) -1;
  231. if (fbi->task_state == C_DISABLE && state == C_ENABLE)
  232. state = C_REENABLE;
  233. if (state != (u_int)-1) {
  234. fbi->task_state = state;
  235. schedule_task(&fbi->task);
  236. }
  237. local_irq_restore(flags);
  238. }
  239. /*
  240.  * Get the VAR structure pointer for the specified console
  241.  */
  242. static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con)
  243. {
  244. struct pxafb_info *fbi = (struct pxafb_info *)info;
  245. return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var;
  246. }
  247. /*
  248.  * Get the DISPLAY structure pointer for the specified console
  249.  */
  250. static inline struct display *get_con_display(struct fb_info *info, int con)
  251. {
  252. struct pxafb_info *fbi = (struct pxafb_info *)info;
  253. return (con < 0) ? fbi->fb.disp : &fb_display[con];
  254. }
  255. /*
  256.  * Get the CMAP pointer for the specified console
  257.  */
  258. static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con)
  259. {
  260. struct pxafb_info *fbi = (struct pxafb_info *)info;
  261. return (con == fbi->currcon || con == -1) ? &fbi->fb.cmap : &fb_display[con].cmap;
  262. }
  263. static inline u_int
  264. chan_to_field(u_int chan, struct fb_bitfield *bf)
  265. {
  266. chan &= 0xffff;
  267. chan >>= 16 - bf->length;
  268. return chan << bf->offset;
  269. }
  270. static int
  271. pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
  272.        u_int trans, struct fb_info *info)
  273. {
  274. struct pxafb_info *fbi = (struct pxafb_info *)info;
  275. u_int val, ret = 1;
  276. if (regno < fbi->palette_size) {
  277. val = ((red >> 0) & 0xf800);
  278. val |= ((green >> 5) & 0x07e0);
  279. val |= ((blue >> 11) & 0x001f);
  280. fbi->palette_cpu[regno] = val;
  281. ret = 0;
  282. }
  283. return ret;
  284. }
  285. static int
  286. pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  287.    u_int trans, struct fb_info *info)
  288. {
  289. struct pxafb_info *fbi = (struct pxafb_info *)info;
  290. u_int val;
  291. int ret = 1;
  292. /*
  293.  * If greyscale is true, then we convert the RGB value
  294.  * to greyscale no mater what visual we are using.
  295.  */
  296. if (fbi->fb.var.grayscale)
  297. red = green = blue = (19595 * red + 38470 * green +
  298. 7471 * blue) >> 16;
  299. switch (fbi->fb.disp->visual) {
  300. case FB_VISUAL_TRUECOLOR:
  301. /*
  302.  * 12 or 16-bit True Colour.  We encode the RGB value
  303.  * according to the RGB bitfield information.
  304.  */
  305. if (regno < 16) {
  306. u16 *pal = fbi->fb.pseudo_palette;
  307. val  = chan_to_field(red, &fbi->fb.var.red);
  308. val |= chan_to_field(green, &fbi->fb.var.green);
  309. val |= chan_to_field(blue, &fbi->fb.var.blue);
  310. pal[regno] = val;
  311. ret = 0;
  312. }
  313. break;
  314. case FB_VISUAL_PSEUDOCOLOR:
  315. ret = pxafb_setpalettereg(regno, red, green, blue, trans, info);
  316. break;
  317. }
  318. return ret;
  319. }
  320. /*
  321.  *  pxafb_decode_var():
  322.  *    Get the video params out of 'var'. If a value doesn't fit, round it up,
  323.  *    if it's too big, return -EINVAL.
  324.  *
  325.  *    Suggestion: Round up in the following order: bits_per_pixel, xres,
  326.  *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
  327.  *    bitfields, horizontal timing, vertical timing.
  328.  */
  329. static int pxafb_validate_var(struct fb_var_screeninfo *var,
  330.  struct pxafb_info *fbi)
  331. {
  332. int ret = -EINVAL;
  333. if (var->xres < MIN_XRES)
  334. var->xres = MIN_XRES;
  335. if (var->yres < MIN_YRES)
  336. var->yres = MIN_YRES;
  337. if (var->xres > fbi->max_xres)
  338. var->xres = fbi->max_xres;
  339. if (var->yres > fbi->max_yres)
  340. var->yres = fbi->max_yres;
  341. var->xres_virtual =
  342.     var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
  343. var->yres_virtual =
  344.     var->yres_virtual < var->yres ? var->yres : var->yres_virtual;
  345. DPRINTK("var->bits_per_pixel=%dn", var->bits_per_pixel);
  346. switch (var->bits_per_pixel) {
  347. #ifdef FBCON_HAS_CFB4
  348. case 4:  ret = 0; break;
  349. #endif
  350. #ifdef FBCON_HAS_CFB8
  351. case 8:  ret = 0; break;
  352. #endif
  353. #ifdef FBCON_HAS_CFB16
  354. case 12:
  355. /* make sure we are in passive mode */
  356. if (!(fbi->lccr0 & LCCR0_PAS))
  357. ret = 0;
  358. break;
  359. case 16:
  360. /* make sure we are in active mode */
  361. if ((fbi->lccr0 & LCCR0_PAS))
  362. ret = 0;
  363. break;
  364. #endif
  365. default:
  366. break;
  367. }
  368. return ret;
  369. }
  370. static inline void pxafb_set_truecolor(u_int is_true_color)
  371. {
  372. DPRINTK("true_color = %dn", is_true_color);
  373. #ifdef CONFIG_SA1100_ASSABET
  374. if (machine_is_assabet()) {
  375. #if 1
  376. // phase 4 or newer Assabet's
  377. if (is_true_color)
  378. BCR_set(BCR_LCD_12RGB);
  379. else
  380. BCR_clear(BCR_LCD_12RGB);
  381. #else
  382. // older Assabet's
  383. if (is_true_color)
  384. BCR_clear(BCR_LCD_12RGB);
  385. else
  386. BCR_set(BCR_LCD_12RGB);
  387. #endif
  388. }
  389. #endif
  390. }
  391. static void
  392. pxafb_hw_set_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
  393. {
  394. fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, &fbi->fb);
  395. /* Set board control register to handle new color depth */
  396. pxafb_set_truecolor(var->bits_per_pixel >= 16);
  397. pxafb_activate_var(var, fbi);
  398. }
  399. /*
  400.  * pxafb_set_var():
  401.  * Set the user defined part of the display for the specified console
  402.  */
  403. static int
  404. pxafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  405. {
  406. struct pxafb_info *fbi = (struct pxafb_info *)info;
  407. struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con);
  408. struct display *display = get_con_display(&fbi->fb, con);
  409. int err, chgvar = 0, rgbidx;
  410. DPRINTK("set_varn");
  411. /*
  412.  * Decode var contents into a par structure, adjusting any
  413.  * out of range values.
  414.  */
  415. err = pxafb_validate_var(var, fbi);
  416. if (err)
  417. return err;
  418. if (var->activate & FB_ACTIVATE_TEST)
  419. return 0;
  420. if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
  421. return -EINVAL;
  422. if (dvar->xres != var->xres)
  423. chgvar = 1;
  424. if (dvar->yres != var->yres)
  425. chgvar = 1;
  426. if (dvar->xres_virtual != var->xres_virtual)
  427. chgvar = 1;
  428. if (dvar->yres_virtual != var->yres_virtual)
  429. chgvar = 1;
  430. if (dvar->bits_per_pixel != var->bits_per_pixel)
  431. chgvar = 1;
  432. if (con < 0)
  433. chgvar = 0;
  434. switch (var->bits_per_pixel) {
  435. #ifdef FBCON_HAS_CFB4
  436. case 4:
  437. if (fbi->cmap_static)
  438. display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
  439. else
  440. display->visual = FB_VISUAL_PSEUDOCOLOR;
  441. display->line_length = var->xres / 2;
  442. display->dispsw = &fbcon_cfb4;
  443. rgbidx = RGB_8;
  444. break;
  445. #endif
  446. #ifdef FBCON_HAS_CFB8
  447. case 8:
  448. if (fbi->cmap_static)
  449. display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
  450. else
  451. display->visual = FB_VISUAL_PSEUDOCOLOR;
  452. display->line_length = var->xres;
  453. display->dispsw = &fbcon_cfb8;
  454. rgbidx = RGB_8;
  455. break;
  456. #endif
  457. #ifdef FBCON_HAS_CFB16
  458. case 12:
  459. case 16:
  460. display->visual = FB_VISUAL_TRUECOLOR;
  461. display->line_length = var->xres * 2;
  462. display->dispsw = &fbcon_cfb16;
  463. display->dispsw_data = fbi->fb.pseudo_palette;
  464. rgbidx = RGB_16;
  465. break;
  466. #endif
  467. default:
  468. rgbidx = 0;
  469. display->dispsw = &fbcon_dummy;
  470. break;
  471. }
  472. display->screen_base = fbi->screen_cpu;
  473. display->next_line = display->line_length;
  474. display->type = fbi->fb.fix.type;
  475. display->type_aux = fbi->fb.fix.type_aux;
  476. display->ypanstep = fbi->fb.fix.ypanstep;
  477. display->ywrapstep = fbi->fb.fix.ywrapstep;
  478. display->can_soft_blank = 1;
  479. display->inverse = 0;
  480. *dvar = *var;
  481. dvar->activate &= ~FB_ACTIVATE_ALL;
  482. /*
  483.  * Copy the RGB parameters for this display
  484.  * from the machine specific parameters.
  485.  */
  486. dvar->red = fbi->rgb[rgbidx]->red;
  487. dvar->green = fbi->rgb[rgbidx]->green;
  488. dvar->blue = fbi->rgb[rgbidx]->blue;
  489. dvar->transp = fbi->rgb[rgbidx]->transp;
  490. DPRINTK("RGBT length = %d:%d:%d:%dn",
  491. dvar->red.length, dvar->green.length, dvar->blue.length,
  492. dvar->transp.length);
  493. DPRINTK("RGBT offset = %d:%d:%d:%dn",
  494. dvar->red.offset, dvar->green.offset, dvar->blue.offset,
  495. dvar->transp.offset);
  496. /*
  497.  * Update the old var.  The fbcon drivers still use this.
  498.  * Once they are using fbi->fb.var, this can be dropped.
  499.  */
  500. display->var = *dvar;
  501. /*
  502.  * If we are setting all the virtual consoles, also set the
  503.  * defaults used to create new consoles.
  504.  */
  505. if (var->activate & FB_ACTIVATE_ALL)
  506. fbi->fb.disp->var = *dvar;
  507. /*
  508.  * If the console has changed and the console has defined
  509.  * a changevar function, call that function.
  510.  */
  511. if (chgvar && info && fbi->fb.changevar)
  512. fbi->fb.changevar(con);
  513. /* If the current console is selected, activate the new var. */
  514. if (con != fbi->currcon)
  515. return 0;
  516. pxafb_hw_set_var(dvar, fbi);
  517. return 0;
  518. }
  519. static int
  520. __do_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  521.       struct fb_info *info)
  522. {
  523. struct pxafb_info *fbi = (struct pxafb_info *)info;
  524. struct fb_cmap *dcmap = get_con_cmap(info, con);
  525. int err = 0;
  526. if (con == -1)
  527. con = fbi->currcon;
  528. /* no colormap allocated? (we always have "this" colour map allocated) */
  529. if (con >= 0)
  530. err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0);
  531. if (!err && con == fbi->currcon)
  532. err = fb_set_cmap(cmap, kspc, pxafb_setcolreg, info);
  533. if (!err)
  534. fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
  535. return err;
  536. }
  537. static int
  538. pxafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  539.   struct fb_info *info)
  540. {
  541. struct display *disp = get_con_display(info, con);
  542. if (disp->visual == FB_VISUAL_TRUECOLOR)
  543. return -EINVAL;
  544. return __do_set_cmap(cmap, kspc, con, info);
  545. }
  546. static int
  547. pxafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
  548. {
  549. struct display *display = get_con_display(info, con);
  550. *fix = info->fix;
  551. fix->line_length = display->line_length;
  552. fix->visual  = display->visual;
  553. return 0;
  554. }
  555. static int
  556. pxafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  557. {
  558. *var = *get_con_var(info, con);
  559. return 0;
  560. }
  561. static int
  562. pxafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
  563. {
  564. struct fb_cmap *dcmap = get_con_cmap(info, con);
  565. fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);
  566. return 0;
  567. }
  568. static struct fb_ops pxafb_ops = {
  569. owner: THIS_MODULE,
  570. fb_get_fix: pxafb_get_fix,
  571. fb_get_var: pxafb_get_var,
  572. fb_set_var: pxafb_set_var,
  573. fb_get_cmap: pxafb_get_cmap,
  574. fb_set_cmap: pxafb_set_cmap,
  575. };
  576. /*
  577.  *  pxafb_switch():       
  578.  * Change to the specified console.  Palette and video mode
  579.  *      are changed to the console's stored parameters.
  580.  *
  581.  * Uh oh, this can be called from a tasklet (IRQ)
  582.  */
  583. static int pxafb_switch(int con, struct fb_info *info)
  584. {
  585. struct pxafb_info *fbi = (struct pxafb_info *)info;
  586. struct display *disp;
  587. struct fb_cmap *cmap;
  588. DPRINTK("con=%d info->modename=%sn", con, fbi->fb.modename);
  589. if (con == fbi->currcon)
  590. return 0;
  591. if (fbi->currcon >= 0) {
  592. disp = fb_display + fbi->currcon;
  593. /*
  594.  * Save the old colormap and video mode.
  595.  */
  596. disp->var = fbi->fb.var;
  597. if (disp->cmap.len)
  598. fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0);
  599. }
  600. fbi->currcon = con;
  601. disp = fb_display + con;
  602. /*
  603.  * Make sure that our colourmap contains 256 entries.
  604.  */
  605. fb_alloc_cmap(&fbi->fb.cmap, 256, 0);
  606. if (disp->cmap.len)
  607. cmap = &disp->cmap;
  608. else
  609. cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
  610. fb_copy_cmap(cmap, &fbi->fb.cmap, 0);
  611. fbi->fb.var = disp->var;
  612. fbi->fb.var.activate = FB_ACTIVATE_NOW;
  613. pxafb_set_var(&fbi->fb.var, con, info);
  614. return 0;
  615. }
  616. /*
  617.  * Formal definition of the VESA spec:
  618.  *  On
  619.  *   This refers to the state of the display when it is in full operation
  620.  *  Stand-By
  621.  *   This defines an optional operating state of minimal power reduction with
  622.  *   the shortest recovery time
  623.  *  Suspend
  624.  *   This refers to a level of power management in which substantial power
  625.  *   reduction is achieved by the display.  The display can have a longer 
  626.  *   recovery time from this state than from the Stand-by state
  627.  *  Off
  628.  *   This indicates that the display is consuming the lowest level of power
  629.  *   and is non-operational. Recovery from this state may optionally require
  630.  *   the user to manually power on the monitor
  631.  *
  632.  *  Now, the fbdev driver adds an additional state, (blank), where they
  633.  *  turn off the video (maybe by colormap tricks), but don't mess with the
  634.  *  video itself: think of it semantically between on and Stand-By.
  635.  *
  636.  *  So here's what we should do in our fbdev blank routine:
  637.  *
  638.  *   VESA_NO_BLANKING (mode 0) Video on,  front/back light on
  639.  *   VESA_VSYNC_SUSPEND (mode 1)   Video on,  front/back light off
  640.  *   VESA_HSYNC_SUSPEND (mode 2)   Video on,  front/back light off
  641.  *   VESA_POWERDOWN (mode 3) Video off, front/back light off
  642.  *
  643.  *  This will match the matrox implementation.
  644.  */
  645. /*
  646.  * pxafb_blank():
  647.  * Blank the display by setting all palette values to zero.  Note, the 
  648.  *  12 and 16 bpp modes don't really use the palette, so this will not
  649.  *      blank the display in all modes.  
  650.  */
  651. static void pxafb_blank(int blank, struct fb_info *info)
  652. {
  653. struct pxafb_info *fbi = (struct pxafb_info *)info;
  654. int i;
  655. DPRINTK("pxafb_blank: blank=%d info->modename=%sn", blank,
  656. fbi->fb.modename);
  657. switch (blank) {
  658. case VESA_POWERDOWN:
  659. case VESA_VSYNC_SUSPEND:
  660. case VESA_HSYNC_SUSPEND:
  661. if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
  662.     fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
  663. for (i = 0; i < fbi->palette_size; i++)
  664. pxafb_setpalettereg(i, 0, 0, 0, 0, info);
  665. pxafb_schedule_task(fbi, C_DISABLE);
  666. if (pxafb_blank_helper)
  667. pxafb_blank_helper(blank);
  668. break;
  669. case VESA_NO_BLANKING:
  670. if (pxafb_blank_helper)
  671. pxafb_blank_helper(blank);
  672. if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
  673.     fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
  674. fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, info);
  675. pxafb_schedule_task(fbi, C_ENABLE);
  676. }
  677. }
  678. static int pxafb_updatevar(int con, struct fb_info *info)
  679. {
  680. DPRINTK("enteredn");
  681. return 0;
  682. }
  683. /*
  684.  * Calculate the PCD value from the clock rate (in picoseconds).
  685.  * We take account of the PPCR clock setting.
  686.  */
  687. static inline int get_pcd(unsigned int pixclock)
  688. {
  689. unsigned int pcd;
  690. if (pixclock) {
  691. pcd = get_lclk_frequency_10khz() * pixclock;
  692. pcd /= 100000000;
  693. pcd += 1; /* make up for integer math truncations */
  694. } else {
  695. printk(KERN_WARNING "Please convert me to use the PCD calculationsn");
  696. pcd = 0;
  697. }
  698. return pcd;
  699. }
  700. /*
  701.  * pxafb_activate_var():
  702.  * Configures LCD Controller based on entries in var parameter.  Settings are      
  703.  *      only written to the controller if changes were made.  
  704.  */
  705. static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
  706. {
  707. struct pxafb_lcd_reg new_regs;
  708. u_int pcd = get_pcd(var->pixclock);
  709. u_long flags;
  710. DPRINTK("Configuring PXA LCDn");
  711. DPRINTK("var: xres=%d hslen=%d lm=%d rm=%dn",
  712. var->xres, var->hsync_len,
  713. var->left_margin, var->right_margin);
  714. DPRINTK("var: yres=%d vslen=%d um=%d bm=%dn",
  715. var->yres, var->vsync_len,
  716. var->upper_margin, var->lower_margin);
  717. #if DEBUG_VAR
  718. if (var->xres < 16        || var->xres > 1024)
  719. printk(KERN_ERR "%s: invalid xres %dn",
  720. fbi->fb.fix.id, var->xres);
  721. if (var->hsync_len < 1    || var->hsync_len > 64)
  722. printk(KERN_ERR "%s: invalid hsync_len %dn",
  723. fbi->fb.fix.id, var->hsync_len);
  724. if (var->left_margin < 1  || var->left_margin > 255)
  725. printk(KERN_ERR "%s: invalid left_margin %dn",
  726. fbi->fb.fix.id, var->left_margin);
  727. if (var->right_margin < 1 || var->right_margin > 255)
  728. printk(KERN_ERR "%s: invalid right_margin %dn",
  729. fbi->fb.fix.id, var->right_margin);
  730. if (var->yres < 1         || var->yres > 1024)
  731. printk(KERN_ERR "%s: invalid yres %dn",
  732. fbi->fb.fix.id, var->yres);
  733. if (var->vsync_len < 1    || var->vsync_len > 64)
  734. printk(KERN_ERR "%s: invalid vsync_len %dn",
  735. fbi->fb.fix.id, var->vsync_len);
  736. if (var->upper_margin < 0 || var->upper_margin > 255)
  737. printk(KERN_ERR "%s: invalid upper_margin %dn",
  738. fbi->fb.fix.id, var->upper_margin);
  739. if (var->lower_margin < 0 || var->lower_margin > 255)
  740. printk(KERN_ERR "%s: invalid lower_margin %dn",
  741. fbi->fb.fix.id, var->lower_margin);
  742. #endif
  743. // FIXME using hardcoded values for now
  744. new_regs.lccr0 = fbi->lccr0;
  745. // |
  746. // LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
  747. // LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
  748. new_regs.lccr1 = 0x3030A7F;
  749. // LCCR1_DisWdth(var->xres) +
  750. // LCCR1_HorSnchWdth(var->hsync_len) +
  751. // LCCR1_BegLnDel(var->left_margin) +
  752. // LCCR1_EndLnDel(var->right_margin);
  753. new_regs.lccr2 = 0x4EF;
  754. // LCCR2_DisHght(var->yres) +
  755. // LCCR2_VrtSnchWdth(var->vsync_len) +
  756. // LCCR2_BegFrmDel(var->upper_margin) +
  757. // LCCR2_EndFrmDel(var->lower_margin);
  758. new_regs.lccr3 = fbi->lccr3;
  759. // |
  760. // (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
  761. // (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) |
  762. // LCCR3_ACBsCntOff;
  763. // if (pcd)
  764. // new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
  765. DPRINTK("nlccr0 = 0x%08xn", new_regs.lccr0);
  766. DPRINTK("nlccr1 = 0x%08xn", new_regs.lccr1);
  767. DPRINTK("nlccr2 = 0x%08xn", new_regs.lccr2);
  768. DPRINTK("nlccr3 = 0x%08xn", new_regs.lccr3);
  769. /* Update shadow copy atomically */
  770. local_irq_save(flags);
  771. /* setup dma descriptors */
  772. fbi->dmadesc_fblow_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 3*16);
  773. fbi->dmadesc_fbhigh_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 2*16);
  774. fbi->dmadesc_palette_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 1*16);
  775. fbi->dmadesc_fblow_dma = fbi->palette_dma - 3*16;
  776. fbi->dmadesc_fbhigh_dma = fbi->palette_dma - 2*16;
  777. fbi->dmadesc_palette_dma = fbi->palette_dma - 1*16;
  778. DPRINTK("fbi->dmadesc_fblow_cpu = 0x%xn", fbi->dmadesc_fblow_cpu);
  779. DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%xn", fbi->dmadesc_fbhigh_cpu);
  780. DPRINTK("fbi->dmadesc_palette_cpu = 0x%xn", fbi->dmadesc_palette_cpu);
  781. DPRINTK("fbi->dmadesc_fblow_dma = 0x%xn", fbi->dmadesc_fblow_dma);
  782. DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%xn", fbi->dmadesc_fbhigh_dma);
  783. DPRINTK("fbi->dmadesc_palette_dma = 0x%xn", fbi->dmadesc_palette_dma);
  784. DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%xn", fbi->dmadesc_fblow_cpu->fdadr);
  785. DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%xn", fbi->dmadesc_fbhigh_cpu->fdadr);
  786. DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%xn", fbi->dmadesc_palette_cpu->fdadr);
  787. DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%xn", fbi->dmadesc_fblow_cpu->fsadr);
  788. DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%xn", fbi->dmadesc_fbhigh_cpu->fsadr);
  789. DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%xn", fbi->dmadesc_palette_cpu->fsadr);
  790. DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%xn", fbi->dmadesc_fblow_cpu->ldcmd);
  791. DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%xn", fbi->dmadesc_fbhigh_cpu->ldcmd);
  792. DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%xn", fbi->dmadesc_palette_cpu->ldcmd);
  793. #define BYTES_PER_PANEL ((fbi->lccr0 & LCCR0_SDS) ? (var->xres * var->yres * var->bits_per_pixel / 8 / 2) : 
  794.                                     (var->xres * var->yres * var->bits_per_pixel / 8))
  795. /* populate descriptors */
  796. fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma;
  797. fbi->dmadesc_fblow_cpu->fsadr = fbi->screen_dma + BYTES_PER_PANEL;
  798. fbi->dmadesc_fblow_cpu->ldcmd = BYTES_PER_PANEL;
  799. fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma;
  800. fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma;
  801. fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL;
  802. fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
  803. fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
  804. fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
  805. fbi->fdadr0 = fbi->dmadesc_palette_dma;
  806. fbi->fdadr1 = fbi->dmadesc_fblow_dma;
  807. fbi->reg_lccr0 = new_regs.lccr0;
  808. fbi->reg_lccr1 = new_regs.lccr1;
  809. fbi->reg_lccr2 = new_regs.lccr2;
  810. fbi->reg_lccr3 = new_regs.lccr3;
  811. local_irq_restore(flags);
  812. /*
  813.  * Only update the registers if the controller is enabled
  814.  * and something has changed.
  815.  */
  816. if ((LCCR0 != fbi->reg_lccr0)       || (LCCR1 != fbi->reg_lccr1) ||
  817.     (LCCR2 != fbi->reg_lccr2)       || (LCCR3 != fbi->reg_lccr3) ||
  818.     (FDADR0 != fbi->fdadr0) || (FDADR1 != fbi->fdadr1))
  819. pxafb_schedule_task(fbi, C_REENABLE);
  820. return 0;
  821. }
  822. /*
  823.  * NOTE!  The following functions are purely helpers for set_ctrlr_state.
  824.  * Do not call them directly; set_ctrlr_state does the correct serialisation
  825.  * to ensure that things happen in the right way 100% of time time.
  826.  * -- rmk
  827.  */
  828. /*
  829.  * FIXME: move LCD power stuff into pxafb_power_up_lcd()
  830.  * Also, I'm expecting that the backlight stuff should
  831.  * be handled differently.
  832.  */
  833. static void pxafb_backlight_on(struct pxafb_info *fbi)
  834. {
  835. DPRINTK("backlight onn");
  836. #ifdef CONFIG_ARCH_PXA_IDP
  837. if(machine_is_pxa_idp()) {
  838. FB_BACKLIGHT_ON();
  839. }
  840. #endif
  841. }
  842. /*
  843.  * FIXME: move LCD power stuf into pxafb_power_down_lcd()
  844.  * Also, I'm expecting that the backlight stuff should
  845.  * be handled differently.
  846.  */
  847. static void pxafb_backlight_off(struct pxafb_info *fbi)
  848. {
  849. DPRINTK("backlight offn");
  850. #ifdef CONFIG_ARCH_PXA_IDP
  851. if(machine_is_pxa_idp()) {
  852. FB_BACKLIGHT_OFF();
  853. }
  854. #endif
  855. }
  856. static void pxafb_power_up_lcd(struct pxafb_info *fbi)
  857. {
  858. DPRINTK("LCD power onn");
  859. CKEN |= CKEN16_LCD;
  860. #if CONFIG_ARCH_PXA_IDP
  861. /* set GPIOs, etc */
  862. if(machine_is_pxa_idp()) {
  863. // FIXME need to add proper delays
  864. FB_PWR_ON();
  865. FB_VLCD_ON(); // FIXME this should be after scanning starts
  866. }
  867. #endif
  868. }
  869. static void pxafb_power_down_lcd(struct pxafb_info *fbi)
  870. {
  871. DPRINTK("LCD power offn");
  872. CKEN &= ~CKEN16_LCD;
  873. /* set GPIOs, etc */
  874. #if CONFIG_ARCH_PXA_IDP
  875. if(machine_is_pxa_idp()) {
  876. // FIXME need to add proper delays
  877. FB_PWR_OFF();
  878. FB_VLCD_OFF(); // FIXME this should be before scanning stops
  879. }
  880. #endif
  881. }
  882. static void pxafb_setup_gpio(struct pxafb_info *fbi)
  883. {
  884. unsigned int lccr0;
  885. /*
  886.  * setup is based on type of panel supported
  887.  */
  888. lccr0 = fbi->lccr0;
  889. /* 4 bit interface */
  890. if ((lccr0 & LCCR0_CMS) && (lccr0 & LCCR0_SDS) && !(lccr0 & LCCR0_DPD))
  891. {
  892. // bits 58-61
  893. GPDR1 |= (0xf << 26);
  894. GAFR1_U = (GAFR1_U & (0xff << 20)) | (0xaa << 20);
  895. // bits 74-77
  896. GPDR2 |= (0xf << 10);
  897. GAFR2_L = (0xaa << 20);
  898. }
  899. /* 8 bit interface */
  900. else if (((lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_DPD))) ||
  901.  (!(lccr0 & LCCR0_CMS) && !(lccr0 & LCCR0_PAS) && !(lccr0 & LCCR0_SDS)))
  902. {
  903. GPDR1 |= (0x3f << 26);
  904. GPDR2 |= (0x3);
  905. GAFR1_U = (GAFR1_U & (0xfff << 20)) | (0x2aa << 20);
  906. GAFR2_L = (GAFR2_L & 0xf) + (0xa);
  907. // bits 74-77
  908. GPDR2 |= (0xf << 10);
  909. GAFR2_L |= (0xaa << 20);
  910. }
  911. /* 16 bit interface */
  912. else if (!(lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_PAS)))
  913. {
  914. GPDR1 |= 0xFC000000;
  915. GPDR2 |= 0x00003FFF;
  916. GAFR1_U = (GAFR1_U & 0x000FFFFF) | 0xAAA00000;
  917. GAFR2_L = (GAFR2_L & 0xF0000000) | 0x0AAAAAAA;
  918. }
  919. }
  920. static void pxafb_enable_controller(struct pxafb_info *fbi)
  921. {
  922. DPRINTK("Enabling LCD controllern");
  923. /* Sequence from 11.7.10 */
  924. LCCR3 = fbi->reg_lccr3;
  925. LCCR2 = fbi->reg_lccr2;
  926. LCCR1 = fbi->reg_lccr1;
  927. LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB;
  928. /* FIXME we used to have LCD power control here */
  929. FDADR0 = fbi->fdadr0;
  930. FDADR1 = fbi->fdadr1;
  931. LCCR0 |= LCCR0_ENB;
  932. DPRINTK("FDADR0 = 0x%08xn", (unsigned int)FDADR0);
  933. DPRINTK("FDADR1 = 0x%08xn", (unsigned int)FDADR1);
  934. DPRINTK("LCCR0 = 0x%08xn", (unsigned int)LCCR0);
  935. DPRINTK("LCCR1 = 0x%08xn", (unsigned int)LCCR1);
  936. DPRINTK("LCCR2 = 0x%08xn", (unsigned int)LCCR2);
  937. DPRINTK("LCCR3 = 0x%08xn", (unsigned int)LCCR3);
  938. }
  939. static void pxafb_disable_controller(struct pxafb_info *fbi)
  940. {
  941. DECLARE_WAITQUEUE(wait, current);
  942. DPRINTK("Disabling LCD controllern");
  943. /* FIXME add power down GPIO stuff here */
  944. add_wait_queue(&fbi->ctrlr_wait, &wait);
  945. set_current_state(TASK_UNINTERRUPTIBLE);
  946. LCSR = 0xffffffff; /* Clear LCD Status Register */
  947. LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
  948. enable_irq(IRQ_LCD); /* Enable LCD IRQ */
  949. LCCR0 &= ~LCCR0_ENB; /* Disable LCD Controller */
  950. schedule_timeout(20 * HZ / 1000);
  951. current->state = TASK_RUNNING;
  952. remove_wait_queue(&fbi->ctrlr_wait, &wait);
  953. }
  954. /*
  955.  *  pxafb_handle_irq: Handle 'LCD DONE' interrupts.
  956.  */
  957. static void pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
  958. {
  959. struct pxafb_info *fbi = dev_id;
  960. unsigned int lcsr = LCSR;
  961. if (lcsr & LCSR_LDD) {
  962. LCCR0 |= LCCR0_LDM;
  963. wake_up(&fbi->ctrlr_wait);
  964. }
  965. LCSR = lcsr;
  966. }
  967. /*
  968.  * This function must be called from task context only, since it will
  969.  * sleep when disabling the LCD controller, or if we get two contending
  970.  * processes trying to alter state.
  971.  */
  972. static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
  973. {
  974. u_int old_state;
  975. down(&fbi->ctrlr_sem);
  976. old_state = fbi->state;
  977. switch (state) {
  978. case C_DISABLE_CLKCHANGE:
  979. /*
  980.  * Disable controller for clock change.  If the
  981.  * controller is already disabled, then do nothing.
  982.  */
  983. if (old_state != C_DISABLE) {
  984. fbi->state = state;
  985. pxafb_disable_controller(fbi);
  986. }
  987. break;
  988. case C_DISABLE:
  989. /*
  990.  * Disable controller
  991.  */
  992. if (old_state != C_DISABLE) {
  993. fbi->state = state;
  994. pxafb_backlight_off(fbi);
  995. if (old_state != C_DISABLE_CLKCHANGE)
  996. pxafb_disable_controller(fbi);
  997. pxafb_power_down_lcd(fbi);
  998. }
  999. break;
  1000. case C_ENABLE_CLKCHANGE:
  1001. /*
  1002.  * Enable the controller after clock change.  Only
  1003.  * do this if we were disabled for the clock change.
  1004.  */
  1005. if (old_state == C_DISABLE_CLKCHANGE) {
  1006. fbi->state = C_ENABLE;
  1007. pxafb_enable_controller(fbi);
  1008. }
  1009. break;
  1010. case C_REENABLE:
  1011. /*
  1012.  * Re-enable the controller only if it was already
  1013.  * enabled.  This is so we reprogram the control
  1014.  * registers.
  1015.  */
  1016. if (old_state == C_ENABLE) {
  1017. pxafb_disable_controller(fbi);
  1018. pxafb_setup_gpio(fbi);
  1019. pxafb_enable_controller(fbi);
  1020. }
  1021. break;
  1022. case C_ENABLE:
  1023. /*
  1024.  * Power up the LCD screen, enable controller, and
  1025.  * turn on the backlight.
  1026.  */
  1027. if (old_state != C_ENABLE) {
  1028. fbi->state = C_ENABLE;
  1029. pxafb_setup_gpio(fbi);
  1030. pxafb_power_up_lcd(fbi);
  1031. pxafb_enable_controller(fbi);
  1032. pxafb_backlight_on(fbi);
  1033. }
  1034. break;
  1035. }
  1036. up(&fbi->ctrlr_sem);
  1037. }
  1038. /*
  1039.  * Our LCD controller task (which is called when we blank or unblank)
  1040.  * via keventd.
  1041.  */
  1042. static void pxafb_task(void *dummy)
  1043. {
  1044. struct pxafb_info *fbi = dummy;
  1045. u_int state = xchg(&fbi->task_state, -1);
  1046. set_ctrlr_state(fbi, state);
  1047. }
  1048. #ifdef CONFIG_CPU_FREQ
  1049. /*
  1050.  * CPU clock speed change handler.  We need to adjust the LCD timing
  1051.  * parameters when the CPU clock is adjusted by the power management
  1052.  * subsystem.
  1053.  */
  1054. static int
  1055. pxafb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
  1056.  void *data)
  1057. {
  1058. struct pxafb_info *fbi = TO_INF(nb, clockchg);
  1059. u_int pcd;
  1060. switch (val) {
  1061. case CPUFREQ_MINMAX:
  1062. /* todo: fill in min/max values */
  1063. break;
  1064. case CPUFREQ_PRECHANGE:
  1065. set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
  1066. break;
  1067. case CPUFREQ_POSTCHANGE:
  1068. pcd = get_pcd(fbi->fb.var.pixclock);
  1069. fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
  1070. set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
  1071. break;
  1072. }
  1073. return 0;
  1074. }
  1075. #endif
  1076. #ifdef CONFIG_PM
  1077. /*
  1078.  * Power management hook.  Note that we won't be called from IRQ context,
  1079.  * unlike the blank functions above, so we may sleep.
  1080.  */
  1081. static int
  1082. pxafb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
  1083. {
  1084. struct pxafb_info *fbi = pm_dev->data;
  1085. DPRINTK("pm_callback: %dn", req);
  1086. if (req == PM_SUSPEND || req == PM_RESUME) {
  1087. int state = (int)data;
  1088. if (state == 0) {
  1089. /* Enter D0. */
  1090. set_ctrlr_state(fbi, C_ENABLE);
  1091. } else {
  1092. /* Enter D1-D3.  Disable the LCD controller.  */
  1093. set_ctrlr_state(fbi, C_DISABLE);
  1094. }
  1095. }
  1096. DPRINTK("donen");
  1097. return 0;
  1098. }
  1099. #endif
  1100. /*
  1101.  * pxafb_map_video_memory():
  1102.  *      Allocates the DRAM memory for the frame buffer.  This buffer is  
  1103.  * remapped into a non-cached, non-buffered, memory region to  
  1104.  *      allow palette and pixel writes to occur without flushing the 
  1105.  *      cache.  Once this area is remapped, all virtual memory
  1106.  *      access to the video memory should occur at the new region.
  1107.  */
  1108. static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
  1109. {
  1110. u_long palette_mem_size;
  1111. /*
  1112.  * We reserve one page for the palette, plus the size
  1113.  * of the framebuffer.
  1114.  *
  1115.  * layout of stuff in memory
  1116.  *
  1117.  *                fblow descriptor
  1118.  *                fbhigh descriptor
  1119.  *                palette descriptor
  1120.  *                palette
  1121.  *   page boundary->
  1122.  *                frame buffer
  1123.  */
  1124. fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
  1125. fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
  1126. &fbi->map_dma);
  1127. if (fbi->map_cpu) {
  1128. fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
  1129. fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
  1130. fbi->fb.fix.smem_start = fbi->screen_dma;
  1131. fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
  1132. palette_mem_size = fbi->palette_size * sizeof(u16);
  1133. DPRINTK("palette_mem_size = 0x%08lxn", (u_long) palette_mem_size);
  1134. fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
  1135. fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
  1136. }
  1137. return fbi->map_cpu ? 0 : -ENOMEM;
  1138. }
  1139. /* Fake monspecs to fill in fbinfo structure */
  1140. static struct fb_monspecs monspecs __initdata = {
  1141. 30000, 70000, 50, 65, 0 /* Generic */
  1142. };
  1143. static struct pxafb_info * __init pxafb_init_fbinfo(void)
  1144. {
  1145. struct pxafb_mach_info *inf;
  1146. struct pxafb_info *fbi;
  1147. fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(struct display) +
  1148.       sizeof(u16) * 16, GFP_KERNEL);
  1149. if (!fbi)
  1150. return NULL;
  1151. memset(fbi, 0, sizeof(struct pxafb_info) + sizeof(struct display));
  1152. fbi->currcon = -1;
  1153. strcpy(fbi->fb.fix.id, PXA_NAME);
  1154. fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
  1155. fbi->fb.fix.type_aux = 0;
  1156. fbi->fb.fix.xpanstep = 0;
  1157. fbi->fb.fix.ypanstep = 0;
  1158. fbi->fb.fix.ywrapstep = 0;
  1159. fbi->fb.fix.accel = FB_ACCEL_NONE;
  1160. fbi->fb.var.nonstd = 0;
  1161. fbi->fb.var.activate = FB_ACTIVATE_NOW;
  1162. fbi->fb.var.height = -1;
  1163. fbi->fb.var.width = -1;
  1164. fbi->fb.var.accel_flags = 0;
  1165. fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
  1166. strcpy(fbi->fb.modename, PXA_NAME);
  1167. strcpy(fbi->fb.fontname, "Acorn8x8");
  1168. fbi->fb.fbops = &pxafb_ops;
  1169. fbi->fb.changevar = NULL;
  1170. fbi->fb.switch_con = pxafb_switch;
  1171. fbi->fb.updatevar = pxafb_updatevar;
  1172. fbi->fb.blank = pxafb_blank;
  1173. fbi->fb.flags = FBINFO_FLAG_DEFAULT;
  1174. fbi->fb.node = -1;
  1175. fbi->fb.monspecs = monspecs;
  1176. fbi->fb.disp = (struct display *)(fbi + 1);
  1177. fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1);
  1178. fbi->rgb[RGB_8] = &rgb_8;
  1179. fbi->rgb[RGB_16] = &def_rgb_16;
  1180. inf = pxafb_get_machine_info(fbi);
  1181. fbi->max_xres = inf->xres;
  1182. fbi->fb.var.xres = inf->xres;
  1183. fbi->fb.var.xres_virtual = inf->xres;
  1184. fbi->max_yres = inf->yres;
  1185. fbi->fb.var.yres = inf->yres;
  1186. fbi->fb.var.yres_virtual = inf->yres;
  1187. fbi->max_bpp = inf->bpp;
  1188. fbi->fb.var.bits_per_pixel = inf->bpp;
  1189. fbi->fb.var.pixclock = inf->pixclock;
  1190. fbi->fb.var.hsync_len = inf->hsync_len;
  1191. fbi->fb.var.left_margin = inf->left_margin;
  1192. fbi->fb.var.right_margin = inf->right_margin;
  1193. fbi->fb.var.vsync_len = inf->vsync_len;
  1194. fbi->fb.var.upper_margin = inf->upper_margin;
  1195. fbi->fb.var.lower_margin = inf->lower_margin;
  1196. fbi->fb.var.sync = inf->sync;
  1197. fbi->fb.var.grayscale = inf->cmap_greyscale;
  1198. fbi->cmap_inverse = inf->cmap_inverse;
  1199. fbi->cmap_static = inf->cmap_static;
  1200. fbi->lccr0 = inf->lccr0;
  1201. fbi->lccr3 = inf->lccr3;
  1202. fbi->state = C_DISABLE;
  1203. fbi->task_state = (u_char)-1;
  1204. fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres *
  1205.   fbi->max_bpp / 8;
  1206. init_waitqueue_head(&fbi->ctrlr_wait);
  1207. INIT_TQUEUE(&fbi->task, pxafb_task, fbi);
  1208. init_MUTEX(&fbi->ctrlr_sem);
  1209. return fbi;
  1210. }
  1211. int __init pxafb_init(void)
  1212. {
  1213. struct pxafb_info *fbi;
  1214. int ret;
  1215. fbi = pxafb_init_fbinfo();
  1216. ret = -ENOMEM;
  1217. if (!fbi)
  1218. goto failed;
  1219. /* Initialize video memory */
  1220. ret = pxafb_map_video_memory(fbi);
  1221. if (ret)
  1222. goto failed;
  1223. ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT,
  1224.   "LCD", fbi);
  1225. if (ret) {
  1226. printk(KERN_ERR "pxafb: failed in request_irq: %dn", ret);
  1227. goto failed;
  1228. }
  1229. pxafb_set_var(&fbi->fb.var, -1, &fbi->fb);
  1230. ret = register_framebuffer(&fbi->fb);
  1231. if (ret < 0)
  1232. goto failed;
  1233. #ifdef CONFIG_PM
  1234. /*
  1235.  * Note that the console registers this as well, but we want to
  1236.  * power down the display prior to sleeping.
  1237.  */
  1238. fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, pxafb_pm_callback);
  1239. if (fbi->pm)
  1240. fbi->pm->data = fbi;
  1241. #endif
  1242. #ifdef CONFIG_CPU_FREQ
  1243. fbi->clockchg.notifier_call = pxafb_clkchg_notifier;
  1244. cpufreq_register_notifier(&fbi->clockchg);
  1245. #endif
  1246. /*
  1247.  * Ok, now enable the LCD controller
  1248.  */
  1249. set_ctrlr_state(fbi, C_ENABLE);
  1250. /* This driver cannot be unloaded at the moment */
  1251. MOD_INC_USE_COUNT;
  1252. return 0;
  1253. failed:
  1254. if (fbi)
  1255. kfree(fbi);
  1256. return ret;
  1257. }
  1258. int __init pxafb_setup(char *options)
  1259. {
  1260. #if 0
  1261. char *this_opt;
  1262. if (!options || !*options)
  1263. return 0;
  1264. for (this_opt = strtok(options, ","); this_opt;
  1265.      this_opt = strtok(NULL, ",")) {
  1266. if (!strncmp(this_opt, "bpp:", 4))
  1267. current_par.max_bpp =
  1268.     simple_strtoul(this_opt + 4, NULL, 0);
  1269. if (!strncmp(this_opt, "lccr0:", 6))
  1270. lcd_shadow.lccr0 =
  1271.     simple_strtoul(this_opt + 6, NULL, 0);
  1272. if (!strncmp(this_opt, "lccr1:", 6)) {
  1273. lcd_shadow.lccr1 =
  1274.     simple_strtoul(this_opt + 6, NULL, 0);
  1275. current_par.max_xres =
  1276.     (lcd_shadow.lccr1 & 0x3ff) + 16;
  1277. }
  1278. if (!strncmp(this_opt, "lccr2:", 6)) {
  1279. lcd_shadow.lccr2 =
  1280.     simple_strtoul(this_opt + 6, NULL, 0);
  1281. current_par.max_yres =
  1282.     (lcd_shadow.
  1283.      lccr0 & LCCR0_SDS) ? ((lcd_shadow.
  1284.     lccr2 & 0x3ff) +
  1285.    1) *
  1286.     2 : ((lcd_shadow.lccr2 & 0x3ff) + 1);
  1287. }
  1288. if (!strncmp(this_opt, "lccr3:", 6))
  1289. lcd_shadow.lccr3 =
  1290.     simple_strtoul(this_opt + 6, NULL, 0);
  1291. }
  1292. #endif
  1293. return 0;
  1294. }