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 ...
This commit is contained in:
Коммит
86a7e1224a
|
@ -0,0 +1,27 @@
|
|||
* 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";
|
||||
};
|
|
@ -1,11 +1,12 @@
|
|||
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;
|
||||
struct videomode *vm = &ctx->panel.vm;
|
||||
unsigned long clk;
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
return clkdiv;
|
||||
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 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");
|
||||
if (ret < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL);
|
||||
if (!rot) {
|
||||
dev_err(dev, "failed to allocate rot\n");
|
||||
return -ENOMEM;
|
||||
if (!dev->of_node) {
|
||||
dev_err(dev, "cannot find of_node.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rot->limit_tbl = (struct rot_limit_table *)
|
||||
platform_get_device_id(pdev)->driver_data;
|
||||
rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL);
|
||||
if (!rot)
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче