Merge tag 'drm-next-2018-10-24' of git://anongit.freedesktop.org/drm/drm

Pull drm updates from Dave Airlie:
 "This is going to rebuild more than drm as it adds a new helper to
  list.h for doing bulk updates. Seemed like a reasonable addition to
  me.

  Otherwise the usual merge window stuff lots of i915 and amdgpu, not so
  much nouveau, and piles of everything else.

  Core:
   - Adds a new list.h helper for doing bulk list updates for TTM.
   - Don't leak fb address in smem_start to userspace (comes with EXPORT
     workaround for people using mali out of tree hacks)
   - udmabuf device to turn memfd regions into dma-buf
   - Per-plane blend mode property
   - ref/unref replacements with get/put
   - fbdev conflicting framebuffers code cleaned up
   - host-endian format variants
   - panel orientation quirk for Acer One 10

  bridge:
   - TI SN65DSI86 chip support

  vkms:
   - GEM support.
   - Cursor support

  amdgpu:
   - Merge amdkfd and amdgpu into one module
   - CEC over DP AUX support
   - Picasso APU support + VCN dynamic powergating
   - Raven2 APU support
   - Vega20 enablement + kfd support
   - ACP powergating improvements
   - ABGR/XBGR display support
   - VCN jpeg support
   - xGMI support
   - DC i2c/aux cleanup
   - Ycbcr 4:2:0 support
   - GPUVM improvements
   - Powerplay and powerplay endian fixes
   - Display underflow fixes

  vmwgfx:
   - Move vmwgfx specific TTM code to vmwgfx
   - Split out vmwgfx buffer/resource validation code
   - Atomic operation rework

  bochs:
   - use more helpers
   - format/byteorder improvements

  qxl:
   - use more helpers

  i915:
   - GGTT coherency getparam
   - Turn off resource streamer API
   - More Icelake enablement + DMC firmware
   - Full PPGTT for Ivybridge, Haswell and Valleyview
   - DDB distribution based on resolution
   - Limited range DP display support

  nouveau:
   - CEC over DP AUX support
   - Initial HDMI 2.0 support

  virtio-gpu:
   - vmap support for PRIME objects

  tegra:
   - Initial Tegra194 support
   - DMA/IOMMU integration fixes

  msm:
   - a6xx perf improvements + clock prefix
   - GPU preemption optimisations
   - a6xx devfreq support
   - cursor support

  rockchip:
   - PX30 support
   - rgb output interface support

  mediatek:
   - HDMI output support on mt2701 and mt7623

  rcar-du:
   - Interlaced modes on Gen3
   - LVDS on R8A77980
   - D3 and E3 SoC support

  hisilicon:
   - misc fixes

  mxsfb:
   - runtime pm support

  sun4i:
   - R40 TCON support
   - Allwinner A64 support
   - R40 HDMI support

  omapdrm:
   - Driver rework changing display pipeline ordering to use common code
   - DMM memory barrier and irq fixes
   - Errata workarounds

  exynos:
   - out-bridge support for LVDS bridge driver
   - Samsung 16x16 tiled format support
   - Plane alpha and pixel blend mode support

  tilcdc:
   - suspend/resume update

  mali-dp:
   - misc updates"

* tag 'drm-next-2018-10-24' of git://anongit.freedesktop.org/drm/drm: (1382 commits)
  firmware/dmc/icl: Add missing MODULE_FIRMWARE() for Icelake.
  drm/i915/icl: Fix signal_levels
  drm/i915/icl: Fix DDI/TC port clk_off bits
  drm/i915/icl: create function to identify combophy port
  drm/i915/gen9+: Fix initial readout for Y tiled framebuffers
  drm/i915: Large page offsets for pread/pwrite
  drm/i915/selftests: Disable shrinker across mmap-exhaustion
  drm/i915/dp: Link train Fallback on eDP only if fallback link BW can fit panel's native mode
  drm/i915: Fix intel_dp_mst_best_encoder()
  drm/i915: Skip vcpi allocation for MSTB ports that are gone
  drm/i915: Don't unset intel_connector->mst_port
  drm/i915: Only reset seqno if actually idle
  drm/i915: Use the correct crtc when sanitizing plane mapping
  drm/i915: Restore vblank interrupts earlier
  drm/i915: Check fb stride against plane max stride
  drm/amdgpu/vcn:Fix uninitialized symbol error
  drm: panel-orientation-quirks: Add quirk for Acer One 10 (S1003)
  drm/amd/amdgpu: Fix debugfs error handling
  drm/amdgpu: Update gc_9_0 golden settings.
  drm/amd/powerplay: update PPtable with DC BTC and Tvr SocLimit fields
  ...
Цей коміт міститься в:
Linus Torvalds
2018-10-28 17:49:53 -07:00
джерело 746bb4ed6d f2bfc71aee
коміт 53b3b6bbfd
893 змінених файлів з 107890 додано та 25795 видалено

Переглянути файл

@@ -149,37 +149,15 @@ static struct drm_driver exynos_drm_driver = {
static int exynos_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct exynos_drm_private *private;
if (!drm_dev)
return 0;
private = drm_dev->dev_private;
drm_kms_helper_poll_disable(drm_dev);
exynos_drm_fbdev_suspend(drm_dev);
private->suspend_state = drm_atomic_helper_suspend(drm_dev);
if (IS_ERR(private->suspend_state)) {
exynos_drm_fbdev_resume(drm_dev);
drm_kms_helper_poll_enable(drm_dev);
return PTR_ERR(private->suspend_state);
}
return 0;
return drm_mode_config_helper_suspend(drm_dev);
}
static void exynos_drm_resume(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct exynos_drm_private *private;
if (!drm_dev)
return;
private = drm_dev->dev_private;
drm_atomic_helper_resume(drm_dev, private->suspend_state);
exynos_drm_fbdev_resume(drm_dev);
drm_kms_helper_poll_enable(drm_dev);
drm_mode_config_helper_resume(drm_dev);
}
static const struct dev_pm_ops exynos_drm_pm_ops = {

Переглянути файл

@@ -92,6 +92,8 @@ struct exynos_drm_plane {
#define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1)
#define EXYNOS_DRM_PLANE_CAP_ZPOS (1 << 2)
#define EXYNOS_DRM_PLANE_CAP_TILE (1 << 3)
#define EXYNOS_DRM_PLANE_CAP_PIX_BLEND (1 << 4)
#define EXYNOS_DRM_PLANE_CAP_WIN_BLEND (1 << 5)
/*
* Exynos DRM plane configuration structure.
@@ -195,7 +197,6 @@ struct drm_exynos_file_private {
*/
struct exynos_drm_private {
struct drm_fb_helper *fb_helper;
struct drm_atomic_state *suspend_state;
struct device *g2d_dev;
struct device *dma_dev;

Переглянути файл

@@ -255,6 +255,7 @@ struct exynos_dsi {
struct mipi_dsi_host dsi_host;
struct drm_connector connector;
struct drm_panel *panel;
struct drm_bridge *out_bridge;
struct device *dev;
void __iomem *reg_base;
@@ -279,7 +280,7 @@ struct exynos_dsi {
struct list_head transfer_list;
const struct exynos_dsi_driver_data *driver_data;
struct device_node *bridge_node;
struct device_node *in_bridge_node;
};
#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
@@ -1382,29 +1383,37 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
return;
pm_runtime_get_sync(dsi->dev);
dsi->state |= DSIM_STATE_ENABLED;
ret = drm_panel_prepare(dsi->panel);
if (ret < 0) {
dsi->state &= ~DSIM_STATE_ENABLED;
pm_runtime_put_sync(dsi->dev);
return;
if (dsi->panel) {
ret = drm_panel_prepare(dsi->panel);
if (ret < 0)
goto err_put_sync;
} else {
drm_bridge_pre_enable(dsi->out_bridge);
}
exynos_dsi_set_display_mode(dsi);
exynos_dsi_set_display_enable(dsi, true);
ret = drm_panel_enable(dsi->panel);
if (ret < 0) {
dsi->state &= ~DSIM_STATE_ENABLED;
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
pm_runtime_put_sync(dsi->dev);
return;
if (dsi->panel) {
ret = drm_panel_enable(dsi->panel);
if (ret < 0)
goto err_display_disable;
} else {
drm_bridge_enable(dsi->out_bridge);
}
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
return;
err_display_disable:
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
err_put_sync:
dsi->state &= ~DSIM_STATE_ENABLED;
pm_runtime_put(dsi->dev);
}
static void exynos_dsi_disable(struct drm_encoder *encoder)
@@ -1417,11 +1426,11 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
drm_panel_disable(dsi->panel);
drm_bridge_disable(dsi->out_bridge);
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
drm_bridge_post_disable(dsi->out_bridge);
dsi->state &= ~DSIM_STATE_ENABLED;
pm_runtime_put_sync(dsi->dev);
}
@@ -1499,7 +1508,30 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct exynos_dsi *dsi = host_to_dsi(host);
struct drm_device *drm = dsi->connector.dev;
struct drm_encoder *encoder = &dsi->encoder;
struct drm_device *drm = encoder->dev;
struct drm_bridge *out_bridge;
out_bridge = of_drm_find_bridge(device->dev.of_node);
if (out_bridge) {
drm_bridge_attach(encoder, out_bridge, NULL);
dsi->out_bridge = out_bridge;
encoder->bridge = NULL;
} else {
int ret = exynos_dsi_create_connector(encoder);
if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(encoder);
return ret;
}
dsi->panel = of_drm_find_panel(device->dev.of_node);
if (dsi->panel) {
drm_panel_attach(dsi->panel, &dsi->connector);
dsi->connector.status = connector_status_connected;
}
}
/*
* This is a temporary solution and should be made by more generic way.
@@ -1518,14 +1550,6 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
dsi->lanes = device->lanes;
dsi->format = device->format;
dsi->mode_flags = device->mode_flags;
dsi->panel = of_drm_find_panel(device->dev.of_node);
if (IS_ERR(dsi->panel))
dsi->panel = NULL;
if (dsi->panel) {
drm_panel_attach(dsi->panel, &dsi->connector);
dsi->connector.status = connector_status_connected;
}
exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
@@ -1541,19 +1565,21 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct exynos_dsi *dsi = host_to_dsi(host);
struct drm_device *drm = dsi->connector.dev;
mutex_lock(&drm->mode_config.mutex);
struct drm_device *drm = dsi->encoder.dev;
if (dsi->panel) {
mutex_lock(&drm->mode_config.mutex);
exynos_dsi_disable(&dsi->encoder);
drm_panel_detach(dsi->panel);
dsi->panel = NULL;
dsi->connector.status = connector_status_disconnected;
mutex_unlock(&drm->mode_config.mutex);
} else {
if (dsi->out_bridge->funcs->detach)
dsi->out_bridge->funcs->detach(dsi->out_bridge);
dsi->out_bridge = NULL;
}
mutex_unlock(&drm->mode_config.mutex);
if (drm->mode_config.poll_enabled)
drm_kms_helper_hotplug_event(drm);
@@ -1634,7 +1660,7 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
if (ret < 0)
return ret;
dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_IN, 0);
dsi->in_bridge_node = of_graph_get_remote_node(node, DSI_PORT_IN, 0);
return 0;
}
@@ -1645,7 +1671,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
struct drm_encoder *encoder = dev_get_drvdata(dev);
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct drm_device *drm_dev = data;
struct drm_bridge *bridge;
struct drm_bridge *in_bridge;
int ret;
drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs,
@@ -1657,17 +1683,10 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
if (ret < 0)
return ret;
ret = exynos_dsi_create_connector(encoder);
if (ret) {
DRM_ERROR("failed to create connector ret = %d\n", ret);
drm_encoder_cleanup(encoder);
return ret;
}
if (dsi->bridge_node) {
bridge = of_drm_find_bridge(dsi->bridge_node);
if (bridge)
drm_bridge_attach(encoder, bridge, NULL);
if (dsi->in_bridge_node) {
in_bridge = of_drm_find_bridge(dsi->in_bridge_node);
if (in_bridge)
drm_bridge_attach(encoder, in_bridge, NULL);
}
return mipi_dsi_host_register(&dsi->dsi_host);
@@ -1786,7 +1805,7 @@ static int exynos_dsi_remove(struct platform_device *pdev)
{
struct exynos_dsi *dsi = platform_get_drvdata(pdev);
of_node_put(dsi->bridge_node);
of_node_put(dsi->in_bridge_node);
pm_runtime_disable(&pdev->dev);

Переглянути файл

@@ -270,20 +270,3 @@ void exynos_drm_fbdev_fini(struct drm_device *dev)
private->fb_helper = NULL;
}
void exynos_drm_fbdev_suspend(struct drm_device *dev)
{
struct exynos_drm_private *private = dev->dev_private;
console_lock();
drm_fb_helper_set_suspend(private->fb_helper, 1);
console_unlock();
}
void exynos_drm_fbdev_resume(struct drm_device *dev)
{
struct exynos_drm_private *private = dev->dev_private;
console_lock();
drm_fb_helper_set_suspend(private->fb_helper, 0);
console_unlock();
}

Переглянути файл

@@ -19,8 +19,6 @@
int exynos_drm_fbdev_init(struct drm_device *dev);
void exynos_drm_fbdev_fini(struct drm_device *dev);
void exynos_drm_fbdev_suspend(struct drm_device *drm);
void exynos_drm_fbdev_resume(struct drm_device *drm);
#else
@@ -39,14 +37,6 @@ static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
#define exynos_drm_output_poll_changed (NULL)
static inline void exynos_drm_fbdev_suspend(struct drm_device *drm)
{
}
static inline void exynos_drm_fbdev_resume(struct drm_device *drm)
{
}
#endif
#endif

Переглянути файл

@@ -448,7 +448,7 @@ static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
}
static void gsc_src_set_fmt(struct gsc_context *ctx, u32 fmt)
static void gsc_src_set_fmt(struct gsc_context *ctx, u32 fmt, bool tiled)
{
u32 cfg;
@@ -514,6 +514,9 @@ static void gsc_src_set_fmt(struct gsc_context *ctx, u32 fmt)
break;
}
if (tiled)
cfg |= (GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE);
gsc_write(cfg, GSC_IN_CON);
}
@@ -632,7 +635,7 @@ static void gsc_src_set_addr(struct gsc_context *ctx, u32 buf_id,
gsc_src_set_buf_seq(ctx, buf_id, true);
}
static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 fmt)
static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 fmt, bool tiled)
{
u32 cfg;
@@ -698,6 +701,9 @@ static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 fmt)
break;
}
if (tiled)
cfg |= (GSC_IN_TILE_C_16x8 | GSC_OUT_TILE_MODE);
gsc_write(cfg, GSC_OUT_CON);
}
@@ -1122,11 +1128,11 @@ static int gsc_commit(struct exynos_drm_ipp *ipp,
return ret;
}
gsc_src_set_fmt(ctx, task->src.buf.fourcc);
gsc_src_set_fmt(ctx, task->src.buf.fourcc, task->src.buf.modifier);
gsc_src_set_transf(ctx, task->transform.rotation);
gsc_src_set_size(ctx, &task->src);
gsc_src_set_addr(ctx, 0, &task->src);
gsc_dst_set_fmt(ctx, task->dst.buf.fourcc);
gsc_dst_set_fmt(ctx, task->dst.buf.fourcc, task->dst.buf.modifier);
gsc_dst_set_size(ctx, &task->dst);
gsc_dst_set_addr(ctx, 0, &task->dst);
gsc_set_prescaler(ctx, &ctx->sc, &task->src.rect, &task->dst.rect);
@@ -1200,6 +1206,10 @@ static const unsigned int gsc_formats[] = {
DRM_FORMAT_YUV420, DRM_FORMAT_YVU420, DRM_FORMAT_YUV422,
};
static const unsigned int gsc_tiled_formats[] = {
DRM_FORMAT_NV12, DRM_FORMAT_NV21,
};
static int gsc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1207,23 +1217,24 @@ static int gsc_probe(struct platform_device *pdev)
struct exynos_drm_ipp_formats *formats;
struct gsc_context *ctx;
struct resource *res;
int ret, i;
int num_formats, ret, i, j;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
formats = devm_kcalloc(dev,
ARRAY_SIZE(gsc_formats), sizeof(*formats),
GFP_KERNEL);
if (!formats)
return -ENOMEM;
driver_data = (struct gsc_driverdata *)of_device_get_match_data(dev);
ctx->dev = dev;
ctx->num_clocks = driver_data->num_clocks;
ctx->clk_names = driver_data->clk_names;
/* construct formats/limits array */
num_formats = ARRAY_SIZE(gsc_formats) + ARRAY_SIZE(gsc_tiled_formats);
formats = devm_kcalloc(dev, num_formats, sizeof(*formats), GFP_KERNEL);
if (!formats)
return -ENOMEM;
/* linear formats */
for (i = 0; i < ARRAY_SIZE(gsc_formats); i++) {
formats[i].fourcc = gsc_formats[i];
formats[i].type = DRM_EXYNOS_IPP_FORMAT_SOURCE |
@@ -1231,8 +1242,19 @@ static int gsc_probe(struct platform_device *pdev)
formats[i].limits = driver_data->limits;
formats[i].num_limits = driver_data->num_limits;
}
/* tiled formats */
for (j = i, i = 0; i < ARRAY_SIZE(gsc_tiled_formats); j++, i++) {
formats[j].fourcc = gsc_tiled_formats[i];
formats[j].modifier = DRM_FORMAT_MOD_SAMSUNG_16_16_TILE;
formats[j].type = DRM_EXYNOS_IPP_FORMAT_SOURCE |
DRM_EXYNOS_IPP_FORMAT_DESTINATION;
formats[j].limits = driver_data->limits;
formats[j].num_limits = driver_data->num_limits;
}
ctx->formats = formats;
ctx->num_formats = ARRAY_SIZE(gsc_formats);
ctx->num_formats = num_formats;
/* clock control */
for (i = 0; i < ctx->num_clocks; i++) {

Переглянути файл

@@ -131,16 +131,14 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
if (plane->state) {
exynos_state = to_exynos_plane_state(plane->state);
if (exynos_state->base.fb)
drm_framebuffer_put(exynos_state->base.fb);
__drm_atomic_helper_plane_destroy_state(plane->state);
kfree(exynos_state);
plane->state = NULL;
}
exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
if (exynos_state) {
plane->state = &exynos_state->base;
plane->state->plane = plane;
__drm_atomic_helper_plane_reset(plane, &exynos_state->base);
plane->state->zpos = exynos_plane->config->zpos;
}
}
@@ -300,6 +298,10 @@ int exynos_plane_init(struct drm_device *dev,
const struct exynos_drm_plane_config *config)
{
int err;
unsigned int supported_modes = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE);
struct drm_plane *plane = &exynos_plane->base;
err = drm_universal_plane_init(dev, &exynos_plane->base,
1 << dev->mode_config.num_crtc,
@@ -320,5 +322,11 @@ int exynos_plane_init(struct drm_device *dev,
exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos,
!(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS));
if (config->capabilities & EXYNOS_DRM_PLANE_CAP_PIX_BLEND)
drm_plane_create_blend_mode_property(plane, supported_modes);
if (config->capabilities & EXYNOS_DRM_PLANE_CAP_WIN_BLEND)
drm_plane_create_alpha_property(plane);
return 0;
}

Переглянути файл

@@ -49,56 +49,46 @@ struct scaler_context {
const struct scaler_data *scaler_data;
};
static u32 scaler_get_format(u32 drm_fmt)
{
switch (drm_fmt) {
case DRM_FORMAT_NV12:
return SCALER_YUV420_2P_UV;
case DRM_FORMAT_NV21:
return SCALER_YUV420_2P_VU;
case DRM_FORMAT_YUV420:
return SCALER_YUV420_3P;
case DRM_FORMAT_YUYV:
return SCALER_YUV422_1P_YUYV;
case DRM_FORMAT_UYVY:
return SCALER_YUV422_1P_UYVY;
case DRM_FORMAT_YVYU:
return SCALER_YUV422_1P_YVYU;
case DRM_FORMAT_NV16:
return SCALER_YUV422_2P_UV;
case DRM_FORMAT_NV61:
return SCALER_YUV422_2P_VU;
case DRM_FORMAT_YUV422:
return SCALER_YUV422_3P;
case DRM_FORMAT_NV24:
return SCALER_YUV444_2P_UV;
case DRM_FORMAT_NV42:
return SCALER_YUV444_2P_VU;
case DRM_FORMAT_YUV444:
return SCALER_YUV444_3P;
case DRM_FORMAT_RGB565:
return SCALER_RGB_565;
case DRM_FORMAT_XRGB1555:
return SCALER_ARGB1555;
case DRM_FORMAT_ARGB1555:
return SCALER_ARGB1555;
case DRM_FORMAT_XRGB4444:
return SCALER_ARGB4444;
case DRM_FORMAT_ARGB4444:
return SCALER_ARGB4444;
case DRM_FORMAT_XRGB8888:
return SCALER_ARGB8888;
case DRM_FORMAT_ARGB8888:
return SCALER_ARGB8888;
case DRM_FORMAT_RGBX8888:
return SCALER_RGBA8888;
case DRM_FORMAT_RGBA8888:
return SCALER_RGBA8888;
default:
break;
}
struct scaler_format {
u32 drm_fmt;
u32 internal_fmt;
u32 chroma_tile_w;
u32 chroma_tile_h;
};
return 0;
static const struct scaler_format scaler_formats[] = {
{ DRM_FORMAT_NV12, SCALER_YUV420_2P_UV, 8, 8 },
{ DRM_FORMAT_NV21, SCALER_YUV420_2P_VU, 8, 8 },
{ DRM_FORMAT_YUV420, SCALER_YUV420_3P, 8, 8 },
{ DRM_FORMAT_YUYV, SCALER_YUV422_1P_YUYV, 16, 16 },
{ DRM_FORMAT_UYVY, SCALER_YUV422_1P_UYVY, 16, 16 },
{ DRM_FORMAT_YVYU, SCALER_YUV422_1P_YVYU, 16, 16 },
{ DRM_FORMAT_NV16, SCALER_YUV422_2P_UV, 8, 16 },
{ DRM_FORMAT_NV61, SCALER_YUV422_2P_VU, 8, 16 },
{ DRM_FORMAT_YUV422, SCALER_YUV422_3P, 8, 16 },
{ DRM_FORMAT_NV24, SCALER_YUV444_2P_UV, 16, 16 },
{ DRM_FORMAT_NV42, SCALER_YUV444_2P_VU, 16, 16 },
{ DRM_FORMAT_YUV444, SCALER_YUV444_3P, 16, 16 },
{ DRM_FORMAT_RGB565, SCALER_RGB_565, 0, 0 },
{ DRM_FORMAT_XRGB1555, SCALER_ARGB1555, 0, 0 },
{ DRM_FORMAT_ARGB1555, SCALER_ARGB1555, 0, 0 },
{ DRM_FORMAT_XRGB4444, SCALER_ARGB4444, 0, 0 },
{ DRM_FORMAT_ARGB4444, SCALER_ARGB4444, 0, 0 },
{ DRM_FORMAT_XRGB8888, SCALER_ARGB8888, 0, 0 },
{ DRM_FORMAT_ARGB8888, SCALER_ARGB8888, 0, 0 },
{ DRM_FORMAT_RGBX8888, SCALER_RGBA8888, 0, 0 },
{ DRM_FORMAT_RGBA8888, SCALER_RGBA8888, 0, 0 },
};
static const struct scaler_format *scaler_get_format(u32 drm_fmt)
{
int i;
for (i = 0; i < ARRAY_SIZE(scaler_formats); i++)
if (scaler_formats[i].drm_fmt == drm_fmt)
return &scaler_formats[i];
return NULL;
}
static inline int scaler_reset(struct scaler_context *scaler)
@@ -152,11 +142,11 @@ static inline void scaler_enable_int(struct scaler_context *scaler)
}
static inline void scaler_set_src_fmt(struct scaler_context *scaler,
u32 src_fmt)
u32 src_fmt, u32 tile)
{
u32 val;
val = SCALER_SRC_CFG_SET_COLOR_FORMAT(src_fmt);
val = SCALER_SRC_CFG_SET_COLOR_FORMAT(src_fmt) | (tile << 10);
scaler_write(val, SCALER_SRC_CFG);
}
@@ -188,15 +178,20 @@ static inline void scaler_set_src_span(struct scaler_context *scaler,
scaler_write(val, SCALER_SRC_SPAN);
}
static inline void scaler_set_src_luma_pos(struct scaler_context *scaler,
struct drm_exynos_ipp_task_rect *src_pos)
static inline void scaler_set_src_luma_chroma_pos(struct scaler_context *scaler,
struct drm_exynos_ipp_task_rect *src_pos,
const struct scaler_format *fmt)
{
u32 val;
val = SCALER_SRC_Y_POS_SET_YH_POS(src_pos->x << 2);
val |= SCALER_SRC_Y_POS_SET_YV_POS(src_pos->y << 2);
scaler_write(val, SCALER_SRC_Y_POS);
scaler_write(val, SCALER_SRC_C_POS); /* ATTENTION! */
val = SCALER_SRC_C_POS_SET_CH_POS(
(src_pos->x * fmt->chroma_tile_w / 16) << 2);
val |= SCALER_SRC_C_POS_SET_CV_POS(
(src_pos->y * fmt->chroma_tile_h / 16) << 2);
scaler_write(val, SCALER_SRC_C_POS);
}
static inline void scaler_set_src_wh(struct scaler_context *scaler,
@@ -366,11 +361,12 @@ static int scaler_commit(struct exynos_drm_ipp *ipp,
struct scaler_context *scaler =
container_of(ipp, struct scaler_context, ipp);
u32 src_fmt = scaler_get_format(task->src.buf.fourcc);
struct drm_exynos_ipp_task_rect *src_pos = &task->src.rect;
u32 dst_fmt = scaler_get_format(task->dst.buf.fourcc);
struct drm_exynos_ipp_task_rect *dst_pos = &task->dst.rect;
const struct scaler_format *src_fmt, *dst_fmt;
src_fmt = scaler_get_format(task->src.buf.fourcc);
dst_fmt = scaler_get_format(task->dst.buf.fourcc);
pm_runtime_get_sync(scaler->dev);
if (scaler_reset(scaler)) {
@@ -380,13 +376,14 @@ static int scaler_commit(struct exynos_drm_ipp *ipp,
scaler->task = task;
scaler_set_src_fmt(scaler, src_fmt);
scaler_set_src_fmt(
scaler, src_fmt->internal_fmt, task->src.buf.modifier != 0);
scaler_set_src_base(scaler, &task->src);
scaler_set_src_span(scaler, &task->src);
scaler_set_src_luma_pos(scaler, src_pos);
scaler_set_src_luma_chroma_pos(scaler, src_pos, src_fmt);
scaler_set_src_wh(scaler, src_pos);
scaler_set_dst_fmt(scaler, dst_fmt);
scaler_set_dst_fmt(scaler, dst_fmt->internal_fmt);
scaler_set_dst_base(scaler, &task->dst);
scaler_set_dst_span(scaler, &task->dst);
scaler_set_dst_luma_pos(scaler, dst_pos);
@@ -617,6 +614,16 @@ static const struct drm_exynos_ipp_limit scaler_5420_one_pixel_limits[] = {
.v = { 65536 * 1 / 4, 65536 * 16 }) },
};
static const struct drm_exynos_ipp_limit scaler_5420_tile_limits[] = {
{ IPP_SIZE_LIMIT(BUFFER, .h = { 16, SZ_8K }, .v = { 16, SZ_8K })},
{ IPP_SIZE_LIMIT(AREA, .h.align = 16, .v.align = 16) },
{ IPP_SCALE_LIMIT(.h = {1, 1}, .v = {1, 1})},
{ }
};
#define IPP_SRCDST_TILE_FORMAT(f, l) \
IPP_SRCDST_MFORMAT(f, DRM_FORMAT_MOD_SAMSUNG_16_16_TILE, (l))
static const struct exynos_drm_ipp_formats exynos5420_formats[] = {
/* SCALER_YUV420_2P_UV */
{ IPP_SRCDST_FORMAT(NV21, scaler_5420_two_pixel_hv_limits) },
@@ -680,6 +687,18 @@ static const struct exynos_drm_ipp_formats exynos5420_formats[] = {
/* SCALER_RGBA8888 */
{ IPP_SRCDST_FORMAT(RGBA8888, scaler_5420_one_pixel_limits) },
/* SCALER_YUV420_2P_UV TILE */
{ IPP_SRCDST_TILE_FORMAT(NV21, scaler_5420_tile_limits) },
/* SCALER_YUV420_2P_VU TILE */
{ IPP_SRCDST_TILE_FORMAT(NV12, scaler_5420_tile_limits) },
/* SCALER_YUV420_3P TILE */
{ IPP_SRCDST_TILE_FORMAT(YUV420, scaler_5420_tile_limits) },
/* SCALER_YUV422_1P_YUYV TILE */
{ IPP_SRCDST_TILE_FORMAT(YUYV, scaler_5420_tile_limits) },
};
static const struct scaler_data exynos5420_data = {

Переглянути файл

@@ -131,14 +131,18 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
.pixel_formats = mixer_formats,
.num_pixel_formats = ARRAY_SIZE(mixer_formats),
.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
EXYNOS_DRM_PLANE_CAP_ZPOS,
EXYNOS_DRM_PLANE_CAP_ZPOS |
EXYNOS_DRM_PLANE_CAP_PIX_BLEND |
EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
}, {
.zpos = 1,
.type = DRM_PLANE_TYPE_CURSOR,
.pixel_formats = mixer_formats,
.num_pixel_formats = ARRAY_SIZE(mixer_formats),
.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
EXYNOS_DRM_PLANE_CAP_ZPOS,
EXYNOS_DRM_PLANE_CAP_ZPOS |
EXYNOS_DRM_PLANE_CAP_PIX_BLEND |
EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
}, {
.zpos = 2,
.type = DRM_PLANE_TYPE_OVERLAY,
@@ -146,7 +150,8 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
.num_pixel_formats = ARRAY_SIZE(vp_formats),
.capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
EXYNOS_DRM_PLANE_CAP_ZPOS |
EXYNOS_DRM_PLANE_CAP_TILE,
EXYNOS_DRM_PLANE_CAP_TILE |
EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
},
};
@@ -309,31 +314,42 @@ static void vp_default_filter(struct mixer_context *ctx)
}
static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win,
bool alpha)
unsigned int pixel_alpha, unsigned int alpha)
{
u32 win_alpha = alpha >> 8;
u32 val;
val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
if (alpha) {
/* blending based on pixel alpha */
switch (pixel_alpha) {
case DRM_MODE_BLEND_PIXEL_NONE:
break;
case DRM_MODE_BLEND_COVERAGE:
val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
break;
case DRM_MODE_BLEND_PREMULTI:
default:
val |= MXR_GRP_CFG_BLEND_PRE_MUL;
val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
break;
}
if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
val |= MXR_GRP_CFG_WIN_BLEND_EN;
val |= win_alpha;
}
mixer_reg_writemask(ctx, MXR_GRAPHIC_CFG(win),
val, MXR_GRP_CFG_MISC_MASK);
}
static void mixer_cfg_vp_blend(struct mixer_context *ctx)
static void mixer_cfg_vp_blend(struct mixer_context *ctx, unsigned int alpha)
{
u32 val;
u32 win_alpha = alpha >> 8;
u32 val = 0;
/*
* No blending at the moment since the NV12/NV21 pixelformats don't
* have an alpha channel. However the mixer supports a global alpha
* value for a layer. Once this functionality is exposed, we can
* support blending of the video layer through this.
*/
val = 0;
if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
val |= MXR_VID_CFG_BLEND_EN;
val |= win_alpha;
}
mixer_reg_write(ctx, MXR_VIDEO_CFG, val);
}
@@ -529,7 +545,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
vp_reg_write(ctx, VP_BOT_C_PTR, chroma_addr[1]);
mixer_cfg_layer(ctx, plane->index, priority, true);
mixer_cfg_vp_blend(ctx);
mixer_cfg_vp_blend(ctx, state->base.alpha);
spin_unlock_irqrestore(&ctx->reg_slock, flags);
@@ -553,10 +569,16 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
unsigned int win = plane->index;
unsigned int x_ratio = 0, y_ratio = 0;
unsigned int dst_x_offset, dst_y_offset;
unsigned int pixel_alpha;
dma_addr_t dma_addr;
unsigned int fmt;
u32 val;
if (fb->format->has_alpha)
pixel_alpha = state->base.pixel_blend_mode;
else
pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
switch (fb->format->format) {
case DRM_FORMAT_XRGB4444:
case DRM_FORMAT_ARGB4444:
@@ -616,7 +638,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
mixer_reg_write(ctx, MXR_GRAPHIC_BASE(win), dma_addr);
mixer_cfg_layer(ctx, win, priority, true);
mixer_cfg_gfx_blend(ctx, win, fb->format->has_alpha);
mixer_cfg_gfx_blend(ctx, win, pixel_alpha, state->base.alpha);
/* layer update mandatory for mixer 16.0.33.0 */
if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||

Переглянути файл

@@ -109,12 +109,15 @@
#define MXR_CFG_SCAN_HD (1 << 0)
#define MXR_CFG_SCAN_MASK 0x47
/* bits for MXR_VIDEO_CFG */
#define MXR_VID_CFG_BLEND_EN (1 << 16)
/* bits for MXR_GRAPHICn_CFG */
#define MXR_GRP_CFG_COLOR_KEY_DISABLE (1 << 21)
#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20)
#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17)
#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16)
#define MXR_GRP_CFG_MISC_MASK ((3 << 16) | (3 << 20))
#define MXR_GRP_CFG_MISC_MASK ((3 << 16) | (3 << 20) | 0xff)
#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8)
#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0)
#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0)