Beispiel #1
0
static void xilinx_drm_plane_set_zpos(struct drm_plane *base_plane,
				      unsigned int zpos)
{
	struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
	struct xilinx_drm_plane_manager *manager = plane->manager;
	bool update = false;
	int i;

	if (plane->zpos == zpos)
		return;

	for (i = 0; i < manager->num_planes; i++) {
		if (manager->planes[i] != plane &&
		    manager->planes[i]->prio == zpos) {
			update = true;
			break;
		}
	}

	plane->zpos = zpos;

	if (update) {
		xilinx_drm_plane_update_prio(manager);
	} else {
		plane->prio = zpos;
		xilinx_osd_layer_set_priority(plane->osd_layer, plane->prio);
	}
}
Beispiel #2
0
/**
 * xilinx_drm_plane_update_prio - Configure plane priorities based on zpos
 * @manager: the plane manager
 *
 * Z-position values are user requested position of planes. The priority is
 * the actual position of planes in hardware. Some hardware doesn't allow
 * any duplicate priority, so this function needs to be called when a duplicate
 * priority is found. Then planes are sorted by zpos value, and the priorities
 * are reconfigured. A plane with lower plane ID gets assigned to the lower
 * priority when planes have the same zpos value.
 */
static void
xilinx_drm_plane_update_prio(struct xilinx_drm_plane_manager *manager)
{
	struct xilinx_drm_plane *planes[MAX_PLANES];
	struct xilinx_drm_plane *plane;
	unsigned int i, j;

	/* sort planes by zpos */
	for (i = 0; i < manager->num_planes; i++) {
		plane = manager->planes[i];

		for (j = i; j > 0; --j) {
			if (planes[j - 1]->zpos <= plane->zpos)
				break;
			planes[j] = planes[j - 1];
		}

		planes[j] = plane;
	}

	xilinx_osd_disable_rue(manager->osd);

	/* remove duplicates by reassigning priority */
	for (i = 0; i < manager->num_planes; i++) {
		planes[i]->prio = i;
		xilinx_osd_layer_set_priority(planes[i]->osd_layer,
					      planes[i]->prio);
	}

	xilinx_osd_enable_rue(manager->osd);
}
Beispiel #3
0
/* set plane dpms */
void xilinx_drm_plane_dpms(struct drm_plane *base_plane, int dpms)
{
	struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
	struct xilinx_drm_plane_manager *manager = plane->manager;
	unsigned int i;

	DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
	DRM_DEBUG_KMS("dpms: %d -> %d\n", plane->dpms, dpms);

	if (plane->dpms == dpms)
		return;

	plane->dpms = dpms;
	switch (dpms) {
	case DRM_MODE_DPMS_ON:
		if (manager->dp_sub) {
			if (plane->primary) {
				xilinx_drm_dp_sub_enable_alpha(manager->dp_sub,
						plane->alpha_enable);
				xilinx_drm_dp_sub_set_alpha(manager->dp_sub,
							    plane->alpha);
			}
			xilinx_drm_dp_sub_layer_enable(manager->dp_sub,
						       plane->dp_layer);
		}

		/* start dma engine */
		for (i = 0; i < MAX_NUM_SUB_PLANES; i++)
			if (plane->dma[i].chan && plane->dma[i].is_active)
				dma_async_issue_pending(plane->dma[i].chan);

		if (plane->rgb2yuv)
			xilinx_rgb2yuv_enable(plane->rgb2yuv);

		if (plane->cresample)
			xilinx_cresample_enable(plane->cresample);

		/* enable osd */
		if (manager->osd) {
			xilinx_osd_disable_rue(manager->osd);

			xilinx_osd_layer_set_priority(plane->osd_layer,
						      plane->prio);
			xilinx_osd_layer_enable_alpha(plane->osd_layer,
						   plane->alpha_enable);
			xilinx_osd_layer_set_alpha(plane->osd_layer,
						   plane->alpha);
			xilinx_osd_layer_enable(plane->osd_layer);

			xilinx_osd_enable_rue(manager->osd);
		}

		break;
	default:
		/* disable/reset osd */
		if (manager->osd) {
			xilinx_osd_disable_rue(manager->osd);

			xilinx_osd_layer_set_dimension(plane->osd_layer,
						       0, 0, 0, 0);
			xilinx_osd_layer_disable(plane->osd_layer);

			xilinx_osd_enable_rue(manager->osd);
		}

		if (plane->cresample) {
			xilinx_cresample_disable(plane->cresample);
			xilinx_cresample_reset(plane->cresample);
		}

		if (plane->rgb2yuv) {
			xilinx_rgb2yuv_disable(plane->rgb2yuv);
			xilinx_rgb2yuv_reset(plane->rgb2yuv);
		}

		/* stop dma engine and release descriptors */
		for (i = 0; i < MAX_NUM_SUB_PLANES; i++) {
			if (plane->dma[i].chan && plane->dma[i].is_active) {
				dmaengine_terminate_all(plane->dma[i].chan);
				plane->dma[i].is_active = false;
			}
		}

		if (manager->dp_sub)
			xilinx_drm_dp_sub_layer_disable(manager->dp_sub,
							plane->dp_layer);

		break;
	}
}
/* set plane dpms */
void xilinx_drm_plane_dpms(struct drm_plane *base_plane, int dpms)
{
	struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
	struct xilinx_drm_plane_manager *manager = plane->manager;

	DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
	DRM_DEBUG_KMS("dpms: %d -> %d\n", plane->dpms, dpms);

	if (plane->dpms == dpms)
		return;

	plane->dpms = dpms;
	switch (dpms) {
	case DRM_MODE_DPMS_ON:
		/* start dma engine */
		dma_async_issue_pending(plane->dma.chan);

		if (plane->rgb2yuv)
			xilinx_rgb2yuv_enable(plane->rgb2yuv);

		if (plane->cresample)
			xilinx_cresample_enable(plane->cresample);

		/* enable osd */
		if (manager->osd) {
			xilinx_osd_disable_rue(manager->osd);

			xilinx_osd_layer_set_priority(plane->osd_layer,
						      plane->prio);
			xilinx_osd_layer_set_alpha(plane->osd_layer, 1,
						   plane->alpha);
			xilinx_osd_layer_enable(plane->osd_layer);
			if (plane->priv) {
				/* set background color as black */
				xilinx_osd_set_color(manager->osd, 0x0, 0x0,
						     0x0);
				xilinx_osd_enable(manager->osd);
			}

			xilinx_osd_enable_rue(manager->osd);
		}

		break;
	default:
		/* disable/reset osd */
		if (manager->osd) {
			xilinx_osd_disable_rue(manager->osd);

			xilinx_osd_layer_set_dimension(plane->osd_layer,
						       0, 0, 0, 0);
			xilinx_osd_layer_disable(plane->osd_layer);
			if (plane->priv)
				xilinx_osd_reset(manager->osd);

			xilinx_osd_enable_rue(manager->osd);
		}

		if (plane->cresample) {
			xilinx_cresample_disable(plane->cresample);
			xilinx_cresample_reset(plane->cresample);
		}

		if (plane->rgb2yuv) {
			xilinx_rgb2yuv_disable(plane->rgb2yuv);
			xilinx_rgb2yuv_reset(plane->rgb2yuv);
		}

		/* stop dma engine and release descriptors */
		dmaengine_terminate_all(plane->dma.chan);
		break;
	}
}