osd: enable shift workaround and fix some zorder issue [1/1]
authorpengcheng chen <pengcheng.chen@amlogic.com>
Tue, 9 Oct 2018 08:45:56 +0000 (16:45 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Sat, 20 Oct 2018 14:29:27 +0000 (07:29 -0700)
PD#163001

Problem:
osd shift workaround default disable
some zorder display error

Solution:
enable shift workaround and fix some zorder issue

Verify:
verified in u200 board

Change-Id: I88489c31bcc4d0db838e59dc3fe1929bdb2a93f6
Signed-off-by: pengcheng chen <pengcheng.chen@amlogic.com>
drivers/amlogic/media/osd/osd_hw.c

index 3e0aa65..aacaa85 100644 (file)
@@ -67,7 +67,7 @@
 #include "osd_hw_def.h"
 #include "osd_fb.h"
 
-//#define OSD_BLEND_SHIFT_WORKAROUND
+#define OSD_BLEND_SHIFT_WORKAROUND
 #ifdef CONFIG_AMLOGIC_VSYNC_FIQ_ENABLE
 #define FIQ_VSYNC
 #endif
@@ -5248,11 +5248,121 @@ static u32 blend_din_to_osd(
 }
 
 #ifdef OSD_BLEND_SHIFT_WORKAROUND
+static u32 get_max_order(u32 order1, u32 order2)
+{
+       u32 max_order = 0;
+
+       if (order1 > order2)
+               max_order = order1;
+       else
+               max_order = order2;
+       return max_order;
+}
+
+static u32 get_min_order(u32 order1, u32 order2)
+{
+       u32 min_order = 0;
+
+       if (order1 > order2)
+               min_order = order2;
+       else
+               min_order = order1;
+       return min_order;
+}
+
+static u32 get_max_order_to_osd(struct hw_osd_blending_s *blending)
+{
+       u32 index = 0, max_order = 0;
+
+       max_order = get_max_order(blending->reorder[OSD1],
+               blending->reorder[OSD2]);
+       max_order = get_max_order(max_order,
+               blending->reorder[OSD3]);
+
+       if (max_order == blending->reorder[OSD1])
+               index = OSD1;
+       else if (max_order == blending->reorder[OSD2])
+               index = OSD2;
+       else if (max_order == blending->reorder[OSD3])
+               index = OSD3;
+       return index;
+}
+
+static u32 get_min_order_to_osd(struct hw_osd_blending_s *blending)
+{
+       u32 index = 0, min_order = 0;
+
+       min_order = get_min_order(blending->reorder[OSD1],
+               blending->reorder[OSD2]);
+       min_order = get_min_order(min_order,
+               blending->reorder[OSD3]);
+
+       if (min_order == blending->reorder[OSD1])
+               index = OSD1;
+       else if (min_order == blending->reorder[OSD2])
+               index = OSD2;
+       else if (min_order == blending->reorder[OSD3])
+               index = OSD3;
+       return index;
+}
+
+static u32 get_middle_order_to_osd(struct hw_osd_blending_s *blending)
+{
+       u32 index = 0;
+
+       if (blending->reorder[OSD1] == LAYER_2)
+               index = OSD1;
+       else if (blending->reorder[OSD2] == LAYER_2)
+               index = OSD2;
+       else if (blending->reorder[OSD3] == LAYER_2)
+               index = OSD3;
+       return index;
+}
+
+static void exchange_din0_din2(struct hw_osd_blending_s *blending)
+{
+       int temp1 = 0, temp2 = 0;
+
+       osd_log_dbg("need exchange osd din0 and din2 order\n");
+       temp1 = blending->din_reoder_sel & 0x000f;
+       temp2 = blending->din_reoder_sel & 0x0f00;
+       blending->din_reoder_sel &= ~0x0f0f;
+       blending->din_reoder_sel |= temp1 << 8;
+       blending->din_reoder_sel |= temp2 >> 8;
+       blending->osd_to_bdin_table[2] = OSD1;
+       blending->osd_to_bdin_table[0] = OSD2;
+       osd_log_dbg("din_reoder_sel%x\n",
+               blending->din_reoder_sel);
+}
+
+static void exchange_din2_din3(struct hw_osd_blending_s *blending)
+{
+       int temp1 = 0, temp2 = 0;
+
+       osd_log_dbg("need exchange osd din2 and din3 order\n");
+       temp1 = blending->din_reoder_sel & 0x0f00;
+       temp2 = blending->din_reoder_sel & 0xf000;
+       blending->din_reoder_sel &= ~0xff00;
+       blending->din_reoder_sel |= temp1 << 4;
+       blending->din_reoder_sel |= temp2 >> 4;
+       blending->osd_to_bdin_table[3] = OSD2;
+       blending->osd_to_bdin_table[2] = OSD3;
+       osd_log_dbg("din_reoder_sel%x\n",
+               blending->din_reoder_sel);
+}
+
+static void exchange_vpp_order(struct hw_osd_blending_s *blending)
+{
+       blending->b_exchange_blend_in = true;
+       osd_log_dbg("need exchange vpp order\n");
+}
+
 static void generate_blend_din_table(struct hw_osd_blending_s *blending)
 {
        int i = 0;
        int osd_count = osd_hw.osd_meson_dev.osd_count - 1;
        int temp1 = 0, temp2 = 0;
+       u32 max_order = 0, min_order = 0;
 
        /* reorder[i] = osd[i]'s display layer */
        for (i = 0; i < OSD_BLEND_LAYERS; i++)
@@ -5336,13 +5446,18 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending)
        }
        case 3:
                /* blend_din1 is bottom, blend_din4 is top layer */
-               /* mode A_BC */
-               /* osd0 always used blend_din1 */
-               /* blend_din1 */
-               blending->din_reoder_sel |= 1 << 0;
-               /* blend_din1 -- osd1 */
-               blending->osd_to_bdin_table[0] = OSD1;
+               osd_log_dbg("reorder:%d,%d,%d\n",
+                       blending->reorder[OSD1],
+                       blending->reorder[OSD2],
+                       blending->reorder[OSD3]);
                if (blending->osd_blend_mode == OSD_BLEND_AB_C) {
+                       /* suppose osd0 used blend_din1,
+                        * osd1 used din2, osd3 used din4
+                        */
+                       /* blend_din1 */
+                       blending->din_reoder_sel |= 1 << 0;
+                       /* blend_din1 -- osd1 */
+                       blending->osd_to_bdin_table[0] = OSD1;
                        /* blend_din4 */
                        blending->din_reoder_sel |= (OSD3 + 1) << 12;
                        /* blend_din4 -- osd3 */
@@ -5351,73 +5466,62 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending)
                        blending->din_reoder_sel |= (OSD2 + 1) << 8;
                        /* blend_din3 -- osd2 */
                        blending->osd_to_bdin_table[2] = OSD2;
-                       osd_log_dbg("reorder:%d,%d,%d\n",
-                               blending->reorder[OSD1],
-                               blending->reorder[OSD2],
+                       max_order = get_max_order(blending->reorder[OSD2],
                                blending->reorder[OSD3]);
-                       if (blending->reorder[OSD2] > blending->reorder[OSD1]) {
-                               /* osd1 is top */
-                               blending->b_exchange_din = true;
-                               osd_log_dbg("need exchange osd din order\n");
-                               temp1 = blending->din_reoder_sel & 0x000f;
-                               temp2 = blending->din_reoder_sel & 0x0f00;
-                               osd_log_dbg("temp1:%x,temp2=%x\n",
-                                       temp1, temp2);
-                               //blending->din_reoder_sel = (1 << 12);
-                               blending->din_reoder_sel &= ~0x0f0f;
-                               blending->din_reoder_sel |= temp1 << 8;
-                               blending->din_reoder_sel |= temp2 >> 8;
-                               osd_log_dbg("din_reoder_sel%x\n",
-                                       blending->din_reoder_sel);
-                               if (blending->reorder[OSD2] <
-                                       blending->reorder[OSD3]) {
-                                       blending->b_exchange_blend_in = true;
-                                       osd_log_dbg("111,need exchange vpp order\n");
-                               }
-                       } else {
-                               if (blending->reorder[OSD1] >
-                                       blending->reorder[OSD3]) {
-                                       blending->b_exchange_blend_in = true;
-                                       osd_log_dbg("222, need exchange vpp order\n");
+                       min_order = get_min_order(blending->reorder[OSD2],
+                               blending->reorder[OSD3]);
+                       if (min_order > blending->reorder[OSD1]) {
+                               /*  osd1 is top layer */
+                               osd_log_dbg("osd1 is top.\n");
+                               if (blending->reorder[OSD3] >
+                                       blending->reorder[OSD2]) {
+                                       /* din3 is bottom,  need exchange
+                                        * din0 and din2 and exchange vpp
+                                        */
+                                       osd_log_dbg("osd3 is bottom\n");
+                                       exchange_din0_din2(blending);
+                                       exchange_vpp_order(blending);
+                               } else {
+                                       osd_log_dbg("osd3 is middle\n");
+                                       exchange_din2_din3(blending);
+                                       exchange_din0_din2(blending);
+                                       exchange_vpp_order(blending);
                                }
+                       } else if ((min_order < blending->reorder[OSD1]) &&
+                               (max_order < blending->reorder[OSD1])) {
+                               /* osd1 is bottom , min is din3, max is din2 */
+                               if (min_order == blending->reorder[OSD2]) {
+                                       osd_log_dbg("osd2 is top\n");
+                                       /* need exchange din2 and din3*/
+                                       exchange_din2_din3(blending);
+                               } else if (min_order == blending->reorder[OSD3])
+                                       osd_log_dbg("osd3 is top, do not need exchange\n");
+                       } else if ((min_order < blending->reorder[OSD1]) &&
+                               (max_order > blending->reorder[OSD1])) {
+                               /* osd1 is middle  */
+                               osd_log_dbg("osd1 is middle\n");
+                               if (min_order == blending->reorder[OSD2])
+                                       exchange_vpp_order(blending);
+                               else if (min_order == blending->reorder[OSD3])
+                                       exchange_din0_din2(blending);
                        }
-               } else {
-                       if (blending->reorder[OSD2] > blending->reorder[OSD3]) {
-                               /* blend_din4 */
-                               blending->din_reoder_sel |= (OSD3 + 1) << 12;
-                               /* blend_din4 -- osd3 */
-                               blending->osd_to_bdin_table[3] = OSD3;
-                               /* blend_din3 */
-                               blending->din_reoder_sel |= (OSD2 + 1) << 8;
-                               /* blend_din3 -- osd2 */
-                               blending->osd_to_bdin_table[2] = OSD2;
-                       } else {
-                               /* blend_din3 */
-                               blending->din_reoder_sel |= (OSD2 + 1) << 12;
-                               /* blend_din3 -- osd2 */
-                               blending->osd_to_bdin_table[3] = OSD2;
-                               /* blend_din3 */
-                               blending->din_reoder_sel |= (OSD3 + 1) << 8;
-                               /* blend_din3 -- osd2 */
-                               blending->osd_to_bdin_table[2] = OSD3;
-                       }
-                       if (blending->reorder[OSD1] < blending->reorder[OSD3]) {
-                               u32 temp1, temp2;
+               } else if (blending->osd_blend_mode == OSD_BLEND_ABC) {
+                       u32 osd_index = 0;
 
-                               blending->b_exchange_din = true;
-                               osd_log_dbg("need exchange osd din order\n");
-                               temp1 = blending->osd_to_bdin_table[2];
-                               temp2 = blending->osd_to_bdin_table[3];
-                               blending->osd_to_bdin_table[3] =
-                                       blending->osd_to_bdin_table[0];
-                               blending->osd_to_bdin_table[2] = temp2;
-                               blending->osd_to_bdin_table[0] = temp1;
-                               temp1 = blending->din_reoder_sel & 0xf000;
-                               temp2 = blending->din_reoder_sel & 0x0f00;
-                               blending->din_reoder_sel = (1 << 12);
-                               blending->din_reoder_sel |= temp1 >> 4;
-                               blending->din_reoder_sel |= temp2 >> 8;
-                       }
+                       osd_index = get_max_order_to_osd(blending);
+                       /* blend_din1 is max_order*/
+                       blending->din_reoder_sel |= (osd_index + 1) << 0;
+                       blending->osd_to_bdin_table[0] = osd_index;
+
+                       osd_index = get_min_order_to_osd(blending);
+                       /* blend_din4 is min_order*/
+                       blending->din_reoder_sel |= (osd_index + 1) << 12;
+                       blending->osd_to_bdin_table[3] = osd_index;
+
+                       osd_index = get_middle_order_to_osd(blending);
+                       /* blend_din3 is middle_order*/
+                       blending->din_reoder_sel |= (osd_index + 1) << 8;
+                       blending->osd_to_bdin_table[2] = osd_index;
                }
                break;
        }
@@ -6821,8 +6925,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                if (index >= OSD_MAX)
                        return;
                osd_setting_blend0_input(index, blending);
-               if (index != OSD1)
-                       osd_log_err("not support case!!!\n");
                osd_setting_blend0(blending);
                memcpy(&output1_data, &(layer_blend->output_data),
                        sizeof(struct dispdata_s));