/** * @mdss_mdp_cdm_out_packer_setup - Programs the output packer block. * @cdm: Pointer to the CDM structure. * @data: Pointer to the structure containing * configuration data. */ static int mdss_mdp_cdm_out_packer_setup(struct mdss_mdp_cdm *cdm, struct mdp_cdm_cfg *data) { int rc = 0; u32 opmode = 0; u32 cdm_enable = 0; struct mdss_mdp_format_params *fmt; if (cdm->out_intf == MDP_CDM_CDWN_OUTPUT_HDMI) { /* Enable HDMI packer */ opmode |= BIT(0); fmt = mdss_mdp_get_format_params(data->out_format); if (!fmt) { pr_err("cdm format = %d, not supported\n", data->out_format); return -EINVAL; } opmode &= ~0x6; opmode |= (fmt->chroma_sample << 1); if (!cdm->is_bypassed) cdm_enable |= BIT(19); } else { /* Disable HDMI pacler for WB */ opmode = 0; if (!cdm->is_bypassed) cdm_enable |= BIT(24); } writel_relaxed(cdm_enable, cdm->mdata->mdp_base + MDSS_MDP_MDP_OUT_CTL_0); writel_relaxed(opmode, cdm->base + MDSS_MDP_REG_CDM_HDMI_PACK_OP_MODE); return rc; }
int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h, struct mdss_mdp_plane_sizes *ps) { struct mdss_mdp_format_params *fmt; int i; if (ps == NULL) return -EINVAL; if ((w > MAX_IMG_WIDTH) || (h > MAX_IMG_HEIGHT)) return -ERANGE; fmt = mdss_mdp_get_format_params(format); if (!fmt) return -EINVAL; memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes)); if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) { u32 bpp = fmt->bpp + 1; ps->num_planes = 1; ps->plane_size[0] = w * h * bpp; ps->ystride[0] = w * bpp; } else { u8 hmap[] = { 1, 2, 1, 2 }; u8 vmap[] = { 1, 1, 2, 2 }; u8 horiz, vert; horiz = hmap[fmt->chroma_sample]; vert = vmap[fmt->chroma_sample]; if (format == MDP_Y_CR_CB_GH2V2) { ps->plane_size[0] = ALIGN(w, 16) * h; ps->plane_size[1] = ALIGN(w / horiz, 16) * (h / vert); ps->ystride[0] = ALIGN(w, 16); ps->ystride[1] = ALIGN(w / horiz, 16); } else { ps->plane_size[0] = w * h; ps->plane_size[1] = (w / horiz) * (h / vert); ps->ystride[0] = w; ps->ystride[1] = (w / horiz); } if (fmt->fetch_planes == MDSS_MDP_PLANE_PSEUDO_PLANAR) { ps->num_planes = 2; ps->plane_size[1] *= 2; ps->ystride[1] *= 2; } else { /* planar */ ps->num_planes = 3; ps->plane_size[2] = ps->plane_size[1]; ps->ystride[2] = ps->ystride[1]; } } for (i = 0; i < ps->num_planes; i++) ps->total_size += ps->plane_size[i]; return 0; }
static int mdss_mdp_overlay_rotator_setup(struct msm_fb_data_type *mfd, struct mdp_overlay *req) { struct mdss_mdp_rotator_session *rot; struct mdss_mdp_format_params *fmt; int ret = 0; pr_debug("rot ctl=%u req id=%x\n", mfd->ctl->num, req->id); fmt = mdss_mdp_get_format_params(req->src.format); if (!fmt) { pr_err("invalid rot format %d\n", req->src.format); return -EINVAL; } ret = mdss_mdp_overlay_req_check(mfd, req, fmt); if (ret) return ret; if (req->id == MSMFB_NEW_REQUEST) { rot = mdss_mdp_rotator_session_alloc(); if (!rot) { pr_err("unable to allocate rotator session\n"); return -ENOMEM; } } else if (req->id & MDSS_MDP_ROT_SESSION_MASK) { rot = mdss_mdp_rotator_session_get(req->id); if (!rot) { pr_err("rotator session=%x not found\n", req->id); return -ENODEV; } } else { pr_err("invalid rotator session id=%x\n", req->id); return -EINVAL; } rot->rotations = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD); rot->format = fmt->format; rot->img_width = req->src.width; rot->img_height = req->src.height; rot->src_rect.x = req->src_rect.x; rot->src_rect.y = req->src_rect.y; rot->src_rect.w = req->src_rect.w; rot->src_rect.h = req->src_rect.h; rot->params_changed++; req->id = rot->session_id; return ret; }
static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd, struct mdp_overlay *req, struct mdss_mdp_pipe **ppipe) { struct mdss_mdp_format_params *fmt; struct mdss_mdp_pipe *pipe; struct mdss_mdp_mixer *mixer = NULL; u32 pipe_type, mixer_mux; int ret; if (mfd == NULL || mfd->ctl == NULL) return -ENODEV; if (req->flags & MDSS_MDP_RIGHT_MIXER) mixer_mux = MDSS_MDP_MIXER_MUX_RIGHT; else mixer_mux = MDSS_MDP_MIXER_MUX_LEFT; pr_debug("pipe ctl=%u req id=%x mux=%d\n", mfd->ctl->num, req->id, mixer_mux); if (req->flags & MDP_ROT_90) { pr_err("unsupported inline rotation\n"); return -ENOTSUPP; } fmt = mdss_mdp_get_format_params(req->src.format); if (!fmt) { pr_err("invalid pipe format %d\n", req->src.format); return -EINVAL; } ret = mdss_mdp_overlay_req_check(mfd, req, fmt); if (ret) return ret; pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, mixer_mux, req->z_order); if (pipe && pipe->ndx != req->id) { pr_err("stage %d taken by pnum=%d\n", req->z_order, pipe->num); return -EBUSY; } if (req->id == MSMFB_NEW_REQUEST) { mixer = mdss_mdp_mixer_get(mfd->ctl, mixer_mux); if (!mixer) { pr_err("unable to get mixer\n"); return -ENODEV; } if (fmt->is_yuv || (req->flags & MDP_OV_PIPE_SHARE)) pipe_type = MDSS_MDP_PIPE_TYPE_VIG; else pipe_type = MDSS_MDP_PIPE_TYPE_RGB; pipe = mdss_mdp_pipe_alloc_locked(pipe_type); /* VIG pipes can also support RGB format */ if (!pipe && pipe_type == MDSS_MDP_PIPE_TYPE_RGB) { pipe_type = MDSS_MDP_PIPE_TYPE_VIG; pipe = mdss_mdp_pipe_alloc_locked(pipe_type); } if (pipe == NULL) { pr_err("error allocating pipe\n"); return -ENOMEM; } pipe->mixer = mixer; pipe->mfd = mfd; } else { pipe = mdss_mdp_pipe_get_locked(req->id); if (pipe == NULL) { pr_err("invalid pipe ndx=%x\n", req->id); return -ENODEV; } } pipe->flags = req->flags; pipe->img_width = req->src.width & 0x3fff; pipe->img_height = req->src.height & 0x3fff; pipe->src.x = req->src_rect.x; pipe->src.y = req->src_rect.y; pipe->src.w = req->src_rect.w; pipe->src.h = req->src_rect.h; pipe->dst.x = req->dst_rect.x; pipe->dst.y = req->dst_rect.y; pipe->dst.w = req->dst_rect.w; pipe->dst.h = req->dst_rect.h; pipe->src_fmt = fmt; pipe->mixer_stage = req->z_order; pipe->is_fg = req->is_fg; pipe->alpha = req->alpha; pipe->transp = req->transp_mask; pipe->req_data = *req; pipe->params_changed++; req->id = pipe->ndx; *ppipe = pipe; mdss_mdp_pipe_unlock(pipe); return ret; }
int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h, struct mdss_mdp_plane_sizes *ps, u32 bwc_mode) { struct mdss_mdp_format_params *fmt; int i, rc; u32 bpp, ystride0_off, ystride1_off; if (ps == NULL) return -EINVAL; if ((w > MAX_IMG_WIDTH) || (h > MAX_IMG_HEIGHT)) return -ERANGE; fmt = mdss_mdp_get_format_params(format); if (!fmt) return -EINVAL; bpp = fmt->bpp; memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes)); if (bwc_mode) { rc = mdss_mdp_get_rau_strides(w, h, fmt, ps); if (rc) return rc; ystride0_off = DIV_ROUND_UP(h, ps->rau_h[0]); ystride1_off = DIV_ROUND_UP(h, ps->rau_h[1]); ps->plane_size[0] = (ps->ystride[0] * ystride0_off) + (ps->ystride[1] * ystride1_off); ps->ystride[0] += ps->ystride[1]; ps->ystride[1] = 2; ps->plane_size[1] = ps->rau_cnt * ps->ystride[1] * (ystride0_off + ystride1_off); } else { if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) { ps->num_planes = 1; ps->plane_size[0] = w * h * bpp; ps->ystride[0] = w * bpp; } else if (format == MDP_Y_CBCR_H2V2_VENUS) { int cf = COLOR_FMT_NV12; ps->num_planes = 2; ps->ystride[0] = VENUS_Y_STRIDE(cf, w); ps->ystride[1] = VENUS_UV_STRIDE(cf, w); ps->plane_size[0] = VENUS_Y_SCANLINES(cf, h) * ps->ystride[0]; ps->plane_size[1] = VENUS_UV_SCANLINES(cf, h) * ps->ystride[1]; } else { u8 hmap[] = { 1, 2, 1, 2 }; u8 vmap[] = { 1, 1, 2, 2 }; u8 horiz, vert, stride_align, height_align; horiz = hmap[fmt->chroma_sample]; vert = vmap[fmt->chroma_sample]; switch (format) { case MDP_Y_CR_CB_GH2V2: stride_align = 16; height_align = 1; break; default: stride_align = 1; height_align = 1; break; } ps->ystride[0] = ALIGN(w, stride_align); ps->ystride[1] = ALIGN(w / horiz, stride_align); ps->plane_size[0] = ps->ystride[0] * ALIGN(h, height_align); ps->plane_size[1] = ps->ystride[1] * (h / vert); if (fmt->fetch_planes == MDSS_MDP_PLANE_PSEUDO_PLANAR) { ps->num_planes = 2; ps->plane_size[1] *= 2; ps->ystride[1] *= 2; } else { /* planar */ ps->num_planes = 3; ps->plane_size[2] = ps->plane_size[1]; ps->ystride[2] = ps->ystride[1]; } } } for (i = 0; i < ps->num_planes; i++) ps->total_size += ps->plane_size[i]; return 0; }