drm/rockchip: vop: add display input/output limit
authorMark Yao <mark.yao@rock-chips.com>
Thu, 19 Jan 2017 09:14:06 +0000 (17:14 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Fri, 20 Jan 2017 03:00:55 +0000 (11:00 +0800)
Change-Id: If218ca6d2de5c05b6f8ed417cefa437c62c31935
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.h
drivers/gpu/drm/rockchip/rockchip_vop_reg.c

index ce906e87e6b9ea3009f2d37ab909525018ecc511..7e8079ec2782b83c3c401206f8a2e068272ef41d 100644 (file)
@@ -448,11 +448,6 @@ static void scl_vop_cal_scl_fac(struct vop *vop, struct vop_win *win,
        if (!win->phy->scl)
                return;
 
-       if (dst_w > 3840) {
-               DRM_ERROR("Maximum destination width (3840) exceeded\n");
-               return;
-       }
-
        if (!win->phy->scl->ext) {
                VOP_SCL_SET(vop, win, scale_yrgb_x,
                            scl_cal_scale2(src_w, dst_w));
@@ -902,6 +897,8 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        struct vop_win *win = to_vop_win(plane);
        struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
        struct drm_crtc_state *crtc_state;
+       const struct vop_data *vop_data;
+       struct vop *vop;
        bool visible;
        int ret;
        struct drm_rect *dest = &vop_plane_state->dest;
@@ -954,6 +951,29 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        if (vop_plane_state->format < 0)
                return vop_plane_state->format;
 
+       vop = to_vop(crtc);
+       vop_data = vop->data;
+
+       if (drm_rect_width(src) >> 16 > vop_data->max_input_fb.width ||
+           drm_rect_height(src) >> 16 > vop_data->max_input_fb.height) {
+               DRM_ERROR("Invalid source: %dx%d. max input: %dx%d\n",
+                         drm_rect_width(src) >> 16,
+                         drm_rect_height(src) >> 16,
+                         vop_data->max_input_fb.width,
+                         vop_data->max_input_fb.height);
+               return -EINVAL;
+       }
+
+       if (drm_rect_width(dest) >> 16 > vop_data->max_input_fb.width ||
+           drm_rect_height(dest) >> 16 > vop_data->max_input_fb.height) {
+               DRM_ERROR("Invalid destination: %dx%d. max output: %dx%d\n",
+                         drm_rect_width(dest),
+                         drm_rect_height(dest),
+                         vop_data->max_output_fb.width,
+                         vop_data->max_output_fb.height);
+               return -EINVAL;
+       }
+
        /*
         * Src.x1 can be odd when do clip, but yuv plane start point
         * need align with 2 pixel.
@@ -1396,6 +1416,11 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
                                struct drm_display_mode *adjusted_mode)
 {
        struct vop *vop = to_vop(crtc);
+       const struct vop_data *vop_data = vop->data;
+
+       if (mode->hdisplay > vop_data->max_disably_output.width ||
+           mode->vdisplay > vop_data->max_disably_output.height)
+               return false;
 
        adjusted_mode->clock =
                clk_round_rate(vop->dclk, mode->clock * 1000) / 1000;
index de9685093aca917217f9d1be71f8d90fbe515943..14174bc3d97a9edd2280778493b7b9bd151276f4 100644 (file)
@@ -248,6 +248,11 @@ struct vop_win_data {
 #define VOP_FEATURE_OUTPUT_10BIT       BIT(0)
 #define VOP_FEATURE_AFBDC              BIT(1)
 
+struct vop_rect {
+       int width;
+       int height;
+};
+
 struct vop_data {
        const struct vop_reg_data *init_table;
        unsigned int table_size;
@@ -257,6 +262,9 @@ struct vop_data {
        const struct vop_csc_table *csc_table;
        unsigned int win_size;
        uint32_t version;
+       struct vop_rect max_input_fb;
+       struct vop_rect max_output_fb;
+       struct vop_rect max_disably_output;
        u64 feature;
 };
 
index e64fbed9b49433b01209e4bf784e4648c8262926..11e950891114d5073ec16b957b614931e8417f41 100644 (file)
@@ -266,6 +266,14 @@ static const struct vop_intr rk3288_vop_intr = {
 static const struct vop_data rk3288_vop = {
        .version = VOP_VERSION(3, 1),
        .feature = VOP_FEATURE_OUTPUT_10BIT,
+       .max_input_fb = { 4096, 8192},
+       .max_output_fb = { 3840, 2160},
+       /*
+        * TODO: rk3288 have two vop, big one support 3840x2160,
+        * little one only support 2560x1600.
+        * Now force use 3840x2160.
+        */
+       .max_disably_output = { 3840, 2160},
        .intr = &rk3288_vop_intr,
        .ctrl = &rk3288_ctrl_data,
        .win = rk3288_vop_win_data,
@@ -369,6 +377,9 @@ static const struct vop_win_data rk3368_vop_win_data[] = {
 static const struct vop_data rk3368_vop = {
        .version = VOP_VERSION(3, 2),
        .feature = VOP_FEATURE_OUTPUT_10BIT,
+       .max_input_fb = { 4096, 8192},
+       .max_output_fb = { 4096, 2160},
+       .max_disably_output = { 4096, 2160},
        .intr = &rk3368_vop_intr,
        .ctrl = &rk3288_ctrl_data,
        .win = rk3368_vop_win_data,
@@ -388,6 +399,9 @@ static const struct vop_intr rk3366_vop_intr = {
 static const struct vop_data rk3366_vop = {
        .version = VOP_VERSION(3, 4),
        .feature = VOP_FEATURE_OUTPUT_10BIT,
+       .max_input_fb = { 4096, 8192},
+       .max_output_fb = { 4096, 2160},
+       .max_disably_output = { 4096, 2160},
        .intr = &rk3366_vop_intr,
        .ctrl = &rk3288_ctrl_data,
        .win = rk3368_vop_win_data,
@@ -497,6 +511,9 @@ static const struct vop_data rk3399_vop_big = {
        .version = VOP_VERSION(3, 5),
        .csc_table = &rk3399_csc_table,
        .feature = VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_AFBDC,
+       .max_input_fb = { 4096, 8192},
+       .max_output_fb = { 4096, 2160},
+       .max_disably_output = { 4096, 2160},
        .intr = &rk3366_vop_intr,
        .ctrl = &rk3288_ctrl_data,
        .win = rk3399_vop_win_data,
@@ -518,6 +535,9 @@ static const struct vop_win_data rk3399_vop_lit_win_data[] = {
 static const struct vop_data rk3399_vop_lit = {
        .version = VOP_VERSION(3, 6),
        .csc_table = &rk3399_csc_table,
+       .max_input_fb = { 4096, 8192},
+       .max_output_fb = { 2560, 1600},
+       .max_disably_output = { 2560, 1600},
        .intr = &rk3366_vop_intr,
        .ctrl = &rk3288_ctrl_data,
        .win = rk3399_vop_lit_win_data,
@@ -527,6 +547,9 @@ static const struct vop_data rk3399_vop_lit = {
 static const struct vop_data rk322x_vop = {
        .version = VOP_VERSION(3, 7),
        .feature = VOP_FEATURE_OUTPUT_10BIT,
+       .max_input_fb = { 4096, 8192},
+       .max_output_fb = { 4096, 2160},
+       .max_disably_output = { 4096, 2160},
        .intr = &rk3366_vop_intr,
        .ctrl = &rk3288_ctrl_data,
        .win = rk3368_vop_win_data,
@@ -611,6 +634,9 @@ static const struct vop_ctrl rk3036_ctrl_data = {
 
 static const struct vop_data rk3036_vop = {
        .version = VOP_VERSION(2, 2),
+       .max_input_fb = { 1920, 1080},
+       .max_output_fb = { 1920, 1080},
+       .max_disably_output = { 1920, 1080},
        .ctrl = &rk3036_ctrl_data,
        .intr = &rk3036_intr,
        .win = rk3036_vop_win_data,