Rev 1179 | Rev 1246 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1179 | Rev 1221 | ||
---|---|---|---|
Line 38... | Line 38... | ||
38 | //MODULE_DESCRIPTION("DRM KMS helper"); |
38 | //MODULE_DESCRIPTION("DRM KMS helper"); |
39 | //MODULE_LICENSE("GPL and additional rights"); |
39 | //MODULE_LICENSE("GPL and additional rights"); |
Line 40... | Line 40... | ||
40 | 40 | ||
Line -... | Line 41... | ||
- | 41 | static LIST_HEAD(kernel_fb_helper_list); |
|
- | 42 | ||
- | 43 | int drm_fb_helper_add_connector(struct drm_connector *connector) |
|
- | 44 | { |
|
- | 45 | connector->fb_helper_private = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); |
|
- | 46 | if (!connector->fb_helper_private) |
|
- | 47 | return -ENOMEM; |
|
- | 48 | ||
- | 49 | return 0; |
|
- | 50 | } |
|
41 | static LIST_HEAD(kernel_fb_helper_list); |
51 | EXPORT_SYMBOL(drm_fb_helper_add_connector); |
42 | 52 | ||
43 | bool drm_fb_helper_force_kernel_mode(void) |
53 | bool drm_fb_helper_force_kernel_mode(void) |
44 | { |
54 | { |
45 | int i = 0; |
55 | int i = 0; |
Line 228... | Line 238... | ||
228 | drm_fb_helper_crtc_free(helper); |
238 | drm_fb_helper_crtc_free(helper); |
229 | return -ENOMEM; |
239 | return -ENOMEM; |
230 | } |
240 | } |
231 | EXPORT_SYMBOL(drm_fb_helper_init_crtc_count); |
241 | EXPORT_SYMBOL(drm_fb_helper_init_crtc_count); |
Line -... | Line 242... | ||
- | 242 | ||
- | 243 | static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green, |
|
- | 244 | u16 blue, u16 regno, struct fb_info *info) |
|
- | 245 | { |
|
- | 246 | struct drm_fb_helper *fb_helper = info->par; |
|
- | 247 | struct drm_framebuffer *fb = fb_helper->fb; |
|
- | 248 | int pindex; |
|
- | 249 | ||
- | 250 | pindex = regno; |
|
- | 251 | ||
- | 252 | if (fb->bits_per_pixel == 16) { |
|
- | 253 | pindex = regno << 3; |
|
- | 254 | ||
- | 255 | if (fb->depth == 16 && regno > 63) |
|
- | 256 | return; |
|
- | 257 | if (fb->depth == 15 && regno > 31) |
|
- | 258 | return; |
|
- | 259 | ||
- | 260 | if (fb->depth == 16) { |
|
- | 261 | u16 r, g, b; |
|
- | 262 | int i; |
|
- | 263 | if (regno < 32) { |
|
- | 264 | for (i = 0; i < 8; i++) |
|
- | 265 | fb_helper->funcs->gamma_set(crtc, red, |
|
- | 266 | green, blue, pindex + i); |
|
- | 267 | } |
|
- | 268 | ||
- | 269 | fb_helper->funcs->gamma_get(crtc, &r, |
|
- | 270 | &g, &b, |
|
- | 271 | pindex >> 1); |
|
- | 272 | ||
- | 273 | for (i = 0; i < 4; i++) |
|
- | 274 | fb_helper->funcs->gamma_set(crtc, r, |
|
- | 275 | green, b, |
|
- | 276 | (pindex >> 1) + i); |
|
- | 277 | } |
|
- | 278 | } |
|
- | 279 | ||
- | 280 | if (fb->depth != 16) |
|
- | 281 | fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex); |
|
- | 282 | ||
- | 283 | if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) { |
|
- | 284 | ((u32 *) fb->pseudo_palette)[regno] = |
|
- | 285 | (regno << info->var.red.offset) | |
|
- | 286 | (regno << info->var.green.offset) | |
|
- | 287 | (regno << info->var.blue.offset); |
|
- | 288 | } |
|
- | 289 | } |
|
- | 290 | ||
- | 291 | int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) |
|
- | 292 | { |
|
- | 293 | struct drm_fb_helper *fb_helper = info->par; |
|
- | 294 | struct drm_device *dev = fb_helper->dev; |
|
- | 295 | u16 *red, *green, *blue, *transp; |
|
- | 296 | struct drm_crtc *crtc; |
|
- | 297 | int i, rc = 0; |
|
- | 298 | int start; |
|
- | 299 | ||
- | 300 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
|
- | 301 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
|
- | 302 | for (i = 0; i < fb_helper->crtc_count; i++) { |
|
- | 303 | if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) |
|
- | 304 | break; |
|
- | 305 | } |
|
- | 306 | if (i == fb_helper->crtc_count) |
|
- | 307 | continue; |
|
- | 308 | ||
- | 309 | red = cmap->red; |
|
- | 310 | green = cmap->green; |
|
- | 311 | blue = cmap->blue; |
|
- | 312 | transp = cmap->transp; |
|
- | 313 | start = cmap->start; |
|
- | 314 | ||
- | 315 | for (i = 0; i < cmap->len; i++) { |
|
- | 316 | u16 hred, hgreen, hblue, htransp = 0xffff; |
|
- | 317 | ||
- | 318 | hred = *red++; |
|
- | 319 | hgreen = *green++; |
|
- | 320 | hblue = *blue++; |
|
- | 321 | ||
- | 322 | if (transp) |
|
- | 323 | htransp = *transp++; |
|
- | 324 | ||
- | 325 | setcolreg(crtc, hred, hgreen, hblue, start++, info); |
|
- | 326 | } |
|
- | 327 | crtc_funcs->load_lut(crtc); |
|
- | 328 | } |
|
- | 329 | return rc; |
|
- | 330 | } |
|
- | 331 | EXPORT_SYMBOL(drm_fb_helper_setcmap); |
|
232 | 332 | ||
233 | int drm_fb_helper_setcolreg(unsigned regno, |
333 | int drm_fb_helper_setcolreg(unsigned regno, |
234 | unsigned red, |
334 | unsigned red, |
235 | unsigned green, |
335 | unsigned green, |
236 | unsigned blue, |
336 | unsigned blue, |
Line 240... | Line 340... | ||
240 | struct drm_fb_helper *fb_helper = info->par; |
340 | struct drm_fb_helper *fb_helper = info->par; |
241 | struct drm_device *dev = fb_helper->dev; |
341 | struct drm_device *dev = fb_helper->dev; |
242 | struct drm_crtc *crtc; |
342 | struct drm_crtc *crtc; |
243 | int i; |
343 | int i; |
Line 244... | Line 344... | ||
244 | 344 | ||
245 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
345 | if (regno > 255) |
Line -... | Line 346... | ||
- | 346 | return 1; |
|
- | 347 | ||
246 | struct drm_framebuffer *fb = fb_helper->fb; |
348 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
247 | 349 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
|
248 | for (i = 0; i < fb_helper->crtc_count; i++) { |
350 | for (i = 0; i < fb_helper->crtc_count; i++) { |
249 | if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) |
351 | if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) |
250 | break; |
352 | break; |
251 | } |
353 | } |
Line 252... | Line -... | ||
252 | if (i == fb_helper->crtc_count) |
- | |
253 | continue; |
- | |
254 | - | ||
255 | if (regno > 255) |
- | |
256 | return 1; |
- | |
257 | - | ||
258 | if (fb->depth == 8) { |
- | |
Line 259... | Line -... | ||
259 | fb_helper->funcs->gamma_set(crtc, red, green, blue, regno); |
- | |
260 | return 0; |
- | |
261 | } |
- | |
262 | - | ||
263 | if (regno < 16) { |
- | |
264 | switch (fb->depth) { |
- | |
265 | case 15: |
- | |
266 | fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) | |
- | |
267 | ((green & 0xf800) >> 6) | |
354 | if (i == fb_helper->crtc_count) |
268 | ((blue & 0xf800) >> 11); |
- | |
269 | break; |
355 | continue; |
270 | case 16: |
- | |
271 | fb->pseudo_palette[regno] = (red & 0xf800) | |
- | |
272 | ((green & 0xfc00) >> 5) | |
- | |
273 | ((blue & 0xf800) >> 11); |
- | |
274 | break; |
- | |
275 | case 24: |
- | |
276 | case 32: |
- | |
277 | fb->pseudo_palette[regno] = |
- | |
278 | (((red >> 8) & 0xff) << info->var.red.offset) | |
- | |
279 | (((green >> 8) & 0xff) << info->var.green.offset) | |
- | |
280 | (((blue >> 8) & 0xff) << info->var.blue.offset); |
356 | |
281 | break; |
357 | |
282 | } |
358 | setcolreg(crtc, red, green, blue, regno, info); |
283 | } |
359 | crtc_funcs->load_lut(crtc); |
Line 448... | Line 524... | ||
448 | return ret; |
524 | return ret; |
449 | } |
525 | } |
450 | EXPORT_SYMBOL(drm_fb_helper_pan_display); |
526 | EXPORT_SYMBOL(drm_fb_helper_pan_display); |
Line 451... | Line 527... | ||
451 | 527 | ||
- | 528 | int drm_fb_helper_single_fb_probe(struct drm_device *dev, |
|
452 | int drm_fb_helper_single_fb_probe(struct drm_device *dev, |
529 | int preferred_bpp, |
453 | int (*fb_create)(struct drm_device *dev, |
530 | int (*fb_create)(struct drm_device *dev, |
454 | uint32_t fb_width, |
531 | uint32_t fb_width, |
455 | uint32_t fb_height, |
532 | uint32_t fb_height, |
456 | uint32_t surface_width, |
533 | uint32_t surface_width, |
- | 534 | uint32_t surface_height, |
|
- | 535 | uint32_t surface_depth, |
|
457 | uint32_t surface_height, |
536 | uint32_t surface_bpp, |
458 | struct drm_framebuffer **fb_ptr)) |
537 | struct drm_framebuffer **fb_ptr)) |
459 | { |
538 | { |
460 | struct drm_crtc *crtc; |
539 | struct drm_crtc *crtc; |
461 | struct drm_connector *connector; |
540 | struct drm_connector *connector; |
Line 466... | Line 545... | ||
466 | int ret, i, conn_count = 0; |
545 | int ret, i, conn_count = 0; |
467 | struct fb_info *info; |
546 | struct fb_info *info; |
468 | struct drm_framebuffer *fb; |
547 | struct drm_framebuffer *fb; |
469 | struct drm_mode_set *modeset = NULL; |
548 | struct drm_mode_set *modeset = NULL; |
470 | struct drm_fb_helper *fb_helper; |
549 | struct drm_fb_helper *fb_helper; |
- | 550 | uint32_t surface_depth = 24, surface_bpp = 32; |
|
Line -... | Line 551... | ||
- | 551 | ||
- | 552 | /* if driver picks 8 or 16 by default use that |
|
- | 553 | for both depth/bpp */ |
|
- | 554 | if (preferred_bpp != surface_bpp) { |
|
- | 555 | surface_depth = surface_bpp = preferred_bpp; |
|
471 | 556 | } |
|
- | 557 | /* first up get a count of crtcs now in use and new min/maxes width/heights */ |
|
- | 558 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
|
- | 559 | struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; |
|
- | 560 | ||
- | 561 | struct drm_fb_helper_cmdline_mode *cmdline_mode; |
|
- | 562 | ||
- | 563 | if (!fb_help_conn) |
|
- | 564 | continue; |
|
- | 565 | ||
- | 566 | cmdline_mode = &fb_help_conn->cmdline_mode; |
|
- | 567 | ||
- | 568 | if (cmdline_mode->bpp_specified) { |
|
- | 569 | switch (cmdline_mode->bpp) { |
|
- | 570 | case 8: |
|
- | 571 | surface_depth = surface_bpp = 8; |
|
- | 572 | break; |
|
- | 573 | case 15: |
|
- | 574 | surface_depth = 15; |
|
- | 575 | surface_bpp = 16; |
|
- | 576 | break; |
|
- | 577 | case 16: |
|
- | 578 | surface_depth = surface_bpp = 16; |
|
- | 579 | break; |
|
- | 580 | case 24: |
|
- | 581 | surface_depth = surface_bpp = 24; |
|
- | 582 | break; |
|
- | 583 | case 32: |
|
- | 584 | surface_depth = 24; |
|
- | 585 | surface_bpp = 32; |
|
- | 586 | break; |
|
- | 587 | } |
|
- | 588 | break; |
|
- | 589 | } |
|
- | 590 | } |
|
472 | /* first up get a count of crtcs now in use and new min/maxes width/heights */ |
591 | |
473 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
592 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
474 | if (drm_helper_crtc_in_use(crtc)) { |
593 | if (drm_helper_crtc_in_use(crtc)) { |
475 | if (crtc->desired_mode) { |
594 | if (crtc->desired_mode) { |
476 | if (crtc->desired_mode->hdisplay < fb_width) |
595 | if (crtc->desired_mode->hdisplay < fb_width) |
Line 496... | Line 615... | ||
496 | } |
615 | } |
Line 497... | Line 616... | ||
497 | 616 | ||
498 | /* do we have an fb already? */ |
617 | /* do we have an fb already? */ |
499 | if (list_empty(&dev->mode_config.fb_kernel_list)) { |
618 | if (list_empty(&dev->mode_config.fb_kernel_list)) { |
500 | ret = (*fb_create)(dev, fb_width, fb_height, surface_width, |
619 | ret = (*fb_create)(dev, fb_width, fb_height, surface_width, |
- | 620 | surface_height, surface_depth, surface_bpp, |
|
501 | surface_height, &fb); |
621 | &fb); |
502 | if (ret) |
622 | if (ret) |
503 | return -EINVAL; |
623 | return -EINVAL; |
504 | new_fb = 1; |
624 | new_fb = 1; |
505 | } else { |
625 | } else { |
Line 575... | Line 695... | ||
575 | list_del(&helper->kernel_fb_list); |
695 | list_del(&helper->kernel_fb_list); |
576 | drm_fb_helper_crtc_free(helper); |
696 | drm_fb_helper_crtc_free(helper); |
577 | } |
697 | } |
578 | EXPORT_SYMBOL(drm_fb_helper_free); |
698 | EXPORT_SYMBOL(drm_fb_helper_free); |
Line 579... | Line 699... | ||
579 | 699 | ||
- | 700 | void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, |
|
580 | void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch) |
701 | uint32_t depth) |
581 | { |
702 | { |
582 | info->fix.type = FB_TYPE_PACKED_PIXELS; |
703 | info->fix.type = FB_TYPE_PACKED_PIXELS; |
- | 704 | info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : |
|
583 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
705 | FB_VISUAL_DIRECTCOLOR; |
584 | info->fix.type_aux = 0; |
706 | info->fix.type_aux = 0; |
585 | info->fix.xpanstep = 1; /* doing it in hw */ |
707 | info->fix.xpanstep = 1; /* doing it in hw */ |
586 | info->fix.ypanstep = 1; /* doing it in hw */ |
708 | info->fix.ypanstep = 1; /* doing it in hw */ |
587 | info->fix.ywrapstep = 0; |
709 | info->fix.ywrapstep = 0; |