Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.29-rc2 790 lines 23 kB view raw
1/* 2 * Frame buffer driver for the Carmine GPU. 3 * 4 * The driver configures the GPU as follows 5 * - FB0 is display 0 with unique memory area 6 * - FB1 is display 1 with unique memory area 7 * - both display use 32 bit colors 8 */ 9#include <linux/delay.h> 10#include <linux/errno.h> 11#include <linux/fb.h> 12#include <linux/interrupt.h> 13#include <linux/pci.h> 14 15#include "carminefb.h" 16#include "carminefb_regs.h" 17 18#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) 19#error "The endianness of the target host has not been defined." 20#endif 21 22/* 23 * The initial video mode can be supplied via two different ways: 24 * - as a string that is passed to fb_find_mode() (module option fb_mode_str) 25 * - as an integer that picks the video mode from carmine_modedb[] (module 26 * option fb_mode) 27 * 28 * If nothing is used than the initial video mode will be the 29 * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[]. 30 */ 31#define CARMINEFB_DEFAULT_VIDEO_MODE 1 32 33static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; 34module_param(fb_mode, uint, 444); 35MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); 36 37static char *fb_mode_str; 38module_param(fb_mode_str, charp, 444); 39MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); 40 41/* 42 * Carminefb displays: 43 * 0b000 None 44 * 0b001 Display 0 45 * 0b010 Display 1 46 */ 47static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; 48module_param(fb_displays, int, 444); 49MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); 50 51struct carmine_hw { 52 void __iomem *v_regs; 53 void __iomem *screen_mem; 54 struct fb_info *fb[MAX_DISPLAY]; 55}; 56 57struct carmine_resolution { 58 u32 htp; 59 u32 hsp; 60 u32 hsw; 61 u32 hdp; 62 u32 vtr; 63 u32 vsp; 64 u32 vsw; 65 u32 vdp; 66 u32 disp_mode; 67}; 68 69struct carmine_fb { 70 void __iomem *display_reg; 71 void __iomem *screen_base; 72 u32 smem_offset; 73 u32 cur_mode; 74 u32 new_mode; 75 struct carmine_resolution *res; 76 u32 pseudo_palette[16]; 77}; 78 79static struct fb_fix_screeninfo carminefb_fix __devinitdata = { 80 .id = "Carmine", 81 .type = FB_TYPE_PACKED_PIXELS, 82 .visual = FB_VISUAL_TRUECOLOR, 83 .accel = FB_ACCEL_NONE, 84}; 85 86static const struct fb_videomode carmine_modedb[] = { 87 { 88 .name = "640x480", 89 .xres = 640, 90 .yres = 480, 91 }, { 92 .name = "800x600", 93 .xres = 800, 94 .yres = 600, 95 }, 96}; 97 98static struct carmine_resolution car_modes[] = { 99 { 100 /* 640x480 */ 101 .htp = 800, 102 .hsp = 672, 103 .hsw = 96, 104 .hdp = 640, 105 .vtr = 525, 106 .vsp = 490, 107 .vsw = 2, 108 .vdp = 480, 109 .disp_mode = 0x1400, 110 }, 111 { 112 /* 800x600 */ 113 .htp = 1060, 114 .hsp = 864, 115 .hsw = 72, 116 .hdp = 800, 117 .vtr = 628, 118 .vsp = 601, 119 .vsw = 2, 120 .vdp = 600, 121 .disp_mode = 0x0d00, 122 } 123}; 124 125static int carmine_find_mode(const struct fb_var_screeninfo *var) 126{ 127 int i; 128 129 for (i = 0; i < ARRAY_SIZE(car_modes); i++) 130 if (car_modes[i].hdp == var->xres && 131 car_modes[i].vdp == var->yres) 132 return i; 133 return -EINVAL; 134} 135 136static void c_set_disp_reg(const struct carmine_fb *par, 137 u32 offset, u32 val) 138{ 139 writel(val, par->display_reg + offset); 140} 141 142static u32 c_get_disp_reg(const struct carmine_fb *par, 143 u32 offset) 144{ 145 return readl(par->display_reg + offset); 146} 147 148static void c_set_hw_reg(const struct carmine_hw *hw, 149 u32 offset, u32 val) 150{ 151 writel(val, hw->v_regs + offset); 152} 153 154static u32 c_get_hw_reg(const struct carmine_hw *hw, 155 u32 offset) 156{ 157 return readl(hw->v_regs + offset); 158} 159 160static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green, 161 unsigned blue, unsigned transp, struct fb_info *info) 162{ 163 if (regno >= 16) 164 return 1; 165 166 red >>= 8; 167 green >>= 8; 168 blue >>= 8; 169 transp >>= 8; 170 171 ((__be32 *)info->pseudo_palette)[regno] = cpu_to_be32(transp << 24 | 172 red << 0 | green << 8 | blue << 16); 173 return 0; 174} 175 176static int carmine_check_var(struct fb_var_screeninfo *var, 177 struct fb_info *info) 178{ 179 int ret; 180 181 ret = carmine_find_mode(var); 182 if (ret < 0) 183 return ret; 184 185 if (var->grayscale || var->rotate || var->nonstd) 186 return -EINVAL; 187 188 var->xres_virtual = var->xres; 189 var->yres_virtual = var->yres; 190 191 var->bits_per_pixel = 32; 192 193#ifdef __BIG_ENDIAN 194 var->transp.offset = 24; 195 var->red.offset = 0; 196 var->green.offset = 8; 197 var->blue.offset = 16; 198#else 199 var->transp.offset = 24; 200 var->red.offset = 16; 201 var->green.offset = 8; 202 var->blue.offset = 0; 203#endif 204 205 var->red.length = 8; 206 var->green.length = 8; 207 var->blue.length = 8; 208 var->transp.length = 8; 209 210 var->red.msb_right = 0; 211 var->green.msb_right = 0; 212 var->blue.msb_right = 0; 213 var->transp.msb_right = 0; 214 return 0; 215} 216 217static void carmine_init_display_param(struct carmine_fb *par) 218{ 219 u32 width; 220 u32 height; 221 u32 param; 222 u32 window_size; 223 u32 soffset = par->smem_offset; 224 225 c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0); 226 c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0); 227 c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE, 228 CARMINE_CURSOR0_PRIORITY_MASK | 229 CARMINE_CURSOR1_PRIORITY_MASK | 230 CARMINE_CURSOR_CUTZ_MASK); 231 232 /* Set default cursor position */ 233 c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0); 234 c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0); 235 236 /* Set default display mode */ 237 c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE | 238 CARMINE_EXT_CMODE_DIRECT24_RGBA); 239 c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE, 240 CARMINE_EXT_CMODE_DIRECT24_RGBA); 241 c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE | 242 CARMINE_EXT_CMODE_DIRECT24_RGBA); 243 c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE | 244 CARMINE_EXT_CMODE_DIRECT24_RGBA); 245 c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE | 246 CARMINE_EXT_CMODE_DIRECT24_RGBA); 247 c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE | 248 CARMINE_EXT_CMODE_DIRECT24_RGBA); 249 c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE | 250 CARMINE_EXT_CMODE_DIRECT24_RGBA); 251 c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE | 252 CARMINE_EXT_CMODE_DIRECT24_RGBA); 253 254 /* Set default frame size to layer mode register */ 255 width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT; 256 width = width << CARMINE_DISP_WIDTH_SHIFT; 257 258 height = par->res->vdp - 1; 259 param = width | height; 260 261 c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param); 262 c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width); 263 c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param); 264 c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param); 265 c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param); 266 c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param); 267 c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param); 268 c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param); 269 270 /* Set default pos and size */ 271 window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT; 272 window_size |= par->res->hdp; 273 274 c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0); 275 c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size); 276 c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0); 277 c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size); 278 c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0); 279 c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size); 280 c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0); 281 c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size); 282 c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0); 283 c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size); 284 c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0); 285 c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size); 286 c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0); 287 c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size); 288 c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0); 289 c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size); 290 291 /* Set default origin address */ 292 c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset); 293 c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset); 294 c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset); 295 c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset); 296 c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset); 297 c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset); 298 c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset); 299 c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset); 300 301 /* Set default display address */ 302 c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset); 303 c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset); 304 c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset); 305 c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset); 306 c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset); 307 c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset); 308 c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset); 309 310 /* Set default display position */ 311 c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0); 312 c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0); 313 c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0); 314 c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0); 315 c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0); 316 c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0); 317 c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0); 318 319 /* Set default blend mode */ 320 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0); 321 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0); 322 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0); 323 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0); 324 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0); 325 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0); 326 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0); 327 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0); 328 329 /* default transparency mode */ 330 c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0); 331 c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0); 332 c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0); 333 c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0); 334 c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0); 335 c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0); 336 c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0); 337 c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0); 338 339 /* Set default read skip parameter */ 340 c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0); 341 c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0); 342 c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0); 343 c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0); 344 c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0); 345 c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0); 346 c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0); 347 348 c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0); 349 c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0); 350 c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0); 351 c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0); 352 c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0); 353 c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0); 354 c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0); 355 356 c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0); 357 c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0); 358 c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0); 359 c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0); 360 c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0); 361 c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0); 362 c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0); 363} 364 365static void set_display_parameters(struct carmine_fb *par) 366{ 367 u32 mode; 368 u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw; 369 370 /* 371 * display timing. Parameters are decreased by one because hardware 372 * spec is 0 to (n - 1) 373 * */ 374 hdp = par->res->hdp - 1; 375 vdp = par->res->vdp - 1; 376 htp = par->res->htp - 1; 377 hsp = par->res->hsp - 1; 378 hsw = par->res->hsw - 1; 379 vtr = par->res->vtr - 1; 380 vsp = par->res->vsp - 1; 381 vsw = par->res->vsw - 1; 382 383 c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL, 384 htp << CARMINE_DISP_HTP_SHIFT); 385 c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD, 386 (hdp << CARMINE_DISP_HDB_SHIFT) | hdp); 387 c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS, 388 (vsw << CARMINE_DISP_VSW_SHIFT) | 389 (hsw << CARMINE_DISP_HSW_SHIFT) | 390 (hsp)); 391 c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL, 392 vtr << CARMINE_DISP_VTR_SHIFT); 393 c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS, 394 (vdp << CARMINE_DISP_VDP_SHIFT) | vsp); 395 396 /* clock */ 397 mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1); 398 mode = (mode & ~CARMINE_DISP_DCM_MASK) | 399 (par->res->disp_mode & CARMINE_DISP_DCM_MASK); 400 /* enable video output and layer 0 */ 401 mode |= CARMINE_DEN | CARMINE_L0E; 402 c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode); 403} 404 405static int carmine_set_par(struct fb_info *info) 406{ 407 struct carmine_fb *par = info->par; 408 int ret; 409 410 ret = carmine_find_mode(&info->var); 411 if (ret < 0) 412 return ret; 413 414 par->new_mode = ret; 415 if (par->cur_mode != par->new_mode) { 416 417 par->cur_mode = par->new_mode; 418 par->res = &car_modes[par->new_mode]; 419 420 carmine_init_display_param(par); 421 set_display_parameters(par); 422 } 423 424 info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8; 425 return 0; 426} 427 428static int init_hardware(struct carmine_hw *hw) 429{ 430 u32 flags; 431 u32 loops; 432 u32 ret; 433 434 /* Initalize Carmine */ 435 /* Sets internal clock */ 436 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 437 CARMINE_DFLT_IP_CLOCK_ENABLE); 438 439 /* Video signal output is turned off */ 440 c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0); 441 c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0); 442 443 /* Software reset */ 444 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1); 445 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0); 446 447 /* I/O mode settings */ 448 flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 | 449 CARMINE_DFLT_IP_DCTL_IO_CONT0; 450 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0, 451 flags); 452 453 /* DRAM initial sequence */ 454 flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD; 455 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, 456 flags); 457 458 flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 | 459 CARMINE_DFLT_IP_DCTL_EMODE; 460 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE, 461 flags); 462 463 flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 | 464 CARMINE_DFLT_IP_DCTL_SET_TIME2; 465 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2, 466 flags); 467 468 flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 | 469 CARMINE_DFLT_IP_DCTL_FIFO_DEPTH; 470 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags); 471 472 flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1; 473 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1, 474 flags); 475 476 flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 | 477 CARMINE_DFLT_IP_DCTL_STATES; 478 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES, 479 flags); 480 481 /* Executes DLL reset */ 482 if (CARMINE_DCTL_DLL_RESET) { 483 for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) { 484 485 ret = c_get_hw_reg(hw, CARMINE_DCTL_REG + 486 CARMINE_DCTL_REG_RSV0_STATES); 487 ret &= CARMINE_DCTL_REG_STATES_MASK; 488 if (!ret) 489 break; 490 491 mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL); 492 } 493 494 if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) { 495 printk(KERN_ERR "DRAM init failed\n"); 496 return -EIO; 497 } 498 } 499 500 flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 | 501 CARMINE_DFLT_IP_DCTL_ADD; 502 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags); 503 504 flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 | 505 CARMINE_DFLT_IP_DCTL_STATES_AFT_RST; 506 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES, 507 flags); 508 509 /* Initialize the write back register */ 510 c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM, 511 CARMINE_WB_REG_WBM_DEFAULT); 512 513 /* Initialize the Kottos registers */ 514 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0); 515 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0); 516 517 /* Set DC offsets */ 518 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0); 519 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0); 520 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0); 521 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0); 522 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0); 523 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0); 524 return 0; 525} 526 527static struct fb_ops carminefb_ops = { 528 .owner = THIS_MODULE, 529 .fb_fillrect = cfb_fillrect, 530 .fb_copyarea = cfb_copyarea, 531 .fb_imageblit = cfb_imageblit, 532 533 .fb_check_var = carmine_check_var, 534 .fb_set_par = carmine_set_par, 535 .fb_setcolreg = carmine_setcolreg, 536}; 537 538static int __devinit alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base, 539 int smem_offset, struct device *device, struct fb_info **rinfo) 540{ 541 int ret; 542 struct fb_info *info; 543 struct carmine_fb *par; 544 545 info = framebuffer_alloc(sizeof *par, device); 546 if (!info) 547 return -ENOMEM; 548 549 par = info->par; 550 par->display_reg = regs; 551 par->smem_offset = smem_offset; 552 553 info->screen_base = smem_base + smem_offset; 554 info->screen_size = CARMINE_DISPLAY_MEM; 555 info->fbops = &carminefb_ops; 556 557 info->fix = carminefb_fix; 558 info->pseudo_palette = par->pseudo_palette; 559 info->flags = FBINFO_DEFAULT; 560 561 ret = fb_alloc_cmap(&info->cmap, 256, 1); 562 if (ret < 0) 563 goto err_free_fb; 564 565 if (fb_mode > ARRAY_SIZE(carmine_modedb)) 566 fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; 567 568 par->cur_mode = par->new_mode = ~0; 569 570 ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb, 571 ARRAY_SIZE(carmine_modedb), 572 &carmine_modedb[fb_mode], 32); 573 if (!ret || ret == 4) { 574 ret = -EINVAL; 575 goto err_dealloc_cmap; 576 } 577 578 fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb), 579 &info->modelist); 580 581 ret = register_framebuffer(info); 582 if (ret < 0) 583 goto err_dealloc_cmap; 584 585 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, 586 info->fix.id); 587 588 *rinfo = info; 589 return 0; 590 591err_dealloc_cmap: 592 fb_dealloc_cmap(&info->cmap); 593err_free_fb: 594 framebuffer_release(info); 595 return ret; 596} 597 598static void cleanup_fb_device(struct fb_info *info) 599{ 600 if (info) { 601 unregister_framebuffer(info); 602 fb_dealloc_cmap(&info->cmap); 603 framebuffer_release(info); 604 } 605} 606 607static int __devinit carminefb_probe(struct pci_dev *dev, 608 const struct pci_device_id *ent) 609{ 610 struct carmine_hw *hw; 611 struct device *device = &dev->dev; 612 struct fb_info *info; 613 int ret; 614 615 ret = pci_enable_device(dev); 616 if (ret) 617 return ret; 618 619 ret = -ENOMEM; 620 hw = kzalloc(sizeof *hw, GFP_KERNEL); 621 if (!hw) 622 goto err_enable_pci; 623 624 carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR); 625 carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR); 626 627 if (!request_mem_region(carminefb_fix.mmio_start, 628 carminefb_fix.mmio_len, 629 "carminefb regbase")) { 630 printk(KERN_ERR "carminefb: Can't reserve regbase.\n"); 631 ret = -EBUSY; 632 goto err_free_hw; 633 } 634 hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start, 635 carminefb_fix.mmio_len); 636 if (!hw->v_regs) { 637 printk(KERN_ERR "carminefb: Can't remap %s register.\n", 638 carminefb_fix.id); 639 goto err_free_reg_mmio; 640 } 641 642 carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR); 643 carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR); 644 645 /* The memory area tends to be very large (256 MiB). Remap only what 646 * is required for that largest resolution to avoid remaps at run 647 * time 648 */ 649 if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM) 650 carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM; 651 652 else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) { 653 printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d " 654 "are required.", carminefb_fix.smem_len, 655 CARMINE_TOTAL_DIPLAY_MEM); 656 goto err_free_reg_mmio; 657 } 658 659 if (!request_mem_region(carminefb_fix.smem_start, 660 carminefb_fix.smem_len, "carminefb smem")) { 661 printk(KERN_ERR "carminefb: Can't reserve smem.\n"); 662 goto err_unmap_vregs; 663 } 664 665 hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start, 666 carminefb_fix.smem_len); 667 if (!hw->screen_mem) { 668 printk(KERN_ERR "carmine: Can't ioremap smem area.\n"); 669 release_mem_region(carminefb_fix.smem_start, 670 carminefb_fix.smem_len); 671 goto err_reg_smem; 672 } 673 674 ret = init_hardware(hw); 675 if (ret) 676 goto err_unmap_screen; 677 678 info = NULL; 679 if (fb_displays & CARMINE_USE_DISPLAY0) { 680 ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG, 681 hw->screen_mem, CARMINE_DISPLAY_MEM * 0, 682 device, &info); 683 if (ret) 684 goto err_deinit_hw; 685 } 686 687 hw->fb[0] = info; 688 689 info = NULL; 690 if (fb_displays & CARMINE_USE_DISPLAY1) { 691 ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG, 692 hw->screen_mem, CARMINE_DISPLAY_MEM * 1, 693 device, &info); 694 if (ret) 695 goto err_cleanup_fb0; 696 } 697 698 hw->fb[1] = info; 699 info = NULL; 700 701 pci_set_drvdata(dev, hw); 702 return 0; 703 704err_cleanup_fb0: 705 cleanup_fb_device(hw->fb[0]); 706err_deinit_hw: 707 /* disable clock, etc */ 708 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0); 709err_unmap_screen: 710 iounmap(hw->screen_mem); 711err_reg_smem: 712 release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len); 713err_unmap_vregs: 714 iounmap(hw->v_regs); 715err_free_reg_mmio: 716 release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len); 717err_free_hw: 718 kfree(hw); 719err_enable_pci: 720 pci_disable_device(dev); 721 return ret; 722} 723 724static void __devexit carminefb_remove(struct pci_dev *dev) 725{ 726 struct carmine_hw *hw = pci_get_drvdata(dev); 727 struct fb_fix_screeninfo fix; 728 int i; 729 730 /* in case we use only fb1 and not fb1 */ 731 if (hw->fb[0]) 732 fix = hw->fb[0]->fix; 733 else 734 fix = hw->fb[1]->fix; 735 736 /* deactivate display(s) and switch clocks */ 737 c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0); 738 c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0); 739 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0); 740 741 for (i = 0; i < MAX_DISPLAY; i++) 742 cleanup_fb_device(hw->fb[i]); 743 744 iounmap(hw->screen_mem); 745 release_mem_region(fix.smem_start, fix.smem_len); 746 iounmap(hw->v_regs); 747 release_mem_region(fix.mmio_start, fix.mmio_len); 748 749 pci_set_drvdata(dev, NULL); 750 pci_disable_device(dev); 751 kfree(hw); 752} 753 754#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf 755static struct pci_device_id carmine_devices[] __devinitdata = { 756{ 757 PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)}, 758 {0, 0, 0, 0, 0, 0, 0} 759}; 760 761MODULE_DEVICE_TABLE(pci, carmine_devices); 762 763static struct pci_driver carmine_pci_driver = { 764 .name = "carminefb", 765 .id_table = carmine_devices, 766 .probe = carminefb_probe, 767 .remove = __devexit_p(carminefb_remove), 768}; 769 770static int __init carminefb_init(void) 771{ 772 if (!(fb_displays & 773 (CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) { 774 printk(KERN_ERR "If you disable both displays than you don't " 775 "need the driver at all\n"); 776 return -EINVAL; 777 } 778 return pci_register_driver(&carmine_pci_driver); 779} 780module_init(carminefb_init); 781 782static void __exit carminefb_cleanup(void) 783{ 784 pci_unregister_driver(&carmine_pci_driver); 785} 786module_exit(carminefb_cleanup); 787 788MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>"); 789MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices"); 790MODULE_LICENSE("GPL v2");