Commit 64c026e2 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

Inki writes:
      This is initial pull request for Exynos. It includes a big change
       that it makes drm_display_mode for timings parameters to be used
       for exynos4 and exynos5 commonly and cleans up unnecessary codes.
       And also it adds device tree support for fimd to get timing values
       and interrupt source from dts file.

       In addition, one more patch, device tree support feature for Exynos
       FIMC, is being reviewed. This patch was posted a little ago like below,
            http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg17568.html

       So we are going to request git pull one more time after reviewed.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: prepare FIMD clocks
  Revert "of/exynos_g2d: Add Bindings for exynos G2D driver"
  drm/exynos: drm_connector: Fix error check condition
  drm/exynos: drm_rotator: Fix incorrect usage of IS_ERR_OR_NULL
  drm/exynos: mixer: Fix incorrect usage of IS_ERR_OR_NULL
  drm/exynos: hdmi: Fix incorrect usage of IS_ERR_OR_NULL
  drm/exynos: change the method for getting the interrupt
  drm/exynos: enable OF_VIDEOMODE and FB_MODE_HELPERS for exynos drm fimd
  drm/exynos: Add display-timing node parsing using video helper function
  drm/exynos: hdmi: move mode_fixup to drm common hdmi
  drm/exynos: hdmi: using drm_display_mode timings for exynos4
parents f0aa848f b4e3a3e8
Samsung 2D Graphic Accelerator using DRM frame work
Samsung FIMG2D is a graphics 2D accelerator which supports Bit Block Transfer.
We set the drawing-context registers for configuring rendering parameters and
then start rendering.
This driver is for SOCs which contain G2D IPs with version 4.1.
Required properties:
-compatible:
should be "samsung,exynos-g2d-41".
-reg:
physical base address of the controller and length
of memory mapped region.
-interrupts:
interrupt combiner values.
Example:
g2d {
compatible = "samsung,exynos-g2d-41";
reg = <0x10850000 0x1000>;
interrupts = <0 91 0>;
};
...@@ -24,7 +24,9 @@ config DRM_EXYNOS_DMABUF ...@@ -24,7 +24,9 @@ config DRM_EXYNOS_DMABUF
config DRM_EXYNOS_FIMD config DRM_EXYNOS_FIMD
bool "Exynos DRM FIMD" bool "Exynos DRM FIMD"
depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM depends on OF && DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
select OF_VIDEOMODE
select FB_MODE_HELPERS
help help
Choose this option if you want to use Exynos FIMD for DRM. Choose this option if you want to use Exynos FIMD for DRM.
......
...@@ -124,7 +124,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) ...@@ -124,7 +124,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
} }
count = drm_add_edid_modes(connector, edid); count = drm_add_edid_modes(connector, edid);
if (count < 0) { if (!count) {
DRM_ERROR("Add edid modes failed %d\n", count); DRM_ERROR("Add edid modes failed %d\n", count);
goto out; goto out;
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <video/of_display_timing.h>
#include <video/samsung_fimd.h> #include <video/samsung_fimd.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
...@@ -884,10 +885,25 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -884,10 +885,25 @@ static int fimd_probe(struct platform_device *pdev)
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
pdata = pdev->dev.platform_data; if (pdev->dev.of_node) {
if (!pdata) { pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
dev_err(dev, "no platform data specified\n"); if (!pdata) {
return -EINVAL; DRM_ERROR("memory allocation for pdata failed\n");
return -ENOMEM;
}
ret = of_get_fb_videomode(dev->of_node, &pdata->panel.timing,
OF_USE_NATIVE_MODE);
if (ret) {
DRM_ERROR("failed: of_get_fb_videomode() : %d\n", ret);
return ret;
}
} else {
pdata = pdev->dev.platform_data;
if (!pdata) {
DRM_ERROR("no platform data specified\n");
return -EINVAL;
}
} }
panel = &pdata->panel; panel = &pdata->panel;
...@@ -918,7 +934,7 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -918,7 +934,7 @@ static int fimd_probe(struct platform_device *pdev)
if (IS_ERR(ctx->regs)) if (IS_ERR(ctx->regs))
return PTR_ERR(ctx->regs); return PTR_ERR(ctx->regs);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "vsync");
if (!res) { if (!res) {
dev_err(dev, "irq request failed.\n"); dev_err(dev, "irq request failed.\n");
return -ENXIO; return -ENXIO;
...@@ -933,6 +949,16 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -933,6 +949,16 @@ static int fimd_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = clk_prepare(ctx->bus_clk);
if (ret < 0)
return ret;
ret = clk_prepare(ctx->lcd_clk);
if (ret < 0) {
clk_unprepare(ctx->bus_clk);
return ret;
}
ctx->vidcon0 = pdata->vidcon0; ctx->vidcon0 = pdata->vidcon0;
ctx->vidcon1 = pdata->vidcon1; ctx->vidcon1 = pdata->vidcon1;
ctx->default_win = pdata->default_win; ctx->default_win = pdata->default_win;
...@@ -980,8 +1006,8 @@ static int fimd_remove(struct platform_device *pdev) ...@@ -980,8 +1006,8 @@ static int fimd_remove(struct platform_device *pdev)
if (ctx->suspended) if (ctx->suspended)
goto out; goto out;
clk_disable(ctx->lcd_clk); clk_unprepare(ctx->lcd_clk);
clk_disable(ctx->bus_clk); clk_unprepare(ctx->bus_clk);
pm_runtime_set_suspended(dev); pm_runtime_set_suspended(dev);
pm_runtime_put_sync(dev); pm_runtime_put_sync(dev);
......
...@@ -205,13 +205,45 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev, ...@@ -205,13 +205,45 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
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_hdmi_context *ctx = to_context(subdrv_dev); struct drm_display_mode *m;
int mode_ok;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
if (hdmi_ops && hdmi_ops->mode_fixup) drm_mode_set_crtcinfo(adjusted_mode, 0);
hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode,
adjusted_mode); mode_ok = drm_hdmi_check_timing(subdrv_dev, adjusted_mode);
/* just return if user desired mode exists. */
if (mode_ok == 0)
return;
/*
* otherwise, find the most suitable mode among modes and change it
* to adjusted_mode.
*/
list_for_each_entry(m, &connector->modes, head) {
mode_ok = drm_hdmi_check_timing(subdrv_dev, m);
if (mode_ok == 0) {
struct drm_mode_object base;
struct list_head head;
DRM_INFO("desired mode doesn't exist so\n");
DRM_INFO("use the most suitable mode among modes.\n");
DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
m->hdisplay, m->vdisplay, m->vrefresh);
/* preserve display mode header while copying. */
head = adjusted_mode->head;
base = adjusted_mode->base;
memcpy(adjusted_mode, m, sizeof(*m));
adjusted_mode->head = head;
adjusted_mode->base = base;
break;
}
}
} }
static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode) static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
......
...@@ -36,9 +36,6 @@ struct exynos_hdmi_ops { ...@@ -36,9 +36,6 @@ struct exynos_hdmi_ops {
int (*power_on)(void *ctx, int mode); int (*power_on)(void *ctx, int mode);
/* manager */ /* manager */
void (*mode_fixup)(void *ctx, struct drm_connector *connector,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
void (*mode_set)(void *ctx, void *mode); void (*mode_set)(void *ctx, void *mode);
void (*get_max_resol)(void *ctx, unsigned int *width, void (*get_max_resol)(void *ctx, unsigned int *width,
unsigned int *height); unsigned int *height);
......
...@@ -674,7 +674,7 @@ static int rotator_probe(struct platform_device *pdev) ...@@ -674,7 +674,7 @@ static int rotator_probe(struct platform_device *pdev)
} }
rot->clock = devm_clk_get(dev, "rotator"); rot->clock = devm_clk_get(dev, "rotator");
if (IS_ERR_OR_NULL(rot->clock)) { if (IS_ERR(rot->clock)) {
dev_err(dev, "failed to get clock\n"); dev_err(dev, "failed to get clock\n");
ret = PTR_ERR(rot->clock); ret = PTR_ERR(rot->clock);
goto err_clk_get; goto err_clk_get;
......
This diff is collapsed.
...@@ -820,7 +820,6 @@ static void mixer_win_disable(void *ctx, int win) ...@@ -820,7 +820,6 @@ static void mixer_win_disable(void *ctx, int win)
static int mixer_check_timing(void *ctx, struct fb_videomode *timing) static int mixer_check_timing(void *ctx, struct fb_videomode *timing)
{ {
struct mixer_context *mixer_ctx = ctx;
u32 w, h; u32 w, h;
w = timing->xres; w = timing->xres;
...@@ -831,9 +830,6 @@ static int mixer_check_timing(void *ctx, struct fb_videomode *timing) ...@@ -831,9 +830,6 @@ static int mixer_check_timing(void *ctx, struct fb_videomode *timing)
timing->refresh, (timing->vmode & timing->refresh, (timing->vmode &
FB_VMODE_INTERLACED) ? true : false); FB_VMODE_INTERLACED) ? true : false);
if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16)
return 0;
if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) || if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) || (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
(w >= 1664 && w <= 1920 && h >= 936 && h <= 1080)) (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
...@@ -1047,13 +1043,13 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx, ...@@ -1047,13 +1043,13 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
spin_lock_init(&mixer_res->reg_slock); spin_lock_init(&mixer_res->reg_slock);
mixer_res->mixer = devm_clk_get(dev, "mixer"); mixer_res->mixer = devm_clk_get(dev, "mixer");
if (IS_ERR_OR_NULL(mixer_res->mixer)) { if (IS_ERR(mixer_res->mixer)) {
dev_err(dev, "failed to get clock 'mixer'\n"); dev_err(dev, "failed to get clock 'mixer'\n");
return -ENODEV; return -ENODEV;
} }
mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { if (IS_ERR(mixer_res->sclk_hdmi)) {
dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
return -ENODEV; return -ENODEV;
} }
...@@ -1096,17 +1092,17 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx, ...@@ -1096,17 +1092,17 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
struct resource *res; struct resource *res;
mixer_res->vp = devm_clk_get(dev, "vp"); mixer_res->vp = devm_clk_get(dev, "vp");
if (IS_ERR_OR_NULL(mixer_res->vp)) { if (IS_ERR(mixer_res->vp)) {
dev_err(dev, "failed to get clock 'vp'\n"); dev_err(dev, "failed to get clock 'vp'\n");
return -ENODEV; return -ENODEV;
} }
mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { if (IS_ERR(mixer_res->sclk_mixer)) {
dev_err(dev, "failed to get clock 'sclk_mixer'\n"); dev_err(dev, "failed to get clock 'sclk_mixer'\n");
return -ENODEV; return -ENODEV;
} }
mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac"); mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { if (IS_ERR(mixer_res->sclk_dac)) {
dev_err(dev, "failed to get clock 'sclk_dac'\n"); dev_err(dev, "failed to get clock 'sclk_dac'\n");
return -ENODEV; return -ENODEV;
} }
......
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