summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--include/drm/drm_fb_helper.h3
8 files changed, 110 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:
}
EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
+static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
+ u16 blue, u16 regno, struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ int pindex;
+
+ pindex = regno;
+
+ if (fb->bits_per_pixel == 16) {
+ pindex = regno << 3;
+
+ if (fb->depth == 16 && regno > 63)
+ return;
+ if (fb->depth == 15 && regno > 31)
+ return;
+
+ if (fb->depth == 16) {
+ u16 r, g, b;
+ int i;
+ if (regno < 32) {
+ for (i = 0; i < 8; i++)
+ fb_helper->funcs->gamma_set(crtc, red,
+ green, blue, pindex + i);
+ }
+
+ fb_helper->funcs->gamma_get(crtc, &r,
+ &g, &b,
+ pindex >> 1);
+
+ for (i = 0; i < 4; i++)
+ fb_helper->funcs->gamma_set(crtc, r,
+ green, b,
+ (pindex >> 1) + i);
+ }
+ }
+
+ if (fb->depth != 16)
+ fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
+
+ if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ ((u32 *) fb->pseudo_palette)[regno] =
+ (regno << info->var.red.offset) |
+ (regno << info->var.green.offset) |
+ (regno << info->var.blue.offset);
+ }
+}
+
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
{
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)
if (transp)
htransp = *transp++;
- fb_helper->funcs->gamma_set(crtc, hred, hgreen, hblue, start++);
+ setcolreg(crtc, hred, hgreen, hblue, start++, info);
}
crtc_funcs->load_lut(crtc);
}
@@ -508,9 +556,11 @@ int drm_fb_helper_setcolreg(unsigned regno,
struct drm_crtc *crtc;
int i;
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct drm_framebuffer *fb = fb_helper->fb;
+ if (regno > 255)
+ return 1;
+ 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 < fb_helper->crtc_count; i++) {
if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
break;
@@ -518,36 +568,9 @@ int drm_fb_helper_setcolreg(unsigned regno,
if (i == fb_helper->crtc_count)
continue;
- if (regno > 255)
- return 1;
-
- if (fb->depth == 8) {
- fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
- return 0;
- }
- if (regno < 16) {
- u32 *pal = fb->pseudo_palette;
- switch (fb->depth) {
- case 15:
- pal[regno] = ((red & 0xf800) >> 1) |
- ((green & 0xf800) >> 6) |
- ((blue & 0xf800) >> 11);
- break;
- case 16:
- pal[regno] = (red & 0xf800) |
- ((green & 0xfc00) >> 5) |
- ((blue & 0xf800) >> 11);
- break;
- case 24:
- case 32:
- pal[regno] =
- (((red >> 8) & 0xff) << info->var.red.offset) |
- (((green >> 8) & 0xff) << info->var.green.offset) |
- (((blue >> 8) & 0xff) << info->var.blue.offset);
- break;
- }
- }
+ setcolreg(crtc, red, green, blue, regno, info);
+ crtc_funcs->load_lut(crtc);
}
return 0;
}
@@ -717,6 +740,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
EXPORT_SYMBOL(drm_fb_helper_pan_display);
int drm_fb_helper_single_fb_probe(struct drm_device *dev,
+ int preferred_bpp,
int (*fb_create)(struct drm_device *dev,
uint32_t fb_width,
uint32_t fb_height,
@@ -739,6 +763,11 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
struct drm_fb_helper *fb_helper;
uint32_t surface_depth = 24, surface_bpp = 32;
+ /* if driver picks 8 or 16 by default use that
+ for both depth/bpp */
+ if (preferred_bpp != surface_bpp) {
+ surface_depth = surface_bpp = preferred_bpp;
+ }
/* first up get a count of crtcs now in use and new min/maxes width/heights */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
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,
{
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
- FB_VISUAL_TRUECOLOR;
+ FB_VISUAL_DIRECTCOLOR;
info->fix.type_aux = 0;
info->fix.xpanstep = 1; /* doing it in hw */
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,
intel_crtc->lut_b[regno] = blue >> 8;
}
+void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, int regno)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ *red = intel_crtc->lut_r[regno] << 8;
+ *green = intel_crtc->lut_g[regno] << 8;
+ *blue = intel_crtc->lut_b[regno] << 8;
+}
+
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
{
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);
extern void intelfb_restore(void);
extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno);
+extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, int regno);
extern int intel_framebuffer_create(struct drm_device *dev,
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 = {
static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.gamma_set = intel_crtc_fb_gamma_set,
+ .gamma_get = intel_crtc_fb_gamma_get,
};
@@ -124,6 +125,10 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
struct device *device = &dev->pdev->dev;
int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+ /* we don't do packed 24bpp */
+ if (surface_bpp == 24)
+ surface_bpp = 32;
+
mode_cmd.width = surface_width;
mode_cmd.height = surface_height;
@@ -245,7 +250,7 @@ int intelfb_probe(struct drm_device *dev)
int ret;
DRM_DEBUG("\n");
- ret = drm_fb_helper_single_fb_probe(dev, intelfb_create);
+ ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create);
return ret;
}
EXPORT_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)
legacy_crtc_load_lut(crtc);
}
-/** Sets the color ramps on behalf of RandR */
+/** Sets the color ramps on behalf of fbcon */
void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
- if (regno == 0)
- DRM_DEBUG("gamma set %d\n", radeon_crtc->crtc_id);
radeon_crtc->lut_r[regno] = red >> 6;
radeon_crtc->lut_g[regno] = green >> 6;
radeon_crtc->lut_b[regno] = blue >> 6;
}
+/** Gets the color ramps on behalf of fbcon */
+void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, int regno)
+{
+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+ *red = radeon_crtc->lut_r[regno] << 6;
+ *green = radeon_crtc->lut_g[regno] << 6;
+ *blue = radeon_crtc->lut_b[regno] << 6;
+}
+
static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
- int i, j;
+ int i;
if (size != 256) {
return;
@@ -132,23 +141,11 @@ static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
return;
}
- if (crtc->fb->depth == 16) {
- for (i = 0; i < 64; i++) {
- if (i <= 31) {
- for (j = 0; j < 8; j++) {
- radeon_crtc->lut_r[i * 8 + j] = red[i] >> 6;
- radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 6;
- }
- }
- for (j = 0; j < 4; j++)
- radeon_crtc->lut_g[i * 4 + j] = green[i] >> 6;
- }
- } else {
- for (i = 0; i < 256; i++) {
- radeon_crtc->lut_r[i] = red[i] >> 6;
- radeon_crtc->lut_g[i] = green[i] >> 6;
- radeon_crtc->lut_b[i] = blue[i] >> 6;
- }
+ /* userspace palettes are always correct as is */
+ for (i = 0; i < 256; i++) {
+ radeon_crtc->lut_r[i] = red[i] >> 6;
+ radeon_crtc->lut_g[i] = green[i] >> 6;
+ radeon_crtc->lut_b[i] = blue[i] >> 6;
}
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
static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
.gamma_set = radeon_crtc_fb_gamma_set,
+ .gamma_get = radeon_crtc_fb_gamma_get,
};
int radeonfb_create(struct drm_device *dev,
@@ -151,6 +152,11 @@ int radeonfb_create(struct drm_device *dev,
mode_cmd.width = surface_width;
mode_cmd.height = surface_height;
+
+ /* avivo can't scanout real 24bpp */
+ if ((surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
+ surface_bpp = 32;
+
mode_cmd.bpp = surface_bpp;
/* need to align pitch with crtc limits */
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)
int radeonfb_probe(struct drm_device *dev)
{
- return drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
+ return drm_fb_helper_single_fb_probe(dev, 32, &radeonfb_create);
}
int 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
radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on);
extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno);
+extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, int regno);
struct drm_framebuffer *radeon_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd *mode_cmd,
struct drm_gem_object *obj);
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index f1ed08559fc..58c892a2cbf 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -39,6 +39,8 @@ struct drm_fb_helper_crtc {
struct drm_fb_helper_funcs {
void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno);
+ void (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, int regno);
};
/* mode specified on the command line */
@@ -71,6 +73,7 @@ struct drm_fb_helper {
};
int drm_fb_helper_single_fb_probe(struct drm_device *dev,
+ int preferred_bpp,
int (*fb_create)(struct drm_device *dev,
uint32_t fb_width,
uint32_t fb_height,