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