diff options
Diffstat (limited to 'drivers/gpu/drm/exynos')
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_buf.c | 47 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_core.c | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 79 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 107 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 23 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_vidi.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 42 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 40 | 
12 files changed, 195 insertions, 213 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c index 4a3a5f72ed4..de8d2090bce 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c @@ -34,14 +34,14 @@  static int lowlevel_buffer_allocate(struct drm_device *dev,  		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;  	struct scatterlist *sgl;  	int ret = 0;  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (flags & EXYNOS_BO_NONCONTIG) { +	if (IS_NONCONTIG_BUFFER(flags)) {  		DRM_DEBUG_KMS("not support allocation type.\n");  		return -EINVAL;  	} @@ -52,13 +52,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,  	}  	if (buf->size >= SZ_1M) { -		npages = (buf->size >> SECTION_SHIFT) + 1; +		npages = buf->size >> SECTION_SHIFT;  		page_size = SECTION_SIZE;  	} else if (buf->size >= SZ_64K) { -		npages = (buf->size >> 16) + 1; +		npages = buf->size >> 16;  		page_size = SZ_64K;  	} else { -		npages = (buf->size >> PAGE_SHIFT) + 1; +		npages = buf->size >> PAGE_SHIFT;  		page_size = PAGE_SIZE;  	} @@ -76,26 +76,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,  		return -ENOMEM;  	} -		buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size, -				&buf->dma_addr, GFP_KERNEL); -		if (!buf->kvaddr) { -			DRM_ERROR("failed to allocate buffer.\n"); -			ret = -ENOMEM; -			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->kvaddr = dma_alloc_writecombine(dev->dev, buf->size, +			&buf->dma_addr, GFP_KERNEL); +	if (!buf->kvaddr) { +		DRM_ERROR("failed to allocate buffer.\n"); +		ret = -ENOMEM; +		goto err1; +	}  	buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);  	if (!buf->pages) { @@ -105,23 +92,17 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,  	}  	sgl = buf->sgt->sgl; +	start_addr = buf->dma_addr;  	while (i < npages) {  		buf->pages[i] = phys_to_page(start_addr);  		sg_set_page(sgl, buf->pages[i], page_size, 0);  		sg_dma_address(sgl) = start_addr;  		start_addr += page_size; -		if (end_addr - start_addr < page_size) -			break;  		sgl = sg_next(sgl);  		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",  			(unsigned long)buf->kvaddr,  			(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  	 * gem framework.  	 */ -	if (flags & EXYNOS_BO_NONCONTIG) { +	if (IS_NONCONTIG_BUFFER(flags)) {  		DRM_DEBUG_KMS("not support allocation type.\n");  		return;  	} diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c index 411832e8e17..eaf630dc5db 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c @@ -54,16 +54,18 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,  		 *  		 * 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)  			return ret;  	} -	if (subdrv->is_local) +	if (!subdrv->manager)  		return 0; +	subdrv->manager->dev = subdrv->dev; +  	/* 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);  	if (!encoder) {  		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) {  		if (subdrv->open) { -			ret = subdrv->open(dev, subdrv->manager.dev, file); +			ret = subdrv->open(dev, subdrv->dev, file);  			if (ret)  				goto err;  		} @@ -197,7 +199,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)  err:  	list_for_each_entry_reverse(subdrv, &subdrv->list, list) {  		if (subdrv->close) -			subdrv->close(dev, subdrv->manager.dev, file); +			subdrv->close(dev, subdrv->dev, file);  	}  	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) {  		if (subdrv->close) -			subdrv->close(dev, subdrv->manager.dev, file); +			subdrv->close(dev, subdrv->dev, file);  	}  }  EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index fbd0a232c93..1d814175cd4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -225,24 +225,25 @@ struct exynos_drm_private {   * Exynos drm sub driver structure.   *   * @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   *	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   *	subdrv is registered to it.   * @remove: this callback is used to release resources created   *	by probe callback.   * @open: this would be called with drm device file open.   * @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.   * @connector: connector object owned by this sub driver.   */  struct exynos_drm_subdrv {  	struct list_head list; +	struct device *dev;  	struct drm_device *drm_dev; -	bool is_local; +	struct exynos_drm_manager *manager;  	int (*probe)(struct drm_device *drm_dev, struct 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,  			struct drm_file *file); -	struct exynos_drm_manager manager;  	struct drm_encoder *encoder;  	struct drm_connector *connector;  }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index ecb6db22970..29fdbfeb43c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -172,7 +172,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)  static void fimd_apply(struct device *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_overlay_ops *ovl_ops = mgr->overlay_ops;  	struct fimd_win_data *win_data; @@ -577,6 +577,13 @@ static struct exynos_drm_overlay_ops fimd_overlay_ops = {  	.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)  {  	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 exynos_drm_subdrv *subdrv = &ctx->subdrv;  	struct drm_device *drm_dev = subdrv->drm_dev; -	struct exynos_drm_manager *manager = &subdrv->manager; +	struct exynos_drm_manager *manager = subdrv->manager;  	u32 val;  	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)  {  	struct exynos_drm_subdrv *subdrv = &ctx->subdrv; -	struct device *dev = subdrv->manager.dev; +	struct device *dev = subdrv->dev;  	DRM_DEBUG_KMS("%s\n", __FILE__); @@ -867,13 +874,10 @@ static int __devinit fimd_probe(struct platform_device *pdev)  	subdrv = &ctx->subdrv; +	subdrv->dev = dev; +	subdrv->manager = &fimd_manager;  	subdrv->probe = fimd_subdrv_probe;  	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); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index fa1aa94a3d8..1dffa8359f8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -56,9 +56,28 @@ static unsigned int convert_to_vm_err_msg(int 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, @@ -130,22 +149,12 @@ static int exynos_drm_gem_map_pages(struct drm_gem_object *obj,  	unsigned long pfn;  	if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { -		unsigned long usize = buf->size; -  		if (!buf->pages)  			return -EINTR; -		while (usize > 0) { -			pfn = page_to_pfn(buf->pages[page_offset++]); -			vm_insert_mixed(vma, f_vaddr, pfn); -			f_vaddr += PAGE_SIZE; -			usize -= PAGE_SIZE; -		} - -		return 0; -	} - -	pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset; +		pfn = page_to_pfn(buf->pages[page_offset++]); +	} else +		pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;  	return vm_insert_mixed(vma, f_vaddr, pfn);  } @@ -319,10 +328,17 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,  	struct exynos_drm_gem_buf *buf;  	int ret; -	size = roundup(size, PAGE_SIZE); -	DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size); +	if (!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);  	if (!buf) @@ -331,7 +347,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,  	exynos_gem_obj = exynos_drm_gem_init(dev, size);  	if (!exynos_gem_obj) {  		ret = -ENOMEM; -		goto err; +		goto err_fini_buf;  	}  	exynos_gem_obj->buffer = buf; @@ -347,18 +363,19 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,  		ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);  		if (ret < 0) {  			drm_gem_object_release(&exynos_gem_obj->base); -			goto err; +			goto err_fini_buf;  		}  	} else {  		ret = exynos_drm_alloc_buf(dev, buf, flags);  		if (ret < 0) {  			drm_gem_object_release(&exynos_gem_obj->base); -			goto err; +			goto err_fini_buf;  		}  	}  	return exynos_gem_obj; -err: + +err_fini_buf:  	exynos_drm_fini_buf(dev, buf);  	return ERR_PTR(ret);  } @@ -497,6 +514,8 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,  		if (!buffer->pages)  			return -EINVAL; +		vma->vm_flags |= VM_MIXEDMAP; +  		do {  			ret = vm_insert_page(vma, uaddr, buffer->pages[i++]);  			if (ret) { @@ -554,10 +573,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,  	obj->filp->f_op = &exynos_drm_gem_fops;  	obj->filp->private_data = obj; -	down_write(¤t->mm->mmap_sem); -	addr = do_mmap(obj->filp, 0, args->size, +	addr = vm_mmap(obj->filp, 0, args->size,  			PROT_READ | PROT_WRITE, MAP_SHARED, 0); -	up_write(¤t->mm->mmap_sem);  	drm_gem_object_unreference_unlocked(obj); @@ -685,7 +702,6 @@ int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,  int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  {  	struct drm_gem_object *obj = vma->vm_private_data; -	struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);  	struct drm_device *dev = obj->dev;  	unsigned long f_vaddr;  	pgoff_t page_offset; @@ -697,21 +713,10 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  	mutex_lock(&dev->struct_mutex); -	/* -	 * allocate all pages as desired size if user wants to allocate -	 * physically non-continuous memory. -	 */ -	if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { -		ret = exynos_drm_gem_get_pages(obj); -		if (ret < 0) -			goto err; -	} -  	ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset);  	if (ret < 0)  		DRM_ERROR("failed to map pages.\n"); -err:  	mutex_unlock(&dev->struct_mutex);  	return convert_to_vm_err_msg(ret); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index e40fbad8b70..4ed84203950 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -29,6 +29,8 @@  #define to_exynos_gem_obj(x)	container_of(x,\  			struct exynos_drm_gem_obj, base) +#define IS_NONCONTIG_BUFFER(f)		(f & EXYNOS_BO_NONCONTIG) +  /*   * exynos drm gem buffer structure.   * diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 14eb26b0ba1..3424463676e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -30,9 +30,8 @@  					struct drm_hdmi_context, subdrv);  /* these callback points shoud be set by specific drivers. */ -static struct exynos_hdmi_display_ops *hdmi_display_ops; -static struct exynos_hdmi_manager_ops *hdmi_manager_ops; -static struct exynos_hdmi_overlay_ops *hdmi_overlay_ops; +static struct exynos_hdmi_ops *hdmi_ops; +static struct exynos_mixer_ops *mixer_ops;  struct drm_hdmi_context {  	struct exynos_drm_subdrv	subdrv; @@ -40,31 +39,20 @@ struct drm_hdmi_context {  	struct exynos_drm_hdmi_context	*mixer_ctx;  }; -void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops -					*display_ops) +void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)  {  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (display_ops) -		hdmi_display_ops = display_ops; +	if (ops) +		hdmi_ops = ops;  } -void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops -					*manager_ops) +void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)  {  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (manager_ops) -		hdmi_manager_ops = manager_ops; -} - -void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops -					*overlay_ops) -{ -	DRM_DEBUG_KMS("%s\n", __FILE__); - -	if (overlay_ops) -		hdmi_overlay_ops = overlay_ops; +	if (ops) +		mixer_ops = ops;  }  static bool drm_hdmi_is_connected(struct device *dev) @@ -73,8 +61,8 @@ static bool drm_hdmi_is_connected(struct device *dev)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_display_ops && hdmi_display_ops->is_connected) -		return hdmi_display_ops->is_connected(ctx->hdmi_ctx->ctx); +	if (hdmi_ops && hdmi_ops->is_connected) +		return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);  	return false;  } @@ -86,9 +74,9 @@ static int drm_hdmi_get_edid(struct device *dev,  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_display_ops && hdmi_display_ops->get_edid) -		return hdmi_display_ops->get_edid(ctx->hdmi_ctx->ctx, -				connector, edid, len); +	if (hdmi_ops && hdmi_ops->get_edid) +		return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, +					  len);  	return 0;  } @@ -99,9 +87,8 @@ static int drm_hdmi_check_timing(struct device *dev, void *timing)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_display_ops && hdmi_display_ops->check_timing) -		return hdmi_display_ops->check_timing(ctx->hdmi_ctx->ctx, -				timing); +	if (hdmi_ops && hdmi_ops->check_timing) +		return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);  	return 0;  } @@ -112,8 +99,8 @@ static int drm_hdmi_power_on(struct device *dev, int mode)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_display_ops && hdmi_display_ops->power_on) -		return hdmi_display_ops->power_on(ctx->hdmi_ctx->ctx, mode); +	if (hdmi_ops && hdmi_ops->power_on) +		return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);  	return 0;  } @@ -130,13 +117,13 @@ static int drm_hdmi_enable_vblank(struct device *subdrv_dev)  {  	struct drm_hdmi_context *ctx = to_context(subdrv_dev);  	struct exynos_drm_subdrv *subdrv = &ctx->subdrv; -	struct exynos_drm_manager *manager = &subdrv->manager; +	struct exynos_drm_manager *manager = subdrv->manager;  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_overlay_ops && hdmi_overlay_ops->enable_vblank) -		return hdmi_overlay_ops->enable_vblank(ctx->mixer_ctx->ctx, -							manager->pipe); +	if (mixer_ops && mixer_ops->enable_vblank) +		return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, +						manager->pipe);  	return 0;  } @@ -147,8 +134,8 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_overlay_ops && hdmi_overlay_ops->disable_vblank) -		return hdmi_overlay_ops->disable_vblank(ctx->mixer_ctx->ctx); +	if (mixer_ops && mixer_ops->disable_vblank) +		return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);  }  static void drm_hdmi_mode_fixup(struct device *subdrv_dev, @@ -160,9 +147,9 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_manager_ops && hdmi_manager_ops->mode_fixup) -		hdmi_manager_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, -						mode, adjusted_mode); +	if (hdmi_ops && hdmi_ops->mode_fixup) +		hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode, +				     adjusted_mode);  }  static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode) @@ -171,8 +158,8 @@ static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_manager_ops && hdmi_manager_ops->mode_set) -		hdmi_manager_ops->mode_set(ctx->hdmi_ctx->ctx, mode); +	if (hdmi_ops && hdmi_ops->mode_set) +		hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);  }  static void drm_hdmi_get_max_resol(struct device *subdrv_dev, @@ -182,9 +169,8 @@ static void drm_hdmi_get_max_resol(struct device *subdrv_dev,  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_manager_ops && hdmi_manager_ops->get_max_resol) -		hdmi_manager_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, -							height); +	if (hdmi_ops && hdmi_ops->get_max_resol) +		hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);  }  static void drm_hdmi_commit(struct device *subdrv_dev) @@ -193,8 +179,8 @@ static void drm_hdmi_commit(struct device *subdrv_dev)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_manager_ops && hdmi_manager_ops->commit) -		hdmi_manager_ops->commit(ctx->hdmi_ctx->ctx); +	if (hdmi_ops && hdmi_ops->commit) +		hdmi_ops->commit(ctx->hdmi_ctx->ctx);  }  static void drm_hdmi_dpms(struct device *subdrv_dev, int mode) @@ -209,8 +195,8 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)  	case DRM_MODE_DPMS_STANDBY:  	case DRM_MODE_DPMS_SUSPEND:  	case DRM_MODE_DPMS_OFF: -		if (hdmi_manager_ops && hdmi_manager_ops->disable) -			hdmi_manager_ops->disable(ctx->hdmi_ctx->ctx); +		if (hdmi_ops && hdmi_ops->disable) +			hdmi_ops->disable(ctx->hdmi_ctx->ctx);  		break;  	default:  		DRM_DEBUG_KMS("unkown dps mode: %d\n", mode); @@ -235,8 +221,8 @@ static void drm_mixer_mode_set(struct device *subdrv_dev,  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_overlay_ops && hdmi_overlay_ops->win_mode_set) -		hdmi_overlay_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay); +	if (mixer_ops && mixer_ops->win_mode_set) +		mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);  }  static void drm_mixer_commit(struct device *subdrv_dev, int zpos) @@ -245,8 +231,8 @@ static void drm_mixer_commit(struct device *subdrv_dev, int zpos)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_overlay_ops && hdmi_overlay_ops->win_commit) -		hdmi_overlay_ops->win_commit(ctx->mixer_ctx->ctx, zpos); +	if (mixer_ops && mixer_ops->win_commit) +		mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos);  }  static void drm_mixer_disable(struct device *subdrv_dev, int zpos) @@ -255,8 +241,8 @@ static void drm_mixer_disable(struct device *subdrv_dev, int zpos)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	if (hdmi_overlay_ops && hdmi_overlay_ops->win_disable) -		hdmi_overlay_ops->win_disable(ctx->mixer_ctx->ctx, zpos); +	if (mixer_ops && mixer_ops->win_disable) +		mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos);  }  static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { @@ -265,6 +251,12 @@ static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {  	.disable = drm_mixer_disable,  }; +static struct exynos_drm_manager hdmi_manager = { +	.pipe		= -1, +	.ops		= &drm_hdmi_manager_ops, +	.overlay_ops	= &drm_hdmi_overlay_ops, +	.display_ops	= &drm_hdmi_display_ops, +};  static int hdmi_subdrv_probe(struct drm_device *drm_dev,  		struct device *dev) @@ -332,12 +324,9 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)  	subdrv = &ctx->subdrv; +	subdrv->dev = dev; +	subdrv->manager = &hdmi_manager;  	subdrv->probe = hdmi_subdrv_probe; -	subdrv->manager.pipe = -1; -	subdrv->manager.ops = &drm_hdmi_manager_ops; -	subdrv->manager.overlay_ops = &drm_hdmi_overlay_ops; -	subdrv->manager.display_ops = &drm_hdmi_display_ops; -	subdrv->manager.dev = dev;  	platform_set_drvdata(pdev, subdrv); diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index 44497cfb6c7..f3ae192c8dc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -38,15 +38,15 @@ struct exynos_drm_hdmi_context {  	void			*ctx;  }; -struct exynos_hdmi_display_ops { +struct exynos_hdmi_ops { +	/* display */  	bool (*is_connected)(void *ctx);  	int (*get_edid)(void *ctx, struct drm_connector *connector,  			u8 *edid, int len);  	int (*check_timing)(void *ctx, void *timing);  	int (*power_on)(void *ctx, int mode); -}; -struct exynos_hdmi_manager_ops { +	/* manager */  	void (*mode_fixup)(void *ctx, struct drm_connector *connector,  				struct drm_display_mode *mode,  				struct drm_display_mode *adjusted_mode); @@ -57,22 +57,17 @@ struct exynos_hdmi_manager_ops {  	void (*disable)(void *ctx);  }; -struct exynos_hdmi_overlay_ops { +struct exynos_mixer_ops { +	/* manager */  	int (*enable_vblank)(void *ctx, int pipe);  	void (*disable_vblank)(void *ctx); + +	/* overlay */  	void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);  	void (*win_commit)(void *ctx, int zpos);  	void (*win_disable)(void *ctx, int zpos);  }; -extern struct platform_driver hdmi_driver; -extern struct platform_driver mixer_driver; - -void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops -					*display_ops); -void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops -					*manager_ops); -void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops -					*overlay_ops); - +void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops); +void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);  #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index c277a3a445f..f92fe4c6174 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -24,6 +24,10 @@ struct exynos_plane {  static const uint32_t formats[] = {  	DRM_FORMAT_XRGB8888, +	DRM_FORMAT_ARGB8888, +	DRM_FORMAT_NV12, +	DRM_FORMAT_NV12M, +	DRM_FORMAT_NV12MT,  };  static int diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 8e1339f9fe1..7b9c153dceb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -199,7 +199,7 @@ static void vidi_dpms(struct device *subdrv_dev, int mode)  static void vidi_apply(struct device *subdrv_dev)  {  	struct vidi_context *ctx = get_vidi_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_overlay_ops *ovl_ops = mgr->overlay_ops;  	struct vidi_win_data *win_data; @@ -374,6 +374,13 @@ static struct exynos_drm_overlay_ops vidi_overlay_ops = {  	.disable = vidi_win_disable,  }; +static struct exynos_drm_manager vidi_manager = { +	.pipe		= -1, +	.ops		= &vidi_manager_ops, +	.overlay_ops	= &vidi_overlay_ops, +	.display_ops	= &vidi_display_ops, +}; +  static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc)  {  	struct exynos_drm_private *dev_priv = drm_dev->dev_private; @@ -425,7 +432,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)  	struct vidi_context *ctx = container_of(work, struct vidi_context,  					work);  	struct exynos_drm_subdrv *subdrv = &ctx->subdrv; -	struct exynos_drm_manager *manager = &subdrv->manager; +	struct exynos_drm_manager *manager = subdrv->manager;  	if (manager->pipe < 0)  		return; @@ -471,7 +478,7 @@ static void vidi_subdrv_remove(struct drm_device *drm_dev)  static int vidi_power_on(struct vidi_context *ctx, bool enable)  {  	struct exynos_drm_subdrv *subdrv = &ctx->subdrv; -	struct device *dev = subdrv->manager.dev; +	struct device *dev = subdrv->dev;  	DRM_DEBUG_KMS("%s\n", __FILE__); @@ -611,13 +618,10 @@ static int __devinit vidi_probe(struct platform_device *pdev)  	ctx->raw_edid = (struct edid *)fake_edid_info;  	subdrv = &ctx->subdrv; +	subdrv->dev = dev; +	subdrv->manager = &vidi_manager;  	subdrv->probe = vidi_subdrv_probe;  	subdrv->remove = vidi_subdrv_remove; -	subdrv->manager.pipe = -1; -	subdrv->manager.ops = &vidi_manager_ops; -	subdrv->manager.overlay_ops = &vidi_overlay_ops; -	subdrv->manager.display_ops = &vidi_display_ops; -	subdrv->manager.dev = dev;  	mutex_init(&ctx->lock); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 575a8cbd353..b0035387645 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -40,7 +40,6 @@  #include "exynos_hdmi.h" -#define HDMI_OVERLAY_NUMBER	3  #define MAX_WIDTH		1920  #define MAX_HEIGHT		1080  #define get_hdmi_context(dev)	platform_get_drvdata(to_platform_device(dev)) @@ -1194,7 +1193,7 @@ static int hdmi_conf_index(struct hdmi_context *hdata,  static bool hdmi_is_connected(void *ctx)  { -	struct hdmi_context *hdata = (struct hdmi_context *)ctx; +	struct hdmi_context *hdata = ctx;  	u32 val = hdmi_reg_read(hdata, HDMI_HPD_STATUS);  	if (val) @@ -1207,7 +1206,7 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector,  				u8 *edid, int len)  {  	struct edid *raw_edid; -	struct hdmi_context *hdata = (struct hdmi_context *)ctx; +	struct hdmi_context *hdata = ctx;  	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1275,7 +1274,7 @@ static int hdmi_v14_check_timing(struct fb_videomode *check_timing)  static int hdmi_check_timing(void *ctx, void *timing)  { -	struct hdmi_context *hdata = (struct hdmi_context *)ctx; +	struct hdmi_context *hdata = ctx;  	struct fb_videomode *check_timing = timing;  	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1312,13 +1311,6 @@ static int hdmi_display_power_on(void *ctx, int mode)  	return 0;  } -static struct exynos_hdmi_display_ops display_ops = { -	.is_connected	= hdmi_is_connected, -	.get_edid	= hdmi_get_edid, -	.check_timing	= hdmi_check_timing, -	.power_on	= hdmi_display_power_on, -}; -  static void hdmi_set_acr(u32 freq, u8 *acr)  {  	u32 n, cts; @@ -1914,7 +1906,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,  				struct drm_display_mode *adjusted_mode)  {  	struct drm_display_mode *m; -	struct hdmi_context *hdata = (struct hdmi_context *)ctx; +	struct hdmi_context *hdata = ctx;  	int index;  	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1951,7 +1943,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,  static void hdmi_mode_set(void *ctx, void *mode)  { -	struct hdmi_context *hdata = (struct hdmi_context *)ctx; +	struct hdmi_context *hdata = ctx;  	int conf_idx;  	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1974,7 +1966,7 @@ static void hdmi_get_max_resol(void *ctx, unsigned int *width,  static void hdmi_commit(void *ctx)  { -	struct hdmi_context *hdata = (struct hdmi_context *)ctx; +	struct hdmi_context *hdata = ctx;  	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1985,7 +1977,7 @@ static void hdmi_commit(void *ctx)  static void hdmi_disable(void *ctx)  { -	struct hdmi_context *hdata = (struct hdmi_context *)ctx; +	struct hdmi_context *hdata = ctx;  	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1996,7 +1988,14 @@ static void hdmi_disable(void *ctx)  	}  } -static struct exynos_hdmi_manager_ops manager_ops = { +static struct exynos_hdmi_ops hdmi_ops = { +	/* display */ +	.is_connected	= hdmi_is_connected, +	.get_edid	= hdmi_get_edid, +	.check_timing	= hdmi_check_timing, +	.power_on	= hdmi_display_power_on, + +	/* manager */  	.mode_fixup	= hdmi_mode_fixup,  	.mode_set	= hdmi_mode_set,  	.get_max_resol	= hdmi_get_max_resol, @@ -2020,7 +2019,7 @@ static void hdmi_hotplug_func(struct work_struct *work)  static irqreturn_t hdmi_irq_handler(int irq, void *arg)  {  	struct exynos_drm_hdmi_context *ctx = arg; -	struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx; +	struct hdmi_context *hdata = ctx->ctx;  	u32 intc_flag;  	intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); @@ -2173,7 +2172,7 @@ static int hdmi_runtime_suspend(struct device *dev)  	DRM_DEBUG_KMS("%s\n", __func__); -	hdmi_resource_poweroff((struct hdmi_context *)ctx->ctx); +	hdmi_resource_poweroff(ctx->ctx);  	return 0;  } @@ -2184,7 +2183,7 @@ static int hdmi_runtime_resume(struct device *dev)  	DRM_DEBUG_KMS("%s\n", __func__); -	hdmi_resource_poweron((struct hdmi_context *)ctx->ctx); +	hdmi_resource_poweron(ctx->ctx);  	return 0;  } @@ -2322,8 +2321,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev)  	hdata->irq = res->start;  	/* register specific callbacks to common hdmi. */ -	exynos_drm_display_ops_register(&display_ops); -	exynos_drm_manager_ops_register(&manager_ops); +	exynos_hdmi_ops_register(&hdmi_ops);  	hdmi_resource_poweron(hdata); @@ -2351,7 +2349,7 @@ err_data:  static int __devexit hdmi_remove(struct platform_device *pdev)  {  	struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev); -	struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx; +	struct hdmi_context *hdata = ctx->ctx;  	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 4d5f41e1952..e15438c0112 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -37,7 +37,8 @@  #include "exynos_drm_drv.h"  #include "exynos_drm_hdmi.h" -#define HDMI_OVERLAY_NUMBER	3 +#define MIXER_WIN_NR		3 +#define MIXER_DEFAULT_WIN	0  #define get_mixer_context(dev)	platform_get_drvdata(to_platform_device(dev)) @@ -75,16 +76,12 @@ struct mixer_resources {  };  struct mixer_context { -	struct fb_videomode	*default_timing; -	unsigned int		default_win; -	unsigned int		default_bpp;  	unsigned int		irq;  	int			pipe;  	bool			interlace; -	bool			vp_enabled;  	struct mixer_resources	mixer_res; -	struct hdmi_win_data	win_data[HDMI_OVERLAY_NUMBER]; +	struct hdmi_win_data	win_data[MIXER_WIN_NR];  };  static const u8 filter_y_horiz_tap8[] = { @@ -643,9 +640,9 @@ static void mixer_win_mode_set(void *ctx,  	win = overlay->zpos;  	if (win == DEFAULT_ZPOS) -		win = mixer_ctx->default_win; +		win = MIXER_DEFAULT_WIN; -	if (win < 0 || win > HDMI_OVERLAY_NUMBER) { +	if (win < 0 || win > MIXER_WIN_NR) {  		DRM_ERROR("overlay plane[%d] is wrong\n", win);  		return;  	} @@ -683,9 +680,9 @@ static void mixer_win_commit(void *ctx, int zpos)  	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);  	if (win == DEFAULT_ZPOS) -		win = mixer_ctx->default_win; +		win = MIXER_DEFAULT_WIN; -	if (win < 0 || win > HDMI_OVERLAY_NUMBER) { +	if (win < 0 || win > MIXER_WIN_NR) {  		DRM_ERROR("overlay plane[%d] is wrong\n", win);  		return;  	} @@ -706,9 +703,9 @@ static void mixer_win_disable(void *ctx, int zpos)  	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);  	if (win == DEFAULT_ZPOS) -		win = mixer_ctx->default_win; +		win = MIXER_DEFAULT_WIN; -	if (win < 0 || win > HDMI_OVERLAY_NUMBER) { +	if (win < 0 || win > MIXER_WIN_NR) {  		DRM_ERROR("overlay plane[%d] is wrong\n", win);  		return;  	} @@ -722,9 +719,12 @@ static void mixer_win_disable(void *ctx, int zpos)  	spin_unlock_irqrestore(&res->reg_slock, flags);  } -static struct exynos_hdmi_overlay_ops overlay_ops = { +static struct exynos_mixer_ops mixer_ops = { +	/* manager */  	.enable_vblank		= mixer_enable_vblank,  	.disable_vblank		= mixer_disable_vblank, + +	/* overlay */  	.win_mode_set		= mixer_win_mode_set,  	.win_commit		= mixer_win_commit,  	.win_disable		= mixer_win_disable, @@ -771,8 +771,7 @@ static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)  static irqreturn_t mixer_irq_handler(int irq, void *arg)  {  	struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg; -	struct mixer_context *ctx = -			(struct mixer_context *)drm_hdmi_ctx->ctx; +	struct mixer_context *ctx = drm_hdmi_ctx->ctx;  	struct mixer_resources *res = &ctx->mixer_res;  	u32 val, val_base; @@ -902,7 +901,7 @@ static int mixer_runtime_resume(struct device *dev)  	DRM_DEBUG_KMS("resume - start\n"); -	mixer_resource_poweron((struct mixer_context *)ctx->ctx); +	mixer_resource_poweron(ctx->ctx);  	return 0;  } @@ -913,7 +912,7 @@ static int mixer_runtime_suspend(struct device *dev)  	DRM_DEBUG_KMS("suspend - start\n"); -	mixer_resource_poweroff((struct mixer_context *)ctx->ctx); +	mixer_resource_poweroff(ctx->ctx);  	return 0;  } @@ -926,8 +925,7 @@ static const struct dev_pm_ops mixer_pm_ops = {  static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,  				 struct platform_device *pdev)  { -	struct mixer_context *mixer_ctx = -			(struct mixer_context *)ctx->ctx; +	struct mixer_context *mixer_ctx = ctx->ctx;  	struct device *dev = &pdev->dev;  	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;  	struct resource *res; @@ -1076,7 +1074,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)  		goto fail;  	/* register specific callback point to common hdmi. */ -	exynos_drm_overlay_ops_register(&overlay_ops); +	exynos_mixer_ops_register(&mixer_ops);  	mixer_resource_poweron(ctx); @@ -1093,7 +1091,7 @@ static int mixer_remove(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct exynos_drm_hdmi_context *drm_hdmi_ctx =  					platform_get_drvdata(pdev); -	struct mixer_context *ctx = (struct mixer_context *)drm_hdmi_ctx->ctx; +	struct mixer_context *ctx = drm_hdmi_ctx->ctx;  	dev_info(dev, "remove successful\n");  |