aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-10-05 23:54:01 -0400
committerDave Airlie <airlied@redhat.com>2009-10-05 23:54:01 -0400
commitb8c00ac5b50b54491657f8b6740db1df50149944 (patch)
treeb4cfbc0dbb5ba063bcc933d7339504b80dc5c61c /drivers/gpu
parent068143d38804825d59d951a192cfadd2e22f457d (diff)
drm/fb: add more correct 8/16/24/32 bpp fb support.
The previous patches had some unwanted side effects, I've fixed the lack of 32bpp working, and fixed up 16bpp so it should also work. this also adds the interface to allow the driver to set a preferred console depth so for example low memory rn50 can set it to 8bpp. It also catches 24bpp on cards that can't do it and forces 32bpp. Tested on r100/r600/i945. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c95
-rw-r--r--drivers/gpu/drm/i915/intel_display.c10
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c39
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h2
7 files changed, 107 insertions, 56 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 3746bd2f0f0..23dc9c115fd 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -454,6 +454,54 @@ out_free:
454} 454}
455EXPORT_SYMBOL(drm_fb_helper_init_crtc_count); 455EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
456 456
457static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
458 u16 blue, u16 regno, struct fb_info *info)
459{
460 struct drm_fb_helper *fb_helper = info->par;
461 struct drm_framebuffer *fb = fb_helper->fb;
462 int pindex;
463
464 pindex = regno;
465
466 if (fb->bits_per_pixel == 16) {
467 pindex = regno << 3;
468
469 if (fb->depth == 16 && regno > 63)
470 return;
471 if (fb->depth == 15 && regno > 31)
472 return;
473
474 if (fb->depth == 16) {
475 u16 r, g, b;
476 int i;
477 if (regno < 32) {
478 for (i = 0; i < 8; i++)
479 fb_helper->funcs->gamma_set(crtc, red,
480 green, blue, pindex + i);
481 }
482
483 fb_helper->funcs->gamma_get(crtc, &r,
484 &g, &b,
485 pindex >> 1);
486
487 for (i = 0; i < 4; i++)
488 fb_helper->funcs->gamma_set(crtc, r,
489 green, b,
490 (pindex >> 1) + i);
491 }
492 }
493
494 if (fb->depth != 16)
495 fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
496
497 if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
498 ((u32 *) fb->pseudo_palette)[regno] =
499 (regno << info->var.red.offset) |
500 (regno << info->var.green.offset) |
501 (regno << info->var.blue.offset);
502 }
503}
504
457int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) 505int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
458{ 506{
459 struct drm_fb_helper *fb_helper = info->par; 507 struct drm_fb_helper *fb_helper = info->par;
@@ -488,7 +536,7 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
488 if (transp) 536 if (transp)
489 htransp = *transp++; 537 htransp = *transp++;
490 538
491 fb_helper->funcs->gamma_set(crtc, hred, hgreen, hblue, start++); 539 setcolreg(crtc, hred, hgreen, hblue, start++, info);
492 } 540 }
493 crtc_funcs->load_lut(crtc); 541 crtc_funcs->load_lut(crtc);
494 } 542 }
@@ -508,9 +556,11 @@ int drm_fb_helper_setcolreg(unsigned regno,
508 struct drm_crtc *crtc; 556 struct drm_crtc *crtc;
509 int i; 557 int i;
510 558
511 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 559 if (regno > 255)
512 struct drm_framebuffer *fb = fb_helper->fb; 560 return 1;
513 561
562 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
563 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
514 for (i = 0; i < fb_helper->crtc_count; i++) { 564 for (i = 0; i < fb_helper->crtc_count; i++) {
515 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) 565 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
516 break; 566 break;
@@ -518,36 +568,9 @@ int drm_fb_helper_setcolreg(unsigned regno,
518 if (i == fb_helper->crtc_count) 568 if (i == fb_helper->crtc_count)
519 continue; 569 continue;
520 570
521 if (regno > 255)
522 return 1;
523
524 if (fb->depth == 8) {
525 fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
526 return 0;
527 }
528 571
529 if (regno < 16) { 572 setcolreg(crtc, red, green, blue, regno, info);
530 u32 *pal = fb->pseudo_palette; 573 crtc_funcs->load_lut(crtc);
531 switch (fb->depth) {
532 case 15:
533 pal[regno] = ((red & 0xf800) >> 1) |
534 ((green & 0xf800) >> 6) |
535 ((blue & 0xf800) >> 11);
536 break;
537 case 16:
538 pal[regno] = (red & 0xf800) |
539 ((green & 0xfc00) >> 5) |
540 ((blue & 0xf800) >> 11);
541 break;
542 case 24:
543 case 32:
544 pal[regno] =
545 (((red >> 8) & 0xff) << info->var.red.offset) |
546 (((green >> 8) & 0xff) << info->var.green.offset) |
547 (((blue >> 8) & 0xff) << info->var.blue.offset);
548 break;
549 }
550 }
551 } 574 }
552 return 0; 575 return 0;
553} 576}
@@ -717,6 +740,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
717EXPORT_SYMBOL(drm_fb_helper_pan_display); 740EXPORT_SYMBOL(drm_fb_helper_pan_display);
718 741
719int drm_fb_helper_single_fb_probe(struct drm_device *dev, 742int drm_fb_helper_single_fb_probe(struct drm_device *dev,
743 int preferred_bpp,
720 int (*fb_create)(struct drm_device *dev, 744 int (*fb_create)(struct drm_device *dev,
721 uint32_t fb_width, 745 uint32_t fb_width,
722 uint32_t fb_height, 746 uint32_t fb_height,
@@ -739,6 +763,11 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
739 struct drm_fb_helper *fb_helper; 763 struct drm_fb_helper *fb_helper;
740 uint32_t surface_depth = 24, surface_bpp = 32; 764 uint32_t surface_depth = 24, surface_bpp = 32;
741 765
766 /* if driver picks 8 or 16 by default use that
767 for both depth/bpp */
768 if (preferred_bpp != surface_bpp) {
769 surface_depth = surface_bpp = preferred_bpp;
770 }
742 /* first up get a count of crtcs now in use and new min/maxes width/heights */ 771 /* first up get a count of crtcs now in use and new min/maxes width/heights */
743 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 772 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
744 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; 773 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
@@ -899,7 +928,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
899{ 928{
900 info->fix.type = FB_TYPE_PACKED_PIXELS; 929 info->fix.type = FB_TYPE_PACKED_PIXELS;
901 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : 930 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
902 FB_VISUAL_TRUECOLOR; 931 FB_VISUAL_DIRECTCOLOR;
903 info->fix.type_aux = 0; 932 info->fix.type_aux = 0;
904 info->fix.xpanstep = 1; /* doing it in hw */ 933 info->fix.xpanstep = 1; /* doing it in hw */
905 info->fix.ypanstep = 1; /* doing it in hw */ 934 info->fix.ypanstep = 1; /* doing it in hw */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a840cb1bd36..893903962e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2922,6 +2922,16 @@ void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
2922 intel_crtc->lut_b[regno] = blue >> 8; 2922 intel_crtc->lut_b[regno] = blue >> 8;
2923} 2923}
2924 2924
2925void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
2926 u16 *blue, int regno)
2927{
2928 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2929
2930 *red = intel_crtc->lut_r[regno] << 8;
2931 *green = intel_crtc->lut_g[regno] << 8;
2932 *blue = intel_crtc->lut_b[regno] << 8;
2933}
2934
2925static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 2935static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
2926 u16 *blue, uint32_t size) 2936 u16 *blue, uint32_t size)
2927{ 2937{
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b9e47f1e1cc..aa96b522135 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -173,6 +173,8 @@ extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc);
173extern void intelfb_restore(void); 173extern void intelfb_restore(void);
174extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, 174extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
175 u16 blue, int regno); 175 u16 blue, int regno);
176extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
177 u16 *blue, int regno);
176 178
177extern int intel_framebuffer_create(struct drm_device *dev, 179extern int intel_framebuffer_create(struct drm_device *dev,
178 struct drm_mode_fb_cmd *mode_cmd, 180 struct drm_mode_fb_cmd *mode_cmd,
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 3ee8db1fbcd..2b0fe54cd92 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -65,6 +65,7 @@ static struct fb_ops intelfb_ops = {
65 65
66static struct drm_fb_helper_funcs intel_fb_helper_funcs = { 66static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
67 .gamma_set = intel_crtc_fb_gamma_set, 67 .gamma_set = intel_crtc_fb_gamma_set,
68 .gamma_get = intel_crtc_fb_gamma_get,
68}; 69};
69 70
70 71
@@ -124,6 +125,10 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
124 struct device *device = &dev->pdev->dev; 125 struct device *device = &dev->pdev->dev;
125 int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1; 126 int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1;
126 127
128 /* we don't do packed 24bpp */
129 if (surface_bpp == 24)
130 surface_bpp = 32;
131
127 mode_cmd.width = surface_width; 132 mode_cmd.width = surface_width;
128 mode_cmd.height = surface_height; 133 mode_cmd.height = surface_height;
129 134
@@ -245,7 +250,7 @@ int intelfb_probe(struct drm_device *dev)
245 int ret; 250 int ret;
246 251
247 DRM_DEBUG("\n"); 252 DRM_DEBUG("\n");
248 ret = drm_fb_helper_single_fb_probe(dev, intelfb_create); 253 ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create);
249 return ret; 254 return ret;
250} 255}
251EXPORT_SYMBOL(intelfb_probe); 256EXPORT_SYMBOL(intelfb_probe);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 44cfcfdf135..3655d91993a 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -106,24 +106,33 @@ void radeon_crtc_load_lut(struct drm_crtc *crtc)
106 legacy_crtc_load_lut(crtc); 106 legacy_crtc_load_lut(crtc);
107} 107}
108 108
109/** Sets the color ramps on behalf of RandR */ 109/** Sets the color ramps on behalf of fbcon */
110void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, 110void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
111 u16 blue, int regno) 111 u16 blue, int regno)
112{ 112{
113 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 113 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
114 114
115 if (regno == 0)
116 DRM_DEBUG("gamma set %d\n", radeon_crtc->crtc_id);
117 radeon_crtc->lut_r[regno] = red >> 6; 115 radeon_crtc->lut_r[regno] = red >> 6;
118 radeon_crtc->lut_g[regno] = green >> 6; 116 radeon_crtc->lut_g[regno] = green >> 6;
119 radeon_crtc->lut_b[regno] = blue >> 6; 117 radeon_crtc->lut_b[regno] = blue >> 6;
120} 118}
121 119
120/** Gets the color ramps on behalf of fbcon */
121void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
122 u16 *blue, int regno)
123{
124 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
125
126 *red = radeon_crtc->lut_r[regno] << 6;
127 *green = radeon_crtc->lut_g[regno] << 6;
128 *blue = radeon_crtc->lut_b[regno] << 6;
129}
130
122static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 131static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
123 u16 *blue, uint32_t size) 132 u16 *blue, uint32_t size)
124{ 133{
125 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 134 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
126 int i, j; 135 int i;
127 136
128 if (size != 256) { 137 if (size != 256) {
129 return; 138 return;
@@ -132,23 +141,11 @@ static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
132 return; 141 return;
133 } 142 }
134 143
135 if (crtc->fb->depth == 16) { 144 /* userspace palettes are always correct as is */
136 for (i = 0; i < 64; i++) { 145 for (i = 0; i < 256; i++) {
137 if (i <= 31) { 146 radeon_crtc->lut_r[i] = red[i] >> 6;
138 for (j = 0; j < 8; j++) { 147 radeon_crtc->lut_g[i] = green[i] >> 6;
139 radeon_crtc->lut_r[i * 8 + j] = red[i] >> 6; 148 radeon_crtc->lut_b[i] = blue[i] >> 6;
140 radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 6;
141 }
142 }
143 for (j = 0; j < 4; j++)
144 radeon_crtc->lut_g[i * 4 + j] = green[i] >> 6;
145 }
146 } else {
147 for (i = 0; i < 256; i++) {
148 radeon_crtc->lut_r[i] = red[i] >> 6;
149 radeon_crtc->lut_g[i] = green[i] >> 6;
150 radeon_crtc->lut_b[i] = blue[i] >> 6;
151 }
152 } 149 }
153 150
154 radeon_crtc_load_lut(crtc); 151 radeon_crtc_load_lut(crtc);
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index c32f44096fe..b38c4c8e2c6 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -124,6 +124,7 @@ static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bo
124 124
125static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { 125static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
126 .gamma_set = radeon_crtc_fb_gamma_set, 126 .gamma_set = radeon_crtc_fb_gamma_set,
127 .gamma_get = radeon_crtc_fb_gamma_get,
127}; 128};
128 129
129int radeonfb_create(struct drm_device *dev, 130int radeonfb_create(struct drm_device *dev,
@@ -151,6 +152,11 @@ int radeonfb_create(struct drm_device *dev,
151 152
152 mode_cmd.width = surface_width; 153 mode_cmd.width = surface_width;
153 mode_cmd.height = surface_height; 154 mode_cmd.height = surface_height;
155
156 /* avivo can't scanout real 24bpp */
157 if ((surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
158 surface_bpp = 32;
159
154 mode_cmd.bpp = surface_bpp; 160 mode_cmd.bpp = surface_bpp;
155 /* need to align pitch with crtc limits */ 161 /* need to align pitch with crtc limits */
156 mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); 162 mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
@@ -315,7 +321,7 @@ int radeon_parse_options(char *options)
315 321
316int radeonfb_probe(struct drm_device *dev) 322int radeonfb_probe(struct drm_device *dev)
317{ 323{
318 return drm_fb_helper_single_fb_probe(dev, &radeonfb_create); 324 return drm_fb_helper_single_fb_probe(dev, 32, &radeonfb_create);
319} 325}
320 326
321int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) 327int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 570a58729da..e61226817cc 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -407,6 +407,8 @@ extern void
407radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on); 407radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on);
408extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, 408extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
409 u16 blue, int regno); 409 u16 blue, int regno);
410extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
411 u16 *blue, int regno);
410struct drm_framebuffer *radeon_framebuffer_create(struct drm_device *dev, 412struct drm_framebuffer *radeon_framebuffer_create(struct drm_device *dev,
411 struct drm_mode_fb_cmd *mode_cmd, 413 struct drm_mode_fb_cmd *mode_cmd,
412 struct drm_gem_object *obj); 414 struct drm_gem_object *obj);