fbdev: dpu20: parse DPU count and HW limitation
authorChiHun Won <chihun.won@samsung.com>
Wed, 4 Jul 2018 05:41:15 +0000 (14:41 +0900)
committerWooyeon Kim <wooy88.kim@samsung.com>
Fri, 6 Jul 2018 01:43:17 +0000 (10:43 +0900)
Change-Id: Ibbddefc595cf19142a3c2cdfcba508e1af2bd86c
Signed-off-by: ChiHun Won <chihun.won@samsung.com>
12 files changed:
drivers/video/fbdev/exynos/dpu20/bts.c
drivers/video/fbdev/exynos/dpu20/cursor.c
drivers/video/fbdev/exynos/dpu20/decon.h
drivers/video/fbdev/exynos/dpu20/decon_core.c
drivers/video/fbdev/exynos/dpu20/dpp.h
drivers/video/fbdev/exynos/dpu20/dpp_drv.c
drivers/video/fbdev/exynos/dpu20/dsim.h
drivers/video/fbdev/exynos/dpu20/dsim_drv.c
drivers/video/fbdev/exynos/dpu20/event_log.c
drivers/video/fbdev/exynos/dpu20/fence.c
drivers/video/fbdev/exynos/dpu20/helper.c
drivers/video/fbdev/exynos/dpu20/win_update.c

index 7c2be5f0d5b6777efba11e9770543210a9bc49de..178c2d48edc135892ef48d45da107bf3ccd1d5a5 100644 (file)
@@ -57,7 +57,7 @@ static void dpu_bts_sum_all_decon_bw(struct decon_device *decon, u32 ch_bw[])
 {
        int i, j;
 
-       if (decon->id < 0 || decon->id >= MAX_DECON_CNT) {
+       if (decon->id < 0 || decon->id >= decon->dt.decon_cnt) {
                decon_warn("[%s] undefined decon id(%d)!\n", __func__, decon->id);
                return;
        }
@@ -65,7 +65,7 @@ static void dpu_bts_sum_all_decon_bw(struct decon_device *decon, u32 ch_bw[])
        for (i = 0; i < BTS_DPU_MAX; ++i)
                decon->bts.ch_bw[decon->id][i] = ch_bw[i];
 
-       for (i = 0; i < MAX_DECON_CNT; ++i) {
+       for (i = 0; i < decon->dt.decon_cnt; ++i) {
                if (decon->id == i)
                        continue;
 
@@ -121,7 +121,7 @@ static void dpu_bts_find_max_disp_freq(struct decon_device *decon,
        DPU_DEBUG_BTS("\tDECON%d : resol clock = %d Khz\n",
                decon->id, decon->bts.resol_clk);
 
-       for (i = 0; i < MAX_DECON_WIN; ++i) {
+       for (i = 0; i < decon->dt.max_win; ++i) {
                idx = config[i].idma_type;
                if ((config[i].state != DECON_WIN_STATE_BUFFER) &&
                                (config[i].state != DECON_WIN_STATE_COLOR))
@@ -145,11 +145,17 @@ static void dpu_bts_share_bw_info(int id)
 {
        int i, j;
        struct decon_device *decon[3];
+       int decon_cnt;
+
+       decon_cnt = get_decon_drvdata(0)->dt.decon_cnt;
 
        for (i = 0; i < MAX_DECON_CNT; i++)
+               decon[i] = NULL;
+
+       for (i = 0; i < decon_cnt; i++)
                decon[i] = get_decon_drvdata(i);
 
-       for (i = 0; i < MAX_DECON_CNT; ++i) {
+       for (i = 0; i < decon_cnt; ++i) {
                if (id == i || decon[i] == NULL)
                        continue;
 
@@ -172,7 +178,7 @@ void dpu_bts_calc_bw(struct decon_device *decon, struct decon_reg_data *regs)
        DPU_DEBUG_BTS("%s + : DECON%d\n", __func__, decon->id);
 
        memset(&bts_info, 0, sizeof(struct bts_decon_info));
-       for (i = 0; i < MAX_DECON_WIN; ++i) {
+       for (i = 0; i < decon->dt.max_win; ++i) {
                if (config[i].state == DECON_WIN_STATE_BUFFER) {
                        idx = config[i].idma_type;
                        bts_info.dpp[idx].used = true;
index b940b5b2dfe62b58412bfd49ca7382bfd0e9bd9d..913c85cc0571805879a9c4a5690a7000718c5461 100644 (file)
@@ -88,6 +88,8 @@ void dpu_cursor_win_update_config(struct decon_device *decon,
                struct decon_reg_data *regs)
 {
        struct decon_frame src, dst;
+       struct v4l2_subdev *sd;
+       struct dpp_restriction res;
        unsigned short cur = regs->cursor_win;
 
        if (!decon->cursor.enabled)
@@ -109,6 +111,9 @@ void dpu_cursor_win_update_config(struct decon_device *decon,
                return;
        }
 
+       sd = decon->dpp_sd[0];
+       v4l2_subdev_call(sd, core, ioctl, DPP_GET_RESTRICTION, &res);
+
        memcpy(&src, &regs->dpp_config[cur].src, sizeof(struct decon_frame));
        memcpy(&dst, &regs->dpp_config[cur].dst, sizeof(struct decon_frame));
 
@@ -120,8 +125,8 @@ void dpu_cursor_win_update_config(struct decon_device *decon,
        if ((dst.y + dst.h) > decon->lcd_info->yres)
                dst.h = dst.h - ((dst.y + dst.h) - decon->lcd_info->yres);
 
-       if (dst.w > SRC_WIDTH_MAX || dst.w < SRC_WIDTH_MIN ||
-               dst.h > SRC_HEIGHT_MAX || dst.h < SRC_HEIGHT_MIN) {
+       if (dst.w > res.src_f_w.max || dst.w < res.src_f_w.min ||
+               dst.h > res.src_f_h.max || dst.h < res.src_f_h.min) {
                decon_info("not supported cursor: [%d] [%d %d] ",
                                cur, decon->lcd_info->xres,
                                decon->lcd_info->yres);
index 0dcb7f74ca8a049bd4b3afc2ba3ba44566789f1e..3b200079cfbf67801e4d7f89062a106d7446cd63 100644 (file)
@@ -57,6 +57,8 @@
 
 #define SUCCESS_EXYNOS_SMC     0
 
+#define MAX_DECON_CNT          3
+
 #if defined(CONFIG_SUPPORT_LEGACY_ION)
 extern struct ion_device *ion_exynos;
 #endif
@@ -691,6 +693,10 @@ struct decon_dt_info {
        int dft_win;
        int dft_idma;
        const char *pd_name;
+       int dpp_cnt;
+       int dsim_cnt;
+       int decon_cnt;
+       int chip_ver;
 };
 
 struct decon_win {
@@ -872,6 +878,7 @@ struct decon_device {
 
        struct v4l2_subdev *out_sd[MAX_DSIM_CNT];
        struct v4l2_subdev *dsim_sd[MAX_DSIM_CNT];
+       /* TODO: MAX_DPP_SUBDEV wil be changed to MAX_DPP_CNT */
        struct v4l2_subdev *dpp_sd[MAX_DPP_SUBDEV];
        struct v4l2_subdev *displayport_sd;
        struct v4l2_device v4l2_dev;
index 6d4d31e247d7dfd5494d83c8138a4e8c0202f0c2..1984ab51af868ace7f55e57f19ea9947fe606a3e 100644 (file)
@@ -109,7 +109,7 @@ static void decon_dump_using_dpp(struct decon_device *decon)
 {
        int i;
 
-       for (i = 0; i < MAX_DPP_SUBDEV; i++) {
+       for (i = 0; i < decon->dt.dpp_cnt; i++) {
                if (test_bit(i, &decon->prev_used_dpp)) {
                        struct v4l2_subdev *sd = NULL;
                        sd = decon->dpp_sd[i];
@@ -123,8 +123,11 @@ static void decon_up_list_saved(void)
 {
        int i;
        struct decon_device *decon;
+       int decon_cnt;
 
-       for (i = 0; i < MAX_DECON_CNT; i++) {
+       decon_cnt = get_decon_drvdata(0)->dt.decon_cnt;
+
+       for (i = 0; i < decon_cnt; i++) {
                decon = get_decon_drvdata(i);
                if (decon) {
                        if (!list_empty(&decon->up.list) || !list_empty(&decon->up.saved_list)) {
@@ -233,7 +236,7 @@ void decon_dpp_stop(struct decon_device *decon, bool do_reset)
        bool rst = false;
        struct v4l2_subdev *sd;
 
-       for (i = 0; i < MAX_DPP_SUBDEV; i++) {
+       for (i = 0; i < decon->dt.dpp_cnt; i++) {
                if (test_bit(i, &decon->prev_used_dpp) &&
                                !test_bit(i, &decon->cur_using_dpp)) {
                        sd = decon->dpp_sd[i];
@@ -1053,7 +1056,7 @@ static int decon_find_biggest_block_rect(struct decon_device *decon,
        r1.bottom = r1.top + config->dst.h - 1;
 
        /* Find the biggest block region from overlays by the top windows */
-       for (j = win_no + 1; j < MAX_DECON_WIN; j++) {
+       for (j = win_no + 1; j < decon->dt.max_win; j++) {
                config = &win_config[j];
                if (config->state != DECON_WIN_STATE_BUFFER)
                        continue;
@@ -1557,7 +1560,7 @@ static int decon_set_dpp_config(struct decon_device *decon,
 
        if (decon->dt.out_type == DECON_OUT_WB) {
                sd = decon->dpp_sd[ODMA_WB];
-               memcpy(&dpp_config.config, &regs->dpp_config[MAX_DECON_WIN],
+               memcpy(&dpp_config.config, &regs->dpp_config[decon->dt.max_win],
                                sizeof(struct decon_win_config));
                dpp_config.rcv_num = aclk_khz;
                ret = v4l2_subdev_call(sd, core, ioctl, DPP_WIN_CONFIG,
@@ -1841,7 +1844,7 @@ static void decon_release_old_bufs(struct decon_device *decon,
        if (decon->dt.out_type == DECON_OUT_WB) {
                for (j = 0; j < plane_cnt[0]; ++j)
                        decon_free_dma_buf(decon,
-                                       &regs->dma_buf_data[MAX_DECON_WIN][j]);
+                                       &regs->dma_buf_data[decon->dt.max_win][j]);
        }
 }
 
@@ -2301,12 +2304,12 @@ static int decon_prepare_win_config(struct decon_device *decon,
        }
 
        if (decon->dt.out_type == DECON_OUT_WB) {
-               regs->protection[MAX_DECON_WIN] = win_config[MAX_DECON_WIN].protection;
-               ret = decon_import_buffer(decon, MAX_DECON_WIN,
-                               &win_config[MAX_DECON_WIN], regs);
+               regs->protection[decon->dt.max_win] = win_config[decon->dt.max_win].protection;
+               ret = decon_import_buffer(decon, decon->dt.max_win,
+                               &win_config[decon->dt.max_win], regs);
        }
 
-       for (i = 0; i < MAX_DPP_SUBDEV; i++) {
+       for (i = 0; i < decon->dt.dpp_cnt; i++) {
                memcpy(&regs->dpp_config[i], &win_config[i],
                                sizeof(struct decon_win_config));
                regs->dpp_config[i].format =
@@ -2586,7 +2589,7 @@ static int decon_ioctl(struct fb_info *info, unsigned int cmd,
 
                decon_info("HWC version %d.0 is operating\n", disp_info.ver);
                disp_info.psr_mode = decon->dt.psr_mode;
-               disp_info.chip_ver = CHIP_VER;
+               disp_info.chip_ver = decon->dt.chip_ver;
                disp_info.mres_info = *mres_info;
 
                if (copy_to_user(argp_info,
@@ -2886,7 +2889,7 @@ static int decon_register_subdevs(struct decon_device *decon)
                return ret;
        }
 
-       for (i = 0;  i < MAX_DPP_SUBDEV; ++i)
+       for (i = 0;  i < MAX_DPP_CNT; ++i)
                decon->dpp_sd[i] = NULL;
        ret = dpu_get_sd_by_drvname(decon, DPP_MODULE_NAME);
        if (ret)
@@ -2904,7 +2907,7 @@ static int decon_register_subdevs(struct decon_device *decon)
 #endif
 
        if (!decon->id) {
-               for (i = 0; i < MAX_DPP_SUBDEV; i++) {
+               for (i = 0; i < decon->dt.dpp_cnt; i++) {
                        if (IS_ERR_OR_NULL(decon->dpp_sd[i]))
                                continue;
                        ret = v4l2_device_register_subdev(v4l2_dev,
@@ -2915,7 +2918,7 @@ static int decon_register_subdevs(struct decon_device *decon)
                        }
                }
 
-               for (i = 0; i < MAX_DSIM_CNT; i++) {
+               for (i = 0; i < decon->dt.dsim_cnt; i++) {
                        if (decon->dsim_sd[i] == NULL || i == 1)
                                continue;
 
@@ -2960,13 +2963,13 @@ static void decon_unregister_subdevs(struct decon_device *decon)
        int i;
 
        if (!decon->id) {
-               for (i = 0; i < MAX_DPP_SUBDEV; i++) {
+               for (i = 0; i < decon->dt.dpp_cnt; i++) {
                        if (decon->dpp_sd[i] == NULL)
                                continue;
                        v4l2_device_unregister_subdev(decon->dpp_sd[i]);
                }
 
-               for (i = 0; i < MAX_DSIM_CNT; i++) {
+               for (i = 0; i < decon->dt.dsim_cnt; i++) {
                        if (decon->dsim_sd[i] == NULL || i == 1)
                                continue;
                        v4l2_device_unregister_subdev(decon->dsim_sd[i]);
@@ -3299,11 +3302,9 @@ static void decon_parse_dt(struct decon_device *decon)
        of_property_read_u32(dev->of_node, "psr_mode",
                        &decon->dt.psr_mode);
        /* H/W trigger: 0, S/W trigger: 1 */
-       of_property_read_u32(dev->of_node, "trig_mode",
-                       &decon->dt.trig_mode);
-       decon_info("decon-%s: max win%d, %s mode, %s trigger\n",
-                       (decon->id == 0) ? "f" : ((decon->id == 1) ? "s" : "t"),
-                       decon->dt.max_win,
+       of_property_read_u32(dev->of_node, "trig_mode", &decon->dt.trig_mode);
+       decon_info("decon%d: max win%d, %s mode, %s trigger\n",
+                       decon->id, decon->dt.max_win,
                        decon->dt.psr_mode ? "command" : "video",
                        decon->dt.trig_mode ? "sw" : "hw");
 
@@ -3322,6 +3323,13 @@ static void decon_parse_dt(struct decon_device *decon)
 
        decon_info("PPC(%llu)\n", decon->bts.ppc);
 
+       of_property_read_u32(dev->of_node, "chip_ver", &decon->dt.chip_ver);
+       of_property_read_u32(dev->of_node, "dpp_cnt", &decon->dt.dpp_cnt);
+       of_property_read_u32(dev->of_node, "dsim_cnt", &decon->dt.dsim_cnt);
+       of_property_read_u32(dev->of_node, "decon_cnt", &decon->dt.decon_cnt);
+       decon_info("chip_ver %d, dpp cnt %d, dsim cnt %d\n", decon->dt.chip_ver,
+                       decon->dt.dpp_cnt, decon->dt.dsim_cnt);
+
        if (decon->dt.out_type == DECON_OUT_DSI) {
                ret = of_property_read_u32_index(dev->of_node, "out_idx", 0,
                                &decon->dt.out_idx[0]);
index b30378514860b45d2c04a422a1bd886278574d4c..266d6c81e1eb00f6ceca28a72402ebc50d8f73b5 100644 (file)
@@ -41,6 +41,7 @@
 extern int dpp_log_level;
 
 #define DPP_MODULE_NAME                "exynos-dpp"
+#define MAX_DPP_CNT            7 /* + ODMA case */
 
 /* about 1msec @ ACLK=630MHz */
 #define INIT_RCV_NUM           630000
@@ -146,6 +147,52 @@ struct dpp_config {
        unsigned long rcv_num;
 };
 
+struct dpp_size_range {
+       u32 min;
+       u32 max;
+       u32 align;
+};
+
+struct dpp_restriction {
+       struct dpp_size_range src_f_w;
+       struct dpp_size_range src_f_h;
+       struct dpp_size_range src_w;
+       struct dpp_size_range src_h;
+       u32 src_x_align;
+       u32 src_y_align;
+
+       struct dpp_size_range dst_f_w;
+       struct dpp_size_range dst_f_h;
+       struct dpp_size_range dst_w;
+       struct dpp_size_range dst_h;
+       u32 dst_x_align;
+       u32 dst_y_align;
+
+       struct dpp_size_range blk_w;
+       struct dpp_size_range blk_h;
+       u32 blk_x_align;
+       u32 blk_y_align;
+
+       u32 src_h_rot_max; /* limit of source img height in case of rotation */
+
+       u32 *format; /* supported format list for each DPP channel */
+       u32 reserved[8];
+};
+
+struct dpp_ch_restriction {
+       int id;
+       unsigned long attr;
+
+       struct dpp_restriction restriction;
+       u32 reserved[4];
+};
+
+struct dpp_restrictions_info {
+       u32 ver; /* version of dpp_restrictions_info structure */
+       struct dpp_ch_restriction dpp_ch[MAX_DPP_CNT];
+       u32 reserved[4];
+};
+
 struct dpp_device {
        int id;
        int port;
@@ -160,16 +207,14 @@ struct dpp_device {
        spinlock_t slock;
        spinlock_t dma_slock;
        struct mutex lock;
+       struct dpp_restriction restriction;
 };
 
 extern struct dpp_device *dpp_drvdata[MAX_DPP_CNT];
 
 static inline struct dpp_device *get_dpp_drvdata(u32 id)
 {
-       if (id >= MAX_DPP_CNT)
-               return NULL;
-       else
-               return dpp_drvdata[id];
+       return dpp_drvdata[id];
 }
 
 static inline u32 dpp_read(u32 id, u32 reg_id)
@@ -284,5 +329,6 @@ void dpp_dump(struct dpp_device *dpp);
 #define DPP_WAIT_IDLE                  _IOR('P', 4, unsigned long)
 #define DPP_SET_RECOVERY_NUM           _IOR('P', 5, unsigned long)
 #define DPP_GET_PORT_NUM               _IOR('P', 7, unsigned long)
+#define DPP_GET_RESTRICTION            _IOR('P', 8, unsigned long)
 
 #endif /* __SAMSUNG_DPP_H__ */
index e9631456f79401fb40b195889567ad04e5d1e59c..3400c34c614774242a0c495730b7e2f0bed94434 100644 (file)
@@ -79,6 +79,7 @@ static void dpp_get_params(struct dpp_device *dpp, struct dpp_params_info *p)
 {
        u64 src_w, src_h, dst_w, dst_h;
        struct decon_win_config *config = &dpp->dpp_config->config;
+       struct dpp_restriction *res = &dpp->restriction;
 
        p->rcv_num = dpp->dpp_config->rcv_num;
        memcpy(&p->src, &config->src, sizeof(struct decon_frame));
@@ -145,7 +146,7 @@ static void dpp_get_params(struct dpp_device *dpp, struct dpp_params_info *p)
 
        if ((config->dpp_parm.rot != DPP_ROT_NORMAL) || (p->is_scale) ||
                (p->format >= DECON_PIXEL_FORMAT_NV16) ||
-               (p->block.w < BLK_WIDTH_MIN) || (p->block.h < BLK_HEIGHT_MIN))
+               (p->block.w < res->blk_w.min) || (p->block.h < res->blk_h.min))
                p->is_block = false;
        else
                p->is_block = true;
@@ -158,7 +159,7 @@ static int dpp_check_size(struct dpp_device *dpp, struct dpp_img_format *vi)
        struct decon_frame *dst = &config->dst;
        struct dpp_size_constraints vc;
 
-       dpp_constraints_params(&vc, vi);
+       dpp_constraints_params(&vc, vi, &dpp->restriction);
 
        if ((!check_align(src->x, src->y, vc.src_mul_x, vc.src_mul_y)) ||
           (!check_align(src->f_w, src->f_h, vc.src_mul_w, vc.src_mul_h)) ||
@@ -524,6 +525,11 @@ static long dpp_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg
                *(int *)arg = dpp->port;
                break;
 
+       case DPP_GET_RESTRICTION:
+               memcpy((struct dpp_restriction *)arg, &dpp->restriction,
+                               sizeof(struct dpp_restriction));
+               break;
+
        default:
                break;
        }
@@ -550,15 +556,128 @@ static void dpp_init_subdev(struct dpp_device *dpp)
        v4l2_set_subdevdata(sd, dpp);
 }
 
+static void dpp_parse_restriction(struct dpp_device *dpp, struct device_node *n)
+{
+       u32 range[3] = {0, };
+       u32 align[2] = {0, };
+
+       dpp_info("dpp restriction\n");
+       of_property_read_u32_array(n, "src_f_w", range, 3);
+       dpp->restriction.src_f_w.min = range[0];
+       dpp->restriction.src_f_w.max = range[1];
+       dpp->restriction.src_f_w.align = range[2];
+
+       of_property_read_u32_array(n, "src_f_h", range, 3);
+       dpp->restriction.src_f_h.min = range[0];
+       dpp->restriction.src_f_h.max = range[1];
+       dpp->restriction.src_f_h.align = range[2];
+
+       of_property_read_u32_array(n, "src_w", range, 3);
+       dpp->restriction.src_w.min = range[0];
+       dpp->restriction.src_w.max = range[1];
+       dpp->restriction.src_w.align = range[2];
+
+       of_property_read_u32_array(n, "src_h", range, 3);
+       dpp->restriction.src_h.min = range[0];
+       dpp->restriction.src_h.max = range[1];
+       dpp->restriction.src_h.align = range[2];
+
+       of_property_read_u32_array(n, "src_xy_align", align, 2);
+       dpp->restriction.src_x_align = align[0];
+       dpp->restriction.src_y_align = align[1];
+
+       of_property_read_u32_array(n, "dst_f_w", range, 3);
+       dpp->restriction.dst_f_w.min = range[0];
+       dpp->restriction.dst_f_w.max = range[1];
+       dpp->restriction.dst_f_w.align = range[2];
+
+       of_property_read_u32_array(n, "dst_f_h", range, 3);
+       dpp->restriction.dst_f_h.min = range[0];
+       dpp->restriction.dst_f_h.max = range[1];
+       dpp->restriction.dst_f_h.align = range[2];
+
+       of_property_read_u32_array(n, "dst_w", range, 3);
+       dpp->restriction.dst_w.min = range[0];
+       dpp->restriction.dst_w.max = range[1];
+       dpp->restriction.dst_w.align = range[2];
+
+       of_property_read_u32_array(n, "dst_h", range, 3);
+       dpp->restriction.dst_h.min = range[0];
+       dpp->restriction.dst_h.max = range[1];
+       dpp->restriction.dst_h.align = range[2];
+
+       of_property_read_u32_array(n, "dst_xy_align", align, 2);
+       dpp->restriction.dst_x_align = align[0];
+       dpp->restriction.dst_y_align = align[1];
+
+       of_property_read_u32_array(n, "blk_w", range, 3);
+       dpp->restriction.blk_w.min = range[0];
+       dpp->restriction.blk_w.max = range[1];
+       dpp->restriction.blk_w.align = range[2];
+
+       of_property_read_u32_array(n, "blk_h", range, 3);
+       dpp->restriction.blk_h.min = range[0];
+       dpp->restriction.blk_h.max = range[1];
+       dpp->restriction.blk_h.align = range[2];
+
+       of_property_read_u32_array(n, "blk_xy_align", align, 2);
+       dpp->restriction.blk_x_align = align[0];
+       dpp->restriction.blk_y_align = align[1];
+
+       if (of_property_read_u32(n, "src_h_rot_max",
+                               &dpp->restriction.src_h_rot_max))
+               dpp->restriction.src_h_rot_max = dpp->restriction.src_h.max;
+}
+
+static void dpp_print_restriction(struct dpp_device *dpp)
+{
+       struct dpp_restriction *res = &dpp->restriction;
+
+       dpp_info("src_f_w[%d %d %d] src_f_h[%d %d %d]\n",
+                       res->src_f_w.min, res->src_f_w.max, res->src_f_w.align,
+                       res->src_f_h.min, res->src_f_h.max, res->src_f_h.align);
+       dpp_info("src_w[%d %d %d] src_h[%d %d %d] src_x_y_align[%d %d]\n",
+                       res->src_w.min, res->src_w.max, res->src_w.align,
+                       res->src_h.min, res->src_h.max, res->src_h.align,
+                       res->src_x_align, res->src_y_align);
+
+       dpp_info("dst_f_w[%d %d %d] dst_f_h[%d %d %d]\n",
+                       res->dst_f_w.min, res->dst_f_w.max, res->dst_f_w.align,
+                       res->dst_f_h.min, res->dst_f_h.max, res->dst_f_h.align);
+       dpp_info("dst_w[%d %d %d] dst_h[%d %d %d] dst_x_y_align[%d %d]\n",
+                       res->dst_w.min, res->dst_w.max, res->dst_w.align,
+                       res->dst_h.min, res->dst_h.max, res->dst_h.align,
+                       res->dst_x_align, res->dst_y_align);
+
+       dpp_info("blk_w[%d %d %d] blk_h[%d %d %d] blk_x_y_align[%d %d]\n",
+                       res->blk_w.min, res->blk_w.max, res->blk_w.align,
+                       res->blk_h.min, res->blk_h.max, res->blk_h.align,
+                       res->blk_x_align, res->blk_y_align);
+
+       dpp_info("src_h_rot_max[%d]\n", res->src_h_rot_max);
+}
+
 static void dpp_parse_dt(struct dpp_device *dpp, struct device *dev)
 {
+       struct device_node *node = dev->of_node;
+       struct dpp_device *dpp0 = get_dpp_drvdata(0);
+
        dpp->id = of_alias_get_id(dev->of_node, "dpp");
        dpp_info("dpp(%d) probe start..\n", dpp->id);
-       of_property_read_u32(dev->of_node, "attr", (u32 *)&dpp->attr);
+       of_property_read_u32(node, "attr", (u32 *)&dpp->attr);
        dpp_info("attributes = 0x%lx\n", dpp->attr);
-       of_property_read_u32(dev->of_node, "port", (u32 *)&dpp->port);
+       of_property_read_u32(node, "port", (u32 *)&dpp->port);
        dpp_info("AXI port = %d\n", dpp->port);
 
+       if (dpp->id == 0) {
+               dpp_parse_restriction(dpp, node);
+               dpp_print_restriction(dpp);
+       } else {
+               memcpy(&dpp->restriction, &dpp0->restriction,
+                               sizeof(struct dpp_restriction));
+               dpp_print_restriction(dpp);
+       }
+
        dpp->dev = dev;
 }
 
index fb402f95c3ea7228caa26a7db67e1d568d409750..6e1c0e63d0ac4adffb183cf8071b6e5c599ae358 100644 (file)
@@ -42,6 +42,7 @@
 extern int dsim_log_level;
 
 #define DSIM_MODULE_NAME                       "exynos-dsim"
+#define MAX_DSIM_CNT                           2
 #define DSIM_DDI_ID_LEN                                3
 
 #define DSIM_PIXEL_FORMAT_RGB24                        0x3E
index 93a1c379b664effdeceb201931dda2c5e8ba118d..e1be71c31e027670c9f895006b8a35af3d4cee3c 100644 (file)
@@ -424,14 +424,16 @@ static void dsim_underrun_info(struct dsim_device *dsim)
 {
 #if defined(CONFIG_EXYNOS9610_BTS)
        struct decon_device *decon;
-       int i;
+       int i, decon_cnt;
 
        dsim_info("\tMIF(%lu), INT(%lu), DISP(%lu)\n",
                        cal_dfs_get_rate(ACPM_DVFS_MIF),
                        cal_dfs_get_rate(ACPM_DVFS_INT),
                        cal_dfs_get_rate(ACPM_DVFS_DISP));
 
-       for (i = 0; i < MAX_DECON_CNT; ++i) {
+       decon_cnt = get_decon_drvdata(0)->dt.decon_cnt;
+
+       for (i = 0; i < decon_cnt; ++i) {
                decon = get_decon_drvdata(i);
 
                if (decon) {
index 6f118d8c6f8116eec15beb505e4726777615292d..e194c25858e828041a512458e348104c2954312a 100644 (file)
@@ -124,8 +124,11 @@ static int __get_decon_id_for_dpp(struct v4l2_subdev *sd)
        struct dpp_device *dpp = v4l2_get_subdevdata(sd);
        int idx;
        int ret = 0;
+       int decon_cnt;
 
-       for (idx = 0; idx < MAX_DECON_CNT; idx++) {
+       decon_cnt = get_decon_drvdata(0)->dt.decon_cnt;
+
+       for (idx = 0; idx < decon_cnt; idx++) {
                decon = get_decon_drvdata(idx);
                if (!decon || IS_ERR_OR_NULL(decon->d.debug_event))
                        continue;
@@ -310,7 +313,7 @@ void DPU_EVENT_LOG_WINCON(struct v4l2_subdev *sd, struct decon_reg_data *regs)
        log->time = ktime_get();
        log->type = DPU_EVT_UPDATE_HANDLER;
 
-       for (win = 0; win < MAX_DECON_WIN; win++) {
+       for (win = 0; win < decon->dt.max_win; win++) {
                if (regs->win_regs[win].wincon & WIN_EN_F(win)) {
                        memcpy(&log->data.reg.win_regs[win], &regs->win_regs[win],
                                sizeof(struct decon_window_regs));
@@ -393,7 +396,7 @@ void DPU_EVENT_LOG_CURSOR(struct v4l2_subdev *sd, struct decon_reg_data *regs)
        log->time = ktime_get();
        log->type = DPU_EVT_CURSOR_UPDATE;
 
-       for (win = 0; win < MAX_DECON_WIN; win++) {
+       for (win = 0; win < decon->dt.max_win; win++) {
                if (regs->is_cursor_win[win] && regs->win_regs[win].wincon & WIN_EN_F(win)) {
                        memcpy(&log->data.reg.win_regs[win], &regs->win_regs[win],
                                sizeof(struct decon_window_regs));
index 40ea61c4874ac65925b811f1c21061418888fd18..14d4132a86670e8978247b156abd8b82607cb559 100644 (file)
@@ -72,7 +72,7 @@ void decon_create_release_fences(struct decon_device *decon,
 {
        int i = 0;
 
-       for (i = 0; i < MAX_DECON_WIN; i++) {
+       for (i = 0; i < decon->dt.max_win; i++) {
                int state = win_data->config[i].state;
                int rel_fence = -1;
 
@@ -201,7 +201,7 @@ void decon_create_release_fences(struct decon_device *decon,
 {
        int i = 0;
 
-       for (i = 0; i < MAX_DECON_WIN; i++) {
+       for (i = 0; i < decon->dt.max_win; i++) {
                int state = win_data->config[i].state;
                int rel_fence = -1;
 
index 0d22eb714336a8d9dc346b33d915d2847f30d5d0..21e42c1807124be03c14282ee66d18729ed22db0 100644 (file)
@@ -543,12 +543,16 @@ void decon_set_protected_content(struct decon_device *decon,
        /* ODMA protection config (WB: writeback) */
        if (decon->dt.out_type == DECON_OUT_WB)
                if (regs)
-                       cur_protect_bits |= (regs->protection[MAX_DECON_WIN] << ODMA_WB);
+                       cur_protect_bits |= (regs->protection[decon->dt.max_win] << ODMA_WB);
 
        if (decon->prev_protection_bitmask != cur_protect_bits) {
 
                /* apply protection configs for each DMA */
-               for (dma_id = 0; dma_id < MAX_DPP_CNT; dma_id++) {
+               for (dma_id = 0; dma_id < decon->dt.max_win; dma_id++) {
+                       /*
+                        * This loop should use max_win instead of dpp_cnt,
+                        * because dpp_cnt includes writeback case
+                        */
                        en = cur_protect_bits & (1 << dma_id);
 
                        change = (cur_protect_bits & (1 << dma_id)) ^
@@ -582,7 +586,7 @@ void dpu_dump_afbc_info(void)
        void *v_addr[2];
        int size[2];
 
-       for (i = 0; i < MAX_DECON_CNT; i++) {
+       for (i = 0; i < 3; i++) {
                decon = get_decon_drvdata(i);
                if (decon == NULL)
                        continue;
@@ -624,13 +628,16 @@ static int dpu_dump_buffer_data(struct dpp_device *dpp)
        int i;
        int id_idx = 0;
        int dump_size = 128;
+       int decon_cnt;
        struct decon_device *decon;
        struct dpu_afbc_info *afbc_info;
        void *v_addr;
 
+       decon_cnt = get_decon_drvdata(0)->dt.decon_cnt;
+
        if (dpp->state == DPP_STATE_ON) {
 
-               for (i = 0; i < MAX_DECON_CNT; i++) {
+               for (i = 0; i < decon_cnt; i++) {
                        decon = get_decon_drvdata(i);
                        if (decon == NULL)
                                continue;
@@ -681,7 +688,7 @@ int dpu_sysmmu_fault_handler(struct iommu_domain *domain,
                return -EINVAL;
        }
 
-       for (i = 0; i < MAX_DPP_SUBDEV; i++) {
+       for (i = 0; i < decon->dt.dpp_cnt; i++) {
                if (test_bit(i, &decon->prev_used_dpp)) {
                        dpp = get_dpp_drvdata(i);
 #if defined(CONFIG_EXYNOS_AFBC_DEBUG)
index 06c7efe8b9f2513755be5d279c6d47e79d219363..a144bda6d5855b5049fa00ebef66be3105a209a7 100644 (file)
@@ -94,6 +94,8 @@ static void win_update_check_limitation(struct decon_device *decon,
        struct decon_win_config *config;
        struct decon_win_rect update;
        struct decon_rect r;
+       struct v4l2_subdev *sd;
+       struct dpp_restriction res;
        int i;
        int sz_align = 1;
        int adj_src_x = 0, adj_src_y = 0;
@@ -103,6 +105,7 @@ static void win_update_check_limitation(struct decon_device *decon,
                if (config->state == DECON_WIN_STATE_DISABLED)
                        continue;
 
+
                r.left = config->dst.x;
                r.top = config->dst.y;
                r.right = config->dst.w + config->dst.x - 1;
@@ -131,8 +134,11 @@ static void win_update_check_limitation(struct decon_device *decon,
                                goto change_full;
                }
 
-               if (((r.right - r.left) < (SRC_WIDTH_MIN * sz_align)) ||
-                               ((r.bottom - r.top) < (SRC_HEIGHT_MIN * sz_align))) {
+               sd = decon->dpp_sd[0];
+               v4l2_subdev_call(sd, core, ioctl, DPP_GET_RESTRICTION, &res);
+
+               if (((r.right - r.left) < (res.src_f_w.min * sz_align)) ||
+                               ((r.bottom - r.top) < (res.src_f_h.min * sz_align))) {
                        goto change_full;
                }