Loading drivers/video/fbdev/msm/mdss_compat_utils.c +1 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,7 @@ static struct mdp_input_layer *__create_layer_list( layer->flags = layer32->flags; layer->pipe_ndx = layer32->pipe_ndx; layer->rect_num = layer32->rect_num; layer->horz_deci = layer32->horz_deci; layer->vert_deci = layer32->vert_deci; layer->z_order = layer32->z_order; Loading drivers/video/fbdev/msm/mdss_compat_utils.h +2 −1 Original line number Diff line number Diff line Loading @@ -515,7 +515,8 @@ struct mdp_input_layer32 { struct mdp_layer_buffer buffer; compat_caddr_t pp_info; int error_code; uint32_t reserved[6]; uint32_t rect_num; uint32_t reserved[5]; }; struct mdp_output_layer32 { Loading drivers/video/fbdev/msm/mdss_mdp_layer.c +128 −85 Original line number Diff line number Diff line Loading @@ -2160,115 +2160,157 @@ static int __multirect_validate_mode(struct msm_fb_data_type *mfd, return 0; } static int __update_multirect_info(struct msm_fb_data_type *mfd, struct mdss_mdp_validate_info_t *validate_info_list, struct mdp_input_layer *layer_list, int ndx, int layer_cnt) /* * linear search for a layer with given source pipe and rectangle number. * If rectangle number is invalid, it's dropped from search criteria */ static int find_layer(enum mdss_mdp_sspp_index pnum, int rect_num, struct mdp_input_layer *layer_list, size_t layer_cnt, int start_index) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); struct mdss_mdp_validate_info_t *vinfo[MDSS_MDP_PIPE_MAX_RECTS]; int i, ptype, max_rects, mode; int cnt = 1; mode = __multirect_layer_flags_to_mode(layer_list[ndx].flags); if (IS_ERR_VALUE(mode)) return mode; int i; pr_debug("layer #%d pipe_ndx=%d multirect mode=%d\n", ndx, layer_list[ndx].pipe_ndx, mode); if (start_index < 0) start_index = 0; vinfo[0] = &validate_info_list[ndx]; vinfo[0]->layer = &layer_list[ndx]; vinfo[0]->multirect.mode = mode; vinfo[0]->multirect.num = MDSS_MDP_PIPE_RECT0; vinfo[0]->multirect.next = NULL; if (start_index >= layer_cnt) return -EINVAL; /* nothing to be done if multirect is disabled */ if (mode == MDSS_MDP_PIPE_MULTIRECT_NONE) return cnt; for (i = start_index; i < layer_cnt; i++) { if (get_pipe_num_from_ndx(layer_list[i].pipe_ndx) == pnum && (rect_num < MDSS_MDP_PIPE_RECT0 || rect_num >= MDSS_MDP_PIPE_MAX_RECTS || layer_list[i].rect_num == rect_num)) return i; } ptype = get_pipe_type_from_ndx(layer_list[ndx].pipe_ndx); if (ptype == MDSS_MDP_PIPE_TYPE_INVALID) { pr_err("invalid pipe ndx %d\n", layer_list[ndx].pipe_ndx); return -EINVAL; return -ENOENT; /* no match found */ } max_rects = mdata->rects_per_sspp[ptype] ? : 1; static int __validate_multirect_param(struct msm_fb_data_type *mfd, struct mdss_mdp_validate_info_t *validate_info_list, struct mdp_input_layer *layer_list, int ndx, size_t layer_count) { int multirect_mode; int pnum; int rect_num; /* populate v_info with default values */ validate_info_list[ndx].layer = &layer_list[ndx]; validate_info_list[ndx].multirect.max_rects = MDSS_MDP_PIPE_MAX_RECTS; validate_info_list[ndx].multirect.next = NULL; validate_info_list[ndx].multirect.num = MDSS_MDP_PIPE_RECT0; validate_info_list[ndx].multirect.mode = MDSS_MDP_PIPE_MULTIRECT_NONE; multirect_mode = __multirect_layer_flags_to_mode( layer_list[ndx].flags); if (IS_ERR_VALUE(multirect_mode)) return multirect_mode; for (i = ndx + 1; i < layer_cnt; i++) { if (layer_list[ndx].pipe_ndx == layer_list[i].pipe_ndx) { if (cnt >= max_rects) { pr_err("more than %d layers of type %d with same pipe_ndx=%d indexes=%d %d\n", max_rects, ptype, layer_list[ndx].pipe_ndx, ndx, i); /* nothing to be done if multirect is disabled */ if (multirect_mode == MDSS_MDP_PIPE_MULTIRECT_NONE) return 0; validate_info_list[ndx].multirect.mode = multirect_mode; pnum = get_pipe_num_from_ndx(layer_list[ndx].pipe_ndx); if (get_pipe_type_from_num(pnum) != MDSS_MDP_PIPE_TYPE_DMA) { pr_err("Multirect not supported on pipe ndx 0x%x\n", layer_list[ndx].pipe_ndx); return -EINVAL; } mode = __multirect_layer_flags_to_mode( layer_list[i].flags); if (IS_ERR_VALUE(mode)) return mode; if (mode != vinfo[0]->multirect.mode) { pr_err("unable to set different multirect modes for pipe_ndx=%d (%d %d)\n", layer_list[ndx].pipe_ndx, ndx, i); rect_num = layer_list[ndx].rect_num; if (rect_num >= MDSS_MDP_PIPE_MAX_RECTS) return -EINVAL; validate_info_list[ndx].multirect.num = rect_num; return 0; } pr_debug("found matching pair for pipe_ndx=%d (%d %d)\n", layer_list[i].pipe_ndx, ndx, i); static int __update_multirect_info(struct msm_fb_data_type *mfd, struct mdss_mdp_validate_info_t *validate_info_list, struct mdp_input_layer *layer_list, int ndx, size_t layer_cnt, int is_rect_num_valid) { int ret; int pair_rect_num = -1; int pair_index; vinfo[cnt] = &validate_info_list[i]; vinfo[cnt]->multirect.num = cnt; vinfo[cnt]->multirect.next = vinfo[0]->layer; vinfo[cnt]->multirect.mode = mode; vinfo[cnt]->layer = &layer_list[i]; if (!is_rect_num_valid) layer_list[ndx].rect_num = MDSS_MDP_PIPE_RECT0; vinfo[cnt - 1]->multirect.next = vinfo[cnt]->layer; cnt++; } } ret = __validate_multirect_param(mfd, validate_info_list, layer_list, ndx, layer_cnt); /* return if we hit error or multirectangle mode is disabled. */ if (IS_ERR_VALUE(ret) || (!ret && validate_info_list[ndx].multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE)) return ret; if (is_rect_num_valid) pair_rect_num = (validate_info_list[ndx].multirect.num == MDSS_MDP_PIPE_RECT0) ? MDSS_MDP_PIPE_RECT1 : MDSS_MDP_PIPE_RECT0; if (cnt == 1) { pr_err("multirect mode enabled but unable to find extra rects for pipe_ndx=%x\n", pair_index = find_layer(get_pipe_num_from_ndx( layer_list[ndx].pipe_ndx), pair_rect_num, layer_list, layer_cnt, ndx + 1); if (IS_ERR_VALUE(pair_index)) { pr_err("Multirect pair not found for pipe ndx 0x%x\n", layer_list[ndx].pipe_ndx); return -EINVAL; } return cnt; if (!is_rect_num_valid) layer_list[pair_index].rect_num = MDSS_MDP_PIPE_RECT1; ret = __validate_multirect_param(mfd, validate_info_list, layer_list, pair_index, layer_cnt); if (IS_ERR_VALUE(ret) || (validate_info_list[ndx].multirect.mode != validate_info_list[pair_index].multirect.mode)) return -EINVAL; validate_info_list[ndx].multirect.next = &layer_list[pair_index]; validate_info_list[pair_index].multirect.next = &layer_list[ndx]; return 0; } static int __validate_multirect(struct msm_fb_data_type *mfd, struct mdss_mdp_validate_info_t *validate_info_list, struct mdp_input_layer *layer_list, int ndx, int layer_cnt) struct mdp_input_layer *layer_list, int ndx, size_t layer_cnt, int is_rect_num_valid) { struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS] = { 0 }; int i, cnt, rc; cnt = __update_multirect_info(mfd, validate_info_list, layer_list, ndx, layer_cnt); if (IS_ERR_VALUE(cnt)) return cnt; int ret; int i; struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS]; struct mdp_input_layer *pair_layer; if (cnt <= 1) { /* nothing to validate in single rect mode */ return 0; } else if (cnt > 2) { pr_err("unsupported multirect configuration, multirect cnt=%d\n", cnt); return -EINVAL; } ret = __update_multirect_info(mfd, validate_info_list, layer_list, ndx, layer_cnt, is_rect_num_valid); /* return if we hit error or multirectangle mode is disabled. */ if (IS_ERR_VALUE(ret) || (!ret && validate_info_list[ndx].multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE)) return ret; layers[0] = validate_info_list[ndx].layer; layers[1] = validate_info_list[ndx].multirect.next; layers[validate_info_list[ndx].multirect.num] = &layer_list[ndx]; pair_layer = validate_info_list[ndx].multirect.next; layers[pair_layer->rect_num] = pair_layer; /* check against smart DMA v1.0 restrictions */ for (i = 0; i < ARRAY_SIZE(__multirect_validators); i++) { if (!__multirect_validators[i](layers, cnt)) if (!__multirect_validators[i](layers, MDSS_MDP_PIPE_MAX_RECTS)) return -EINVAL; } rc = __multirect_validate_mode(mfd, layers, cnt); if (IS_ERR_VALUE(rc)) return rc; ret = __multirect_validate_mode(mfd, layers, MDSS_MDP_PIPE_MAX_RECTS); if (IS_ERR_VALUE(ret)) return ret; return 0; } Loading Loading @@ -2416,14 +2458,14 @@ static int __validate_layers(struct msm_fb_data_type *mfd, if (!validate_info_list[i].layer) { ret = __validate_multirect(mfd, validate_info_list, layer_list, i, layer_count); layer_list, i, layer_count, !!(commit->flags & MDP_COMMIT_RECT_NUM)); if (ret) { pr_err("error validating multirect config. ret=%d i=%d\n", ret, i); goto end; } } rect_num = validate_info_list[i].multirect.num; BUG_ON(rect_num >= MDSS_MDP_PIPE_MAX_RECTS); Loading Loading @@ -2782,7 +2824,8 @@ int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd, for (i = 0; i < layer_count; i++) { if (!validate_info_list[i].layer) { ret = __update_multirect_info(mfd, validate_info_list, layer_list, i, layer_count); layer_list, i, layer_count, !!(commit->flags & MDP_COMMIT_RECT_NUM)); if (IS_ERR_VALUE(ret)) { pr_err("error updating multirect config. ret=%d i=%d\n", ret, i); Loading include/uapi/linux/msm_mdp_ext.h +13 −1 Original line number Diff line number Diff line Loading @@ -178,6 +178,12 @@ VALIDATE/COMMIT FLAG CONFIGURATION */ #define MDP_COMMIT_CWB_DSPP 0x1000 /* * Flag to indicate that rectangle number is being assigned * by userspace in multi-rectangle mode */ #define MDP_COMMIT_RECT_NUM 0x2000 #define MDP_COMMIT_VERSION_1_0 0x00010000 #define OUT_LAYER_COLOR_SPACE Loading Loading @@ -425,8 +431,14 @@ struct mdp_input_layer { */ int error_code; /* * For source pipes supporting multi-rectangle, this field identifies * the rectangle index of the source pipe. */ uint32_t rect_num; /* 32bits reserved value for future usage. */ uint32_t reserved[6]; uint32_t reserved[5]; }; struct mdp_output_layer { Loading Loading
drivers/video/fbdev/msm/mdss_compat_utils.c +1 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,7 @@ static struct mdp_input_layer *__create_layer_list( layer->flags = layer32->flags; layer->pipe_ndx = layer32->pipe_ndx; layer->rect_num = layer32->rect_num; layer->horz_deci = layer32->horz_deci; layer->vert_deci = layer32->vert_deci; layer->z_order = layer32->z_order; Loading
drivers/video/fbdev/msm/mdss_compat_utils.h +2 −1 Original line number Diff line number Diff line Loading @@ -515,7 +515,8 @@ struct mdp_input_layer32 { struct mdp_layer_buffer buffer; compat_caddr_t pp_info; int error_code; uint32_t reserved[6]; uint32_t rect_num; uint32_t reserved[5]; }; struct mdp_output_layer32 { Loading
drivers/video/fbdev/msm/mdss_mdp_layer.c +128 −85 Original line number Diff line number Diff line Loading @@ -2160,115 +2160,157 @@ static int __multirect_validate_mode(struct msm_fb_data_type *mfd, return 0; } static int __update_multirect_info(struct msm_fb_data_type *mfd, struct mdss_mdp_validate_info_t *validate_info_list, struct mdp_input_layer *layer_list, int ndx, int layer_cnt) /* * linear search for a layer with given source pipe and rectangle number. * If rectangle number is invalid, it's dropped from search criteria */ static int find_layer(enum mdss_mdp_sspp_index pnum, int rect_num, struct mdp_input_layer *layer_list, size_t layer_cnt, int start_index) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); struct mdss_mdp_validate_info_t *vinfo[MDSS_MDP_PIPE_MAX_RECTS]; int i, ptype, max_rects, mode; int cnt = 1; mode = __multirect_layer_flags_to_mode(layer_list[ndx].flags); if (IS_ERR_VALUE(mode)) return mode; int i; pr_debug("layer #%d pipe_ndx=%d multirect mode=%d\n", ndx, layer_list[ndx].pipe_ndx, mode); if (start_index < 0) start_index = 0; vinfo[0] = &validate_info_list[ndx]; vinfo[0]->layer = &layer_list[ndx]; vinfo[0]->multirect.mode = mode; vinfo[0]->multirect.num = MDSS_MDP_PIPE_RECT0; vinfo[0]->multirect.next = NULL; if (start_index >= layer_cnt) return -EINVAL; /* nothing to be done if multirect is disabled */ if (mode == MDSS_MDP_PIPE_MULTIRECT_NONE) return cnt; for (i = start_index; i < layer_cnt; i++) { if (get_pipe_num_from_ndx(layer_list[i].pipe_ndx) == pnum && (rect_num < MDSS_MDP_PIPE_RECT0 || rect_num >= MDSS_MDP_PIPE_MAX_RECTS || layer_list[i].rect_num == rect_num)) return i; } ptype = get_pipe_type_from_ndx(layer_list[ndx].pipe_ndx); if (ptype == MDSS_MDP_PIPE_TYPE_INVALID) { pr_err("invalid pipe ndx %d\n", layer_list[ndx].pipe_ndx); return -EINVAL; return -ENOENT; /* no match found */ } max_rects = mdata->rects_per_sspp[ptype] ? : 1; static int __validate_multirect_param(struct msm_fb_data_type *mfd, struct mdss_mdp_validate_info_t *validate_info_list, struct mdp_input_layer *layer_list, int ndx, size_t layer_count) { int multirect_mode; int pnum; int rect_num; /* populate v_info with default values */ validate_info_list[ndx].layer = &layer_list[ndx]; validate_info_list[ndx].multirect.max_rects = MDSS_MDP_PIPE_MAX_RECTS; validate_info_list[ndx].multirect.next = NULL; validate_info_list[ndx].multirect.num = MDSS_MDP_PIPE_RECT0; validate_info_list[ndx].multirect.mode = MDSS_MDP_PIPE_MULTIRECT_NONE; multirect_mode = __multirect_layer_flags_to_mode( layer_list[ndx].flags); if (IS_ERR_VALUE(multirect_mode)) return multirect_mode; for (i = ndx + 1; i < layer_cnt; i++) { if (layer_list[ndx].pipe_ndx == layer_list[i].pipe_ndx) { if (cnt >= max_rects) { pr_err("more than %d layers of type %d with same pipe_ndx=%d indexes=%d %d\n", max_rects, ptype, layer_list[ndx].pipe_ndx, ndx, i); /* nothing to be done if multirect is disabled */ if (multirect_mode == MDSS_MDP_PIPE_MULTIRECT_NONE) return 0; validate_info_list[ndx].multirect.mode = multirect_mode; pnum = get_pipe_num_from_ndx(layer_list[ndx].pipe_ndx); if (get_pipe_type_from_num(pnum) != MDSS_MDP_PIPE_TYPE_DMA) { pr_err("Multirect not supported on pipe ndx 0x%x\n", layer_list[ndx].pipe_ndx); return -EINVAL; } mode = __multirect_layer_flags_to_mode( layer_list[i].flags); if (IS_ERR_VALUE(mode)) return mode; if (mode != vinfo[0]->multirect.mode) { pr_err("unable to set different multirect modes for pipe_ndx=%d (%d %d)\n", layer_list[ndx].pipe_ndx, ndx, i); rect_num = layer_list[ndx].rect_num; if (rect_num >= MDSS_MDP_PIPE_MAX_RECTS) return -EINVAL; validate_info_list[ndx].multirect.num = rect_num; return 0; } pr_debug("found matching pair for pipe_ndx=%d (%d %d)\n", layer_list[i].pipe_ndx, ndx, i); static int __update_multirect_info(struct msm_fb_data_type *mfd, struct mdss_mdp_validate_info_t *validate_info_list, struct mdp_input_layer *layer_list, int ndx, size_t layer_cnt, int is_rect_num_valid) { int ret; int pair_rect_num = -1; int pair_index; vinfo[cnt] = &validate_info_list[i]; vinfo[cnt]->multirect.num = cnt; vinfo[cnt]->multirect.next = vinfo[0]->layer; vinfo[cnt]->multirect.mode = mode; vinfo[cnt]->layer = &layer_list[i]; if (!is_rect_num_valid) layer_list[ndx].rect_num = MDSS_MDP_PIPE_RECT0; vinfo[cnt - 1]->multirect.next = vinfo[cnt]->layer; cnt++; } } ret = __validate_multirect_param(mfd, validate_info_list, layer_list, ndx, layer_cnt); /* return if we hit error or multirectangle mode is disabled. */ if (IS_ERR_VALUE(ret) || (!ret && validate_info_list[ndx].multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE)) return ret; if (is_rect_num_valid) pair_rect_num = (validate_info_list[ndx].multirect.num == MDSS_MDP_PIPE_RECT0) ? MDSS_MDP_PIPE_RECT1 : MDSS_MDP_PIPE_RECT0; if (cnt == 1) { pr_err("multirect mode enabled but unable to find extra rects for pipe_ndx=%x\n", pair_index = find_layer(get_pipe_num_from_ndx( layer_list[ndx].pipe_ndx), pair_rect_num, layer_list, layer_cnt, ndx + 1); if (IS_ERR_VALUE(pair_index)) { pr_err("Multirect pair not found for pipe ndx 0x%x\n", layer_list[ndx].pipe_ndx); return -EINVAL; } return cnt; if (!is_rect_num_valid) layer_list[pair_index].rect_num = MDSS_MDP_PIPE_RECT1; ret = __validate_multirect_param(mfd, validate_info_list, layer_list, pair_index, layer_cnt); if (IS_ERR_VALUE(ret) || (validate_info_list[ndx].multirect.mode != validate_info_list[pair_index].multirect.mode)) return -EINVAL; validate_info_list[ndx].multirect.next = &layer_list[pair_index]; validate_info_list[pair_index].multirect.next = &layer_list[ndx]; return 0; } static int __validate_multirect(struct msm_fb_data_type *mfd, struct mdss_mdp_validate_info_t *validate_info_list, struct mdp_input_layer *layer_list, int ndx, int layer_cnt) struct mdp_input_layer *layer_list, int ndx, size_t layer_cnt, int is_rect_num_valid) { struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS] = { 0 }; int i, cnt, rc; cnt = __update_multirect_info(mfd, validate_info_list, layer_list, ndx, layer_cnt); if (IS_ERR_VALUE(cnt)) return cnt; int ret; int i; struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS]; struct mdp_input_layer *pair_layer; if (cnt <= 1) { /* nothing to validate in single rect mode */ return 0; } else if (cnt > 2) { pr_err("unsupported multirect configuration, multirect cnt=%d\n", cnt); return -EINVAL; } ret = __update_multirect_info(mfd, validate_info_list, layer_list, ndx, layer_cnt, is_rect_num_valid); /* return if we hit error or multirectangle mode is disabled. */ if (IS_ERR_VALUE(ret) || (!ret && validate_info_list[ndx].multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE)) return ret; layers[0] = validate_info_list[ndx].layer; layers[1] = validate_info_list[ndx].multirect.next; layers[validate_info_list[ndx].multirect.num] = &layer_list[ndx]; pair_layer = validate_info_list[ndx].multirect.next; layers[pair_layer->rect_num] = pair_layer; /* check against smart DMA v1.0 restrictions */ for (i = 0; i < ARRAY_SIZE(__multirect_validators); i++) { if (!__multirect_validators[i](layers, cnt)) if (!__multirect_validators[i](layers, MDSS_MDP_PIPE_MAX_RECTS)) return -EINVAL; } rc = __multirect_validate_mode(mfd, layers, cnt); if (IS_ERR_VALUE(rc)) return rc; ret = __multirect_validate_mode(mfd, layers, MDSS_MDP_PIPE_MAX_RECTS); if (IS_ERR_VALUE(ret)) return ret; return 0; } Loading Loading @@ -2416,14 +2458,14 @@ static int __validate_layers(struct msm_fb_data_type *mfd, if (!validate_info_list[i].layer) { ret = __validate_multirect(mfd, validate_info_list, layer_list, i, layer_count); layer_list, i, layer_count, !!(commit->flags & MDP_COMMIT_RECT_NUM)); if (ret) { pr_err("error validating multirect config. ret=%d i=%d\n", ret, i); goto end; } } rect_num = validate_info_list[i].multirect.num; BUG_ON(rect_num >= MDSS_MDP_PIPE_MAX_RECTS); Loading Loading @@ -2782,7 +2824,8 @@ int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd, for (i = 0; i < layer_count; i++) { if (!validate_info_list[i].layer) { ret = __update_multirect_info(mfd, validate_info_list, layer_list, i, layer_count); layer_list, i, layer_count, !!(commit->flags & MDP_COMMIT_RECT_NUM)); if (IS_ERR_VALUE(ret)) { pr_err("error updating multirect config. ret=%d i=%d\n", ret, i); Loading
include/uapi/linux/msm_mdp_ext.h +13 −1 Original line number Diff line number Diff line Loading @@ -178,6 +178,12 @@ VALIDATE/COMMIT FLAG CONFIGURATION */ #define MDP_COMMIT_CWB_DSPP 0x1000 /* * Flag to indicate that rectangle number is being assigned * by userspace in multi-rectangle mode */ #define MDP_COMMIT_RECT_NUM 0x2000 #define MDP_COMMIT_VERSION_1_0 0x00010000 #define OUT_LAYER_COLOR_SPACE Loading Loading @@ -425,8 +431,14 @@ struct mdp_input_layer { */ int error_code; /* * For source pipes supporting multi-rectangle, this field identifies * the rectangle index of the source pipe. */ uint32_t rect_num; /* 32bits reserved value for future usage. */ uint32_t reserved[6]; uint32_t reserved[5]; }; struct mdp_output_layer { Loading