提交 86a7e122 编写于 作者: D 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

   Summary:
   - Consider fallback option to gem allocation fail
     . try to allocate physically non-contiguous memory
       if iommu is supported when physically contiguous memory allocation
       failed.
   - Add runtime pm support to g2d driver
   - Add device tree support
     . add device tree support to rotator driver, make fimd driver get
       signal polarities from device tree.
   - some fixups
     . correct pixel format setting to fimd driver, and consider pixel
       format checking to a particular window layer.
   - some cleanups
     . replace fb_videomode with videomode.
     . remove non-DT support

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (21 commits)
  drm/exynos: Fix build error with exynos_drm_connector.c
  drm/exynos: Remove non-DT support in exynos_drm_fimd
  drm/exynos: Remove non-DT support in exynos_hdmi
  drm/exynos: Remove non-DT support in exynos_drm_g2d
  drm/exynos: Remove non-DT support in exynos_hdmiphy
  drm/exynos: Remove non-DT support in exynos_ddc
  drm/exynos: Make Exynos DRM drivers depend on OF
  drm/exynos: Consider fallback option to allocation fail
  drm/exynos: fimd: move platform data parsing to separate function
  drm/exynos: fimd: get signal polarities from device tree
  drm/exynos: fimd: replace struct fb_videomode with videomode
  drm/exynos: check a pixel format to a particular window layer
  drm/exynos: fix fimd pixel format setting
  drm/exynos: Add NULL pointer check
  drm/exynos: Remove redundant error messages
  drm/exynos: Add missing of.h header include
  drm/exynos: Remove redundant NULL check in exynos_drm_buf
  drm/exynos: add device tree support for rotator
  drm/exynos: Add missing includes
  drm/exynos: add runtime pm interfaces to g2d driver
  ...
* Samsung Image Rotator
Required properties:
- compatible : value should be one of the following:
(a) "samsung,exynos4210-rotator" for Rotator IP in Exynos4210
(b) "samsung,exynos4212-rotator" for Rotator IP in Exynos4212/4412
(c) "samsung,exynos5250-rotator" for Rotator IP in Exynos5250
- reg : Physical base address of the IP registers and length of memory
mapped region.
- interrupts : Interrupt specifier for rotator interrupt, according to format
specific to interrupt parent.
- clocks : Clock specifier for rotator clock, according to generic clock
bindings. (See Documentation/devicetree/bindings/clock/exynos*.txt)
- clock-names : Names of clocks. For exynos rotator, it should be "rotator".
Example:
rotator@12810000 {
compatible = "samsung,exynos4210-rotator";
reg = <0x12810000 0x1000>;
interrupts = <0 83 0>;
clocks = <&clock 278>;
clock-names = "rotator";
};
config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series"
depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
depends on OF && DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
select DRM_KMS_HELPER
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
select VIDEOMODE_HELPERS
help
Choose this option if you have a Samsung SoC EXYNOS chipset.
If M is selected the module will be called exynosdrm.
......@@ -24,9 +25,8 @@ config DRM_EXYNOS_DMABUF
config DRM_EXYNOS_FIMD
bool "Exynos DRM FIMD"
depends on OF && DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
select FB_MODE_HELPERS
select VIDEOMODE_HELPERS
help
Choose this option if you want to use Exynos FIMD for DRM.
......
......@@ -15,7 +15,7 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include "exynos_drm_drv.h"
#include "exynos_hdmi.h"
......@@ -41,13 +41,6 @@ static int s5p_ddc_remove(struct i2c_client *client)
return 0;
}
static struct i2c_device_id ddc_idtable[] = {
{"s5p_ddc", 0},
{"exynos5-hdmiddc", 0},
{ },
};
#ifdef CONFIG_OF
static struct of_device_id hdmiddc_match_types[] = {
{
.compatible = "samsung,exynos5-hdmiddc",
......@@ -57,15 +50,13 @@ static struct of_device_id hdmiddc_match_types[] = {
/* end node */
}
};
#endif
struct i2c_driver ddc_driver = {
.driver = {
.name = "exynos-hdmiddc",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(hdmiddc_match_types),
.of_match_table = hdmiddc_match_types,
},
.id_table = ddc_idtable,
.probe = s5p_ddc_probe,
.remove = s5p_ddc_remove,
.command = NULL,
......
......@@ -149,10 +149,8 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
DRM_DEBUG_KMS("desired size = 0x%x\n", size);
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer) {
DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
if (!buffer)
return NULL;
}
buffer->size = size;
return buffer;
......@@ -161,11 +159,6 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
void exynos_drm_fini_buf(struct drm_device *dev,
struct exynos_drm_gem_buf *buffer)
{
if (!buffer) {
DRM_DEBUG_KMS("buffer is null.\n");
return;
}
kfree(buffer);
buffer = NULL;
}
......
......@@ -17,6 +17,7 @@
#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_connector.h"
#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
drm_connector)
......@@ -28,35 +29,6 @@ struct exynos_drm_connector {
uint32_t dpms;
};
/* convert exynos_video_timings to drm_display_mode */
static inline void
convert_to_display_mode(struct drm_display_mode *mode,
struct exynos_drm_panel_info *panel)
{
struct fb_videomode *timing = &panel->timing;
mode->clock = timing->pixclock / 1000;
mode->vrefresh = timing->refresh;
mode->hdisplay = timing->xres;
mode->hsync_start = mode->hdisplay + timing->right_margin;
mode->hsync_end = mode->hsync_start + timing->hsync_len;
mode->htotal = mode->hsync_end + timing->left_margin;
mode->vdisplay = timing->yres;
mode->vsync_start = mode->vdisplay + timing->lower_margin;
mode->vsync_end = mode->vsync_start + timing->vsync_len;
mode->vtotal = mode->vsync_end + timing->upper_margin;
mode->width_mm = panel->width_mm;
mode->height_mm = panel->height_mm;
if (timing->vmode & FB_VMODE_INTERLACED)
mode->flags |= DRM_MODE_FLAG_INTERLACE;
if (timing->vmode & FB_VMODE_DOUBLE)
mode->flags |= DRM_MODE_FLAG_DBLSCAN;
}
static int exynos_drm_connector_get_modes(struct drm_connector *connector)
{
struct exynos_drm_connector *exynos_connector =
......@@ -111,7 +83,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
return 0;
}
convert_to_display_mode(mode, panel);
drm_display_mode_from_videomode(&panel->vm, mode);
mode->width_mm = panel->width_mm;
mode->height_mm = panel->height_mm;
connector->display_info.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm;
......@@ -278,10 +252,8 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
int err;
exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
if (!exynos_connector) {
DRM_ERROR("failed to allocate connector\n");
if (!exynos_connector)
return NULL;
}
connector = &exynos_connector->drm_connector;
......
......@@ -15,6 +15,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_plane.h"
......@@ -324,10 +325,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
struct drm_crtc *crtc;
exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
if (!exynos_crtc) {
DRM_ERROR("failed to allocate exynos crtc\n");
if (!exynos_crtc)
return -ENOMEM;
}
exynos_crtc->pipe = nr;
exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
......
......@@ -11,6 +11,7 @@
#include <drm/drmP.h>
#include <drm/exynos_drm.h>
#include "exynos_drm_dmabuf.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
......@@ -230,7 +231,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer) {
DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
ret = -ENOMEM;
goto err_unmap_attach;
}
......
......@@ -47,10 +47,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
int nr;
private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
if (!private) {
DRM_ERROR("failed to allocate private\n");
if (!private)
return -ENOMEM;
}
INIT_LIST_HEAD(&private->pageflip_event_list);
dev->dev_private = (void *)private;
......
......@@ -324,10 +324,8 @@ exynos_drm_encoder_create(struct drm_device *dev,
return NULL;
exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
if (!exynos_encoder) {
DRM_ERROR("failed to allocate encoder\n");
if (!exynos_encoder)
return NULL;
}
exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
exynos_encoder->manager = manager;
......
......@@ -156,10 +156,8 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
}
exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb) {
DRM_ERROR("failed to allocate exynos drm framebuffer\n");
if (!exynos_fb)
return ERR_PTR(-ENOMEM);
}
drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
exynos_fb->exynos_gem_obj[0] = exynos_gem_obj;
......@@ -220,10 +218,8 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
int i, ret;
exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb) {
DRM_ERROR("failed to allocate exynos drm framebuffer\n");
if (!exynos_fb)
return ERR_PTR(-ENOMEM);
}
obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
if (!obj) {
......
......@@ -16,9 +16,11 @@
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h"
......@@ -165,8 +167,18 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
size = mode_cmd.pitches[0] * mode_cmd.height;
/* 0 means to allocate physically continuous memory */
exynos_gem_obj = exynos_drm_gem_create(dev, 0, size);
exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
/*
* If physically contiguous memory allocation fails and if IOMMU is
* supported then try to get buffer from non physically contiguous
* memory area.
*/
if (IS_ERR(exynos_gem_obj) && is_drm_iommu_supported(dev)) {
dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG,
size);
}
if (IS_ERR(exynos_gem_obj)) {
ret = PTR_ERR(exynos_gem_obj);
goto err_release_framebuffer;
......@@ -236,10 +248,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
return 0;
fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
if (!fbdev) {
DRM_ERROR("failed to allocate drm fbdev.\n");
if (!fbdev)
return -ENOMEM;
}
private->fb_helper = helper = &fbdev->drm_fb_helper;
helper->funcs = &exynos_drm_fb_helper_funcs;
......
......@@ -17,10 +17,12 @@
#include <linux/regmap.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <drm/drmP.h>
#include <drm/exynos_drm.h>
#include "regs-fimc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h"
#include "exynos_drm_fimc.h"
......@@ -1343,10 +1345,8 @@ static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
struct drm_exynos_ipp_prop_list *prop_list;
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
if (!prop_list) {
DRM_ERROR("failed to alloc property list.\n");
if (!prop_list)
return -ENOMEM;
}
prop_list->version = 1;
prop_list->writeback = 1;
......
......@@ -16,10 +16,12 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <video/of_display_timing.h>
#include <video/of_videomode.h>
#include <video/samsung_fimd.h>
#include <drm/exynos_drm.h>
......@@ -35,6 +37,8 @@
* CPU Interface.
*/
#define FIMD_DEFAULT_FRAMERATE 60
/* position control register for hardware window 0, 2 ~ 4.*/
#define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16)
#define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16)
......@@ -65,11 +69,13 @@ struct fimd_driver_data {
unsigned int has_shadowcon:1;
unsigned int has_clksel:1;
unsigned int has_limited_fmt:1;
};
static struct fimd_driver_data s3c64xx_fimd_driver_data = {
.timing_base = 0x0,
.has_clksel = 1,
.has_limited_fmt = 1,
};
static struct fimd_driver_data exynos4_fimd_driver_data = {
......@@ -90,6 +96,7 @@ struct fimd_win_data {
unsigned int fb_width;
unsigned int fb_height;
unsigned int bpp;
unsigned int pixel_format;
dma_addr_t dma_addr;
unsigned int buf_offsize;
unsigned int line_size; /* bytes */
......@@ -115,11 +122,10 @@ struct fimd_context {
wait_queue_head_t wait_vsync_queue;
atomic_t wait_vsync_event;
struct exynos_drm_panel_info *panel;
struct exynos_drm_panel_info panel;
struct fimd_driver_data *driver_data;
};
#ifdef CONFIG_OF
static const struct of_device_id fimd_driver_dt_match[] = {
{ .compatible = "samsung,s3c6400-fimd",
.data = &s3c64xx_fimd_driver_data },
......@@ -129,21 +135,14 @@ static const struct of_device_id fimd_driver_dt_match[] = {
.data = &exynos5_fimd_driver_data },
{},
};
#endif
static inline struct fimd_driver_data *drm_fimd_get_driver_data(
struct platform_device *pdev)
{
#ifdef CONFIG_OF
const struct of_device_id *of_id =
of_match_device(fimd_driver_dt_match, &pdev->dev);
if (of_id)
return (struct fimd_driver_data *)of_id->data;
#endif
return (struct fimd_driver_data *)
platform_get_device_id(pdev)->driver_data;
return (struct fimd_driver_data *)of_id->data;
}
static bool fimd_display_is_connected(struct device *dev)
......@@ -157,7 +156,7 @@ static void *fimd_get_panel(struct device *dev)
{
struct fimd_context *ctx = get_fimd_context(dev);
return ctx->panel;
return &ctx->panel;
}
static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode)
......@@ -237,8 +236,8 @@ static void fimd_apply(struct device *subdrv_dev)
static void fimd_commit(struct device *dev)
{
struct fimd_context *ctx = get_fimd_context(dev);
struct exynos_drm_panel_info *panel = ctx->panel;
struct fb_videomode *timing = &panel->timing;
struct exynos_drm_panel_info *panel = &ctx->panel;
struct videomode *vm = &panel->vm;
struct fimd_driver_data *driver_data;
u32 val;
......@@ -250,22 +249,22 @@ static void fimd_commit(struct device *dev)
writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
/* setup vertical timing values. */
val = VIDTCON0_VBPD(timing->upper_margin - 1) |
VIDTCON0_VFPD(timing->lower_margin - 1) |
VIDTCON0_VSPW(timing->vsync_len - 1);
val = VIDTCON0_VBPD(vm->vback_porch - 1) |
VIDTCON0_VFPD(vm->vfront_porch - 1) |
VIDTCON0_VSPW(vm->vsync_len - 1);
writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
/* setup horizontal timing values. */
val = VIDTCON1_HBPD(timing->left_margin - 1) |
VIDTCON1_HFPD(timing->right_margin - 1) |
VIDTCON1_HSPW(timing->hsync_len - 1);
val = VIDTCON1_HBPD(vm->hback_porch - 1) |
VIDTCON1_HFPD(vm->hfront_porch - 1) |
VIDTCON1_HSPW(vm->hsync_len - 1);
writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
/* setup horizontal and vertical display size. */
val = VIDTCON2_LINEVAL(timing->yres - 1) |
VIDTCON2_HOZVAL(timing->xres - 1) |
VIDTCON2_LINEVAL_E(timing->yres - 1) |
VIDTCON2_HOZVAL_E(timing->xres - 1);
val = VIDTCON2_LINEVAL(vm->vactive - 1) |
VIDTCON2_HOZVAL(vm->hactive - 1) |
VIDTCON2_LINEVAL_E(vm->vactive - 1) |
VIDTCON2_HOZVAL_E(vm->hactive - 1);
writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
/* setup clock source, clock divider, enable dma. */
......@@ -396,6 +395,7 @@ static void fimd_win_mode_set(struct device *dev,
win_data->fb_height = overlay->fb_height;
win_data->dma_addr = overlay->dma_addr[0] + offset;
win_data->bpp = overlay->bpp;
win_data->pixel_format = overlay->pixel_format;
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
(overlay->bpp >> 3);
win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
......@@ -417,39 +417,38 @@ static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
val = WINCONx_ENWIN;
switch (win_data->bpp) {
case 1:
val |= WINCON0_BPPMODE_1BPP;
val |= WINCONx_BITSWP;
val |= WINCONx_BURSTLEN_4WORD;
break;
case 2:
val |= WINCON0_BPPMODE_2BPP;
val |= WINCONx_BITSWP;
val |= WINCONx_BURSTLEN_8WORD;
break;
case 4:
val |= WINCON0_BPPMODE_4BPP;
val |= WINCONx_BITSWP;
val |= WINCONx_BURSTLEN_8WORD;
break;
case 8:
/*
* In case of s3c64xx, window 0 doesn't support alpha channel.
* So the request format is ARGB8888 then change it to XRGB8888.
*/
if (ctx->driver_data->has_limited_fmt && !win) {
if (win_data->pixel_format == DRM_FORMAT_ARGB8888)
win_data->pixel_format = DRM_FORMAT_XRGB8888;
}
switch (win_data->pixel_format) {
case DRM_FORMAT_C8:
val |= WINCON0_BPPMODE_8BPP_PALETTE;
val |= WINCONx_BURSTLEN_8WORD;
val |= WINCONx_BYTSWP;
break;
case 16:
case DRM_FORMAT_XRGB1555:
val |= WINCON0_BPPMODE_16BPP_1555;
val |= WINCONx_HAWSWP;
val |= WINCONx_BURSTLEN_16WORD;
break;
case DRM_FORMAT_RGB565:
val |= WINCON0_BPPMODE_16BPP_565;
val |= WINCONx_HAWSWP;
val |= WINCONx_BURSTLEN_16WORD;
break;
case 24:
case DRM_FORMAT_XRGB8888:
val |= WINCON0_BPPMODE_24BPP_888;
val |= WINCONx_WSWP;
val |= WINCONx_BURSTLEN_16WORD;
break;
case 32:
val |= WINCON1_BPPMODE_28BPP_A4888
case DRM_FORMAT_ARGB8888:
val |= WINCON1_BPPMODE_25BPP_A1888
| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
val |= WINCONx_WSWP;
val |= WINCONx_BURSTLEN_16WORD;
......@@ -746,45 +745,54 @@ static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
drm_iommu_detach_device(drm_dev, dev);
}
static int fimd_calc_clkdiv(struct fimd_context *ctx,
struct fb_videomode *timing)
static int fimd_configure_clocks(struct fimd_context *ctx, struct device *dev)
{
unsigned long clk = clk_get_rate(ctx->lcd_clk);
u32 retrace;
u32 clkdiv;
u32 best_framerate = 0;
u32 framerate;
retrace = timing->left_margin + timing->hsync_len +
timing->right_margin + timing->xres;
retrace *= timing->upper_margin + timing->vsync_len +
timing->lower_margin + timing->yres;
/* default framerate is 60Hz */
if (!timing->refresh)
timing->refresh = 60;
clk /= retrace;
for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
int tmp;
/* get best framerate */
framerate = clk / clkdiv;
tmp = timing->refresh - framerate;
if (tmp < 0) {
best_framerate = framerate;
continue;
} else {
if (!best_framerate)
best_framerate = framerate;
else if (tmp < (best_framerate - framerate))
best_framerate = framerate;
break;
struct videomode *vm = &ctx->panel.vm;
unsigned long clk;
ctx->bus_clk = devm_clk_get(dev, "fimd");
if (IS_ERR(ctx->bus_clk)) {
dev_err(dev, "failed to get bus clock\n");
return PTR_ERR(ctx->bus_clk);
}
ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
if (IS_ERR(ctx->lcd_clk)) {
dev_err(dev, "failed to get lcd clock\n");
return PTR_ERR(ctx->lcd_clk);
}
clk = clk_get_rate(ctx->lcd_clk);
if (clk == 0) {
dev_err(dev, "error getting sclk_fimd clock rate\n");
return -EINVAL;
}
if (vm->pixelclock == 0) {
unsigned long c;
c = vm->hactive + vm->hback_porch + vm->hfront_porch +
vm->hsync_len;
c *= vm->vactive + vm->vback_porch + vm->vfront_porch +
vm->vsync_len;
vm->pixelclock = c * FIMD_DEFAULT_FRAMERATE;
if (vm->pixelclock == 0) {
dev_err(dev, "incorrect display timings\n");
return -EINVAL;
}
dev_warn(dev, "pixel clock recalculated to %luHz (%dHz frame rate)\n",
vm->pixelclock, FIMD_DEFAULT_FRAMERATE);
}
ctx->clkdiv = DIV_ROUND_UP(clk, vm->pixelclock);
if (ctx->clkdiv > 256) {
dev_warn(dev, "calculated pixel clock divider too high (%u), lowered to 256\n",
ctx->clkdiv);
ctx->clkdiv = 256;
}
vm->pixelclock = clk / ctx->clkdiv;
DRM_DEBUG_KMS("pixel clock = %lu, clkdiv = %d\n", vm->pixelclock,
ctx->clkdiv);
return clkdiv;
return 0;
}
static void fimd_clear_win(struct fimd_context *ctx, int win)
......@@ -876,59 +884,53 @@ static int fimd_activate(struct fimd_context *ctx, bool enable)
return 0;
}
static int fimd_get_platform_data(struct fimd_context *ctx, struct device *dev)
{
struct videomode *vm;
int ret;
vm = &ctx->panel.vm;
ret = of_get_videomode(dev->of_node, vm, OF_USE_NATIVE_MODE);
if (ret) {
DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
return ret;
}
if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
ctx->vidcon1 |= VIDCON1_INV_VSYNC;
if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
ctx->vidcon1 |= VIDCON1_INV_HSYNC;
if (vm->flags & DISPLAY_FLAGS_DE_LOW)
ctx->vidcon1 |= VIDCON1_INV_VDEN;
if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
ctx->vidcon1 |= VIDCON1_INV_VCLK;
return 0;
}
static int fimd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fimd_context *ctx;
struct exynos_drm_subdrv *subdrv;
struct exynos_drm_fimd_pdata *pdata;
struct exynos_drm_panel_info *panel;
struct resource *res;
int win;
int ret = -EINVAL;
if (dev->of_node) {
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
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 = dev->platform_data;
if (!pdata) {
DRM_ERROR("no platform data specified\n");
return -EINVAL;
}
}
panel = &pdata->panel;
if (!panel) {
dev_err(dev, "panel is null.\n");
return -EINVAL;
}
if (!dev->of_node)
return -ENODEV;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->bus_clk = devm_clk_get(dev, "fimd");
if (IS_ERR(ctx->bus_clk)) {
dev_err(dev, "failed to get bus clock\n");
return PTR_ERR(ctx->bus_clk);
}
ret = fimd_get_platform_data(ctx, dev);
if (ret)
return ret;
ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
if (IS_ERR(ctx->lcd_clk)) {
dev_err(dev, "failed to get lcd clock\n");
return PTR_ERR(ctx->lcd_clk);
}
ret = fimd_configure_clocks(ctx, dev);
if (ret)
return ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -952,10 +954,6 @@ static int fimd_probe(struct platform_device *pdev)
}
ctx->driver_data = drm_fimd_get_driver_data(pdev);
ctx->vidcon0 = pdata->vidcon0;
ctx->vidcon1 = pdata->vidcon1;
ctx->default_win = pdata->default_win;
ctx->panel = panel;
DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
atomic_set(&ctx->wait_vsync_event, 0);
......@@ -973,12 +971,6 @@ static int fimd_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
ctx->clkdiv = fimd_calc_clkdiv(ctx, &panel->timing);
panel->timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
panel->timing.pixclock, ctx->clkdiv);
for (win = 0; win < WINDOWS_NR; win++)
fimd_clear_win(ctx, win);
......@@ -1067,20 +1059,6 @@ static int fimd_runtime_resume(struct device *dev)
}
#endif
static struct platform_device_id fimd_driver_ids[] = {
{
.name = "s3c64xx-fb",
.driver_data = (unsigned long)&s3c64xx_fimd_driver_data,
}, {
.name = "exynos4-fb",
.driver_data = (unsigned long)&exynos4_fimd_driver_data,
}, {
.name = "exynos5-fb",
.driver_data = (unsigned long)&exynos5_fimd_driver_data,
},
{},
};
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)
......@@ -1089,11 +1067,10 @@ static const struct dev_pm_ops fimd_pm_ops = {
struct platform_driver fimd_driver = {
.probe = fimd_probe,
.remove = fimd_remove,
.id_table = fimd_driver_ids,
.driver = {
.name = "exynos4-fb",
.owner = THIS_MODULE,
.pm = &fimd_pm_ops,
.of_match_table = of_match_ptr(fimd_driver_dt_match),
.of_match_table = fimd_driver_dt_match,
},
};
......@@ -23,6 +23,7 @@
#include <drm/drmP.h>
#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_g2d.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h"
......@@ -446,10 +447,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
}
g2d_userptr = kzalloc(sizeof(*g2d_userptr), GFP_KERNEL);
if (!g2d_userptr) {
DRM_ERROR("failed to allocate g2d_userptr.\n");
if (!g2d_userptr)
return ERR_PTR(-ENOMEM);
}
atomic_set(&g2d_userptr->refcount, 1);
......@@ -499,7 +498,6 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt) {
DRM_ERROR("failed to allocate sg table.\n");
ret = -ENOMEM;
goto err_free_userptr;
}
......@@ -808,17 +806,8 @@ static void g2d_dma_start(struct g2d_data *g2d,
int ret;
ret = pm_runtime_get_sync(g2d->dev);
if (ret < 0) {
dev_warn(g2d->dev, "failed pm power on.\n");
return;
}
ret = clk_prepare_enable(g2d->gate_clk);
if (ret < 0) {
dev_warn(g2d->dev, "failed to enable clock.\n");
pm_runtime_put_sync(g2d->dev);
if (ret < 0)
return;
}
writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR);
writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND);
......@@ -871,7 +860,6 @@ static void g2d_runqueue_worker(struct work_struct *work)
runqueue_work);
mutex_lock(&g2d->runqueue_mutex);
clk_disable_unprepare(g2d->gate_clk);
pm_runtime_put_sync(g2d->dev);
complete(&g2d->runqueue_node->complete);
......@@ -1096,8 +1084,6 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
e = kzalloc(sizeof(*node->event), GFP_KERNEL);
if (!e) {
dev_err(dev, "failed to allocate event\n");
spin_lock_irqsave(&drm_dev->event_lock, flags);
file->event_space += sizeof(e->event);
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
......@@ -1327,10 +1313,8 @@ static int g2d_open(struct drm_device *drm_dev, struct device *dev,
struct exynos_drm_g2d_private *g2d_priv;
g2d_priv = kzalloc(sizeof(*g2d_priv), GFP_KERNEL);
if (!g2d_priv) {
dev_err(dev, "failed to allocate g2d private data\n");
if (!g2d_priv)
return -ENOMEM;
}
g2d_priv->dev = dev;
file_priv->g2d_priv = g2d_priv;
......@@ -1386,10 +1370,8 @@ static int g2d_probe(struct platform_device *pdev)
int ret;
g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL);
if (!g2d) {
dev_err(dev, "failed to allocate driver data\n");
if (!g2d)
return -ENOMEM;
}
g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",
sizeof(struct g2d_runqueue_node), 0, 0, NULL);
......@@ -1524,14 +1506,38 @@ static int g2d_resume(struct device *dev)
}
#endif
static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
#ifdef CONFIG_PM_RUNTIME
static int g2d_runtime_suspend(struct device *dev)
{
struct g2d_data *g2d = dev_get_drvdata(dev);
clk_disable_unprepare(g2d->gate_clk);
return 0;
}
static int g2d_runtime_resume(struct device *dev)
{
struct g2d_data *g2d = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(g2d->gate_clk);
if (ret < 0)
dev_warn(dev, "failed to enable clock.\n");
return ret;
}
#endif
static const struct dev_pm_ops g2d_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(g2d_suspend, g2d_resume)
SET_RUNTIME_PM_OPS(g2d_runtime_suspend, g2d_runtime_resume, NULL)
};
#ifdef CONFIG_OF
static const struct of_device_id exynos_g2d_match[] = {
{ .compatible = "samsung,exynos5250-g2d" },
{},
};
#endif
struct platform_driver g2d_driver = {
.probe = g2d_probe,
......@@ -1540,6 +1546,6 @@ struct platform_driver g2d_driver = {
.name = "s5p-g2d",
.owner = THIS_MODULE,
.pm = &g2d_pm_ops,
.of_match_table = of_match_ptr(exynos_g2d_match),
.of_match_table = exynos_g2d_match,
},
};
......@@ -18,6 +18,7 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_buf.h"
#include "exynos_drm_iommu.h"
static unsigned int convert_to_vm_err_msg(int msg)
{
......@@ -191,10 +192,8 @@ struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
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");
if (!exynos_gem_obj)
return NULL;
}
exynos_gem_obj->size = size;
obj = &exynos_gem_obj->base;
......@@ -668,6 +667,18 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG |
EXYNOS_BO_WC, args->size);
/*
* If physically contiguous memory allocation fails and if IOMMU is
* supported then try to get buffer from non physically contiguous
* memory area.
*/
if (IS_ERR(exynos_gem_obj) && is_drm_iommu_supported(dev)) {
dev_warn(dev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
exynos_gem_obj = exynos_drm_gem_create(dev,
EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC,
args->size);
}
if (IS_ERR(exynos_gem_obj))
return PTR_ERR(exynos_gem_obj);
......
......@@ -20,6 +20,7 @@
#include <drm/drmP.h>
#include <drm/exynos_drm.h>
#include "regs-gsc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h"
#include "exynos_drm_gsc.h"
......@@ -1337,10 +1338,8 @@ static int gsc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
struct drm_exynos_ipp_prop_list *prop_list;
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
if (!prop_list) {
DRM_ERROR("failed to alloc property list.\n");
if (!prop_list)
return -ENOMEM;
}
prop_list->version = 1;
prop_list->writeback = 1;
......
......@@ -403,10 +403,8 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev)
struct drm_hdmi_context *ctx;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx) {
DRM_LOG_KMS("failed to alloc common hdmi context.\n");
if (!ctx)
return -ENOMEM;
}
subdrv = &ctx->subdrv;
......
......@@ -47,10 +47,16 @@ int drm_create_iommu_mapping(struct drm_device *drm_dev)
dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
GFP_KERNEL);
if (!dev->dma_parms)
goto error;
dma_set_max_seg_size(dev, 0xffffffffu);
dev->archdata.mapping = mapping;
return 0;
error:
arm_iommu_release_mapping(mapping);
return -ENOMEM;
}
/*
......@@ -91,6 +97,9 @@ int drm_iommu_attach_device(struct drm_device *drm_dev,
subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev,
sizeof(*subdrv_dev->dma_parms),
GFP_KERNEL);
if (!subdrv_dev->dma_parms)
return -ENOMEM;
dma_set_max_seg_size(subdrv_dev, 0xffffffffu);
ret = arm_iommu_attach_device(subdrv_dev, dev->archdata.mapping);
......
......@@ -408,10 +408,8 @@ static struct drm_exynos_ipp_cmd_work *ipp_create_cmd_work(void)
struct drm_exynos_ipp_cmd_work *cmd_work;
cmd_work = kzalloc(sizeof(*cmd_work), GFP_KERNEL);
if (!cmd_work) {
DRM_ERROR("failed to alloc cmd_work.\n");
if (!cmd_work)
return ERR_PTR(-ENOMEM);
}
INIT_WORK((struct work_struct *)cmd_work, ipp_sched_cmd);
......@@ -423,10 +421,8 @@ static struct drm_exynos_ipp_event_work *ipp_create_event_work(void)
struct drm_exynos_ipp_event_work *event_work;
event_work = kzalloc(sizeof(*event_work), GFP_KERNEL);
if (!event_work) {
DRM_ERROR("failed to alloc event_work.\n");
if (!event_work)
return ERR_PTR(-ENOMEM);
}
INIT_WORK((struct work_struct *)event_work, ipp_sched_event);
......@@ -482,10 +478,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
/* allocate command node */
c_node = kzalloc(sizeof(*c_node), GFP_KERNEL);
if (!c_node) {
DRM_ERROR("failed to allocate map node.\n");
if (!c_node)
return -ENOMEM;
}
/* create property id */
ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node,
......@@ -694,10 +688,8 @@ static struct drm_exynos_ipp_mem_node
mutex_lock(&c_node->mem_lock);
m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
if (!m_node) {
DRM_ERROR("failed to allocate queue node.\n");
if (!m_node)
goto err_unlock;
}
/* clear base address for error handling */
memset(&buf_info, 0x0, sizeof(buf_info));
......@@ -798,9 +790,7 @@ static int ipp_get_event(struct drm_device *drm_dev,
DRM_DEBUG_KMS("ops_id[%d]buf_id[%d]\n", qbuf->ops_id, qbuf->buf_id);
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e) {
DRM_ERROR("failed to allocate event.\n");
spin_lock_irqsave(&drm_dev->event_lock, flags);
file->event_space += sizeof(e->event);
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
......@@ -1780,10 +1770,8 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
struct exynos_drm_ipp_private *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
DRM_ERROR("failed to allocate priv.\n");
if (!priv)
return -ENOMEM;
}
priv->dev = dev;
file_priv->ipp_priv = priv;
......
......@@ -16,6 +16,7 @@
#include "exynos_drm_encoder.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_plane.h"
#define to_exynos_plane(x) container_of(x, struct exynos_plane, base)
......@@ -264,10 +265,8 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
int err;
exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
if (!exynos_plane) {
DRM_ERROR("failed to allocate plane\n");
if (!exynos_plane)
return NULL;
}
err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs,
&exynos_plane_funcs, formats, ARRAY_SIZE(formats),
......
......@@ -21,6 +21,7 @@
#include <drm/exynos_drm.h>
#include "regs-rotator.h"
#include "exynos_drm.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h"
/*
......@@ -471,10 +472,8 @@ static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
struct drm_exynos_ipp_prop_list *prop_list;
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
if (!prop_list) {
DRM_ERROR("failed to alloc property list.\n");
if (!prop_list)
return -ENOMEM;
}
prop_list->version = 1;
prop_list->flip = (1 << EXYNOS_DRM_FLIP_VERTICAL) |
......@@ -631,21 +630,96 @@ static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
return 0;
}
static struct rot_limit_table rot_limit_tbl_4210 = {
.ycbcr420_2p = {
.min_w = 32,
.min_h = 32,
.max_w = SZ_64K,
.max_h = SZ_64K,
.align = 3,
},
.rgb888 = {
.min_w = 8,
.min_h = 8,
.max_w = SZ_16K,
.max_h = SZ_16K,
.align = 2,
},
};
static struct rot_limit_table rot_limit_tbl_4x12 = {
.ycbcr420_2p = {
.min_w = 32,
.min_h = 32,
.max_w = SZ_32K,
.max_h = SZ_32K,
.align = 3,
},
.rgb888 = {
.min_w = 8,
.min_h = 8,
.max_w = SZ_8K,
.max_h = SZ_8K,
.align = 2,
},
};
static struct rot_limit_table rot_limit_tbl_5250 = {
.ycbcr420_2p = {
.min_w = 32,
.min_h = 32,
.max_w = SZ_32K,
.max_h = SZ_32K,
.align = 3,
},
.rgb888 = {
.min_w = 8,
.min_h = 8,
.max_w = SZ_8K,
.max_h = SZ_8K,
.align = 1,
},
};
static const struct of_device_id exynos_rotator_match[] = {
{
.compatible = "samsung,exynos4210-rotator",
.data = &rot_limit_tbl_4210,
},
{
.compatible = "samsung,exynos4212-rotator",
.data = &rot_limit_tbl_4x12,
},
{
.compatible = "samsung,exynos5250-rotator",
.data = &rot_limit_tbl_5250,
},
{},
};
static int rotator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rot_context *rot;
struct exynos_drm_ippdrv *ippdrv;
const struct of_device_id *match;
int ret;
if (!dev->of_node) {
dev_err(dev, "cannot find of_node.\n");
return -ENODEV;
}
rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL);
if (!rot) {
dev_err(dev, "failed to allocate rot\n");
if (!rot)
return -ENOMEM;
}
rot->limit_tbl = (struct rot_limit_table *)
platform_get_device_id(pdev)->driver_data;
match = of_match_node(exynos_rotator_match, dev->of_node);
if (!match) {
dev_err(dev, "failed to match node\n");
return -ENODEV;
}
rot->limit_tbl = (struct rot_limit_table *)match->data;
rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rot->regs = devm_ioremap_resource(dev, rot->regs_res);
......@@ -717,31 +791,6 @@ static int rotator_remove(struct platform_device *pdev)
return 0;
}
static struct rot_limit_table rot_limit_tbl = {
.ycbcr420_2p = {
.min_w = 32,
.min_h = 32,
.max_w = SZ_32K,
.max_h = SZ_32K,
.align = 3,
},
.rgb888 = {
.min_w = 8,
.min_h = 8,
.max_w = SZ_8K,
.max_h = SZ_8K,
.align = 2,
},
};
static struct platform_device_id rotator_driver_ids[] = {
{
.name = "exynos-rot",
.driver_data = (unsigned long)&rot_limit_tbl,
},
{},
};
static int rotator_clk_crtl(struct rot_context *rot, bool enable)
{
if (enable) {
......@@ -803,10 +852,10 @@ static const struct dev_pm_ops rotator_pm_ops = {
struct platform_driver rotator_driver = {
.probe = rotator_probe,
.remove = rotator_remove,
.id_table = rotator_driver_ids,
.driver = {
.name = "exynos-rot",
.owner = THIS_MODULE,
.pm = &rotator_pm_ops,
.of_match_table = exynos_rotator_match,
},
};
......@@ -23,6 +23,7 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_vidi.h"
/* vidi has totally three virtual windows. */
#define WINDOWS_NR 3
......
......@@ -32,6 +32,7 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <drm/exynos_drm.h>
......@@ -1824,10 +1825,8 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
sizeof(res->regul_bulk[0]), GFP_KERNEL);
if (!res->regul_bulk) {
DRM_ERROR("failed to get memory for regulators\n");
if (!res->regul_bulk)
goto fail;
}
for (i = 0; i < ARRAY_SIZE(supply); ++i) {
res->regul_bulk[i].supply = supply[i];
res->regul_bulk[i].consumer = NULL;
......@@ -1859,7 +1858,6 @@ void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
hdmi_hdmiphy = hdmiphy;
}
#ifdef CONFIG_OF
static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
(struct device *dev)
{
......@@ -1868,10 +1866,8 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
u32 value;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd) {
DRM_ERROR("memory allocation for pdata failed\n");
if (!pd)
goto err_data;
}
if (!of_find_property(np, "hpd-gpio", &value)) {
DRM_ERROR("no hpd gpio property found\n");
......@@ -1885,33 +1881,7 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
err_data:
return NULL;
}
#else
static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
(struct device *dev)
{
return NULL;
}
#endif
static struct platform_device_id hdmi_driver_types[] = {
{
.name = "s5pv210-hdmi",
.driver_data = HDMI_TYPE13,
}, {
.name = "exynos4-hdmi",
.driver_data = HDMI_TYPE13,
}, {
.name = "exynos4-hdmi14",
.driver_data = HDMI_TYPE14,
}, {
.name = "exynos5-hdmi",
.driver_data = HDMI_TYPE14,
}, {
/* end node */
}
};
#ifdef CONFIG_OF
static struct of_device_id hdmi_match_types[] = {
{
.compatible = "samsung,exynos5-hdmi",
......@@ -1923,7 +1893,6 @@ static struct of_device_id hdmi_match_types[] = {
/* end node */
}
};
#endif
static int hdmi_probe(struct platform_device *pdev)
{
......@@ -1932,36 +1901,23 @@ static int hdmi_probe(struct platform_device *pdev)
struct hdmi_context *hdata;
struct s5p_hdmi_platform_data *pdata;
struct resource *res;
const struct of_device_id *match;
int ret;
if (dev->of_node) {
pdata = drm_hdmi_dt_parse_pdata(dev);
if (IS_ERR(pdata)) {
DRM_ERROR("failed to parse dt\n");
return PTR_ERR(pdata);
}
} else {
pdata = dev->platform_data;
}
if (!dev->of_node)
return -ENODEV;
if (!pdata) {
DRM_ERROR("no platform data specified\n");
pdata = drm_hdmi_dt_parse_pdata(dev);
if (!pdata)
return -EINVAL;
}
drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
GFP_KERNEL);
if (!drm_hdmi_ctx) {
DRM_ERROR("failed to allocate common hdmi context.\n");
drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL);
if (!drm_hdmi_ctx)
return -ENOMEM;
}
hdata = devm_kzalloc(dev, sizeof(struct hdmi_context),
GFP_KERNEL);
if (!hdata) {
DRM_ERROR("out of memory\n");
hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
if (!hdata)
return -ENOMEM;
}
mutex_init(&hdata->hdmi_mutex);
......@@ -1970,23 +1926,15 @@ static int hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drm_hdmi_ctx);
if (dev->of_node) {
const struct of_device_id *match;
match = of_match_node(of_match_ptr(hdmi_match_types),
dev->of_node);
if (match == NULL)
return -ENODEV;
hdata->type = (enum hdmi_type)match->data;
} else {
hdata->type = (enum hdmi_type)platform_get_device_id
(pdev)->driver_data;
}
match = of_match_node(hdmi_match_types, dev->of_node);
if (!match)
return -ENODEV;
hdata->type = (enum hdmi_type)match->data;
hdata->hpd_gpio = pdata->hpd_gpio;
hdata->dev = dev;
ret = hdmi_resources_init(hdata);
if (ret) {
DRM_ERROR("hdmi_resources_init failed\n");
return -EINVAL;
......@@ -2141,11 +2089,10 @@ static const struct dev_pm_ops hdmi_pm_ops = {
struct platform_driver hdmi_driver = {
.probe = hdmi_probe,
.remove = hdmi_remove,
.id_table = hdmi_driver_types,
.driver = {
.name = "exynos-hdmi",
.owner = THIS_MODULE,
.pm = &hdmi_pm_ops,
.of_match_table = of_match_ptr(hdmi_match_types),
.of_match_table = hdmi_match_types,
},
};
......@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include "exynos_drm_drv.h"
#include "exynos_hdmi.h"
......@@ -39,13 +40,6 @@ static int hdmiphy_remove(struct i2c_client *client)
return 0;
}
static const struct i2c_device_id hdmiphy_id[] = {
{ "s5p_hdmiphy", 0 },
{ "exynos5-hdmiphy", 0 },
{ },
};
#ifdef CONFIG_OF
static struct of_device_id hdmiphy_match_types[] = {
{
.compatible = "samsung,exynos5-hdmiphy",
......@@ -57,15 +51,13 @@ static struct of_device_id hdmiphy_match_types[] = {
/* end node */
}
};
#endif
struct i2c_driver hdmiphy_driver = {
.driver = {
.name = "exynos-hdmiphy",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(hdmiphy_match_types),
.of_match_table = hdmiphy_match_types,
},
.id_table = hdmiphy_id,
.probe = hdmiphy_probe,
.remove = hdmiphy_remove,
.command = NULL,
......
......@@ -30,6 +30,7 @@
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <drm/exynos_drm.h>
......@@ -1185,16 +1186,12 @@ static int mixer_probe(struct platform_device *pdev)
drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
GFP_KERNEL);
if (!drm_hdmi_ctx) {
DRM_ERROR("failed to allocate common hdmi context.\n");
if (!drm_hdmi_ctx)
return -ENOMEM;
}
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx) {
DRM_ERROR("failed to alloc mixer context.\n");
if (!ctx)
return -ENOMEM;
}
mutex_init(&ctx->mixer_mutex);
......
......@@ -15,6 +15,7 @@
#define _EXYNOS_DRM_H_
#include <uapi/drm/exynos_drm.h>
#include <video/videomode.h>
/**
* A structure for lcd panel information.
......@@ -24,7 +25,7 @@
* @height_mm: physical size of lcd height.
*/
struct exynos_drm_panel_info {
struct fb_videomode timing;
struct videomode vm;
u32 width_mm;
u32 height_mm;
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册