diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index 404c53a2bdc6..03dd77399ebc 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -510,6 +510,7 @@ struct osd_device_data_s { u32 vpp_fifo_len; u32 dummy_data; u32 has_viu2; + u32 osd0_sc_independ; u32 viu1_osd_count; u32 viu2_index; struct clk *vpu_clkc; diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index 4b6c078958d4..dd1b06816c8b 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -3740,6 +3740,7 @@ static struct osd_device_data_s osd_gxbb = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxtvbb = { @@ -3755,6 +3756,7 @@ static struct osd_device_data_s osd_gxtvbb = { .vpp_fifo_len = 0xfff, .dummy_data = 0x0, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxl = { @@ -3770,6 +3772,7 @@ static struct osd_device_data_s osd_gxl = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxm = { @@ -3785,6 +3788,7 @@ static struct osd_device_data_s osd_gxm = { .vpp_fifo_len = 0xfff, .dummy_data = 0x00202000,/* dummy data is different */ .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_txl = { @@ -3800,6 +3804,7 @@ static struct osd_device_data_s osd_txl = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_txlx = { @@ -3815,6 +3820,7 @@ static struct osd_device_data_s osd_txlx = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_axg = { @@ -3831,6 +3837,7 @@ static struct osd_device_data_s osd_axg = { .vpp_fifo_len = 0x400, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_g12a = { @@ -3846,6 +3853,7 @@ static struct osd_device_data_s osd_g12a = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_g12b = { @@ -3861,6 +3869,7 @@ static struct osd_device_data_s osd_g12b = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_tl1 = { @@ -3876,21 +3885,7 @@ static struct osd_device_data_s osd_tl1 = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, -}; - -static struct osd_device_data_s osd_tm2 = { - .cpu_id = __MESON_CPU_MAJOR_ID_TM2, - .osd_ver = OSD_HIGH_ONE, - .afbc_type = MALI_AFBC, - .osd_count = 4, - .has_deband = 1, - .has_lut = 1, - .has_rdma = 1, - .has_dolby_vision = 0, - .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ - .vpp_fifo_len = 0xfff,/* 2048 */ - .dummy_data = 0x00808000, - .has_viu2 = 1, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_sm1 = { @@ -3906,6 +3901,23 @@ static struct osd_device_data_s osd_sm1 = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, +}; + +static struct osd_device_data_s osd_tm2 = { + .cpu_id = __MESON_CPU_MAJOR_ID_TM2, + .osd_ver = OSD_HIGH_ONE, + .afbc_type = MALI_AFBC, + .osd_count = 4, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0xfff,/* 2048 */ + .dummy_data = 0x00808000, + .has_viu2 = 1, + .osd0_sc_independ = 1, }; static const struct of_device_id meson_fb_dt_match[] = { @@ -4003,7 +4015,6 @@ static int osd_probe(struct platform_device *pdev) return -ENODEV; } } - /* get interrupt resource */ int_viu_vsync = platform_get_irq_byname(pdev, "viu-vsync"); if (int_viu_vsync == -ENXIO) { diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 2feeee0910c3..f1705df422b1 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -75,7 +75,6 @@ #include "osd_hw_def.h" #include "osd_fb.h" -#define OSD_BLEND_SHIFT_WORKAROUND #ifdef CONFIG_AMLOGIC_VSYNC_FIQ_ENABLE #define FIQ_VSYNC #endif @@ -5741,7 +5740,6 @@ static u32 blend_din_to_osd( return osd_index; } -#ifdef OSD_BLEND_SHIFT_WORKAROUND static u32 get_max_order(u32 order1, u32 order2) { u32 max_order = 0; @@ -6031,155 +6029,6 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending) blending->din_reoder_sel; } -#else -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; - - /* reorder[i] = osd[i]'s display layer */ - for (i = 0; i < OSD_BLEND_LAYERS; i++) - blending->osd_to_bdin_table[i] = -1; - blending->din_reoder_sel = 0; - switch (blending->layer_cnt) { - case 0: - break; - case 1: - for (i = 0; i < osd_count; i++) { - if (blending->reorder[i] != LAYER_UNSUPPORT) { - /* blend_din1 */ - blending->din_reoder_sel |= (i + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = i; - break; - } - } - break; - case 2: - { - int temp_index[2] = {0}; - int j = 0; - - for (i = 0; i < osd_count; i++) { - if (blending->reorder[i] != LAYER_UNSUPPORT) { - /* save the osd index */ - temp_index[j] = i; - j++; - } - } - osd_log_dbg(MODULE_BLEND, "blend_din4==%d\n", - blending->reorder[temp_index[0]]); - osd_log_dbg(MODULE_BLEND, "blend_din1==%d\n", - blending->reorder[temp_index[1]]); - /* mode A_C */ - if (blending->osd_blend_mode == OSD_BLEND_A_C) { - /* blend_din1 */ - blending->din_reoder_sel |= (temp_index[0] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[0]; - /* blend_din3 */ - blending->din_reoder_sel |= (temp_index[1] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[1]; - /* exchane vpp osd blend in order */ - if (blending->reorder[temp_index[0]] < - blending->reorder[temp_index[1]]) { - blending->b_exchange_blend_in = true; - osd_log_dbg(MODULE_BLEND, "need exchange vpp order\n"); - } - } else { - if (blending->reorder[temp_index[0]] < - blending->reorder[temp_index[1]]) { - /* blend_din4 */ - blending->din_reoder_sel |= - (temp_index[0] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[0]; - /* blend_din1 */ - blending->din_reoder_sel |= - (temp_index[1] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[1]; - blending->b_exchange_din = true; - osd_log_dbg(MODULE_BLEND, "need exchange osd din order\n"); - } else { - /* blend_din1 */ - blending->din_reoder_sel |= - (temp_index[0] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[0]; - /* blend_din3 */ - blending->din_reoder_sel |= - (temp_index[1] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[1]; - } - } - break; - } - 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; - 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]) { - if (blending->osd_blend_mode == OSD_BLEND_A_BC) { - blending->b_exchange_blend_in = true; - osd_log_dbg(MODULE_BLEND, "need exchange vpp order\n"); - } else { - u32 temp1, temp2; - - blending->b_exchange_din = true; - osd_log_dbg(MODULE_BLEND, "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; - } - } - break; - } - osd_log_dbg(MODULE_BLEND, "osd_to_bdin_table[i]=[%x,%x,%x,%x]\n", - blending->osd_to_bdin_table[0], - blending->osd_to_bdin_table[1], - blending->osd_to_bdin_table[2], - blending->osd_to_bdin_table[3]); - blending->blend_reg.din_reoder_sel = - blending->din_reoder_sel; -} -#endif static bool is_freescale_para_changed(u32 index) { static int first[HW_OSD_COUNT - 1] = {1}; @@ -6338,13 +6187,9 @@ static void set_blend_order(struct hw_osd_blending_s *blending) static void set_blend_din(struct hw_osd_blending_s *blending) { int i = 0, osd_index; -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* workaround for shift issue */ /* blend_din_en must equal 5 */ u32 blend_din_en = 0x5; -#else - u32 blend_din_en = 0x9; -#endif if (!blending) return; @@ -6365,7 +6210,6 @@ static void set_blend_din(struct hw_osd_blending_s *blending) static void set_blend_mode(struct hw_osd_blending_s *blending) { u8 osd_blend_mode = OSD_BLEND_NONE; - //u32 osd_index; if (!blending) return; @@ -6389,11 +6233,7 @@ static void set_blend_mode(struct hw_osd_blending_s *blending) if (osd_hw.hdr_used) osd_blend_mode = OSD_BLEND_ABC; else -#ifdef OSD_BLEND_SHIFT_WORKAROUND osd_blend_mode = OSD_BLEND_AB_C; -#else - osd_blend_mode = OSD_BLEND_A_BC; -#endif break; } blending->osd_blend_mode = osd_blend_mode; @@ -6537,19 +6377,9 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) } layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* blend1_dout to blend2 */ blend_reg->din2_osd_sel = 0; -#else - /* input1 default route to blend1 */ - if (layer_blend->input1 & BYPASS_DIN) { - /* blend1_dout to dout1 */ - blend_reg->din2_osd_sel = 1; - layer_blend->input1 &= ~BYPASS_DIN; - } else - /* blend1_dout to blend2 */ - blend_reg->din2_osd_sel = 0; -#endif + if (layer_blend->input2 & BYPASS_DIN) { /* blend1_din3 bypass to dout1 */ blend_reg->din3_osd_sel = 1; @@ -6613,7 +6443,6 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) } if (blend_reg->din3_osd_sel || layer_blend->input1 == BLEND_NO_DIN) { /* blend din3 bypass,output == input */ -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->input2 == BLEND_NO_DIN) { memcpy(&layer_blend->output_data, &layer_blend->input1_data, @@ -6624,16 +6453,7 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) sizeof(struct dispdata_s)); } layer_blend->output_data.h += workaround_line; -#else - layer_blend->output_data.x = 0; - layer_blend->output_data.y = 0; - layer_blend->output_data.w = - layer_blend->input2_data.x + - layer_blend->input2_data.w; - layer_blend->output_data.h = - layer_blend->input2_data.y + - layer_blend->input2_data.h; -#endif + } else calc_max_output(blending); blend_hsize = layer_blend->output_data.w; @@ -6666,7 +6486,6 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) /* osd_blend_blend0_size share with blend2_size*/ blend_reg->osd_blend_blend0_size = blend_vsize << 16 | blend_hsize; -#ifdef OSD_BLEND_SHIFT_WORKAROUND switch (layer_blend->input2) { case BLEND1_DIN: blend1_input = 0; @@ -6676,19 +6495,7 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) blend1_input = 1; break; } -#else - switch (layer_blend->input2) { - case BLEND1_DIN: - /* blend1_dout to blend2 */ - blend_reg->din2_osd_sel = 0; - break; - default: - /* blend1_dout to dout1 */ - blend_reg->din2_osd_sel = 1; - break; - } - blend1_input = blend_reg->din2_osd_sel; -#endif + /* premult set */ blend_reg->blend2_premult_en = 3; if (blend1_input) @@ -6700,11 +6507,9 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) blend_vsize = layer_blend->output_data.h; blend_reg->osd_blend_blend0_size = blend_vsize << 16 | blend_hsize; -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* blend 0 and blend1 size need same */ blend_reg->osd_blend_blend1_size = blend_reg->osd_blend_blend0_size; -#endif } osd_log_dbg2(MODULE_BLEND, "layer_blend2->output_data:%d,%d,%d,%d\n", layer_blend->output_data.x, @@ -6743,11 +6548,7 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) switch (layer_blend->input1) { case BLEND1_DIN: blend_reg->postbld_src3_sel = POSTBLD_OSD2; -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->blend_core1_bypass) -#else - if (blend_reg->din3_osd_sel) -#endif blend_reg->postbld_osd1_premult = 0; else blend_reg->postbld_osd1_premult = 1; @@ -6776,11 +6577,7 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) switch (layer_blend->input2) { case BLEND1_DIN: blend_reg->postbld_src4_sel = POSTBLD_OSD2; -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->blend_core1_bypass) -#else - if (blend_reg->din3_osd_sel) -#endif blend_reg->postbld_osd2_premult = 0; else blend_reg->postbld_osd2_premult = 1; @@ -6815,7 +6612,6 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) blend_reg->vpp_osd2_blend_v_scope); } -/* input w, h is background */ static void osd_set_freescale(u32 index, struct hw_osd_blending_s *blending) @@ -7056,7 +6852,6 @@ static void osd_setting_blend1_input(u32 index, layer_blend->output_data.h); } -/* every output is next path input */ static void set_blend_path(struct hw_osd_blending_s *blending) { struct layer_blend_s *layer_blend; @@ -7071,9 +6866,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending) output_index = get_output_device_id(index); layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); -#ifdef OSD_BLEND_SHIFT_WORKAROUND layer_blend->blend_core1_bypass = 0; -#endif switch (blending->osd_blend_mode) { case OSD_BLEND_NONE: blend_reg->postbld_osd1_premult = 0; @@ -7181,9 +6974,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending) index = blend_din_to_osd(input1, blending); if (index >= OSD_MAX) return; -#ifndef OSD_BLEND_SHIFT_WORKAROUND - osd_setting_blend0_input(index, blending); -#endif if (index != OSD1) { /* here used freescale osd1/osd2 */ osd_log_dbg2(MODULE_BLEND, @@ -7191,9 +6981,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending) index); osd_set_freescale(index, blending); } -#ifdef OSD_BLEND_SHIFT_WORKAROUND osd_setting_blend0_input(index, blending); -#endif osd_setting_blend0(blending); memcpy(&output1_data, &(layer_blend->output_data), sizeof(struct dispdata_s)); @@ -7209,22 +6997,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } layer_blend->input1 = BLEND_NO_DIN; layer_blend->input2 = input2; -#ifndef OSD_BLEND_SHIFT_WORKAROUND - if (osd_hw.blend_bypass) - layer_blend->input2 |= BYPASS_DIN; -#endif -#if 0 - layer_blend->input2_data.x = - osd_hw.free_dst_data[index].x_start; - layer_blend->input2_data.w = - osd_hw.free_dst_data[index].x_end - - osd_hw.free_dst_data[index].x_start + 1; - layer_blend->input2_data.y = - osd_hw.free_dst_data[index].y_start; - layer_blend->input2_data.h = - osd_hw.free_dst_data[index].y_end - - osd_hw.free_dst_data[index].y_start + 1; -#endif + osd_setting_blend1_input(index, blending); memcpy(&layer_blend->input2_data, &layer_blend->output_data, @@ -7312,32 +7085,10 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_log_dbg2(MODULE_BLEND, "before blend1: set osd%d freescale\n", index); osd_set_freescale(index, blending); -#ifdef OSD_BLEND_SHIFT_WORKAROUND layer_blend->input1 = BLEND_NO_DIN; /* must bypass for shift workaround */ layer_blend->input2 = BLEND_DIN4 | BYPASS_DIN; layer_blend->blend_core1_bypass = 1; -#else - /* always route(bypass) to dout1 */ - layer_blend->input1 = BLEND_NO_DIN | BYPASS_DIN; - layer_blend->input2 = BLEND_DIN4; - if (osd_hw.blend_bypass) - layer_blend->input2 |= BYPASS_DIN; -#endif - #if 0 - layer_blend->input2_data.x = - osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; - layer_blend->input2_data.w = - osd_hw.free_dst_data[index].x_end - - osd_hw.free_dst_data[index].x_start + 1; - layer_blend->input2_data.y = - osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; - layer_blend->input2_data.h = - osd_hw.free_dst_data[index].y_end - - osd_hw.free_dst_data[index].y_start + 1; - #endif osd_setting_blend1_input(index, blending); memcpy(&layer_blend->input2_data, &layer_blend->output_data, @@ -7422,10 +7173,8 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2 = BLEND1_DIN; memcpy(&layer_blend->input1_data, &output1_data, sizeof(struct dispdata_s)); -#ifdef OSD_BLEND_SHIFT_WORKAROUND memcpy(&layer_blend->input2_data, &layer_blend->output_data, sizeof(struct dispdata_s)); -#endif osd_setting_blend2(blending); /* used osd0 freescale */ osd_set_freescale(OSD1, blending); @@ -7549,7 +7298,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } vpp_setting_blend(blending); break; -#ifdef OSD_BLEND_SHIFT_WORKAROUND case OSD_BLEND_AB_C: /* blend0 -->blend2-->sc->vpp_osd1 */ /* sc-->blend1-->blend2-->sc-->vpp_osd1 */ @@ -7654,7 +7402,563 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } vpp_setting_blend(blending); break; -#endif + } +} + +static void osd_setting_blend0_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_reg_s *blend_reg; + struct layer_blend_s *layer_blend; + u32 index = 0; + u32 bld_osd_h_start = 0, bld_osd_h_end = 0; + u32 bld_osd_v_start = 0, bld_osd_v_end = 0; + + if (!blending) + return; + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + /* blend0 only accept input1 */ + if (layer_blend->input1 & BYPASS_DIN) { + blend_reg->din0_byp_blend = 1; + layer_blend->input1 &= ~BYPASS_DIN; + } else + blend_reg->din0_byp_blend = 0; + if (layer_blend->input1 != BLEND_NO_DIN) { + /* calculate osd blend din scope */ + index = blend_din_to_osd(layer_blend->input1, blending); + if (index >= OSD_MAX) + return; + layer_blend->input1_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input1_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input1_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input1_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + bld_osd_h_start = + layer_blend->input1_data.x; + bld_osd_h_end = + layer_blend->input1_data.x + + layer_blend->input1_data.w - 1; + bld_osd_v_start = + layer_blend->input1_data.y; + bld_osd_v_end = + layer_blend->input1_data.y + + layer_blend->input1_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + } + layer_blend->output_data.x = 0; + layer_blend->output_data.y = 0; + layer_blend->output_data.w = layer_blend->input1_data.x + + layer_blend->input1_data.w; + layer_blend->output_data.h = layer_blend->input1_data.y + + layer_blend->input1_data.h; + osd_log_dbg2(MODULE_BLEND, + "blend0:input1_data[osd%d]:%d,%d,%d,%d\n", + index, + layer_blend->input1_data.x, + layer_blend->input1_data.y, + layer_blend->input1_data.w, + layer_blend->input1_data.h); + osd_log_dbg2(MODULE_BLEND, + "blend0:layer_blend->output_data:%d,%d,%d,%d\n", + layer_blend->output_data.x, + layer_blend->output_data.y, + layer_blend->output_data.w, + layer_blend->output_data.h); +} + +static void osd_setting_blend1_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + u32 index = 0; + u32 blend_hsize, blend_vsize; + u32 bld_osd_h_start = 0, bld_osd_h_end = 0; + u32 bld_osd_v_start = 0, bld_osd_v_end = 0; + /* for g12a blend shift issue */ + + if (!blending) + return; + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + /* blend1_dout to blend2 */ + blend_reg->din2_osd_sel = 0; + + if (layer_blend->input2 & BYPASS_DIN) { + /* blend1_din3 bypass to dout1 */ + blend_reg->din3_osd_sel = 1; + layer_blend->input2 &= ~BYPASS_DIN; + } else + /* blend1_din3 input to blend1 */ + blend_reg->din3_osd_sel = 0; + + if (layer_blend->input1 != BLEND_NO_DIN) { + index = blend_din_to_osd(layer_blend->input1, blending); + if (index >= OSD_MAX) + return; + layer_blend->input1_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input1_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input1_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input1_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + /* calculate osd blend din scope */ + bld_osd_h_start = + layer_blend->input1_data.x; + bld_osd_h_end = + layer_blend->input1_data.x + + layer_blend->input1_data.w - 1; + bld_osd_v_start = + layer_blend->input1_data.y; + bld_osd_v_end = + layer_blend->input1_data.y + + layer_blend->input1_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + osd_log_dbg2(MODULE_BLEND, + "blend1:input1_data(osd%d):%d,%d,%d,%d\n", + index, + layer_blend->input1_data.x, + layer_blend->input1_data.y, + layer_blend->input1_data.w, + layer_blend->input1_data.h); + } + if (layer_blend->input2 != BLEND_NO_DIN) { + index = blend_din_to_osd(layer_blend->input2, blending); + if (index >= OSD_MAX) + return; + layer_blend->input2_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input2_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input2_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input2_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + /* calculate osd blend din scope */ + bld_osd_h_start = + layer_blend->input2_data.x; + bld_osd_h_end = + layer_blend->input2_data.x + + layer_blend->input2_data.w - 1; + bld_osd_v_start = + layer_blend->input2_data.y; + bld_osd_v_end = + layer_blend->input2_data.y + + layer_blend->input2_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + osd_log_dbg2(MODULE_BLEND, + "layer_blend->input2_data:%d,%d,%d,%d\n", + layer_blend->input2_data.x, + layer_blend->input2_data.y, + layer_blend->input2_data.w, + layer_blend->input2_data.h); + } + if (blend_reg->din3_osd_sel || layer_blend->input1 == BLEND_NO_DIN) { + /* blend din3 bypass,output == input */ + if (layer_blend->input2 == BLEND_NO_DIN) { + memcpy(&layer_blend->output_data, + &layer_blend->input1_data, + sizeof(struct dispdata_s)); + } else { + memcpy(&layer_blend->output_data, + &layer_blend->input2_data, + sizeof(struct dispdata_s)); + } + } else + calc_max_output(blending); + blend_hsize = layer_blend->output_data.w; + blend_vsize = layer_blend->output_data.h; + blend_reg->osd_blend_blend1_size = + blend_vsize << 16 | blend_hsize; + + osd_log_dbg2(MODULE_BLEND, "layer_blend1->output_data:%d,%d,%d,%d\n", + layer_blend->output_data.x, + layer_blend->output_data.y, + layer_blend->output_data.w, + layer_blend->output_data.h); +} + +/* input w, h is background */ +static void osd_set_freescale_new(u32 index, + struct hw_osd_blending_s *blending) + +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + u32 width, height; + u32 src_height; + + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + if (index >= osd_hw.osd_meson_dev.viu1_osd_count) { + osd_log_err("error osd index=%d\n", index); + return; + } + osd_hw.free_scale_enable[index] = 0x10001; + osd_hw.free_scale[index].h_enable = 1; + osd_hw.free_scale[index].v_enable = 1; + osd_hw.free_scale_mode[index] = 1; + + osd_hw.free_src_data[index].x_start = + osd_hw.src_data[index].x; + osd_hw.free_src_data[index].x_end = + osd_hw.src_data[index].x + + osd_hw.src_data[index].w - 1; + osd_hw.free_src_data[index].y_start = + osd_hw.src_data[index].y; + osd_hw.free_src_data[index].y_end = + osd_hw.src_data[index].y + + osd_hw.src_data[index].h - 1; + + /* direct used dst as freescale dst */ + osd_hw.free_dst_data[index].x_start = + osd_hw.dst_data[index].x; + osd_hw.free_dst_data[index].y_start = + osd_hw.dst_data[index].y; + width = osd_hw.dst_data[index].w; + height = osd_hw.dst_data[index].h; + if (osd_hw.field_out_en) { + height = height >> 1; + osd_hw.free_dst_data[index].y_start >>= 1; + } + osd_hw.free_dst_data[index].x_end = + osd_hw.free_dst_data[index].x_start + + width - 1; + osd_hw.free_dst_data[index].y_end = + osd_hw.free_dst_data[index].y_start + + height - 1; + + src_height = osd_hw.free_src_data[index].x_end - + osd_hw.free_src_data[index].x_start + 1; + osd_set_dummy_data(index, 0xff); + osd_log_dbg2(MODULE_BLEND, "osd%d:free_src_data:%d,%d,%d,%d\n", + index, + osd_hw.free_src_data[index].x_start, + osd_hw.free_src_data[index].y_start, + osd_hw.free_src_data[index].x_end, + osd_hw.free_src_data[index].y_end); + osd_log_dbg2(MODULE_BLEND, "osd%d:free_dst_data:%d,%d,%d,%d\n", + index, + osd_hw.free_dst_data[index].x_start, + osd_hw.free_dst_data[index].y_start, + osd_hw.free_dst_data[index].x_end, + osd_hw.free_dst_data[index].y_end); +} + +/* every output is next path input */ +static void set_blend_path_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + struct dispdata_s output1_data; + u32 index = 0; + u8 input1 = 0, input2 = 0; + u32 output_index; + + if (!blending) + return; + output_index = get_output_device_id(index); + + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + layer_blend->blend_core1_bypass = 0; + switch (blending->osd_blend_mode) { + case OSD_BLEND_NONE: + blend_reg->postbld_osd1_premult = 0; + blend_reg->postbld_src4_sel = POSTBLD_CLOSE; + blend_reg->postbld_src3_sel = POSTBLD_CLOSE; + blend_reg->postbld_osd2_premult = 0; + break; + case OSD_BLEND_A: + /* sc-->blend0-->blend2-->vpp_osd1 */ + layer_blend->input1 = BLEND_DIN1; + if (osd_hw.blend_bypass) + layer_blend->input1 |= BYPASS_DIN; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + if (!blend_reg->din0_byp_blend) { + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + /* same with blend0's background */ + osd_setting_blend2(blending); + } + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_AC: + /* sc-->blend0 -->blend1-->blend2-->vpp_osd1 */ + /* sc-->blend0 & blend1-->blend2-->vpp_osd1 */ + if (!blending->b_exchange_din) { + input1 = BLEND_DIN1; + input2 = BLEND_DIN4; + } else { + input1 = BLEND_DIN4; + input2 = BLEND_DIN1; + } + layer_blend->input1 = input1; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(input1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + index = blend_din_to_osd(input2, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + layer_blend->input1 = BLEND_NO_DIN; + layer_blend->input2 = input2; + osd_setting_blend1_new(blending); + + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + + /* blend0 output-> blend2 input1 */ + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + /* blend1 output-> blend2 input2 */ + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_A_C: + /* sc-->blend0 -->blend2->vpp_osd1 */ + /* sc-->blend1 -->vpp_osd2 */ + layer_blend->input1 = BLEND_DIN1; + if (osd_hw.blend_bypass) + layer_blend->input1 |= BYPASS_DIN; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + if (!blend_reg->din0_byp_blend) { + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + /* background is same with blend0's background */ + osd_setting_blend2(blending); + } + /* save blend0/blend2 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + /* adjust input 1 offset*/ + output1_data.x += + osd_hw.disp_info[output_index].position_x; + output1_data.y += + osd_hw.disp_info[output_index].position_y; + + index = blend_din_to_osd(BLEND_DIN4, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + layer_blend->input1 = BLEND_NO_DIN; + layer_blend->input2 = BLEND_DIN4 | BYPASS_DIN; + layer_blend->blend_core1_bypass = 1; + osd_setting_blend1_new(blending); + /* adjust input 2 offset*/ + layer_blend->output_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->output_data.y += + osd_hw.disp_info[output_index].position_y; + + if (!blending->b_exchange_blend_in) { + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + } else { + layer_blend->input1 = BLEND1_DIN; + layer_blend->input2 = BLEND2_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &output1_data, + sizeof(struct dispdata_s)); + } + vpp_setting_blend(blending); + break; + case OSD_BLEND_ABC: + /* sc->blend0 -->blend2-->vpp_osd1 */ + /* sc-->blend1 -->blend2 */ + input1 = BLEND_DIN1; + input2 = BLEND_DIN4; + layer_blend->input1 = input1; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(input1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + layer_blend->input1 = BLEND_DIN3; + layer_blend->input2 = input2; + index = blend_din_to_osd(layer_blend->input1, blending); + osd_set_freescale_new(index, blending); + index = blend_din_to_osd(layer_blend->input2, blending); + osd_set_freescale_new(index, blending); + osd_setting_blend1_new(blending); + + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_AB_C: + /* sc-->blend0 -->blend2->vpp_osd1 */ + /* sc-->blend1-->blend2-->vpp_osd1 */ + /* sc -->vpp_osd2 */ + layer_blend->input1 = BLEND_DIN1; + layer_blend->input2 = BLEND_NO_DIN; + blending->blend_din = BLEND_DIN1; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + /* din3 input to blend1 */ + layer_blend->input1 = BLEND_DIN3; + layer_blend->input2 = BLEND_NO_DIN | BYPASS_DIN; + layer_blend->blend_core1_bypass = 1; + blending->blend_din = BLEND_DIN3; + index = blend_din_to_osd(BLEND_DIN3, blending); + osd_set_freescale_new(index, blending); + osd_setting_blend1_new(blending); + + /* din1=>blend0 & din3-> blend1 ==> blend2 */ + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + output1_data.x += + osd_hw.disp_info[output_index].position_x; + output1_data.y += + osd_hw.disp_info[output_index].position_y; + osd_log_dbg2(MODULE_BLEND, "output1_data:%d,%d,%d,%d\n", + output1_data.x, + output1_data.w, + output1_data.y, + output1_data.h); + + + /* din4 ==> vpp */ + index = blend_din_to_osd(BLEND_DIN4, blending); + blending->blend_din = BLEND_DIN4; + osd_set_freescale_new(index, blending); + layer_blend->input2_data.x = + osd_hw.free_dst_data[index].x_start + + osd_hw.disp_info[output_index].position_x; + layer_blend->input2_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input2_data.y = + osd_hw.free_dst_data[index].y_start + + osd_hw.disp_info[output_index].position_y; + layer_blend->input2_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + /* 2vpp input */ + if (!blending->b_exchange_blend_in) { + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + } else { + layer_blend->input1 = BLEND1_DIN; + layer_blend->input2 = BLEND2_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->input2_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, + &output1_data, + sizeof(struct dispdata_s)); + } + vpp_setting_blend(blending); + break; } } @@ -7663,16 +7967,16 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) int i; u32 reg_offset = 2; u32 osd1_alpha_div = 0, osd2_alpha_div = 0; -#ifdef OSD_BLEND_SHIFT_WORKAROUND u32 osd_count = OSD_BLEND_LAYERS; -#else - u32 osd_count = osd_hw.osd_meson_dev.viu1_osd_count; -#endif u32 dv_core2_hsize; u32 dv_core2_vsize; if (!blend_reg) return; + /* osd0 scale position before osd blend */ + if (osd_hw.osd_meson_dev.osd0_sc_independ) + VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCALE_CTRL, 0x01); + /* osd blend ctrl */ VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_CTRL, 4 << 29| @@ -7734,7 +8038,6 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i, blend_reg->osd_blend_din_scope_v[i]); } -#ifdef OSD_BLEND_SHIFT_WORKAROUND else { if ((blend_reg->osd_blend_din_scope_v[i] & 0xffff) == 0) blend_reg->osd_blend_din_scope_v[i] = 0x43a0439; @@ -7742,7 +8045,6 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i, blend_reg->osd_blend_din_scope_v[i]); } -#endif } dv_core2_vsize = (blend_reg->osd_blend_blend0_size >> 16) & 0xfff; @@ -7857,7 +8159,8 @@ static int osd_setting_order(u32 output_index) blending->b_exchange_blend_in = false; blending->osd1_freescale_disable = false; adjust_dst_position(output_index); - uniformization_fb(OSD1, blending); + if (!osd_hw.osd_meson_dev.osd0_sc_independ) + uniformization_fb(OSD1, blending); /* set blend mode */ set_blend_mode(blending); @@ -7866,7 +8169,10 @@ static int osd_setting_order(u32 output_index) set_blend_din(blending); /* set blend path */ - set_blend_path(blending); + if (osd_hw.osd_meson_dev.osd0_sc_independ) + set_blend_path_new(blending); + else + set_blend_path(blending); line1 = get_enter_encp_line(); vinfo_height = osd_hw.field_out_en[output_index] ? (osd_hw.vinfo_height[output_index] * 2) : diff --git a/drivers/amlogic/media/osd/osd_reg.h b/drivers/amlogic/media/osd/osd_reg.h index 517ca97827f0..e2218bd572c1 100644 --- a/drivers/amlogic/media/osd/osd_reg.h +++ b/drivers/amlogic/media/osd/osd_reg.h @@ -392,7 +392,7 @@ #define VPP_OSD_SCALE_COEF_IDX 0x1dcc #define VPP_OSD_SCALE_COEF 0x1dcd #define VPP_INT_LINE_NUM 0x1dce - +#define VPP_OSD_SCALE_CTRL 0x1dff /* osd2 scaler */ #define OSD2_VSC_PHASE_STEP 0x3d00 #define OSD2_VSC_INI_PHASE 0x3d01