2 * Copyright © 2007 David Airlie
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/errno.h>
33 #include <linux/string.h>
35 #include <linux/tty.h>
36 #include <linux/slab.h>
37 #include <linux/delay.h>
39 #include <linux/init.h>
44 #include "drm_crtc_helper.h"
45 #include "radeon_drm.h"
46 #include "radeon_drv.h"
49 struct drm_device *dev;
50 struct drm_display_mode *our_mode;
51 struct radeon_framebuffer *radeon_fb;
53 /* crtc currently bound to this */
58 var_to_refresh(const struct fb_var_screeninfo *var)
60 int xtot = var->xres + var->left_margin + var->right_margin +
62 int ytot = var->yres + var->upper_margin + var->lower_margin +
65 return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
68 static int radeonfb_setcolreg(unsigned regno, unsigned red, unsigned green,
69 unsigned blue, unsigned transp,
72 struct radeonfb_par *par = info->par;
73 struct drm_device *dev = par->dev;
74 struct drm_crtc *crtc;
77 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
78 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
79 struct drm_mode_set *modeset = &radeon_crtc->mode_set;
80 struct drm_framebuffer *fb = modeset->fb;
82 for (i = 0; i < par->crtc_count; i++)
83 if (crtc->base.id == par->crtc_ids[i])
86 if (i == par->crtc_count)
94 radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno);
101 fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
102 ((green & 0xf800) >> 6) |
103 ((blue & 0xf800) >> 11);
106 fb->pseudo_palette[regno] = (red & 0xf800) |
107 ((green & 0xfc00) >> 5) |
108 ((blue & 0xf800) >> 11);
112 fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
114 ((blue & 0xff00) >> 8);
122 static int radeonfb_check_var(struct fb_var_screeninfo *var,
123 struct fb_info *info)
125 struct radeonfb_par *par = info->par;
126 struct radeon_framebuffer *radeon_fb = par->radeon_fb;
127 struct drm_framebuffer *fb = &radeon_fb->base;
130 if (var->pixclock == -1 || !var->pixclock)
133 /* Need to resize the fb object !!! */
134 if (var->xres > fb->width || var->yres > fb->height) {
135 DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
136 DRM_ERROR("Need resizing code.\n");
140 switch (var->bits_per_pixel) {
142 depth = (var->green.length == 6) ? 16 : 15;
145 depth = (var->transp.length > 0) ? 32 : 24;
148 depth = var->bits_per_pixel;
155 var->green.offset = 0;
156 var->blue.offset = 0;
158 var->green.length = 8;
159 var->blue.length = 8;
160 var->transp.length = 0;
161 var->transp.offset = 0;
164 var->red.offset = 10;
165 var->green.offset = 5;
166 var->blue.offset = 0;
168 var->green.length = 5;
169 var->blue.length = 5;
170 var->transp.length = 1;
171 var->transp.offset = 15;
174 var->red.offset = 11;
175 var->green.offset = 5;
176 var->blue.offset = 0;
178 var->green.length = 6;
179 var->blue.length = 5;
180 var->transp.length = 0;
181 var->transp.offset = 0;
184 var->red.offset = 16;
185 var->green.offset = 8;
186 var->blue.offset = 0;
188 var->green.length = 8;
189 var->blue.length = 8;
190 var->transp.length = 0;
191 var->transp.offset = 0;
194 var->red.offset = 16;
195 var->green.offset = 8;
196 var->blue.offset = 0;
198 var->green.length = 8;
199 var->blue.length = 8;
200 var->transp.length = 8;
201 var->transp.offset = 24;
210 /* this will let fbcon do the mode init */
211 /* FIXME: take mode config lock? */
212 static int radeonfb_set_par(struct fb_info *info)
214 struct radeonfb_par *par = info->par;
215 struct drm_device *dev = par->dev;
216 struct fb_var_screeninfo *var = &info->var;
219 DRM_DEBUG("%d %d\n", var->xres, var->pixclock);
221 if (var->pixclock != -1) {
223 DRM_ERROR("PIXEL CLCOK SET\n");
225 struct radeon_framebuffer *radeon_fb = par->radeon_fb;
226 struct drm_framebuffer *fb = &radeon_fb->base;
227 struct drm_display_mode *drm_mode, *search_mode;
228 struct drm_connector *connector = NULL;
229 struct drm_device *dev = par->dev;
233 switch (var->bits_per_pixel) {
235 fb->depth = (var->green.length == 6) ? 16 : 15;
238 fb->depth = (var->transp.length > 0) ? 32 : 24;
241 fb->depth = var->bits_per_pixel;
245 fb->bits_per_pixel = var->bits_per_pixel;
247 info->fix.line_length = fb->pitch;
248 info->fix.smem_len = info->fix.line_length * fb->height;
249 info->fix.visual = (fb->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
251 info->screen_size = info->fix.smem_len; /* ??? */
252 /* reuse desired mode if possible */
253 /* create a drm mode */
254 drm_mode = drm_mode_create(dev);
255 drm_mode->hdisplay = var->xres;
256 drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
257 drm_mode->hsync_end = drm_mode->hsync_start + var->hsync_len;
258 drm_mode->htotal = drm_mode->hsync_end + var->left_margin;
259 drm_mode->vdisplay = var->yres;
260 drm_mode->vsync_start = drm_mode->vdisplay + var->lower_margin;
261 drm_mode->vsync_end = drm_mode->vsync_start + var->vsync_len;
262 drm_mode->vtotal = drm_mode->vsync_end + var->upper_margin;
263 drm_mode->clock = PICOS2KHZ(var->pixclock);
264 drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
266 drm_mode->flags |= var->sync & FB_SYNC_HOR_HIGH_ACT ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
267 drm_mode->flags |= var->sync & FB_SYNC_VERT_HIGH_ACT ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
269 drm_mode_set_name(drm_mode);
270 drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V);
273 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
274 if (connector->encoder &&
275 connector->encoder->crtc == par->set.crtc){
281 /* no connector bound, bail */
286 drm_mode_debug_printmodeline(drm_mode);
287 list_for_each_entry(search_mode, &connector->modes, head) {
288 drm_mode_debug_printmodeline(search_mode);
289 if (drm_mode_equal(drm_mode, search_mode)) {
290 drm_mode_destroy(dev, drm_mode);
291 drm_mode = search_mode;
297 /* If we didn't find a matching mode that exists on our connector,
298 * create a new attachment for the incoming user specified mode
302 /* this also destroys the mode */
303 drm_mode_detachmode_crtc(dev, par->our_mode);
306 par->set.mode = drm_mode;
307 par->our_mode = drm_mode;
308 drm_mode_debug_printmodeline(drm_mode);
310 drm_mode_attachmode_crtc(dev, par->set.crtc, par->set.mode);
312 par->set.mode = drm_mode;
314 drm_mode_detachmode_crtc(dev, par->our_mode);
315 par->our_mode = NULL;
317 return par->set.crtc->funcs->set_config(&par->set);
321 struct drm_crtc *crtc;
324 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
325 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
327 for (i = 0; i < par->crtc_count; i++)
328 if (crtc->base.id == par->crtc_ids[i])
331 if (i == par->crtc_count)
334 if (crtc->fb == radeon_crtc->mode_set.fb) {
335 ret = crtc->funcs->set_config(&radeon_crtc->mode_set);
345 static void radeonfb_copyarea(struct fb_info *info,
346 const struct fb_copyarea *region)
348 struct radeonfb_par *par = info->par;
349 struct drm_device *dev = par->dev;
350 struct drm_i915_private *dev_priv = dev->dev_private;
351 u32 src_x1, src_y1, dst_x1, dst_y1, dst_x2, dst_y2, offset;
352 u32 cmd, rop_depth_pitch, src_pitch;
355 cmd = XY_SRC_COPY_BLT_CMD;
360 dst_x2 = region->dx + region->width;
361 dst_y2 = region->dy + region->height;
362 offset = par->fb->offset;
363 rop_depth_pitch = BLT_ROP_GXCOPY | par->fb->pitch;
364 src_pitch = par->fb->pitch;
366 switch (par->fb->bits_per_pixel) {
368 rop_depth_pitch |= BLT_DEPTH_16_565;
371 rop_depth_pitch |= BLT_DEPTH_32;
372 cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
378 OUT_RING(rop_depth_pitch);
379 OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
380 OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
382 OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
388 #define ROUND_UP_TO(x, y) (((x) + (y) - 1) / (y) * (y))
389 #define ROUND_DOWN_TO(x, y) ((x) / (y) * (y))
391 void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
393 struct radeonfb_par *par = info->par;
394 struct drm_device *dev = par->dev;
395 struct drm_i915_private *dev_priv = dev->dev_private;
396 u32 cmd, rop_pitch_depth, tmp;
397 int nbytes, ndwords, pad;
398 u32 dst_x1, dst_y1, dst_x2, dst_y2, offset, bg, fg;
403 /* size in bytes of a padded scanline */
404 nbytes = ROUND_UP_TO(image->width, 16) / 8;
406 /* Total bytes of padded scanline data to write out. */
407 nbytes *= image->height;
410 * Check if the glyph data exceeds the immediate mode limit.
411 * It would take a large font (1K pixels) to hit this limit.
413 if (nbytes > 128 || image->depth != 1)
414 return cfb_imageblit(info, image);
416 /* Src data is packaged a dword (32-bit) at a time. */
417 ndwords = ROUND_UP_TO(nbytes, 4) / 4;
420 * Ring has to be padded to a quad word. But because the command starts
421 with 7 bytes, pad only if there is an even number of ndwords
423 pad = !(ndwords % 2);
425 DRM_DEBUG("imageblit %dx%dx%d to (%d,%d)\n", image->width,
426 image->height, image->depth, image->dx, image->dy);
427 DRM_DEBUG("nbytes: %d, ndwords: %d, pad: %d\n", nbytes, ndwords, pad);
429 tmp = (XY_MONO_SRC_COPY_IMM_BLT & 0xff) + ndwords;
430 cmd = (XY_MONO_SRC_COPY_IMM_BLT & ~0xff) | tmp;
431 offset = par->fb->offset;
434 dst_x2 = image->dx + image->width;
435 dst_y2 = image->dy + image->height;
436 rop_pitch_depth = BLT_ROP_GXCOPY | par->fb->pitch;
438 switch (par->fb->bits_per_pixel) {
440 rop_pitch_depth |= BLT_DEPTH_8;
441 fg = image->fg_color;
442 bg = image->bg_color;
445 rop_pitch_depth |= BLT_DEPTH_16_565;
446 fg = par->fb->pseudo_palette[image->fg_color];
447 bg = par->fb->pseudo_palette[image->bg_color];
450 rop_pitch_depth |= BLT_DEPTH_32;
451 cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
452 fg = par->fb->pseudo_palette[image->fg_color];
453 bg = par->fb->pseudo_palette[image->bg_color];
456 DRM_ERROR("unknown depth %d\n", par->fb->bits_per_pixel);
460 BEGIN_LP_RING(8 + ndwords);
462 OUT_RING(rop_pitch_depth);
463 OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
464 OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
469 iw = ROUND_UP_TO(image->width, 8) / 8;
472 for (j = 0; j < 2; ++j) {
473 for (i = 0; i < 2; ++i) {
474 if (ix != iw || i == 0)
475 dat |= image->data[iy*iw + ix++] << (i+j*2)*8;
477 if (ix == iw && iy != (image->height - 1)) {
489 static int radeonfb_pan_display(struct fb_var_screeninfo *var,
490 struct fb_info *info)
492 struct radeonfb_par *par = info->par;
493 struct drm_device *dev = par->dev;
494 struct drm_mode_set *modeset;
495 struct drm_crtc *crtc;
496 struct radeon_crtc *radeon_crtc;
500 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
502 for (i = 0; i < par->crtc_count; i++)
503 if (crtc->base.id == par->crtc_ids[i])
506 if (i == par->crtc_count)
509 radeon_crtc = to_radeon_crtc(crtc);
510 modeset = &radeon_crtc->mode_set;
512 modeset->x = var->xoffset;
513 modeset->y = var->yoffset;
515 if (modeset->num_connectors) {
516 ret = crtc->funcs->set_config(modeset);
519 info->var.xoffset = var->xoffset;
520 info->var.yoffset = var->yoffset;
528 static void radeonfb_on(struct fb_info *info)
530 struct radeonfb_par *par = info->par;
531 struct drm_device *dev = par->dev;
532 struct drm_crtc *crtc;
533 struct drm_encoder *encoder;
537 * For each CRTC in this fb, find all associated encoders
538 * and turn them off, then turn off the CRTC.
540 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
541 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
543 for (i = 0; i < par->crtc_count; i++)
544 if (crtc->base.id == par->crtc_ids[i])
547 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
549 /* Found a CRTC on this fb, now find encoders */
550 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
551 if (encoder->crtc == crtc) {
552 struct drm_encoder_helper_funcs *encoder_funcs;
553 encoder_funcs = encoder->helper_private;
554 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
560 static void radeonfb_off(struct fb_info *info, int dpms_mode)
562 struct radeonfb_par *par = info->par;
563 struct drm_device *dev = par->dev;
564 struct drm_crtc *crtc;
565 struct drm_encoder *encoder;
569 * For each CRTC in this fb, find all associated encoders
570 * and turn them off, then turn off the CRTC.
572 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
573 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
575 for (i = 0; i < par->crtc_count; i++)
576 if (crtc->base.id == par->crtc_ids[i])
579 /* Found a CRTC on this fb, now find encoders */
580 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
581 if (encoder->crtc == crtc) {
582 struct drm_encoder_helper_funcs *encoder_funcs;
583 encoder_funcs = encoder->helper_private;
584 encoder_funcs->dpms(encoder, dpms_mode);
587 if (dpms_mode == DRM_MODE_DPMS_OFF)
588 crtc_funcs->dpms(crtc, dpms_mode);
592 int radeonfb_blank(int blank, struct fb_info *info)
595 case FB_BLANK_UNBLANK:
598 case FB_BLANK_NORMAL:
599 radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
601 case FB_BLANK_HSYNC_SUSPEND:
602 radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
604 case FB_BLANK_VSYNC_SUSPEND:
605 radeonfb_off(info, DRM_MODE_DPMS_SUSPEND);
607 case FB_BLANK_POWERDOWN:
608 radeonfb_off(info, DRM_MODE_DPMS_OFF);
614 static struct fb_ops radeonfb_ops = {
615 .owner = THIS_MODULE,
616 //.fb_open = radeonfb_open,
617 //.fb_read = radeonfb_read,
618 //.fb_write = radeonfb_write,
619 //.fb_release = radeonfb_release,
620 //.fb_ioctl = radeonfb_ioctl,
621 .fb_check_var = radeonfb_check_var,
622 .fb_set_par = radeonfb_set_par,
623 .fb_setcolreg = radeonfb_setcolreg,
624 .fb_fillrect = cfb_fillrect,
625 .fb_copyarea = cfb_copyarea, //radeonfb_copyarea,
626 .fb_imageblit = cfb_imageblit, //radeonfb_imageblit,
627 .fb_pan_display = radeonfb_pan_display,
628 .fb_blank = radeonfb_blank,
632 * Curretly it is assumed that the old framebuffer is reused.
635 * caller should hold the mode config lock.
638 int radeonfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
640 struct fb_info *info;
641 struct drm_framebuffer *fb;
642 struct drm_display_mode *mode = crtc->desired_mode;
655 info->var.xres = mode->hdisplay;
656 info->var.right_margin = mode->hsync_start - mode->hdisplay;
657 info->var.hsync_len = mode->hsync_end - mode->hsync_start;
658 info->var.left_margin = mode->htotal - mode->hsync_end;
659 info->var.yres = mode->vdisplay;
660 info->var.lower_margin = mode->vsync_start - mode->vdisplay;
661 info->var.vsync_len = mode->vsync_end - mode->vsync_start;
662 info->var.upper_margin = mode->vtotal - mode->vsync_end;
663 info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100;
665 info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
669 EXPORT_SYMBOL(radeonfb_resize);
671 static struct drm_mode_set panic_mode;
673 int radeonfb_panic(struct notifier_block *n, unsigned long ununsed,
676 DRM_ERROR("panic occurred, switching back to text console\n");
677 drm_crtc_helper_set_config(&panic_mode);
681 EXPORT_SYMBOL(radeonfb_panic);
683 static struct notifier_block paniced = {
684 .notifier_call = radeonfb_panic,
687 static int radeon_align_pitch(struct drm_device *dev, int width, int bpp)
689 struct drm_radeon_private *dev_priv = dev->dev_private;
691 int align_large = (radeon_is_avivo(dev_priv));
695 case 1: pitch_mask = align_large ? 255 : 127; break;
696 case 2: pitch_mask = align_large ? 127 : 31; break;
698 case 4: pitch_mask = align_large ? 63 : 15; break;
701 aligned += pitch_mask;
702 aligned &= ~pitch_mask;
706 int radeonfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height,
707 uint32_t surface_width, uint32_t surface_height,
708 struct radeon_framebuffer **radeon_fb_p)
710 struct fb_info *info;
711 struct radeonfb_par *par;
712 struct drm_framebuffer *fb;
713 struct radeon_framebuffer *radeon_fb;
714 struct drm_mode_fb_cmd mode_cmd;
715 struct drm_gem_object *fbo = NULL;
716 struct drm_radeon_gem_object *obj_priv;
717 struct device *device = &dev->pdev->dev;
718 int size, aligned_size, ret;
720 mode_cmd.width = surface_width;/* crtc->desired_mode->hdisplay; */
721 mode_cmd.height = surface_height;/* crtc->desired_mode->vdisplay; */
724 /* need to align pitch with crtc limits */
725 mode_cmd.pitch = radeon_align_pitch(dev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8);
728 size = mode_cmd.pitch * mode_cmd.height;
729 aligned_size = ALIGN(size, PAGE_SIZE);
731 fbo = radeon_gem_object_alloc(dev, aligned_size, 1, RADEON_GEM_DOMAIN_VRAM);
733 printk(KERN_ERR "failed to allocate framebuffer\n");
737 obj_priv = fbo->driver_private;
739 ret = radeon_gem_object_pin(fbo, PAGE_SIZE);
741 DRM_ERROR("failed to pin fb: %d\n", ret);
742 mutex_lock(&dev->struct_mutex);
746 mutex_lock(&dev->struct_mutex);
747 fb = radeon_user_framebuffer_create(dev, NULL, &mode_cmd);
749 DRM_ERROR("failed to allocate fb.\n");
754 list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
756 radeon_fb = to_radeon_framebuffer(fb);
757 *radeon_fb_p = radeon_fb;
759 radeon_fb->obj = fbo;
761 info = framebuffer_alloc(sizeof(struct radeonfb_par), device);
769 strcpy(info->fix.id, "radeondrmfb");
770 info->fix.type = FB_TYPE_PACKED_PIXELS;
771 info->fix.visual = FB_VISUAL_TRUECOLOR;
772 info->fix.type_aux = 0;
773 info->fix.xpanstep = 1; /* doing it in hw */
774 info->fix.ypanstep = 1; /* doing it in hw */
775 info->fix.ywrapstep = 0;
776 info->fix.accel = FB_ACCEL_I830;
777 info->fix.type_aux = 0;
779 info->flags = FBINFO_DEFAULT;
781 info->fbops = &radeonfb_ops;
783 info->fix.line_length = fb->pitch;
784 info->fix.smem_start = dev->mode_config.fb_base + obj_priv->bo->offset;
785 info->fix.smem_len = size;
787 info->flags = FBINFO_DEFAULT;
789 ret = drm_bo_kmap(obj_priv->bo, 0, PAGE_ALIGN(size) >> PAGE_SHIFT,
790 &radeon_fb->kmap_obj);
791 info->screen_base = radeon_fb->kmap_obj.virtual;
792 if (!info->screen_base) {
796 info->screen_size = size;
798 memset(info->screen_base, 0, size);
800 info->pseudo_palette = fb->pseudo_palette;
801 info->var.xres_virtual = fb->width;
802 info->var.yres_virtual = fb->height;
803 info->var.bits_per_pixel = fb->bits_per_pixel;
804 info->var.xoffset = 0;
805 info->var.yoffset = 0;
806 info->var.activate = FB_ACTIVATE_NOW;
807 info->var.height = -1;
808 info->var.width = -1;
810 info->var.xres = fb_width;
811 info->var.yres = fb_height;
813 info->fix.mmio_start = pci_resource_start(dev->pdev, 2);
814 info->fix.mmio_len = pci_resource_len(dev->pdev, 2);
816 info->pixmap.size = 64*1024;
817 info->pixmap.buf_align = 8;
818 info->pixmap.access_align = 32;
819 info->pixmap.flags = FB_PIXMAP_SYSTEM;
820 info->pixmap.scan_align = 1;
822 DRM_DEBUG("fb depth is %d\n", fb->depth);
823 DRM_DEBUG(" pitch is %d\n", fb->pitch);
826 info->var.red.offset = 0;
827 info->var.green.offset = 0;
828 info->var.blue.offset = 0;
829 info->var.red.length = 8; /* 8bit DAC */
830 info->var.green.length = 8;
831 info->var.blue.length = 8;
832 info->var.transp.offset = 0;
833 info->var.transp.length = 0;
836 info->var.red.offset = 10;
837 info->var.green.offset = 5;
838 info->var.blue.offset = 0;
839 info->var.red.length = 5;
840 info->var.green.length = 5;
841 info->var.blue.length = 5;
842 info->var.transp.offset = 15;
843 info->var.transp.length = 1;
846 info->var.red.offset = 11;
847 info->var.green.offset = 5;
848 info->var.blue.offset = 0;
849 info->var.red.length = 5;
850 info->var.green.length = 6;
851 info->var.blue.length = 5;
852 info->var.transp.offset = 0;
855 info->var.red.offset = 16;
856 info->var.green.offset = 8;
857 info->var.blue.offset = 0;
858 info->var.red.length = 8;
859 info->var.green.length = 8;
860 info->var.blue.length = 8;
861 info->var.transp.offset = 0;
862 info->var.transp.length = 0;
865 info->var.red.offset = 16;
866 info->var.green.offset = 8;
867 info->var.blue.offset = 0;
868 info->var.red.length = 8;
869 info->var.green.length = 8;
870 info->var.blue.length = 8;
871 info->var.transp.offset = 24;
872 info->var.transp.length = 8;
880 par->radeon_fb = radeon_fb;
883 /* To allow resizeing without swapping buffers */
884 printk("allocated %p %dx%d fb: 0x%08x, bo %p\n", dev, radeon_fb->base.width,
885 radeon_fb->base.height, obj_priv->bo->offset, fbo);
887 mutex_unlock(&dev->struct_mutex);
891 drm_gem_object_unreference(fbo);
892 mutex_unlock(&dev->struct_mutex);
897 static int radeonfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc)
899 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
900 struct radeon_framebuffer *radeon_fb;
901 struct drm_framebuffer *fb;
902 struct drm_connector *connector;
903 struct fb_info *info;
904 struct radeonfb_par *par;
905 struct drm_mode_set *modeset;
906 unsigned int width, height;
908 int ret, i, conn_count;
910 if (!drm_helper_crtc_in_use(crtc))
913 if (!crtc->desired_mode)
916 width = crtc->desired_mode->hdisplay;
917 height = crtc->desired_mode->vdisplay;
919 /* is there an fb bound to this crtc already */
920 if (!radeon_crtc->mode_set.fb) {
921 ret = radeonfb_create(dev, width, height, width, height, &radeon_fb);
926 fb = radeon_crtc->mode_set.fb;
927 radeon_fb = to_radeon_framebuffer(fb);
928 if ((radeon_fb->base.width < width) || (radeon_fb->base.height < height))
932 info = radeon_fb->base.fbdev;
935 modeset = &radeon_crtc->mode_set;
936 modeset->fb = &radeon_fb->base;
938 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
939 if (connector->encoder)
940 if (connector->encoder->crtc == modeset->crtc) {
941 modeset->connectors[conn_count] = connector;
943 if (conn_count > RADEONFB_CONN_LIMIT)
948 for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++)
949 modeset->connectors[i] = NULL;
951 par->crtc_ids[0] = crtc->base.id;
953 modeset->num_connectors = conn_count;
954 if (modeset->mode != modeset->crtc->desired_mode)
955 modeset->mode = modeset->crtc->desired_mode;
960 info->var.pixclock = -1;
961 if (register_framebuffer(info) < 0)
964 radeonfb_set_par(info);
966 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
969 /* Switch back to kernel console on panic */
970 panic_mode = *modeset;
971 atomic_notifier_chain_register(&panic_notifier_list, &paniced);
972 printk(KERN_INFO "registered panic notifier\n");
977 static int radeonfb_multi_fb_probe(struct drm_device *dev)
980 struct drm_crtc *crtc;
983 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
984 ret = radeonfb_multi_fb_probe_crtc(dev, crtc);
991 static int radeonfb_single_fb_probe(struct drm_device *dev)
993 struct drm_crtc *crtc;
994 struct drm_connector *connector;
995 unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
996 unsigned int surface_width = 0, surface_height = 0;
999 int ret, i, conn_count = 0;
1000 struct radeon_framebuffer *radeon_fb;
1001 struct fb_info *info;
1002 struct radeonfb_par *par;
1003 struct drm_mode_set *modeset = NULL;
1006 /* first up get a count of crtcs now in use and new min/maxes width/heights */
1007 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1008 if (drm_helper_crtc_in_use(crtc)) {
1009 if (crtc->desired_mode) {
1010 if (crtc->desired_mode->hdisplay < fb_width)
1011 fb_width = crtc->desired_mode->hdisplay;
1013 if (crtc->desired_mode->vdisplay < fb_height)
1014 fb_height = crtc->desired_mode->vdisplay;
1016 if (crtc->desired_mode->hdisplay > surface_width)
1017 surface_width = crtc->desired_mode->hdisplay;
1019 if (crtc->desired_mode->vdisplay > surface_height)
1020 surface_height = crtc->desired_mode->vdisplay;
1027 if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
1028 /* hmm everyone went away - assume VGA cable just fell out
1029 and will come back later. */
1033 /* do we have an fb already? */
1034 if (list_empty(&dev->mode_config.fb_kernel_list)) {
1035 /* create an fb if we don't have one */
1036 ret = radeonfb_create(dev, fb_width, fb_height, surface_width, surface_height, &radeon_fb);
1041 struct drm_framebuffer *fb;
1042 fb = list_first_entry(&dev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head);
1043 radeon_fb = to_radeon_framebuffer(fb);
1045 /* if someone hotplugs something bigger than we have already allocated, we are pwned.
1046 As really we can't resize an fbdev that is in the wild currently due to fbdev
1047 not really being designed for the lower layers moving stuff around under it.
1048 - so in the grand style of things - punt. */
1049 if ((fb->width < surface_width) || (fb->height < surface_height)) {
1050 DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
1055 info = radeon_fb->base.fbdev;
1059 /* okay we need to setup new connector sets in the crtcs */
1060 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1061 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1062 modeset = &radeon_crtc->mode_set;
1063 modeset->fb = &radeon_fb->base;
1065 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1066 if (connector->encoder)
1067 if(connector->encoder->crtc == modeset->crtc) {
1068 modeset->connectors[conn_count] = connector;
1070 if (conn_count > RADEONFB_CONN_LIMIT)
1075 for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++)
1076 modeset->connectors[i] = NULL;
1079 par->crtc_ids[crtc_count++] = crtc->base.id;
1081 modeset->num_connectors = conn_count;
1082 if (modeset->mode != modeset->crtc->desired_mode)
1083 modeset->mode = modeset->crtc->desired_mode;
1085 par->crtc_count = crtc_count;
1088 info->var.pixclock = -1;
1089 if (register_framebuffer(info) < 0)
1092 radeonfb_set_par(info);
1094 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
1097 /* Switch back to kernel console on panic */
1098 panic_mode = *modeset;
1099 atomic_notifier_chain_register(&panic_notifier_list, &paniced);
1100 printk(KERN_INFO "registered panic notifier\n");
1105 int radeonfb_probe(struct drm_device *dev)
1111 /* something has changed in the lower levels of hell - deal with it
1114 /* two modes : a) 1 fb to rule all crtcs.
1116 two actions 1) new connected device
1118 case a/1 : if the fb surface isn't big enough - resize the surface fb.
1119 if the fb size isn't big enough - resize fb into surface.
1120 if everything big enough configure the new crtc/etc.
1121 case a/2 : undo the configuration
1122 possibly resize down the fb to fit the new configuration.
1123 case b/1 : see if it is on a new crtc - setup a new fb and add it.
1124 case b/2 : teardown the new fb.
1128 /* search for an fb */
1129 // if (radeon_fbpercrtc == 1) {
1130 // ret = radeonfb_multi_fb_probe(dev);
1132 ret = radeonfb_single_fb_probe(dev);
1137 EXPORT_SYMBOL(radeonfb_probe);
1139 int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
1141 struct fb_info *info;
1142 struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
1150 unregister_framebuffer(info);
1151 drm_bo_kunmap(&radeon_fb->kmap_obj);
1152 mutex_lock(&dev->struct_mutex);
1153 drm_gem_object_unreference(radeon_fb->obj);
1154 mutex_unlock(&dev->struct_mutex);
1155 framebuffer_release(info);
1158 atomic_notifier_chain_unregister(&panic_notifier_list, &paniced);
1159 memset(&panic_mode, 0, sizeof(struct drm_mode_set));
1162 EXPORT_SYMBOL(radeonfb_remove);
1163 MODULE_LICENSE("GPL");