Commit 88a29f8c authored by Dave Airlie's avatar Dave Airlie

Merge tag 'mediatek-drm-next-6.12' of...

Merge tag 'mediatek-drm-next-6.12' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux into drm-next

Mediatek DRM Next for Linux 6.12

1. Support alpha blending
2. Remove cl in struct cmdq_pkt
3. Fixup for ovl adaptor
4. Declare Z Position for all planes
5. Drop unnecessary check for property presence
6. Add dsi per-frame lp code for mt8188
7. Fix missing configuration flags in mtk_crtc_ddp_config()
8. Use spin_lock_irqsave() for CRTC event lock
9. Add power domain binding to the mediatek DPI controller
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20240901131354.2686-1-chunkuang.hu@kernel.org
parents eb7205b7 5474d49b
...@@ -62,6 +62,9 @@ properties: ...@@ -62,6 +62,9 @@ properties:
- const: default - const: default
- const: sleep - const: sleep
power-domains:
maxItems: 1
port: port:
$ref: /schemas/graph.yaml#/properties/port $ref: /schemas/graph.yaml#/properties/port
description: description:
...@@ -76,6 +79,20 @@ required: ...@@ -76,6 +79,20 @@ required:
- clock-names - clock-names
- port - port
allOf:
- if:
not:
properties:
compatible:
contains:
enum:
- mediatek,mt6795-dpi
- mediatek,mt8173-dpi
- mediatek,mt8186-dpi
then:
properties:
power-domains: false
additionalProperties: false additionalProperties: false
examples: examples:
......
...@@ -69,6 +69,8 @@ struct mtk_crtc { ...@@ -69,6 +69,8 @@ struct mtk_crtc {
/* lock for display hardware access */ /* lock for display hardware access */
struct mutex hw_lock; struct mutex hw_lock;
bool config_updating; bool config_updating;
/* lock for config_updating to cmd buffer */
spinlock_t config_lock;
}; };
struct mtk_crtc_state { struct mtk_crtc_state {
...@@ -106,51 +108,18 @@ static void mtk_crtc_finish_page_flip(struct mtk_crtc *mtk_crtc) ...@@ -106,51 +108,18 @@ static void mtk_crtc_finish_page_flip(struct mtk_crtc *mtk_crtc)
static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc) static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc)
{ {
unsigned long flags;
drm_crtc_handle_vblank(&mtk_crtc->base); drm_crtc_handle_vblank(&mtk_crtc->base);
spin_lock_irqsave(&mtk_crtc->config_lock, flags);
if (!mtk_crtc->config_updating && mtk_crtc->pending_needs_vblank) { if (!mtk_crtc->config_updating && mtk_crtc->pending_needs_vblank) {
mtk_crtc_finish_page_flip(mtk_crtc); mtk_crtc_finish_page_flip(mtk_crtc);
mtk_crtc->pending_needs_vblank = false; mtk_crtc->pending_needs_vblank = false;
} }
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
} }
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
static int mtk_drm_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt,
size_t size)
{
struct device *dev;
dma_addr_t dma_addr;
pkt->va_base = kzalloc(size, GFP_KERNEL);
if (!pkt->va_base)
return -ENOMEM;
pkt->buf_size = size;
pkt->cl = (void *)client;
dev = client->chan->mbox->dev;
dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma_addr)) {
dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
kfree(pkt->va_base);
return -ENOMEM;
}
pkt->pa_base = dma_addr;
return 0;
}
static void mtk_drm_cmdq_pkt_destroy(struct cmdq_pkt *pkt)
{
struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
DMA_TO_DEVICE);
kfree(pkt->va_base);
}
#endif
static void mtk_crtc_destroy(struct drm_crtc *crtc) static void mtk_crtc_destroy(struct drm_crtc *crtc)
{ {
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
...@@ -158,7 +127,7 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc) ...@@ -158,7 +127,7 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
mtk_mutex_put(mtk_crtc->mutex); mtk_mutex_put(mtk_crtc->mutex);
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
mtk_drm_cmdq_pkt_destroy(&mtk_crtc->cmdq_handle); cmdq_pkt_destroy(&mtk_crtc->cmdq_client, &mtk_crtc->cmdq_handle);
if (mtk_crtc->cmdq_client.chan) { if (mtk_crtc->cmdq_client.chan) {
mbox_free_channel(mtk_crtc->cmdq_client.chan); mbox_free_channel(mtk_crtc->cmdq_client.chan);
...@@ -308,12 +277,19 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) ...@@ -308,12 +277,19 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
struct mtk_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_crtc, cmdq_client); struct mtk_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_crtc, cmdq_client);
struct mtk_crtc_state *state; struct mtk_crtc_state *state;
unsigned int i; unsigned int i;
unsigned long flags;
if (data->sta < 0) if (data->sta < 0)
return; return;
state = to_mtk_crtc_state(mtk_crtc->base.state); state = to_mtk_crtc_state(mtk_crtc->base.state);
spin_lock_irqsave(&mtk_crtc->config_lock, flags);
if (mtk_crtc->config_updating) {
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
goto ddp_cmdq_cb_out;
}
state->pending_config = false; state->pending_config = false;
if (mtk_crtc->pending_planes) { if (mtk_crtc->pending_planes) {
...@@ -340,6 +316,10 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) ...@@ -340,6 +316,10 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
mtk_crtc->pending_async_planes = false; mtk_crtc->pending_async_planes = false;
} }
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
ddp_cmdq_cb_out:
mtk_crtc->cmdq_vblank_cnt = 0; mtk_crtc->cmdq_vblank_cnt = 0;
wake_up(&mtk_crtc->cb_blocking_queue); wake_up(&mtk_crtc->cb_blocking_queue);
} }
...@@ -449,6 +429,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc) ...@@ -449,6 +429,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
{ {
struct drm_device *drm = mtk_crtc->base.dev; struct drm_device *drm = mtk_crtc->base.dev;
struct drm_crtc *crtc = &mtk_crtc->base; struct drm_crtc *crtc = &mtk_crtc->base;
unsigned long flags;
int i; int i;
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
...@@ -480,10 +461,10 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc) ...@@ -480,10 +461,10 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
pm_runtime_put(drm->dev); pm_runtime_put(drm->dev);
if (crtc->state->event && !crtc->state->active) { if (crtc->state->event && !crtc->state->active) {
spin_lock_irq(&crtc->dev->event_lock); spin_lock_irqsave(&crtc->dev->event_lock, flags);
drm_crtc_send_vblank_event(crtc, crtc->state->event); drm_crtc_send_vblank_event(crtc, crtc->state->event);
crtc->state->event = NULL; crtc->state->event = NULL;
spin_unlock_irq(&crtc->dev->event_lock); spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
} }
} }
...@@ -569,9 +550,14 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank) ...@@ -569,9 +550,14 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
struct mtk_drm_private *priv = crtc->dev->dev_private; struct mtk_drm_private *priv = crtc->dev->dev_private;
unsigned int pending_planes = 0, pending_async_planes = 0; unsigned int pending_planes = 0, pending_async_planes = 0;
int i; int i;
unsigned long flags;
mutex_lock(&mtk_crtc->hw_lock); mutex_lock(&mtk_crtc->hw_lock);
spin_lock_irqsave(&mtk_crtc->config_lock, flags);
mtk_crtc->config_updating = true; mtk_crtc->config_updating = true;
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
if (needs_vblank) if (needs_vblank)
mtk_crtc->pending_needs_vblank = true; mtk_crtc->pending_needs_vblank = true;
...@@ -607,7 +593,7 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank) ...@@ -607,7 +593,7 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false);
mtk_crtc_ddp_config(crtc, cmdq_handle); mtk_crtc_ddp_config(crtc, cmdq_handle);
cmdq_pkt_finalize(cmdq_handle); cmdq_pkt_eoc(cmdq_handle);
dma_sync_single_for_device(mtk_crtc->cmdq_client.chan->mbox->dev, dma_sync_single_for_device(mtk_crtc->cmdq_client.chan->mbox->dev,
cmdq_handle->pa_base, cmdq_handle->pa_base,
cmdq_handle->cmd_buf_size, cmdq_handle->cmd_buf_size,
...@@ -625,7 +611,10 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank) ...@@ -625,7 +611,10 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0); mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
} }
#endif #endif
spin_lock_irqsave(&mtk_crtc->config_lock, flags);
mtk_crtc->config_updating = false; mtk_crtc->config_updating = false;
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
mutex_unlock(&mtk_crtc->hw_lock); mutex_unlock(&mtk_crtc->hw_lock);
} }
...@@ -925,7 +914,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, ...@@ -925,7 +914,7 @@ static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev,
mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes),
mtk_ddp_comp_supported_rotations(comp), mtk_ddp_comp_supported_rotations(comp),
mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_formats(comp),
mtk_ddp_comp_get_num_formats(comp)); mtk_ddp_comp_get_num_formats(comp), i);
if (ret) if (ret)
return ret; return ret;
...@@ -1068,6 +1057,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path, ...@@ -1068,6 +1057,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size); drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size); drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
mutex_init(&mtk_crtc->hw_lock); mutex_init(&mtk_crtc->hw_lock);
spin_lock_init(&mtk_crtc->config_lock);
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
i = priv->mbox_index++; i = priv->mbox_index++;
...@@ -1094,9 +1084,9 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path, ...@@ -1094,9 +1084,9 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
mbox_free_channel(mtk_crtc->cmdq_client.chan); mbox_free_channel(mtk_crtc->cmdq_client.chan);
mtk_crtc->cmdq_client.chan = NULL; mtk_crtc->cmdq_client.chan = NULL;
} else { } else {
ret = mtk_drm_cmdq_pkt_create(&mtk_crtc->cmdq_client, ret = cmdq_pkt_create(&mtk_crtc->cmdq_client,
&mtk_crtc->cmdq_handle, &mtk_crtc->cmdq_handle,
PAGE_SIZE); PAGE_SIZE);
if (ret) { if (ret) {
dev_dbg(dev, "mtk_crtc %d failed to create cmdq packet\n", dev_dbg(dev, "mtk_crtc %d failed to create cmdq packet\n",
drm_crtc_index(&mtk_crtc->base)); drm_crtc_index(&mtk_crtc->base));
......
...@@ -56,8 +56,12 @@ ...@@ -56,8 +56,12 @@
#define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4) #define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4)
#define GMC_THRESHOLD_LOW ((1 << GMC_THRESHOLD_BITS) / 8) #define GMC_THRESHOLD_LOW ((1 << GMC_THRESHOLD_BITS) / 8)
#define OVL_CON_CLRFMT_MAN BIT(23)
#define OVL_CON_BYTE_SWAP BIT(24) #define OVL_CON_BYTE_SWAP BIT(24)
#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
/* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
#define OVL_CON_RGB_SWAP BIT(25)
#define OVL_CON_CLRFMT_RGB (1 << 12) #define OVL_CON_CLRFMT_RGB (1 << 12)
#define OVL_CON_CLRFMT_ARGB8888 (2 << 12) #define OVL_CON_CLRFMT_ARGB8888 (2 << 12)
#define OVL_CON_CLRFMT_RGBA8888 (3 << 12) #define OVL_CON_CLRFMT_RGBA8888 (3 << 12)
...@@ -65,6 +69,11 @@ ...@@ -65,6 +69,11 @@
#define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP) #define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_UYVY (4 << 12) #define OVL_CON_CLRFMT_UYVY (4 << 12)
#define OVL_CON_CLRFMT_YUYV (5 << 12) #define OVL_CON_CLRFMT_YUYV (5 << 12)
#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
#define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ #define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
0 : OVL_CON_CLRFMT_RGB) 0 : OVL_CON_CLRFMT_RGB)
#define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ #define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
...@@ -377,7 +386,8 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx, ...@@ -377,7 +386,8 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
DISP_REG_OVL_RDMA_CTRL(idx)); DISP_REG_OVL_RDMA_CTRL(idx));
} }
static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt,
unsigned int blend_mode)
{ {
/* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX"
* is defined in mediatek HW data sheet. * is defined in mediatek HW data sheet.
...@@ -398,22 +408,30 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) ...@@ -398,22 +408,30 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
case DRM_FORMAT_RGBA8888: case DRM_FORMAT_RGBA8888:
case DRM_FORMAT_RGBX1010102: case DRM_FORMAT_RGBX1010102:
case DRM_FORMAT_RGBA1010102: case DRM_FORMAT_RGBA1010102:
return OVL_CON_CLRFMT_RGBA8888; return blend_mode == DRM_MODE_BLEND_COVERAGE ?
OVL_CON_CLRFMT_RGBA8888 :
OVL_CON_CLRFMT_PRGBA8888;
case DRM_FORMAT_BGRX8888: case DRM_FORMAT_BGRX8888:
case DRM_FORMAT_BGRA8888: case DRM_FORMAT_BGRA8888:
case DRM_FORMAT_BGRX1010102: case DRM_FORMAT_BGRX1010102:
case DRM_FORMAT_BGRA1010102: case DRM_FORMAT_BGRA1010102:
return OVL_CON_CLRFMT_BGRA8888; return blend_mode == DRM_MODE_BLEND_COVERAGE ?
OVL_CON_CLRFMT_BGRA8888 :
OVL_CON_CLRFMT_PBGRA8888;
case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_ARGB2101010:
return OVL_CON_CLRFMT_ARGB8888; return blend_mode == DRM_MODE_BLEND_COVERAGE ?
OVL_CON_CLRFMT_ARGB8888 :
OVL_CON_CLRFMT_PARGB8888;
case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888: case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_ABGR2101010:
return OVL_CON_CLRFMT_ABGR8888; return blend_mode == DRM_MODE_BLEND_COVERAGE ?
OVL_CON_CLRFMT_ABGR8888 :
OVL_CON_CLRFMT_PABGR8888;
case DRM_FORMAT_UYVY: case DRM_FORMAT_UYVY:
return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB; return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
case DRM_FORMAT_YUYV: case DRM_FORMAT_YUYV:
...@@ -434,6 +452,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, ...@@ -434,6 +452,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
unsigned int fmt = pending->format; unsigned int fmt = pending->format;
unsigned int offset = (pending->y << 16) | pending->x; unsigned int offset = (pending->y << 16) | pending->x;
unsigned int src_size = (pending->height << 16) | pending->width; unsigned int src_size = (pending->height << 16) | pending->width;
unsigned int blend_mode = state->base.pixel_blend_mode;
unsigned int ignore_pixel_alpha = 0; unsigned int ignore_pixel_alpha = 0;
unsigned int con; unsigned int con;
bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR; bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR;
...@@ -452,7 +471,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, ...@@ -452,7 +471,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
return; return;
} }
con = ovl_fmt_convert(ovl, fmt); con = ovl_fmt_convert(ovl, fmt, blend_mode);
if (state->base.fb) { if (state->base.fb) {
con |= OVL_CON_AEN; con |= OVL_CON_AEN;
con |= state->base.alpha & OVL_CON_ALPHA; con |= state->base.alpha & OVL_CON_ALPHA;
...@@ -463,7 +482,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, ...@@ -463,7 +482,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
* For RGB888 related formats, whether CONST_BLD is enabled or not won't * For RGB888 related formats, whether CONST_BLD is enabled or not won't
* affect the result. Therefore we use !has_alpha as the condition. * affect the result. Therefore we use !has_alpha as the condition.
*/ */
if (state->base.fb && !state->base.fb->format->has_alpha) if ((state->base.fb && !state->base.fb->format->has_alpha) ||
blend_mode == DRM_MODE_BLEND_PIXEL_NONE)
ignore_pixel_alpha = OVL_CONST_BLEND; ignore_pixel_alpha = OVL_CONST_BLEND;
if (pending->rotation & DRM_MODE_REFLECT_Y) { if (pending->rotation & DRM_MODE_REFLECT_Y) {
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/soc/mediatek/mtk-mmsys.h> #include <linux/soc/mediatek/mtk-mmsys.h>
#include <linux/soc/mediatek/mtk-mutex.h> #include <linux/soc/mediatek/mtk-mutex.h>
#include "mtk_crtc.h"
#include "mtk_ddp_comp.h" #include "mtk_ddp_comp.h"
#include "mtk_disp_drv.h" #include "mtk_disp_drv.h"
#include "mtk_drm_drv.h" #include "mtk_drm_drv.h"
...@@ -494,12 +493,12 @@ static int compare_of(struct device *dev, void *data) ...@@ -494,12 +493,12 @@ static int compare_of(struct device *dev, void *data)
static int ovl_adaptor_comp_init(struct device *dev, struct component_match **match) static int ovl_adaptor_comp_init(struct device *dev, struct component_match **match)
{ {
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev); struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
struct device_node *node, *parent; struct device_node *parent;
struct platform_device *comp_pdev; struct platform_device *comp_pdev;
parent = dev->parent->parent->of_node->parent; parent = dev->parent->parent->of_node->parent;
for_each_child_of_node(parent, node) { for_each_child_of_node_scoped(parent, node) {
const struct of_device_id *of_id; const struct of_device_id *of_id;
enum mtk_ovl_adaptor_comp_type type; enum mtk_ovl_adaptor_comp_type type;
int id; int id;
......
...@@ -341,14 +341,11 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev) ...@@ -341,14 +341,11 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n"); dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
#endif #endif
if (of_find_property(dev->of_node, "mediatek,rdma-fifo-size", &ret)) { ret = of_property_read_u32(dev->of_node,
ret = of_property_read_u32(dev->of_node, "mediatek,rdma-fifo-size",
"mediatek,rdma-fifo-size", &priv->fifo_size);
&priv->fifo_size); if (ret && (ret != -EINVAL))
if (ret) return dev_err_probe(dev, ret, "Failed to get rdma fifo size\n");
return dev_err_probe(dev, ret,
"Failed to get rdma fifo size\n");
}
/* Disable and clear pending interrupts */ /* Disable and clear pending interrupts */
writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE); writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
......
...@@ -88,12 +88,15 @@ ...@@ -88,12 +88,15 @@
#define DSI_HSA_WC 0x50 #define DSI_HSA_WC 0x50
#define DSI_HBP_WC 0x54 #define DSI_HBP_WC 0x54
#define DSI_HFP_WC 0x58 #define DSI_HFP_WC 0x58
#define HFP_HS_VB_PS_WC GENMASK(30, 16)
#define HFP_HS_EN BIT(31)
#define DSI_CMDQ_SIZE 0x60 #define DSI_CMDQ_SIZE 0x60
#define CMDQ_SIZE 0x3f #define CMDQ_SIZE 0x3f
#define CMDQ_SIZE_SEL BIT(15) #define CMDQ_SIZE_SEL BIT(15)
#define DSI_HSTX_CKL_WC 0x64 #define DSI_HSTX_CKL_WC 0x64
#define HSTX_CKL_WC GENMASK(15, 2)
#define DSI_RX_DATA0 0x74 #define DSI_RX_DATA0 0x74
#define DSI_RX_DATA1 0x78 #define DSI_RX_DATA1 0x78
...@@ -187,6 +190,7 @@ struct mtk_dsi_driver_data { ...@@ -187,6 +190,7 @@ struct mtk_dsi_driver_data {
bool has_shadow_ctl; bool has_shadow_ctl;
bool has_size_ctl; bool has_size_ctl;
bool cmdq_long_packet_ctl; bool cmdq_long_packet_ctl;
bool support_per_frame_lp;
}; };
struct mtk_dsi { struct mtk_dsi {
...@@ -426,7 +430,75 @@ static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact) ...@@ -426,7 +430,75 @@ static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact)
writel(ps_val, dsi->regs + DSI_PSCTRL); writel(ps_val, dsi->regs + DSI_PSCTRL);
} }
static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) static void mtk_dsi_config_vdo_timing_per_frame_lp(struct mtk_dsi *dsi)
{
u32 horizontal_sync_active_byte;
u32 horizontal_backporch_byte;
u32 horizontal_frontporch_byte;
u32 hfp_byte_adjust, v_active_adjust;
u32 cklp_wc_min_adjust, cklp_wc_max_adjust;
u32 dsi_tmp_buf_bpp;
unsigned int da_hs_trail;
unsigned int ps_wc, hs_vb_ps_wc;
u32 v_active_roundup, hstx_cklp_wc;
u32 hstx_cklp_wc_max, hstx_cklp_wc_min;
struct videomode *vm = &dsi->vm;
if (dsi->format == MIPI_DSI_FMT_RGB565)
dsi_tmp_buf_bpp = 2;
else
dsi_tmp_buf_bpp = 3;
da_hs_trail = dsi->phy_timing.da_hs_trail;
ps_wc = vm->hactive * dsi_tmp_buf_bpp;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
horizontal_sync_active_byte =
vm->hsync_len * dsi_tmp_buf_bpp - 10;
horizontal_backporch_byte =
vm->hback_porch * dsi_tmp_buf_bpp - 10;
hfp_byte_adjust = 12;
v_active_adjust = 32 + horizontal_sync_active_byte;
cklp_wc_min_adjust = 12 + 2 + 4 + horizontal_sync_active_byte;
cklp_wc_max_adjust = 20 + 6 + 4 + horizontal_sync_active_byte;
} else {
horizontal_sync_active_byte = vm->hsync_len * dsi_tmp_buf_bpp - 4;
horizontal_backporch_byte = (vm->hback_porch + vm->hsync_len) *
dsi_tmp_buf_bpp - 10;
cklp_wc_min_adjust = 4;
cklp_wc_max_adjust = 12 + 4 + 4;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
hfp_byte_adjust = 18;
v_active_adjust = 28;
} else {
hfp_byte_adjust = 12;
v_active_adjust = 22;
}
}
horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp - hfp_byte_adjust;
v_active_roundup = (v_active_adjust + horizontal_backporch_byte + ps_wc +
horizontal_frontporch_byte) % dsi->lanes;
if (v_active_roundup)
horizontal_backporch_byte += dsi->lanes - v_active_roundup;
hstx_cklp_wc_min = (DIV_ROUND_UP(cklp_wc_min_adjust, dsi->lanes) + da_hs_trail + 1)
* dsi->lanes / 6 - 1;
hstx_cklp_wc_max = (DIV_ROUND_UP((cklp_wc_max_adjust + horizontal_backporch_byte +
ps_wc), dsi->lanes) + da_hs_trail + 1) * dsi->lanes / 6 - 1;
hstx_cklp_wc = FIELD_PREP(HSTX_CKL_WC, (hstx_cklp_wc_min + hstx_cklp_wc_max) / 2);
writel(hstx_cklp_wc, dsi->regs + DSI_HSTX_CKL_WC);
hs_vb_ps_wc = ps_wc - (dsi->phy_timing.lpx + dsi->phy_timing.da_hs_exit +
dsi->phy_timing.da_hs_prepare + dsi->phy_timing.da_hs_zero + 2) * dsi->lanes;
horizontal_frontporch_byte |= FIELD_PREP(HFP_HS_EN, 1) |
FIELD_PREP(HFP_HS_VB_PS_WC, hs_vb_ps_wc);
writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC);
writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC);
}
static void mtk_dsi_config_vdo_timing_per_line_lp(struct mtk_dsi *dsi)
{ {
u32 horizontal_sync_active_byte; u32 horizontal_sync_active_byte;
u32 horizontal_backporch_byte; u32 horizontal_backporch_byte;
...@@ -436,7 +508,6 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) ...@@ -436,7 +508,6 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
u32 dsi_tmp_buf_bpp, data_phy_cycles; u32 dsi_tmp_buf_bpp, data_phy_cycles;
u32 delta; u32 delta;
struct mtk_phy_timing *timing = &dsi->phy_timing; struct mtk_phy_timing *timing = &dsi->phy_timing;
struct videomode *vm = &dsi->vm; struct videomode *vm = &dsi->vm;
if (dsi->format == MIPI_DSI_FMT_RGB565) if (dsi->format == MIPI_DSI_FMT_RGB565)
...@@ -444,16 +515,6 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) ...@@ -444,16 +515,6 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
else else
dsi_tmp_buf_bpp = 3; dsi_tmp_buf_bpp = 3;
writel(vm->vsync_len, dsi->regs + DSI_VSA_NL);
writel(vm->vback_porch, dsi->regs + DSI_VBP_NL);
writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL);
writel(vm->vactive, dsi->regs + DSI_VACT_NL);
if (dsi->driver_data->has_size_ctl)
writel(FIELD_PREP(DSI_HEIGHT, vm->vactive) |
FIELD_PREP(DSI_WIDTH, vm->hactive),
dsi->regs + DSI_SIZE_CON);
horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10); horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10);
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
...@@ -499,6 +560,26 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) ...@@ -499,6 +560,26 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC); writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC); writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC);
writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC); writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC);
}
static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
{
struct videomode *vm = &dsi->vm;
writel(vm->vsync_len, dsi->regs + DSI_VSA_NL);
writel(vm->vback_porch, dsi->regs + DSI_VBP_NL);
writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL);
writel(vm->vactive, dsi->regs + DSI_VACT_NL);
if (dsi->driver_data->has_size_ctl)
writel(FIELD_PREP(DSI_HEIGHT, vm->vactive) |
FIELD_PREP(DSI_WIDTH, vm->hactive),
dsi->regs + DSI_SIZE_CON);
if (dsi->driver_data->support_per_frame_lp)
mtk_dsi_config_vdo_timing_per_frame_lp(dsi);
else
mtk_dsi_config_vdo_timing_per_line_lp(dsi);
mtk_dsi_ps_control(dsi, false); mtk_dsi_ps_control(dsi, false);
} }
...@@ -1197,6 +1278,7 @@ static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = { ...@@ -1197,6 +1278,7 @@ static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = {
.has_shadow_ctl = true, .has_shadow_ctl = true,
.has_size_ctl = true, .has_size_ctl = true,
.cmdq_long_packet_ctl = true, .cmdq_long_packet_ctl = true,
.support_per_frame_lp = true,
}; };
static const struct of_device_id mtk_dsi_of_match[] = { static const struct of_device_id mtk_dsi_of_match[] = {
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Copyright (c) 2021 MediaTek Inc. * Copyright (c) 2021 MediaTek Inc.
*/ */
#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h> #include <drm/drm_framebuffer.h>
#include <linux/clk.h> #include <linux/clk.h>
...@@ -35,6 +36,7 @@ ...@@ -35,6 +36,7 @@
#define MIX_SRC_L0_EN BIT(0) #define MIX_SRC_L0_EN BIT(0)
#define MIX_L_SRC_CON(n) (0x28 + 0x18 * (n)) #define MIX_L_SRC_CON(n) (0x28 + 0x18 * (n))
#define NON_PREMULTI_SOURCE (2 << 12) #define NON_PREMULTI_SOURCE (2 << 12)
#define PREMULTI_SOURCE (3 << 12)
#define MIX_L_SRC_SIZE(n) (0x30 + 0x18 * (n)) #define MIX_L_SRC_SIZE(n) (0x30 + 0x18 * (n))
#define MIX_L_SRC_OFFSET(n) (0x34 + 0x18 * (n)) #define MIX_L_SRC_OFFSET(n) (0x34 + 0x18 * (n))
#define MIX_FUNC_DCM0 0x120 #define MIX_FUNC_DCM0 0x120
...@@ -175,7 +177,13 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx, ...@@ -175,7 +177,13 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
alpha_con |= state->base.alpha & MIXER_ALPHA; alpha_con |= state->base.alpha & MIXER_ALPHA;
} }
if (state->base.fb && !state->base.fb->format->has_alpha) { if (state->base.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
alpha_con |= PREMULTI_SOURCE;
else
alpha_con |= NON_PREMULTI_SOURCE;
if ((state->base.fb && !state->base.fb->format->has_alpha) ||
state->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE) {
/* /*
* Mixer doesn't support CONST_BLD mode, * Mixer doesn't support CONST_BLD mode,
* use a trick to make the output equivalent * use a trick to make the output equivalent
...@@ -191,8 +199,7 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx, ...@@ -191,8 +199,7 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &mixer->cmdq_base, mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &mixer->cmdq_base,
mixer->regs, MIX_L_SRC_SIZE(idx)); mixer->regs, MIX_L_SRC_SIZE(idx));
mtk_ddp_write(cmdq_pkt, offset, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_OFFSET(idx)); mtk_ddp_write(cmdq_pkt, offset, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_OFFSET(idx));
mtk_ddp_write_mask(cmdq_pkt, alpha_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx), mtk_ddp_write(cmdq_pkt, alpha_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx));
0x1ff);
mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base, mixer->regs, MIX_SRC_CON, mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base, mixer->regs, MIX_SRC_CON,
BIT(idx)); BIT(idx));
} }
......
...@@ -321,7 +321,7 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = { ...@@ -321,7 +321,7 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
unsigned long possible_crtcs, enum drm_plane_type type, unsigned long possible_crtcs, enum drm_plane_type type,
unsigned int supported_rotations, const u32 *formats, unsigned int supported_rotations, const u32 *formats,
size_t num_formats) size_t num_formats, unsigned int plane_idx)
{ {
int err; int err;
...@@ -338,6 +338,22 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, ...@@ -338,6 +338,22 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
return err; return err;
} }
/*
* The hardware does not support repositioning planes by muxing: their
* Z-position is infact fixed and the only way to change the actual
* order is to swap the contents of the entire register set of one
* overlay with another, which may be more expensive than desired.
*
* With no repositioning, the caller of this function guarantees that
* the plane_idx is correct. This means that, for example, the PRIMARY
* plane fed to this function will always have plane_idx zero.
*/
err = drm_plane_create_zpos_immutable_property(plane, plane_idx);
if (err) {
DRM_ERROR("Failed to create zpos property for plane %u\n", plane_idx);
return err;
}
if (supported_rotations) { if (supported_rotations) {
err = drm_plane_create_rotation_property(plane, err = drm_plane_create_rotation_property(plane,
DRM_MODE_ROTATE_0, DRM_MODE_ROTATE_0,
...@@ -346,6 +362,17 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, ...@@ -346,6 +362,17 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
DRM_INFO("Create rotation property failed\n"); DRM_INFO("Create rotation property failed\n");
} }
err = drm_plane_create_alpha_property(plane);
if (err)
DRM_ERROR("failed to create property: alpha\n");
err = drm_plane_create_blend_mode_property(plane,
BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE) |
BIT(DRM_MODE_BLEND_PIXEL_NONE));
if (err)
DRM_ERROR("failed to create property: blend_mode\n");
drm_plane_helper_add(plane, &mtk_plane_helper_funcs); drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
return 0; return 0;
......
...@@ -49,6 +49,5 @@ to_mtk_plane_state(struct drm_plane_state *state) ...@@ -49,6 +49,5 @@ to_mtk_plane_state(struct drm_plane_state *state)
int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
unsigned long possible_crtcs, enum drm_plane_type type, unsigned long possible_crtcs, enum drm_plane_type type,
unsigned int supported_rotations, const u32 *formats, unsigned int supported_rotations, const u32 *formats,
size_t num_formats); size_t num_formats, unsigned int plane_idx);
#endif #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