__init bool sysfb_parse_mode(const struct screen_info *si,
                             struct simplefb_platform_data *mode)
 {
-       const struct simplefb_format *f;
        __u8 type;
+       u32 bits_per_pixel;
        unsigned int i;
 
        type = si->orig_video_isVGA;
        if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI)
                return false;
 
+       /*
+        * The meaning of depth and bpp for direct-color formats is
+        * inconsistent:
+        *
+        *  - DRM format info specifies depth as the number of color
+        *    bits; including alpha, but not including filler bits.
+        *  - Linux' EFI platform code computes lfb_depth from the
+        *    individual color channels, including the reserved bits.
+        *  - VBE 1.1 defines lfb_depth for XRGB1555 as 16, but later
+        *    versions use 15.
+        *  - On the kernel command line, 'bpp' of 32 is usually
+        *    XRGB8888 including the filler bits, but 15 is XRGB1555
+        *    not including the filler bit.
+        *
+        * It's not easily possible to fix this in struct screen_info,
+        * as this could break UAPI. The best solution is to compute
+        * bits_per_pixel here and ignore lfb_depth. In the loop below,
+        * ignore simplefb formats with alpha bits, as EFI and VESA
+        * don't specify alpha channels.
+        */
+       if (si->lfb_depth > 8) {
+               bits_per_pixel = max(max3(si->red_size + si->red_pos,
+                                         si->green_size + si->green_pos,
+                                         si->blue_size + si->blue_pos),
+                                    si->rsvd_size + si->rsvd_pos);
+       } else {
+               bits_per_pixel = si->lfb_depth;
+       }
+
        for (i = 0; i < ARRAY_SIZE(formats); ++i) {
-               f = &formats[i];
-               if (si->lfb_depth == f->bits_per_pixel &&
+               const struct simplefb_format *f = &formats[i];
+
+               if (f->transp.length)
+                       continue; /* transparent formats are unsupported by VESA/EFI */
+
+               if (bits_per_pixel == f->bits_per_pixel &&
                    si->red_size == f->red.length &&
                    si->red_pos == f->red.offset &&
                    si->green_size == f->green.length &&
                    si->green_pos == f->green.offset &&
                    si->blue_size == f->blue.length &&
-                   si->blue_pos == f->blue.offset &&
-                   si->rsvd_size == f->transp.length &&
-                   si->rsvd_pos == f->transp.offset) {
+                   si->blue_pos == f->blue.offset) {
                        mode->format = f->name;
                        mode->width = si->lfb_width;
                        mode->height = si->lfb_height;