/**
 * @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;
}
예제 #3
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}