Exemple #1
0
int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane)
{
	int plane_id, depth = plane->drm_plane.state->normalized_zpos;
	unsigned int i;
	u32 mask, val;

	switch (plane->desc) {
	case STI_GDP_0:
		plane_id = GAM_DEPTH_GDP0_ID;
		break;
	case STI_GDP_1:
		plane_id = GAM_DEPTH_GDP1_ID;
		break;
	case STI_GDP_2:
		plane_id = GAM_DEPTH_GDP2_ID;
		break;
	case STI_GDP_3:
		plane_id = GAM_DEPTH_GDP3_ID;
		break;
	case STI_HQVDP_0:
		plane_id = GAM_DEPTH_VID0_ID;
		break;
	case STI_CURSOR:
		/* no need to set depth for cursor */
		return 0;
	default:
		DRM_ERROR("Unknown plane %d\n", plane->desc);
		return 1;
	}

	/* Search if a previous depth was already assigned to the plane */
	val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
	for (i = 0; i < GAM_MIXER_NB_DEPTH_LEVEL; i++) {
		mask = GAM_DEPTH_MASK_ID << (3 * i);
		if ((val & mask) == plane_id << (3 * i))
			break;
	}

	mask |= GAM_DEPTH_MASK_ID << (3 * depth);
	plane_id = plane_id << (3 * depth);

	DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
			 sti_plane_to_str(plane), depth);
	dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",
		plane_id, mask);

	val &= ~mask;
	val |= plane_id;
	sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);

	dev_dbg(mixer->dev, "Read GAM_MIXER_CRB 0x%x\n",
		sti_mixer_reg_read(mixer, GAM_MIXER_CRB));
	return 0;
}
int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer)
{
	int layer_id = 0, depth = layer->zorder;
	u32 mask, val;

	if (depth >= GAM_MIXER_NB_DEPTH_LEVEL)
		return 1;

	switch (layer->desc) {
	case STI_GDP_0:
		layer_id = GAM_DEPTH_GDP0_ID;
		break;
	case STI_GDP_1:
		layer_id = GAM_DEPTH_GDP1_ID;
		break;
	case STI_GDP_2:
		layer_id = GAM_DEPTH_GDP2_ID;
		break;
	case STI_GDP_3:
		layer_id = GAM_DEPTH_GDP3_ID;
		break;
	case STI_VID_0:
		layer_id = GAM_DEPTH_VID0_ID;
		break;
	case STI_VID_1:
		layer_id = GAM_DEPTH_VID1_ID;
		break;
	default:
		DRM_ERROR("Unknown layer %d\n", layer->desc);
		return 1;
	}
	mask = GAM_DEPTH_MASK_ID << (3 * depth);
	layer_id = layer_id << (3 * depth);

	DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
			 sti_layer_to_str(layer), depth);
	dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",
		layer_id, mask);

	val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
	val &= ~mask;
	val |= layer_id;
	sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);

	dev_dbg(mixer->dev, "Read GAM_MIXER_CRB 0x%x\n",
		sti_mixer_reg_read(mixer, GAM_MIXER_CRB));
	return 0;
}
Exemple #3
0
static void sti_hqvdp_atomic_disable(struct drm_plane *drm_plane,
				     struct drm_plane_state *oldstate)
{
	struct sti_plane *plane = to_sti_plane(drm_plane);

	if (!drm_plane->crtc) {
		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
				 drm_plane->base.id);
		return;
	}

	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
			 drm_plane->crtc->base.id,
			 sti_mixer_to_str(to_sti_mixer(drm_plane->crtc)),
			 drm_plane->base.id, sti_plane_to_str(plane));

	plane->status = STI_PLANE_DISABLING;
}
int sti_mixer_set_layer_status(struct sti_mixer *mixer,
			       struct sti_layer *layer, bool status)
{
	u32 mask, val;

	DRM_DEBUG_DRIVER("%s %s %s\n", status ? "enable" : "disable",
			 sti_mixer_to_str(mixer), sti_layer_to_str(layer));

	mask = sti_mixer_get_layer_mask(layer);
	if (!mask) {
		DRM_ERROR("Can not find layer mask\n");
		return -EINVAL;
	}

	val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);
	val &= ~mask;
	val |= status ? mask : 0;
	sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);

	return 0;
}
int sti_mixer_active_video_area(struct sti_mixer *mixer,
				struct drm_display_mode *mode)
{
	u32 ydo, xdo, yds, xds;

	ydo = sti_vtg_get_line_number(*mode, 0);
	yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
	xdo = sti_vtg_get_pixel_number(*mode, 0);
	xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);

	DRM_DEBUG_DRIVER("%s active video area xdo:%d ydo:%d xds:%d yds:%d\n",
			 sti_mixer_to_str(mixer), xdo, ydo, xds, yds);
	sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);
	sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);

	sti_mixer_set_background_color(mixer, 0xFF, 0, 0);

	sti_mixer_set_background_area(mixer, mode);
	sti_mixer_set_background_status(mixer, true);
	return 0;
}
Exemple #6
0
struct sti_mixer *sti_mixer_create(struct device *dev,
				   struct drm_device *drm_dev,
				   int id,
				   void __iomem *baseaddr)
{
	struct sti_mixer *mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);

	dev_dbg(dev, "%s\n", __func__);
	if (!mixer) {
		DRM_ERROR("Failed to allocated memory for mixer\n");
		return NULL;
	}
	mixer->regs = baseaddr;
	mixer->dev = dev;
	mixer->id = id;

	DRM_DEBUG_DRIVER("%s created. Regs=%p\n",
			 sti_mixer_to_str(mixer), mixer->regs);

	return mixer;
}
struct sti_mixer *sti_mixer_create(struct device *dev, int id,
				   void __iomem *baseaddr)
{
	struct sti_mixer *mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
	struct device_node *np = dev->of_node;

	dev_dbg(dev, "%s\n", __func__);
	if (!mixer) {
		DRM_ERROR("Failed to allocated memory for mixer\n");
		return NULL;
	}
	mixer->regs = baseaddr;
	mixer->dev = dev;
	mixer->id = id;

	if (of_device_is_compatible(np, "st,stih416-compositor"))
		sti_mixer_set_matrix(mixer);

	DRM_DEBUG_DRIVER("%s created. Regs=%p\n",
			 sti_mixer_to_str(mixer), mixer->regs);

	return mixer;
}
Exemple #8
0
static int mixer_dbg_show(struct seq_file *s, void *arg)
{
	struct drm_info_node *node = s->private;
	struct sti_mixer *mixer = (struct sti_mixer *)node->info_ent->data;

	seq_printf(s, "%s: (vaddr = 0x%p)",
		   sti_mixer_to_str(mixer), mixer->regs);

	DBGFS_DUMP(GAM_MIXER_CTL);
	mixer_dbg_ctl(s, sti_mixer_reg_read(mixer, GAM_MIXER_CTL));
	DBGFS_DUMP(GAM_MIXER_BKC);
	DBGFS_DUMP(GAM_MIXER_BCO);
	DBGFS_DUMP(GAM_MIXER_BCS);
	DBGFS_DUMP(GAM_MIXER_AVO);
	DBGFS_DUMP(GAM_MIXER_AVS);
	DBGFS_DUMP(GAM_MIXER_CRB);
	mixer_dbg_crb(s, sti_mixer_reg_read(mixer, GAM_MIXER_CRB));
	DBGFS_DUMP(GAM_MIXER_ACT);
	DBGFS_DUMP(GAM_MIXER_MBP);
	DBGFS_DUMP(GAM_MIXER_MX0);
	mixer_dbg_mxn(s, mixer->regs + GAM_MIXER_MX0);
	seq_putc(s, '\n');
	return 0;
}
Exemple #9
0
static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane,
				  struct drm_plane_state *state)
{
	struct sti_plane *plane = to_sti_plane(drm_plane);
	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
	struct drm_crtc *crtc = state->crtc;
	struct drm_framebuffer *fb = state->fb;
	bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
	struct drm_crtc_state *crtc_state;
	struct drm_display_mode *mode;
	int dst_x, dst_y, dst_w, dst_h;
	int src_x, src_y, src_w, src_h;

	/* no need for further checks if the plane is being disabled */
	if (!crtc || !fb)
		return 0;

	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
	mode = &crtc_state->mode;
	dst_x = state->crtc_x;
	dst_y = state->crtc_y;
	dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
	dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
	/* src_x are in 16.16 format */
	src_x = state->src_x >> 16;
	src_y = state->src_y >> 16;
	src_w = state->src_w >> 16;
	src_h = state->src_h >> 16;

	if (!sti_hqvdp_check_hw_scaling(hqvdp, mode,
					src_w, src_h,
					dst_w, dst_h)) {
		DRM_ERROR("Scaling beyond HW capabilities\n");
		return -EINVAL;
	}

	if (!drm_fb_cma_get_gem_obj(fb, 0)) {
		DRM_ERROR("Can't get CMA GEM object for fb\n");
		return -EINVAL;
	}

	/*
	 * Input / output size
	 * Align to upper even value
	 */
	dst_w = ALIGN(dst_w, 2);
	dst_h = ALIGN(dst_h, 2);

	if ((src_w > MAX_WIDTH) || (src_w < MIN_WIDTH) ||
	    (src_h > MAX_HEIGHT) || (src_h < MIN_HEIGHT) ||
	    (dst_w > MAX_WIDTH) || (dst_w < MIN_WIDTH) ||
	    (dst_h > MAX_HEIGHT) || (dst_h < MIN_HEIGHT)) {
		DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
			  src_w, src_h,
			  dst_w, dst_h);
		return -EINVAL;
	}

	if (first_prepare) {
		/* Start HQVDP XP70 coprocessor */
		sti_hqvdp_start_xp70(hqvdp);

		/* Prevent VTG shutdown */
		if (clk_prepare_enable(hqvdp->clk_pix_main)) {
			DRM_ERROR("Failed to prepare/enable pix main clk\n");
			return -EINVAL;
		}

		/* Register VTG Vsync callback to handle bottom fields */
		if (sti_vtg_register_client(hqvdp->vtg,
					    &hqvdp->vtg_nb,
					    crtc)) {
			DRM_ERROR("Cannot register VTG notifier\n");
			return -EINVAL;
		}
	}

	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
		      crtc->base.id, sti_mixer_to_str(to_sti_mixer(crtc)),
		      drm_plane->base.id, sti_plane_to_str(plane));
	DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
		      sti_plane_to_str(plane),
		      dst_w, dst_h, dst_x, dst_y,
		      src_w, src_h, src_x, src_y);

	return 0;
}