On Wednesday, 2018-02-07 17:24:45 +0200, Ville Syrjala wrote: > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > Replace the switch statements that try to map between the fb format and > the fb_bitfield infromation with a single table. > > Note that this changes the behaviour of drm_fb_helper_check_var() to > return an error of the requested fb_bitfields don't match the actual > pixel format. Previously we just sort of semi-trusted some of the > bpp/depth information the user was asking for, and never actually > checked if that matches the fb pixel format. > > This prepares us to use all different rgb format channel layouts. > Basically would just need some decent way for the driver/cmdline > to select the one you want. > > I didn't think about endianness here at all. Not sure how fbdev is > supposed to deal with that stuff anyway, and I don't think we ever > reached a real concensus on the drm fourcc endianness either. So > I'll just pretend everything is little endian and ignore everything > else. > > Cc: Linus Walleij <linus.walleij@xxxxxxxxxx> > Cc: Noralf Trønnes <noralf@xxxxxxxxxxx> > Cc: Ilia Mirkin <imirkin@xxxxxxxxxxxx> > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/drm_fb_helper.c | 280 +++++++++++++++++++++++----------------- > 1 file changed, 163 insertions(+), 117 deletions(-) > > diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c > index 035784ddd133..0c906e3a5bb1 100644 > --- a/drivers/gpu/drm/drm_fb_helper.c > +++ b/drivers/gpu/drm/drm_fb_helper.c > @@ -40,6 +40,7 @@ > #include <drm/drm_crtc_helper.h> > #include <drm/drm_atomic.h> > #include <drm/drm_atomic_helper.h> > +#include <drm/drm_fourcc.h> > > #include "drm_crtc_internal.h" > #include "drm_crtc_helper_internal.h" > @@ -1561,6 +1562,147 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, > } > EXPORT_SYMBOL(drm_fb_helper_ioctl); > > +#define FB_FORMAT_C(c) { \ > + .format = DRM_FORMAT_C##c, \ > + .blue = { .length = (c), }, \ > + .green = { .length = (c), }, \ > + .red = { .length = (c), }, \ > +} > +#define FB_FORMAT_RGB(r, g, b) { \ > + .format = DRM_FORMAT_RGB##r##g##b, \ > + .blue = { .length = (b), .offset = 0, }, \ > + .green = { .length = (g), .offset = (b), }, \ > + .red = { .length = (r), .offset = (b)+(g), }, \ > +} > +#define FB_FORMAT_BGR(b, g, r) { \ > + .format = DRM_FORMAT_BGR##b##g##r, \ > + .red = { .length = (r), .offset = 0, }, \ > + .green = { .length = (g), .offset = (r), }, \ > + .blue = { .length = (b), .offset = (r)+(g), }, \ > +} > +#define FB_FORMAT_XRGB(x, r, g, b) { \ > + .format = DRM_FORMAT_XRGB##x##r##g##b, \ > + .blue = { .length = (b), .offset = 0, }, \ > + .green = { .length = (g), .offset = (b), }, \ > + .red = { .length = (r), .offset = (b)+(g), }, \ > +} > +#define FB_FORMAT_XBGR(x, b, g, r) { \ > + .format = DRM_FORMAT_XBGR##x##b##g##r, \ > + .red = { .length = (r), .offset = 0, }, \ > + .green = { .length = (g), .offset = (r), }, \ > + .blue = { .length = (b), .offset = (r)+(g), }, \ > +} > +#define FB_FORMAT_RGBX(r, g, b, x) { \ > + .format = DRM_FORMAT_RGBX##r##g##b##x, \ > + .blue = { .length = (b), .offset = (x), }, \ > + .green = { .length = (g), .offset = (x)+(b), }, \ > + .red = { .length = (r), .offset = (x)+(b)+(g), }, \ > +} > +#define FB_FORMAT_BGRX(b, g, r, x) { \ > + .format = DRM_FORMAT_BGRX##b##g##r##x, \ > + .red = { .length = (r), .offset = (x), }, \ > + .green = { .length = (g), .offset = (x)+(r), }, \ > + .blue = { .length = (b), .offset = (x)+(r)+(g), }, \ > +} > +#define FB_FORMAT_ARGB(a, r, g, b) { \ > + .format = DRM_FORMAT_ARGB##a##r##g##b, \ > + .blue = { .length = (b), .offset = 0, }, \ > + .green = { .length = (g), .offset = (b), }, \ > + .red = { .length = (r), .offset = (b)+(g), }, \ > + .transp = { .length = (a), .offset = (b)+(g)+(r), }, \ > +} > +#define FB_FORMAT_ABGR(a, b, g, r) { \ > + .format = DRM_FORMAT_ABGR##a##b##g##r, \ > + .red = { .length = (r), .offset = 0, }, \ > + .green = { .length = (g), .offset = (r), }, \ > + .blue = { .length = (b), .offset = (r)+(g), },\ > + .transp = { .length = (a), .offset = (r)+(g)+(b), }, \ > +} > +#define FB_FORMAT_RGBA(r, g, b, a) { \ > + .format = DRM_FORMAT_RGBA##r##g##b##a, \ > + .transp = { .length = (a), .offset = 0, }, \ > + .blue = { .length = (b), .offset = (a), }, \ > + .green = { .length = (g), .offset = (a)+(b), }, \ > + .red = { .length = (r), .offset = (a)+(b)+(g), }, \ > +} > +#define FB_FORMAT_BGRA(b, g, r, a) { \ > + .format = DRM_FORMAT_BGRA##b##g##r##a, \ > + .transp = { .length = (a), .offset = 0, }, \ > + .red = { .length = (r), .offset = (a), }, \ > + .green = { .length = (g), .offset = (a)+(r), }, \ > + .blue = { .length = (b), .offset = (a)+(r)+(g), }, \ > +} > + > +struct drm_fb_helper_format { > + u32 format; > + struct fb_bitfield red, green, blue, transp; > +}; > + > +static const struct drm_fb_helper_format fb_formats[] = { > + FB_FORMAT_C(8), > + > + FB_FORMAT_XRGB(1, 5, 5, 5), > + FB_FORMAT_XBGR(1, 5, 5, 5), > + FB_FORMAT_RGBX(5, 5, 5, 1), > + FB_FORMAT_BGRX(5, 5, 5, 1), > + > + FB_FORMAT_ARGB(1, 5, 5, 5), > + FB_FORMAT_ABGR(1, 5, 5, 5), > + FB_FORMAT_RGBA(5, 5, 5, 1), > + FB_FORMAT_BGRA(5, 5, 5, 1), > + > + FB_FORMAT_RGB(5, 6, 5), > + FB_FORMAT_BGR(5, 6, 5), > + > + FB_FORMAT_RGB(8, 8, 8), > + FB_FORMAT_BGR(8, 8, 8), > + > + FB_FORMAT_XRGB(8, 8, 8, 8), > + FB_FORMAT_XBGR(8, 8, 8, 8), > + FB_FORMAT_RGBX(8, 8, 8, 8), > + FB_FORMAT_BGRX(8, 8, 8, 8), > + > + FB_FORMAT_ARGB(8, 8, 8, 8), > + FB_FORMAT_ABGR(8, 8, 8, 8), > + FB_FORMAT_RGBA(8, 8, 8, 8), > + FB_FORMAT_BGRA(8, 8, 8, 8), > + > + FB_FORMAT_XRGB(2, 10, 10, 10), > + FB_FORMAT_XBGR(2, 10, 10, 10), > + FB_FORMAT_RGBX(10, 10, 10, 2), > + FB_FORMAT_BGRX(10, 10, 10, 2), > + > + FB_FORMAT_ARGB(2, 10, 10, 10), > + FB_FORMAT_ABGR(2, 10, 10, 10), > + FB_FORMAT_RGBA(10, 10, 10, 2), > + FB_FORMAT_BGRA(10, 10, 10, 2), > +}; > + > +static bool fb_format_match(const struct fb_var_screeninfo *var, > + const struct drm_fb_helper_format *fb_format) > +{ > + return !memcmp(&var->red, &fb_format->red, > + sizeof(var->red)) && > + !memcmp(&var->green, &fb_format->green, > + sizeof(var->green)) && > + !memcmp(&var->blue, &fb_format->blue, > + sizeof(var->blue)) && > + !memcmp(&var->transp, &fb_format->transp, > + sizeof(var->transp)); This relies on the padding being initialised to 0 everywhere, which I'm not sure is true even with the static array here, but feels rather fragile regardless... > +} > + > +static const struct drm_fb_helper_format *fb_format_lookup(u32 format) > +{ > + int i; > + > + for (i = 0; i < ARRAY_SIZE(fb_formats); i++) { > + if (fb_formats[i].format == format) > + return &fb_formats[i]; > + } > + > + return NULL; > +} > + > /** > * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var > * @var: screeninfo to check > @@ -1569,9 +1711,9 @@ EXPORT_SYMBOL(drm_fb_helper_ioctl); > int drm_fb_helper_check_var(struct fb_var_screeninfo *var, > struct fb_info *info) > { > + const struct drm_fb_helper_format *fb_format; > struct drm_fb_helper *fb_helper = info->par; > struct drm_framebuffer *fb = fb_helper->fb; > - int depth; > > if (var->pixclock != 0 || in_dbg_master()) > return -EINVAL; > @@ -1591,72 +1733,20 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, > return -EINVAL; > } > > - switch (var->bits_per_pixel) { > - case 16: > - depth = (var->green.length == 6) ? 16 : 15; > - break; > - case 32: > - depth = (var->transp.length > 0) ? 32 : 24; > - break; > - default: > - depth = var->bits_per_pixel; > - break; > - } > + /* > + * FIXME just store the fb_bitfields for the > + * chosen fb format somewhere to avoid the lookup? > + * Or sort the table and use bsearch()? > + */ > + fb_format = fb_format_lookup(fb->format->format); > + if (WARN_ON(!fb_format)) > + return -EINVAL; > > - switch (depth) { > - case 8: > - var->red.offset = 0; > - var->green.offset = 0; > - var->blue.offset = 0; > - var->red.length = 8; > - var->green.length = 8; > - var->blue.length = 8; > - var->transp.length = 0; > - var->transp.offset = 0; > - break; > - case 15: > - var->red.offset = 10; > - var->green.offset = 5; > - var->blue.offset = 0; > - var->red.length = 5; > - var->green.length = 5; > - var->blue.length = 5; > - var->transp.length = 1; > - var->transp.offset = 15; > - break; > - case 16: > - var->red.offset = 11; > - var->green.offset = 5; > - var->blue.offset = 0; > - var->red.length = 5; > - var->green.length = 6; > - var->blue.length = 5; > - var->transp.length = 0; > - var->transp.offset = 0; > - break; > - case 24: > - var->red.offset = 16; > - var->green.offset = 8; > - var->blue.offset = 0; > - var->red.length = 8; > - var->green.length = 8; > - var->blue.length = 8; > - var->transp.length = 0; > - var->transp.offset = 0; > - break; > - case 32: > - var->red.offset = 16; > - var->green.offset = 8; > - var->blue.offset = 0; > - var->red.length = 8; > - var->green.length = 8; > - var->blue.length = 8; > - var->transp.length = 8; > - var->transp.offset = 24; > - break; > - default: > + if (!fb_format_match(var, fb_format)) { > + DRM_DEBUG_KMS("var screeninfo does not match pixel format\n"); > return -EINVAL; > } > + > return 0; > } > EXPORT_SYMBOL(drm_fb_helper_check_var); > @@ -1948,6 +2038,7 @@ EXPORT_SYMBOL(drm_fb_helper_fill_fix); > void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, > uint32_t fb_width, uint32_t fb_height) > { > + const struct drm_fb_helper_format *fb_format; > struct drm_framebuffer *fb = fb_helper->fb; > > info->pseudo_palette = fb_helper->pseudo_palette; > @@ -1959,59 +2050,14 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe > info->var.yoffset = 0; > info->var.activate = FB_ACTIVATE_NOW; > > - switch (fb->format->depth) { > - case 8: > - info->var.red.offset = 0; > - info->var.green.offset = 0; > - info->var.blue.offset = 0; > - info->var.red.length = 8; /* 8bit DAC */ > - info->var.green.length = 8; > - info->var.blue.length = 8; > - info->var.transp.offset = 0; > - info->var.transp.length = 0; > - break; > - case 15: > - info->var.red.offset = 10; > - info->var.green.offset = 5; > - info->var.blue.offset = 0; > - info->var.red.length = 5; > - info->var.green.length = 5; > - info->var.blue.length = 5; > - info->var.transp.offset = 15; > - info->var.transp.length = 1; > - break; > - case 16: > - info->var.red.offset = 11; > - info->var.green.offset = 5; > - info->var.blue.offset = 0; > - info->var.red.length = 5; > - info->var.green.length = 6; > - info->var.blue.length = 5; > - info->var.transp.offset = 0; > - break; > - case 24: > - info->var.red.offset = 16; > - info->var.green.offset = 8; > - info->var.blue.offset = 0; > - info->var.red.length = 8; > - info->var.green.length = 8; > - info->var.blue.length = 8; > - info->var.transp.offset = 0; > - info->var.transp.length = 0; > - break; > - case 32: > - info->var.red.offset = 16; > - info->var.green.offset = 8; > - info->var.blue.offset = 0; > - info->var.red.length = 8; > - info->var.green.length = 8; > - info->var.blue.length = 8; > - info->var.transp.offset = 24; > - info->var.transp.length = 8; > - break; > - default: > - break; > - } > + fb_format = fb_format_lookup(fb->format->format); > + if (WARN_ON(!fb_format)) > + return; > + > + info->var.red = fb_format->red; > + info->var.green = fb_format->green; > + info->var.blue = fb_format->blue; > + info->var.transp = fb_format->transp; > > info->var.xres = fb_width; > info->var.yres = fb_height; > -- > 2.13.6 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel