#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_gem_shmem_helper.h>
 #include <drm/drm_vblank.h>
        return new_color;
 }
 
-static void alpha_blending(const u8 *argb_src, u8 *argb_dst)
+/**
+ * alpha_blend - alpha blending equation
+ * @argb_src: src pixel on premultiplied alpha mode
+ * @argb_dst: dst pixel completely opaque
+ *
+ * blend pixels using premultiplied blend formula. The current DRM assumption
+ * is that pixel color values have been already pre-multiplied with the alpha
+ * channel values. See more drm_plane_create_blend_mode_property(). Also, this
+ * formula assumes a completely opaque background.
+ */
+static void alpha_blend(const u8 *argb_src, u8 *argb_dst)
 {
        u8 alpha;
 
        argb_dst[0] = blend_channel(argb_src[0], argb_dst[0], alpha);
        argb_dst[1] = blend_channel(argb_src[1], argb_dst[1], alpha);
        argb_dst[2] = blend_channel(argb_src[2], argb_dst[2], alpha);
-       /* Opaque primary */
-       argb_dst[3] = 0xFF;
+}
+
+/**
+ * x_blend - blending equation that ignores the pixel alpha
+ *
+ * overwrites RGB color value from src pixel to dst pixel.
+ */
+static void x_blend(const u8 *xrgb_src, u8 *xrgb_dst)
+{
+       memcpy(xrgb_dst, xrgb_src, sizeof(u8) * 3);
 }
 
 /**
  * @vaddr_src: source address
  * @dst_composer: destination framebuffer's metadata
  * @src_composer: source framebuffer's metadata
+ * @pixel_blend: blending equation based on plane format
  *
- * Blend the vaddr_src value with the vaddr_dst value using the pre-multiplied
- * alpha blending equation, since DRM currently assumes that the pixel color
- * values have already been pre-multiplied with the alpha channel values. See
- * more drm_plane_create_blend_mode_property(). This function uses buffer's
- * metadata to locate the new composite values at vaddr_dst.
+ * Blend the vaddr_src value with the vaddr_dst value using a pixel blend
+ * equation according to the supported plane formats DRM_FORMAT_(A/XRGB8888)
+ * and clearing alpha channel to an completely opaque background. This function
+ * uses buffer's metadata to locate the new composite values at vaddr_dst.
+ *
+ * TODO: completely clear the primary plane (a = 0xff) before starting to blend
+ * pixel color values
  */
 static void blend(void *vaddr_dst, void *vaddr_src,
                  struct vkms_composer *dst_composer,
-                 struct vkms_composer *src_composer)
+                 struct vkms_composer *src_composer,
+                 void (*pixel_blend)(const u8 *, u8 *))
 {
        int i, j, j_dst, i_dst;
        int offset_src, offset_dst;
 
                        pixel_src = (u8 *)(vaddr_src + offset_src);
                        pixel_dst = (u8 *)(vaddr_dst + offset_dst);
-                       alpha_blending(pixel_src, pixel_dst);
+                       pixel_blend(pixel_src, pixel_dst);
+                       /* clearing alpha channel (0xff)*/
+                       pixel_dst[3] = 0xff;
                }
                i_dst++;
        }
 {
        struct drm_gem_object *plane_obj;
        struct drm_gem_shmem_object *plane_shmem_obj;
+       struct drm_framebuffer *fb = &plane_composer->fb;
+       void (*pixel_blend)(const u8 *p_src, u8 *p_dst);
 
        plane_obj = drm_gem_fb_get_obj(&plane_composer->fb, 0);
        plane_shmem_obj = to_drm_gem_shmem_obj(plane_obj);
        if (WARN_ON(!plane_shmem_obj->vaddr))
                return;
 
-       blend(vaddr_out, plane_shmem_obj->vaddr,
-             primary_composer, plane_composer);
+       if (fb->format->format == DRM_FORMAT_ARGB8888)
+               pixel_blend = &alpha_blend;
+       else
+               pixel_blend = &x_blend;
+
+       blend(vaddr_out, plane_shmem_obj->vaddr, primary_composer,
+             plane_composer, pixel_blend);
 }
 
 static int compose_active_planes(void **vaddr_out,