27,16 → 27,8 |
* Modularization |
*/ |
|
//#include <linux/module.h> |
//#include <linux/kernel.h> |
//#include <linux/errno.h> |
//#include <linux/string.h> |
//#include <linux/mm.h> |
//#include <linux/tty.h> |
//#include <linux/slab.h> |
//#include <linux/delay.h> |
//#include <linux/fb.h> |
//#include <linux/init.h> |
#include <linux/module.h> |
#include <linux/fb.h> |
|
#include "drmP.h" |
#include "drm.h" |
45,559 → 37,29 |
#include "radeon_drm.h" |
#include "radeon.h" |
|
#include "drm_fb_helper.h" |
|
#include <drm_mm.h> |
#include "radeon_object.h" |
|
struct fb_info *framebuffer_alloc(size_t size); |
|
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ |
#define FB_VISUAL_TRUECOLOR 2 /* True color */ |
|
struct fb_fix_screeninfo { |
char id[16]; /* identification string eg "TT Builtin" */ |
unsigned long smem_start; /* Start of frame buffer mem */ |
/* (physical address) */ |
__u32 smem_len; /* Length of frame buffer mem */ |
__u32 type; /* see FB_TYPE_* */ |
__u32 type_aux; /* Interleave for interleaved Planes */ |
__u32 visual; /* see FB_VISUAL_* */ |
__u16 xpanstep; /* zero if no hardware panning */ |
__u16 ypanstep; /* zero if no hardware panning */ |
__u16 ywrapstep; /* zero if no hardware ywrap */ |
__u32 line_length; /* length of a line in bytes */ |
unsigned long mmio_start; /* Start of Memory Mapped I/O */ |
/* (physical address) */ |
__u32 mmio_len; /* Length of Memory Mapped I/O */ |
__u32 accel; /* Indicate to driver which */ |
/* specific chip/card we have */ |
__u16 reserved[3]; /* Reserved for future compatibility */ |
}; |
|
|
|
|
struct fb_bitfield { |
__u32 offset; /* beginning of bitfield */ |
__u32 length; /* length of bitfield */ |
__u32 msb_right; /* != 0 : Most significant bit is */ |
/* right */ |
}; |
|
|
struct fb_var_screeninfo { |
__u32 xres; /* visible resolution */ |
__u32 yres; |
__u32 xres_virtual; /* virtual resolution */ |
__u32 yres_virtual; |
__u32 xoffset; /* offset from virtual to visible */ |
__u32 yoffset; /* resolution */ |
|
__u32 bits_per_pixel; /* guess what */ |
__u32 grayscale; /* != 0 Graylevels instead of colors */ |
|
struct fb_bitfield red; /* bitfield in fb mem if true color, */ |
struct fb_bitfield green; /* else only length is significant */ |
struct fb_bitfield blue; |
struct fb_bitfield transp; /* transparency */ |
|
__u32 nonstd; /* != 0 Non standard pixel format */ |
|
__u32 activate; /* see FB_ACTIVATE_* */ |
|
__u32 height; /* height of picture in mm */ |
__u32 width; /* width of picture in mm */ |
|
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */ |
|
/* Timing: All values in pixclocks, except pixclock (of course) */ |
__u32 pixclock; /* pixel clock in ps (pico seconds) */ |
__u32 left_margin; /* time from sync to picture */ |
__u32 right_margin; /* time from picture to sync */ |
__u32 upper_margin; /* time from sync to picture */ |
__u32 lower_margin; |
__u32 hsync_len; /* length of horizontal sync */ |
__u32 vsync_len; /* length of vertical sync */ |
__u32 sync; /* see FB_SYNC_* */ |
__u32 vmode; /* see FB_VMODE_* */ |
__u32 rotate; /* angle we rotate counter clockwise */ |
__u32 reserved[5]; /* Reserved for future compatibility */ |
}; |
|
|
|
struct fb_chroma { |
__u32 redx; /* in fraction of 1024 */ |
__u32 greenx; |
__u32 bluex; |
__u32 whitex; |
__u32 redy; |
__u32 greeny; |
__u32 bluey; |
__u32 whitey; |
}; |
|
struct fb_videomode { |
const char *name; /* optional */ |
u32 refresh; /* optional */ |
u32 xres; |
u32 yres; |
u32 pixclock; |
u32 left_margin; |
u32 right_margin; |
u32 upper_margin; |
u32 lower_margin; |
u32 hsync_len; |
u32 vsync_len; |
u32 sync; |
u32 vmode; |
u32 flag; |
}; |
|
|
struct fb_monspecs { |
struct fb_chroma chroma; |
struct fb_videomode *modedb; /* mode database */ |
__u8 manufacturer[4]; /* Manufacturer */ |
__u8 monitor[14]; /* Monitor String */ |
__u8 serial_no[14]; /* Serial Number */ |
__u8 ascii[14]; /* ? */ |
__u32 modedb_len; /* mode database length */ |
__u32 model; /* Monitor Model */ |
__u32 serial; /* Serial Number - Integer */ |
__u32 year; /* Year manufactured */ |
__u32 week; /* Week Manufactured */ |
__u32 hfmin; /* hfreq lower limit (Hz) */ |
__u32 hfmax; /* hfreq upper limit (Hz) */ |
__u32 dclkmin; /* pixelclock lower limit (Hz) */ |
__u32 dclkmax; /* pixelclock upper limit (Hz) */ |
__u16 input; /* display type - see FB_DISP_* */ |
__u16 dpms; /* DPMS support - see FB_DPMS_ */ |
__u16 signal; /* Signal Type - see FB_SIGNAL_* */ |
__u16 vfmin; /* vfreq lower limit (Hz) */ |
__u16 vfmax; /* vfreq upper limit (Hz) */ |
__u16 gamma; /* Gamma - in fractions of 100 */ |
__u16 gtf : 1; /* supports GTF */ |
__u16 misc; /* Misc flags - see FB_MISC_* */ |
__u8 version; /* EDID version... */ |
__u8 revision; /* ...and revision */ |
__u8 max_x; /* Maximum horizontal size (cm) */ |
__u8 max_y; /* Maximum vertical size (cm) */ |
}; |
|
|
struct fb_info { |
int node; |
int flags; |
// struct mutex lock; /* Lock for open/release/ioctl funcs */ |
// struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ |
struct fb_var_screeninfo var; /* Current var */ |
struct fb_fix_screeninfo fix; /* Current fix */ |
struct fb_monspecs monspecs; /* Current Monitor specs */ |
// struct work_struct queue; /* Framebuffer event queue */ |
// struct fb_pixmap pixmap; /* Image hardware mapper */ |
// struct fb_pixmap sprite; /* Cursor hardware mapper */ |
// struct fb_cmap cmap; /* Current cmap */ |
struct list_head modelist; /* mode list */ |
struct fb_videomode *mode; /* current mode */ |
|
#ifdef CONFIG_FB_BACKLIGHT |
/* assigned backlight device */ |
/* set before framebuffer registration, |
remove after unregister */ |
struct backlight_device *bl_dev; |
|
/* Backlight level curve */ |
struct mutex bl_curve_mutex; |
u8 bl_curve[FB_BACKLIGHT_LEVELS]; |
#endif |
#ifdef CONFIG_FB_DEFERRED_IO |
struct delayed_work deferred_work; |
struct fb_deferred_io *fbdefio; |
#endif |
|
struct fb_ops *fbops; |
// struct device *device; /* This is the parent */ |
// struct device *dev; /* This is this fb device */ |
int class_flag; /* private sysfs flags */ |
#ifdef CONFIG_FB_TILEBLITTING |
struct fb_tile_ops *tileops; /* Tile Blitting */ |
#endif |
char __iomem *screen_base; /* Virtual address */ |
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ |
void *pseudo_palette; /* Fake palette of 16 colors */ |
#define FBINFO_STATE_RUNNING 0 |
#define FBINFO_STATE_SUSPENDED 1 |
u32 state; /* Hardware state i.e suspend */ |
void *fbcon_par; /* fbcon use-only private area */ |
/* From here on everything is device dependent */ |
void *par; |
/* we need the PCI or similiar aperture base/size not |
smem_start/size as smem_start may just be an object |
allocated inside the aperture so may not actually overlap */ |
resource_size_t aperture_base; |
resource_size_t aperture_size; |
}; |
|
|
|
struct radeon_fb_device { |
struct drm_fb_helper helper; |
struct radeon_framebuffer *rfb; |
struct radeon_device *rdev; |
struct drm_display_mode *mode; |
struct radeon_framebuffer *rfb; |
int crtc_count; |
/* crtc currently bound to this */ |
uint32_t crtc_ids[2]; |
}; |
|
int radeon_gem_fb_object_create(struct radeon_device *rdev, int size, |
int alignment, int initial_domain, |
bool discardable, bool kernel, |
bool interruptible, |
struct drm_gem_object **obj); |
|
struct fb_info *framebuffer_alloc(size_t size); |
|
#if 0 |
static int radeonfb_setcolreg(unsigned regno, |
unsigned red, |
unsigned green, |
unsigned blue, |
unsigned transp, |
struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct drm_crtc *crtc; |
int i; |
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct drm_mode_set *modeset = &radeon_crtc->mode_set; |
struct drm_framebuffer *fb = modeset->fb; |
|
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
if (i == rfbdev->crtc_count) { |
continue; |
} |
if (regno > 255) { |
return 1; |
} |
if (fb->depth == 8) { |
radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno); |
return 0; |
} |
|
if (regno < 16) { |
switch (fb->depth) { |
case 15: |
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) | |
((green & 0xf800) >> 6) | |
((blue & 0xf800) >> 11); |
break; |
case 16: |
fb->pseudo_palette[regno] = (red & 0xf800) | |
((green & 0xfc00) >> 5) | |
((blue & 0xf800) >> 11); |
break; |
case 24: |
case 32: |
fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | |
(green & 0xff00) | |
((blue & 0xff00) >> 8); |
break; |
} |
} |
} |
return 0; |
} |
|
static int radeonfb_check_var(struct fb_var_screeninfo *var, |
struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct radeon_framebuffer *rfb = rfbdev->rfb; |
struct drm_framebuffer *fb = &rfb->base; |
int depth; |
|
if (var->pixclock == -1 || !var->pixclock) { |
return -EINVAL; |
} |
/* Need to resize the fb object !!! */ |
if (var->xres > fb->width || var->yres > fb->height) { |
DRM_ERROR("Requested width/height is greater than current fb " |
"object %dx%d > %dx%d\n", var->xres, var->yres, |
fb->width, fb->height); |
DRM_ERROR("Need resizing code.\n"); |
return -EINVAL; |
} |
|
switch (var->bits_per_pixel) { |
case 16: |
depth = (var->green.length == 6) ? 16 : 15; |
break; |
case 32: |
depth = (var->transp.length > 0) ? 32 : 24; |
break; |
default: |
depth = var->bits_per_pixel; |
break; |
} |
|
switch (depth) { |
case 8: |
var->red.offset = 0; |
var->green.offset = 0; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 15: |
var->red.offset = 10; |
var->green.offset = 5; |
var->blue.offset = 0; |
var->red.length = 5; |
var->green.length = 5; |
var->blue.length = 5; |
var->transp.length = 1; |
var->transp.offset = 15; |
break; |
case 16: |
var->red.offset = 11; |
var->green.offset = 5; |
var->blue.offset = 0; |
var->red.length = 5; |
var->green.length = 6; |
var->blue.length = 5; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 24: |
var->red.offset = 16; |
var->green.offset = 8; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 32: |
var->red.offset = 16; |
var->green.offset = 8; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 8; |
var->transp.offset = 24; |
break; |
default: |
return -EINVAL; |
} |
return 0; |
} |
|
#endif |
|
|
/* this will let fbcon do the mode init */ |
static int radeonfb_set_par(struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct fb_var_screeninfo *var = &info->var; |
struct drm_crtc *crtc; |
int ret; |
int i; |
|
if (var->pixclock != -1) { |
DRM_ERROR("PIXEL CLCOK SET\n"); |
return -EINVAL; |
} |
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
|
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
if (i == rfbdev->crtc_count) { |
continue; |
} |
if (crtc->fb == radeon_crtc->mode_set.fb) { |
// mutex_lock(&dev->mode_config.mutex); |
ret = crtc->funcs->set_config(&radeon_crtc->mode_set); |
// mutex_unlock(&dev->mode_config.mutex); |
if (ret) { |
return ret; |
} |
} |
} |
return 0; |
} |
|
#if 0 |
|
static int radeonfb_pan_display(struct fb_var_screeninfo *var, |
struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct drm_mode_set *modeset; |
struct drm_crtc *crtc; |
struct radeon_crtc *radeon_crtc; |
int ret = 0; |
int i; |
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
|
if (i == rfbdev->crtc_count) { |
continue; |
} |
|
radeon_crtc = to_radeon_crtc(crtc); |
modeset = &radeon_crtc->mode_set; |
|
modeset->x = var->xoffset; |
modeset->y = var->yoffset; |
|
if (modeset->num_connectors) { |
mutex_lock(&dev->mode_config.mutex); |
ret = crtc->funcs->set_config(modeset); |
mutex_unlock(&dev->mode_config.mutex); |
if (!ret) { |
info->var.xoffset = var->xoffset; |
info->var.yoffset = var->yoffset; |
} |
} |
} |
return ret; |
} |
|
static void radeonfb_on(struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct drm_crtc *crtc; |
struct drm_encoder *encoder; |
int i; |
|
/* |
* For each CRTC in this fb, find all associated encoders |
* and turn them off, then turn off the CRTC. |
*/ |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
|
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
|
mutex_lock(&dev->mode_config.mutex); |
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); |
mutex_unlock(&dev->mode_config.mutex); |
|
/* Found a CRTC on this fb, now find encoders */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct drm_encoder_helper_funcs *encoder_funcs; |
|
encoder_funcs = encoder->helper_private; |
mutex_lock(&dev->mode_config.mutex); |
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
} |
} |
|
static void radeonfb_off(struct fb_info *info, int dpms_mode) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct drm_crtc *crtc; |
struct drm_encoder *encoder; |
int i; |
|
/* |
* For each CRTC in this fb, find all associated encoders |
* and turn them off, then turn off the CRTC. |
*/ |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
|
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
|
/* Found a CRTC on this fb, now find encoders */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct drm_encoder_helper_funcs *encoder_funcs; |
|
encoder_funcs = encoder->helper_private; |
mutex_lock(&dev->mode_config.mutex); |
encoder_funcs->dpms(encoder, dpms_mode); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
if (dpms_mode == DRM_MODE_DPMS_OFF) { |
mutex_lock(&dev->mode_config.mutex); |
crtc_funcs->dpms(crtc, dpms_mode); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
} |
|
int radeonfb_blank(int blank, struct fb_info *info) |
{ |
switch (blank) { |
case FB_BLANK_UNBLANK: |
radeonfb_on(info); |
break; |
case FB_BLANK_NORMAL: |
radeonfb_off(info, DRM_MODE_DPMS_STANDBY); |
break; |
case FB_BLANK_HSYNC_SUSPEND: |
radeonfb_off(info, DRM_MODE_DPMS_STANDBY); |
break; |
case FB_BLANK_VSYNC_SUSPEND: |
radeonfb_off(info, DRM_MODE_DPMS_SUSPEND); |
break; |
case FB_BLANK_POWERDOWN: |
radeonfb_off(info, DRM_MODE_DPMS_OFF); |
break; |
} |
return 0; |
} |
|
static struct fb_ops radeonfb_ops = { |
.owner = THIS_MODULE, |
.fb_check_var = radeonfb_check_var, |
.fb_set_par = radeonfb_set_par, |
.fb_setcolreg = radeonfb_setcolreg, |
.fb_fillrect = cfb_fillrect, |
.fb_copyarea = cfb_copyarea, |
.fb_imageblit = cfb_imageblit, |
.fb_pan_display = radeonfb_pan_display, |
.fb_blank = radeonfb_blank, |
// .owner = THIS_MODULE, |
.fb_check_var = drm_fb_helper_check_var, |
.fb_set_par = drm_fb_helper_set_par, |
.fb_setcolreg = drm_fb_helper_setcolreg, |
// .fb_fillrect = cfb_fillrect, |
// .fb_copyarea = cfb_copyarea, |
// .fb_imageblit = cfb_imageblit, |
// .fb_pan_display = drm_fb_helper_pan_display, |
.fb_blank = drm_fb_helper_blank, |
}; |
|
/** |
640,26 → 102,10 |
} |
EXPORT_SYMBOL(radeonfb_resize); |
|
static struct drm_mode_set panic_mode; |
|
int radeonfb_panic(struct notifier_block *n, unsigned long ununsed, |
void *panic_str) |
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) |
{ |
DRM_ERROR("panic occurred, switching back to text console\n"); |
drm_crtc_helper_set_config(&panic_mode); |
return 0; |
} |
EXPORT_SYMBOL(radeonfb_panic); |
|
static struct notifier_block paniced = { |
.notifier_call = radeonfb_panic, |
}; |
#endif |
|
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) |
{ |
int aligned = width; |
int align_large = (ASIC_IS_AVIVO(rdev)); |
int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; |
int pitch_mask = 0; |
|
switch (bpp / 8) { |
680,11 → 126,16 |
return aligned; |
} |
|
int radeonfb_create(struct radeon_device *rdev, |
static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { |
.gamma_set = radeon_crtc_fb_gamma_set, |
}; |
|
int radeonfb_create(struct drm_device *dev, |
uint32_t fb_width, uint32_t fb_height, |
uint32_t surface_width, uint32_t surface_height, |
struct radeon_framebuffer **rfb_p) |
struct drm_framebuffer **fb_p) |
{ |
struct radeon_device *rdev = dev->dev_private; |
struct fb_info *info; |
struct radeon_fb_device *rfbdev; |
struct drm_framebuffer *fb = NULL; |
697,15 → 148,15 |
u64 fb_gpuaddr; |
void *fbptr = NULL; |
unsigned long tmp; |
bool fb_tiled = false; /* useful for testing */ |
u32 tiling_flags = 0; |
|
ENTRY(); |
|
mode_cmd.width = surface_width; |
mode_cmd.height = surface_height; |
mode_cmd.bpp = 32; |
/* need to align pitch with crtc limits */ |
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8); |
mode_cmd.depth = 32; |
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); |
mode_cmd.depth = 24; |
|
size = mode_cmd.pitch * mode_cmd.height; |
aligned_size = ALIGN(size, PAGE_SIZE); |
715,7 → 166,6 |
false, 0, |
false, &gobj); |
|
|
if (ret) { |
printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", |
surface_width, surface_height); |
724,7 → 174,7 |
} |
robj = gobj->driver_private; |
|
// mutex_lock(&rdev->ddev->struct_mutex); |
mutex_lock(&rdev->ddev->struct_mutex); |
fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); |
if (fb == NULL) { |
DRM_ERROR("failed to allocate fb.\n"); |
740,8 → 190,8 |
|
list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); |
|
*fb_p = fb; |
rfb = to_radeon_framebuffer(fb); |
*rfb_p = rfb; |
rdev->fbdev_rfb = rfb; |
rdev->fbdev_robj = robj; |
|
750,7 → 200,15 |
ret = -ENOMEM; |
goto out_unref; |
} |
|
rdev->fbdev_info = info; |
rfbdev = info->par; |
rfbdev->helper.funcs = &radeon_fb_helper_funcs; |
rfbdev->helper.dev = dev; |
ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, 2, |
RADEONFB_CONN_LIMIT); |
if (ret) |
goto out_unref; |
|
// ret = radeon_object_kmap(robj, &fbptr); |
// if (ret) { |
757,37 → 215,28 |
// goto out_unref; |
// } |
|
|
fbptr = (void*)0xFE000000; // LFB_BASE |
|
strcpy(info->fix.id, "radeondrmfb"); |
|
strcpy(info->fix.id, "radeondrmfb"); |
info->fix.type = FB_TYPE_PACKED_PIXELS; |
info->fix.visual = FB_VISUAL_TRUECOLOR; |
info->fix.type_aux = 0; |
info->fix.xpanstep = 1; /* doing it in hw */ |
info->fix.ypanstep = 1; /* doing it in hw */ |
info->fix.ywrapstep = 0; |
// info->fix.accel = FB_ACCEL_NONE; |
info->fix.type_aux = 0; |
// info->flags = FBINFO_DEFAULT; |
// info->fbops = &radeonfb_ops; |
info->fix.line_length = fb->pitch; |
drm_fb_helper_fill_fix(info, fb->pitch); |
|
info->flags = FBINFO_DEFAULT; |
info->fbops = &radeonfb_ops; |
|
tmp = fb_gpuaddr - rdev->mc.vram_location; |
info->fix.smem_start = rdev->mc.aper_base + tmp; |
info->fix.smem_len = size; |
info->screen_base = fbptr; |
info->screen_size = size; |
info->pseudo_palette = fb->pseudo_palette; |
info->var.xres_virtual = fb->width; |
info->var.yres_virtual = fb->height; |
info->var.bits_per_pixel = fb->bits_per_pixel; |
info->var.xoffset = 0; |
info->var.yoffset = 0; |
// info->var.activate = FB_ACTIVATE_NOW; |
info->var.height = -1; |
info->var.width = -1; |
info->var.xres = fb_width; |
info->var.yres = fb_height; |
|
drm_fb_helper_fill_var(info, fb, fb_width, fb_height); |
|
/* setup aperture base/size for vesafb takeover */ |
info->aperture_base = rdev->ddev->mode_config.fb_base; |
info->aperture_size = rdev->mc.real_vram_size; |
|
info->fix.mmio_start = 0; |
info->fix.mmio_len = 0; |
// info->pixmap.size = 64*1024; |
805,60 → 254,6 |
DRM_INFO("fb depth is %d\n", fb->depth); |
DRM_INFO(" pitch is %d\n", fb->pitch); |
|
switch (fb->depth) { |
case 8: |
info->var.red.offset = 0; |
info->var.green.offset = 0; |
info->var.blue.offset = 0; |
info->var.red.length = 8; /* 8bit DAC */ |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 0; |
info->var.transp.length = 0; |
break; |
case 15: |
info->var.red.offset = 10; |
info->var.green.offset = 5; |
info->var.blue.offset = 0; |
info->var.red.length = 5; |
info->var.green.length = 5; |
info->var.blue.length = 5; |
info->var.transp.offset = 15; |
info->var.transp.length = 1; |
break; |
case 16: |
info->var.red.offset = 11; |
info->var.green.offset = 5; |
info->var.blue.offset = 0; |
info->var.red.length = 5; |
info->var.green.length = 6; |
info->var.blue.length = 5; |
info->var.transp.offset = 0; |
break; |
case 24: |
info->var.red.offset = 16; |
info->var.green.offset = 8; |
info->var.blue.offset = 0; |
info->var.red.length = 8; |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 0; |
info->var.transp.length = 0; |
break; |
case 32: |
info->var.red.offset = 16; |
info->var.green.offset = 8; |
info->var.blue.offset = 0; |
info->var.red.length = 8; |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 24; |
info->var.transp.length = 8; |
break; |
default: |
break; |
} |
|
dbgprintf("fb = %x\n", fb); |
|
fb->fbdev = info; |
865,7 → 260,7 |
rfbdev->rfb = rfb; |
rfbdev->rdev = rdev; |
|
// mutex_unlock(&rdev->ddev->struct_mutex); |
mutex_unlock(&rdev->ddev->struct_mutex); |
return 0; |
|
out_unref: |
879,156 → 274,15 |
kfree(fb); |
} |
// drm_gem_object_unreference(gobj); |
// mutex_unlock(&rdev->ddev->struct_mutex); |
mutex_unlock(&rdev->ddev->struct_mutex); |
out: |
return ret; |
} |
|
static int radeonfb_single_fb_probe(struct radeon_device *rdev) |
{ |
struct drm_crtc *crtc; |
struct drm_connector *connector; |
unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1; |
unsigned int surface_width = 0, surface_height = 0; |
int new_fb = 0; |
int crtc_count = 0; |
int ret, i, conn_count = 0; |
struct radeon_framebuffer *rfb; |
struct fb_info *info; |
struct radeon_fb_device *rfbdev; |
struct drm_mode_set *modeset = NULL; |
|
ENTRY(); |
|
/* first up get a count of crtcs now in use and new min/maxes width/heights */ |
list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) { |
if (drm_helper_crtc_in_use(crtc)) { |
if (crtc->desired_mode) { |
if (crtc->desired_mode->hdisplay < fb_width) |
fb_width = crtc->desired_mode->hdisplay; |
|
if (crtc->desired_mode->vdisplay < fb_height) |
fb_height = crtc->desired_mode->vdisplay; |
|
if (crtc->desired_mode->hdisplay > surface_width) |
surface_width = crtc->desired_mode->hdisplay; |
|
if (crtc->desired_mode->vdisplay > surface_height) |
surface_height = crtc->desired_mode->vdisplay; |
} |
crtc_count++; |
} |
} |
|
if (crtc_count == 0 || fb_width == -1 || fb_height == -1) { |
/* hmm everyone went away - assume VGA cable just fell out |
and will come back later. */ |
|
dbgprintf("crtc count %x width %x height %x\n", |
crtc_count, fb_width, fb_height); |
return 0; |
} |
|
/* do we have an fb already? */ |
if (list_empty(&rdev->ddev->mode_config.fb_kernel_list)) { |
/* create an fb if we don't have one */ |
ret = radeonfb_create(rdev, fb_width, fb_height, surface_width, surface_height, &rfb); |
if (ret) { |
return -EINVAL; |
} |
new_fb = 1; |
} else { |
struct drm_framebuffer *fb; |
fb = list_first_entry(&rdev->ddev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head); |
rfb = to_radeon_framebuffer(fb); |
|
/* if someone hotplugs something bigger than we have already allocated, we are pwned. |
As really we can't resize an fbdev that is in the wild currently due to fbdev |
not really being designed for the lower layers moving stuff around under it. |
- so in the grand style of things - punt. */ |
if ((fb->width < surface_width) || (fb->height < surface_height)) { |
DRM_ERROR("Framebuffer not large enough to scale console onto.\n"); |
return -EINVAL; |
} |
} |
|
info = rfb->base.fbdev; |
rdev->fbdev_info = info; |
rfbdev = info->par; |
|
crtc_count = 0; |
/* okay we need to setup new connector sets in the crtcs */ |
list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) { |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
modeset = &radeon_crtc->mode_set; |
modeset->fb = &rfb->base; |
conn_count = 0; |
list_for_each_entry(connector, &rdev->ddev->mode_config.connector_list, head) { |
if (connector->encoder) |
if (connector->encoder->crtc == modeset->crtc) { |
modeset->connectors[conn_count] = connector; |
conn_count++; |
if (conn_count > RADEONFB_CONN_LIMIT) |
BUG(); |
} |
} |
|
for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++) |
modeset->connectors[i] = NULL; |
|
|
rfbdev->crtc_ids[crtc_count++] = crtc->base.id; |
|
modeset->num_connectors = conn_count; |
if (modeset->crtc->desired_mode) { |
if (modeset->mode) { |
drm_mode_destroy(rdev->ddev, modeset->mode); |
} |
modeset->mode = drm_mode_duplicate(rdev->ddev, |
modeset->crtc->desired_mode); |
} |
} |
rfbdev->crtc_count = crtc_count; |
|
if (new_fb) { |
info->var.pixclock = -1; |
// if (register_framebuffer(info) < 0) |
// return -EINVAL; |
} else { |
radeonfb_set_par(info); |
} |
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, |
info->fix.id); |
|
/* Switch back to kernel console on panic */ |
// panic_mode = *modeset; |
// atomic_notifier_chain_register(&panic_notifier_list, &paniced); |
// printk(KERN_INFO "registered panic notifier\n"); |
LEAVE(); |
|
return 0; |
} |
|
int radeonfb_probe(struct drm_device *dev) |
{ |
int ret; |
|
/* something has changed in the lower levels of hell - deal with it |
here */ |
|
/* two modes : a) 1 fb to rule all crtcs. |
b) one fb per crtc. |
two actions 1) new connected device |
2) device removed. |
case a/1 : if the fb surface isn't big enough - resize the surface fb. |
if the fb size isn't big enough - resize fb into surface. |
if everything big enough configure the new crtc/etc. |
case a/2 : undo the configuration |
possibly resize down the fb to fit the new configuration. |
case b/1 : see if it is on a new crtc - setup a new fb and add it. |
case b/2 : teardown the new fb. |
*/ |
ret = radeonfb_single_fb_probe(dev->dev_private); |
ret = drm_fb_helper_single_fb_probe(dev, &radeonfb_create); |
return ret; |
} |
EXPORT_SYMBOL(radeonfb_probe); |
1044,6 → 298,7 |
} |
info = fb->fbdev; |
if (info) { |
struct radeon_fb_device *rfbdev = info->par; |
robj = rfb->obj->driver_private; |
// unregister_framebuffer(info); |
// radeon_object_kunmap(robj); |
1052,8 → 307,7 |
} |
|
printk(KERN_INFO "unregistered panic notifier\n"); |
// atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); |
// memset(&panic_mode, 0, sizeof(struct drm_mode_set)); |
|
return 0; |
} |
EXPORT_SYMBOL(radeonfb_remove); |
1192,8 → 446,6 |
|
bool ret; |
|
ENTRY(); |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
{ |
struct drm_display_mode *mode; |
1244,17 → 496,17 |
|
fb->width = width; |
fb->height = height; |
fb->pitch = radeon_align_pitch(dev->dev_private, width, 32) |
* ((32 + 1) / 8); |
fb->pitch = radeon_align_pitch(dev->dev_private, width, 32, false) * ((32 + 1) / 8); |
|
crtc->fb = fb; |
|
ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb); |
|
sysSetScreen(width,height); |
sysSetScreen(width, height, fb->pitch); |
|
if (ret == true) |
{ |
dbgprintf("new mode %d %d pitch %d\n", width, height, fb->pitch); |
} |
else |
{ |