|
@@ -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 */
|