aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
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);