Commit 78c76a53 authored by Inki Dae's avatar Inki Dae

Merge tag 'exynos-drm-next-for-v4.18' of...

Merge tag 'exynos-drm-next-for-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into exynos-drm-next

- Add S5PV210 FIMD variant support.

- Add IPP v2 framework.
  . it is a rewritten version of the Exynos mem-to-mem image processing
    framework which supprts color space conversion, image up/down-scaling
    and rotation. This new version replaces existing userspace API with
    new easy-to-use and simple ones so we have already applied the use of
    these API to real user, Tizen Platform[1], and also makes existing
    Scaler, FIMC, GScaler and Rotator drivers to use IPP v2 core API.

    And below are patch lists we have applied to a real user,
    https://git.tizen.org/cgit/platform/adaptation/samsung_exynos/libtdm-exynos/log/?h=tizen&qt=grep&q=ipp
    https://git.tizen.org/cgit/platform/adaptation/samsung_exynos/libtdm-exynos/commit/?h=tizen&id=b59be207365d10efd489e6f71c8a045b558c44fe
    https://git.tizen.org/cgit/platform/kernel/linux-exynos/log/?h=tizen&qt=grep&q=ipp

    TDM(Tizen Display Manager) is a Display HAL for Tizen platform.
    Ps. Only real user using IPP API is Tizen.

    [1] https://www.tizen.org/

- Two cleanups
  . One is to just remove mode_set callback from MIPI-DSI driver
    because drm_display_mode data is already available from crtc
    atomic state.
  . And other is to just use new return type, vm_fault_t
    for page fault handler.
parents a02cbe2e e8929999
* Samsung Exynos Image Scaler
Required properties:
- compatible : value should be one of the following:
(a) "samsung,exynos5420-scaler" for Scaler IP in Exynos5420
(b) "samsung,exynos5433-scaler" for Scaler IP in Exynos5433
- reg : Physical base address of the IP registers and length of memory
mapped region.
- interrupts : Interrupt specifier for scaler interrupt, according to format
specific to interrupt parent.
- clocks : Clock specifier for scaler clock, according to generic clock
bindings. (See Documentation/devicetree/bindings/clock/exynos*.txt)
- clock-names : Names of clocks. For exynos scaler, it should be "mscl"
on 5420 and "pclk", "aclk" and "aclk_xiu" on 5433.
Example:
scaler@12800000 {
compatible = "samsung,exynos5420-scaler";
reg = <0x12800000 0x1294>;
interrupts = <0 220 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clock CLK_MSCL0>;
clock-names = "mscl";
};
config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series"
depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM)
depends on OF && DRM && (ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM)
select DRM_KMS_HELPER
select VIDEOMODE_HELPERS
select SND_SOC_HDMI_CODEC if SND_SOC
......@@ -95,21 +95,31 @@ config DRM_EXYNOS_G2D
help
Choose this option if you want to use Exynos G2D for DRM.
config DRM_EXYNOS_IPP
bool
config DRM_EXYNOS_FIMC
bool "FIMC"
depends on BROKEN && MFD_SYSCON
select DRM_EXYNOS_IPP
help
Choose this option if you want to use Exynos FIMC for DRM.
config DRM_EXYNOS_ROTATOR
bool "Rotator"
depends on BROKEN
select DRM_EXYNOS_IPP
help
Choose this option if you want to use Exynos Rotator for DRM.
config DRM_EXYNOS_SCALER
bool "Scaler"
select DRM_EXYNOS_IPP
help
Choose this option if you want to use Exynos Scaler for DRM.
config DRM_EXYNOS_GSC
bool "GScaler"
depends on BROKEN && ARCH_EXYNOS5 && VIDEO_SAMSUNG_EXYNOS_GSC=n
depends on VIDEO_SAMSUNG_EXYNOS_GSC=n
select DRM_EXYNOS_IPP
help
Choose this option if you want to use Exynos GSC for DRM.
......
......@@ -18,8 +18,10 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_MIXER) += exynos_mixer.o
exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC) += exynos_drm_fimc.o
exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o
exynosdrm-$(CONFIG_DRM_EXYNOS_SCALER) += exynos_drm_scaler.o
exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o
exynosdrm-$(CONFIG_DRM_EXYNOS_MIC) += exynos_drm_mic.o
......
......@@ -27,15 +27,23 @@
#include "exynos_drm_fb.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_ipp.h"
#include "exynos_drm_vidi.h"
#include "exynos_drm_g2d.h"
#include "exynos_drm_iommu.h"
#define DRIVER_NAME "exynos"
#define DRIVER_DESC "Samsung SoC DRM"
#define DRIVER_DATE "20110530"
#define DRIVER_DATE "20180330"
/*
* Interface history:
*
* 1.0 - Original version
* 1.1 - Upgrade IPP driver to version 2.0
*/
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 0
#define DRIVER_MINOR 1
int exynos_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
......@@ -108,6 +116,16 @@ static const struct drm_ioctl_desc exynos_ioctls[] = {
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_RESOURCES,
exynos_drm_ipp_get_res_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_CAPS, exynos_drm_ipp_get_caps_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_LIMITS,
exynos_drm_ipp_get_limits_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(EXYNOS_IPP_COMMIT, exynos_drm_ipp_commit_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
};
static const struct file_operations exynos_drm_driver_fops = {
......@@ -204,6 +222,7 @@ struct exynos_drm_driver_info {
#define DRM_COMPONENT_DRIVER BIT(0) /* supports component framework */
#define DRM_VIRTUAL_DEVICE BIT(1) /* create virtual platform device */
#define DRM_DMA_DEVICE BIT(2) /* can be used for dma allocations */
#define DRM_FIMC_DEVICE BIT(3) /* devices shared with V4L2 subsystem */
#define DRV_PTR(drv, cond) (IS_ENABLED(cond) ? &drv : NULL)
......@@ -243,10 +262,16 @@ static struct exynos_drm_driver_info exynos_drm_drivers[] = {
DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D),
}, {
DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
DRM_COMPONENT_DRIVER | DRM_FIMC_DEVICE,
}, {
DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR),
DRM_COMPONENT_DRIVER
}, {
DRV_PTR(scaler_driver, CONFIG_DRM_EXYNOS_SCALER),
DRM_COMPONENT_DRIVER
}, {
DRV_PTR(gsc_driver, CONFIG_DRM_EXYNOS_GSC),
DRM_COMPONENT_DRIVER
}, {
&exynos_drm_platform_driver,
DRM_VIRTUAL_DEVICE
......@@ -274,7 +299,11 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
&info->driver->driver,
(void *)platform_bus_type.match))) {
put_device(p);
component_match_add(dev, &match, compare_dev, d);
if (!(info->flags & DRM_FIMC_DEVICE) ||
exynos_drm_check_fimc_device(d) == 0)
component_match_add(dev, &match,
compare_dev, d);
p = d;
}
put_device(p);
......
......@@ -273,6 +273,15 @@ static inline int exynos_dpi_bind(struct drm_device *dev,
}
#endif
#ifdef CONFIG_DRM_EXYNOS_FIMC
int exynos_drm_check_fimc_device(struct device *dev);
#else
static inline int exynos_drm_check_fimc_device(struct device *dev)
{
return 0;
}
#endif
int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
bool nonblock);
int exynos_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);
......@@ -289,6 +298,7 @@ extern struct platform_driver vidi_driver;
extern struct platform_driver g2d_driver;
extern struct platform_driver fimc_driver;
extern struct platform_driver rotator_driver;
extern struct platform_driver scaler_driver;
extern struct platform_driver gsc_driver;
extern struct platform_driver mic_driver;
#endif
......@@ -270,7 +270,6 @@ struct exynos_dsi {
u32 lanes;
u32 mode_flags;
u32 format;
struct videomode vm;
int state;
struct drm_property *brightness;
......@@ -881,30 +880,30 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
{
struct videomode *vm = &dsi->vm;
struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode;
unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
u32 reg;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
reg = DSIM_CMD_ALLOW(0xf)
| DSIM_STABLE_VFP(vm->vfront_porch)
| DSIM_MAIN_VBP(vm->vback_porch);
| DSIM_STABLE_VFP(m->vsync_start - m->vdisplay)
| DSIM_MAIN_VBP(m->vtotal - m->vsync_end);
exynos_dsi_write(dsi, DSIM_MVPORCH_REG, reg);
reg = DSIM_MAIN_HFP(vm->hfront_porch)
| DSIM_MAIN_HBP(vm->hback_porch);
reg = DSIM_MAIN_HFP(m->hsync_start - m->hdisplay)
| DSIM_MAIN_HBP(m->htotal - m->hsync_end);
exynos_dsi_write(dsi, DSIM_MHPORCH_REG, reg);
reg = DSIM_MAIN_VSA(vm->vsync_len)
| DSIM_MAIN_HSA(vm->hsync_len);
reg = DSIM_MAIN_VSA(m->vsync_end - m->vsync_start)
| DSIM_MAIN_HSA(m->hsync_end - m->hsync_start);
exynos_dsi_write(dsi, DSIM_MSYNC_REG, reg);
}
reg = DSIM_MAIN_HRESOL(vm->hactive, num_bits_resol) |
DSIM_MAIN_VRESOL(vm->vactive, num_bits_resol);
reg = DSIM_MAIN_HRESOL(m->hdisplay, num_bits_resol) |
DSIM_MAIN_VRESOL(m->vdisplay, num_bits_resol);
exynos_dsi_write(dsi, DSIM_MDRESOL_REG, reg);
dev_dbg(dsi->dev, "LCD size = %dx%d\n", vm->hactive, vm->vactive);
dev_dbg(dsi->dev, "LCD size = %dx%d\n", m->hdisplay, m->vdisplay);
}
static void exynos_dsi_set_display_enable(struct exynos_dsi *dsi, bool enable)
......@@ -1485,26 +1484,7 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
return 0;
}
static void exynos_dsi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct videomode *vm = &dsi->vm;
struct drm_display_mode *m = adjusted_mode;
vm->hactive = m->hdisplay;
vm->vactive = m->vdisplay;
vm->vfront_porch = m->vsync_start - m->vdisplay;
vm->vback_porch = m->vtotal - m->vsync_end;
vm->vsync_len = m->vsync_end - m->vsync_start;
vm->hfront_porch = m->hsync_start - m->hdisplay;
vm->hback_porch = m->htotal - m->hsync_end;
vm->hsync_len = m->hsync_end - m->hsync_start;
}
static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
.mode_set = exynos_dsi_mode_set,
.enable = exynos_dsi_enable,
.disable = exynos_dsi_disable,
};
......
This diff is collapsed.
/*
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
*
* Authors:
* Eunchul Kim <chulspro.kim@samsung.com>
* Jinyoung Jeon <jy0.jeon@samsung.com>
* Sangmin Lee <lsmin.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef _EXYNOS_DRM_FIMC_H_
#define _EXYNOS_DRM_FIMC_H_
/*
* TODO
* FIMD output interface notifier callback.
*/
#endif /* _EXYNOS_DRM_FIMC_H_ */
......@@ -121,6 +121,12 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
.has_limited_fmt = 1,
};
static struct fimd_driver_data s5pv210_fimd_driver_data = {
.timing_base = 0x0,
.has_shadowcon = 1,
.has_clksel = 1,
};
static struct fimd_driver_data exynos3_fimd_driver_data = {
.timing_base = 0x20000,
.lcdblk_offset = 0x210,
......@@ -193,6 +199,8 @@ struct fimd_context {
static const struct of_device_id fimd_driver_dt_match[] = {
{ .compatible = "samsung,s3c6400-fimd",
.data = &s3c64xx_fimd_driver_data },
{ .compatible = "samsung,s5pv210-fimd",
.data = &s5pv210_fimd_driver_data },
{ .compatible = "samsung,exynos3250-fimd",
.data = &exynos3_fimd_driver_data },
{ .compatible = "samsung,exynos4210-fimd",
......
......@@ -431,37 +431,24 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
return 0;
}
int exynos_drm_gem_fault(struct vm_fault *vmf)
vm_fault_t exynos_drm_gem_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj = vma->vm_private_data;
struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
unsigned long pfn;
pgoff_t page_offset;
int ret;
page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
if (page_offset >= (exynos_gem->size >> PAGE_SHIFT)) {
DRM_ERROR("invalid page offset\n");
ret = -EINVAL;
goto out;
return VM_FAULT_SIGBUS;
}
pfn = page_to_pfn(exynos_gem->pages[page_offset]);
ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV));
out:
switch (ret) {
case 0:
case -ERESTARTSYS:
case -EINTR:
return VM_FAULT_NOPAGE;
case -ENOMEM:
return VM_FAULT_OOM;
default:
return VM_FAULT_SIGBUS;
}
return vmf_insert_mixed(vma, vmf->address,
__pfn_to_pfn_t(pfn, PFN_DEV));
}
static int exynos_drm_gem_mmap_obj(struct drm_gem_object *obj,
......
......@@ -13,6 +13,7 @@
#define _EXYNOS_DRM_GEM_H_
#include <drm/drm_gem.h>
#include <linux/mm_types.h>
#define to_exynos_gem(x) container_of(x, struct exynos_drm_gem, base)
......@@ -111,7 +112,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
struct drm_mode_create_dumb *args);
/* page fault handler and mmap fault address(virtual) to physical memory. */
int exynos_drm_gem_fault(struct vm_fault *vmf);
vm_fault_t exynos_drm_gem_fault(struct vm_fault *vmf);
/* set vm_flags and we can change the vm attribute to other one at here. */
int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
......
This diff is collapsed.
/*
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
*
* Authors:
* Eunchul Kim <chulspro.kim@samsung.com>
* Jinyoung Jeon <jy0.jeon@samsung.com>
* Sangmin Lee <lsmin.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef _EXYNOS_DRM_GSC_H_
#define _EXYNOS_DRM_GSC_H_
/*
* TODO
* FIMD output interface notifier callback.
* Mixer output interface notifier callback.
*/
#endif /* _EXYNOS_DRM_GSC_H_ */
This diff is collapsed.
/*
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef _EXYNOS_DRM_IPP_H_
#define _EXYNOS_DRM_IPP_H_
#include <drm/drmP.h>
struct exynos_drm_ipp;
struct exynos_drm_ipp_task;
/**
* struct exynos_drm_ipp_funcs - exynos_drm_ipp control functions
*/
struct exynos_drm_ipp_funcs {
/**
* @commit:
*
* This is the main entry point to start framebuffer processing
* in the hardware. The exynos_drm_ipp_task has been already validated.
* This function must not wait until the device finishes processing.
* When the driver finishes processing, it has to call
* exynos_exynos_drm_ipp_task_done() function.
*
* RETURNS:
*
* 0 on success or negative error codes in case of failure.
*/
int (*commit)(struct exynos_drm_ipp *ipp,
struct exynos_drm_ipp_task *task);
/**
* @abort:
*
* Informs the driver that it has to abort the currently running
* task as soon as possible (i.e. as soon as it can stop the device
* safely), even if the task would not have been finished by then.
* After the driver performs the necessary steps, it has to call
* exynos_drm_ipp_task_done() (as if the task ended normally).
* This function does not have to (and will usually not) wait
* until the device enters a state when it can be stopped.
*/
void (*abort)(struct exynos_drm_ipp *ipp,
struct exynos_drm_ipp_task *task);
};
/**
* struct exynos_drm_ipp - central picture processor module structure
*/
struct exynos_drm_ipp {
struct drm_device *dev;
struct list_head head;
unsigned int id;
const char *name;
const struct exynos_drm_ipp_funcs *funcs;
unsigned int capabilities;
const struct exynos_drm_ipp_formats *formats;
unsigned int num_formats;
atomic_t sequence;
spinlock_t lock;
struct exynos_drm_ipp_task *task;
struct list_head todo_list;
wait_queue_head_t done_wq;
};
struct exynos_drm_ipp_buffer {
struct drm_exynos_ipp_task_buffer buf;
struct drm_exynos_ipp_task_rect rect;
struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
const struct drm_format_info *format;
dma_addr_t dma_addr[MAX_FB_BUFFER];
};
/**
* struct exynos_drm_ipp_task - a structure describing transformation that
* has to be performed by the picture processor hardware module
*/
struct exynos_drm_ipp_task {
struct drm_device *dev;
struct exynos_drm_ipp *ipp;
struct list_head head;
struct exynos_drm_ipp_buffer src;
struct exynos_drm_ipp_buffer dst;
struct drm_exynos_ipp_task_transform transform;
struct drm_exynos_ipp_task_alpha alpha;
struct work_struct cleanup_work;
unsigned int flags;
int ret;
struct drm_pending_exynos_ipp_event *event;
};
#define DRM_EXYNOS_IPP_TASK_DONE (1 << 0)
#define DRM_EXYNOS_IPP_TASK_ASYNC (1 << 1)
struct exynos_drm_ipp_formats {
uint32_t fourcc;
uint32_t type;
uint64_t modifier;
const struct drm_exynos_ipp_limit *limits;
unsigned int num_limits;
};
/* helper macros to set exynos_drm_ipp_formats structure and limits*/
#define IPP_SRCDST_MFORMAT(f, m, l) \
.fourcc = DRM_FORMAT_##f, .modifier = m, .limits = l, \
.num_limits = ARRAY_SIZE(l), \
.type = (DRM_EXYNOS_IPP_FORMAT_SOURCE | \
DRM_EXYNOS_IPP_FORMAT_DESTINATION)
#define IPP_SRCDST_FORMAT(f, l) IPP_SRCDST_MFORMAT(f, 0, l)
#define IPP_SIZE_LIMIT(l, val...) \
.type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE | \
DRM_EXYNOS_IPP_LIMIT_SIZE_##l), val
#define IPP_SCALE_LIMIT(val...) \
.type = (DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE), val
int exynos_drm_ipp_register(struct drm_device *dev, struct exynos_drm_ipp *ipp,
const struct exynos_drm_ipp_funcs *funcs, unsigned int caps,
const struct exynos_drm_ipp_formats *formats,
unsigned int num_formats, const char *name);
void exynos_drm_ipp_unregister(struct drm_device *dev,
struct exynos_drm_ipp *ipp);
void exynos_drm_ipp_task_done(struct exynos_drm_ipp_task *task, int ret);
#ifdef CONFIG_DRM_EXYNOS_IPP
int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int exynos_drm_ipp_commit_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
#else
static inline int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_exynos_ioctl_ipp_get_res *resp = data;
resp->count_ipps = 0;
return 0;
}
static inline int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
return -ENODEV;
}
static inline int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
return -ENODEV;
}
static inline int exynos_drm_ipp_commit_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
return -ENODEV;
}
#endif
#endif
This diff is collapsed.
This diff is collapsed.
......@@ -954,8 +954,6 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
drm_mode_connector_attach_encoder(connector, encoder);
if (hdata->bridge) {
encoder->bridge = hdata->bridge;
hdata->bridge->encoder = encoder;
ret = drm_bridge_attach(encoder, hdata->bridge, NULL);
if (ret)
DRM_ERROR("Failed to attach bridge\n");
......
......@@ -473,7 +473,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
chroma_addr[1] = chroma_addr[0] + 0x40;
} else {
luma_addr[1] = luma_addr[0] + fb->pitches[0];
chroma_addr[1] = chroma_addr[0] + fb->pitches[0];
chroma_addr[1] = chroma_addr[0] + fb->pitches[1];
}
} else {
luma_addr[1] = 0;
......@@ -482,6 +482,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
spin_lock_irqsave(&ctx->reg_slock, flags);
vp_reg_write(ctx, VP_SHADOW_UPDATE, 1);
/* interlace or progressive scan mode */
val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0);
vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_LINE_SKIP);
......@@ -495,21 +496,23 @@ static void vp_video_buffer(struct mixer_context *ctx,
vp_reg_write(ctx, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
VP_IMG_VSIZE(fb->height));
/* chroma plane for NV12/NV21 is half the height of the luma plane */
vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[1]) |
VP_IMG_VSIZE(fb->height / 2));
vp_reg_write(ctx, VP_SRC_WIDTH, state->src.w);
vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h);
vp_reg_write(ctx, VP_SRC_H_POSITION,
VP_SRC_H_POSITION_VAL(state->src.x));
vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y);
vp_reg_write(ctx, VP_DST_WIDTH, state->crtc.w);
vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x);
if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h / 2);
vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y / 2);
vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h / 2);
vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2);
} else {
vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h);
vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y);
vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h);
vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y);
}
......@@ -699,6 +702,15 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
/* interlace scan need to check shadow register */
if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) &&
vp_reg_read(ctx, VP_SHADOW_UPDATE))
goto out;
base = mixer_reg_read(ctx, MXR_CFG);
shadow = mixer_reg_read(ctx, MXR_CFG_S);
if (base != shadow)
goto out;
base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0));
shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0));
if (base != shadow)
......
......@@ -47,6 +47,7 @@
#define MXR_MO 0x0304
#define MXR_RESOLUTION 0x0310
#define MXR_CFG_S 0x2004
#define MXR_GRAPHIC0_BASE_S 0x2024
#define MXR_GRAPHIC1_BASE_S 0x2044
......
This diff is collapsed.
......@@ -135,6 +135,219 @@ struct drm_exynos_g2d_exec {
__u64 async;
};
/* Exynos DRM IPP v2 API */
/**
* Enumerate available IPP hardware modules.
*
* @count_ipps: size of ipp_id array / number of ipp modules (set by driver)
* @reserved: padding
* @ipp_id_ptr: pointer to ipp_id array or NULL
*/
struct drm_exynos_ioctl_ipp_get_res {
__u32 count_ipps;
__u32 reserved;
__u64 ipp_id_ptr;
};
enum drm_exynos_ipp_format_type {
DRM_EXYNOS_IPP_FORMAT_SOURCE = 0x01,
DRM_EXYNOS_IPP_FORMAT_DESTINATION = 0x02,
};
struct drm_exynos_ipp_format {
__u32 fourcc;
__u32 type;
__u64 modifier;
};
enum drm_exynos_ipp_capability {
DRM_EXYNOS_IPP_CAP_CROP = 0x01,
DRM_EXYNOS_IPP_CAP_ROTATE = 0x02,
DRM_EXYNOS_IPP_CAP_SCALE = 0x04,
DRM_EXYNOS_IPP_CAP_CONVERT = 0x08,
};
/**
* Get IPP hardware capabilities and supported image formats.
*
* @ipp_id: id of IPP module to query
* @capabilities: bitmask of drm_exynos_ipp_capability (set by driver)
* @reserved: padding
* @formats_count: size of formats array (in entries) / number of filled
* formats (set by driver)
* @formats_ptr: pointer to formats array or NULL
*/
struct drm_exynos_ioctl_ipp_get_caps {
__u32 ipp_id;
__u32 capabilities;
__u32 reserved;
__u32 formats_count;
__u64 formats_ptr;
};
enum drm_exynos_ipp_limit_type {
/* size (horizontal/vertial) limits, in pixels (min, max, alignment) */
DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE = 0x0001,
/* scale ratio (horizonta/vertial), 16.16 fixed point (min, max) */
DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE = 0x0002,
/* image buffer area */
DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER = 0x0001 << 16,
/* src/dst rectangle area */
DRM_EXYNOS_IPP_LIMIT_SIZE_AREA = 0x0002 << 16,
/* src/dst rectangle area when rotation enabled */
DRM_EXYNOS_IPP_LIMIT_SIZE_ROTATED = 0x0003 << 16,
DRM_EXYNOS_IPP_LIMIT_TYPE_MASK = 0x000f,
DRM_EXYNOS_IPP_LIMIT_SIZE_MASK = 0x000f << 16,
};
struct drm_exynos_ipp_limit_val {
__u32 min;
__u32 max;
__u32 align;
__u32 reserved;
};
/**
* IPP module limitation.
*
* @type: limit type (see drm_exynos_ipp_limit_type enum)
* @reserved: padding
* @h: horizontal limits
* @v: vertical limits
*/
struct drm_exynos_ipp_limit {
__u32 type;
__u32 reserved;
struct drm_exynos_ipp_limit_val h;
struct drm_exynos_ipp_limit_val v;
};
/**
* Get IPP limits for given image format.
*
* @ipp_id: id of IPP module to query
* @fourcc: image format code (see DRM_FORMAT_* in drm_fourcc.h)
* @modifier: image format modifier (see DRM_FORMAT_MOD_* in drm_fourcc.h)
* @type: source/destination identifier (drm_exynos_ipp_format_flag enum)
* @limits_count: size of limits array (in entries) / number of filled entries
* (set by driver)
* @limits_ptr: pointer to limits array or NULL
*/
struct drm_exynos_ioctl_ipp_get_limits {
__u32 ipp_id;
__u32 fourcc;
__u64 modifier;
__u32 type;
__u32 limits_count;
__u64 limits_ptr;
};
enum drm_exynos_ipp_task_id {
/* buffer described by struct drm_exynos_ipp_task_buffer */
DRM_EXYNOS_IPP_TASK_BUFFER = 0x0001,
/* rectangle described by struct drm_exynos_ipp_task_rect */
DRM_EXYNOS_IPP_TASK_RECTANGLE = 0x0002,
/* transformation described by struct drm_exynos_ipp_task_transform */
DRM_EXYNOS_IPP_TASK_TRANSFORM = 0x0003,
/* alpha configuration described by struct drm_exynos_ipp_task_alpha */
DRM_EXYNOS_IPP_TASK_ALPHA = 0x0004,
/* source image data (for buffer and rectangle chunks) */
DRM_EXYNOS_IPP_TASK_TYPE_SOURCE = 0x0001 << 16,
/* destination image data (for buffer and rectangle chunks) */
DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION = 0x0002 << 16,
};
/**
* Memory buffer with image data.
*
* @id: must be DRM_EXYNOS_IPP_TASK_BUFFER
* other parameters are same as for AddFB2 generic DRM ioctl
*/
struct drm_exynos_ipp_task_buffer {
__u32 id;
__u32 fourcc;
__u32 width, height;
__u32 gem_id[4];
__u32 offset[4];
__u32 pitch[4];
__u64 modifier;
};
/**
* Rectangle for processing.
*
* @id: must be DRM_EXYNOS_IPP_TASK_RECTANGLE
* @reserved: padding
* @x,@y: left corner in pixels
* @w,@h: width/height in pixels
*/
struct drm_exynos_ipp_task_rect {
__u32 id;
__u32 reserved;
__u32 x;
__u32 y;
__u32 w;
__u32 h;
};
/**
* Image tranformation description.
*
* @id: must be DRM_EXYNOS_IPP_TASK_TRANSFORM
* @rotation: DRM_MODE_ROTATE_* and DRM_MODE_REFLECT_* values
*/
struct drm_exynos_ipp_task_transform {
__u32 id;
__u32 rotation;
};
/**
* Image global alpha configuration for formats without alpha values.
*
* @id: must be DRM_EXYNOS_IPP_TASK_ALPHA
* @value: global alpha value (0-255)
*/
struct drm_exynos_ipp_task_alpha {
__u32 id;
__u32 value;
};
enum drm_exynos_ipp_flag {
/* generate DRM event after processing */
DRM_EXYNOS_IPP_FLAG_EVENT = 0x01,
/* dry run, only check task parameters */
DRM_EXYNOS_IPP_FLAG_TEST_ONLY = 0x02,
/* non-blocking processing */
DRM_EXYNOS_IPP_FLAG_NONBLOCK = 0x04,
};
#define DRM_EXYNOS_IPP_FLAGS (DRM_EXYNOS_IPP_FLAG_EVENT |\
DRM_EXYNOS_IPP_FLAG_TEST_ONLY | DRM_EXYNOS_IPP_FLAG_NONBLOCK)
/**
* Perform image processing described by array of drm_exynos_ipp_task_*
* structures (parameters array).
*
* @ipp_id: id of IPP module to run the task
* @flags: bitmask of drm_exynos_ipp_flag values
* @reserved: padding
* @params_size: size of parameters array (in bytes)
* @params_ptr: pointer to parameters array or NULL
* @user_data: (optional) data for drm event
*/
struct drm_exynos_ioctl_ipp_commit {
__u32 ipp_id;
__u32 flags;
__u32 reserved;
__u32 params_size;
__u64 params_ptr;
__u64 user_data;
};
#define DRM_EXYNOS_GEM_CREATE 0x00
#define DRM_EXYNOS_GEM_MAP 0x01
/* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */
......@@ -147,6 +360,11 @@ struct drm_exynos_g2d_exec {
#define DRM_EXYNOS_G2D_EXEC 0x22
/* Reserved 0x30 ~ 0x33 for obsolete Exynos IPP ioctls */
/* IPP - Image Post Processing */
#define DRM_EXYNOS_IPP_GET_RESOURCES 0x40
#define DRM_EXYNOS_IPP_GET_CAPS 0x41
#define DRM_EXYNOS_IPP_GET_LIMITS 0x42
#define DRM_EXYNOS_IPP_COMMIT 0x43
#define DRM_IOCTL_EXYNOS_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)
......@@ -165,8 +383,20 @@ struct drm_exynos_g2d_exec {
#define DRM_IOCTL_EXYNOS_G2D_EXEC DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec)
#define DRM_IOCTL_EXYNOS_IPP_GET_RESOURCES DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_IPP_GET_RESOURCES, \
struct drm_exynos_ioctl_ipp_get_res)
#define DRM_IOCTL_EXYNOS_IPP_GET_CAPS DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_IPP_GET_CAPS, struct drm_exynos_ioctl_ipp_get_caps)
#define DRM_IOCTL_EXYNOS_IPP_GET_LIMITS DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_IPP_GET_LIMITS, \
struct drm_exynos_ioctl_ipp_get_limits)
#define DRM_IOCTL_EXYNOS_IPP_COMMIT DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_IPP_COMMIT, struct drm_exynos_ioctl_ipp_commit)
/* EXYNOS specific events */
#define DRM_EXYNOS_G2D_EVENT 0x80000000
#define DRM_EXYNOS_IPP_EVENT 0x80000002
struct drm_exynos_g2d_event {
struct drm_event base;
......@@ -177,6 +407,16 @@ struct drm_exynos_g2d_event {
__u32 reserved;
};
struct drm_exynos_ipp_event {
struct drm_event base;
__u64 user_data;
__u32 tv_sec;
__u32 tv_usec;
__u32 ipp_id;
__u32 sequence;
__u64 reserved;
};
#if defined(__cplusplus)
}
#endif
......
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