Commit 126b5440 authored by Marcin Kościelnicki's avatar Marcin Kościelnicki Committed by Ben Skeggs

drm/nouveau: Fix fbcon on mixed pre-NV50 + NV50 multicard.

We used single shared fbops struct and patched it at fb init time with
pointers to the right variant. On mixed multicard, this meant that
it was either sending NV50-style commands to all cards, or NV04-style
commands to all cards.
Signed-off-by: default avatarMarcin Kościelnicki <koriakin@0x04.net>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 7dad9ef6
...@@ -107,6 +107,34 @@ static struct fb_ops nouveau_fbcon_ops = { ...@@ -107,6 +107,34 @@ static struct fb_ops nouveau_fbcon_ops = {
.fb_setcmap = drm_fb_helper_setcmap, .fb_setcmap = drm_fb_helper_setcmap,
}; };
static struct fb_ops nv04_fbcon_ops = {
.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 = nv04_fbcon_fillrect,
.fb_copyarea = nv04_fbcon_copyarea,
.fb_imageblit = nv04_fbcon_imageblit,
.fb_sync = nouveau_fbcon_sync,
.fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank,
.fb_setcmap = drm_fb_helper_setcmap,
};
static struct fb_ops nv50_fbcon_ops = {
.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 = nv50_fbcon_fillrect,
.fb_copyarea = nv50_fbcon_copyarea,
.fb_imageblit = nv50_fbcon_imageblit,
.fb_sync = nouveau_fbcon_sync,
.fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank,
.fb_setcmap = drm_fb_helper_setcmap,
};
static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno) u16 blue, int regno)
{ {
...@@ -324,9 +352,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, ...@@ -324,9 +352,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
switch (dev_priv->card_type) { switch (dev_priv->card_type) {
case NV_50: case NV_50:
nv50_fbcon_accel_init(info); nv50_fbcon_accel_init(info);
info->fbops = &nv50_fbcon_ops;
break; break;
default: default:
nv04_fbcon_accel_init(info); nv04_fbcon_accel_init(info);
info->fbops = &nv04_fbcon_ops;
break; break;
}; };
} }
......
...@@ -40,7 +40,13 @@ int nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb); ...@@ -40,7 +40,13 @@ int nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb);
void nouveau_fbcon_restore(void); void nouveau_fbcon_restore(void);
void nouveau_fbcon_zfill(struct drm_device *dev); void nouveau_fbcon_zfill(struct drm_device *dev);
void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
int nv04_fbcon_accel_init(struct fb_info *info); int nv04_fbcon_accel_init(struct fb_info *info);
void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
int nv50_fbcon_accel_init(struct fb_info *info); int nv50_fbcon_accel_init(struct fb_info *info);
void nouveau_fbcon_gpu_lockup(struct fb_info *info); void nouveau_fbcon_gpu_lockup(struct fb_info *info);
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "nouveau_dma.h" #include "nouveau_dma.h"
#include "nouveau_fbcon.h" #include "nouveau_fbcon.h"
static void void
nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -54,7 +54,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) ...@@ -54,7 +54,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
FIRE_RING(chan); FIRE_RING(chan);
} }
static void void
nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -88,7 +88,7 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -88,7 +88,7 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
FIRE_RING(chan); FIRE_RING(chan);
} }
static void void
nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -307,9 +307,6 @@ nv04_fbcon_accel_init(struct fb_info *info) ...@@ -307,9 +307,6 @@ nv04_fbcon_accel_init(struct fb_info *info)
FIRE_RING(chan); FIRE_RING(chan);
info->fbops->fb_fillrect = nv04_fbcon_fillrect;
info->fbops->fb_copyarea = nv04_fbcon_copyarea;
info->fbops->fb_imageblit = nv04_fbcon_imageblit;
return 0; return 0;
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include "nouveau_dma.h" #include "nouveau_dma.h"
#include "nouveau_fbcon.h" #include "nouveau_fbcon.h"
static void void
nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -46,7 +46,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -46,7 +46,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
FIRE_RING(chan); FIRE_RING(chan);
} }
static void void
nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -81,7 +81,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) ...@@ -81,7 +81,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
FIRE_RING(chan); FIRE_RING(chan);
} }
static void void
nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -262,9 +262,6 @@ nv50_fbcon_accel_init(struct fb_info *info) ...@@ -262,9 +262,6 @@ nv50_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys + OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys +
dev_priv->vm_vram_base); dev_priv->vm_vram_base);
info->fbops->fb_fillrect = nv50_fbcon_fillrect;
info->fbops->fb_copyarea = nv50_fbcon_copyarea;
info->fbops->fb_imageblit = nv50_fbcon_imageblit;
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment