viu2: add viu2 rotate
authorpengcheng chen <pengcheng.chen@amlogic.com>
Mon, 4 Jun 2018 10:10:25 +0000 (18:10 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Fri, 29 Jun 2018 07:29:27 +0000 (00:29 -0700)
PD#165090: viu2: add viu2 rotate

Change-Id: Ib9804f7113a8da9fd97c653fcf367b46db5af778
Signed-off-by: pengcheng chen <pengcheng.chen@amlogic.com>
arch/arm64/boot/dts/amlogic/mesong12b.dtsi
drivers/amlogic/media/osd/osd.h
drivers/amlogic/media/osd/osd_debug.c
drivers/amlogic/media/osd/osd_fb.c
drivers/amlogic/media/osd/osd_hw.c
drivers/amlogic/media/osd/osd_hw.h
drivers/amlogic/media/osd/osd_reg.h

index b11a384..1f679f1 100644 (file)
        vout2 {
                compatible = "amlogic, vout2";
                dev_name = "vout";
-               status = "disabled";
+               status = "okay";
                clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>,
                        <&clkc CLKID_VPU_CLKC_MUX>;
                clock-names = "vpu_clkc0",
index ebaa105..48844e9 100644 (file)
@@ -339,6 +339,12 @@ enum afbc_pix_format_e {
        RGBA1010102,
 };
 
+enum viu2_rotate_format {
+       YUV422 = 4,
+       RGB = 6,
+       RGBA = 8,
+};
+
 struct pandata_s {
        s32 x_start;
        s32 x_end;
@@ -673,6 +679,7 @@ struct hw_para_s {
        u32 free_scale_mode[HW_OSD_COUNT];
        u32 free_scale_mode_backup[HW_OSD_COUNT];
        u32 osd_reverse[HW_OSD_COUNT];
+       u32 osd_rotate[HW_OSD_COUNT];
        /* struct osd_rotate_s rotate[HW_OSD_COUNT]; */
        int use_h_filter_mode[HW_OSD_COUNT];
        int use_v_filter_mode[HW_OSD_COUNT];
index ceec4ae..d52da8a 100644 (file)
@@ -299,47 +299,81 @@ static void osd_debug_dump_register_all(void)
                if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) &&
                        (osd_hw.osd_afbcd[index].enable)) {
                        reg = osd_reg->afbc_header_buf_addr_low_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_header_buf_addr_high_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_format_specifier_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_buffer_width_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_buffer_hight_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_boundings_box_x_start_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_boundings_box_x_end_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_boundings_box_y_start_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_boundings_box_y_end_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_output_buf_addr_low_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_output_buf_addr_high_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_output_buf_stride_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                        reg = osd_reg->afbc_prefetch_cfg_s;
-                       osd_log_info("reg[0x%x]: 0x%08x\n\n",
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
                }
        }
 
+       if (osd_hw.osd_meson_dev.cpu_id >= __MESON_CPU_MAJOR_ID_G12B) {
+               if (osd_hw.osd_meson_dev.has_viu2) {
+                       reg = VPP2_MISC;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VPU_VIU_VENC_MUX_CTRL;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VIU2_RMIF_CTRL1;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VIU2_RMIF_SCOPE_X;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VIU2_RMIF_SCOPE_Y;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VIU2_ROT_BLK_SIZE;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VIU2_ROT_LBUF_SIZE;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VIU2_ROT_FMT_CTRL;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VIU2_ROT_OUT_VCROP;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+                       reg = VPP2_OFIFO_SIZE;
+                       osd_log_info("reg[0x%x]: 0x%08x\n",
+                               reg, osd_reg_read(reg));
+               }
+       }
        if (osd_hw.osd_meson_dev.afbc_type == MESON_AFBC) {
                reg = VIU_MISC_CTRL1;
                        osd_log_info("reg[0x%x]: 0x%08x\n",
index 68d0e06..744ecd5 100644 (file)
@@ -653,10 +653,18 @@ static int osd_set_par(struct fb_info *info)
        struct osd_ctl_s *osd_ctrl = &fbdev->osd_ctl;
        u32 virt_end_x, virt_end_y;
 
-       vinfo = get_current_vinfo();
-       if (!vinfo) {
-               osd_log_err("current vinfo NULL\n");
-               return -1;
+       if (fbdev->fb_index <= OSD3) {
+               vinfo = get_current_vinfo();
+               if (!vinfo) {
+                       osd_log_err("current vinfo NULL\n");
+                       return -1;
+               }
+       } else {
+               vinfo = get_current_vinfo2();
+               if (!vinfo) {
+                       osd_log_err("current vinfo NULL\n");
+                       return -1;
+               }
        }
        virt_end_x = osd_ctrl->disp_start_x + info->var.xres;
        virt_end_y = osd_ctrl->disp_start_y + info->var.yres;
@@ -2862,6 +2870,34 @@ static ssize_t store_osd_single_step(struct device *device,
        return count;
 }
 
+static ssize_t show_osd_rotate(
+       struct device *device, struct device_attribute *attr,
+       char *buf)
+{
+       struct fb_info *fb_info = dev_get_drvdata(device);
+       u32 rotate;
+
+       osd_get_rotate(fb_info->node, &rotate);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
+}
+
+static ssize_t store_osd_rotate(
+       struct device *device, struct device_attribute *attr,
+       const char *buf, size_t count)
+{
+       struct fb_info *fb_info = dev_get_drvdata(device);
+       int res = 0;
+       int ret = 0;
+
+       ret = kstrtoint(buf, 0, &res);
+       if (ret < 0)
+               return -EINVAL;
+
+       osd_set_rotate(fb_info->node, res);
+       return count;
+}
+
 static inline  int str2lower(char *str)
 {
        while (*str != '\0') {
@@ -3112,6 +3148,8 @@ static struct device_attribute osd_attrs_viu2[] = {
                        show_osd_afbc_debug, store_osd_afbc_debug),
        __ATTR(osd_afbc_format, 0644,
                        show_osd_afbc_format, store_osd_afbc_format),
+       __ATTR(osd_rotate, 0644,
+                       show_osd_rotate, store_osd_rotate),
 };
 
 #ifdef CONFIG_PM
@@ -3481,7 +3519,7 @@ static int osd_probe(struct platform_device *pdev)
                goto failed1;
        } else
                osd_log_info("viu vsync irq: %d\n", int_viu_vsync);
-       if (osd_hw.osd_meson_dev.has_viu2) {
+       if (osd_meson_dev.has_viu2) {
        int_viu2_vsync = platform_get_irq_byname(pdev, "viu2-vsync");
                if (int_viu2_vsync  == -ENXIO) {
                        osd_log_err("cannot get viu2 irq resource\n");
index f979fe2..14eaa7a 100644 (file)
@@ -660,6 +660,8 @@ static void osd_vpu_power_on_viu2(void)
                        VPU_MEM_POWER_ON);
                switch_vpu_mem_pd_vmod(VPU_VIU2_OFIFO,
                        VPU_MEM_POWER_ON);
+               switch_vpu_mem_pd_vmod(VPU_VIU2_OSD_ROT,
+                       VPU_MEM_POWER_ON);
                val = osd_reg_read(VPU_CLK_GATE);
                val =  val | 0x30000;
                osd_reg_write(VPU_CLK_GATE, val);
@@ -2922,6 +2924,20 @@ void osd_set_single_step(u32 osd_single_step)
        }
 }
 
+void osd_get_rotate(u32 index, u32 *osd_rotate)
+{
+       *osd_rotate = osd_hw.osd_rotate[index];
+}
+
+void osd_set_rotate(u32 index, u32 osd_rotate)
+{
+       if (index != OSD4)
+               osd_log_err("osd%d not support rotate\n", index);
+       osd_hw.osd_rotate[index] = osd_rotate;
+       add_to_update_list(index, DISP_OSD_ROTATE);
+       osd_wait_vsync_hw();
+}
+
 int osd_get_capbility(u32 index)
 {
        u32 capbility = 0;
@@ -4428,6 +4444,98 @@ static void osd_update_disp_osd_reverse(u32 index)
 
 static void osd_update_disp_osd_rotate(u32 index)
 {
+       u32 rotate_en = osd_hw.osd_rotate[index];
+       u32 src_fmt = RGBA;
+       u32 x_start, x_end, y_start, y_end;
+       u32 src_width, src_height;
+       u32 rot_hsize, blk_vsize, rd_blk_hsize;
+       u32 reg_fmt_buf_en, reg_fmt_444_mode, line5_mode;
+       u32 y_reverse = 0, x_reverse = 0;
+       u32 data32;
+       enum color_index_e idx;
+       struct dispdata_s src_data;
+       const struct vinfo_s *vinfo;
+       int out_y_crop_start, out_y_crop_end;
+
+       if (osd_hw.osd_meson_dev.cpu_id < __MESON_CPU_MAJOR_ID_G12B)
+               return;
+       src_data.x = 0;
+       src_data.y = 0;
+       src_data.w = osd_hw.fb_gem[index].xres;
+       src_data.h = osd_hw.fb_gem[index].yres;
+       vinfo = get_current_vinfo2();
+       if (!vinfo) {
+               osd_log_err("current vinfo NULL\n");
+               return;
+       }
+       out_y_crop_start = 0;
+       out_y_crop_end = vinfo->height;
+       src_width = src_data.w;
+       src_height = src_data.h;
+
+       x_start = src_data.x;
+       x_end = src_data.x + src_data.w - 1;
+       y_start = src_data.y;
+       y_end = src_data.y + src_data.h - 1;
+       /* x/y start end can be crop axis */
+       switch (src_fmt) {
+       case YUV422:
+               blk_vsize                 = 30;
+               rd_blk_hsize      = 32;
+               reg_fmt_buf_en    = 1;
+               reg_fmt_444_mode  = 0;
+               line5_mode                = 1;
+               break;
+       case RGB:
+               blk_vsize                 = 20;
+               rd_blk_hsize      = 22;
+               reg_fmt_buf_en    = 0;
+               reg_fmt_444_mode  = 1;
+               line5_mode                = 0;
+               break;
+       case RGBA:
+               blk_vsize                 = 15;
+               rd_blk_hsize      = 16;
+               reg_fmt_buf_en    = 0;
+               reg_fmt_444_mode  = 1;
+               line5_mode                = 0;
+               break;
+       }
+       osd_reg_set_bits(VPP2_MISC, rotate_en, 16, 1);
+       rotate_en = 0;
+       osd_reg_set_bits(VPU_VIU_VENC_MUX_CTRL,
+               rotate_en, 20, 1);
+       idx = osd_hw.color_info[index]->color_index;
+       data32 = (osd_hw.fb_gem[index].canvas_idx << 16) |
+               (2 << 8) | (1 << 7) | (0 << 6) |
+               (y_reverse << 5) |
+               (x_reverse << 4) | src_fmt;
+       osd_reg_set_bits(VIU2_RMIF_CTRL1, data32, 0, 32);
+       osd_reg_set_bits(VIU2_RMIF_SCOPE_X,
+               x_end << 16 | x_start, 0, 32);
+       osd_reg_set_bits(VIU2_RMIF_SCOPE_Y,
+               y_end << 16 | y_start, 0, 32);
+
+       rot_hsize = (src_height + blk_vsize - 1) / blk_vsize;
+       osd_reg_set_bits(
+               VIU2_ROT_BLK_SIZE,
+               rd_blk_hsize | (blk_vsize << 8), 0, 32);
+       osd_reg_set_bits(
+               VIU2_ROT_LBUF_SIZE,
+               rot_hsize * rd_blk_hsize |
+               (rot_hsize << 16), 0, 32);
+       osd_reg_set_bits(
+               VIU2_ROT_FMT_CTRL,
+               reg_fmt_buf_en |
+               (line5_mode << 1) |
+               (reg_fmt_444_mode << 2) |
+               (180    << 8) | (0xe4 << 24), 0, 32);
+       osd_reg_set_bits(VIU2_ROT_OUT_VCROP,
+               out_y_crop_end |
+               out_y_crop_start << 16, 0, 32);
+       osd_reg_set_bits(
+               VPP2_OFIFO_SIZE,
+               src_height - 1, 20, 12);
        remove_from_update_list(index, DISP_OSD_ROTATE);
 }
 
@@ -7231,7 +7339,6 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                        hw_osd_reg_array[OSD1].osd_fifo_ctrl_stat, data32);
        }
        osd_set_deband(osd_hw.osd_deband_enable);
-       /* memset(osd_hw.rotate, 0, sizeof(struct osd_rotate_s)); */
        if (osd_hw.fb_drvier_probe) {
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
                INIT_LIST_HEAD(&post_fence_list);
index 60d6dbd..a0fcfba 100644 (file)
@@ -198,4 +198,6 @@ void osd_get_urgent_info(u32 *ports, u32 *basic_urgent);
 void osd_set_single_step_mode(u32 osd_single_step_mode);
 void osd_set_single_step(u32 osd_single_step);
 void output_save_info(void);
+void osd_get_rotate(u32 index, u32 *osd_rotate);
+void osd_set_rotate(u32 index, u32 osd_rotate);
 #endif
index ac92bf0..5941fe8 100644 (file)
 #define VIU2_OSD1_MALI_UNPACK_CTRL 0x1e4f
 #define VIU2_OSD1_DIMM_CTRL 0x1e50
 #define VIU2_OSD1_UNSUPPORT VIU_OSD2_TCOLOR_AG3
+/* viu2 rotate */
+#define VIU2_RMIF_CTRL1 0x1e81
+#define VIU2_RMIF_SCOPE_X 0x1e83
+#define VIU2_RMIF_SCOPE_Y 0x1e84
+#define VIU2_ROT_BLK_SIZE 0x1e85
+#define VIU2_ROT_LBUF_SIZE 0x1e86
+#define VIU2_ROT_FMT_CTRL 0x1e87
+#define VIU2_ROT_OUT_VCROP 0x1e89
+
 /* encode */
 #define ENCP_VFIFO2VD_CTL 0x1b58
 #define ENCP_VFIFO2VD_PIXEL_START 0x1b59