Commit 2b8376c8 authored by Gustavo Padovan's avatar Gustavo Padovan Committed by Inki Dae

drm/exynos: remove struct exynos_drm_encoder layer

struct exynos_drm_encoder was justing wrapping struct drm_encoder, it had
only a drm_encoder member and the internal exynos_drm_encoders ops that
was directly mapped to the drm_encoder helper funcs.

So now exynos DRM uses struct drm_encoder directly, this removes
completely the struct exynos_drm_encoder.

v2: add empty .mode_fixup() and .mode_set() to DSI and DPI to avoid null
pointer.
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent 6cf27275
...@@ -3,10 +3,9 @@ ...@@ -3,10 +3,9 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos
exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \ exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fbdev.o \
exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ exynos_drm_fb.o exynos_drm_buf.o exynos_drm_gem.o \
exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ exynos_drm_core.o exynos_drm_plane.o exynos_drm_dmabuf.o
exynos_drm_plane.o exynos_drm_dmabuf.o
exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
......
...@@ -61,7 +61,7 @@ struct decon_context { ...@@ -61,7 +61,7 @@ struct decon_context {
atomic_t wait_vsync_event; atomic_t wait_vsync_event;
struct exynos_drm_panel_info panel; struct exynos_drm_panel_info panel;
struct exynos_drm_encoder *encoder; struct drm_encoder *encoder;
}; };
static const struct of_device_id decon_driver_dt_match[] = { static const struct of_device_id decon_driver_dt_match[] = {
......
...@@ -32,18 +32,18 @@ ...@@ -32,18 +32,18 @@
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include "exynos_dp_core.h" #include "exynos_dp_core.h"
#include "exynos_drm_encoder.h" #include "exynos_drm_crtc.h"
#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ #define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \
connector) connector)
static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp) static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp)
{ {
return to_exynos_crtc(dp->encoder.base.crtc); return to_exynos_crtc(dp->encoder.crtc);
} }
static inline struct exynos_dp_device *encoder_to_dp( static inline struct exynos_dp_device *encoder_to_dp(
struct exynos_drm_encoder *e) struct drm_encoder *e)
{ {
return container_of(e, struct exynos_dp_device, encoder); return container_of(e, struct exynos_dp_device, encoder);
} }
...@@ -889,7 +889,7 @@ static void exynos_dp_hotplug(struct work_struct *work) ...@@ -889,7 +889,7 @@ static void exynos_dp_hotplug(struct work_struct *work)
drm_helper_hpd_irq_event(dp->drm_dev); drm_helper_hpd_irq_event(dp->drm_dev);
} }
static void exynos_dp_commit(struct exynos_drm_encoder *encoder) static void exynos_dp_commit(struct drm_encoder *encoder)
{ {
struct exynos_dp_device *dp = encoder_to_dp(encoder); struct exynos_dp_device *dp = encoder_to_dp(encoder);
int ret; int ret;
...@@ -995,7 +995,7 @@ static struct drm_encoder *exynos_dp_best_encoder( ...@@ -995,7 +995,7 @@ static struct drm_encoder *exynos_dp_best_encoder(
{ {
struct exynos_dp_device *dp = ctx_from_connector(connector); struct exynos_dp_device *dp = ctx_from_connector(connector);
return &dp->encoder.base; return &dp->encoder;
} }
static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = { static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
...@@ -1020,10 +1020,9 @@ static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, ...@@ -1020,10 +1020,9 @@ static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp,
return 0; return 0;
} }
static int exynos_dp_create_connector(struct exynos_drm_encoder *exynos_encoder) static int exynos_dp_create_connector(struct drm_encoder *encoder)
{ {
struct exynos_dp_device *dp = encoder_to_dp(exynos_encoder); struct exynos_dp_device *dp = encoder_to_dp(encoder);
struct drm_encoder *encoder = &exynos_encoder->base;
struct drm_connector *connector = &dp->connector; struct drm_connector *connector = &dp->connector;
int ret; int ret;
...@@ -1053,7 +1052,20 @@ static int exynos_dp_create_connector(struct exynos_drm_encoder *exynos_encoder) ...@@ -1053,7 +1052,20 @@ static int exynos_dp_create_connector(struct exynos_drm_encoder *exynos_encoder)
return ret; return ret;
} }
static void exynos_dp_enable(struct exynos_drm_encoder *encoder) static bool exynos_dp_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void exynos_dp_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
}
static void exynos_dp_enable(struct drm_encoder *encoder)
{ {
struct exynos_dp_device *dp = encoder_to_dp(encoder); struct exynos_dp_device *dp = encoder_to_dp(encoder);
struct exynos_drm_crtc *crtc = dp_to_crtc(dp); struct exynos_drm_crtc *crtc = dp_to_crtc(dp);
...@@ -1080,7 +1092,7 @@ static void exynos_dp_enable(struct exynos_drm_encoder *encoder) ...@@ -1080,7 +1092,7 @@ static void exynos_dp_enable(struct exynos_drm_encoder *encoder)
dp->dpms_mode = DRM_MODE_DPMS_ON; dp->dpms_mode = DRM_MODE_DPMS_ON;
} }
static void exynos_dp_disable(struct exynos_drm_encoder *encoder) static void exynos_dp_disable(struct drm_encoder *encoder)
{ {
struct exynos_dp_device *dp = encoder_to_dp(encoder); struct exynos_dp_device *dp = encoder_to_dp(encoder);
struct exynos_drm_crtc *crtc = dp_to_crtc(dp); struct exynos_drm_crtc *crtc = dp_to_crtc(dp);
...@@ -1111,11 +1123,17 @@ static void exynos_dp_disable(struct exynos_drm_encoder *encoder) ...@@ -1111,11 +1123,17 @@ static void exynos_dp_disable(struct exynos_drm_encoder *encoder)
dp->dpms_mode = DRM_MODE_DPMS_OFF; dp->dpms_mode = DRM_MODE_DPMS_OFF;
} }
static struct exynos_drm_encoder_ops exynos_dp_encoder_ops = { static struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = {
.mode_fixup = exynos_dp_mode_fixup,
.mode_set = exynos_dp_mode_set,
.enable = exynos_dp_enable, .enable = exynos_dp_enable,
.disable = exynos_dp_disable, .disable = exynos_dp_disable,
}; };
static struct drm_encoder_funcs exynos_dp_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
{ {
struct device_node *dp_node = dev->of_node; struct device_node *dp_node = dev->of_node;
...@@ -1192,10 +1210,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) ...@@ -1192,10 +1210,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
struct exynos_dp_device *dp = dev_get_drvdata(dev); struct exynos_dp_device *dp = dev_get_drvdata(dev);
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
struct exynos_drm_encoder *exynos_encoder = &dp->encoder; struct drm_encoder *encoder = &dp->encoder;
struct resource *res; struct resource *res;
unsigned int irq_flags; unsigned int irq_flags;
int ret = 0; int pipe, ret = 0;
dp->dev = &pdev->dev; dp->dev = &pdev->dev;
dp->dpms_mode = DRM_MODE_DPMS_OFF; dp->dpms_mode = DRM_MODE_DPMS_OFF;
...@@ -1285,17 +1303,24 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) ...@@ -1285,17 +1303,24 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
dp->drm_dev = drm_dev; dp->drm_dev = drm_dev;
ret = exynos_drm_encoder_create(drm_dev, exynos_encoder, pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
EXYNOS_DISPLAY_TYPE_LCD); EXYNOS_DISPLAY_TYPE_LCD);
if (ret) { if (pipe < 0)
DRM_ERROR("failed to create encoder\n"); return pipe;
return ret;
} encoder->possible_crtcs = 1 << pipe;
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs,
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);
ret = exynos_dp_create_connector(exynos_encoder); ret = exynos_dp_create_connector(encoder);
if (ret) { if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret); DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(&exynos_encoder->base); drm_encoder_cleanup(encoder);
return ret; return ret;
} }
...@@ -1326,7 +1351,6 @@ static int exynos_dp_probe(struct platform_device *pdev) ...@@ -1326,7 +1351,6 @@ static int exynos_dp_probe(struct platform_device *pdev)
if (!dp) if (!dp)
return -ENOMEM; return -ENOMEM;
dp->encoder.ops = &exynos_dp_encoder_ops;
platform_set_drvdata(pdev, dp); platform_set_drvdata(pdev, dp);
panel_node = of_parse_phandle(dev->of_node, "panel", 0); panel_node = of_parse_phandle(dev->of_node, "panel", 0);
......
...@@ -147,7 +147,7 @@ struct link_train { ...@@ -147,7 +147,7 @@ struct link_train {
}; };
struct exynos_dp_device { struct exynos_dp_device {
struct exynos_drm_encoder encoder; struct drm_encoder encoder;
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct drm_connector connector; struct drm_connector connector;
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_fbdev.h" #include "exynos_drm_fbdev.h"
static LIST_HEAD(exynos_drm_subdrv_list); static LIST_HEAD(exynos_drm_subdrv_list);
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_plane.h" #include "exynos_drm_plane.h"
static void exynos_drm_crtc_enable(struct drm_crtc *crtc) static void exynos_drm_crtc_enable(struct drm_crtc *crtc)
......
...@@ -20,11 +20,10 @@ ...@@ -20,11 +20,10 @@
#include <video/of_videomode.h> #include <video/of_videomode.h>
#include <video/videomode.h> #include <video/videomode.h>
#include "exynos_drm_encoder.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
struct exynos_dpi { struct exynos_dpi {
struct exynos_drm_encoder encoder; struct drm_encoder encoder;
struct device *dev; struct device *dev;
struct device_node *panel_node; struct device_node *panel_node;
...@@ -36,7 +35,7 @@ struct exynos_dpi { ...@@ -36,7 +35,7 @@ struct exynos_dpi {
#define connector_to_dpi(c) container_of(c, struct exynos_dpi, connector) #define connector_to_dpi(c) container_of(c, struct exynos_dpi, connector)
static inline struct exynos_dpi *encoder_to_dpi(struct exynos_drm_encoder *e) static inline struct exynos_dpi *encoder_to_dpi(struct drm_encoder *e)
{ {
return container_of(e, struct exynos_dpi, encoder); return container_of(e, struct exynos_dpi, encoder);
} }
...@@ -98,7 +97,7 @@ exynos_dpi_best_encoder(struct drm_connector *connector) ...@@ -98,7 +97,7 @@ exynos_dpi_best_encoder(struct drm_connector *connector)
{ {
struct exynos_dpi *ctx = connector_to_dpi(connector); struct exynos_dpi *ctx = connector_to_dpi(connector);
return &ctx->encoder.base; return &ctx->encoder;
} }
static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = { static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = {
...@@ -106,11 +105,9 @@ static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = { ...@@ -106,11 +105,9 @@ static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = {
.best_encoder = exynos_dpi_best_encoder, .best_encoder = exynos_dpi_best_encoder,
}; };
static int exynos_dpi_create_connector( static int exynos_dpi_create_connector(struct drm_encoder *encoder)
struct exynos_drm_encoder *exynos_encoder)
{ {
struct exynos_dpi *ctx = encoder_to_dpi(exynos_encoder); struct exynos_dpi *ctx = encoder_to_dpi(encoder);
struct drm_encoder *encoder = &exynos_encoder->base;
struct drm_connector *connector = &ctx->connector; struct drm_connector *connector = &ctx->connector;
int ret; int ret;
...@@ -131,7 +128,20 @@ static int exynos_dpi_create_connector( ...@@ -131,7 +128,20 @@ static int exynos_dpi_create_connector(
return 0; return 0;
} }
static void exynos_dpi_enable(struct exynos_drm_encoder *encoder) static bool exynos_dpi_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void exynos_dpi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
}
static void exynos_dpi_enable(struct drm_encoder *encoder)
{ {
struct exynos_dpi *ctx = encoder_to_dpi(encoder); struct exynos_dpi *ctx = encoder_to_dpi(encoder);
...@@ -141,7 +151,7 @@ static void exynos_dpi_enable(struct exynos_drm_encoder *encoder) ...@@ -141,7 +151,7 @@ static void exynos_dpi_enable(struct exynos_drm_encoder *encoder)
} }
} }
static void exynos_dpi_disable(struct exynos_drm_encoder *encoder) static void exynos_dpi_disable(struct drm_encoder *encoder)
{ {
struct exynos_dpi *ctx = encoder_to_dpi(encoder); struct exynos_dpi *ctx = encoder_to_dpi(encoder);
...@@ -151,11 +161,17 @@ static void exynos_dpi_disable(struct exynos_drm_encoder *encoder) ...@@ -151,11 +161,17 @@ static void exynos_dpi_disable(struct exynos_drm_encoder *encoder)
} }
} }
static struct exynos_drm_encoder_ops exynos_dpi_encoder_ops = { static struct drm_encoder_helper_funcs exynos_dpi_encoder_helper_funcs = {
.mode_fixup = exynos_dpi_mode_fixup,
.mode_set = exynos_dpi_mode_set,
.enable = exynos_dpi_enable, .enable = exynos_dpi_enable,
.disable = exynos_dpi_disable, .disable = exynos_dpi_disable,
}; };
static struct drm_encoder_funcs exynos_dpi_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
/* of_* functions will be removed after merge of of_graph patches */ /* of_* functions will be removed after merge of of_graph patches */
static struct device_node * static struct device_node *
of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg) of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg)
...@@ -280,29 +296,34 @@ static int exynos_dpi_parse_dt(struct exynos_dpi *ctx) ...@@ -280,29 +296,34 @@ static int exynos_dpi_parse_dt(struct exynos_dpi *ctx)
return 0; return 0;
} }
int exynos_dpi_bind(struct drm_device *dev, int exynos_dpi_bind(struct drm_device *dev, struct drm_encoder *encoder)
struct exynos_drm_encoder *exynos_encoder)
{ {
int ret; int ret;
ret = exynos_drm_encoder_create(dev, exynos_encoder, ret = exynos_drm_crtc_get_pipe_from_type(dev, EXYNOS_DISPLAY_TYPE_LCD);
EXYNOS_DISPLAY_TYPE_LCD); if (ret < 0)
if (ret) {
DRM_ERROR("failed to create encoder\n");
return ret; return ret;
}
ret = exynos_dpi_create_connector(exynos_encoder); encoder->possible_crtcs = 1 << ret;
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
drm_encoder_init(dev, encoder, &exynos_dpi_encoder_funcs,
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &exynos_dpi_encoder_helper_funcs);
ret = exynos_dpi_create_connector(encoder);
if (ret) { if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret); DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(&exynos_encoder->base); drm_encoder_cleanup(encoder);
return ret; return ret;
} }
return 0; return 0;
} }
struct exynos_drm_encoder *exynos_dpi_probe(struct device *dev) struct drm_encoder *exynos_dpi_probe(struct device *dev)
{ {
struct exynos_dpi *ctx; struct exynos_dpi *ctx;
int ret; int ret;
...@@ -311,7 +332,6 @@ struct exynos_drm_encoder *exynos_dpi_probe(struct device *dev) ...@@ -311,7 +332,6 @@ struct exynos_drm_encoder *exynos_dpi_probe(struct device *dev)
if (!ctx) if (!ctx)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ctx->encoder.ops = &exynos_dpi_encoder_ops;
ctx->dev = dev; ctx->dev = dev;
ret = exynos_dpi_parse_dt(ctx); ret = exynos_dpi_parse_dt(ctx);
...@@ -329,7 +349,7 @@ struct exynos_drm_encoder *exynos_dpi_probe(struct device *dev) ...@@ -329,7 +349,7 @@ struct exynos_drm_encoder *exynos_dpi_probe(struct device *dev)
return &ctx->encoder; return &ctx->encoder;
} }
int exynos_dpi_remove(struct exynos_drm_encoder *encoder) int exynos_dpi_remove(struct drm_encoder *encoder)
{ {
struct exynos_dpi *ctx = encoder_to_dpi(encoder); struct exynos_dpi *ctx = encoder_to_dpi(encoder);
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_fbdev.h" #include "exynos_drm_fbdev.h"
#include "exynos_drm_fb.h" #include "exynos_drm_fb.h"
#include "exynos_drm_gem.h" #include "exynos_drm_gem.h"
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#define MAX_PLANE 5 #define MAX_PLANE 5
#define MAX_FB_BUFFER 4 #define MAX_FB_BUFFER 4
#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder, base)
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base) #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) #define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base)
...@@ -77,40 +76,6 @@ struct exynos_drm_plane { ...@@ -77,40 +76,6 @@ struct exynos_drm_plane {
unsigned int zpos; unsigned int zpos;
}; };
/*
* Exynos DRM Encoder Structure.
* - this structure is common to analog tv, digital tv and lcd panel.
*
* @mode_fixup: fix mode data comparing to hw specific display mode.
* @mode_set: convert drm_display_mode to hw specific display mode and
* would be called by encoder->mode_set().
* @enable: display device on.
* @disable: display device off.
*/
struct exynos_drm_encoder;
struct exynos_drm_encoder_ops {
void (*mode_fixup)(struct exynos_drm_encoder *encoder,
struct drm_connector *connector,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
void (*mode_set)(struct exynos_drm_encoder *encoder,
struct drm_display_mode *mode);
void (*enable)(struct exynos_drm_encoder *encoder);
void (*disable)(struct exynos_drm_encoder *encoder);
};
/*
* exynos specific encoder structure.
*
* @drm_encoder: encoder object.
* @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
* @ops: pointer to callbacks for exynos drm specific functionality
*/
struct exynos_drm_encoder {
struct drm_encoder base;
struct exynos_drm_encoder_ops *ops;
};
/* /*
* Exynos drm crtc ops * Exynos drm crtc ops
* *
...@@ -255,18 +220,18 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file); ...@@ -255,18 +220,18 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file);
void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file); void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file);
#ifdef CONFIG_DRM_EXYNOS_DPI #ifdef CONFIG_DRM_EXYNOS_DPI
struct exynos_drm_encoder *exynos_dpi_probe(struct device *dev); struct drm_encoder *exynos_dpi_probe(struct device *dev);
int exynos_dpi_remove(struct exynos_drm_encoder *encoder); int exynos_dpi_remove(struct drm_encoder *encoder);
int exynos_dpi_bind(struct drm_device *dev, struct exynos_drm_encoder *encoder); int exynos_dpi_bind(struct drm_device *dev, struct drm_encoder *encoder);
#else #else
static inline struct exynos_drm_encoder * static inline struct drm_encoder *
exynos_dpi_probe(struct device *dev) { return NULL; } exynos_dpi_probe(struct device *dev) { return NULL; }
static inline int exynos_dpi_remove(struct exynos_drm_encoder *encoder) static inline int exynos_dpi_remove(struct drm_encoder *encoder)
{ {
return 0; return 0;
} }
static inline int exynos_dpi_bind(struct drm_device *dev, static inline int exynos_dpi_bind(struct drm_device *dev,
struct exynos_drm_encoder *encoder) struct drm_encoder *encoder)
{ {
return 0; return 0;
} }
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <video/videomode.h> #include <video/videomode.h>
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
/* returns true iff both arguments logically differs */ /* returns true iff both arguments logically differs */
...@@ -260,7 +259,7 @@ struct exynos_dsi_driver_data { ...@@ -260,7 +259,7 @@ struct exynos_dsi_driver_data {
}; };
struct exynos_dsi { struct exynos_dsi {
struct exynos_drm_encoder encoder; struct drm_encoder encoder;
struct mipi_dsi_host dsi_host; struct mipi_dsi_host dsi_host;
struct drm_connector connector; struct drm_connector connector;
struct device_node *panel_node; struct device_node *panel_node;
...@@ -296,7 +295,7 @@ struct exynos_dsi { ...@@ -296,7 +295,7 @@ struct exynos_dsi {
#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector) #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
static inline struct exynos_dsi *encoder_to_dsi(struct exynos_drm_encoder *e) static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e)
{ {
return container_of(e, struct exynos_dsi, encoder); return container_of(e, struct exynos_dsi, encoder);
} }
...@@ -1273,7 +1272,7 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id) ...@@ -1273,7 +1272,7 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id) static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id)
{ {
struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id; struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id;
struct drm_encoder *encoder = &dsi->encoder.base; struct drm_encoder *encoder = &dsi->encoder;
if (dsi->state & DSIM_STATE_VIDOUT_AVAILABLE) if (dsi->state & DSIM_STATE_VIDOUT_AVAILABLE)
exynos_drm_crtc_te_handler(encoder->crtc); exynos_drm_crtc_te_handler(encoder->crtc);
...@@ -1519,7 +1518,7 @@ static void exynos_dsi_poweroff(struct exynos_dsi *dsi) ...@@ -1519,7 +1518,7 @@ static void exynos_dsi_poweroff(struct exynos_dsi *dsi)
dev_err(dsi->dev, "cannot disable regulators %d\n", ret); dev_err(dsi->dev, "cannot disable regulators %d\n", ret);
} }
static void exynos_dsi_enable(struct exynos_drm_encoder *encoder) static void exynos_dsi_enable(struct drm_encoder *encoder)
{ {
struct exynos_dsi *dsi = encoder_to_dsi(encoder); struct exynos_dsi *dsi = encoder_to_dsi(encoder);
int ret; int ret;
...@@ -1555,7 +1554,7 @@ static void exynos_dsi_enable(struct exynos_drm_encoder *encoder) ...@@ -1555,7 +1554,7 @@ static void exynos_dsi_enable(struct exynos_drm_encoder *encoder)
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
} }
static void exynos_dsi_disable(struct exynos_drm_encoder *encoder) static void exynos_dsi_disable(struct drm_encoder *encoder)
{ {
struct exynos_dsi *dsi = encoder_to_dsi(encoder); struct exynos_dsi *dsi = encoder_to_dsi(encoder);
...@@ -1583,7 +1582,7 @@ exynos_dsi_detect(struct drm_connector *connector, bool force) ...@@ -1583,7 +1582,7 @@ exynos_dsi_detect(struct drm_connector *connector, bool force)
if (dsi->panel) if (dsi->panel)
drm_panel_attach(dsi->panel, &dsi->connector); drm_panel_attach(dsi->panel, &dsi->connector);
} else if (!dsi->panel_node) { } else if (!dsi->panel_node) {
struct exynos_drm_encoder *encoder; struct drm_encoder *encoder;
encoder = platform_get_drvdata(to_platform_device(dsi->dev)); encoder = platform_get_drvdata(to_platform_device(dsi->dev));
exynos_dsi_disable(encoder); exynos_dsi_disable(encoder);
...@@ -1629,7 +1628,7 @@ exynos_dsi_best_encoder(struct drm_connector *connector) ...@@ -1629,7 +1628,7 @@ exynos_dsi_best_encoder(struct drm_connector *connector)
{ {
struct exynos_dsi *dsi = connector_to_dsi(connector); struct exynos_dsi *dsi = connector_to_dsi(connector);
return &dsi->encoder.base; return &dsi->encoder;
} }
static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = { static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = {
...@@ -1637,11 +1636,9 @@ static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = { ...@@ -1637,11 +1636,9 @@ static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = {
.best_encoder = exynos_dsi_best_encoder, .best_encoder = exynos_dsi_best_encoder,
}; };
static int exynos_dsi_create_connector( static int exynos_dsi_create_connector(struct drm_encoder *encoder)
struct exynos_drm_encoder *exynos_encoder)
{ {
struct exynos_dsi *dsi = encoder_to_dsi(exynos_encoder); struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct drm_encoder *encoder = &exynos_encoder->base;
struct drm_connector *connector = &dsi->connector; struct drm_connector *connector = &dsi->connector;
int ret; int ret;
...@@ -1662,28 +1659,42 @@ static int exynos_dsi_create_connector( ...@@ -1662,28 +1659,42 @@ static int exynos_dsi_create_connector(
return 0; return 0;
} }
static void exynos_dsi_mode_set(struct exynos_drm_encoder *encoder, static bool exynos_dsi_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode) const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void exynos_dsi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{ {
struct exynos_dsi *dsi = encoder_to_dsi(encoder); struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct videomode *vm = &dsi->vm; struct videomode *vm = &dsi->vm;
struct drm_display_mode *m = adjusted_mode;
vm->hactive = mode->hdisplay;
vm->vactive = mode->vdisplay; vm->hactive = m->hdisplay;
vm->vfront_porch = mode->vsync_start - mode->vdisplay; vm->vactive = m->vdisplay;
vm->vback_porch = mode->vtotal - mode->vsync_end; vm->vfront_porch = m->vsync_start - m->vdisplay;
vm->vsync_len = mode->vsync_end - mode->vsync_start; vm->vback_porch = m->vtotal - m->vsync_end;
vm->hfront_porch = mode->hsync_start - mode->hdisplay; vm->vsync_len = m->vsync_end - m->vsync_start;
vm->hback_porch = mode->htotal - mode->hsync_end; vm->hfront_porch = m->hsync_start - m->hdisplay;
vm->hsync_len = mode->hsync_end - mode->hsync_start; vm->hback_porch = m->htotal - m->hsync_end;
vm->hsync_len = m->hsync_end - m->hsync_start;
} }
static struct exynos_drm_encoder_ops exynos_dsi_encoder_ops = { static struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
.mode_fixup = exynos_dsi_mode_fixup,
.mode_set = exynos_dsi_mode_set, .mode_set = exynos_dsi_mode_set,
.enable = exynos_dsi_enable, .enable = exynos_dsi_enable,
.disable = exynos_dsi_disable, .disable = exynos_dsi_disable,
}; };
static struct drm_encoder_funcs exynos_dsi_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
/* of_* functions will be removed after merge of of_graph patches */ /* of_* functions will be removed after merge of of_graph patches */
...@@ -1804,23 +1815,30 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) ...@@ -1804,23 +1815,30 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
static int exynos_dsi_bind(struct device *dev, struct device *master, static int exynos_dsi_bind(struct device *dev, struct device *master,
void *data) void *data)
{ {
struct exynos_drm_encoder *exynos_encoder = dev_get_drvdata(dev); struct drm_encoder *encoder = dev_get_drvdata(dev);
struct exynos_dsi *dsi = encoder_to_dsi(exynos_encoder); struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
struct drm_bridge *bridge; struct drm_bridge *bridge;
int ret; int ret;
ret = exynos_drm_encoder_create(drm_dev, exynos_encoder, ret = exynos_drm_crtc_get_pipe_from_type(drm_dev,
EXYNOS_DISPLAY_TYPE_LCD); EXYNOS_DISPLAY_TYPE_LCD);
if (ret) { if (ret < 0)
DRM_ERROR("failed to create encoder\n");
return ret; return ret;
}
ret = exynos_dsi_create_connector(exynos_encoder); encoder->possible_crtcs = 1 << ret;
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs,
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs);
ret = exynos_dsi_create_connector(encoder);
if (ret) { if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret); DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(&exynos_encoder->base); drm_encoder_cleanup(encoder);
return ret; return ret;
} }
...@@ -1835,7 +1853,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, ...@@ -1835,7 +1853,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
static void exynos_dsi_unbind(struct device *dev, struct device *master, static void exynos_dsi_unbind(struct device *dev, struct device *master,
void *data) void *data)
{ {
struct exynos_drm_encoder *encoder = dev_get_drvdata(dev); struct drm_encoder *encoder = dev_get_drvdata(dev);
struct exynos_dsi *dsi = encoder_to_dsi(encoder); struct exynos_dsi *dsi = encoder_to_dsi(encoder);
exynos_dsi_disable(encoder); exynos_dsi_disable(encoder);
...@@ -1859,8 +1877,6 @@ static int exynos_dsi_probe(struct platform_device *pdev) ...@@ -1859,8 +1877,6 @@ static int exynos_dsi_probe(struct platform_device *pdev)
if (!dsi) if (!dsi)
return -ENOMEM; return -ENOMEM;
dsi->encoder.ops = &exynos_dsi_encoder_ops;
/* To be checked as invalid one */ /* To be checked as invalid one */
dsi->te_gpio = -ENOENT; dsi->te_gpio = -ENOENT;
......
/* exynos_drm_encoder.c
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* Authors:
* Inki Dae <inki.dae@samsung.com>
* Joonyoung Shim <jy0922.shim@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 <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_crtc.h"
static bool
exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
struct drm_connector *connector;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->encoder != encoder)
continue;
if (exynos_encoder->ops->mode_fixup)
exynos_encoder->ops->mode_fixup(exynos_encoder,
connector, mode,
adjusted_mode);
}
return true;
}
static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
if (exynos_encoder->ops->mode_set)
exynos_encoder->ops->mode_set(exynos_encoder, adjusted_mode);
}
static void exynos_drm_encoder_enable(struct drm_encoder *encoder)
{
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
if (exynos_encoder->ops->enable)
exynos_encoder->ops->enable(exynos_encoder);
}
static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
{
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
if (exynos_encoder->ops->disable)
exynos_encoder->ops->disable(exynos_encoder);
}
static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
.mode_fixup = exynos_drm_encoder_mode_fixup,
.mode_set = exynos_drm_encoder_mode_set,
.enable = exynos_drm_encoder_enable,
.disable = exynos_drm_encoder_disable,
};
static struct drm_encoder_funcs exynos_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
int exynos_drm_encoder_create(struct drm_device *dev,
struct exynos_drm_encoder *exynos_encoder,
enum exynos_drm_output_type type)
{
struct drm_encoder *encoder;
int pipe;
pipe = exynos_drm_crtc_get_pipe_from_type(dev, type);
if (pipe < 0)
return pipe;
encoder = &exynos_encoder->base;
encoder->possible_crtcs = 1 << pipe;
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
DRM_DEBUG_KMS("encoder has been created\n");
return 0;
}
/*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* Authors:
* Inki Dae <inki.dae@samsung.com>
* Joonyoung Shim <jy0922.shim@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.
*/
#ifndef _EXYNOS_DRM_ENCODER_H_
#define _EXYNOS_DRM_ENCODER_H_
#include "exynos_drm_drv.h"
int exynos_drm_encoder_create(struct drm_device *dev, struct exynos_drm_encoder
*encoder, enum exynos_drm_output_type type);
#endif
...@@ -169,7 +169,7 @@ struct fimd_context { ...@@ -169,7 +169,7 @@ struct fimd_context {
struct exynos_drm_panel_info panel; struct exynos_drm_panel_info panel;
struct fimd_driver_data *driver_data; struct fimd_driver_data *driver_data;
struct exynos_drm_encoder *encoder; struct drm_encoder *encoder;
}; };
static const struct of_device_id fimd_driver_dt_match[] = { static const struct of_device_id fimd_driver_dt_match[] = {
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h" #include "exynos_drm_plane.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_vidi.h" #include "exynos_drm_vidi.h"
/* vidi has totally three virtual windows. */ /* vidi has totally three virtual windows. */
...@@ -35,7 +34,7 @@ ...@@ -35,7 +34,7 @@
connector) connector)
struct vidi_context { struct vidi_context {
struct exynos_drm_encoder encoder; struct drm_encoder encoder;
struct platform_device *pdev; struct platform_device *pdev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct exynos_drm_crtc *crtc; struct exynos_drm_crtc *crtc;
...@@ -54,7 +53,7 @@ struct vidi_context { ...@@ -54,7 +53,7 @@ struct vidi_context {
int pipe; int pipe;
}; };
static inline struct vidi_context *encoder_to_vidi(struct exynos_drm_encoder *e) static inline struct vidi_context *encoder_to_vidi(struct drm_encoder *e)
{ {
return container_of(e, struct vidi_context, encoder); return container_of(e, struct vidi_context, encoder);
} }
...@@ -358,7 +357,7 @@ static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector) ...@@ -358,7 +357,7 @@ static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector)
{ {
struct vidi_context *ctx = ctx_from_connector(connector); struct vidi_context *ctx = ctx_from_connector(connector);
return &ctx->encoder.base; return &ctx->encoder;
} }
static struct drm_connector_helper_funcs vidi_connector_helper_funcs = { static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
...@@ -366,10 +365,9 @@ static struct drm_connector_helper_funcs vidi_connector_helper_funcs = { ...@@ -366,10 +365,9 @@ static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
.best_encoder = vidi_best_encoder, .best_encoder = vidi_best_encoder,
}; };
static int vidi_create_connector(struct exynos_drm_encoder *exynos_encoder) static int vidi_create_connector(struct drm_encoder *encoder)
{ {
struct vidi_context *ctx = encoder_to_vidi(exynos_encoder); struct vidi_context *ctx = encoder_to_vidi(encoder);
struct drm_encoder *encoder = &exynos_encoder->base;
struct drm_connector *connector = &ctx->connector; struct drm_connector *connector = &ctx->connector;
int ret; int ret;
...@@ -389,15 +387,47 @@ static int vidi_create_connector(struct exynos_drm_encoder *exynos_encoder) ...@@ -389,15 +387,47 @@ static int vidi_create_connector(struct exynos_drm_encoder *exynos_encoder)
return 0; return 0;
} }
static bool exynos_vidi_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void exynos_vidi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
}
static void exynos_vidi_enable(struct drm_encoder *encoder)
{
}
static void exynos_vidi_disable(struct drm_encoder *encoder)
{
}
static struct drm_encoder_helper_funcs exynos_vidi_encoder_helper_funcs = {
.mode_fixup = exynos_vidi_mode_fixup,
.mode_set = exynos_vidi_mode_set,
.enable = exynos_vidi_enable,
.disable = exynos_vidi_disable,
};
static struct drm_encoder_funcs exynos_vidi_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
static int vidi_bind(struct device *dev, struct device *master, void *data) static int vidi_bind(struct device *dev, struct device *master, void *data)
{ {
struct vidi_context *ctx = dev_get_drvdata(dev); struct vidi_context *ctx = dev_get_drvdata(dev);
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
struct exynos_drm_encoder *exynos_encoder = &ctx->encoder; struct drm_encoder *encoder = &ctx->encoder;
struct exynos_drm_plane *exynos_plane; struct exynos_drm_plane *exynos_plane;
enum drm_plane_type type; enum drm_plane_type type;
unsigned int zpos; unsigned int zpos;
int ret; int pipe, ret;
vidi_ctx_initialize(ctx, drm_dev); vidi_ctx_initialize(ctx, drm_dev);
...@@ -419,17 +449,24 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) ...@@ -419,17 +449,24 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
return PTR_ERR(ctx->crtc); return PTR_ERR(ctx->crtc);
} }
ret = exynos_drm_encoder_create(drm_dev, exynos_encoder, pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
EXYNOS_DISPLAY_TYPE_VIDI); EXYNOS_DISPLAY_TYPE_VIDI);
if (ret) { if (pipe < 0)
DRM_ERROR("failed to create encoder\n"); return pipe;
return ret;
} encoder->possible_crtcs = 1 << pipe;
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
drm_encoder_init(drm_dev, encoder, &exynos_vidi_encoder_funcs,
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &exynos_vidi_encoder_helper_funcs);
ret = vidi_create_connector(exynos_encoder); ret = vidi_create_connector(encoder);
if (ret) { if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret); DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(&exynos_encoder->base); drm_encoder_cleanup(encoder);
return ret; return ret;
} }
......
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_encoder.h"
#include "exynos_mixer.h" #include "exynos_mixer.h"
#include <linux/gpio.h> #include <linux/gpio.h>
...@@ -88,7 +87,7 @@ struct hdmi_resources { ...@@ -88,7 +87,7 @@ struct hdmi_resources {
}; };
struct hdmi_context { struct hdmi_context {
struct exynos_drm_encoder encoder; struct drm_encoder encoder;
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct drm_connector connector; struct drm_connector connector;
...@@ -116,7 +115,7 @@ struct hdmi_context { ...@@ -116,7 +115,7 @@ struct hdmi_context {
struct regmap *pmureg; struct regmap *pmureg;
}; };
static inline struct hdmi_context *encoder_to_hdmi(struct exynos_drm_encoder *e) static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e)
{ {
return container_of(e, struct hdmi_context, encoder); return container_of(e, struct hdmi_context, encoder);
} }
...@@ -1032,7 +1031,7 @@ static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector) ...@@ -1032,7 +1031,7 @@ static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
{ {
struct hdmi_context *hdata = ctx_from_connector(connector); struct hdmi_context *hdata = ctx_from_connector(connector);
return &hdata->encoder.base; return &hdata->encoder;
} }
static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = { static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
...@@ -1041,9 +1040,9 @@ static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = { ...@@ -1041,9 +1040,9 @@ static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
.best_encoder = hdmi_best_encoder, .best_encoder = hdmi_best_encoder,
}; };
static int hdmi_create_connector(struct exynos_drm_encoder *exynos_encoder) static int hdmi_create_connector(struct drm_encoder *encoder)
{ {
struct hdmi_context *hdata = encoder_to_hdmi(exynos_encoder); struct hdmi_context *hdata = encoder_to_hdmi(encoder);
struct drm_connector *connector = &hdata->connector; struct drm_connector *connector = &hdata->connector;
int ret; int ret;
...@@ -1059,28 +1058,35 @@ static int hdmi_create_connector(struct exynos_drm_encoder *exynos_encoder) ...@@ -1059,28 +1058,35 @@ static int hdmi_create_connector(struct exynos_drm_encoder *exynos_encoder)
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs); drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
drm_connector_register(connector); drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, &exynos_encoder->base); drm_mode_connector_attach_encoder(connector, encoder);
return 0; return 0;
} }
static void hdmi_mode_fixup(struct exynos_drm_encoder *encoder, static bool hdmi_mode_fixup(struct drm_encoder *encoder,
struct drm_connector *connector,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
struct drm_device *dev = encoder->dev;
struct drm_connector *connector;
struct drm_display_mode *m; struct drm_display_mode *m;
int mode_ok; int mode_ok;
DRM_DEBUG_KMS("%s\n", __FILE__);
drm_mode_set_crtcinfo(adjusted_mode, 0); drm_mode_set_crtcinfo(adjusted_mode, 0);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->encoder == encoder)
break;
}
if (connector->encoder != encoder)
return true;
mode_ok = hdmi_mode_valid(connector, adjusted_mode); mode_ok = hdmi_mode_valid(connector, adjusted_mode);
/* just return if user desired mode exists. */ /* just return if user desired mode exists. */
if (mode_ok == MODE_OK) if (mode_ok == MODE_OK)
return; return true;
/* /*
* otherwise, find the most suitable mode among modes and change it * otherwise, find the most suitable mode among modes and change it
...@@ -1100,6 +1106,8 @@ static void hdmi_mode_fixup(struct exynos_drm_encoder *encoder, ...@@ -1100,6 +1106,8 @@ static void hdmi_mode_fixup(struct exynos_drm_encoder *encoder,
break; break;
} }
} }
return true;
} }
static void hdmi_set_acr(u32 freq, u8 *acr) static void hdmi_set_acr(u32 freq, u8 *acr)
...@@ -1697,22 +1705,23 @@ static void hdmi_conf_apply(struct hdmi_context *hdata) ...@@ -1697,22 +1705,23 @@ static void hdmi_conf_apply(struct hdmi_context *hdata)
hdmi_regs_dump(hdata, "start"); hdmi_regs_dump(hdata, "start");
} }
static void hdmi_mode_set(struct exynos_drm_encoder *encoder, static void hdmi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode) struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{ {
struct hdmi_context *hdata = encoder_to_hdmi(encoder); struct hdmi_context *hdata = encoder_to_hdmi(encoder);
struct drm_display_mode *m = mode; struct drm_display_mode *m = adjusted_mode;
DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n", DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
m->hdisplay, m->vdisplay, m->hdisplay, m->vdisplay,
m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ? m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
"INTERLACED" : "PROGRESSIVE"); "INTERLACED" : "PROGRESSIVE");
drm_mode_copy(&hdata->current_mode, mode); drm_mode_copy(&hdata->current_mode, m);
hdata->cea_video_id = drm_match_cea_mode(mode); hdata->cea_video_id = drm_match_cea_mode(mode);
} }
static void hdmi_enable(struct exynos_drm_encoder *encoder) static void hdmi_enable(struct drm_encoder *encoder)
{ {
struct hdmi_context *hdata = encoder_to_hdmi(encoder); struct hdmi_context *hdata = encoder_to_hdmi(encoder);
struct hdmi_resources *res = &hdata->res; struct hdmi_resources *res = &hdata->res;
...@@ -1738,11 +1747,11 @@ static void hdmi_enable(struct exynos_drm_encoder *encoder) ...@@ -1738,11 +1747,11 @@ static void hdmi_enable(struct exynos_drm_encoder *encoder)
hdmi_conf_apply(hdata); hdmi_conf_apply(hdata);
} }
static void hdmi_disable(struct exynos_drm_encoder *encoder) static void hdmi_disable(struct drm_encoder *encoder)
{ {
struct hdmi_context *hdata = encoder_to_hdmi(encoder); struct hdmi_context *hdata = encoder_to_hdmi(encoder);
struct hdmi_resources *res = &hdata->res; struct hdmi_resources *res = &hdata->res;
struct drm_crtc *crtc = hdata->encoder.base.crtc; struct drm_crtc *crtc = encoder->crtc;
const struct drm_crtc_helper_funcs *funcs = NULL; const struct drm_crtc_helper_funcs *funcs = NULL;
if (!hdata->powered) if (!hdata->powered)
...@@ -1783,13 +1792,17 @@ static void hdmi_disable(struct exynos_drm_encoder *encoder) ...@@ -1783,13 +1792,17 @@ static void hdmi_disable(struct exynos_drm_encoder *encoder)
hdata->powered = false; hdata->powered = false;
} }
static struct exynos_drm_encoder_ops hdmi_encoder_ops = { static struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = {
.mode_fixup = hdmi_mode_fixup, .mode_fixup = hdmi_mode_fixup,
.mode_set = hdmi_mode_set, .mode_set = hdmi_mode_set,
.enable = hdmi_enable, .enable = hdmi_enable,
.disable = hdmi_disable, .disable = hdmi_disable,
}; };
static struct drm_encoder_funcs exynos_hdmi_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
static void hdmi_hotplug_work_func(struct work_struct *work) static void hdmi_hotplug_work_func(struct work_struct *work)
{ {
struct hdmi_context *hdata; struct hdmi_context *hdata;
...@@ -1917,22 +1930,29 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) ...@@ -1917,22 +1930,29 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
{ {
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
struct hdmi_context *hdata = dev_get_drvdata(dev); struct hdmi_context *hdata = dev_get_drvdata(dev);
struct exynos_drm_encoder *exynos_encoder = &hdata->encoder; struct drm_encoder *encoder = &hdata->encoder;
int ret; int ret, pipe;
hdata->drm_dev = drm_dev; hdata->drm_dev = drm_dev;
ret = exynos_drm_encoder_create(drm_dev, exynos_encoder, pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
EXYNOS_DISPLAY_TYPE_HDMI); EXYNOS_DISPLAY_TYPE_HDMI);
if (ret) { if (pipe < 0)
DRM_ERROR("failed to create encoder\n"); return pipe;
return ret;
} encoder->possible_crtcs = 1 << pipe;
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
ret = hdmi_create_connector(exynos_encoder); ret = hdmi_create_connector(encoder);
if (ret) { if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret); DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(&exynos_encoder->base); drm_encoder_cleanup(encoder);
return ret; return ret;
} }
...@@ -1985,7 +2005,6 @@ static int hdmi_probe(struct platform_device *pdev) ...@@ -1985,7 +2005,6 @@ static int hdmi_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
hdata->drv_data = match->data; hdata->drv_data = match->data;
hdata->encoder.ops = &hdmi_encoder_ops;
platform_set_drvdata(pdev, hdata); platform_set_drvdata(pdev, hdata);
......
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