mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
Merge branch 'exynos-drm-next' of git://git.infradead.org/users/kmpark/linux-samsung into drm-core-next
these patch sets include the following features: - add Samsung SoC Exynos based HDMI support. - add pm feature for fimd driver. - add multi buffer plane pixel formats to drm/drm_fourcc.h. multi buffer plane pixel format has seperated memory spaces for each plane. for exampme, NV12M has Y plane and CbCr plane and these are in non-continuous memory region. compared with NV12, NV12M's memory shape is like following. NV12 : ______(Y)(CbCr)_______ NV12M : __(Y)_ ..... _(CbCr)__ - bug fix to vblank. - code clean to exynos gem framework. * 'exynos-drm-next' of git://git.infradead.org/users/kmpark/linux-samsung: drm/exynos: added hdmi display support drm/exynos: added mutex lock and code clean. drm/exynos: extend vblank off delay time. drm/exynos: change driver name. drm/exynos: Support multi buffers drm: Add multi buffer plane pixel formats drm/exynos: added pm support. drm/exynos: remove buffer creation of fbdev from drm framebuffer creation drm/exynos: Split creation of gem object and gem handle drm/exynos: Fix a fake mmap offset creation drm/exynos: gem code cleanup
This commit is contained in:
commit
863f78b5ff
@ -18,3 +18,10 @@ config DRM_EXYNOS_FIMD
|
||||
help
|
||||
Choose this option if you want to use Exynos FIMD for DRM.
|
||||
If M is selected, the module will be called exynos_drm_fimd
|
||||
|
||||
config DRM_EXYNOS_HDMI
|
||||
tristate "Exynos DRM HDMI"
|
||||
depends on DRM_EXYNOS
|
||||
help
|
||||
Choose this option if you want to use Exynos HDMI for DRM.
|
||||
If M is selected, the module will be called exynos_drm_hdmi
|
||||
|
@ -10,3 +10,5 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
|
||||
|
||||
obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
|
||||
obj-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
|
||||
obj-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o exynos_ddc.o \
|
||||
exynos_hdmiphy.o exynos_drm_hdmi.o
|
||||
|
58
drivers/gpu/drm/exynos/exynos_ddc.c
Normal file
58
drivers/gpu/drm/exynos/exynos_ddc.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Samsung Electronics Co.Ltd
|
||||
* Authors:
|
||||
* Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
* Inki Dae <inki.dae@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_hdmi.h"
|
||||
|
||||
static int s5p_ddc_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
{
|
||||
hdmi_attach_ddc_client(client);
|
||||
|
||||
dev_info(&client->adapter->dev, "attached s5p_ddc "
|
||||
"into i2c adapter successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5p_ddc_remove(struct i2c_client *client)
|
||||
{
|
||||
dev_info(&client->adapter->dev, "detached s5p_ddc "
|
||||
"from i2c adapter successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_device_id ddc_idtable[] = {
|
||||
{"s5p_ddc", 0},
|
||||
{ },
|
||||
};
|
||||
|
||||
struct i2c_driver ddc_driver = {
|
||||
.driver = {
|
||||
.name = "s5p_ddc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = ddc_idtable,
|
||||
.probe = s5p_ddc_probe,
|
||||
.remove = __devexit_p(s5p_ddc_remove),
|
||||
.command = NULL,
|
||||
};
|
||||
EXPORT_SYMBOL(ddc_driver);
|
@ -73,7 +73,7 @@ struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
if (!buffer) {
|
||||
DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->size = size;
|
||||
@ -84,8 +84,7 @@ struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
|
||||
*/
|
||||
if (lowlevel_buffer_allocate(dev, buffer) < 0) {
|
||||
kfree(buffer);
|
||||
buffer = NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
|
@ -30,9 +30,6 @@
|
||||
struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
|
||||
unsigned int size);
|
||||
|
||||
/* get memory information of a drm framebuffer. */
|
||||
struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
|
||||
|
||||
/* remove allocated physical memory. */
|
||||
void exynos_drm_buf_destroy(struct drm_device *dev,
|
||||
struct exynos_drm_gem_buf *buffer);
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "exynos_drm_fb.h"
|
||||
#include "exynos_drm_encoder.h"
|
||||
#include "exynos_drm_gem.h"
|
||||
#include "exynos_drm_buf.h"
|
||||
|
||||
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
|
||||
drm_crtc)
|
||||
@ -80,20 +79,24 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
unsigned int actual_w;
|
||||
unsigned int actual_h;
|
||||
int nr = exynos_drm_format_num_buffers(fb->pixel_format);
|
||||
int i;
|
||||
|
||||
buffer = exynos_drm_fb_get_buf(fb);
|
||||
if (!buffer) {
|
||||
DRM_LOG_KMS("buffer is null.\n");
|
||||
return -EFAULT;
|
||||
for (i = 0; i < nr; i++) {
|
||||
buffer = exynos_drm_fb_buffer(fb, i);
|
||||
if (!buffer) {
|
||||
DRM_LOG_KMS("buffer is null\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
overlay->dma_addr[i] = buffer->dma_addr;
|
||||
overlay->vaddr[i] = buffer->kvaddr;
|
||||
|
||||
DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
|
||||
i, (unsigned long)overlay->vaddr[i],
|
||||
(unsigned long)overlay->dma_addr[i]);
|
||||
}
|
||||
|
||||
overlay->dma_addr = buffer->dma_addr;
|
||||
overlay->vaddr = buffer->kvaddr;
|
||||
|
||||
DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
|
||||
(unsigned long)overlay->vaddr,
|
||||
(unsigned long)overlay->dma_addr);
|
||||
|
||||
actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
|
||||
actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
|
||||
|
||||
@ -104,6 +107,7 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
|
||||
overlay->fb_height = fb->height;
|
||||
overlay->bpp = fb->bits_per_pixel;
|
||||
overlay->pitch = fb->pitches[0];
|
||||
overlay->pixel_format = fb->pixel_format;
|
||||
|
||||
/* set overlay range to be displayed. */
|
||||
overlay->crtc_x = pos->crtc_x;
|
||||
|
@ -38,12 +38,14 @@
|
||||
#include "exynos_drm_gem.h"
|
||||
#include "exynos_drm_plane.h"
|
||||
|
||||
#define DRIVER_NAME "exynos-drm"
|
||||
#define DRIVER_NAME "exynos"
|
||||
#define DRIVER_DESC "Samsung SoC DRM"
|
||||
#define DRIVER_DATE "20110530"
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 0
|
||||
|
||||
#define VBLANK_OFF_DELAY 50000
|
||||
|
||||
static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
struct exynos_drm_private *private;
|
||||
@ -107,6 +109,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
goto err_drm_device;
|
||||
}
|
||||
|
||||
drm_vblank_offdelay = VBLANK_OFF_DELAY;
|
||||
|
||||
return 0;
|
||||
|
||||
err_drm_device:
|
||||
|
@ -34,12 +34,15 @@
|
||||
|
||||
#define MAX_CRTC 2
|
||||
#define MAX_PLANE 5
|
||||
#define MAX_FB_BUFFER 3
|
||||
#define DEFAULT_ZPOS -1
|
||||
|
||||
struct drm_device;
|
||||
struct exynos_drm_overlay;
|
||||
struct drm_connector;
|
||||
|
||||
extern unsigned int drm_vblank_offdelay;
|
||||
|
||||
/* this enumerates display type. */
|
||||
enum exynos_drm_output_type {
|
||||
EXYNOS_DISPLAY_TYPE_NONE,
|
||||
@ -82,9 +85,10 @@ struct exynos_drm_overlay_ops {
|
||||
* @scan_flag: interlace or progressive way.
|
||||
* (it could be DRM_MODE_FLAG_*)
|
||||
* @bpp: pixel size.(in bit)
|
||||
* @dma_addr: bus(accessed by dma) address to the memory region allocated
|
||||
* for a overlay.
|
||||
* @vaddr: virtual memory addresss to this overlay.
|
||||
* @pixel_format: fourcc pixel format of this overlay
|
||||
* @dma_addr: array of bus(accessed by dma) address to the memory region
|
||||
* allocated for a overlay.
|
||||
* @vaddr: array of virtual memory addresss to this overlay.
|
||||
* @zpos: order of overlay layer(z position).
|
||||
* @default_win: a window to be enabled.
|
||||
* @color_key: color key on or off.
|
||||
@ -112,8 +116,9 @@ struct exynos_drm_overlay {
|
||||
unsigned int scan_flag;
|
||||
unsigned int bpp;
|
||||
unsigned int pitch;
|
||||
dma_addr_t dma_addr;
|
||||
void __iomem *vaddr;
|
||||
uint32_t pixel_format;
|
||||
dma_addr_t dma_addr[MAX_FB_BUFFER];
|
||||
void __iomem *vaddr[MAX_FB_BUFFER];
|
||||
int zpos;
|
||||
|
||||
bool default_win;
|
||||
|
@ -33,7 +33,6 @@
|
||||
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_drm_fb.h"
|
||||
#include "exynos_drm_buf.h"
|
||||
#include "exynos_drm_gem.h"
|
||||
|
||||
#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb)
|
||||
@ -42,15 +41,11 @@
|
||||
* exynos specific framebuffer structure.
|
||||
*
|
||||
* @fb: drm framebuffer obejct.
|
||||
* @exynos_gem_obj: exynos specific gem object containing a gem object.
|
||||
* @buffer: pointer to exynos_drm_gem_buffer object.
|
||||
* - contain the memory information to memory region allocated
|
||||
* at default framebuffer creation.
|
||||
* @exynos_gem_obj: array of exynos specific gem object containing a gem object.
|
||||
*/
|
||||
struct exynos_drm_fb {
|
||||
struct drm_framebuffer fb;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER];
|
||||
};
|
||||
|
||||
static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
|
||||
@ -61,13 +56,6 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
|
||||
|
||||
drm_framebuffer_cleanup(fb);
|
||||
|
||||
/*
|
||||
* default framebuffer has no gem object so
|
||||
* a buffer of the default framebuffer should be released at here.
|
||||
*/
|
||||
if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer)
|
||||
exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer);
|
||||
|
||||
kfree(exynos_fb);
|
||||
exynos_fb = NULL;
|
||||
}
|
||||
@ -81,7 +69,7 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return drm_gem_handle_create(file_priv,
|
||||
&exynos_fb->exynos_gem_obj->base, handle);
|
||||
&exynos_fb->exynos_gem_obj[0]->base, handle);
|
||||
}
|
||||
|
||||
static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
|
||||
@ -102,132 +90,88 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
|
||||
.dirty = exynos_drm_fb_dirty,
|
||||
};
|
||||
|
||||
static struct drm_framebuffer *
|
||||
exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
struct drm_framebuffer *
|
||||
exynos_drm_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj)
|
||||
{
|
||||
struct exynos_drm_fb *exynos_fb;
|
||||
struct drm_framebuffer *fb;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
|
||||
struct drm_gem_object *obj;
|
||||
unsigned int size;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
DRM_LOG_KMS("drm fb create(%dx%d)\n",
|
||||
mode_cmd->width, mode_cmd->height);
|
||||
|
||||
exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
|
||||
if (!exynos_fb) {
|
||||
DRM_ERROR("failed to allocate exynos drm framebuffer.\n");
|
||||
DRM_ERROR("failed to allocate exynos drm framebuffer\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
fb = &exynos_fb->fb;
|
||||
ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs);
|
||||
ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to initialize framebuffer.\n");
|
||||
goto err_init;
|
||||
DRM_ERROR("failed to initialize framebuffer\n");
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
DRM_LOG_KMS("create: fb id: %d\n", fb->base.id);
|
||||
drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
|
||||
exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
|
||||
|
||||
size = mode_cmd->pitches[0] * mode_cmd->height;
|
||||
|
||||
/*
|
||||
* mode_cmd->handles[0] could be NULL at booting time or
|
||||
* with user request. if NULL, a new buffer or a gem object
|
||||
* would be allocated.
|
||||
*/
|
||||
if (!mode_cmd->handles[0]) {
|
||||
if (!file_priv) {
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
|
||||
/*
|
||||
* in case that file_priv is NULL, it allocates
|
||||
* only buffer and this buffer would be used
|
||||
* for default framebuffer.
|
||||
*/
|
||||
buffer = exynos_drm_buf_create(dev, size);
|
||||
if (IS_ERR(buffer)) {
|
||||
ret = PTR_ERR(buffer);
|
||||
goto err_buffer;
|
||||
}
|
||||
|
||||
exynos_fb->buffer = buffer;
|
||||
|
||||
DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n",
|
||||
(unsigned long)buffer->dma_addr, size);
|
||||
|
||||
goto out;
|
||||
} else {
|
||||
exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
|
||||
&mode_cmd->handles[0],
|
||||
size);
|
||||
if (IS_ERR(exynos_gem_obj)) {
|
||||
ret = PTR_ERR(exynos_gem_obj);
|
||||
goto err_buffer;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
obj = drm_gem_object_lookup(dev, file_priv,
|
||||
mode_cmd->handles[0]);
|
||||
if (!obj) {
|
||||
DRM_ERROR("failed to lookup gem object.\n");
|
||||
goto err_buffer;
|
||||
}
|
||||
|
||||
exynos_gem_obj = to_exynos_gem_obj(obj);
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* if got a exynos_gem_obj from either a handle or
|
||||
* a new creation then exynos_fb->exynos_gem_obj is NULL
|
||||
* so that default framebuffer has no its own gem object,
|
||||
* only its own buffer object.
|
||||
*/
|
||||
exynos_fb->buffer = exynos_gem_obj->buffer;
|
||||
|
||||
DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
|
||||
(unsigned long)exynos_fb->buffer->dma_addr, size,
|
||||
(unsigned int)&exynos_gem_obj->base);
|
||||
|
||||
out:
|
||||
exynos_fb->exynos_gem_obj = exynos_gem_obj;
|
||||
|
||||
drm_helper_mode_fill_fb_struct(fb, mode_cmd);
|
||||
|
||||
return fb;
|
||||
|
||||
err_buffer:
|
||||
drm_framebuffer_cleanup(fb);
|
||||
|
||||
err_init:
|
||||
kfree(exynos_fb);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
return &exynos_fb->fb;
|
||||
}
|
||||
|
||||
struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
static struct drm_framebuffer *
|
||||
exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_framebuffer *fb;
|
||||
struct exynos_drm_fb *exynos_fb;
|
||||
int nr;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return exynos_drm_fb_init(file_priv, dev, mode_cmd);
|
||||
obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
|
||||
if (!obj) {
|
||||
DRM_ERROR("failed to lookup gem object\n");
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
|
||||
fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj);
|
||||
if (IS_ERR(fb))
|
||||
return fb;
|
||||
|
||||
exynos_fb = to_exynos_fb(fb);
|
||||
nr = exynos_drm_format_num_buffers(fb->pixel_format);
|
||||
|
||||
for (i = 1; i < nr; i++) {
|
||||
obj = drm_gem_object_lookup(dev, file_priv,
|
||||
mode_cmd->handles[i]);
|
||||
if (!obj) {
|
||||
DRM_ERROR("failed to lookup gem object\n");
|
||||
exynos_drm_fb_destroy(fb);
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
|
||||
exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
|
||||
}
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
|
||||
struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
|
||||
int index)
|
||||
{
|
||||
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
buffer = exynos_fb->buffer;
|
||||
if (index >= MAX_FB_BUFFER)
|
||||
return NULL;
|
||||
|
||||
buffer = exynos_fb->exynos_gem_obj[index]->buffer;
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
@ -248,7 +192,7 @@ static void exynos_drm_output_poll_changed(struct drm_device *dev)
|
||||
}
|
||||
|
||||
static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
|
||||
.fb_create = exynos_drm_fb_create,
|
||||
.fb_create = exynos_user_fb_create,
|
||||
.output_poll_changed = exynos_drm_output_poll_changed,
|
||||
};
|
||||
|
||||
|
@ -28,9 +28,27 @@
|
||||
#ifndef _EXYNOS_DRM_FB_H_
|
||||
#define _EXYNOS_DRM_FB_H
|
||||
|
||||
struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
|
||||
struct drm_file *filp,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
static inline int exynos_drm_format_num_buffers(uint32_t format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_NV12M:
|
||||
case DRM_FORMAT_NV12MT:
|
||||
return 2;
|
||||
case DRM_FORMAT_YUV420M:
|
||||
return 3;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct drm_framebuffer *
|
||||
exynos_drm_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
/* get memory information of a drm framebuffer */
|
||||
struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
|
||||
int index);
|
||||
|
||||
void exynos_drm_mode_config_init(struct drm_device *dev);
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_drm_fb.h"
|
||||
#include "exynos_drm_gem.h"
|
||||
#include "exynos_drm_buf.h"
|
||||
|
||||
#define MAX_CONNECTOR 4
|
||||
#define PREFERRED_BPP 32
|
||||
@ -43,8 +42,8 @@
|
||||
drm_fb_helper)
|
||||
|
||||
struct exynos_drm_fbdev {
|
||||
struct drm_fb_helper drm_fb_helper;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_fb_helper drm_fb_helper;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
};
|
||||
|
||||
static int exynos_drm_fbdev_set_par(struct fb_info *info)
|
||||
@ -90,19 +89,17 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
|
||||
{
|
||||
struct fb_info *fbi = helper->fbdev;
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
|
||||
unsigned long offset;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_fb->fb = fb;
|
||||
|
||||
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
|
||||
|
||||
buffer = exynos_drm_fb_get_buf(fb);
|
||||
/* RGB formats use only one buffer */
|
||||
buffer = exynos_drm_fb_buffer(fb, 0);
|
||||
if (!buffer) {
|
||||
DRM_LOG_KMS("buffer is null.\n");
|
||||
return -EFAULT;
|
||||
@ -124,10 +121,12 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct fb_info *fbi;
|
||||
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
|
||||
struct platform_device *pdev = dev->platformdev;
|
||||
unsigned long size;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
@ -151,14 +150,23 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
goto out;
|
||||
}
|
||||
|
||||
exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
|
||||
if (IS_ERR_OR_NULL(exynos_fbdev->fb)) {
|
||||
DRM_ERROR("failed to create drm framebuffer.\n");
|
||||
ret = PTR_ERR(exynos_fbdev->fb);
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
exynos_gem_obj = exynos_drm_gem_create(dev, size);
|
||||
if (IS_ERR(exynos_gem_obj)) {
|
||||
ret = PTR_ERR(exynos_gem_obj);
|
||||
goto out;
|
||||
}
|
||||
|
||||
exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
|
||||
|
||||
helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
|
||||
&exynos_gem_obj->base);
|
||||
if (IS_ERR_OR_NULL(helper->fb)) {
|
||||
DRM_ERROR("failed to create drm framebuffer.\n");
|
||||
ret = PTR_ERR(helper->fb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
helper->fb = exynos_fbdev->fb;
|
||||
helper->fbdev = fbi;
|
||||
|
||||
fbi->par = helper;
|
||||
@ -172,8 +180,10 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
}
|
||||
|
||||
ret = exynos_drm_fbdev_update(helper, helper->fb);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
fb_dealloc_cmap(&fbi->cmap);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* if failed, all resources allocated above would be released by
|
||||
@ -206,16 +216,13 @@ static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
|
||||
{
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
|
||||
struct drm_framebuffer *fb = exynos_fbdev->fb;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct drm_framebuffer *fb = helper->fb;
|
||||
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
|
||||
unsigned long size;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (helper->fb != fb) {
|
||||
DRM_ERROR("drm framebuffer is different\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (exynos_drm_fbdev_is_samefb(fb, sizes))
|
||||
return 0;
|
||||
|
||||
@ -225,16 +232,26 @@ static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
|
||||
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
||||
sizes->surface_depth);
|
||||
|
||||
if (exynos_fbdev->exynos_gem_obj)
|
||||
exynos_drm_gem_destroy(exynos_fbdev->exynos_gem_obj);
|
||||
|
||||
if (fb->funcs->destroy)
|
||||
fb->funcs->destroy(fb);
|
||||
|
||||
exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
|
||||
if (IS_ERR(exynos_fbdev->fb)) {
|
||||
DRM_ERROR("failed to allocate fb.\n");
|
||||
return PTR_ERR(exynos_fbdev->fb);
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
exynos_gem_obj = exynos_drm_gem_create(dev, size);
|
||||
if (IS_ERR(exynos_gem_obj))
|
||||
return PTR_ERR(exynos_gem_obj);
|
||||
|
||||
exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
|
||||
|
||||
helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
|
||||
&exynos_gem_obj->base);
|
||||
if (IS_ERR_OR_NULL(helper->fb)) {
|
||||
DRM_ERROR("failed to create drm framebuffer.\n");
|
||||
return PTR_ERR(helper->fb);
|
||||
}
|
||||
|
||||
helper->fb = exynos_fbdev->fb;
|
||||
return exynos_drm_fbdev_update(helper, helper->fb);
|
||||
}
|
||||
|
||||
@ -368,6 +385,9 @@ void exynos_drm_fbdev_fini(struct drm_device *dev)
|
||||
|
||||
fbdev = to_exynos_fbdev(private->fb_helper);
|
||||
|
||||
if (fbdev->exynos_gem_obj)
|
||||
exynos_drm_gem_destroy(fbdev->exynos_gem_obj);
|
||||
|
||||
exynos_drm_fbdev_destroy(dev, private->fb_helper);
|
||||
kfree(fbdev);
|
||||
private->fb_helper = NULL;
|
||||
|
@ -87,6 +87,7 @@ struct fimd_context {
|
||||
u32 vidcon0;
|
||||
u32 vidcon1;
|
||||
bool suspended;
|
||||
struct mutex lock;
|
||||
|
||||
struct fb_videomode *timing;
|
||||
};
|
||||
@ -137,11 +138,22 @@ static struct exynos_drm_display_ops fimd_display_ops = {
|
||||
|
||||
static void fimd_dpms(struct device *subdrv_dev, int mode)
|
||||
{
|
||||
struct fimd_context *ctx = get_fimd_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
pm_runtime_get_sync(subdrv_dev);
|
||||
/*
|
||||
* enable fimd hardware only if suspended status.
|
||||
*
|
||||
* P.S. fimd_dpms function would be called at booting time so
|
||||
* clk_enable could be called double time.
|
||||
*/
|
||||
if (ctx->suspended)
|
||||
pm_runtime_get_sync(subdrv_dev);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
@ -152,6 +164,8 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
|
||||
DRM_DEBUG_KMS("unspecified mode %d\n", mode);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
static void fimd_apply(struct device *subdrv_dev)
|
||||
@ -181,6 +195,9 @@ static void fimd_commit(struct device *dev)
|
||||
struct fb_videomode *timing = ctx->timing;
|
||||
u32 val;
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* setup polarity values from machine code. */
|
||||
@ -310,8 +327,8 @@ static void fimd_win_mode_set(struct device *dev,
|
||||
win_data->ovl_height = overlay->crtc_height;
|
||||
win_data->fb_width = overlay->fb_width;
|
||||
win_data->fb_height = overlay->fb_height;
|
||||
win_data->dma_addr = overlay->dma_addr + offset;
|
||||
win_data->vaddr = overlay->vaddr + offset;
|
||||
win_data->dma_addr = overlay->dma_addr[0] + offset;
|
||||
win_data->vaddr = overlay->vaddr[0] + offset;
|
||||
win_data->bpp = overlay->bpp;
|
||||
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
|
||||
(overlay->bpp >> 3);
|
||||
@ -414,6 +431,9 @@ static void fimd_win_commit(struct device *dev, int zpos)
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
@ -797,13 +817,6 @@ static int __devinit fimd_probe(struct platform_device *pdev)
|
||||
goto err_req_irq;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
for (win = 0; win < WINDOWS_NR; win++)
|
||||
fimd_clear_win(ctx, win);
|
||||
|
||||
ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
|
||||
ctx->vidcon0 = pdata->vidcon0;
|
||||
ctx->vidcon1 = pdata->vidcon1;
|
||||
@ -825,7 +838,17 @@ static int __devinit fimd_probe(struct platform_device *pdev)
|
||||
subdrv->manager.display_ops = &fimd_display_ops;
|
||||
subdrv->manager.dev = dev;
|
||||
|
||||
mutex_init(&ctx->lock);
|
||||
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
for (win = 0; win < WINDOWS_NR; win++)
|
||||
fimd_clear_win(ctx, win);
|
||||
|
||||
exynos_drm_subdrv_register(subdrv);
|
||||
|
||||
return 0;
|
||||
@ -885,6 +908,47 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int fimd_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
ret = pm_runtime_suspend(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fimd_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume(dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to resume runtime pm.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
ret = pm_runtime_set_active(dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to active runtime pm.\n");
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_suspend(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int fimd_runtime_suspend(struct device *dev)
|
||||
{
|
||||
@ -917,11 +981,19 @@ static int fimd_runtime_resume(struct device *dev)
|
||||
}
|
||||
|
||||
ctx->suspended = false;
|
||||
|
||||
/* if vblank was enabled status, enable it again. */
|
||||
if (test_and_clear_bit(0, &ctx->irq_flags))
|
||||
fimd_enable_vblank(dev);
|
||||
|
||||
fimd_apply(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops fimd_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
|
||||
SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
|
@ -55,93 +55,96 @@ static unsigned int convert_to_vm_err_msg(int msg)
|
||||
return out_msg;
|
||||
}
|
||||
|
||||
static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
|
||||
static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
|
||||
struct drm_file *file_priv,
|
||||
unsigned int *handle)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static struct exynos_drm_gem_obj
|
||||
*exynos_drm_gem_init(struct drm_device *drm_dev,
|
||||
struct drm_file *file_priv, unsigned int *handle,
|
||||
unsigned int size)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
|
||||
exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
|
||||
if (!exynos_gem_obj) {
|
||||
DRM_ERROR("failed to allocate exynos gem object.\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
obj = &exynos_gem_obj->base;
|
||||
|
||||
ret = drm_gem_object_init(drm_dev, obj, size);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to initialize gem object.\n");
|
||||
ret = -EINVAL;
|
||||
goto err_object_init;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
|
||||
|
||||
ret = drm_gem_create_mmap_offset(obj);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to allocate mmap offset.\n");
|
||||
goto err_create_mmap_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate a id of idr table where the obj is registered
|
||||
* and handle has the id what user can see.
|
||||
*/
|
||||
ret = drm_gem_handle_create(file_priv, obj, handle);
|
||||
if (ret)
|
||||
goto err_handle_create;
|
||||
return ret;
|
||||
|
||||
DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
|
||||
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
|
||||
return exynos_gem_obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_handle_create:
|
||||
drm_gem_free_mmap_offset(obj);
|
||||
void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
err_create_mmap_offset:
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!exynos_gem_obj)
|
||||
return;
|
||||
|
||||
obj = &exynos_gem_obj->base;
|
||||
|
||||
DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count));
|
||||
|
||||
exynos_drm_buf_destroy(obj->dev, exynos_gem_obj->buffer);
|
||||
|
||||
if (obj->map_list.map)
|
||||
drm_gem_free_mmap_offset(obj);
|
||||
|
||||
/* release file pointer to gem object. */
|
||||
drm_gem_object_release(obj);
|
||||
|
||||
err_object_init:
|
||||
kfree(exynos_gem_obj);
|
||||
}
|
||||
|
||||
return ERR_PTR(ret);
|
||||
static struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
|
||||
unsigned long size)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
|
||||
exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
|
||||
if (!exynos_gem_obj) {
|
||||
DRM_ERROR("failed to allocate exynos gem object\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj = &exynos_gem_obj->base;
|
||||
|
||||
ret = drm_gem_object_init(dev, obj, size);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to initialize gem object\n");
|
||||
kfree(exynos_gem_obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
|
||||
|
||||
return exynos_gem_obj;
|
||||
}
|
||||
|
||||
struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
unsigned int *handle, unsigned long size)
|
||||
unsigned long size)
|
||||
{
|
||||
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
|
||||
size = roundup(size, PAGE_SIZE);
|
||||
|
||||
DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
|
||||
|
||||
buffer = exynos_drm_buf_create(dev, size);
|
||||
if (IS_ERR(buffer)) {
|
||||
return ERR_CAST(buffer);
|
||||
}
|
||||
if (!buffer)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
exynos_gem_obj = exynos_drm_gem_init(dev, file_priv, handle, size);
|
||||
if (IS_ERR(exynos_gem_obj)) {
|
||||
exynos_gem_obj = exynos_drm_gem_init(dev, size);
|
||||
if (!exynos_gem_obj) {
|
||||
exynos_drm_buf_destroy(dev, buffer);
|
||||
return exynos_gem_obj;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
exynos_gem_obj->buffer = buffer;
|
||||
@ -150,23 +153,30 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
|
||||
}
|
||||
|
||||
int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_exynos_gem_create *args = data;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
|
||||
&args->handle, args->size);
|
||||
exynos_gem_obj = exynos_drm_gem_create(dev, args->size);
|
||||
if (IS_ERR(exynos_gem_obj))
|
||||
return PTR_ERR(exynos_gem_obj);
|
||||
|
||||
ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
|
||||
&args->handle);
|
||||
if (ret) {
|
||||
exynos_drm_gem_destroy(exynos_gem_obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_exynos_gem_map_off *args = data;
|
||||
|
||||
@ -185,7 +195,7 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
static int exynos_drm_gem_mmap_buffer(struct file *filp,
|
||||
struct vm_area_struct *vma)
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_object *obj = filp->private_data;
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
|
||||
@ -196,6 +206,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);
|
||||
vma->vm_file = filp;
|
||||
|
||||
@ -232,7 +243,7 @@ static const struct file_operations exynos_drm_gem_fops = {
|
||||
};
|
||||
|
||||
int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_exynos_gem_mmap *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
@ -278,32 +289,19 @@ int exynos_drm_gem_init_object(struct drm_gem_object *obj)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj)
|
||||
void exynos_drm_gem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
DRM_DEBUG_KMS("handle count = %d\n",
|
||||
atomic_read(&gem_obj->handle_count));
|
||||
|
||||
if (gem_obj->map_list.map)
|
||||
drm_gem_free_mmap_offset(gem_obj);
|
||||
|
||||
/* release file pointer to gem object. */
|
||||
drm_gem_object_release(gem_obj);
|
||||
|
||||
exynos_gem_obj = to_exynos_gem_obj(gem_obj);
|
||||
|
||||
exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->buffer);
|
||||
|
||||
kfree(exynos_gem_obj);
|
||||
exynos_drm_gem_destroy(to_exynos_gem_obj(obj));
|
||||
}
|
||||
|
||||
int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *dev, struct drm_mode_create_dumb *args)
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
@ -316,19 +314,27 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
|
||||
args->pitch = args->width * args->bpp >> 3;
|
||||
args->size = args->pitch * args->height;
|
||||
|
||||
exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, &args->handle,
|
||||
args->size);
|
||||
exynos_gem_obj = exynos_drm_gem_create(dev, args->size);
|
||||
if (IS_ERR(exynos_gem_obj))
|
||||
return PTR_ERR(exynos_gem_obj);
|
||||
|
||||
ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv,
|
||||
&args->handle);
|
||||
if (ret) {
|
||||
exynos_drm_gem_destroy(exynos_gem_obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
|
||||
struct drm_device *dev, uint32_t handle, uint64_t *offset)
|
||||
struct drm_device *dev, uint32_t handle,
|
||||
uint64_t *offset)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct drm_gem_object *obj;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
@ -343,19 +349,46 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
|
||||
obj = drm_gem_object_lookup(dev, file_priv, handle);
|
||||
if (!obj) {
|
||||
DRM_ERROR("failed to lookup gem object.\n");
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
exynos_gem_obj = to_exynos_gem_obj(obj);
|
||||
|
||||
*offset = get_gem_mmap_offset(&exynos_gem_obj->base);
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
if (!exynos_gem_obj->base.map_list.map) {
|
||||
ret = drm_gem_create_mmap_offset(&exynos_gem_obj->base);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
*offset = (u64)exynos_gem_obj->base.map_list.hash.key << PAGE_SHIFT;
|
||||
DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
|
||||
|
||||
out:
|
||||
drm_gem_object_unreference(obj);
|
||||
unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
|
||||
struct drm_device *dev,
|
||||
unsigned int handle)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* obj->refcount and obj->handle_count are decreased and
|
||||
* if both them are 0 then exynos_drm_gem_free_object()
|
||||
* would be called by callback to release resources.
|
||||
*/
|
||||
ret = drm_gem_handle_delete(file_priv, handle);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to delete drm_gem_handle.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -403,28 +436,6 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
|
||||
struct drm_device *dev, unsigned int handle)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* obj->refcount and obj->handle_count are decreased and
|
||||
* if both them are 0 then exynos_drm_gem_free_object()
|
||||
* would be called by callback to release resources.
|
||||
*/
|
||||
ret = drm_gem_handle_delete(file_priv, handle);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to delete drm_gem_handle.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
|
||||
MODULE_DESCRIPTION("Samsung SoC DRM GEM Module");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -60,14 +60,16 @@ struct exynos_drm_gem_buf {
|
||||
* user can access the buffer through kms_bo.handle.
|
||||
*/
|
||||
struct exynos_drm_gem_obj {
|
||||
struct drm_gem_object base;
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
struct drm_gem_object base;
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
};
|
||||
|
||||
/* create a new buffer and get a new gem handle. */
|
||||
/* destroy a buffer with gem object */
|
||||
void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
|
||||
|
||||
/* create a new buffer with gem object */
|
||||
struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
unsigned int *handle, unsigned long size);
|
||||
unsigned long size);
|
||||
|
||||
/*
|
||||
* request gem object creation and buffer allocation as the size
|
||||
@ -75,15 +77,18 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
|
||||
* height and bpp.
|
||||
*/
|
||||
int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* get buffer offset to map to user space. */
|
||||
int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* unmap a buffer from user space. */
|
||||
int exynos_drm_gem_munmap_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
/*
|
||||
* mmap the physically continuous memory that a gem object contains
|
||||
* to user space.
|
||||
*/
|
||||
int exynos_drm_gem_mmap_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);
|
||||
@ -93,24 +98,13 @@ void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj);
|
||||
|
||||
/* create memory region for drm framebuffer. */
|
||||
int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *dev, struct drm_mode_create_dumb *args);
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args);
|
||||
|
||||
/* map memory region for drm framebuffer to user space. */
|
||||
int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
|
||||
struct drm_device *dev, uint32_t handle, uint64_t *offset);
|
||||
|
||||
/* page fault handler and mmap fault address(virtual) to physical memory. */
|
||||
int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
|
||||
|
||||
/*
|
||||
* mmap the physically continuous memory that a gem object contains
|
||||
* to user space.
|
||||
*/
|
||||
int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* set vm_flags and we can change the vm attribute to other one at here. */
|
||||
int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
struct drm_device *dev, uint32_t handle,
|
||||
uint64_t *offset);
|
||||
|
||||
/*
|
||||
* destroy memory region allocated.
|
||||
@ -118,6 +112,13 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
* would be released by drm_gem_handle_delete().
|
||||
*/
|
||||
int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
|
||||
struct drm_device *dev, unsigned int handle);
|
||||
struct drm_device *dev,
|
||||
unsigned int handle);
|
||||
|
||||
/* page fault handler and mmap fault address(virtual) to physical memory. */
|
||||
int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
|
||||
|
||||
/* set vm_flags and we can change the vm attribute to other one at here. */
|
||||
int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
|
||||
#endif
|
||||
|
439
drivers/gpu/drm/exynos/exynos_drm_hdmi.c
Normal file
439
drivers/gpu/drm/exynos/exynos_drm_hdmi.c
Normal file
@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Samsung Electronics Co.Ltd
|
||||
* Authors:
|
||||
* Inki Dae <inki.dae@samsung.com>
|
||||
* Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/exynos_drm.h>
|
||||
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_drm_hdmi.h"
|
||||
|
||||
#define to_context(dev) platform_get_drvdata(to_platform_device(dev))
|
||||
#define to_subdrv(dev) to_context(dev)
|
||||
#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\
|
||||
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;
|
||||
|
||||
struct drm_hdmi_context {
|
||||
struct exynos_drm_subdrv subdrv;
|
||||
struct exynos_drm_hdmi_context *hdmi_ctx;
|
||||
struct exynos_drm_hdmi_context *mixer_ctx;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops
|
||||
*display_ops)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (display_ops)
|
||||
hdmi_display_ops = display_ops;
|
||||
}
|
||||
EXPORT_SYMBOL(exynos_drm_display_ops_register);
|
||||
|
||||
void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops
|
||||
*manager_ops)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (manager_ops)
|
||||
hdmi_manager_ops = manager_ops;
|
||||
}
|
||||
EXPORT_SYMBOL(exynos_drm_manager_ops_register);
|
||||
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL(exynos_drm_overlay_ops_register);
|
||||
|
||||
static bool drm_hdmi_is_connected(struct device *dev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(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);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int drm_hdmi_get_edid(struct device *dev,
|
||||
struct drm_connector *connector, u8 *edid, int len)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_hdmi_check_timing(struct device *dev, void *timing)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(dev);
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_hdmi_power_on(struct device *dev, int mode)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(dev);
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct exynos_drm_display_ops drm_hdmi_display_ops = {
|
||||
.type = EXYNOS_DISPLAY_TYPE_HDMI,
|
||||
.is_connected = drm_hdmi_is_connected,
|
||||
.get_edid = drm_hdmi_get_edid,
|
||||
.check_timing = drm_hdmi_check_timing,
|
||||
.power_on = drm_hdmi_power_on,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(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);
|
||||
}
|
||||
|
||||
static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void drm_hdmi_commit(struct device *subdrv_dev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (hdmi_manager_ops && hdmi_manager_ops->commit)
|
||||
hdmi_manager_ops->commit(ctx->hdmi_ctx->ctx);
|
||||
}
|
||||
|
||||
static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
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_manager_ops && hdmi_manager_ops->disable)
|
||||
hdmi_manager_ops->disable(ctx->hdmi_ctx->ctx);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unkown dps mode: %d\n", mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
|
||||
.dpms = drm_hdmi_dpms,
|
||||
.enable_vblank = drm_hdmi_enable_vblank,
|
||||
.disable_vblank = drm_hdmi_disable_vblank,
|
||||
.mode_set = drm_hdmi_mode_set,
|
||||
.commit = drm_hdmi_commit,
|
||||
};
|
||||
|
||||
static void drm_mixer_mode_set(struct device *subdrv_dev,
|
||||
struct exynos_drm_overlay *overlay)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(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);
|
||||
}
|
||||
|
||||
static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
|
||||
.mode_set = drm_mixer_mode_set,
|
||||
.commit = drm_mixer_commit,
|
||||
.disable = drm_mixer_disable,
|
||||
};
|
||||
|
||||
|
||||
static int hdmi_subdrv_probe(struct drm_device *drm_dev,
|
||||
struct device *dev)
|
||||
{
|
||||
struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
|
||||
struct drm_hdmi_context *ctx;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct exynos_drm_common_hdmi_pd *pd;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
pd = pdev->dev.platform_data;
|
||||
|
||||
if (!pd) {
|
||||
DRM_DEBUG_KMS("platform data is null.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!pd->hdmi_dev) {
|
||||
DRM_DEBUG_KMS("hdmi device is null.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!pd->mixer_dev) {
|
||||
DRM_DEBUG_KMS("mixer device is null.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&hdmi_driver);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("failed to register hdmi driver.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&mixer_driver);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("failed to register mixer driver.\n");
|
||||
goto err_hdmidrv;
|
||||
}
|
||||
|
||||
ctx = get_ctx_from_subdrv(subdrv);
|
||||
|
||||
ctx->hdmi_ctx = (struct exynos_drm_hdmi_context *)
|
||||
to_context(pd->hdmi_dev);
|
||||
if (!ctx->hdmi_ctx) {
|
||||
DRM_DEBUG_KMS("hdmi context is null.\n");
|
||||
ret = -EFAULT;
|
||||
goto err_mixerdrv;
|
||||
}
|
||||
|
||||
ctx->hdmi_ctx->drm_dev = drm_dev;
|
||||
|
||||
ctx->mixer_ctx = (struct exynos_drm_hdmi_context *)
|
||||
to_context(pd->mixer_dev);
|
||||
if (!ctx->mixer_ctx) {
|
||||
DRM_DEBUG_KMS("mixer context is null.\n");
|
||||
ret = -EFAULT;
|
||||
goto err_mixerdrv;
|
||||
}
|
||||
|
||||
ctx->mixer_ctx->drm_dev = drm_dev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_mixerdrv:
|
||||
platform_driver_unregister(&mixer_driver);
|
||||
err_hdmidrv:
|
||||
platform_driver_unregister(&hdmi_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hdmi_subdrv_remove(struct drm_device *drm_dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
platform_driver_unregister(&hdmi_driver);
|
||||
platform_driver_unregister(&mixer_driver);
|
||||
}
|
||||
|
||||
static void exynos_drm_hdmi_late_probe(struct work_struct *work)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = container_of(work,
|
||||
struct drm_hdmi_context, work);
|
||||
|
||||
/*
|
||||
* this function calls subdrv->probe() so this must be called
|
||||
* after probe context.
|
||||
*
|
||||
* PS. subdrv->probe() will call platform_driver_register() to probe
|
||||
* hdmi and mixer driver.
|
||||
*/
|
||||
exynos_drm_subdrv_register(&ctx->subdrv);
|
||||
}
|
||||
|
||||
static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct exynos_drm_subdrv *subdrv;
|
||||
struct drm_hdmi_context *ctx;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx) {
|
||||
DRM_LOG_KMS("failed to alloc common hdmi context.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
subdrv = &ctx->subdrv;
|
||||
|
||||
subdrv->probe = hdmi_subdrv_probe;
|
||||
subdrv->remove = hdmi_subdrv_remove;
|
||||
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);
|
||||
|
||||
INIT_WORK(&ctx->work, exynos_drm_hdmi_late_probe);
|
||||
|
||||
schedule_work(&ctx->work);
|
||||
|
||||
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);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_drm_subdrv_unregister(&ctx->subdrv);
|
||||
kfree(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver exynos_drm_common_hdmi_driver = {
|
||||
.probe = exynos_drm_hdmi_probe,
|
||||
.remove = __devexit_p(exynos_drm_hdmi_remove),
|
||||
.driver = {
|
||||
.name = "exynos-drm-hdmi",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &hdmi_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init exynos_drm_hdmi_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
ret = platform_driver_register(&exynos_drm_common_hdmi_driver);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("failed to register hdmi common driver.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit exynos_drm_hdmi_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&exynos_drm_common_hdmi_driver);
|
||||
}
|
||||
|
||||
module_init(exynos_drm_hdmi_init);
|
||||
module_exit(exynos_drm_hdmi_exit);
|
||||
|
||||
MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
|
||||
MODULE_AUTHOR("Seung-Woo Kim, <sw0312.kim@samsung.com>");
|
||||
MODULE_DESCRIPTION("Samsung SoC DRM HDMI Driver");
|
||||
MODULE_LICENSE("GPL");
|
73
drivers/gpu/drm/exynos/exynos_drm_hdmi.h
Normal file
73
drivers/gpu/drm/exynos/exynos_drm_hdmi.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* exynos_drm_hdmi.h
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* Authoer: 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_HDMI_H_
|
||||
#define _EXYNOS_DRM_HDMI_H_
|
||||
|
||||
/*
|
||||
* exynos hdmi common context structure.
|
||||
*
|
||||
* @drm_dev: pointer to drm_device.
|
||||
* @ctx: pointer to the context of specific device driver.
|
||||
* this context should be hdmi_context or mixer_context.
|
||||
*/
|
||||
struct exynos_drm_hdmi_context {
|
||||
struct drm_device *drm_dev;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
struct exynos_hdmi_display_ops {
|
||||
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 {
|
||||
void (*mode_set)(void *ctx, void *mode);
|
||||
void (*commit)(void *ctx);
|
||||
void (*disable)(void *ctx);
|
||||
};
|
||||
|
||||
struct exynos_hdmi_overlay_ops {
|
||||
int (*enable_vblank)(void *ctx, int pipe);
|
||||
void (*disable_vblank)(void *ctx);
|
||||
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);
|
||||
|
||||
#endif
|
1176
drivers/gpu/drm/exynos/exynos_hdmi.c
Normal file
1176
drivers/gpu/drm/exynos/exynos_hdmi.c
Normal file
File diff suppressed because it is too large
Load Diff
87
drivers/gpu/drm/exynos/exynos_hdmi.h
Normal file
87
drivers/gpu/drm/exynos/exynos_hdmi.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* Authors:
|
||||
* Inki Dae <inki.dae@samsung.com>
|
||||
* Seung-Woo Kim <sw0312.kim@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_HDMI_H_
|
||||
#define _EXYNOS_HDMI_H_
|
||||
|
||||
struct hdmi_conf {
|
||||
int width;
|
||||
int height;
|
||||
int vrefresh;
|
||||
bool interlace;
|
||||
const u8 *hdmiphy_data;
|
||||
const struct hdmi_preset_conf *conf;
|
||||
};
|
||||
|
||||
struct hdmi_resources {
|
||||
struct clk *hdmi;
|
||||
struct clk *sclk_hdmi;
|
||||
struct clk *sclk_pixel;
|
||||
struct clk *sclk_hdmiphy;
|
||||
struct clk *hdmiphy;
|
||||
struct regulator_bulk_data *regul_bulk;
|
||||
int regul_count;
|
||||
};
|
||||
|
||||
struct hdmi_context {
|
||||
struct device *dev;
|
||||
struct drm_device *drm_dev;
|
||||
struct fb_videomode *default_timing;
|
||||
unsigned int default_win;
|
||||
unsigned int default_bpp;
|
||||
bool hpd_handle;
|
||||
bool enabled;
|
||||
|
||||
struct resource *regs_res;
|
||||
/** base address of HDMI registers */
|
||||
void __iomem *regs;
|
||||
/** HDMI hotplug interrupt */
|
||||
unsigned int irq;
|
||||
/** workqueue for delayed work */
|
||||
struct workqueue_struct *wq;
|
||||
/** hotplug handling work */
|
||||
struct work_struct hotplug_work;
|
||||
|
||||
struct i2c_client *ddc_port;
|
||||
struct i2c_client *hdmiphy_port;
|
||||
|
||||
/** current hdmiphy conf index */
|
||||
int cur_conf;
|
||||
/** other resources */
|
||||
struct hdmi_resources res;
|
||||
|
||||
void *parent_ctx;
|
||||
};
|
||||
|
||||
|
||||
void hdmi_attach_ddc_client(struct i2c_client *ddc);
|
||||
void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy);
|
||||
|
||||
extern struct i2c_driver hdmiphy_driver;
|
||||
extern struct i2c_driver ddc_driver;
|
||||
|
||||
#endif
|
58
drivers/gpu/drm/exynos/exynos_hdmiphy.c
Normal file
58
drivers/gpu/drm/exynos/exynos_hdmiphy.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Samsung Electronics Co.Ltd
|
||||
* Authors:
|
||||
* Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
* Inki Dae <inki.dae@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_hdmi.h"
|
||||
|
||||
|
||||
static int hdmiphy_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
hdmi_attach_hdmiphy_client(client);
|
||||
|
||||
dev_info(&client->adapter->dev, "attached s5p_hdmiphy "
|
||||
"into i2c adapter successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdmiphy_remove(struct i2c_client *client)
|
||||
{
|
||||
dev_info(&client->adapter->dev, "detached s5p_hdmiphy "
|
||||
"from i2c adapter successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id hdmiphy_id[] = {
|
||||
{ "s5p_hdmiphy", 0 },
|
||||
{ },
|
||||
};
|
||||
|
||||
struct i2c_driver hdmiphy_driver = {
|
||||
.driver = {
|
||||
.name = "s5p-hdmiphy",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = hdmiphy_id,
|
||||
.probe = hdmiphy_probe,
|
||||
.remove = __devexit_p(hdmiphy_remove),
|
||||
.command = NULL,
|
||||
};
|
||||
EXPORT_SYMBOL(hdmiphy_driver);
|
1070
drivers/gpu/drm/exynos/exynos_mixer.c
Normal file
1070
drivers/gpu/drm/exynos/exynos_mixer.c
Normal file
File diff suppressed because it is too large
Load Diff
92
drivers/gpu/drm/exynos/exynos_mixer.h
Normal file
92
drivers/gpu/drm/exynos/exynos_mixer.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* Authors:
|
||||
* Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
* 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_MIXER_H_
|
||||
#define _EXYNOS_MIXER_H_
|
||||
|
||||
#define HDMI_OVERLAY_NUMBER 3
|
||||
|
||||
struct hdmi_win_data {
|
||||
dma_addr_t dma_addr;
|
||||
void __iomem *vaddr;
|
||||
dma_addr_t chroma_dma_addr;
|
||||
void __iomem *chroma_vaddr;
|
||||
uint32_t pixel_format;
|
||||
unsigned int bpp;
|
||||
unsigned int crtc_x;
|
||||
unsigned int crtc_y;
|
||||
unsigned int crtc_width;
|
||||
unsigned int crtc_height;
|
||||
unsigned int fb_x;
|
||||
unsigned int fb_y;
|
||||
unsigned int fb_width;
|
||||
unsigned int fb_height;
|
||||
unsigned int mode_width;
|
||||
unsigned int mode_height;
|
||||
unsigned int scan_flags;
|
||||
};
|
||||
|
||||
struct mixer_resources {
|
||||
struct device *dev;
|
||||
/** interrupt index */
|
||||
int irq;
|
||||
/** pointer to Mixer registers */
|
||||
void __iomem *mixer_regs;
|
||||
/** pointer to Video Processor registers */
|
||||
void __iomem *vp_regs;
|
||||
/** spinlock for protection of registers */
|
||||
spinlock_t reg_slock;
|
||||
/** other resources */
|
||||
struct clk *mixer;
|
||||
struct clk *vp;
|
||||
struct clk *sclk_mixer;
|
||||
struct clk *sclk_hdmi;
|
||||
struct clk *sclk_dac;
|
||||
};
|
||||
|
||||
struct mixer_context {
|
||||
unsigned int default_win;
|
||||
struct fb_videomode *default_timing;
|
||||
unsigned int default_bpp;
|
||||
|
||||
/** mixer interrupt */
|
||||
unsigned int irq;
|
||||
/** current crtc pipe for vblank */
|
||||
int pipe;
|
||||
/** interlace scan mode */
|
||||
bool interlace;
|
||||
/** vp enabled status */
|
||||
bool vp_enabled;
|
||||
|
||||
/** mixer and vp resources */
|
||||
struct mixer_resources mixer_res;
|
||||
|
||||
/** overlay window data */
|
||||
struct hdmi_win_data win_data[HDMI_OVERLAY_NUMBER];
|
||||
};
|
||||
|
||||
#endif
|
147
drivers/gpu/drm/exynos/regs-hdmi.h
Normal file
147
drivers/gpu/drm/exynos/regs-hdmi.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
*
|
||||
* Cloned from drivers/media/video/s5p-tv/regs-hdmi.h
|
||||
*
|
||||
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* HDMI register header file for Samsung TVOUT driver
|
||||
*
|
||||
* 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 Foundation.
|
||||
*/
|
||||
|
||||
#ifndef SAMSUNG_REGS_HDMI_H
|
||||
#define SAMSUNG_REGS_HDMI_H
|
||||
|
||||
/*
|
||||
* Register part
|
||||
*/
|
||||
|
||||
#define HDMI_CTRL_BASE(x) ((x) + 0x00000000)
|
||||
#define HDMI_CORE_BASE(x) ((x) + 0x00010000)
|
||||
#define HDMI_TG_BASE(x) ((x) + 0x00050000)
|
||||
|
||||
/* Control registers */
|
||||
#define HDMI_INTC_CON HDMI_CTRL_BASE(0x0000)
|
||||
#define HDMI_INTC_FLAG HDMI_CTRL_BASE(0x0004)
|
||||
#define HDMI_HPD_STATUS HDMI_CTRL_BASE(0x000C)
|
||||
#define HDMI_PHY_RSTOUT HDMI_CTRL_BASE(0x0014)
|
||||
#define HDMI_PHY_VPLL HDMI_CTRL_BASE(0x0018)
|
||||
#define HDMI_PHY_CMU HDMI_CTRL_BASE(0x001C)
|
||||
#define HDMI_CORE_RSTOUT HDMI_CTRL_BASE(0x0020)
|
||||
|
||||
/* Core registers */
|
||||
#define HDMI_CON_0 HDMI_CORE_BASE(0x0000)
|
||||
#define HDMI_CON_1 HDMI_CORE_BASE(0x0004)
|
||||
#define HDMI_CON_2 HDMI_CORE_BASE(0x0008)
|
||||
#define HDMI_SYS_STATUS HDMI_CORE_BASE(0x0010)
|
||||
#define HDMI_PHY_STATUS HDMI_CORE_BASE(0x0014)
|
||||
#define HDMI_STATUS_EN HDMI_CORE_BASE(0x0020)
|
||||
#define HDMI_HPD HDMI_CORE_BASE(0x0030)
|
||||
#define HDMI_MODE_SEL HDMI_CORE_BASE(0x0040)
|
||||
#define HDMI_BLUE_SCREEN_0 HDMI_CORE_BASE(0x0050)
|
||||
#define HDMI_BLUE_SCREEN_1 HDMI_CORE_BASE(0x0054)
|
||||
#define HDMI_BLUE_SCREEN_2 HDMI_CORE_BASE(0x0058)
|
||||
#define HDMI_H_BLANK_0 HDMI_CORE_BASE(0x00A0)
|
||||
#define HDMI_H_BLANK_1 HDMI_CORE_BASE(0x00A4)
|
||||
#define HDMI_V_BLANK_0 HDMI_CORE_BASE(0x00B0)
|
||||
#define HDMI_V_BLANK_1 HDMI_CORE_BASE(0x00B4)
|
||||
#define HDMI_V_BLANK_2 HDMI_CORE_BASE(0x00B8)
|
||||
#define HDMI_H_V_LINE_0 HDMI_CORE_BASE(0x00C0)
|
||||
#define HDMI_H_V_LINE_1 HDMI_CORE_BASE(0x00C4)
|
||||
#define HDMI_H_V_LINE_2 HDMI_CORE_BASE(0x00C8)
|
||||
#define HDMI_VSYNC_POL HDMI_CORE_BASE(0x00E4)
|
||||
#define HDMI_INT_PRO_MODE HDMI_CORE_BASE(0x00E8)
|
||||
#define HDMI_V_BLANK_F_0 HDMI_CORE_BASE(0x0110)
|
||||
#define HDMI_V_BLANK_F_1 HDMI_CORE_BASE(0x0114)
|
||||
#define HDMI_V_BLANK_F_2 HDMI_CORE_BASE(0x0118)
|
||||
#define HDMI_H_SYNC_GEN_0 HDMI_CORE_BASE(0x0120)
|
||||
#define HDMI_H_SYNC_GEN_1 HDMI_CORE_BASE(0x0124)
|
||||
#define HDMI_H_SYNC_GEN_2 HDMI_CORE_BASE(0x0128)
|
||||
#define HDMI_V_SYNC_GEN_1_0 HDMI_CORE_BASE(0x0130)
|
||||
#define HDMI_V_SYNC_GEN_1_1 HDMI_CORE_BASE(0x0134)
|
||||
#define HDMI_V_SYNC_GEN_1_2 HDMI_CORE_BASE(0x0138)
|
||||
#define HDMI_V_SYNC_GEN_2_0 HDMI_CORE_BASE(0x0140)
|
||||
#define HDMI_V_SYNC_GEN_2_1 HDMI_CORE_BASE(0x0144)
|
||||
#define HDMI_V_SYNC_GEN_2_2 HDMI_CORE_BASE(0x0148)
|
||||
#define HDMI_V_SYNC_GEN_3_0 HDMI_CORE_BASE(0x0150)
|
||||
#define HDMI_V_SYNC_GEN_3_1 HDMI_CORE_BASE(0x0154)
|
||||
#define HDMI_V_SYNC_GEN_3_2 HDMI_CORE_BASE(0x0158)
|
||||
#define HDMI_ACR_CON HDMI_CORE_BASE(0x0180)
|
||||
#define HDMI_AVI_CON HDMI_CORE_BASE(0x0300)
|
||||
#define HDMI_AVI_BYTE(n) HDMI_CORE_BASE(0x0320 + 4 * (n))
|
||||
#define HDMI_DC_CONTROL HDMI_CORE_BASE(0x05C0)
|
||||
#define HDMI_VIDEO_PATTERN_GEN HDMI_CORE_BASE(0x05C4)
|
||||
#define HDMI_HPD_GEN HDMI_CORE_BASE(0x05C8)
|
||||
#define HDMI_AUI_CON HDMI_CORE_BASE(0x0360)
|
||||
#define HDMI_SPD_CON HDMI_CORE_BASE(0x0400)
|
||||
|
||||
/* Timing generator registers */
|
||||
#define HDMI_TG_CMD HDMI_TG_BASE(0x0000)
|
||||
#define HDMI_TG_H_FSZ_L HDMI_TG_BASE(0x0018)
|
||||
#define HDMI_TG_H_FSZ_H HDMI_TG_BASE(0x001C)
|
||||
#define HDMI_TG_HACT_ST_L HDMI_TG_BASE(0x0020)
|
||||
#define HDMI_TG_HACT_ST_H HDMI_TG_BASE(0x0024)
|
||||
#define HDMI_TG_HACT_SZ_L HDMI_TG_BASE(0x0028)
|
||||
#define HDMI_TG_HACT_SZ_H HDMI_TG_BASE(0x002C)
|
||||
#define HDMI_TG_V_FSZ_L HDMI_TG_BASE(0x0030)
|
||||
#define HDMI_TG_V_FSZ_H HDMI_TG_BASE(0x0034)
|
||||
#define HDMI_TG_VSYNC_L HDMI_TG_BASE(0x0038)
|
||||
#define HDMI_TG_VSYNC_H HDMI_TG_BASE(0x003C)
|
||||
#define HDMI_TG_VSYNC2_L HDMI_TG_BASE(0x0040)
|
||||
#define HDMI_TG_VSYNC2_H HDMI_TG_BASE(0x0044)
|
||||
#define HDMI_TG_VACT_ST_L HDMI_TG_BASE(0x0048)
|
||||
#define HDMI_TG_VACT_ST_H HDMI_TG_BASE(0x004C)
|
||||
#define HDMI_TG_VACT_SZ_L HDMI_TG_BASE(0x0050)
|
||||
#define HDMI_TG_VACT_SZ_H HDMI_TG_BASE(0x0054)
|
||||
#define HDMI_TG_FIELD_CHG_L HDMI_TG_BASE(0x0058)
|
||||
#define HDMI_TG_FIELD_CHG_H HDMI_TG_BASE(0x005C)
|
||||
#define HDMI_TG_VACT_ST2_L HDMI_TG_BASE(0x0060)
|
||||
#define HDMI_TG_VACT_ST2_H HDMI_TG_BASE(0x0064)
|
||||
#define HDMI_TG_VSYNC_TOP_HDMI_L HDMI_TG_BASE(0x0078)
|
||||
#define HDMI_TG_VSYNC_TOP_HDMI_H HDMI_TG_BASE(0x007C)
|
||||
#define HDMI_TG_VSYNC_BOT_HDMI_L HDMI_TG_BASE(0x0080)
|
||||
#define HDMI_TG_VSYNC_BOT_HDMI_H HDMI_TG_BASE(0x0084)
|
||||
#define HDMI_TG_FIELD_TOP_HDMI_L HDMI_TG_BASE(0x0088)
|
||||
#define HDMI_TG_FIELD_TOP_HDMI_H HDMI_TG_BASE(0x008C)
|
||||
#define HDMI_TG_FIELD_BOT_HDMI_L HDMI_TG_BASE(0x0090)
|
||||
#define HDMI_TG_FIELD_BOT_HDMI_H HDMI_TG_BASE(0x0094)
|
||||
|
||||
/*
|
||||
* Bit definition part
|
||||
*/
|
||||
|
||||
/* HDMI_INTC_CON */
|
||||
#define HDMI_INTC_EN_GLOBAL (1 << 6)
|
||||
#define HDMI_INTC_EN_HPD_PLUG (1 << 3)
|
||||
#define HDMI_INTC_EN_HPD_UNPLUG (1 << 2)
|
||||
|
||||
/* HDMI_INTC_FLAG */
|
||||
#define HDMI_INTC_FLAG_HPD_PLUG (1 << 3)
|
||||
#define HDMI_INTC_FLAG_HPD_UNPLUG (1 << 2)
|
||||
|
||||
/* HDMI_PHY_RSTOUT */
|
||||
#define HDMI_PHY_SW_RSTOUT (1 << 0)
|
||||
|
||||
/* HDMI_CORE_RSTOUT */
|
||||
#define HDMI_CORE_SW_RSTOUT (1 << 0)
|
||||
|
||||
/* HDMI_CON_0 */
|
||||
#define HDMI_BLUE_SCR_EN (1 << 5)
|
||||
#define HDMI_EN (1 << 0)
|
||||
|
||||
/* 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_MODE_MASK (3 << 0)
|
||||
|
||||
/* HDMI_TG_CMD */
|
||||
#define HDMI_TG_EN (1 << 0)
|
||||
#define HDMI_FIELD_EN (1 << 1)
|
||||
|
||||
#endif /* SAMSUNG_REGS_HDMI_H */
|
141
drivers/gpu/drm/exynos/regs-mixer.h
Normal file
141
drivers/gpu/drm/exynos/regs-mixer.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
*
|
||||
* Cloned from drivers/media/video/s5p-tv/regs-mixer.h
|
||||
*
|
||||
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* Mixer register header file for Samsung Mixer driver
|
||||
*
|
||||
* 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 Foundation.
|
||||
*/
|
||||
#ifndef SAMSUNG_REGS_MIXER_H
|
||||
#define SAMSUNG_REGS_MIXER_H
|
||||
|
||||
/*
|
||||
* Register part
|
||||
*/
|
||||
#define MXR_STATUS 0x0000
|
||||
#define MXR_CFG 0x0004
|
||||
#define MXR_INT_EN 0x0008
|
||||
#define MXR_INT_STATUS 0x000C
|
||||
#define MXR_LAYER_CFG 0x0010
|
||||
#define MXR_VIDEO_CFG 0x0014
|
||||
#define MXR_GRAPHIC0_CFG 0x0020
|
||||
#define MXR_GRAPHIC0_BASE 0x0024
|
||||
#define MXR_GRAPHIC0_SPAN 0x0028
|
||||
#define MXR_GRAPHIC0_SXY 0x002C
|
||||
#define MXR_GRAPHIC0_WH 0x0030
|
||||
#define MXR_GRAPHIC0_DXY 0x0034
|
||||
#define MXR_GRAPHIC0_BLANK 0x0038
|
||||
#define MXR_GRAPHIC1_CFG 0x0040
|
||||
#define MXR_GRAPHIC1_BASE 0x0044
|
||||
#define MXR_GRAPHIC1_SPAN 0x0048
|
||||
#define MXR_GRAPHIC1_SXY 0x004C
|
||||
#define MXR_GRAPHIC1_WH 0x0050
|
||||
#define MXR_GRAPHIC1_DXY 0x0054
|
||||
#define MXR_GRAPHIC1_BLANK 0x0058
|
||||
#define MXR_BG_CFG 0x0060
|
||||
#define MXR_BG_COLOR0 0x0064
|
||||
#define MXR_BG_COLOR1 0x0068
|
||||
#define MXR_BG_COLOR2 0x006C
|
||||
#define MXR_CM_COEFF_Y 0x0080
|
||||
#define MXR_CM_COEFF_CB 0x0084
|
||||
#define MXR_CM_COEFF_CR 0x0088
|
||||
#define MXR_GRAPHIC0_BASE_S 0x2024
|
||||
#define MXR_GRAPHIC1_BASE_S 0x2044
|
||||
|
||||
/* for parametrized access to layer registers */
|
||||
#define MXR_GRAPHIC_CFG(i) (0x0020 + (i) * 0x20)
|
||||
#define MXR_GRAPHIC_BASE(i) (0x0024 + (i) * 0x20)
|
||||
#define MXR_GRAPHIC_SPAN(i) (0x0028 + (i) * 0x20)
|
||||
#define MXR_GRAPHIC_SXY(i) (0x002C + (i) * 0x20)
|
||||
#define MXR_GRAPHIC_WH(i) (0x0030 + (i) * 0x20)
|
||||
#define MXR_GRAPHIC_DXY(i) (0x0034 + (i) * 0x20)
|
||||
#define MXR_GRAPHIC_BLANK(i) (0x0038 + (i) * 0x20)
|
||||
#define MXR_GRAPHIC_BASE_S(i) (0x2024 + (i) * 0x20)
|
||||
|
||||
/*
|
||||
* Bit definition part
|
||||
*/
|
||||
|
||||
/* generates mask for range of bits */
|
||||
#define MXR_MASK(high_bit, low_bit) \
|
||||
(((2 << ((high_bit) - (low_bit))) - 1) << (low_bit))
|
||||
|
||||
#define MXR_MASK_VAL(val, high_bit, low_bit) \
|
||||
(((val) << (low_bit)) & MXR_MASK(high_bit, low_bit))
|
||||
|
||||
/* bits for MXR_STATUS */
|
||||
#define MXR_STATUS_16_BURST (1 << 7)
|
||||
#define MXR_STATUS_BURST_MASK (1 << 7)
|
||||
#define MXR_STATUS_BIG_ENDIAN (1 << 3)
|
||||
#define MXR_STATUS_ENDIAN_MASK (1 << 3)
|
||||
#define MXR_STATUS_SYNC_ENABLE (1 << 2)
|
||||
#define MXR_STATUS_REG_RUN (1 << 0)
|
||||
|
||||
/* bits for MXR_CFG */
|
||||
#define MXR_CFG_RGB601_0_255 (0 << 9)
|
||||
#define MXR_CFG_RGB601_16_235 (1 << 9)
|
||||
#define MXR_CFG_RGB709_0_255 (2 << 9)
|
||||
#define MXR_CFG_RGB709_16_235 (3 << 9)
|
||||
#define MXR_CFG_RGB_FMT_MASK 0x600
|
||||
#define MXR_CFG_OUT_YUV444 (0 << 8)
|
||||
#define MXR_CFG_OUT_RGB888 (1 << 8)
|
||||
#define MXR_CFG_OUT_MASK (1 << 8)
|
||||
#define MXR_CFG_DST_SDO (0 << 7)
|
||||
#define MXR_CFG_DST_HDMI (1 << 7)
|
||||
#define MXR_CFG_DST_MASK (1 << 7)
|
||||
#define MXR_CFG_SCAN_HD_720 (0 << 6)
|
||||
#define MXR_CFG_SCAN_HD_1080 (1 << 6)
|
||||
#define MXR_CFG_GRP1_ENABLE (1 << 5)
|
||||
#define MXR_CFG_GRP0_ENABLE (1 << 4)
|
||||
#define MXR_CFG_VP_ENABLE (1 << 3)
|
||||
#define MXR_CFG_SCAN_INTERLACE (0 << 2)
|
||||
#define MXR_CFG_SCAN_PROGRASSIVE (1 << 2)
|
||||
#define MXR_CFG_SCAN_NTSC (0 << 1)
|
||||
#define MXR_CFG_SCAN_PAL (1 << 1)
|
||||
#define MXR_CFG_SCAN_SD (0 << 0)
|
||||
#define MXR_CFG_SCAN_HD (1 << 0)
|
||||
#define MXR_CFG_SCAN_MASK 0x47
|
||||
|
||||
/* bits for MXR_GRAPHICn_CFG */
|
||||
#define MXR_GRP_CFG_COLOR_KEY_DISABLE (1 << 21)
|
||||
#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20)
|
||||
#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17)
|
||||
#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16)
|
||||
#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8)
|
||||
#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0)
|
||||
#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0)
|
||||
|
||||
/* bits for MXR_GRAPHICn_WH */
|
||||
#define MXR_GRP_WH_H_SCALE(x) MXR_MASK_VAL(x, 28, 28)
|
||||
#define MXR_GRP_WH_V_SCALE(x) MXR_MASK_VAL(x, 12, 12)
|
||||
#define MXR_GRP_WH_WIDTH(x) MXR_MASK_VAL(x, 26, 16)
|
||||
#define MXR_GRP_WH_HEIGHT(x) MXR_MASK_VAL(x, 10, 0)
|
||||
|
||||
/* bits for MXR_GRAPHICn_SXY */
|
||||
#define MXR_GRP_SXY_SX(x) MXR_MASK_VAL(x, 26, 16)
|
||||
#define MXR_GRP_SXY_SY(x) MXR_MASK_VAL(x, 10, 0)
|
||||
|
||||
/* bits for MXR_GRAPHICn_DXY */
|
||||
#define MXR_GRP_DXY_DX(x) MXR_MASK_VAL(x, 26, 16)
|
||||
#define MXR_GRP_DXY_DY(x) MXR_MASK_VAL(x, 10, 0)
|
||||
|
||||
/* bits for MXR_INT_EN */
|
||||
#define MXR_INT_EN_VSYNC (1 << 11)
|
||||
#define MXR_INT_EN_ALL (0x0f << 8)
|
||||
|
||||
/* bit for MXR_INT_STATUS */
|
||||
#define MXR_INT_CLEAR_VSYNC (1 << 11)
|
||||
#define MXR_INT_STATUS_VSYNC (1 << 0)
|
||||
|
||||
/* bit for MXR_LAYER_CFG */
|
||||
#define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8)
|
||||
#define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4)
|
||||
#define MXR_LAYER_CFG_VP_VAL(x) MXR_MASK_VAL(x, 3, 0)
|
||||
|
||||
#endif /* SAMSUNG_REGS_MIXER_H */
|
||||
|
91
drivers/gpu/drm/exynos/regs-vp.h
Normal file
91
drivers/gpu/drm/exynos/regs-vp.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
*
|
||||
* Cloned from drivers/media/video/s5p-tv/regs-vp.h
|
||||
*
|
||||
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* Video processor register header file for Samsung Mixer driver
|
||||
*
|
||||
* 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 Foundation.
|
||||
*/
|
||||
|
||||
#ifndef SAMSUNG_REGS_VP_H
|
||||
#define SAMSUNG_REGS_VP_H
|
||||
|
||||
/*
|
||||
* Register part
|
||||
*/
|
||||
|
||||
#define VP_ENABLE 0x0000
|
||||
#define VP_SRESET 0x0004
|
||||
#define VP_SHADOW_UPDATE 0x0008
|
||||
#define VP_FIELD_ID 0x000C
|
||||
#define VP_MODE 0x0010
|
||||
#define VP_IMG_SIZE_Y 0x0014
|
||||
#define VP_IMG_SIZE_C 0x0018
|
||||
#define VP_PER_RATE_CTRL 0x001C
|
||||
#define VP_TOP_Y_PTR 0x0028
|
||||
#define VP_BOT_Y_PTR 0x002C
|
||||
#define VP_TOP_C_PTR 0x0030
|
||||
#define VP_BOT_C_PTR 0x0034
|
||||
#define VP_ENDIAN_MODE 0x03CC
|
||||
#define VP_SRC_H_POSITION 0x0044
|
||||
#define VP_SRC_V_POSITION 0x0048
|
||||
#define VP_SRC_WIDTH 0x004C
|
||||
#define VP_SRC_HEIGHT 0x0050
|
||||
#define VP_DST_H_POSITION 0x0054
|
||||
#define VP_DST_V_POSITION 0x0058
|
||||
#define VP_DST_WIDTH 0x005C
|
||||
#define VP_DST_HEIGHT 0x0060
|
||||
#define VP_H_RATIO 0x0064
|
||||
#define VP_V_RATIO 0x0068
|
||||
#define VP_POLY8_Y0_LL 0x006C
|
||||
#define VP_POLY4_Y0_LL 0x00EC
|
||||
#define VP_POLY4_C0_LL 0x012C
|
||||
|
||||
/*
|
||||
* Bit definition part
|
||||
*/
|
||||
|
||||
/* generates mask for range of bits */
|
||||
|
||||
#define VP_MASK(high_bit, low_bit) \
|
||||
(((2 << ((high_bit) - (low_bit))) - 1) << (low_bit))
|
||||
|
||||
#define VP_MASK_VAL(val, high_bit, low_bit) \
|
||||
(((val) << (low_bit)) & VP_MASK(high_bit, low_bit))
|
||||
|
||||
/* VP_ENABLE */
|
||||
#define VP_ENABLE_ON (1 << 0)
|
||||
|
||||
/* VP_SRESET */
|
||||
#define VP_SRESET_PROCESSING (1 << 0)
|
||||
|
||||
/* VP_SHADOW_UPDATE */
|
||||
#define VP_SHADOW_UPDATE_ENABLE (1 << 0)
|
||||
|
||||
/* VP_MODE */
|
||||
#define VP_MODE_NV12 (0 << 6)
|
||||
#define VP_MODE_NV21 (1 << 6)
|
||||
#define VP_MODE_LINE_SKIP (1 << 5)
|
||||
#define VP_MODE_MEM_LINEAR (0 << 4)
|
||||
#define VP_MODE_MEM_TILED (1 << 4)
|
||||
#define VP_MODE_FMT_MASK (5 << 4)
|
||||
#define VP_MODE_FIELD_ID_AUTO_TOGGLING (1 << 2)
|
||||
#define VP_MODE_2D_IPC (1 << 1)
|
||||
|
||||
/* VP_IMG_SIZE_Y */
|
||||
/* VP_IMG_SIZE_C */
|
||||
#define VP_IMG_HSIZE(x) VP_MASK_VAL(x, 29, 16)
|
||||
#define VP_IMG_VSIZE(x) VP_MASK_VAL(x, 13, 0)
|
||||
|
||||
/* VP_SRC_H_POSITION */
|
||||
#define VP_SRC_H_POSITION_VAL(x) VP_MASK_VAL(x, 14, 4)
|
||||
|
||||
/* VP_ENDIAN_MODE */
|
||||
#define VP_ENDIAN_MODE_LITTLE (1 << 0)
|
||||
|
||||
#endif /* SAMSUNG_REGS_VP_H */
|
@ -107,6 +107,10 @@
|
||||
#define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
|
||||
#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
|
||||
|
||||
/* 2 non contiguous plane YCbCr */
|
||||
#define DRM_FORMAT_NV12M fourcc_code('N', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane */
|
||||
#define DRM_FORMAT_NV12MT fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */
|
||||
|
||||
/*
|
||||
* 3 plane YCbCr
|
||||
* index 0: Y plane, [7:0] Y
|
||||
@ -127,4 +131,7 @@
|
||||
#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
|
||||
#define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
|
||||
|
||||
/* 3 non contiguous plane YCbCr */
|
||||
#define DRM_FORMAT_YUV420M fourcc_code('Y', 'M', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
|
||||
|
||||
#endif /* DRM_FOURCC_H */
|
||||
|
@ -112,4 +112,31 @@ struct exynos_drm_fimd_pdata {
|
||||
unsigned int bpp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Platform Specific Structure for DRM based HDMI.
|
||||
*
|
||||
* @hdmi_dev: device point to specific hdmi driver.
|
||||
* @mixer_dev: device point to specific mixer driver.
|
||||
*
|
||||
* this structure is used for common hdmi driver and each device object
|
||||
* would be used to access specific device driver(hdmi or mixer driver)
|
||||
*/
|
||||
struct exynos_drm_common_hdmi_pd {
|
||||
struct device *hdmi_dev;
|
||||
struct device *mixer_dev;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
struct exynos_drm_hdmi_pdata {
|
||||
struct fb_videomode timing;
|
||||
unsigned int default_win;
|
||||
unsigned int bpp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user