Commit a7d68836 authored by Dave Airlie's avatar Dave Airlie

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

Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next

   This pull request contains just cleanup for atomic pageflip/modeset
   support, and some fixeups.

   We wanted to merge atomic pageflip/modeset feature support, new drivers
   - MIC and DECON for exynos5433 SoC - and relevant patches this time.
   However, I'd found that these features are not only safe enough
   but also aren't tested yet. So for them, I'd like to have enough times
   for the reviews.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: Fix FIMD buffer size calculation
  drm/exynos: Enable DP clock to fix display on Exynos5250 and other
  drm/exynos: fimd: check whether exynos_drm_crtc_create succeed or not
  drm/exynos: dsi: remove the empty mode_valid callback
  drm/exynos: add ratio calculation
  drm/exynos: use src_x and src_y instead of fb_x and fb_y
  drm/exynos: mixer: add 2x scaling to mixer_graph_buffer
  drm/exynos: remove superfluous error messages
  drm/exynos: fix typos in hdmi and mixer
  drm/exynos/ipp: Validate buffer enqueue requests
  drm/exynos: track vblank events on a per crtc basis
  drm/exynos: remove leftover functions declarations
  drm/exynos: remove exynos_plane_destroy()
  drm/exynos: make zpos property immutable
  drm/exynos: preset zpos value for overlay planes
  drm/exynos: remove struct *_win_data abstraction on planes
  drm/exynos: remove unused exynos_crtc->win_enable() callback
  drm/exynos: fimd: fix alpha setting for XR24 pixel format
parents 1d8ac08d 68a29134
This diff is collapsed.
......@@ -32,10 +32,16 @@
#include <drm/bridge/ptn3460.h>
#include "exynos_dp_core.h"
#include "exynos_drm_fimd.h"
#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \
connector)
static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp)
{
return to_exynos_crtc(dp->encoder->crtc);
}
static inline struct exynos_dp_device *
display_to_dp(struct exynos_drm_display *d)
{
......@@ -1070,6 +1076,8 @@ static void exynos_dp_poweron(struct exynos_dp_device *dp)
}
}
fimd_dp_clock_enable(dp_to_crtc(dp), true);
clk_prepare_enable(dp->clock);
exynos_dp_phy_init(dp);
exynos_dp_init_dp(dp);
......@@ -1094,6 +1102,8 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp)
exynos_dp_phy_exit(dp);
clk_disable_unprepare(dp->clock);
fimd_dp_clock_enable(dp_to_crtc(dp), false);
if (dp->panel) {
if (drm_panel_unprepare(dp->panel))
DRM_ERROR("failed to turnoff the panel\n");
......
......@@ -34,9 +34,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
if (mode > DRM_MODE_DPMS_ON) {
/* wait for the completion of page flip. */
if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
!atomic_read(&exynos_crtc->pending_flip),
HZ/20))
atomic_set(&exynos_crtc->pending_flip, 0);
(exynos_crtc->event == NULL), HZ/20))
exynos_crtc->event = NULL;
drm_crtc_vblank_off(crtc);
}
......@@ -164,11 +163,10 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
uint32_t page_flip_flags)
{
struct drm_device *dev = crtc->dev;
struct exynos_drm_private *dev_priv = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct drm_framebuffer *old_fb = crtc->primary->fb;
unsigned int crtc_w, crtc_h;
int ret = -EINVAL;
int ret;
/* when the page flip is requested, crtc's dpms should be on */
if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
......@@ -176,48 +174,49 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
return -EINVAL;
}
mutex_lock(&dev->struct_mutex);
if (!event)
return -EINVAL;
if (event) {
/*
* the pipe from user always is 0 so we can set pipe number
* of current owner to event.
*/
event->pipe = exynos_crtc->pipe;
spin_lock_irq(&dev->event_lock);
if (exynos_crtc->event) {
ret = -EBUSY;
goto out;
}
ret = drm_vblank_get(dev, exynos_crtc->pipe);
if (ret) {
DRM_DEBUG("failed to acquire vblank counter\n");
ret = drm_vblank_get(dev, exynos_crtc->pipe);
if (ret) {
DRM_DEBUG("failed to acquire vblank counter\n");
goto out;
}
goto out;
}
exynos_crtc->event = event;
spin_unlock_irq(&dev->event_lock);
/*
* the pipe from user always is 0 so we can set pipe number
* of current owner to event.
*/
event->pipe = exynos_crtc->pipe;
crtc->primary->fb = fb;
crtc_w = fb->width - crtc->x;
crtc_h = fb->height - crtc->y;
ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
crtc_w, crtc_h, crtc->x, crtc->y,
crtc_w, crtc_h);
if (ret) {
crtc->primary->fb = old_fb;
spin_lock_irq(&dev->event_lock);
list_add_tail(&event->base.link,
&dev_priv->pageflip_event_list);
atomic_set(&exynos_crtc->pending_flip, 1);
exynos_crtc->event = NULL;
drm_vblank_put(dev, exynos_crtc->pipe);
spin_unlock_irq(&dev->event_lock);
crtc->primary->fb = fb;
crtc_w = fb->width - crtc->x;
crtc_h = fb->height - crtc->y;
ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
crtc_w, crtc_h, crtc->x, crtc->y,
crtc_w, crtc_h);
if (ret) {
crtc->primary->fb = old_fb;
spin_lock_irq(&dev->event_lock);
drm_vblank_put(dev, exynos_crtc->pipe);
list_del(&event->base.link);
atomic_set(&exynos_crtc->pending_flip, 0);
spin_unlock_irq(&dev->event_lock);
goto out;
}
return ret;
}
return 0;
out:
mutex_unlock(&dev->struct_mutex);
spin_unlock_irq(&dev->event_lock);
return ret;
}
......@@ -239,13 +238,13 @@ static struct drm_crtc_funcs exynos_crtc_funcs = {
};
struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
struct drm_plane *plane,
int pipe,
enum exynos_drm_output_type type,
struct exynos_drm_crtc_ops *ops,
void *ctx)
{
struct exynos_drm_crtc *exynos_crtc;
struct drm_plane *plane;
struct exynos_drm_private *private = drm_dev->dev_private;
struct drm_crtc *crtc;
int ret;
......@@ -255,19 +254,12 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
return ERR_PTR(-ENOMEM);
init_waitqueue_head(&exynos_crtc->pending_flip_queue);
atomic_set(&exynos_crtc->pending_flip, 0);
exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
exynos_crtc->pipe = pipe;
exynos_crtc->type = type;
exynos_crtc->ops = ops;
exynos_crtc->ctx = ctx;
plane = exynos_plane_init(drm_dev, 1 << pipe,
DRM_PLANE_TYPE_PRIMARY);
if (IS_ERR(plane)) {
ret = PTR_ERR(plane);
goto err_plane;
}
crtc = &exynos_crtc->base;
......@@ -284,7 +276,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
err_crtc:
plane->funcs->destroy(plane);
err_plane:
kfree(exynos_crtc);
return ERR_PTR(ret);
}
......@@ -320,26 +311,20 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
{
struct exynos_drm_private *dev_priv = dev->dev_private;
struct drm_pending_vblank_event *e, *t;
struct drm_crtc *drm_crtc = dev_priv->crtc[pipe];
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
if (exynos_crtc->event) {
list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
base.link) {
/* if event's pipe isn't same as crtc then ignore it. */
if (pipe != e->pipe)
continue;
list_del(&e->base.link);
drm_send_vblank_event(dev, -1, e);
drm_send_vblank_event(dev, -1, exynos_crtc->event);
drm_vblank_put(dev, pipe);
atomic_set(&exynos_crtc->pending_flip, 0);
wake_up(&exynos_crtc->pending_flip_queue);
}
exynos_crtc->event = NULL;
spin_unlock_irqrestore(&dev->event_lock, flags);
}
......
......@@ -18,6 +18,7 @@
#include "exynos_drm_drv.h"
struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
struct drm_plane *plane,
int pipe,
enum exynos_drm_output_type type,
struct exynos_drm_crtc_ops *ops,
......@@ -27,12 +28,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe);
void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
struct exynos_drm_plane *plane);
void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
/* This function gets pipe value to crtc device matched with out_type. */
int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
unsigned int out_type);
......
......@@ -55,13 +55,11 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
{
struct exynos_drm_private *private;
int ret;
int nr;
private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
if (!private)
return -ENOMEM;
INIT_LIST_HEAD(&private->pageflip_event_list);
dev_set_drvdata(dev->dev, dev);
dev->dev_private = (void *)private;
......@@ -81,19 +79,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
exynos_drm_mode_config_init(dev);
for (nr = 0; nr < MAX_PLANE; nr++) {
struct drm_plane *plane;
unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
plane = exynos_plane_init(dev, possible_crtcs,
DRM_PLANE_TYPE_OVERLAY);
if (!IS_ERR(plane))
continue;
ret = PTR_ERR(plane);
goto err_mode_config_cleanup;
}
/* setup possible_clones. */
exynos_drm_encoder_setup(dev);
......@@ -237,25 +222,13 @@ static void exynos_drm_preclose(struct drm_device *dev,
static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
{
struct exynos_drm_private *private = dev->dev_private;
struct drm_pending_vblank_event *v, *vt;
struct drm_pending_event *e, *et;
unsigned long flags;
if (!file->driver_priv)
return;
/* Release all events not unhandled by page flip handler. */
spin_lock_irqsave(&dev->event_lock, flags);
list_for_each_entry_safe(v, vt, &private->pageflip_event_list,
base.link) {
if (v->base.file_priv == file) {
list_del(&v->base.link);
drm_vblank_put(dev, v->pipe);
v->base.destroy(&v->base);
}
}
/* Release all events handled by page flip handler but not freed. */
list_for_each_entry_safe(e, et, &file->event_list, link) {
list_del(&e->link);
......
......@@ -21,7 +21,6 @@
#define MAX_CRTC 3
#define MAX_PLANE 5
#define MAX_FB_BUFFER 4
#define DEFAULT_ZPOS -1
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base)
#define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base)
......@@ -48,20 +47,22 @@ enum exynos_drm_output_type {
* Exynos drm common overlay structure.
*
* @base: plane object
* @fb_x: offset x on a framebuffer to be displayed.
* @src_x: offset x on a framebuffer to be displayed.
* - the unit is screen coordinates.
* @fb_y: offset y on a framebuffer to be displayed.
* @src_y: offset y on a framebuffer to be displayed.
* - 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.
* @fb_width: width of a framebuffer.
* @fb_height: height of a framebuffer.
* @crtc_x: offset x on hardware screen.
* @crtc_y: offset y on hardware screen.
* @crtc_width: window width to be displayed (hardware screen).
* @crtc_height: window height to be displayed (hardware screen).
* @mode_width: width of screen mode.
* @mode_height: height of screen mode.
* @h_ratio: horizontal scaling ratio, 16.16 fixed point
* @v_ratio: vertical scaling ratio, 16.16 fixed point
* @refresh: refresh rate.
* @scan_flag: interlace or progressive way.
* (it could be DRM_MODE_FLAG_*)
......@@ -78,6 +79,7 @@ enum exynos_drm_output_type {
* @transparency: transparency on or off.
* @activated: activated or not.
* @enabled: enabled or not.
* @resume: to resume or not.
*
* this structure is common to exynos SoC and its contents would be copied
* to hardware specific overlay info.
......@@ -85,25 +87,27 @@ enum exynos_drm_output_type {
struct exynos_drm_plane {
struct drm_plane base;
unsigned int fb_x;
unsigned int fb_y;
unsigned int fb_width;
unsigned int fb_height;
unsigned int src_x;
unsigned int src_y;
unsigned int src_width;
unsigned int src_height;
unsigned int fb_width;
unsigned int fb_height;
unsigned int crtc_x;
unsigned int crtc_y;
unsigned int crtc_width;
unsigned int crtc_height;
unsigned int mode_width;
unsigned int mode_height;
unsigned int h_ratio;
unsigned int v_ratio;
unsigned int refresh;
unsigned int scan_flag;
unsigned int bpp;
unsigned int pitch;
uint32_t pixel_format;
dma_addr_t dma_addr[MAX_FB_BUFFER];
int zpos;
unsigned int zpos;
unsigned int index_color;
bool default_win:1;
......@@ -112,6 +116,7 @@ struct exynos_drm_plane {
bool transparency:1;
bool activated:1;
bool enabled:1;
bool resume:1;
};
/*
......@@ -172,9 +177,7 @@ struct exynos_drm_display {
* @disable_vblank: specific driver callback for disabling vblank interrupt.
* @wait_for_vblank: wait for vblank interrupt to make sure that
* hardware overlay is updated.
* @win_mode_set: copy drm overlay info to hw specific overlay info.
* @win_commit: apply hardware specific overlay data to registers.
* @win_enable: enable hardware specific overlay.
* @win_disable: disable hardware specific overlay.
* @te_handler: trigger to transfer video image at the tearing effect
* synchronization signal if there is a page flip request.
......@@ -189,11 +192,8 @@ struct exynos_drm_crtc_ops {
int (*enable_vblank)(struct exynos_drm_crtc *crtc);
void (*disable_vblank)(struct exynos_drm_crtc *crtc);
void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
void (*win_mode_set)(struct exynos_drm_crtc *crtc,
struct exynos_drm_plane *plane);
void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
void (*win_commit)(struct exynos_drm_crtc *crtc, unsigned int zpos);
void (*win_disable)(struct exynos_drm_crtc *crtc, unsigned int zpos);
void (*te_handler)(struct exynos_drm_crtc *crtc);
};
......@@ -210,6 +210,7 @@ struct exynos_drm_crtc_ops {
* we can refer to the crtc to current hardware interrupt occurred through
* this pipe value.
* @dpms: store the crtc dpms value
* @event: vblank event that is currently queued for flip
* @ops: pointer to callbacks for exynos drm specific functionality
* @ctx: A pointer to the crtc's implementation specific context
*/
......@@ -219,7 +220,7 @@ struct exynos_drm_crtc {
unsigned int pipe;
unsigned int dpms;
wait_queue_head_t pending_flip_queue;
atomic_t pending_flip;
struct drm_pending_vblank_event *event;
struct exynos_drm_crtc_ops *ops;
void *ctx;
};
......@@ -249,9 +250,6 @@ struct drm_exynos_file_private {
struct exynos_drm_private {
struct drm_fb_helper *fb_helper;
/* list head for new event to be added. */
struct list_head pageflip_event_list;
/*
* created crtc object would be contained at this array and
* this array is used to be aware of which crtc did it request vblank.
......
......@@ -1473,12 +1473,6 @@ static int exynos_dsi_get_modes(struct drm_connector *connector)
return 0;
}
static int exynos_dsi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
return MODE_OK;
}
static struct drm_encoder *
exynos_dsi_best_encoder(struct drm_connector *connector)
{
......@@ -1489,7 +1483,6 @@ exynos_dsi_best_encoder(struct drm_connector *connector)
static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = {
.get_modes = exynos_dsi_get_modes,
.mode_valid = exynos_dsi_mode_valid,
.best_encoder = exynos_dsi_best_encoder,
};
......
......@@ -151,10 +151,8 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
exynos_gem_obj = to_exynos_gem_obj(obj);
ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
if (ret < 0) {
DRM_ERROR("cannot use this gem memory type for fb.\n");
return ERR_PTR(-EINVAL);
}
if (ret < 0)
return ERR_PTR(ret);
exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb)
......@@ -250,10 +248,8 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
exynos_fb->exynos_gem_obj[i] = exynos_gem_obj;
ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
if (ret < 0) {
DRM_ERROR("cannot use this gem memory type for fb.\n");
if (ret < 0)
goto err_unreference;
}
}
ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
......
This diff is collapsed.
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
#ifndef _EXYNOS_DRM_FIMD_H_
#define _EXYNOS_DRM_FIMD_H_
extern void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable);
#endif /* _EXYNOS_DRM_FIMD_H_ */
......@@ -476,6 +476,45 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
return ret;
}
static int ipp_validate_mem_node(struct drm_device *drm_dev,
struct drm_exynos_ipp_mem_node *m_node,
struct drm_exynos_ipp_cmd_node *c_node)
{
struct drm_exynos_ipp_config *ipp_cfg;
unsigned int num_plane;
unsigned long min_size, size;
unsigned int bpp;
int i;
/* The property id should already be varified */
ipp_cfg = &c_node->property.config[m_node->prop_id];
num_plane = drm_format_num_planes(ipp_cfg->fmt);
/**
* This is a rather simplified validation of a memory node.
* It basically verifies provided gem object handles
* and the buffer sizes with respect to current configuration.
* This is not the best that can be done
* but it seems more than enough
*/
for (i = 0; i < num_plane; ++i) {
if (!m_node->buf_info.handles[i]) {
DRM_ERROR("invalid handle for plane %d\n", i);
return -EINVAL;
}
bpp = drm_format_plane_cpp(ipp_cfg->fmt, i);
min_size = (ipp_cfg->sz.hsize * ipp_cfg->sz.vsize * bpp) >> 3;
size = exynos_drm_gem_get_size(drm_dev,
m_node->buf_info.handles[i],
c_node->filp);
if (min_size > size) {
DRM_ERROR("invalid size for plane %d\n", i);
return -EINVAL;
}
}
return 0;
}
static int ipp_put_mem_node(struct drm_device *drm_dev,
struct drm_exynos_ipp_cmd_node *c_node,
struct drm_exynos_ipp_mem_node *m_node)
......@@ -552,6 +591,11 @@ static struct drm_exynos_ipp_mem_node
}
mutex_lock(&c_node->mem_lock);
if (ipp_validate_mem_node(drm_dev, m_node, c_node)) {
ipp_put_mem_node(drm_dev, c_node, m_node);
mutex_unlock(&c_node->mem_lock);
return ERR_PTR(-EFAULT);
}
list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]);
mutex_unlock(&c_node->mem_lock);
......
......@@ -92,7 +92,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
uint32_t src_w, uint32_t src_h)
{
struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
unsigned int actual_w;
unsigned int actual_h;
......@@ -111,13 +110,17 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
crtc_y = 0;
}
/* set ratio */
exynos_plane->h_ratio = (src_w << 16) / crtc_w;
exynos_plane->v_ratio = (src_h << 16) / crtc_h;
/* set drm framebuffer data. */
exynos_plane->fb_x = src_x;
exynos_plane->fb_y = src_y;
exynos_plane->src_x = src_x;
exynos_plane->src_y = src_y;
exynos_plane->src_width = (actual_w * exynos_plane->h_ratio) >> 16;
exynos_plane->src_height = (actual_h * exynos_plane->v_ratio) >> 16;
exynos_plane->fb_width = fb->width;
exynos_plane->fb_height = fb->height;
exynos_plane->src_width = src_w;
exynos_plane->src_height = src_h;
exynos_plane->bpp = fb->bits_per_pixel;
exynos_plane->pitch = fb->pitches[0];
exynos_plane->pixel_format = fb->pixel_format;
......@@ -139,9 +142,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
exynos_plane->crtc_width, exynos_plane->crtc_height);
plane->crtc = crtc;
if (exynos_crtc->ops->win_mode_set)
exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
}
int
......@@ -182,39 +182,14 @@ static int exynos_disable_plane(struct drm_plane *plane)
return 0;
}
static void exynos_plane_destroy(struct drm_plane *plane)
{
struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
exynos_disable_plane(plane);
drm_plane_cleanup(plane);
kfree(exynos_plane);
}
static int exynos_plane_set_property(struct drm_plane *plane,
struct drm_property *property,
uint64_t val)
{
struct drm_device *dev = plane->dev;
struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
struct exynos_drm_private *dev_priv = dev->dev_private;
if (property == dev_priv->plane_zpos_property) {
exynos_plane->zpos = val;
return 0;
}
return -EINVAL;
}
static struct drm_plane_funcs exynos_plane_funcs = {
.update_plane = exynos_update_plane,
.disable_plane = exynos_disable_plane,
.destroy = exynos_plane_destroy,
.set_property = exynos_plane_set_property,
.destroy = drm_plane_cleanup,
};
static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
unsigned int zpos)
{
struct drm_device *dev = plane->dev;
struct exynos_drm_private *dev_priv = dev->dev_private;
......@@ -222,41 +197,36 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
prop = dev_priv->plane_zpos_property;
if (!prop) {
prop = drm_property_create_range(dev, 0, "zpos", 0,
MAX_PLANE - 1);
prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE,
"zpos", 0, MAX_PLANE - 1);
if (!prop)
return;
dev_priv->plane_zpos_property = prop;
}
drm_object_attach_property(&plane->base, prop, 0);
drm_object_attach_property(&plane->base, prop, zpos);
}
struct drm_plane *exynos_plane_init(struct drm_device *dev,
unsigned long possible_crtcs,
enum drm_plane_type type)
int exynos_plane_init(struct drm_device *dev,
struct exynos_drm_plane *exynos_plane,
unsigned long possible_crtcs, enum drm_plane_type type,
unsigned int zpos)
{
struct exynos_drm_plane *exynos_plane;
int err;
exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
if (!exynos_plane)
return ERR_PTR(-ENOMEM);
err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
&exynos_plane_funcs, formats,
ARRAY_SIZE(formats), type);
if (err) {
DRM_ERROR("failed to initialize plane\n");
kfree(exynos_plane);
return ERR_PTR(err);
return err;
}
if (type == DRM_PLANE_TYPE_PRIMARY)
exynos_plane->zpos = DEFAULT_ZPOS;
else
exynos_plane_attach_zpos_property(&exynos_plane->base);
exynos_plane->zpos = zpos;
return &exynos_plane->base;
if (type == DRM_PLANE_TYPE_OVERLAY)
exynos_plane_attach_zpos_property(&exynos_plane->base, zpos);
return 0;
}
......@@ -20,6 +20,7 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
struct drm_plane *exynos_plane_init(struct drm_device *dev,
unsigned long possible_crtcs,
enum drm_plane_type type);
int exynos_plane_init(struct drm_device *dev,
struct exynos_drm_plane *exynos_plane,
unsigned long possible_crtcs, enum drm_plane_type type,
unsigned int zpos);
......@@ -23,6 +23,7 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_vidi.h"
......@@ -32,20 +33,6 @@
#define ctx_from_connector(c) container_of(c, struct vidi_context, \
connector)
struct vidi_win_data {
unsigned int offset_x;
unsigned int offset_y;
unsigned int ovl_width;
unsigned int ovl_height;
unsigned int fb_width;
unsigned int fb_height;
unsigned int bpp;
dma_addr_t dma_addr;
unsigned int buf_offsize;
unsigned int line_size; /* bytes */
bool enabled;
};
struct vidi_context {
struct exynos_drm_display display;
struct platform_device *pdev;
......@@ -53,7 +40,7 @@ struct vidi_context {
struct exynos_drm_crtc *crtc;
struct drm_encoder *encoder;
struct drm_connector connector;
struct vidi_win_data win_data[WINDOWS_NR];
struct exynos_drm_plane planes[WINDOWS_NR];
struct edid *raw_edid;
unsigned int clkdiv;
unsigned int default_win;
......@@ -97,19 +84,6 @@ static const char fake_edid_info[] = {
0x00, 0x00, 0x00, 0x06
};
static void vidi_apply(struct vidi_context *ctx)
{
struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops;
struct vidi_win_data *win_data;
int i;
for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i];
if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
crtc_ops->win_commit(ctx->crtc, i);
}
}
static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
{
struct vidi_context *ctx = crtc->ctx;
......@@ -143,104 +117,46 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
ctx->vblank_on = false;
}
static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
struct exynos_drm_plane *plane)
{
struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data;
int win;
unsigned long offset;
if (!plane) {
DRM_ERROR("plane is NULL\n");
return;
}
win = plane->zpos;
if (win == DEFAULT_ZPOS)
win = ctx->default_win;
if (win < 0 || win >= WINDOWS_NR)
return;
offset = plane->fb_x * (plane->bpp >> 3);
offset += plane->fb_y * plane->pitch;
DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
win_data = &ctx->win_data[win];
win_data->offset_x = plane->crtc_x;
win_data->offset_y = plane->crtc_y;
win_data->ovl_width = plane->crtc_width;
win_data->ovl_height = plane->crtc_height;
win_data->fb_width = plane->fb_width;
win_data->fb_height = plane->fb_height;
win_data->dma_addr = plane->dma_addr[0] + offset;
win_data->bpp = plane->bpp;
win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
(plane->bpp >> 3);
win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
/*
* some parts of win_data should be transferred to user side
* through specific ioctl.
*/
DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
win_data->offset_x, win_data->offset_y);
DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
win_data->ovl_width, win_data->ovl_height);
DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
plane->fb_width, plane->crtc_width);
}
static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
static void vidi_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
{
struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data;
int win = zpos;
struct exynos_drm_plane *plane;
if (ctx->suspended)
return;
if (win == DEFAULT_ZPOS)
win = ctx->default_win;
if (win < 0 || win >= WINDOWS_NR)
return;
win_data = &ctx->win_data[win];
plane = &ctx->planes[win];
win_data->enabled = true;
plane->enabled = true;
DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
if (ctx->vblank_on)
schedule_work(&ctx->work);
}
static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
static void vidi_win_disable(struct exynos_drm_crtc *crtc, unsigned int win)
{
struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data;
int win = zpos;
if (win == DEFAULT_ZPOS)
win = ctx->default_win;
struct exynos_drm_plane *plane;
if (win < 0 || win >= WINDOWS_NR)
return;
win_data = &ctx->win_data[win];
win_data->enabled = false;
plane = &ctx->planes[win];
plane->enabled = false;
/* TODO. */
}
static int vidi_power_on(struct vidi_context *ctx, bool enable)
{
struct exynos_drm_plane *plane;
int i;
DRM_DEBUG_KMS("%s\n", __FILE__);
if (enable != false && enable != true)
......@@ -253,7 +169,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
if (test_and_clear_bit(0, &ctx->irq_flags))
vidi_enable_vblank(ctx->crtc);
vidi_apply(ctx);
for (i = 0; i < WINDOWS_NR; i++) {
plane = &ctx->planes[i];
if (plane->enabled)
vidi_win_commit(ctx->crtc, i);
}
} else {
ctx->suspended = true;
}
......@@ -301,7 +221,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = {
.dpms = vidi_dpms,
.enable_vblank = vidi_enable_vblank,
.disable_vblank = vidi_disable_vblank,
.win_mode_set = vidi_win_mode_set,
.win_commit = vidi_win_commit,
.win_disable = vidi_win_disable,
};
......@@ -543,12 +462,25 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
{
struct vidi_context *ctx = dev_get_drvdata(dev);
struct drm_device *drm_dev = data;
struct exynos_drm_plane *exynos_plane;
enum drm_plane_type type;
unsigned int zpos;
int ret;
vidi_ctx_initialize(ctx, drm_dev);
ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
EXYNOS_DISPLAY_TYPE_VIDI,
for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
DRM_PLANE_TYPE_OVERLAY;
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type, zpos);
if (ret)
return ret;
}
exynos_plane = &ctx->planes[ctx->default_win];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
&vidi_crtc_ops, ctx);
if (IS_ERR(ctx->crtc)) {
DRM_ERROR("failed to create crtc.\n");
......
......@@ -2007,7 +2007,7 @@ static void hdmi_mode_set(struct exynos_drm_display *display,
DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
m->hdisplay, m->vdisplay,
m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
"INTERLACED" : "PROGERESSIVE");
"INTERLACED" : "PROGRESSIVE");
/* preserve mode information for later use. */
drm_mode_copy(&hdata->current_mode, mode);
......
This diff is collapsed.
......@@ -101,7 +101,7 @@
#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_PROGRESSIVE (1 << 2)
#define MXR_CFG_SCAN_NTSC (0 << 1)
#define MXR_CFG_SCAN_PAL (1 << 1)
#define MXR_CFG_SCAN_SD (0 << 0)
......
......@@ -289,6 +289,11 @@
#define VIDISD14C_ALPHA1_B_LIMIT 0xf
#define VIDISD14C_ALPHA1_B(_x) ((_x) << 0)
#define VIDW_ALPHA 0x021c
#define VIDW_ALPHA_R(_x) ((_x) << 16)
#define VIDW_ALPHA_G(_x) ((_x) << 8)
#define VIDW_ALPHA_B(_x) ((_x) << 0)
/* Video buffer addresses */
#define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8))
#define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8))
......@@ -436,6 +441,12 @@
#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0)
#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
/* Display port clock control */
#define DP_MIE_CLKCON 0x27c
#define DP_MIE_CLK_DISABLE 0x0
#define DP_MIE_CLK_DP_ENABLE 0x2
#define DP_MIE_CLK_MIE_ENABLE 0x3
/* Notes on per-window bpp settings
*
* Value Win0 Win1 Win2 Win3 Win 4
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment