You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'exynos-drm-next' of git://git.infradead.org/users/kmpark/linux-samsung into drm-core-next
* 'exynos-drm-next' of git://git.infradead.org/users/kmpark/linux-samsung: drm/exynos: add G2D driver drm/exynos: added vp scaling feature for hdmi drm/exynos: added source size to overlay structure drm/exynos: add additional display mode for hdmi drm/exynos: enable dvi mode for dvi monitor drm/exynos: fixed wrong pageflip finish event for interlace mode drm/exynos: add PM functions for hdmi and mixer drm/exynos: add dpms for hdmi drm/exynos: use threaded irq for hdmi hotplug drm/exynos: use platform_get_irq_byname for hdmi drm/exynos: cleanup for hdmi platform data drm/exynos: added a feature to get gem buffer information. drm/exynos: added drm prime feature. drm/exynos: added cache attribute support for gem. vgaarb: Provide dummy default device functions
This commit is contained in:
@@ -10,6 +10,12 @@ config DRM_EXYNOS
|
||||
Choose this option if you have a Samsung SoC EXYNOS chipset.
|
||||
If M is selected the module will be called exynosdrm.
|
||||
|
||||
config DRM_EXYNOS_DMABUF
|
||||
bool "EXYNOS DRM DMABUF"
|
||||
depends on DRM_EXYNOS
|
||||
help
|
||||
Choose this option if you want to use DMABUF feature for DRM.
|
||||
|
||||
config DRM_EXYNOS_FIMD
|
||||
bool "Exynos DRM FIMD"
|
||||
depends on DRM_EXYNOS && !FB_S3C
|
||||
@@ -27,3 +33,9 @@ config DRM_EXYNOS_VIDI
|
||||
depends on DRM_EXYNOS
|
||||
help
|
||||
Choose this option if you want to use Exynos VIDI for DRM.
|
||||
|
||||
config DRM_EXYNOS_G2D
|
||||
bool "Exynos DRM G2D"
|
||||
depends on DRM_EXYNOS
|
||||
help
|
||||
Choose this option if you want to use Exynos G2D for DRM.
|
||||
|
||||
@@ -8,10 +8,12 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
|
||||
exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \
|
||||
exynos_drm_plane.o
|
||||
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \
|
||||
exynos_ddc.o exynos_hdmiphy.o \
|
||||
exynos_drm_hdmi.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
|
||||
|
||||
obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
|
||||
|
||||
@@ -35,7 +35,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
|
||||
unsigned int flags, struct exynos_drm_gem_buf *buf)
|
||||
{
|
||||
dma_addr_t start_addr;
|
||||
unsigned int npages, page_size, i = 0;
|
||||
unsigned int npages, i = 0;
|
||||
struct scatterlist *sgl;
|
||||
int ret = 0;
|
||||
|
||||
@@ -53,13 +53,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
|
||||
|
||||
if (buf->size >= SZ_1M) {
|
||||
npages = buf->size >> SECTION_SHIFT;
|
||||
page_size = SECTION_SIZE;
|
||||
buf->page_size = SECTION_SIZE;
|
||||
} else if (buf->size >= SZ_64K) {
|
||||
npages = buf->size >> 16;
|
||||
page_size = SZ_64K;
|
||||
buf->page_size = SZ_64K;
|
||||
} else {
|
||||
npages = buf->size >> PAGE_SHIFT;
|
||||
page_size = PAGE_SIZE;
|
||||
buf->page_size = PAGE_SIZE;
|
||||
}
|
||||
|
||||
buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
|
||||
@@ -96,9 +96,9 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
|
||||
|
||||
while (i < npages) {
|
||||
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], buf->page_size, 0);
|
||||
sg_dma_address(sgl) = start_addr;
|
||||
start_addr += page_size;
|
||||
start_addr += buf->page_size;
|
||||
sgl = sg_next(sgl);
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -105,6 +105,8 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
|
||||
overlay->fb_y = pos->fb_y;
|
||||
overlay->fb_width = fb->width;
|
||||
overlay->fb_height = fb->height;
|
||||
overlay->src_width = pos->src_w;
|
||||
overlay->src_height = pos->src_h;
|
||||
overlay->bpp = fb->bits_per_pixel;
|
||||
overlay->pitch = fb->pitches[0];
|
||||
overlay->pixel_format = fb->pixel_format;
|
||||
@@ -153,6 +155,8 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc)
|
||||
pos.crtc_y = 0;
|
||||
pos.crtc_w = fb->width - crtc->x;
|
||||
pos.crtc_h = fb->height - crtc->y;
|
||||
pos.src_w = pos.crtc_w;
|
||||
pos.src_h = pos.crtc_h;
|
||||
|
||||
return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
|
||||
* - the unit is screen coordinates.
|
||||
* @fb_y: offset y on a framebuffer to be displayed
|
||||
* - the unit is screen coordinates.
|
||||
* @src_w: width of source area to be displayed from a framebuffer.
|
||||
* @src_h: height of source area to be displayed from a framebuffer.
|
||||
* @crtc_x: offset x on hardware screen.
|
||||
* @crtc_y: offset y on hardware screen.
|
||||
* @crtc_w: width of hardware screen.
|
||||
@@ -50,6 +52,8 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
|
||||
struct exynos_drm_crtc_pos {
|
||||
unsigned int fb_x;
|
||||
unsigned int fb_y;
|
||||
unsigned int src_w;
|
||||
unsigned int src_h;
|
||||
unsigned int crtc_x;
|
||||
unsigned int crtc_y;
|
||||
unsigned int crtc_w;
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
/* exynos_drm_dmabuf.c
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* Author: Inki Dae <inki.dae@samsung.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_drm_gem.h"
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
static struct sg_table *exynos_pages_to_sg(struct page **pages, int nr_pages,
|
||||
unsigned int page_size)
|
||||
{
|
||||
struct sg_table *sgt = NULL;
|
||||
struct scatterlist *sgl;
|
||||
int i, ret;
|
||||
|
||||
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
|
||||
if (!sgt)
|
||||
goto out;
|
||||
|
||||
ret = sg_alloc_table(sgt, nr_pages, GFP_KERNEL);
|
||||
if (ret)
|
||||
goto err_free_sgt;
|
||||
|
||||
if (page_size < PAGE_SIZE)
|
||||
page_size = PAGE_SIZE;
|
||||
|
||||
for_each_sg(sgt->sgl, sgl, nr_pages, i)
|
||||
sg_set_page(sgl, pages[i], page_size, 0);
|
||||
|
||||
return sgt;
|
||||
|
||||
err_free_sgt:
|
||||
kfree(sgt);
|
||||
sgt = NULL;
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct sg_table *
|
||||
exynos_gem_map_dma_buf(struct dma_buf_attachment *attach,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv;
|
||||
struct drm_device *dev = gem_obj->base.dev;
|
||||
struct exynos_drm_gem_buf *buf;
|
||||
struct sg_table *sgt = NULL;
|
||||
unsigned int npages;
|
||||
int nents;
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
buf = gem_obj->buffer;
|
||||
|
||||
/* there should always be pages allocated. */
|
||||
if (!buf->pages) {
|
||||
DRM_ERROR("pages is null.\n");
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
npages = buf->size / buf->page_size;
|
||||
|
||||
sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size);
|
||||
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);
|
||||
|
||||
DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n",
|
||||
npages, buf->size, buf->page_size);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return sgt;
|
||||
}
|
||||
|
||||
static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
sgt = NULL;
|
||||
}
|
||||
|
||||
static void exynos_dmabuf_release(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv;
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* exynos_dmabuf_release() call means that file object's
|
||||
* f_count is 0 and it calls drm_gem_object_handle_unreference()
|
||||
* to drop the references that these values had been increased
|
||||
* at drm_prime_handle_to_fd()
|
||||
*/
|
||||
if (exynos_gem_obj->base.export_dma_buf == dmabuf) {
|
||||
exynos_gem_obj->base.export_dma_buf = NULL;
|
||||
|
||||
/*
|
||||
* drop this gem object refcount to release allocated buffer
|
||||
* and resources.
|
||||
*/
|
||||
drm_gem_object_unreference_unlocked(&exynos_gem_obj->base);
|
||||
}
|
||||
}
|
||||
|
||||
static void *exynos_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
|
||||
unsigned long page_num)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void exynos_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
|
||||
unsigned long page_num,
|
||||
void *addr)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void *exynos_gem_dmabuf_kmap(struct dma_buf *dma_buf,
|
||||
unsigned long page_num)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf,
|
||||
unsigned long page_num, void *addr)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static struct dma_buf_ops exynos_dmabuf_ops = {
|
||||
.map_dma_buf = exynos_gem_map_dma_buf,
|
||||
.unmap_dma_buf = exynos_gem_unmap_dma_buf,
|
||||
.kmap = exynos_gem_dmabuf_kmap,
|
||||
.kmap_atomic = exynos_gem_dmabuf_kmap_atomic,
|
||||
.kunmap = exynos_gem_dmabuf_kunmap,
|
||||
.kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic,
|
||||
.release = exynos_dmabuf_release,
|
||||
};
|
||||
|
||||
struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
|
||||
struct drm_gem_object *obj, int flags)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
|
||||
|
||||
return dma_buf_export(exynos_gem_obj, &exynos_dmabuf_ops,
|
||||
exynos_gem_obj->base.size, 0600);
|
||||
}
|
||||
|
||||
struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
|
||||
struct dma_buf *dma_buf)
|
||||
{
|
||||
struct dma_buf_attachment *attach;
|
||||
struct sg_table *sgt;
|
||||
struct scatterlist *sgl;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
struct page *page;
|
||||
int ret, i = 0;
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
/* is this one of own objects? */
|
||||
if (dma_buf->ops == &exynos_dmabuf_ops) {
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
exynos_gem_obj = dma_buf->priv;
|
||||
obj = &exynos_gem_obj->base;
|
||||
|
||||
/* is it from our device? */
|
||||
if (obj->dev == drm_dev) {
|
||||
drm_gem_object_reference(obj);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
attach = dma_buf_attach(dma_buf, drm_dev->dev);
|
||||
if (IS_ERR(attach))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
||||
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR(sgt)) {
|
||||
ret = PTR_ERR(sgt);
|
||||
goto err_buf_detach;
|
||||
}
|
||||
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
if (!buffer) {
|
||||
DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_unmap_attach;
|
||||
}
|
||||
|
||||
buffer->pages = kzalloc(sizeof(*page) * sgt->nents, GFP_KERNEL);
|
||||
if (!buffer->pages) {
|
||||
DRM_ERROR("failed to allocate pages.\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_free_buffer;
|
||||
}
|
||||
|
||||
exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size);
|
||||
if (!exynos_gem_obj) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_pages;
|
||||
}
|
||||
|
||||
sgl = sgt->sgl;
|
||||
buffer->dma_addr = sg_dma_address(sgl);
|
||||
|
||||
while (i < sgt->nents) {
|
||||
buffer->pages[i] = sg_page(sgl);
|
||||
buffer->size += sg_dma_len(sgl);
|
||||
sgl = sg_next(sgl);
|
||||
i++;
|
||||
}
|
||||
|
||||
exynos_gem_obj->buffer = buffer;
|
||||
buffer->sgt = sgt;
|
||||
exynos_gem_obj->base.import_attach = attach;
|
||||
|
||||
DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr,
|
||||
buffer->size);
|
||||
|
||||
return &exynos_gem_obj->base;
|
||||
|
||||
err_free_pages:
|
||||
kfree(buffer->pages);
|
||||
buffer->pages = NULL;
|
||||
err_free_buffer:
|
||||
kfree(buffer);
|
||||
buffer = NULL;
|
||||
err_unmap_attach:
|
||||
dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
|
||||
err_buf_detach:
|
||||
dma_buf_detach(dma_buf, attach);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
|
||||
MODULE_DESCRIPTION("Samsung SoC DRM DMABUF Module");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,39 @@
|
||||
/* exynos_drm_dmabuf.h
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* Author: Inki Dae <inki.dae@samsung.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _EXYNOS_DRM_DMABUF_H_
|
||||
#define _EXYNOS_DRM_DMABUF_H_
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_DMABUF
|
||||
struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
|
||||
struct drm_gem_object *obj, int flags);
|
||||
|
||||
struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
|
||||
struct dma_buf *dma_buf);
|
||||
#else
|
||||
#define exynos_dmabuf_prime_export NULL
|
||||
#define exynos_dmabuf_prime_import NULL
|
||||
#endif
|
||||
#endif
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "exynos_drm_gem.h"
|
||||
#include "exynos_drm_plane.h"
|
||||
#include "exynos_drm_vidi.h"
|
||||
#include "exynos_drm_dmabuf.h"
|
||||
#include "exynos_drm_g2d.h"
|
||||
|
||||
#define DRIVER_NAME "exynos"
|
||||
#define DRIVER_DESC "Samsung SoC DRM"
|
||||
@@ -147,8 +149,17 @@ static int exynos_drm_unload(struct drm_device *dev)
|
||||
|
||||
static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
|
||||
{
|
||||
struct drm_exynos_file_private *file_priv;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
|
||||
if (!file_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_prime_init_file_private(&file->prime);
|
||||
file->driver_priv = file_priv;
|
||||
|
||||
return exynos_drm_subdrv_open(dev, file);
|
||||
}
|
||||
|
||||
@@ -170,6 +181,7 @@ static void exynos_drm_preclose(struct drm_device *dev,
|
||||
e->base.destroy(&e->base);
|
||||
}
|
||||
}
|
||||
drm_prime_destroy_file_private(&file->prime);
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
|
||||
exynos_drm_subdrv_close(dev, file);
|
||||
@@ -207,10 +219,18 @@ static struct drm_ioctl_desc exynos_ioctls[] = {
|
||||
DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP,
|
||||
exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET,
|
||||
exynos_drm_gem_get_ioctl, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS, exynos_plane_set_zpos_ioctl,
|
||||
DRM_UNLOCKED | DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
|
||||
vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER,
|
||||
exynos_g2d_get_ver_ioctl, DRM_UNLOCKED | DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST,
|
||||
exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC,
|
||||
exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH),
|
||||
};
|
||||
|
||||
static const struct file_operations exynos_drm_driver_fops = {
|
||||
@@ -225,7 +245,7 @@ static const struct file_operations exynos_drm_driver_fops = {
|
||||
|
||||
static struct drm_driver exynos_drm_driver = {
|
||||
.driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM |
|
||||
DRIVER_MODESET | DRIVER_GEM,
|
||||
DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
|
||||
.load = exynos_drm_load,
|
||||
.unload = exynos_drm_unload,
|
||||
.open = exynos_drm_open,
|
||||
@@ -241,6 +261,10 @@ static struct drm_driver exynos_drm_driver = {
|
||||
.dumb_create = exynos_drm_gem_dumb_create,
|
||||
.dumb_map_offset = exynos_drm_gem_dumb_map_offset,
|
||||
.dumb_destroy = exynos_drm_gem_dumb_destroy,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_export = exynos_dmabuf_prime_export,
|
||||
.gem_prime_import = exynos_dmabuf_prime_import,
|
||||
.ioctls = exynos_ioctls,
|
||||
.fops = &exynos_drm_driver_fops,
|
||||
.name = DRIVER_NAME,
|
||||
@@ -307,6 +331,12 @@ static int __init exynos_drm_init(void)
|
||||
goto out_vidi;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_G2D
|
||||
ret = platform_driver_register(&g2d_driver);
|
||||
if (ret < 0)
|
||||
goto out_g2d;
|
||||
#endif
|
||||
|
||||
ret = platform_driver_register(&exynos_drm_platform_driver);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@@ -314,6 +344,11 @@ static int __init exynos_drm_init(void)
|
||||
return 0;
|
||||
|
||||
out:
|
||||
#ifdef CONFIG_DRM_EXYNOS_G2D
|
||||
platform_driver_unregister(&g2d_driver);
|
||||
out_g2d:
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_VIDI
|
||||
out_vidi:
|
||||
platform_driver_unregister(&vidi_driver);
|
||||
@@ -341,6 +376,10 @@ static void __exit exynos_drm_exit(void)
|
||||
|
||||
platform_driver_unregister(&exynos_drm_platform_driver);
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_G2D
|
||||
platform_driver_unregister(&g2d_driver);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_HDMI
|
||||
platform_driver_unregister(&exynos_drm_common_hdmi_driver);
|
||||
platform_driver_unregister(&mixer_driver);
|
||||
|
||||
@@ -77,6 +77,8 @@ struct exynos_drm_overlay_ops {
|
||||
* - the unit is screen coordinates.
|
||||
* @fb_width: width of a framebuffer.
|
||||
* @fb_height: height of a framebuffer.
|
||||
* @src_width: width of a partial image to be displayed from framebuffer.
|
||||
* @src_height: height of a partial image to be displayed from framebuffer.
|
||||
* @crtc_x: offset x on hardware screen.
|
||||
* @crtc_y: offset y on hardware screen.
|
||||
* @crtc_width: window width to be displayed (hardware screen).
|
||||
@@ -108,6 +110,8 @@ struct exynos_drm_overlay {
|
||||
unsigned int fb_y;
|
||||
unsigned int fb_width;
|
||||
unsigned int fb_height;
|
||||
unsigned int src_width;
|
||||
unsigned int src_height;
|
||||
unsigned int crtc_x;
|
||||
unsigned int crtc_y;
|
||||
unsigned int crtc_width;
|
||||
@@ -205,6 +209,18 @@ struct exynos_drm_manager {
|
||||
struct exynos_drm_display_ops *display_ops;
|
||||
};
|
||||
|
||||
struct exynos_drm_g2d_private {
|
||||
struct device *dev;
|
||||
struct list_head inuse_cmdlist;
|
||||
struct list_head event_list;
|
||||
struct list_head gem_list;
|
||||
unsigned int gem_nr;
|
||||
};
|
||||
|
||||
struct drm_exynos_file_private {
|
||||
struct exynos_drm_g2d_private *g2d_priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Exynos drm private structure.
|
||||
*/
|
||||
@@ -287,4 +303,5 @@ extern struct platform_driver hdmi_driver;
|
||||
extern struct platform_driver mixer_driver;
|
||||
extern struct platform_driver exynos_drm_common_hdmi_driver;
|
||||
extern struct platform_driver vidi_driver;
|
||||
extern struct platform_driver g2d_driver;
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics Co.Ltd
|
||||
* Authors: Joonyoung Shim <jy0922.shim@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundationr
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_G2D
|
||||
extern int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int exynos_g2d_set_cmdlist_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
#else
|
||||
static inline int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int exynos_g2d_set_cmdlist_ioctl(struct drm_device *dev,
|
||||
void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
@@ -66,6 +66,22 @@ static int check_gem_flags(unsigned int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
DRM_DEBUG_KMS("flags = 0x%x\n", obj->flags);
|
||||
|
||||
/* non-cachable as default. */
|
||||
if (obj->flags & EXYNOS_BO_CACHABLE)
|
||||
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
|
||||
else if (obj->flags & EXYNOS_BO_WC)
|
||||
vma->vm_page_prot =
|
||||
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
|
||||
else
|
||||
vma->vm_page_prot =
|
||||
pgprot_noncached(vm_get_page_prot(vma->vm_flags));
|
||||
}
|
||||
|
||||
static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
|
||||
{
|
||||
if (!IS_NONCONTIG_BUFFER(flags)) {
|
||||
@@ -80,7 +96,7 @@ out:
|
||||
return roundup(size, PAGE_SIZE);
|
||||
}
|
||||
|
||||
static struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
|
||||
struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
|
||||
gfp_t gfpmask)
|
||||
{
|
||||
struct inode *inode;
|
||||
@@ -180,6 +196,7 @@ static int exynos_drm_gem_get_pages(struct drm_gem_object *obj)
|
||||
}
|
||||
|
||||
npages = obj->size >> PAGE_SHIFT;
|
||||
buf->page_size = PAGE_SIZE;
|
||||
|
||||
buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
|
||||
if (!buf->sgt) {
|
||||
@@ -262,24 +279,24 @@ static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
|
||||
void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct exynos_drm_gem_buf *buf;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!exynos_gem_obj)
|
||||
return;
|
||||
|
||||
obj = &exynos_gem_obj->base;
|
||||
buf = exynos_gem_obj->buffer;
|
||||
|
||||
DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count));
|
||||
|
||||
if ((exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) &&
|
||||
exynos_gem_obj->buffer->pages)
|
||||
if (!buf->pages)
|
||||
return;
|
||||
|
||||
if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG)
|
||||
exynos_drm_gem_put_pages(obj);
|
||||
else
|
||||
exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags,
|
||||
exynos_gem_obj->buffer);
|
||||
exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf);
|
||||
|
||||
exynos_drm_fini_buf(obj->dev, exynos_gem_obj->buffer);
|
||||
exynos_drm_fini_buf(obj->dev, buf);
|
||||
exynos_gem_obj->buffer = NULL;
|
||||
|
||||
if (obj->map_list.map)
|
||||
@@ -292,7 +309,7 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
|
||||
exynos_gem_obj = NULL;
|
||||
}
|
||||
|
||||
static struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
|
||||
struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
|
||||
unsigned long size)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
@@ -493,8 +510,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
|
||||
|
||||
vma->vm_flags |= (VM_IO | VM_RESERVED);
|
||||
|
||||
/* in case of direct mapping, always having non-cachable attribute */
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
update_vm_cache_attr(exynos_gem_obj, vma);
|
||||
|
||||
vm_size = usize = vma->vm_end - vma->vm_start;
|
||||
|
||||
@@ -588,6 +604,32 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{ struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct drm_exynos_gem_info *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
||||
if (!obj) {
|
||||
DRM_ERROR("failed to lookup gem object.\n");
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
exynos_gem_obj = to_exynos_gem_obj(obj);
|
||||
|
||||
args->flags = exynos_gem_obj->flags;
|
||||
args->size = exynos_gem_obj->size;
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exynos_drm_gem_init_object(struct drm_gem_object *obj)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
@@ -597,8 +639,17 @@ int exynos_drm_gem_init_object(struct drm_gem_object *obj)
|
||||
|
||||
void exynos_drm_gem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct exynos_drm_gem_buf *buf;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_gem_obj = to_exynos_gem_obj(obj);
|
||||
buf = exynos_gem_obj->buffer;
|
||||
|
||||
if (obj->import_attach)
|
||||
drm_prime_gem_destroy(obj, buf->sgt);
|
||||
|
||||
exynos_drm_gem_destroy(to_exynos_gem_obj(obj));
|
||||
}
|
||||
|
||||
@@ -724,6 +775,8 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
|
||||
int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
@@ -735,8 +788,20 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
return ret;
|
||||
}
|
||||
|
||||
obj = vma->vm_private_data;
|
||||
exynos_gem_obj = to_exynos_gem_obj(obj);
|
||||
|
||||
ret = check_gem_flags(exynos_gem_obj->flags);
|
||||
if (ret) {
|
||||
drm_gem_vm_close(vma);
|
||||
drm_gem_free_mmap_offset(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vma->vm_flags &= ~VM_PFNMAP;
|
||||
vma->vm_flags |= VM_MIXEDMAP;
|
||||
|
||||
update_vm_cache_attr(exynos_gem_obj, vma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
* device address with IOMMU.
|
||||
* @sgt: sg table to transfer page data.
|
||||
* @pages: contain all pages to allocated memory region.
|
||||
* @page_size: could be 4K, 64K or 1MB.
|
||||
* @size: size of allocated memory region.
|
||||
*/
|
||||
struct exynos_drm_gem_buf {
|
||||
@@ -47,6 +48,7 @@ struct exynos_drm_gem_buf {
|
||||
dma_addr_t dma_addr;
|
||||
struct sg_table *sgt;
|
||||
struct page **pages;
|
||||
unsigned long page_size;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
@@ -74,9 +76,15 @@ struct exynos_drm_gem_obj {
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
|
||||
|
||||
/* destroy a buffer with gem object */
|
||||
void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
|
||||
|
||||
/* create a private gem object and initialize it. */
|
||||
struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
|
||||
unsigned long size);
|
||||
|
||||
/* create a new buffer with gem object */
|
||||
struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
|
||||
unsigned int flags,
|
||||
@@ -119,6 +127,10 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
|
||||
int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* get buffer information to memory region allocated by gem. */
|
||||
int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* initialize gem object. */
|
||||
int exynos_drm_gem_init_object(struct drm_gem_object *obj);
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ struct drm_hdmi_context {
|
||||
struct exynos_drm_subdrv subdrv;
|
||||
struct exynos_drm_hdmi_context *hdmi_ctx;
|
||||
struct exynos_drm_hdmi_context *mixer_ctx;
|
||||
|
||||
bool enabled[MIXER_WIN_NR];
|
||||
};
|
||||
|
||||
void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
|
||||
@@ -189,23 +191,34 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
if (hdmi_ops && hdmi_ops->disable)
|
||||
hdmi_ops->disable(ctx->hdmi_ctx->ctx);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unkown dps mode: %d\n", mode);
|
||||
break;
|
||||
if (mixer_ops && mixer_ops->dpms)
|
||||
mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
|
||||
|
||||
if (hdmi_ops && hdmi_ops->dpms)
|
||||
hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
|
||||
}
|
||||
|
||||
static void drm_hdmi_apply(struct device *subdrv_dev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
for (i = 0; i < MIXER_WIN_NR; i++) {
|
||||
if (!ctx->enabled[i])
|
||||
continue;
|
||||
if (mixer_ops && mixer_ops->win_commit)
|
||||
mixer_ops->win_commit(ctx->mixer_ctx->ctx, i);
|
||||
}
|
||||
|
||||
if (hdmi_ops && hdmi_ops->commit)
|
||||
hdmi_ops->commit(ctx->hdmi_ctx->ctx);
|
||||
}
|
||||
|
||||
static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
|
||||
.dpms = drm_hdmi_dpms,
|
||||
.apply = drm_hdmi_apply,
|
||||
.enable_vblank = drm_hdmi_enable_vblank,
|
||||
.disable_vblank = drm_hdmi_disable_vblank,
|
||||
.mode_fixup = drm_hdmi_mode_fixup,
|
||||
@@ -228,21 +241,37 @@ static void drm_mixer_mode_set(struct device *subdrv_dev,
|
||||
static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (win < 0 || win > MIXER_WIN_NR) {
|
||||
DRM_ERROR("mixer window[%d] is wrong\n", win);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mixer_ops && mixer_ops->win_commit)
|
||||
mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos);
|
||||
mixer_ops->win_commit(ctx->mixer_ctx->ctx, win);
|
||||
|
||||
ctx->enabled[win] = true;
|
||||
}
|
||||
|
||||
static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (win < 0 || win > MIXER_WIN_NR) {
|
||||
DRM_ERROR("mixer window[%d] is wrong\n", win);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mixer_ops && mixer_ops->win_disable)
|
||||
mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos);
|
||||
mixer_ops->win_disable(ctx->mixer_ctx->ctx, win);
|
||||
|
||||
ctx->enabled[win] = false;
|
||||
}
|
||||
|
||||
static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
|
||||
@@ -335,25 +364,6 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdmi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdmi_runtime_resume(struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops hdmi_pm_ops = {
|
||||
.runtime_suspend = hdmi_runtime_suspend,
|
||||
.runtime_resume = hdmi_runtime_resume,
|
||||
};
|
||||
|
||||
static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
|
||||
@@ -372,6 +382,5 @@ struct platform_driver exynos_drm_common_hdmi_driver = {
|
||||
.driver = {
|
||||
.name = "exynos-drm-hdmi",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &hdmi_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
#ifndef _EXYNOS_DRM_HDMI_H_
|
||||
#define _EXYNOS_DRM_HDMI_H_
|
||||
|
||||
#define MIXER_WIN_NR 3
|
||||
#define MIXER_DEFAULT_WIN 0
|
||||
|
||||
/*
|
||||
* exynos hdmi common context structure.
|
||||
*
|
||||
@@ -54,13 +57,14 @@ struct exynos_hdmi_ops {
|
||||
void (*get_max_resol)(void *ctx, unsigned int *width,
|
||||
unsigned int *height);
|
||||
void (*commit)(void *ctx);
|
||||
void (*disable)(void *ctx);
|
||||
void (*dpms)(void *ctx, int mode);
|
||||
};
|
||||
|
||||
struct exynos_mixer_ops {
|
||||
/* manager */
|
||||
int (*enable_vblank)(void *ctx, int pipe);
|
||||
void (*disable_vblank)(void *ctx);
|
||||
void (*dpms)(void *ctx, int mode);
|
||||
|
||||
/* overlay */
|
||||
void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
|
||||
|
||||
@@ -41,8 +41,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
container_of(plane, struct exynos_plane, base);
|
||||
struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
|
||||
struct exynos_drm_crtc_pos pos;
|
||||
unsigned int x = src_x >> 16;
|
||||
unsigned int y = src_y >> 16;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
@@ -53,10 +51,12 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
pos.crtc_w = crtc_w;
|
||||
pos.crtc_h = crtc_h;
|
||||
|
||||
pos.fb_x = x;
|
||||
pos.fb_y = y;
|
||||
/* considering 16.16 fixed point of source values */
|
||||
pos.fb_x = src_x >> 16;
|
||||
pos.fb_y = src_y >> 16;
|
||||
pos.src_w = src_w >> 16;
|
||||
pos.src_h = src_h >> 16;
|
||||
|
||||
/* TODO: scale feature */
|
||||
ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -138,14 +138,16 @@
|
||||
#define HDMI_ASP_MASK (1 << 2)
|
||||
#define HDMI_EN (1 << 0)
|
||||
|
||||
/* HDMI_CON_2 */
|
||||
#define HDMI_VID_PREAMBLE_DIS (1 << 5)
|
||||
#define HDMI_GUARD_BAND_DIS (1 << 1)
|
||||
|
||||
/* HDMI_PHY_STATUS */
|
||||
#define HDMI_PHY_STATUS_READY (1 << 0)
|
||||
|
||||
/* HDMI_MODE_SEL */
|
||||
#define HDMI_MODE_HDMI_EN (1 << 1)
|
||||
#define HDMI_MODE_DVI_EN (1 << 0)
|
||||
#define HDMI_DVI_MODE_EN (1)
|
||||
#define HDMI_DVI_MODE_DIS (0)
|
||||
#define HDMI_MODE_MASK (3 << 0)
|
||||
|
||||
/* HDMI_TG_CMD */
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#ifndef _EXYNOS_DRM_H_
|
||||
#define _EXYNOS_DRM_H_
|
||||
|
||||
#include "drm.h"
|
||||
|
||||
/**
|
||||
* User-desired buffer creation information structure.
|
||||
*
|
||||
@@ -74,6 +76,21 @@ struct drm_exynos_gem_mmap {
|
||||
uint64_t mapped;
|
||||
};
|
||||
|
||||
/**
|
||||
* A structure to gem information.
|
||||
*
|
||||
* @handle: a handle to gem object created.
|
||||
* @flags: flag value including memory type and cache attribute and
|
||||
* this value would be set by driver.
|
||||
* @size: size to memory region allocated by gem and this size would
|
||||
* be set by driver.
|
||||
*/
|
||||
struct drm_exynos_gem_info {
|
||||
unsigned int handle;
|
||||
unsigned int flags;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* A structure for user connection request of virtual display.
|
||||
*
|
||||
@@ -95,18 +112,64 @@ struct drm_exynos_plane_set_zpos {
|
||||
|
||||
/* memory type definitions. */
|
||||
enum e_drm_exynos_gem_mem_type {
|
||||
/* Physically Continuous memory and used as default. */
|
||||
EXYNOS_BO_CONTIG = 0 << 0,
|
||||
/* Physically Non-Continuous memory. */
|
||||
EXYNOS_BO_NONCONTIG = 1 << 0,
|
||||
EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG
|
||||
/* non-cachable mapping and used as default. */
|
||||
EXYNOS_BO_NONCACHABLE = 0 << 1,
|
||||
/* cachable mapping. */
|
||||
EXYNOS_BO_CACHABLE = 1 << 1,
|
||||
/* write-combine mapping. */
|
||||
EXYNOS_BO_WC = 1 << 2,
|
||||
EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG | EXYNOS_BO_CACHABLE |
|
||||
EXYNOS_BO_WC
|
||||
};
|
||||
|
||||
struct drm_exynos_g2d_get_ver {
|
||||
__u32 major;
|
||||
__u32 minor;
|
||||
};
|
||||
|
||||
struct drm_exynos_g2d_cmd {
|
||||
__u32 offset;
|
||||
__u32 data;
|
||||
};
|
||||
|
||||
enum drm_exynos_g2d_event_type {
|
||||
G2D_EVENT_NOT,
|
||||
G2D_EVENT_NONSTOP,
|
||||
G2D_EVENT_STOP, /* not yet */
|
||||
};
|
||||
|
||||
struct drm_exynos_g2d_set_cmdlist {
|
||||
__u64 cmd;
|
||||
__u64 cmd_gem;
|
||||
__u32 cmd_nr;
|
||||
__u32 cmd_gem_nr;
|
||||
|
||||
/* for g2d event */
|
||||
__u64 event_type;
|
||||
__u64 user_data;
|
||||
};
|
||||
|
||||
struct drm_exynos_g2d_exec {
|
||||
__u64 async;
|
||||
};
|
||||
|
||||
#define DRM_EXYNOS_GEM_CREATE 0x00
|
||||
#define DRM_EXYNOS_GEM_MAP_OFFSET 0x01
|
||||
#define DRM_EXYNOS_GEM_MMAP 0x02
|
||||
/* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */
|
||||
#define DRM_EXYNOS_GEM_GET 0x04
|
||||
#define DRM_EXYNOS_PLANE_SET_ZPOS 0x06
|
||||
#define DRM_EXYNOS_VIDI_CONNECTION 0x07
|
||||
|
||||
/* G2D */
|
||||
#define DRM_EXYNOS_G2D_GET_VER 0x20
|
||||
#define DRM_EXYNOS_G2D_SET_CMDLIST 0x21
|
||||
#define DRM_EXYNOS_G2D_EXEC 0x22
|
||||
|
||||
#define DRM_IOCTL_EXYNOS_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)
|
||||
|
||||
@@ -116,12 +179,34 @@ enum e_drm_exynos_gem_mem_type {
|
||||
#define DRM_IOCTL_EXYNOS_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap)
|
||||
|
||||
#define DRM_IOCTL_EXYNOS_GEM_GET DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_EXYNOS_GEM_GET, struct drm_exynos_gem_info)
|
||||
|
||||
#define DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_EXYNOS_PLANE_SET_ZPOS, struct drm_exynos_plane_set_zpos)
|
||||
|
||||
#define DRM_IOCTL_EXYNOS_VIDI_CONNECTION DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_EXYNOS_VIDI_CONNECTION, struct drm_exynos_vidi_connection)
|
||||
|
||||
#define DRM_IOCTL_EXYNOS_G2D_GET_VER DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_EXYNOS_G2D_GET_VER, struct drm_exynos_g2d_get_ver)
|
||||
#define DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_EXYNOS_G2D_SET_CMDLIST, struct drm_exynos_g2d_set_cmdlist)
|
||||
#define DRM_IOCTL_EXYNOS_G2D_EXEC DRM_IOWR(DRM_COMMAND_BASE + \
|
||||
DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec)
|
||||
|
||||
/* EXYNOS specific events */
|
||||
#define DRM_EXYNOS_G2D_EVENT 0x80000000
|
||||
|
||||
struct drm_exynos_g2d_event {
|
||||
struct drm_event base;
|
||||
__u64 user_data;
|
||||
__u32 tv_sec;
|
||||
__u32 tv_usec;
|
||||
__u32 cmdlist_no;
|
||||
__u32 reserved;
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/**
|
||||
@@ -169,16 +254,14 @@ struct exynos_drm_common_hdmi_pd {
|
||||
/**
|
||||
* Platform Specific Structure for DRM based HDMI core.
|
||||
*
|
||||
* @timing: default video mode for initializing
|
||||
* @default_win: default window layer number to be used for UI.
|
||||
* @bpp: default bit per pixel.
|
||||
* @is_v13: set if hdmi version 13 is.
|
||||
* @cfg_hpd: function pointer to configure hdmi hotplug detection pin
|
||||
* @get_hpd: function pointer to get value of hdmi hotplug detection pin
|
||||
*/
|
||||
struct exynos_drm_hdmi_pdata {
|
||||
struct fb_videomode timing;
|
||||
unsigned int default_win;
|
||||
unsigned int bpp;
|
||||
unsigned int is_v13:1;
|
||||
bool is_v13;
|
||||
void (*cfg_hpd)(bool external);
|
||||
int (*get_hpd)(void);
|
||||
};
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
Reference in New Issue
Block a user