Commit 86a7e122 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

   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
  ...
parents 3b28802e 6914262a
* 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 config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series" 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 DRM_KMS_HELPER
select FB_CFB_FILLRECT select FB_CFB_FILLRECT
select FB_CFB_COPYAREA select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT select FB_CFB_IMAGEBLIT
select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
select VIDEOMODE_HELPERS
help help
Choose this option if you have a Samsung SoC EXYNOS chipset. Choose this option if you have a Samsung SoC EXYNOS chipset.
If M is selected the module will be called exynosdrm. If M is selected the module will be called exynosdrm.
...@@ -24,9 +25,8 @@ config DRM_EXYNOS_DMABUF ...@@ -24,9 +25,8 @@ config DRM_EXYNOS_DMABUF
config DRM_EXYNOS_FIMD config DRM_EXYNOS_FIMD
bool "Exynos DRM 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 FB_MODE_HELPERS
select VIDEOMODE_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.
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/of.h>
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_hdmi.h" #include "exynos_hdmi.h"
...@@ -41,13 +41,6 @@ static int s5p_ddc_remove(struct i2c_client *client) ...@@ -41,13 +41,6 @@ static int s5p_ddc_remove(struct i2c_client *client)
return 0; 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[] = { static struct of_device_id hdmiddc_match_types[] = {
{ {
.compatible = "samsung,exynos5-hdmiddc", .compatible = "samsung,exynos5-hdmiddc",
...@@ -57,15 +50,13 @@ static struct of_device_id hdmiddc_match_types[] = { ...@@ -57,15 +50,13 @@ static struct of_device_id hdmiddc_match_types[] = {
/* end node */ /* end node */
} }
}; };
#endif
struct i2c_driver ddc_driver = { struct i2c_driver ddc_driver = {
.driver = { .driver = {
.name = "exynos-hdmiddc", .name = "exynos-hdmiddc",
.owner = THIS_MODULE, .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, .probe = s5p_ddc_probe,
.remove = s5p_ddc_remove, .remove = s5p_ddc_remove,
.command = NULL, .command = NULL,
......
...@@ -149,10 +149,8 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, ...@@ -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); DRM_DEBUG_KMS("desired size = 0x%x\n", size);
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer) { if (!buffer)
DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
return NULL; return NULL;
}
buffer->size = size; buffer->size = size;
return buffer; return buffer;
...@@ -161,11 +159,6 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, ...@@ -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, void exynos_drm_fini_buf(struct drm_device *dev,
struct exynos_drm_gem_buf *buffer) struct exynos_drm_gem_buf *buffer)
{ {
if (!buffer) {
DRM_DEBUG_KMS("buffer is null.\n");
return;
}
kfree(buffer); kfree(buffer);
buffer = NULL; buffer = NULL;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h" #include "exynos_drm_encoder.h"
#include "exynos_drm_connector.h"
#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
drm_connector) drm_connector)
...@@ -28,35 +29,6 @@ struct exynos_drm_connector { ...@@ -28,35 +29,6 @@ struct exynos_drm_connector {
uint32_t dpms; 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) static int exynos_drm_connector_get_modes(struct drm_connector *connector)
{ {
struct exynos_drm_connector *exynos_connector = struct exynos_drm_connector *exynos_connector =
...@@ -111,7 +83,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) ...@@ -111,7 +83,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
return 0; 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.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm; connector->display_info.height_mm = mode->height_mm;
...@@ -278,10 +252,8 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, ...@@ -278,10 +252,8 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
int err; int err;
exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL); exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
if (!exynos_connector) { if (!exynos_connector)
DRM_ERROR("failed to allocate connector\n");
return NULL; return NULL;
}
connector = &exynos_connector->drm_connector; connector = &exynos_connector->drm_connector;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h" #include "exynos_drm_encoder.h"
#include "exynos_drm_plane.h" #include "exynos_drm_plane.h"
...@@ -324,10 +325,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) ...@@ -324,10 +325,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
struct drm_crtc *crtc; struct drm_crtc *crtc;
exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
if (!exynos_crtc) { if (!exynos_crtc)
DRM_ERROR("failed to allocate exynos crtc\n");
return -ENOMEM; return -ENOMEM;
}
exynos_crtc->pipe = nr; exynos_crtc->pipe = nr;
exynos_crtc->dpms = DRM_MODE_DPMS_OFF; exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
#include "exynos_drm_dmabuf.h"
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_gem.h" #include "exynos_drm_gem.h"
...@@ -230,7 +231,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, ...@@ -230,7 +231,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer) { if (!buffer) {
DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_unmap_attach; goto err_unmap_attach;
} }
......
...@@ -47,10 +47,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) ...@@ -47,10 +47,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
int nr; int nr;
private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
if (!private) { if (!private)
DRM_ERROR("failed to allocate private\n");
return -ENOMEM; return -ENOMEM;
}
INIT_LIST_HEAD(&private->pageflip_event_list); INIT_LIST_HEAD(&private->pageflip_event_list);
dev->dev_private = (void *)private; dev->dev_private = (void *)private;
......
...@@ -324,10 +324,8 @@ exynos_drm_encoder_create(struct drm_device *dev, ...@@ -324,10 +324,8 @@ exynos_drm_encoder_create(struct drm_device *dev,
return NULL; return NULL;
exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL); exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
if (!exynos_encoder) { if (!exynos_encoder)
DRM_ERROR("failed to allocate encoder\n");
return NULL; return NULL;
}
exynos_encoder->dpms = DRM_MODE_DPMS_OFF; exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
exynos_encoder->manager = manager; exynos_encoder->manager = manager;
......
...@@ -156,10 +156,8 @@ exynos_drm_framebuffer_init(struct drm_device *dev, ...@@ -156,10 +156,8 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
} }
exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb) { if (!exynos_fb)
DRM_ERROR("failed to allocate exynos drm framebuffer\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
exynos_fb->exynos_gem_obj[0] = exynos_gem_obj; 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, ...@@ -220,10 +218,8 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
int i, ret; int i, ret;
exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb) { if (!exynos_fb)
DRM_ERROR("failed to allocate exynos drm framebuffer\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
if (!obj) { if (!obj) {
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_fb.h" #include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_gem.h" #include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
...@@ -165,8 +167,18 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, ...@@ -165,8 +167,18 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
size = mode_cmd.pitches[0] * mode_cmd.height; size = mode_cmd.pitches[0] * mode_cmd.height;
/* 0 means to allocate physically continuous memory */ exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
exynos_gem_obj = exynos_drm_gem_create(dev, 0, 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)) { if (IS_ERR(exynos_gem_obj)) {
ret = PTR_ERR(exynos_gem_obj); ret = PTR_ERR(exynos_gem_obj);
goto err_release_framebuffer; goto err_release_framebuffer;
...@@ -236,10 +248,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev) ...@@ -236,10 +248,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
return 0; return 0;
fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
if (!fbdev) { if (!fbdev)
DRM_ERROR("failed to allocate drm fbdev.\n");
return -ENOMEM; return -ENOMEM;
}
private->fb_helper = helper = &fbdev->drm_fb_helper; private->fb_helper = helper = &fbdev->drm_fb_helper;
helper->funcs = &exynos_drm_fb_helper_funcs; helper->funcs = &exynos_drm_fb_helper_funcs;
......
...@@ -17,10 +17,12 @@ ...@@ -17,10 +17,12 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/of.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
#include "regs-fimc.h" #include "regs-fimc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h" #include "exynos_drm_ipp.h"
#include "exynos_drm_fimc.h" #include "exynos_drm_fimc.h"
...@@ -1343,10 +1345,8 @@ static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv) ...@@ -1343,10 +1345,8 @@ static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
struct drm_exynos_ipp_prop_list *prop_list; struct drm_exynos_ipp_prop_list *prop_list;
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL); prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
if (!prop_list) { if (!prop_list)
DRM_ERROR("failed to alloc property list.\n");
return -ENOMEM; return -ENOMEM;
}
prop_list->version = 1; prop_list->version = 1;
prop_list->writeback = 1; prop_list->writeback = 1;
......
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/of.h>
#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/of_display_timing.h>
#include <video/of_videomode.h>
#include <video/samsung_fimd.h> #include <video/samsung_fimd.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
...@@ -35,6 +37,8 @@ ...@@ -35,6 +37,8 @@
* CPU Interface. * CPU Interface.
*/ */
#define FIMD_DEFAULT_FRAMERATE 60
/* position control register for hardware window 0, 2 ~ 4.*/ /* position control register for hardware window 0, 2 ~ 4.*/
#define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16) #define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16)
#define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16) #define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16)
...@@ -65,11 +69,13 @@ struct fimd_driver_data { ...@@ -65,11 +69,13 @@ struct fimd_driver_data {
unsigned int has_shadowcon:1; unsigned int has_shadowcon:1;
unsigned int has_clksel:1; unsigned int has_clksel:1;
unsigned int has_limited_fmt:1;
}; };
static struct fimd_driver_data s3c64xx_fimd_driver_data = { static struct fimd_driver_data s3c64xx_fimd_driver_data = {
.timing_base = 0x0, .timing_base = 0x0,
.has_clksel = 1, .has_clksel = 1,
.has_limited_fmt = 1,
}; };
static struct fimd_driver_data exynos4_fimd_driver_data = { static struct fimd_driver_data exynos4_fimd_driver_data = {
...@@ -90,6 +96,7 @@ struct fimd_win_data { ...@@ -90,6 +96,7 @@ struct fimd_win_data {
unsigned int fb_width; unsigned int fb_width;
unsigned int fb_height; unsigned int fb_height;
unsigned int bpp; unsigned int bpp;
unsigned int pixel_format;
dma_addr_t dma_addr; dma_addr_t dma_addr;
unsigned int buf_offsize; unsigned int buf_offsize;
unsigned int line_size; /* bytes */ unsigned int line_size; /* bytes */
...@@ -115,11 +122,10 @@ struct fimd_context { ...@@ -115,11 +122,10 @@ struct fimd_context {
wait_queue_head_t wait_vsync_queue; wait_queue_head_t wait_vsync_queue;
atomic_t wait_vsync_event; atomic_t wait_vsync_event;
struct exynos_drm_panel_info *panel; struct exynos_drm_panel_info panel;
struct fimd_driver_data *driver_data; struct fimd_driver_data *driver_data;
}; };
#ifdef CONFIG_OF
static const struct of_device_id fimd_driver_dt_match[] = { static const struct of_device_id fimd_driver_dt_match[] = {
{ .compatible = "samsung,s3c6400-fimd", { .compatible = "samsung,s3c6400-fimd",
.data = &s3c64xx_fimd_driver_data }, .data = &s3c64xx_fimd_driver_data },
...@@ -129,21 +135,14 @@ static const struct of_device_id fimd_driver_dt_match[] = { ...@@ -129,21 +135,14 @@ static const struct of_device_id fimd_driver_dt_match[] = {
.data = &exynos5_fimd_driver_data }, .data = &exynos5_fimd_driver_data },
{}, {},
}; };
#endif
static inline struct fimd_driver_data *drm_fimd_get_driver_data( static inline struct fimd_driver_data *drm_fimd_get_driver_data(
struct platform_device *pdev) struct platform_device *pdev)
{ {
#ifdef CONFIG_OF
const struct of_device_id *of_id = const struct of_device_id *of_id =
of_match_device(fimd_driver_dt_match, &pdev->dev); of_match_device(fimd_driver_dt_match, &pdev->dev);
if (of_id)
return (struct fimd_driver_data *)of_id->data; return (struct fimd_driver_data *)of_id->data;
#endif
return (struct fimd_driver_data *)
platform_get_device_id(pdev)->driver_data;
} }
static bool fimd_display_is_connected(struct device *dev) static bool fimd_display_is_connected(struct device *dev)
...@@ -157,7 +156,7 @@ static void *fimd_get_panel(struct device *dev) ...@@ -157,7 +156,7 @@ static void *fimd_get_panel(struct device *dev)
{ {
struct fimd_context *ctx = get_fimd_context(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) 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) ...@@ -237,8 +236,8 @@ static void fimd_apply(struct device *subdrv_dev)
static void fimd_commit(struct device *dev) static void fimd_commit(struct device *dev)
{ {
struct fimd_context *ctx = get_fimd_context(dev); struct fimd_context *ctx = get_fimd_context(dev);
struct exynos_drm_panel_info *panel = ctx->panel; struct exynos_drm_panel_info *panel = &ctx->panel;
struct fb_videomode *timing = &panel->timing; struct videomode *vm = &panel->vm;
struct fimd_driver_data *driver_data; struct fimd_driver_data *driver_data;
u32 val; u32 val;
...@@ -250,22 +249,22 @@ static void fimd_commit(struct device *dev) ...@@ -250,22 +249,22 @@ static void fimd_commit(struct device *dev)
writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1); writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
/* setup vertical timing values. */ /* setup vertical timing values. */
val = VIDTCON0_VBPD(timing->upper_margin - 1) | val = VIDTCON0_VBPD(vm->vback_porch - 1) |
VIDTCON0_VFPD(timing->lower_margin - 1) | VIDTCON0_VFPD(vm->vfront_porch - 1) |
VIDTCON0_VSPW(timing->vsync_len - 1); VIDTCON0_VSPW(vm->vsync_len - 1);
writel(val, ctx->regs + driver_data->timing_base + VIDTCON0); writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
/* setup horizontal timing values. */ /* setup horizontal timing values. */
val = VIDTCON1_HBPD(timing->left_margin - 1) | val = VIDTCON1_HBPD(vm->hback_porch - 1) |
VIDTCON1_HFPD(timing->right_margin - 1) | VIDTCON1_HFPD(vm->hfront_porch - 1) |
VIDTCON1_HSPW(timing->hsync_len - 1); VIDTCON1_HSPW(vm->hsync_len - 1);
writel(val, ctx->regs + driver_data->timing_base + VIDTCON1); writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
/* setup horizontal and vertical display size. */ /* setup horizontal and vertical display size. */
val = VIDTCON2_LINEVAL(timing->yres - 1) | val = VIDTCON2_LINEVAL(vm->vactive - 1) |
VIDTCON2_HOZVAL(timing->xres - 1) | VIDTCON2_HOZVAL(vm->hactive - 1) |
VIDTCON2_LINEVAL_E(timing->yres - 1) | VIDTCON2_LINEVAL_E(vm->vactive - 1) |
VIDTCON2_HOZVAL_E(timing->xres - 1); VIDTCON2_HOZVAL_E(vm->hactive - 1);
writel(val, ctx->regs + driver_data->timing_base + VIDTCON2); writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
/* setup clock source, clock divider, enable dma. */ /* setup clock source, clock divider, enable dma. */
...@@ -396,6 +395,7 @@ static void fimd_win_mode_set(struct device *dev, ...@@ -396,6 +395,7 @@ static void fimd_win_mode_set(struct device *dev,
win_data->fb_height = overlay->fb_height; win_data->fb_height = overlay->fb_height;
win_data->dma_addr = overlay->dma_addr[0] + offset; win_data->dma_addr = overlay->dma_addr[0] + offset;
win_data->bpp = overlay->bpp; win_data->bpp = overlay->bpp;
win_data->pixel_format = overlay->pixel_format;
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
(overlay->bpp >> 3); (overlay->bpp >> 3);
win_data->line_size = 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) ...@@ -417,39 +417,38 @@ static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
val = WINCONx_ENWIN; val = WINCONx_ENWIN;
switch (win_data->bpp) { /*
case 1: * In case of s3c64xx, window 0 doesn't support alpha channel.
val |= WINCON0_BPPMODE_1BPP; * So the request format is ARGB8888 then change it to XRGB8888.
val |= WINCONx_BITSWP; */
val |= WINCONx_BURSTLEN_4WORD; if (ctx->driver_data->has_limited_fmt && !win) {
break; if (win_data->pixel_format == DRM_FORMAT_ARGB8888)
case 2: win_data->pixel_format = DRM_FORMAT_XRGB8888;
val |= WINCON0_BPPMODE_2BPP; }
val |= WINCONx_BITSWP;
val |= WINCONx_BURSTLEN_8WORD; switch (win_data->pixel_format) {
break; case DRM_FORMAT_C8:
case 4:
val |= WINCON0_BPPMODE_4BPP;
val |= WINCONx_BITSWP;
val |= WINCONx_BURSTLEN_8WORD;
break;
case 8:
val |= WINCON0_BPPMODE_8BPP_PALETTE; val |= WINCON0_BPPMODE_8BPP_PALETTE;
val |= WINCONx_BURSTLEN_8WORD; val |= WINCONx_BURSTLEN_8WORD;
val |= WINCONx_BYTSWP; val |= WINCONx_BYTSWP;
break; 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 |= WINCON0_BPPMODE_16BPP_565;
val |= WINCONx_HAWSWP; val |= WINCONx_HAWSWP;
val |= WINCONx_BURSTLEN_16WORD; val |= WINCONx_BURSTLEN_16WORD;
break; break;
case 24: case DRM_FORMAT_XRGB8888:
val |= WINCON0_BPPMODE_24BPP_888; val |= WINCON0_BPPMODE_24BPP_888;
val |= WINCONx_WSWP; val |= WINCONx_WSWP;
val |= WINCONx_BURSTLEN_16WORD; val |= WINCONx_BURSTLEN_16WORD;
break; break;
case 32: case DRM_FORMAT_ARGB8888:
val |= WINCON1_BPPMODE_28BPP_A4888 val |= WINCON1_BPPMODE_25BPP_A1888
| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
val |= WINCONx_WSWP; val |= WINCONx_WSWP;
val |= WINCONx_BURSTLEN_16WORD; val |= WINCONx_BURSTLEN_16WORD;
...@@ -746,45 +745,54 @@ static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev) ...@@ -746,45 +745,54 @@ static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
drm_iommu_detach_device(drm_dev, dev); drm_iommu_detach_device(drm_dev, dev);
} }
static int fimd_calc_clkdiv(struct fimd_context *ctx, static int fimd_configure_clocks(struct fimd_context *ctx, struct device *dev)
struct fb_videomode *timing)
{ {
unsigned long clk = clk_get_rate(ctx->lcd_clk); struct videomode *vm = &ctx->panel.vm;
u32 retrace; unsigned long clk;
u32 clkdiv;
u32 best_framerate = 0; ctx->bus_clk = devm_clk_get(dev, "fimd");
u32 framerate; if (IS_ERR(ctx->bus_clk)) {
dev_err(dev, "failed to get bus clock\n");
retrace = timing->left_margin + timing->hsync_len + return PTR_ERR(ctx->bus_clk);
timing->right_margin + timing->xres; }
retrace *= timing->upper_margin + timing->vsync_len +
timing->lower_margin + timing->yres; ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
if (IS_ERR(ctx->lcd_clk)) {
/* default framerate is 60Hz */ dev_err(dev, "failed to get lcd clock\n");
if (!timing->refresh) return PTR_ERR(ctx->lcd_clk);
timing->refresh = 60; }
clk /= retrace; clk = clk_get_rate(ctx->lcd_clk);
if (clk == 0) {
for (clkdiv = 1; clkdiv < 0x100; clkdiv++) { dev_err(dev, "error getting sclk_fimd clock rate\n");
int tmp; return -EINVAL;
}
/* get best framerate */
framerate = clk / clkdiv; if (vm->pixelclock == 0) {
tmp = timing->refresh - framerate; unsigned long c;
if (tmp < 0) { c = vm->hactive + vm->hback_porch + vm->hfront_porch +
best_framerate = framerate; vm->hsync_len;
continue; c *= vm->vactive + vm->vback_porch + vm->vfront_porch +
} else { vm->vsync_len;
if (!best_framerate) vm->pixelclock = c * FIMD_DEFAULT_FRAMERATE;
best_framerate = framerate; if (vm->pixelclock == 0) {
else if (tmp < (best_framerate - framerate)) dev_err(dev, "incorrect display timings\n");
best_framerate = framerate; return -EINVAL;
break;
} }
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) 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) ...@@ -876,59 +884,53 @@ static int fimd_activate(struct fimd_context *ctx, bool enable)
return 0; 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) static int fimd_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct fimd_context *ctx; struct fimd_context *ctx;
struct exynos_drm_subdrv *subdrv; struct exynos_drm_subdrv *subdrv;
struct exynos_drm_fimd_pdata *pdata;
struct exynos_drm_panel_info *panel;
struct resource *res; struct resource *res;
int win; int win;
int ret = -EINVAL; int ret = -EINVAL;
if (dev->of_node) { if (!dev->of_node)
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); return -ENODEV;
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;
}
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx) if (!ctx)
return -ENOMEM; return -ENOMEM;
ctx->bus_clk = devm_clk_get(dev, "fimd"); ret = fimd_get_platform_data(ctx, dev);
if (IS_ERR(ctx->bus_clk)) { if (ret)
dev_err(dev, "failed to get bus clock\n"); return ret;
return PTR_ERR(ctx->bus_clk);
}
ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd"); ret = fimd_configure_clocks(ctx, dev);
if (IS_ERR(ctx->lcd_clk)) { if (ret)
dev_err(dev, "failed to get lcd clock\n"); return ret;
return PTR_ERR(ctx->lcd_clk);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -952,10 +954,6 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -952,10 +954,6 @@ static int fimd_probe(struct platform_device *pdev)
} }
ctx->driver_data = drm_fimd_get_driver_data(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); DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
atomic_set(&ctx->wait_vsync_event, 0); atomic_set(&ctx->wait_vsync_event, 0);
...@@ -973,12 +971,6 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -973,12 +971,6 @@ static int fimd_probe(struct platform_device *pdev)
pm_runtime_enable(dev); pm_runtime_enable(dev);
pm_runtime_get_sync(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++) for (win = 0; win < WINDOWS_NR; win++)
fimd_clear_win(ctx, win); fimd_clear_win(ctx, win);
...@@ -1067,20 +1059,6 @@ static int fimd_runtime_resume(struct device *dev) ...@@ -1067,20 +1059,6 @@ static int fimd_runtime_resume(struct device *dev)
} }
#endif #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 = { static const struct dev_pm_ops fimd_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume) SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL) SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
...@@ -1089,11 +1067,10 @@ static const struct dev_pm_ops fimd_pm_ops = { ...@@ -1089,11 +1067,10 @@ static const struct dev_pm_ops fimd_pm_ops = {
struct platform_driver fimd_driver = { struct platform_driver fimd_driver = {
.probe = fimd_probe, .probe = fimd_probe,
.remove = fimd_remove, .remove = fimd_remove,
.id_table = fimd_driver_ids,
.driver = { .driver = {
.name = "exynos4-fb", .name = "exynos4-fb",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &fimd_pm_ops, .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 @@ ...@@ -23,6 +23,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_g2d.h"
#include "exynos_drm_gem.h" #include "exynos_drm_gem.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
...@@ -446,10 +447,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, ...@@ -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); g2d_userptr = kzalloc(sizeof(*g2d_userptr), GFP_KERNEL);
if (!g2d_userptr) { if (!g2d_userptr)
DRM_ERROR("failed to allocate g2d_userptr.\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
atomic_set(&g2d_userptr->refcount, 1); atomic_set(&g2d_userptr->refcount, 1);
...@@ -499,7 +498,6 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, ...@@ -499,7 +498,6 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt) { if (!sgt) {
DRM_ERROR("failed to allocate sg table.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_free_userptr; goto err_free_userptr;
} }
...@@ -808,17 +806,8 @@ static void g2d_dma_start(struct g2d_data *g2d, ...@@ -808,17 +806,8 @@ static void g2d_dma_start(struct g2d_data *g2d,
int ret; int ret;
ret = pm_runtime_get_sync(g2d->dev); ret = pm_runtime_get_sync(g2d->dev);
if (ret < 0) { 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);
return; return;
}
writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR);
writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND);
...@@ -871,7 +860,6 @@ static void g2d_runqueue_worker(struct work_struct *work) ...@@ -871,7 +860,6 @@ static void g2d_runqueue_worker(struct work_struct *work)
runqueue_work); runqueue_work);
mutex_lock(&g2d->runqueue_mutex); mutex_lock(&g2d->runqueue_mutex);
clk_disable_unprepare(g2d->gate_clk);
pm_runtime_put_sync(g2d->dev); pm_runtime_put_sync(g2d->dev);
complete(&g2d->runqueue_node->complete); complete(&g2d->runqueue_node->complete);
...@@ -1096,8 +1084,6 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, ...@@ -1096,8 +1084,6 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
e = kzalloc(sizeof(*node->event), GFP_KERNEL); e = kzalloc(sizeof(*node->event), GFP_KERNEL);
if (!e) { if (!e) {
dev_err(dev, "failed to allocate event\n");
spin_lock_irqsave(&drm_dev->event_lock, flags); spin_lock_irqsave(&drm_dev->event_lock, flags);
file->event_space += sizeof(e->event); file->event_space += sizeof(e->event);
spin_unlock_irqrestore(&drm_dev->event_lock, flags); spin_unlock_irqrestore(&drm_dev->event_lock, flags);
...@@ -1327,10 +1313,8 @@ static int g2d_open(struct drm_device *drm_dev, struct device *dev, ...@@ -1327,10 +1313,8 @@ static int g2d_open(struct drm_device *drm_dev, struct device *dev,
struct exynos_drm_g2d_private *g2d_priv; struct exynos_drm_g2d_private *g2d_priv;
g2d_priv = kzalloc(sizeof(*g2d_priv), GFP_KERNEL); g2d_priv = kzalloc(sizeof(*g2d_priv), GFP_KERNEL);
if (!g2d_priv) { if (!g2d_priv)
dev_err(dev, "failed to allocate g2d private data\n");
return -ENOMEM; return -ENOMEM;
}
g2d_priv->dev = dev; g2d_priv->dev = dev;
file_priv->g2d_priv = g2d_priv; file_priv->g2d_priv = g2d_priv;
...@@ -1386,10 +1370,8 @@ static int g2d_probe(struct platform_device *pdev) ...@@ -1386,10 +1370,8 @@ static int g2d_probe(struct platform_device *pdev)
int ret; int ret;
g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL); g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL);
if (!g2d) { if (!g2d)
dev_err(dev, "failed to allocate driver data\n");
return -ENOMEM; return -ENOMEM;
}
g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab", g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",
sizeof(struct g2d_runqueue_node), 0, 0, NULL); sizeof(struct g2d_runqueue_node), 0, 0, NULL);
...@@ -1524,14 +1506,38 @@ static int g2d_resume(struct device *dev) ...@@ -1524,14 +1506,38 @@ static int g2d_resume(struct device *dev)
} }
#endif #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[] = { static const struct of_device_id exynos_g2d_match[] = {
{ .compatible = "samsung,exynos5250-g2d" }, { .compatible = "samsung,exynos5250-g2d" },
{}, {},
}; };
#endif
struct platform_driver g2d_driver = { struct platform_driver g2d_driver = {
.probe = g2d_probe, .probe = g2d_probe,
...@@ -1540,6 +1546,6 @@ struct platform_driver g2d_driver = { ...@@ -1540,6 +1546,6 @@ struct platform_driver g2d_driver = {
.name = "s5p-g2d", .name = "s5p-g2d",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &g2d_pm_ops, .pm = &g2d_pm_ops,
.of_match_table = of_match_ptr(exynos_g2d_match), .of_match_table = exynos_g2d_match,
}, },
}; };
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_gem.h" #include "exynos_drm_gem.h"
#include "exynos_drm_buf.h" #include "exynos_drm_buf.h"
#include "exynos_drm_iommu.h"
static unsigned int convert_to_vm_err_msg(int msg) 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, ...@@ -191,10 +192,8 @@ struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
int ret; int ret;
exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
if (!exynos_gem_obj) { if (!exynos_gem_obj)
DRM_ERROR("failed to allocate exynos gem object\n");
return NULL; return NULL;
}
exynos_gem_obj->size = size; exynos_gem_obj->size = size;
obj = &exynos_gem_obj->base; obj = &exynos_gem_obj->base;
...@@ -668,6 +667,18 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, ...@@ -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_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG |
EXYNOS_BO_WC, args->size); 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)) if (IS_ERR(exynos_gem_obj))
return PTR_ERR(exynos_gem_obj); return PTR_ERR(exynos_gem_obj);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
#include "regs-gsc.h" #include "regs-gsc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h" #include "exynos_drm_ipp.h"
#include "exynos_drm_gsc.h" #include "exynos_drm_gsc.h"
...@@ -1337,10 +1338,8 @@ static int gsc_init_prop_list(struct exynos_drm_ippdrv *ippdrv) ...@@ -1337,10 +1338,8 @@ static int gsc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
struct drm_exynos_ipp_prop_list *prop_list; struct drm_exynos_ipp_prop_list *prop_list;
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL); prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
if (!prop_list) { if (!prop_list)
DRM_ERROR("failed to alloc property list.\n");
return -ENOMEM; return -ENOMEM;
}
prop_list->version = 1; prop_list->version = 1;
prop_list->writeback = 1; prop_list->writeback = 1;
......
...@@ -403,10 +403,8 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev) ...@@ -403,10 +403,8 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev)
struct drm_hdmi_context *ctx; struct drm_hdmi_context *ctx;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx) { if (!ctx)
DRM_LOG_KMS("failed to alloc common hdmi context.\n");
return -ENOMEM; return -ENOMEM;
}
subdrv = &ctx->subdrv; subdrv = &ctx->subdrv;
......
...@@ -47,10 +47,16 @@ int drm_create_iommu_mapping(struct drm_device *drm_dev) ...@@ -47,10 +47,16 @@ int drm_create_iommu_mapping(struct drm_device *drm_dev)
dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
GFP_KERNEL); GFP_KERNEL);
if (!dev->dma_parms)
goto error;
dma_set_max_seg_size(dev, 0xffffffffu); dma_set_max_seg_size(dev, 0xffffffffu);
dev->archdata.mapping = mapping; dev->archdata.mapping = mapping;
return 0; return 0;
error:
arm_iommu_release_mapping(mapping);
return -ENOMEM;
} }
/* /*
...@@ -91,6 +97,9 @@ int drm_iommu_attach_device(struct drm_device *drm_dev, ...@@ -91,6 +97,9 @@ int drm_iommu_attach_device(struct drm_device *drm_dev,
subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev, subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev,
sizeof(*subdrv_dev->dma_parms), sizeof(*subdrv_dev->dma_parms),
GFP_KERNEL); GFP_KERNEL);
if (!subdrv_dev->dma_parms)
return -ENOMEM;
dma_set_max_seg_size(subdrv_dev, 0xffffffffu); dma_set_max_seg_size(subdrv_dev, 0xffffffffu);
ret = arm_iommu_attach_device(subdrv_dev, dev->archdata.mapping); 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) ...@@ -408,10 +408,8 @@ static struct drm_exynos_ipp_cmd_work *ipp_create_cmd_work(void)
struct drm_exynos_ipp_cmd_work *cmd_work; struct drm_exynos_ipp_cmd_work *cmd_work;
cmd_work = kzalloc(sizeof(*cmd_work), GFP_KERNEL); cmd_work = kzalloc(sizeof(*cmd_work), GFP_KERNEL);
if (!cmd_work) { if (!cmd_work)
DRM_ERROR("failed to alloc cmd_work.\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
INIT_WORK((struct work_struct *)cmd_work, ipp_sched_cmd); 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) ...@@ -423,10 +421,8 @@ static struct drm_exynos_ipp_event_work *ipp_create_event_work(void)
struct drm_exynos_ipp_event_work *event_work; struct drm_exynos_ipp_event_work *event_work;
event_work = kzalloc(sizeof(*event_work), GFP_KERNEL); event_work = kzalloc(sizeof(*event_work), GFP_KERNEL);
if (!event_work) { if (!event_work)
DRM_ERROR("failed to alloc event_work.\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
INIT_WORK((struct work_struct *)event_work, ipp_sched_event); 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, ...@@ -482,10 +478,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
/* allocate command node */ /* allocate command node */
c_node = kzalloc(sizeof(*c_node), GFP_KERNEL); c_node = kzalloc(sizeof(*c_node), GFP_KERNEL);
if (!c_node) { if (!c_node)
DRM_ERROR("failed to allocate map node.\n");
return -ENOMEM; return -ENOMEM;
}
/* create property id */ /* create property id */
ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node, ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node,
...@@ -694,10 +688,8 @@ static struct drm_exynos_ipp_mem_node ...@@ -694,10 +688,8 @@ static struct drm_exynos_ipp_mem_node
mutex_lock(&c_node->mem_lock); mutex_lock(&c_node->mem_lock);
m_node = kzalloc(sizeof(*m_node), GFP_KERNEL); m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
if (!m_node) { if (!m_node)
DRM_ERROR("failed to allocate queue node.\n");
goto err_unlock; goto err_unlock;
}
/* clear base address for error handling */ /* clear base address for error handling */
memset(&buf_info, 0x0, sizeof(buf_info)); memset(&buf_info, 0x0, sizeof(buf_info));
...@@ -798,9 +790,7 @@ static int ipp_get_event(struct drm_device *drm_dev, ...@@ -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); DRM_DEBUG_KMS("ops_id[%d]buf_id[%d]\n", qbuf->ops_id, qbuf->buf_id);
e = kzalloc(sizeof(*e), GFP_KERNEL); e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e) { if (!e) {
DRM_ERROR("failed to allocate event.\n");
spin_lock_irqsave(&drm_dev->event_lock, flags); spin_lock_irqsave(&drm_dev->event_lock, flags);
file->event_space += sizeof(e->event); file->event_space += sizeof(e->event);
spin_unlock_irqrestore(&drm_dev->event_lock, flags); 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, ...@@ -1780,10 +1770,8 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
struct exynos_drm_ipp_private *priv; struct exynos_drm_ipp_private *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL); priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) { if (!priv)
DRM_ERROR("failed to allocate priv.\n");
return -ENOMEM; return -ENOMEM;
}
priv->dev = dev; priv->dev = dev;
file_priv->ipp_priv = priv; file_priv->ipp_priv = priv;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "exynos_drm_encoder.h" #include "exynos_drm_encoder.h"
#include "exynos_drm_fb.h" #include "exynos_drm_fb.h"
#include "exynos_drm_gem.h" #include "exynos_drm_gem.h"
#include "exynos_drm_plane.h"
#define to_exynos_plane(x) container_of(x, struct exynos_plane, base) #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, ...@@ -264,10 +265,8 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
int err; int err;
exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
if (!exynos_plane) { if (!exynos_plane)
DRM_ERROR("failed to allocate plane\n");
return NULL; return NULL;
}
err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs, err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs,
&exynos_plane_funcs, formats, ARRAY_SIZE(formats), &exynos_plane_funcs, formats, ARRAY_SIZE(formats),
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
#include "regs-rotator.h" #include "regs-rotator.h"
#include "exynos_drm.h" #include "exynos_drm.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h" #include "exynos_drm_ipp.h"
/* /*
...@@ -471,10 +472,8 @@ static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv) ...@@ -471,10 +472,8 @@ static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
struct drm_exynos_ipp_prop_list *prop_list; struct drm_exynos_ipp_prop_list *prop_list;
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL); prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
if (!prop_list) { if (!prop_list)
DRM_ERROR("failed to alloc property list.\n");
return -ENOMEM; return -ENOMEM;
}
prop_list->version = 1; prop_list->version = 1;
prop_list->flip = (1 << EXYNOS_DRM_FLIP_VERTICAL) | 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) ...@@ -631,21 +630,96 @@ static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
return 0; 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) static int rotator_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct rot_context *rot; struct rot_context *rot;
struct exynos_drm_ippdrv *ippdrv; struct exynos_drm_ippdrv *ippdrv;
const struct of_device_id *match;
int ret; int ret;
if (!dev->of_node) {
dev_err(dev, "cannot find of_node.\n");
return -ENODEV;
}
rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL); rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL);
if (!rot) { if (!rot)
dev_err(dev, "failed to allocate rot\n");
return -ENOMEM; return -ENOMEM;
}
rot->limit_tbl = (struct rot_limit_table *) match = of_match_node(exynos_rotator_match, dev->of_node);
platform_get_device_id(pdev)->driver_data; 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_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rot->regs = devm_ioremap_resource(dev, rot->regs_res); rot->regs = devm_ioremap_resource(dev, rot->regs_res);
...@@ -717,31 +791,6 @@ static int rotator_remove(struct platform_device *pdev) ...@@ -717,31 +791,6 @@ static int rotator_remove(struct platform_device *pdev)
return 0; 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) static int rotator_clk_crtl(struct rot_context *rot, bool enable)
{ {
if (enable) { if (enable) {
...@@ -803,10 +852,10 @@ static const struct dev_pm_ops rotator_pm_ops = { ...@@ -803,10 +852,10 @@ static const struct dev_pm_ops rotator_pm_ops = {
struct platform_driver rotator_driver = { struct platform_driver rotator_driver = {
.probe = rotator_probe, .probe = rotator_probe,
.remove = rotator_remove, .remove = rotator_remove,
.id_table = rotator_driver_ids,
.driver = { .driver = {
.name = "exynos-rot", .name = "exynos-rot",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &rotator_pm_ops, .pm = &rotator_pm_ops,
.of_match_table = exynos_rotator_match,
}, },
}; };
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#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_encoder.h"
#include "exynos_drm_vidi.h"
/* vidi has totally three virtual windows. */ /* vidi has totally three virtual windows. */
#define WINDOWS_NR 3 #define WINDOWS_NR 3
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
...@@ -1824,10 +1825,8 @@ static int hdmi_resources_init(struct hdmi_context *hdata) ...@@ -1824,10 +1825,8 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) * res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
sizeof(res->regul_bulk[0]), GFP_KERNEL); sizeof(res->regul_bulk[0]), GFP_KERNEL);
if (!res->regul_bulk) { if (!res->regul_bulk)
DRM_ERROR("failed to get memory for regulators\n");
goto fail; goto fail;
}
for (i = 0; i < ARRAY_SIZE(supply); ++i) { for (i = 0; i < ARRAY_SIZE(supply); ++i) {
res->regul_bulk[i].supply = supply[i]; res->regul_bulk[i].supply = supply[i];
res->regul_bulk[i].consumer = NULL; res->regul_bulk[i].consumer = NULL;
...@@ -1859,7 +1858,6 @@ void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy) ...@@ -1859,7 +1858,6 @@ void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
hdmi_hdmiphy = hdmiphy; hdmi_hdmiphy = hdmiphy;
} }
#ifdef CONFIG_OF
static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
(struct device *dev) (struct device *dev)
{ {
...@@ -1868,10 +1866,8 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata ...@@ -1868,10 +1866,8 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
u32 value; u32 value;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd) { if (!pd)
DRM_ERROR("memory allocation for pdata failed\n");
goto err_data; goto err_data;
}
if (!of_find_property(np, "hpd-gpio", &value)) { if (!of_find_property(np, "hpd-gpio", &value)) {
DRM_ERROR("no hpd gpio property found\n"); DRM_ERROR("no hpd gpio property found\n");
...@@ -1885,33 +1881,7 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata ...@@ -1885,33 +1881,7 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
err_data: err_data:
return NULL; 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[] = { static struct of_device_id hdmi_match_types[] = {
{ {
.compatible = "samsung,exynos5-hdmi", .compatible = "samsung,exynos5-hdmi",
...@@ -1923,7 +1893,6 @@ static struct of_device_id hdmi_match_types[] = { ...@@ -1923,7 +1893,6 @@ static struct of_device_id hdmi_match_types[] = {
/* end node */ /* end node */
} }
}; };
#endif
static int hdmi_probe(struct platform_device *pdev) static int hdmi_probe(struct platform_device *pdev)
{ {
...@@ -1932,36 +1901,23 @@ 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 hdmi_context *hdata;
struct s5p_hdmi_platform_data *pdata; struct s5p_hdmi_platform_data *pdata;
struct resource *res; struct resource *res;
const struct of_device_id *match;
int ret; int ret;
if (dev->of_node) { if (!dev->of_node)
pdata = drm_hdmi_dt_parse_pdata(dev); return -ENODEV;
if (IS_ERR(pdata)) {
DRM_ERROR("failed to parse dt\n");
return PTR_ERR(pdata);
}
} else {
pdata = dev->platform_data;
}
if (!pdata) { pdata = drm_hdmi_dt_parse_pdata(dev);
DRM_ERROR("no platform data specified\n"); if (!pdata)
return -EINVAL; return -EINVAL;
}
drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL);
GFP_KERNEL); if (!drm_hdmi_ctx)
if (!drm_hdmi_ctx) {
DRM_ERROR("failed to allocate common hdmi context.\n");
return -ENOMEM; return -ENOMEM;
}
hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
GFP_KERNEL); if (!hdata)
if (!hdata) {
DRM_ERROR("out of memory\n");
return -ENOMEM; return -ENOMEM;
}
mutex_init(&hdata->hdmi_mutex); mutex_init(&hdata->hdmi_mutex);
...@@ -1970,23 +1926,15 @@ static int hdmi_probe(struct platform_device *pdev) ...@@ -1970,23 +1926,15 @@ static int hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drm_hdmi_ctx); platform_set_drvdata(pdev, drm_hdmi_ctx);
if (dev->of_node) { match = of_match_node(hdmi_match_types, dev->of_node);
const struct of_device_id *match; if (!match)
match = of_match_node(of_match_ptr(hdmi_match_types),
dev->of_node);
if (match == NULL)
return -ENODEV; return -ENODEV;
hdata->type = (enum hdmi_type)match->data; hdata->type = (enum hdmi_type)match->data;
} else {
hdata->type = (enum hdmi_type)platform_get_device_id
(pdev)->driver_data;
}
hdata->hpd_gpio = pdata->hpd_gpio; hdata->hpd_gpio = pdata->hpd_gpio;
hdata->dev = dev; hdata->dev = dev;
ret = hdmi_resources_init(hdata); ret = hdmi_resources_init(hdata);
if (ret) { if (ret) {
DRM_ERROR("hdmi_resources_init failed\n"); DRM_ERROR("hdmi_resources_init failed\n");
return -EINVAL; return -EINVAL;
...@@ -2141,11 +2089,10 @@ static const struct dev_pm_ops hdmi_pm_ops = { ...@@ -2141,11 +2089,10 @@ static const struct dev_pm_ops hdmi_pm_ops = {
struct platform_driver hdmi_driver = { struct platform_driver hdmi_driver = {
.probe = hdmi_probe, .probe = hdmi_probe,
.remove = hdmi_remove, .remove = hdmi_remove,
.id_table = hdmi_driver_types,
.driver = { .driver = {
.name = "exynos-hdmi", .name = "exynos-hdmi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &hdmi_pm_ops, .pm = &hdmi_pm_ops,
.of_match_table = of_match_ptr(hdmi_match_types), .of_match_table = hdmi_match_types,
}, },
}; };
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/of.h>
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_hdmi.h" #include "exynos_hdmi.h"
...@@ -39,13 +40,6 @@ static int hdmiphy_remove(struct i2c_client *client) ...@@ -39,13 +40,6 @@ static int hdmiphy_remove(struct i2c_client *client)
return 0; 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[] = { static struct of_device_id hdmiphy_match_types[] = {
{ {
.compatible = "samsung,exynos5-hdmiphy", .compatible = "samsung,exynos5-hdmiphy",
...@@ -57,15 +51,13 @@ static struct of_device_id hdmiphy_match_types[] = { ...@@ -57,15 +51,13 @@ static struct of_device_id hdmiphy_match_types[] = {
/* end node */ /* end node */
} }
}; };
#endif
struct i2c_driver hdmiphy_driver = { struct i2c_driver hdmiphy_driver = {
.driver = { .driver = {
.name = "exynos-hdmiphy", .name = "exynos-hdmiphy",
.owner = THIS_MODULE, .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, .probe = hdmiphy_probe,
.remove = hdmiphy_remove, .remove = hdmiphy_remove,
.command = NULL, .command = NULL,
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
...@@ -1185,16 +1186,12 @@ static int mixer_probe(struct platform_device *pdev) ...@@ -1185,16 +1186,12 @@ static int mixer_probe(struct platform_device *pdev)
drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
GFP_KERNEL); GFP_KERNEL);
if (!drm_hdmi_ctx) { if (!drm_hdmi_ctx)
DRM_ERROR("failed to allocate common hdmi context.\n");
return -ENOMEM; return -ENOMEM;
}
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx) { if (!ctx)
DRM_ERROR("failed to alloc mixer context.\n");
return -ENOMEM; return -ENOMEM;
}
mutex_init(&ctx->mixer_mutex); mutex_init(&ctx->mixer_mutex);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define _EXYNOS_DRM_H_ #define _EXYNOS_DRM_H_
#include <uapi/drm/exynos_drm.h> #include <uapi/drm/exynos_drm.h>
#include <video/videomode.h>
/** /**
* A structure for lcd panel information. * A structure for lcd panel information.
...@@ -24,7 +25,7 @@ ...@@ -24,7 +25,7 @@
* @height_mm: physical size of lcd height. * @height_mm: physical size of lcd height.
*/ */
struct exynos_drm_panel_info { struct exynos_drm_panel_info {
struct fb_videomode timing; struct videomode vm;
u32 width_mm; u32 width_mm;
u32 height_mm; u32 height_mm;
}; };
......
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