root/drivers/staging/sm750fb/sm750_hw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hw_sm750_map
  2. hw_sm750_inithw
  3. hw_sm750_output_setMode
  4. hw_sm750_crtc_checkMode
  5. hw_sm750_crtc_setMode
  6. hw_sm750_setColReg
  7. hw_sm750le_setBLANK
  8. hw_sm750_setBLANK
  9. hw_sm750_initAccel
  10. hw_sm750le_deWait
  11. hw_sm750_deWait
  12. hw_sm750_pan_display

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/module.h>
   3 #include <linux/kernel.h>
   4 #include <linux/errno.h>
   5 #include <linux/string.h>
   6 #include <linux/mm.h>
   7 #include <linux/slab.h>
   8 #include <linux/delay.h>
   9 #include <linux/fb.h>
  10 #include <linux/ioport.h>
  11 #include <linux/init.h>
  12 #include <linux/pci.h>
  13 #include <linux/vmalloc.h>
  14 #include <linux/pagemap.h>
  15 #include <linux/console.h>
  16 #ifdef CONFIG_MTRR
  17 #include <asm/mtrr.h>
  18 #endif
  19 #include <linux/platform_device.h>
  20 #include <linux/screen_info.h>
  21 #include <linux/sizes.h>
  22 
  23 #include "sm750.h"
  24 #include "ddk750.h"
  25 #include "sm750_accel.h"
  26 
  27 void __iomem *mmio750;
  28 
  29 int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
  30 {
  31         int ret;
  32 
  33         ret = 0;
  34 
  35         sm750_dev->vidreg_start  = pci_resource_start(pdev, 1);
  36         sm750_dev->vidreg_size = SZ_2M;
  37 
  38         pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start);
  39 
  40         /*
  41          * reserve the vidreg space of smi adaptor
  42          * if you do this, you need to add release region code
  43          * in lynxfb_remove, or memory will not be mapped again
  44          * successfully
  45          */
  46         ret = pci_request_region(pdev, 1, "sm750fb");
  47         if (ret) {
  48                 pr_err("Can not request PCI regions.\n");
  49                 goto exit;
  50         }
  51 
  52         /* now map mmio and vidmem */
  53         sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start,
  54                                            sm750_dev->vidreg_size);
  55         if (!sm750_dev->pvReg) {
  56                 pr_err("mmio failed\n");
  57                 ret = -EFAULT;
  58                 goto exit;
  59         } else {
  60                 pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg);
  61         }
  62 
  63         sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1;
  64         sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1;
  65 
  66         mmio750 = sm750_dev->pvReg;
  67         sm750_set_chip_type(sm750_dev->devid, sm750_dev->revid);
  68 
  69         sm750_dev->vidmem_start = pci_resource_start(pdev, 0);
  70         /*
  71          * don't use pdev_resource[x].end - resource[x].start to
  72          * calculate the resource size, it's only the maximum available
  73          * size but not the actual size, using
  74          * @ddk750_get_vm_size function can be safe.
  75          */
  76         sm750_dev->vidmem_size = ddk750_get_vm_size();
  77         pr_info("video memory phyAddr = %lx, size = %u bytes\n",
  78                 sm750_dev->vidmem_start, sm750_dev->vidmem_size);
  79 
  80         /* reserve the vidmem space of smi adaptor */
  81         sm750_dev->pvMem = ioremap_wc(sm750_dev->vidmem_start,
  82                                       sm750_dev->vidmem_size);
  83         if (!sm750_dev->pvMem) {
  84                 pr_err("Map video memory failed\n");
  85                 ret = -EFAULT;
  86                 goto exit;
  87         } else {
  88                 pr_info("video memory vaddr = %p\n", sm750_dev->pvMem);
  89         }
  90 exit:
  91         return ret;
  92 }
  93 
  94 int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
  95 {
  96         struct init_status *parm;
  97 
  98         parm = &sm750_dev->initParm;
  99         if (parm->chip_clk == 0)
 100                 parm->chip_clk = (sm750_get_chip_type() == SM750LE) ?
 101                                                 DEFAULT_SM750LE_CHIP_CLOCK :
 102                                                 DEFAULT_SM750_CHIP_CLOCK;
 103 
 104         if (parm->mem_clk == 0)
 105                 parm->mem_clk = parm->chip_clk;
 106         if (parm->master_clk == 0)
 107                 parm->master_clk = parm->chip_clk / 3;
 108 
 109         ddk750_init_hw((struct initchip_param *)&sm750_dev->initParm);
 110         /* for sm718, open pci burst */
 111         if (sm750_dev->devid == 0x718) {
 112                 poke32(SYSTEM_CTRL,
 113                        peek32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST);
 114         }
 115 
 116         if (sm750_get_chip_type() != SM750LE) {
 117                 unsigned int val;
 118                 /* does user need CRT? */
 119                 if (sm750_dev->nocrt) {
 120                         poke32(MISC_CTRL,
 121                                peek32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF);
 122                         /* shut off dpms */
 123                         val = peek32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
 124                         val |= SYSTEM_CTRL_DPMS_VPHN;
 125                         poke32(SYSTEM_CTRL, val);
 126                 } else {
 127                         poke32(MISC_CTRL,
 128                                peek32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF);
 129                         /* turn on dpms */
 130                         val = peek32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
 131                         val |= SYSTEM_CTRL_DPMS_VPHP;
 132                         poke32(SYSTEM_CTRL, val);
 133                 }
 134 
 135                 val = peek32(PANEL_DISPLAY_CTRL) &
 136                         ~(PANEL_DISPLAY_CTRL_DUAL_DISPLAY |
 137                           PANEL_DISPLAY_CTRL_DOUBLE_PIXEL);
 138                 switch (sm750_dev->pnltype) {
 139                 case sm750_24TFT:
 140                         break;
 141                 case sm750_doubleTFT:
 142                         val |= PANEL_DISPLAY_CTRL_DOUBLE_PIXEL;
 143                         break;
 144                 case sm750_dualTFT:
 145                         val |= PANEL_DISPLAY_CTRL_DUAL_DISPLAY;
 146                         break;
 147                 }
 148                 poke32(PANEL_DISPLAY_CTRL, val);
 149         } else {
 150                 /*
 151                  * for 750LE, no DVI chip initialization
 152                  * makes Monitor no signal
 153                  *
 154                  * Set up GPIO for software I2C to program DVI chip in the
 155                  * Xilinx SP605 board, in order to have video signal.
 156                  */
 157                 sm750_sw_i2c_init(0, 1);
 158 
 159                 /*
 160                  * Customer may NOT use CH7301 DVI chip, which has to be
 161                  * initialized differently.
 162                  */
 163                 if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
 164                         /*
 165                          * The following register values for CH7301 are from
 166                          * Chrontel app note and our experiment.
 167                          */
 168                         pr_info("yes,CH7301 DVI chip found\n");
 169                         sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16);
 170                         sm750_sw_i2c_write_reg(0xec, 0x21, 0x9);
 171                         sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0);
 172                         pr_info("okay,CH7301 DVI chip setup done\n");
 173                 }
 174         }
 175 
 176         /* init 2d engine */
 177         if (!sm750_dev->accel_off)
 178                 hw_sm750_initAccel(sm750_dev);
 179 
 180         return 0;
 181 }
 182 
 183 int hw_sm750_output_setMode(struct lynxfb_output *output,
 184                             struct fb_var_screeninfo *var,
 185                             struct fb_fix_screeninfo *fix)
 186 {
 187         int ret;
 188         enum disp_output disp_set;
 189         int channel;
 190 
 191         ret = 0;
 192         disp_set = 0;
 193         channel = *output->channel;
 194 
 195         if (sm750_get_chip_type() != SM750LE) {
 196                 if (channel == sm750_primary) {
 197                         pr_info("primary channel\n");
 198                         if (output->paths & sm750_panel)
 199                                 disp_set |= do_LCD1_PRI;
 200                         if (output->paths & sm750_crt)
 201                                 disp_set |= do_CRT_PRI;
 202 
 203                 } else {
 204                         pr_info("secondary channel\n");
 205                         if (output->paths & sm750_panel)
 206                                 disp_set |= do_LCD1_SEC;
 207                         if (output->paths & sm750_crt)
 208                                 disp_set |= do_CRT_SEC;
 209                 }
 210                 ddk750_set_logical_disp_out(disp_set);
 211         } else {
 212                 /* just open DISPLAY_CONTROL_750LE register bit 3:0 */
 213                 u32 reg;
 214 
 215                 reg = peek32(DISPLAY_CONTROL_750LE);
 216                 reg |= 0xf;
 217                 poke32(DISPLAY_CONTROL_750LE, reg);
 218         }
 219 
 220         pr_info("ddk setlogicdispout done\n");
 221         return ret;
 222 }
 223 
 224 int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc,
 225                             struct fb_var_screeninfo *var)
 226 {
 227         struct sm750_dev *sm750_dev;
 228         struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc);
 229 
 230         sm750_dev = par->dev;
 231 
 232         switch (var->bits_per_pixel) {
 233         case 8:
 234         case 16:
 235                 break;
 236         case 32:
 237                 if (sm750_dev->revid == SM750LE_REVISION_ID) {
 238                         pr_debug("750le do not support 32bpp\n");
 239                         return -EINVAL;
 240                 }
 241                 break;
 242         default:
 243                 return -EINVAL;
 244         }
 245 
 246         return 0;
 247 }
 248 
 249 /* set the controller's mode for @crtc charged with @var and @fix parameters */
 250 int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
 251                           struct fb_var_screeninfo *var,
 252                           struct fb_fix_screeninfo *fix)
 253 {
 254         int ret, fmt;
 255         u32 reg;
 256         struct mode_parameter modparm;
 257         enum clock_type clock;
 258         struct sm750_dev *sm750_dev;
 259         struct lynxfb_par *par;
 260 
 261         ret = 0;
 262         par = container_of(crtc, struct lynxfb_par, crtc);
 263         sm750_dev = par->dev;
 264 
 265         if (!sm750_dev->accel_off) {
 266                 /* set 2d engine pixel format according to mode bpp */
 267                 switch (var->bits_per_pixel) {
 268                 case 8:
 269                         fmt = 0;
 270                         break;
 271                 case 16:
 272                         fmt = 1;
 273                         break;
 274                 case 32:
 275                 default:
 276                         fmt = 2;
 277                         break;
 278                 }
 279                 sm750_hw_set2dformat(&sm750_dev->accel, fmt);
 280         }
 281 
 282         /* set timing */
 283         modparm.pixel_clock = ps_to_hz(var->pixclock);
 284         modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT)
 285                                          ? POS : NEG;
 286         modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT)
 287                                            ? POS : NEG;
 288         modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT)
 289                                        ? POS : NEG;
 290         modparm.horizontal_display_end = var->xres;
 291         modparm.horizontal_sync_width = var->hsync_len;
 292         modparm.horizontal_sync_start = var->xres + var->right_margin;
 293         modparm.horizontal_total = var->xres + var->left_margin +
 294                                    var->right_margin + var->hsync_len;
 295         modparm.vertical_display_end = var->yres;
 296         modparm.vertical_sync_height = var->vsync_len;
 297         modparm.vertical_sync_start = var->yres + var->lower_margin;
 298         modparm.vertical_total = var->yres + var->upper_margin +
 299                                  var->lower_margin + var->vsync_len;
 300 
 301         /* choose pll */
 302         if (crtc->channel != sm750_secondary)
 303                 clock = PRIMARY_PLL;
 304         else
 305                 clock = SECONDARY_PLL;
 306 
 307         pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
 308         ret = ddk750_setModeTiming(&modparm, clock);
 309         if (ret) {
 310                 pr_err("Set mode timing failed\n");
 311                 goto exit;
 312         }
 313 
 314         if (crtc->channel != sm750_secondary) {
 315                 /* set pitch, offset, width, start address, etc... */
 316                 poke32(PANEL_FB_ADDRESS,
 317                        crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK);
 318 
 319                 reg = var->xres * (var->bits_per_pixel >> 3);
 320                 /*
 321                  * crtc->channel is not equal to par->index on numeric,
 322                  * be aware of that
 323                  */
 324                 reg = ALIGN(reg, crtc->line_pad);
 325                 reg = (reg << PANEL_FB_WIDTH_WIDTH_SHIFT) &
 326                        PANEL_FB_WIDTH_WIDTH_MASK;
 327                 reg |= (fix->line_length & PANEL_FB_WIDTH_OFFSET_MASK);
 328                 poke32(PANEL_FB_WIDTH, reg);
 329 
 330                 reg = ((var->xres - 1) << PANEL_WINDOW_WIDTH_WIDTH_SHIFT) &
 331                        PANEL_WINDOW_WIDTH_WIDTH_MASK;
 332                 reg |= (var->xoffset & PANEL_WINDOW_WIDTH_X_MASK);
 333                 poke32(PANEL_WINDOW_WIDTH, reg);
 334 
 335                 reg = (var->yres_virtual - 1) <<
 336                       PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT;
 337                 reg &= PANEL_WINDOW_HEIGHT_HEIGHT_MASK;
 338                 reg |= (var->yoffset & PANEL_WINDOW_HEIGHT_Y_MASK);
 339                 poke32(PANEL_WINDOW_HEIGHT, reg);
 340 
 341                 poke32(PANEL_PLANE_TL, 0);
 342 
 343                 reg = ((var->yres - 1) << PANEL_PLANE_BR_BOTTOM_SHIFT) &
 344                        PANEL_PLANE_BR_BOTTOM_MASK;
 345                 reg |= ((var->xres - 1) & PANEL_PLANE_BR_RIGHT_MASK);
 346                 poke32(PANEL_PLANE_BR, reg);
 347 
 348                 /* set pixel format */
 349                 reg = peek32(PANEL_DISPLAY_CTRL);
 350                 poke32(PANEL_DISPLAY_CTRL, reg | (var->bits_per_pixel >> 4));
 351         } else {
 352                 /* not implemented now */
 353                 poke32(CRT_FB_ADDRESS, crtc->oScreen);
 354                 reg = var->xres * (var->bits_per_pixel >> 3);
 355                 /*
 356                  * crtc->channel is not equal to par->index on numeric,
 357                  * be aware of that
 358                  */
 359                 reg = ALIGN(reg, crtc->line_pad) << CRT_FB_WIDTH_WIDTH_SHIFT;
 360                 reg &= CRT_FB_WIDTH_WIDTH_MASK;
 361                 reg |= (fix->line_length & CRT_FB_WIDTH_OFFSET_MASK);
 362                 poke32(CRT_FB_WIDTH, reg);
 363 
 364                 /* SET PIXEL FORMAT */
 365                 reg = peek32(CRT_DISPLAY_CTRL);
 366                 reg |= ((var->bits_per_pixel >> 4) &
 367                         CRT_DISPLAY_CTRL_FORMAT_MASK);
 368                 poke32(CRT_DISPLAY_CTRL, reg);
 369         }
 370 
 371 exit:
 372         return ret;
 373 }
 374 
 375 int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
 376                        ushort red, ushort green, ushort blue)
 377 {
 378         static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
 379 
 380         poke32(add[crtc->channel] + index * 4,
 381                (red << 16) | (green << 8) | blue);
 382         return 0;
 383 }
 384 
 385 int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
 386 {
 387         int dpms, crtdb;
 388 
 389         switch (blank) {
 390         case FB_BLANK_UNBLANK:
 391                 dpms = CRT_DISPLAY_CTRL_DPMS_0;
 392                 crtdb = 0;
 393                 break;
 394         case FB_BLANK_NORMAL:
 395                 dpms = CRT_DISPLAY_CTRL_DPMS_0;
 396                 crtdb = CRT_DISPLAY_CTRL_BLANK;
 397                 break;
 398         case FB_BLANK_VSYNC_SUSPEND:
 399                 dpms = CRT_DISPLAY_CTRL_DPMS_2;
 400                 crtdb = CRT_DISPLAY_CTRL_BLANK;
 401                 break;
 402         case FB_BLANK_HSYNC_SUSPEND:
 403                 dpms = CRT_DISPLAY_CTRL_DPMS_1;
 404                 crtdb = CRT_DISPLAY_CTRL_BLANK;
 405                 break;
 406         case FB_BLANK_POWERDOWN:
 407                 dpms = CRT_DISPLAY_CTRL_DPMS_3;
 408                 crtdb = CRT_DISPLAY_CTRL_BLANK;
 409                 break;
 410         default:
 411                 return -EINVAL;
 412         }
 413 
 414         if (output->paths & sm750_crt) {
 415                 unsigned int val;
 416 
 417                 val = peek32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_DPMS_MASK;
 418                 poke32(CRT_DISPLAY_CTRL, val | dpms);
 419 
 420                 val = peek32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK;
 421                 poke32(CRT_DISPLAY_CTRL, val | crtdb);
 422         }
 423         return 0;
 424 }
 425 
 426 int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
 427 {
 428         unsigned int dpms, pps, crtdb;
 429 
 430         dpms = 0;
 431         pps = 0;
 432         crtdb = 0;
 433 
 434         switch (blank) {
 435         case FB_BLANK_UNBLANK:
 436                 pr_debug("flag = FB_BLANK_UNBLANK\n");
 437                 dpms = SYSTEM_CTRL_DPMS_VPHP;
 438                 pps = PANEL_DISPLAY_CTRL_DATA;
 439                 break;
 440         case FB_BLANK_NORMAL:
 441                 pr_debug("flag = FB_BLANK_NORMAL\n");
 442                 dpms = SYSTEM_CTRL_DPMS_VPHP;
 443                 crtdb = CRT_DISPLAY_CTRL_BLANK;
 444                 break;
 445         case FB_BLANK_VSYNC_SUSPEND:
 446                 dpms = SYSTEM_CTRL_DPMS_VNHP;
 447                 crtdb = CRT_DISPLAY_CTRL_BLANK;
 448                 break;
 449         case FB_BLANK_HSYNC_SUSPEND:
 450                 dpms = SYSTEM_CTRL_DPMS_VPHN;
 451                 crtdb = CRT_DISPLAY_CTRL_BLANK;
 452                 break;
 453         case FB_BLANK_POWERDOWN:
 454                 dpms = SYSTEM_CTRL_DPMS_VNHN;
 455                 crtdb = CRT_DISPLAY_CTRL_BLANK;
 456                 break;
 457         }
 458 
 459         if (output->paths & sm750_crt) {
 460                 unsigned int val = peek32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
 461 
 462                 poke32(SYSTEM_CTRL, val | dpms);
 463 
 464                 val = peek32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK;
 465                 poke32(CRT_DISPLAY_CTRL, val | crtdb);
 466         }
 467 
 468         if (output->paths & sm750_panel) {
 469                 unsigned int val = peek32(PANEL_DISPLAY_CTRL);
 470 
 471                 val &= ~PANEL_DISPLAY_CTRL_DATA;
 472                 val |= pps;
 473                 poke32(PANEL_DISPLAY_CTRL, val);
 474         }
 475 
 476         return 0;
 477 }
 478 
 479 void hw_sm750_initAccel(struct sm750_dev *sm750_dev)
 480 {
 481         u32 reg;
 482 
 483         sm750_enable_2d_engine(1);
 484 
 485         if (sm750_get_chip_type() == SM750LE) {
 486                 reg = peek32(DE_STATE1);
 487                 reg |= DE_STATE1_DE_ABORT;
 488                 poke32(DE_STATE1, reg);
 489 
 490                 reg = peek32(DE_STATE1);
 491                 reg &= ~DE_STATE1_DE_ABORT;
 492                 poke32(DE_STATE1, reg);
 493 
 494         } else {
 495                 /* engine reset */
 496                 reg = peek32(SYSTEM_CTRL);
 497                 reg |= SYSTEM_CTRL_DE_ABORT;
 498                 poke32(SYSTEM_CTRL, reg);
 499 
 500                 reg = peek32(SYSTEM_CTRL);
 501                 reg &= ~SYSTEM_CTRL_DE_ABORT;
 502                 poke32(SYSTEM_CTRL, reg);
 503         }
 504 
 505         /* call 2d init */
 506         sm750_dev->accel.de_init(&sm750_dev->accel);
 507 }
 508 
 509 int hw_sm750le_deWait(void)
 510 {
 511         int i = 0x10000000;
 512         unsigned int mask = DE_STATE2_DE_STATUS_BUSY | DE_STATE2_DE_FIFO_EMPTY |
 513                 DE_STATE2_DE_MEM_FIFO_EMPTY;
 514 
 515         while (i--) {
 516                 unsigned int val = peek32(DE_STATE2);
 517 
 518                 if ((val & mask) ==
 519                     (DE_STATE2_DE_FIFO_EMPTY | DE_STATE2_DE_MEM_FIFO_EMPTY))
 520                         return 0;
 521         }
 522         /* timeout error */
 523         return -1;
 524 }
 525 
 526 int hw_sm750_deWait(void)
 527 {
 528         int i = 0x10000000;
 529         unsigned int mask = SYSTEM_CTRL_DE_STATUS_BUSY |
 530                 SYSTEM_CTRL_DE_FIFO_EMPTY |
 531                 SYSTEM_CTRL_DE_MEM_FIFO_EMPTY;
 532 
 533         while (i--) {
 534                 unsigned int val = peek32(SYSTEM_CTRL);
 535 
 536                 if ((val & mask) ==
 537                     (SYSTEM_CTRL_DE_FIFO_EMPTY | SYSTEM_CTRL_DE_MEM_FIFO_EMPTY))
 538                         return 0;
 539         }
 540         /* timeout error */
 541         return -1;
 542 }
 543 
 544 int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
 545                          const struct fb_var_screeninfo *var,
 546                          const struct fb_info *info)
 547 {
 548         u32 total;
 549         /* check params */
 550         if ((var->xoffset + var->xres > var->xres_virtual) ||
 551             (var->yoffset + var->yres > var->yres_virtual)) {
 552                 return -EINVAL;
 553         }
 554 
 555         total = var->yoffset * info->fix.line_length +
 556                 ((var->xoffset * var->bits_per_pixel) >> 3);
 557         total += crtc->oScreen;
 558         if (crtc->channel == sm750_primary) {
 559                 poke32(PANEL_FB_ADDRESS,
 560                        peek32(PANEL_FB_ADDRESS) |
 561                        (total & PANEL_FB_ADDRESS_ADDRESS_MASK));
 562         } else {
 563                 poke32(CRT_FB_ADDRESS,
 564                        peek32(CRT_FB_ADDRESS) |
 565                        (total & CRT_FB_ADDRESS_ADDRESS_MASK));
 566         }
 567         return 0;
 568 }

/* [<][>][^][v][top][bottom][index][help] */