diff options
Diffstat (limited to 'drivers/gpu/drm/sti/sti_layer.c')
| -rw-r--r-- | drivers/gpu/drm/sti/sti_layer.c | 197 | 
1 files changed, 197 insertions, 0 deletions
diff --git a/drivers/gpu/drm/sti/sti_layer.c b/drivers/gpu/drm/sti/sti_layer.c new file mode 100644 index 000000000000..06a587c4f1bb --- /dev/null +++ b/drivers/gpu/drm/sti/sti_layer.c @@ -0,0 +1,197 @@ +/* + * Copyright (C) STMicroelectronics SA 2014 + * Authors: Benjamin Gaignard <[email protected]> + *          Fabien Dessenne <[email protected]> + *          for STMicroelectronics. + * License terms:  GNU General Public License (GPL), version 2 + */ + +#include <drm/drmP.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "sti_compositor.h" +#include "sti_gdp.h" +#include "sti_layer.h" +#include "sti_vid.h" + +const char *sti_layer_to_str(struct sti_layer *layer) +{ +	switch (layer->desc) { +	case STI_GDP_0: +		return "GDP0"; +	case STI_GDP_1: +		return "GDP1"; +	case STI_GDP_2: +		return "GDP2"; +	case STI_GDP_3: +		return "GDP3"; +	case STI_VID_0: +		return "VID0"; +	case STI_VID_1: +		return "VID1"; +	case STI_CURSOR: +		return "CURSOR"; +	default: +		return "<UNKNOWN LAYER>"; +	} +} + +struct sti_layer *sti_layer_create(struct device *dev, int desc, +				   void __iomem *baseaddr) +{ + +	struct sti_layer *layer = NULL; + +	switch (desc & STI_LAYER_TYPE_MASK) { +	case STI_GDP: +		layer = sti_gdp_create(dev, desc); +		break; +	case STI_VID: +		layer = sti_vid_create(dev); +		break; +	} + +	if (!layer) { +		DRM_ERROR("Failed to create layer\n"); +		return NULL; +	} + +	layer->desc = desc; +	layer->dev = dev; +	layer->regs = baseaddr; + +	layer->ops->init(layer); + +	DRM_DEBUG_DRIVER("%s created\n", sti_layer_to_str(layer)); + +	return layer; +} + +int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb, +		      struct drm_display_mode *mode, int mixer_id, +		      int dest_x, int dest_y, int dest_w, int dest_h, +		      int src_x, int src_y, int src_w, int src_h) +{ +	int ret; +	unsigned int i; +	struct drm_gem_cma_object *cma_obj; + +	if (!layer || !fb || !mode) { +		DRM_ERROR("Null fb, layer or mode\n"); +		return 1; +	} + +	cma_obj = drm_fb_cma_get_gem_obj(fb, 0); +	if (!cma_obj) { +		DRM_ERROR("Can't get CMA GEM object for fb\n"); +		return 1; +	} + +	layer->fb = fb; +	layer->mode = mode; +	layer->mixer_id = mixer_id; +	layer->dst_x = dest_x; +	layer->dst_y = dest_y; +	layer->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x); +	layer->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y); +	layer->src_x = src_x; +	layer->src_y = src_y; +	layer->src_w = src_w; +	layer->src_h = src_h; +	layer->format = fb->pixel_format; +	layer->paddr = cma_obj->paddr; +	for (i = 0; i < 4; i++) { +		layer->pitches[i] = fb->pitches[i]; +		layer->offsets[i] = fb->offsets[i]; +	} + +	DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n", +			 sti_layer_to_str(layer), +			 layer->mixer_id); +	DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n", +			 sti_layer_to_str(layer), +			 layer->dst_w, layer->dst_h, layer->dst_x, layer->dst_y, +			 layer->src_w, layer->src_h, layer->src_x, +			 layer->src_y); + +	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, +			 (char *)&layer->format, (unsigned long)layer->paddr); + +	if (!layer->ops->prepare) +		goto err_no_prepare; + +	ret = layer->ops->prepare(layer, !layer->enabled); +	if (!ret) +		layer->enabled = true; + +	return ret; + +err_no_prepare: +	DRM_ERROR("Cannot prepare\n"); +	return 1; +} + +int sti_layer_commit(struct sti_layer *layer) +{ +	if (!layer) +		return 1; + +	if (!layer->ops->commit) +		goto err_no_commit; + +	return layer->ops->commit(layer); + +err_no_commit: +	DRM_ERROR("Cannot commit\n"); +	return 1; +} + +int sti_layer_disable(struct sti_layer *layer) +{ +	int ret; + +	DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer)); +	if (!layer) +		return 1; + +	if (!layer->enabled) +		return 0; + +	if (!layer->ops->disable) +		goto err_no_disable; + +	ret = layer->ops->disable(layer); +	if (!ret) +		layer->enabled = false; +	else +		DRM_ERROR("Disable failed\n"); + +	return ret; + +err_no_disable: +	DRM_ERROR("Cannot disable\n"); +	return 1; +} + +const uint32_t *sti_layer_get_formats(struct sti_layer *layer) +{ +	if (!layer) +		return NULL; + +	if (!layer->ops->get_formats) +		return NULL; + +	return layer->ops->get_formats(layer); +} + +unsigned int sti_layer_get_nb_formats(struct sti_layer *layer) +{ +	if (!layer) +		return 0; + +	if (!layer->ops->get_nb_formats) +		return 0; + +	return layer->ops->get_nb_formats(layer); +}  |