}
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono);
 
+static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc)
+{
+       /* only handle formats with depth != 0 and alpha channel */
+       switch (fourcc) {
+       case DRM_FORMAT_ARGB1555:
+               return DRM_FORMAT_XRGB1555;
+       case DRM_FORMAT_ABGR1555:
+               return DRM_FORMAT_XBGR1555;
+       case DRM_FORMAT_RGBA5551:
+               return DRM_FORMAT_RGBX5551;
+       case DRM_FORMAT_BGRA5551:
+               return DRM_FORMAT_BGRX5551;
+       case DRM_FORMAT_ARGB8888:
+               return DRM_FORMAT_XRGB8888;
+       case DRM_FORMAT_ABGR8888:
+               return DRM_FORMAT_XBGR8888;
+       case DRM_FORMAT_RGBA8888:
+               return DRM_FORMAT_RGBX8888;
+       case DRM_FORMAT_BGRA8888:
+               return DRM_FORMAT_BGRX8888;
+       case DRM_FORMAT_ARGB2101010:
+               return DRM_FORMAT_XRGB2101010;
+       case DRM_FORMAT_ABGR2101010:
+               return DRM_FORMAT_XBGR2101010;
+       case DRM_FORMAT_RGBA1010102:
+               return DRM_FORMAT_RGBX1010102;
+       case DRM_FORMAT_BGRA1010102:
+               return DRM_FORMAT_BGRX1010102;
+       }
+
+       return fourcc;
+}
+
 static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc)
 {
        const uint32_t *fourccs_end = fourccs + nfourccs;
        return false;
 }
 
-static const uint32_t conv_from_xrgb8888[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_ARGB8888,
-       DRM_FORMAT_XRGB2101010,
-       DRM_FORMAT_ARGB2101010,
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_RGB888,
-};
-
-static const uint32_t conv_from_rgb565_888[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_ARGB8888,
-};
-
-static bool is_conversion_supported(uint32_t from, uint32_t to)
-{
-       switch (from) {
-       case DRM_FORMAT_XRGB8888:
-       case DRM_FORMAT_ARGB8888:
-               return is_listed_fourcc(conv_from_xrgb8888, ARRAY_SIZE(conv_from_xrgb8888), to);
-       case DRM_FORMAT_RGB565:
-       case DRM_FORMAT_RGB888:
-               return is_listed_fourcc(conv_from_rgb565_888, ARRAY_SIZE(conv_from_rgb565_888), to);
-       case DRM_FORMAT_XRGB2101010:
-               return to == DRM_FORMAT_ARGB2101010;
-       case DRM_FORMAT_ARGB2101010:
-               return to == DRM_FORMAT_XRGB2101010;
-       default:
-               return false;
-       }
-}
-
 /**
  * drm_fb_build_fourcc_list - Filters a list of supported color formats against
  *                            the device's native formats
  * @dev: DRM device
  * @native_fourccs: 4CC codes of natively supported color formats
  * @native_nfourccs: The number of entries in @native_fourccs
- * @driver_fourccs: 4CC codes of all driver-supported color formats
- * @driver_nfourccs: The number of entries in @driver_fourccs
  * @fourccs_out: Returns 4CC codes of supported color formats
  * @nfourccs_out: The number of available entries in @fourccs_out
  *
  * This function create a list of supported color format from natively
- * supported formats and the emulated formats.
+ * supported formats and additional emulated formats.
  * At a minimum, most userspace programs expect at least support for
  * XRGB8888 on the primary plane. Devices that have to emulate the
  * format, and possibly others, can use drm_fb_build_fourcc_list() to
  * create a list of supported color formats. The returned list can
  * be handed over to drm_universal_plane_init() et al. Native formats
- * will go before emulated formats. Other heuristics might be applied
+ * will go before emulated formats. Native formats with alpha channel
+ * will be replaced by such without, as primary planes usually don't
+ * support alpha. Other heuristics might be applied
  * to optimize the order. Formats near the beginning of the list are
- * usually preferred over formats near the end of the list. Formats
- * without conversion helpers will be skipped. New drivers should only
- * pass in XRGB8888 and avoid exposing additional emulated formats.
+ * usually preferred over formats near the end of the list.
  *
  * Returns:
  * The number of color-formats 4CC codes returned in @fourccs_out.
  */
 size_t drm_fb_build_fourcc_list(struct drm_device *dev,
                                const u32 *native_fourccs, size_t native_nfourccs,
-                               const u32 *driver_fourccs, size_t driver_nfourccs,
                                u32 *fourccs_out, size_t nfourccs_out)
 {
+       /*
+        * XRGB8888 is the default fallback format for most of userspace
+        * and it's currently the only format that should be emulated for
+        * the primary plane. Only if there's ever another default fallback,
+        * it should be added here.
+        */
+       static const uint32_t extra_fourccs[] = {
+               DRM_FORMAT_XRGB8888,
+       };
+       static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs);
+
        u32 *fourccs = fourccs_out;
        const u32 *fourccs_end = fourccs_out + nfourccs_out;
-       uint32_t native_format = 0;
        size_t i;
 
        /*
         */
 
        for (i = 0; i < native_nfourccs; ++i) {
-               u32 fourcc = native_fourccs[i];
+               /*
+                * Several DTs, boot loaders and firmware report native
+                * alpha formats that are non-alpha formats instead. So
+                * replace alpha formats by non-alpha formats.
+                */
+               u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]);
 
                if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
                        continue; /* skip duplicate entries */
 
                drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc);
 
-               /*
-                * There should only be one native format with the current API.
-                * This API needs to be refactored to correctly support arbitrary
-                * sets of native formats, since it needs to report which native
-                * format to use for each emulated format.
-                */
-               if (!native_format)
-                       native_format = fourcc;
                *fourccs = fourcc;
                ++fourccs;
        }
         * The extra formats, emulated by the driver, go second.
         */
 
-       for (i = 0; (i < driver_nfourccs) && (fourccs < fourccs_end); ++i) {
-               u32 fourcc = driver_fourccs[i];
+       for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) {
+               u32 fourcc = extra_fourccs[i];
 
                if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
                        continue; /* skip duplicate and native entries */
                } else if (fourccs == fourccs_end) {
                        drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc);
                        continue; /* end of available output buffer */
-               } else if (!is_conversion_supported(fourcc, native_format)) {
-                       drm_dbg_kms(dev, "Unsupported emulated format %p4cc\n", &fourcc);
-                       continue; /* format is not supported for conversion */
                }
 
                drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc);