Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 173fa4ec authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'exynos-drm-fixes' of...

Merge branch 'exynos-drm-fixes' of git://git.infradead.org/users/kmpark/linux-samsung into drm-intel-fixes

* 'exynos-drm-fixes' of git://git.infradead.org/users/kmpark/linux-samsung:
  drm/exynos: fixed exynos broken ioctl
  drm/exynos: fix to pointer manager member of struct exynos_drm_subdrv
  drm/exynos: fix struct for operation callback functions to driver name
  drm/exynos: use define instead of default_win member in struct mixer_context
  drm/exynos: rename s/HDMI_OVERLAY_NUMBER/MIXER_WIN_NR
  drm/exynos: remove unused codes in hdmi and mixer
  drm/exynos: remove unnecessary type conversion of hdmi and mixer
  drm/exynos: add format list of plane
  drm/exynos: fixed duplicated page allocation bug.
  drm/exynos: fixed page align and code clean.
parents 19e5c4e7 490aa60e
Loading
Loading
Loading
Loading
+14 −33
Original line number Original line Diff line number Diff line
@@ -34,14 +34,14 @@
static int lowlevel_buffer_allocate(struct drm_device *dev,
static int lowlevel_buffer_allocate(struct drm_device *dev,
		unsigned int flags, struct exynos_drm_gem_buf *buf)
		unsigned int flags, struct exynos_drm_gem_buf *buf)
{
{
	dma_addr_t start_addr, end_addr;
	dma_addr_t start_addr;
	unsigned int npages, page_size, i = 0;
	unsigned int npages, page_size, i = 0;
	struct scatterlist *sgl;
	struct scatterlist *sgl;
	int ret = 0;
	int ret = 0;


	DRM_DEBUG_KMS("%s\n", __FILE__);
	DRM_DEBUG_KMS("%s\n", __FILE__);


	if (flags & EXYNOS_BO_NONCONTIG) {
	if (IS_NONCONTIG_BUFFER(flags)) {
		DRM_DEBUG_KMS("not support allocation type.\n");
		DRM_DEBUG_KMS("not support allocation type.\n");
		return -EINVAL;
		return -EINVAL;
	}
	}
@@ -52,13 +52,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
	}
	}


	if (buf->size >= SZ_1M) {
	if (buf->size >= SZ_1M) {
		npages = (buf->size >> SECTION_SHIFT) + 1;
		npages = buf->size >> SECTION_SHIFT;
		page_size = SECTION_SIZE;
		page_size = SECTION_SIZE;
	} else if (buf->size >= SZ_64K) {
	} else if (buf->size >= SZ_64K) {
		npages = (buf->size >> 16) + 1;
		npages = buf->size >> 16;
		page_size = SZ_64K;
		page_size = SZ_64K;
	} else {
	} else {
		npages = (buf->size >> PAGE_SHIFT) + 1;
		npages = buf->size >> PAGE_SHIFT;
		page_size = PAGE_SIZE;
		page_size = PAGE_SIZE;
	}
	}


@@ -84,19 +84,6 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
		goto err1;
		goto err1;
	}
	}


		start_addr = buf->dma_addr;
		end_addr = buf->dma_addr + buf->size;

		buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
		if (!buf->pages) {
			DRM_ERROR("failed to allocate pages.\n");
			ret = -ENOMEM;
			goto err2;
		}

	start_addr = buf->dma_addr;
	end_addr = buf->dma_addr + buf->size;

	buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
	buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
	if (!buf->pages) {
	if (!buf->pages) {
		DRM_ERROR("failed to allocate pages.\n");
		DRM_ERROR("failed to allocate pages.\n");
@@ -105,23 +92,17 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
	}
	}


	sgl = buf->sgt->sgl;
	sgl = buf->sgt->sgl;
	start_addr = buf->dma_addr;


	while (i < npages) {
	while (i < npages) {
		buf->pages[i] = phys_to_page(start_addr);
		buf->pages[i] = phys_to_page(start_addr);
		sg_set_page(sgl, buf->pages[i], page_size, 0);
		sg_set_page(sgl, buf->pages[i], page_size, 0);
		sg_dma_address(sgl) = start_addr;
		sg_dma_address(sgl) = start_addr;
		start_addr += page_size;
		start_addr += page_size;
		if (end_addr - start_addr < page_size)
			break;
		sgl = sg_next(sgl);
		sgl = sg_next(sgl);
		i++;
		i++;
	}
	}


	buf->pages[i] = phys_to_page(start_addr);

	sgl = sg_next(sgl);
	sg_set_page(sgl, buf->pages[i+1], end_addr - start_addr, 0);

	DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
	DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
			(unsigned long)buf->kvaddr,
			(unsigned long)buf->kvaddr,
			(unsigned long)buf->dma_addr,
			(unsigned long)buf->dma_addr,
@@ -150,7 +131,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
	 * non-continuous memory would be released by exynos
	 * non-continuous memory would be released by exynos
	 * gem framework.
	 * gem framework.
	 */
	 */
	if (flags & EXYNOS_BO_NONCONTIG) {
	if (IS_NONCONTIG_BUFFER(flags)) {
		DRM_DEBUG_KMS("not support allocation type.\n");
		DRM_DEBUG_KMS("not support allocation type.\n");
		return;
		return;
	}
	}
+8 −6
Original line number Original line Diff line number Diff line
@@ -54,16 +54,18 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
		 *
		 *
		 * P.S. note that this driver is considered for modularization.
		 * P.S. note that this driver is considered for modularization.
		 */
		 */
		ret = subdrv->probe(dev, subdrv->manager.dev);
		ret = subdrv->probe(dev, subdrv->dev);
		if (ret)
		if (ret)
			return ret;
			return ret;
	}
	}


	if (subdrv->is_local)
	if (!subdrv->manager)
		return 0;
		return 0;


	subdrv->manager->dev = subdrv->dev;

	/* create and initialize a encoder for this sub driver. */
	/* create and initialize a encoder for this sub driver. */
	encoder = exynos_drm_encoder_create(dev, &subdrv->manager,
	encoder = exynos_drm_encoder_create(dev, subdrv->manager,
			(1 << MAX_CRTC) - 1);
			(1 << MAX_CRTC) - 1);
	if (!encoder) {
	if (!encoder) {
		DRM_ERROR("failed to create encoder\n");
		DRM_ERROR("failed to create encoder\n");
@@ -186,7 +188,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)


	list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
	list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
		if (subdrv->open) {
		if (subdrv->open) {
			ret = subdrv->open(dev, subdrv->manager.dev, file);
			ret = subdrv->open(dev, subdrv->dev, file);
			if (ret)
			if (ret)
				goto err;
				goto err;
		}
		}
@@ -197,7 +199,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
err:
err:
	list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
	list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
		if (subdrv->close)
		if (subdrv->close)
			subdrv->close(dev, subdrv->manager.dev, file);
			subdrv->close(dev, subdrv->dev, file);
	}
	}
	return ret;
	return ret;
}
}
@@ -209,7 +211,7 @@ void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)


	list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
	list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
		if (subdrv->close)
		if (subdrv->close)
			subdrv->close(dev, subdrv->manager.dev, file);
			subdrv->close(dev, subdrv->dev, file);
	}
	}
}
}
EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
+5 −5
Original line number Original line Diff line number Diff line
@@ -225,24 +225,25 @@ struct exynos_drm_private {
 * Exynos drm sub driver structure.
 * Exynos drm sub driver structure.
 *
 *
 * @list: sub driver has its own list object to register to exynos drm driver.
 * @list: sub driver has its own list object to register to exynos drm driver.
 * @dev: pointer to device object for subdrv device driver.
 * @drm_dev: pointer to drm_device and this pointer would be set
 * @drm_dev: pointer to drm_device and this pointer would be set
 *	when sub driver calls exynos_drm_subdrv_register().
 *	when sub driver calls exynos_drm_subdrv_register().
 * @is_local: appear encoder and connector disrelated device.
 * @manager: subdrv has its own manager to control a hardware appropriately
 *	and we can access a hardware drawing on this manager.
 * @probe: this callback would be called by exynos drm driver after
 * @probe: this callback would be called by exynos drm driver after
 *	subdrv is registered to it.
 *	subdrv is registered to it.
 * @remove: this callback is used to release resources created
 * @remove: this callback is used to release resources created
 *	by probe callback.
 *	by probe callback.
 * @open: this would be called with drm device file open.
 * @open: this would be called with drm device file open.
 * @close: this would be called with drm device file close.
 * @close: this would be called with drm device file close.
 * @manager: subdrv has its own manager to control a hardware appropriately
 *	and we can access a hardware drawing on this manager.
 * @encoder: encoder object owned by this sub driver.
 * @encoder: encoder object owned by this sub driver.
 * @connector: connector object owned by this sub driver.
 * @connector: connector object owned by this sub driver.
 */
 */
struct exynos_drm_subdrv {
struct exynos_drm_subdrv {
	struct list_head list;
	struct list_head list;
	struct device *dev;
	struct drm_device *drm_dev;
	struct drm_device *drm_dev;
	bool is_local;
	struct exynos_drm_manager *manager;


	int (*probe)(struct drm_device *drm_dev, struct device *dev);
	int (*probe)(struct drm_device *drm_dev, struct device *dev);
	void (*remove)(struct drm_device *dev);
	void (*remove)(struct drm_device *dev);
@@ -251,7 +252,6 @@ struct exynos_drm_subdrv {
	void (*close)(struct drm_device *drm_dev, struct device *dev,
	void (*close)(struct drm_device *drm_dev, struct device *dev,
			struct drm_file *file);
			struct drm_file *file);


	struct exynos_drm_manager manager;
	struct drm_encoder *encoder;
	struct drm_encoder *encoder;
	struct drm_connector *connector;
	struct drm_connector *connector;
};
};
+12 −8
Original line number Original line Diff line number Diff line
@@ -172,7 +172,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
static void fimd_apply(struct device *subdrv_dev)
static void fimd_apply(struct device *subdrv_dev)
{
{
	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
	struct exynos_drm_manager *mgr = &ctx->subdrv.manager;
	struct exynos_drm_manager *mgr = ctx->subdrv.manager;
	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
	struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
	struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
	struct fimd_win_data *win_data;
	struct fimd_win_data *win_data;
@@ -577,6 +577,13 @@ static struct exynos_drm_overlay_ops fimd_overlay_ops = {
	.disable = fimd_win_disable,
	.disable = fimd_win_disable,
};
};


static struct exynos_drm_manager fimd_manager = {
	.pipe		= -1,
	.ops		= &fimd_manager_ops,
	.overlay_ops	= &fimd_overlay_ops,
	.display_ops	= &fimd_display_ops,
};

static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
{
{
	struct exynos_drm_private *dev_priv = drm_dev->dev_private;
	struct exynos_drm_private *dev_priv = drm_dev->dev_private;
@@ -628,7 +635,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
	struct fimd_context *ctx = (struct fimd_context *)dev_id;
	struct fimd_context *ctx = (struct fimd_context *)dev_id;
	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
	struct drm_device *drm_dev = subdrv->drm_dev;
	struct drm_device *drm_dev = subdrv->drm_dev;
	struct exynos_drm_manager *manager = &subdrv->manager;
	struct exynos_drm_manager *manager = subdrv->manager;
	u32 val;
	u32 val;


	val = readl(ctx->regs + VIDINTCON1);
	val = readl(ctx->regs + VIDINTCON1);
@@ -744,7 +751,7 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
static int fimd_power_on(struct fimd_context *ctx, bool enable)
static int fimd_power_on(struct fimd_context *ctx, bool enable)
{
{
	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
	struct device *dev = subdrv->manager.dev;
	struct device *dev = subdrv->dev;


	DRM_DEBUG_KMS("%s\n", __FILE__);
	DRM_DEBUG_KMS("%s\n", __FILE__);


@@ -867,13 +874,10 @@ static int __devinit fimd_probe(struct platform_device *pdev)


	subdrv = &ctx->subdrv;
	subdrv = &ctx->subdrv;


	subdrv->dev = dev;
	subdrv->manager = &fimd_manager;
	subdrv->probe = fimd_subdrv_probe;
	subdrv->probe = fimd_subdrv_probe;
	subdrv->remove = fimd_subdrv_remove;
	subdrv->remove = fimd_subdrv_remove;
	subdrv->manager.pipe = -1;
	subdrv->manager.ops = &fimd_manager_ops;
	subdrv->manager.overlay_ops = &fimd_overlay_ops;
	subdrv->manager.display_ops = &fimd_display_ops;
	subdrv->manager.dev = dev;


	mutex_init(&ctx->lock);
	mutex_init(&ctx->lock);


+36 −9
Original line number Original line Diff line number Diff line
@@ -56,9 +56,28 @@ static unsigned int convert_to_vm_err_msg(int msg)
	return out_msg;
	return out_msg;
}
}


static unsigned int mask_gem_flags(unsigned int flags)
static int check_gem_flags(unsigned int flags)
{
{
	return flags &= EXYNOS_BO_NONCONTIG;
	if (flags & ~(EXYNOS_BO_MASK)) {
		DRM_ERROR("invalid flags.\n");
		return -EINVAL;
	}

	return 0;
}

static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
{
	if (!IS_NONCONTIG_BUFFER(flags)) {
		if (size >= SZ_1M)
			return roundup(size, SECTION_SIZE);
		else if (size >= SZ_64K)
			return roundup(size, SZ_64K);
		else
			goto out;
	}
out:
	return roundup(size, PAGE_SIZE);
}
}


static struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
static struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
@@ -319,10 +338,17 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
	struct exynos_drm_gem_buf *buf;
	struct exynos_drm_gem_buf *buf;
	int ret;
	int ret;


	size = roundup(size, PAGE_SIZE);
	if (!size) {
	DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
		DRM_ERROR("invalid size.\n");
		return ERR_PTR(-EINVAL);
	}

	size = roundup_gem_size(size, flags);
	DRM_DEBUG_KMS("%s\n", __FILE__);


	flags = mask_gem_flags(flags);
	ret = check_gem_flags(flags);
	if (ret)
		return ERR_PTR(ret);


	buf = exynos_drm_init_buf(dev, size);
	buf = exynos_drm_init_buf(dev, size);
	if (!buf)
	if (!buf)
@@ -331,7 +357,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
	exynos_gem_obj = exynos_drm_gem_init(dev, size);
	exynos_gem_obj = exynos_drm_gem_init(dev, size);
	if (!exynos_gem_obj) {
	if (!exynos_gem_obj) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto err;
		goto err_fini_buf;
	}
	}


	exynos_gem_obj->buffer = buf;
	exynos_gem_obj->buffer = buf;
@@ -347,18 +373,19 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
		ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);
		ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);
		if (ret < 0) {
		if (ret < 0) {
			drm_gem_object_release(&exynos_gem_obj->base);
			drm_gem_object_release(&exynos_gem_obj->base);
			goto err;
			goto err_fini_buf;
		}
		}
	} else {
	} else {
		ret = exynos_drm_alloc_buf(dev, buf, flags);
		ret = exynos_drm_alloc_buf(dev, buf, flags);
		if (ret < 0) {
		if (ret < 0) {
			drm_gem_object_release(&exynos_gem_obj->base);
			drm_gem_object_release(&exynos_gem_obj->base);
			goto err;
			goto err_fini_buf;
		}
		}
	}
	}


	return exynos_gem_obj;
	return exynos_gem_obj;
err:

err_fini_buf:
	exynos_drm_fini_buf(dev, buf);
	exynos_drm_fini_buf(dev, buf);
	return ERR_PTR(ret);
	return ERR_PTR(ret);
}
}
Loading