mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
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 -----BEGIN PGP SIGNATURE----- iQJMBAABCgA2FiEEACwLKSDmq+9RDv5P4cpzo8lZTiQFAmbS51EYHGNodW5rdWFu Zy5odUBrZXJuZWwub3JnAAoJEOHKc6PJWU4kQMgP/06EQVDngO4eSFV1PrkGMnzG 7tXE9pmaaX3jzTa0ayIWe7WfJ5ICPKx9A4lAjJNKeX8Vhu/z+ZkDutlnJQ6UD3Kb PBAVFvvHycwER1pU7BLdLxRYCG/hW8POncFyDeDNqeAJ+RT+eEOs5eQMwqclNDTe 3jQv+M0mJsnrfgeNvvH7qoBPPdw/x/U2hLV6v4NPCDw3WTLkj4VfSSYys2uaDyOT AEp0qccLOeVfKgvLpxylIW36hqE4CURgs8k7REXc6yePnX8/sy/+UZt6ebxKDxbp H30HAo2+L3j6KNGhhdrVCIfqPxj5g+9DJtuK/4fAGKLmhjxOCl0DbiecT/IK+nfo 4oD1lq4qxZ46jmt+NYSrkXGQFA5Q1ffUgAXbZCDNppN03FRa3sAN+vSAKaVkMFE/ dY5b4Zl1nUekMxhySVAziVYw51A/DEB9f1CW4MoDumNTKgnxcA7wNjC5DGBENUqy +ew6dUD4QlODxhxlWnG5oKiFE+0qerFp36qnkCTVkre4nEmaAUOMmTFtkbXTsxur 6Y7L4Dq0YXYEhSpvhP46g9HNtdC32xbuL+msLZE/wecfvHy99vrE8ghGKCltgdBt u5qSRGb4gQfnk4rCFV9qMgV87lT3r+ve4Zw3NkqromyYDhB1A/981ejMeyBdblSN LoZwwK1jRKFULRv7MQNM =dgfr -----END PGP SIGNATURE----- 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: Dave 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
This commit is contained in:
commit
88a29f8c5f
@ -62,6 +62,9 @@ properties:
|
||||
- const: default
|
||||
- const: sleep
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
@ -76,6 +79,20 @@ required:
|
||||
- clock-names
|
||||
- port
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- mediatek,mt6795-dpi
|
||||
- mediatek,mt8173-dpi
|
||||
- mediatek,mt8186-dpi
|
||||
then:
|
||||
properties:
|
||||
power-domains: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -69,6 +69,8 @@ struct mtk_crtc {
|
||||
/* lock for display hardware access */
|
||||
struct mutex hw_lock;
|
||||
bool config_updating;
|
||||
/* lock for config_updating to cmd buffer */
|
||||
spinlock_t config_lock;
|
||||
};
|
||||
|
||||
struct mtk_crtc_state {
|
||||
@ -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)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
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) {
|
||||
mtk_crtc_finish_page_flip(mtk_crtc);
|
||||
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)
|
||||
{
|
||||
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
@ -158,7 +127,7 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
|
||||
|
||||
mtk_mutex_put(mtk_crtc->mutex);
|
||||
#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) {
|
||||
mbox_free_channel(mtk_crtc->cmdq_client.chan);
|
||||
@ -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_state *state;
|
||||
unsigned int i;
|
||||
unsigned long flags;
|
||||
|
||||
if (data->sta < 0)
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
if (mtk_crtc->pending_planes) {
|
||||
@ -340,6 +316,10 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
|
||||
mtk_crtc->pending_async_planes = false;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
|
||||
|
||||
ddp_cmdq_cb_out:
|
||||
|
||||
mtk_crtc->cmdq_vblank_cnt = 0;
|
||||
wake_up(&mtk_crtc->cb_blocking_queue);
|
||||
}
|
||||
@ -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_crtc *crtc = &mtk_crtc->base;
|
||||
unsigned long flags;
|
||||
int 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)
|
||||
pm_runtime_put(drm->dev);
|
||||
|
||||
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);
|
||||
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)
|
||||
struct mtk_drm_private *priv = crtc->dev->dev_private;
|
||||
unsigned int pending_planes = 0, pending_async_planes = 0;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&mtk_crtc->hw_lock);
|
||||
|
||||
spin_lock_irqsave(&mtk_crtc->config_lock, flags);
|
||||
mtk_crtc->config_updating = true;
|
||||
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
|
||||
|
||||
if (needs_vblank)
|
||||
mtk_crtc->pending_needs_vblank = true;
|
||||
|
||||
@ -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_wfe(cmdq_handle, mtk_crtc->cmdq_event, false);
|
||||
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,
|
||||
cmdq_handle->pa_base,
|
||||
cmdq_handle->cmd_buf_size,
|
||||
@ -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);
|
||||
}
|
||||
#endif
|
||||
spin_lock_irqsave(&mtk_crtc->config_lock, flags);
|
||||
mtk_crtc->config_updating = false;
|
||||
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
|
||||
|
||||
mutex_unlock(&mtk_crtc->hw_lock);
|
||||
}
|
||||
|
||||
@ -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_ddp_comp_supported_rotations(comp),
|
||||
mtk_ddp_comp_get_formats(comp),
|
||||
mtk_ddp_comp_get_num_formats(comp));
|
||||
mtk_ddp_comp_get_num_formats(comp), i);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -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_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
|
||||
mutex_init(&mtk_crtc->hw_lock);
|
||||
spin_lock_init(&mtk_crtc->config_lock);
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
i = priv->mbox_index++;
|
||||
@ -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);
|
||||
mtk_crtc->cmdq_client.chan = NULL;
|
||||
} else {
|
||||
ret = mtk_drm_cmdq_pkt_create(&mtk_crtc->cmdq_client,
|
||||
&mtk_crtc->cmdq_handle,
|
||||
PAGE_SIZE);
|
||||
ret = cmdq_pkt_create(&mtk_crtc->cmdq_client,
|
||||
&mtk_crtc->cmdq_handle,
|
||||
PAGE_SIZE);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "mtk_crtc %d failed to create cmdq packet\n",
|
||||
drm_crtc_index(&mtk_crtc->base));
|
||||
|
@ -56,8 +56,12 @@
|
||||
#define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4)
|
||||
#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_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_ARGB8888 (2 << 12)
|
||||
#define OVL_CON_CLRFMT_RGBA8888 (3 << 12)
|
||||
@ -65,6 +69,11 @@
|
||||
#define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
|
||||
#define OVL_CON_CLRFMT_UYVY (4 << 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 ? \
|
||||
0 : OVL_CON_CLRFMT_RGB)
|
||||
#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,
|
||||
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"
|
||||
* 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)
|
||||
case DRM_FORMAT_RGBA8888:
|
||||
case DRM_FORMAT_RGBX1010102:
|
||||
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_BGRA8888:
|
||||
case DRM_FORMAT_BGRX1010102:
|
||||
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_ARGB8888:
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
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_ABGR8888:
|
||||
case DRM_FORMAT_XBGR2101010:
|
||||
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:
|
||||
return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
|
||||
case DRM_FORMAT_YUYV:
|
||||
@ -434,6 +452,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
|
||||
unsigned int fmt = pending->format;
|
||||
unsigned int offset = (pending->y << 16) | pending->x;
|
||||
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 con;
|
||||
bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR;
|
||||
@ -452,7 +471,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
|
||||
return;
|
||||
}
|
||||
|
||||
con = ovl_fmt_convert(ovl, fmt);
|
||||
con = ovl_fmt_convert(ovl, fmt, blend_mode);
|
||||
if (state->base.fb) {
|
||||
con |= OVL_CON_AEN;
|
||||
con |= state->base.alpha & OVL_CON_ALPHA;
|
||||
@ -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
|
||||
* 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;
|
||||
|
||||
if (pending->rotation & DRM_MODE_REFLECT_Y) {
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/soc/mediatek/mtk-mmsys.h>
|
||||
#include <linux/soc/mediatek/mtk-mutex.h>
|
||||
|
||||
#include "mtk_crtc.h"
|
||||
#include "mtk_ddp_comp.h"
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_drv.h"
|
||||
@ -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)
|
||||
{
|
||||
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
|
||||
struct device_node *node, *parent;
|
||||
struct device_node *parent;
|
||||
struct platform_device *comp_pdev;
|
||||
|
||||
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;
|
||||
enum mtk_ovl_adaptor_comp_type type;
|
||||
int id;
|
||||
|
@ -341,14 +341,11 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
|
||||
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
|
||||
#endif
|
||||
|
||||
if (of_find_property(dev->of_node, "mediatek,rdma-fifo-size", &ret)) {
|
||||
ret = of_property_read_u32(dev->of_node,
|
||||
"mediatek,rdma-fifo-size",
|
||||
&priv->fifo_size);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to get rdma fifo size\n");
|
||||
}
|
||||
ret = of_property_read_u32(dev->of_node,
|
||||
"mediatek,rdma-fifo-size",
|
||||
&priv->fifo_size);
|
||||
if (ret && (ret != -EINVAL))
|
||||
return dev_err_probe(dev, ret, "Failed to get rdma fifo size\n");
|
||||
|
||||
/* Disable and clear pending interrupts */
|
||||
writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
|
||||
|
@ -88,12 +88,15 @@
|
||||
#define DSI_HSA_WC 0x50
|
||||
#define DSI_HBP_WC 0x54
|
||||
#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 CMDQ_SIZE 0x3f
|
||||
#define CMDQ_SIZE_SEL BIT(15)
|
||||
|
||||
#define DSI_HSTX_CKL_WC 0x64
|
||||
#define HSTX_CKL_WC GENMASK(15, 2)
|
||||
|
||||
#define DSI_RX_DATA0 0x74
|
||||
#define DSI_RX_DATA1 0x78
|
||||
@ -187,6 +190,7 @@ struct mtk_dsi_driver_data {
|
||||
bool has_shadow_ctl;
|
||||
bool has_size_ctl;
|
||||
bool cmdq_long_packet_ctl;
|
||||
bool support_per_frame_lp;
|
||||
};
|
||||
|
||||
struct mtk_dsi {
|
||||
@ -426,7 +430,75 @@ static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact)
|
||||
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_backporch_byte;
|
||||
@ -436,7 +508,6 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
|
||||
u32 dsi_tmp_buf_bpp, data_phy_cycles;
|
||||
u32 delta;
|
||||
struct mtk_phy_timing *timing = &dsi->phy_timing;
|
||||
|
||||
struct videomode *vm = &dsi->vm;
|
||||
|
||||
if (dsi->format == MIPI_DSI_FMT_RGB565)
|
||||
@ -444,16 +515,6 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
|
||||
else
|
||||
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);
|
||||
|
||||
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)
|
||||
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(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);
|
||||
}
|
||||
@ -1197,6 +1278,7 @@ static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = {
|
||||
.has_shadow_ctl = true,
|
||||
.has_size_ctl = true,
|
||||
.cmdq_long_packet_ctl = true,
|
||||
.support_per_frame_lp = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_dsi_of_match[] = {
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <linux/clk.h>
|
||||
@ -35,6 +36,7 @@
|
||||
#define MIX_SRC_L0_EN BIT(0)
|
||||
#define MIX_L_SRC_CON(n) (0x28 + 0x18 * (n))
|
||||
#define NON_PREMULTI_SOURCE (2 << 12)
|
||||
#define PREMULTI_SOURCE (3 << 12)
|
||||
#define MIX_L_SRC_SIZE(n) (0x30 + 0x18 * (n))
|
||||
#define MIX_L_SRC_OFFSET(n) (0x34 + 0x18 * (n))
|
||||
#define MIX_FUNC_DCM0 0x120
|
||||
@ -175,7 +177,13 @@ void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
|
||||
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,
|
||||
* use a trick to make the output equivalent
|
||||
@ -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,
|
||||
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_mask(cmdq_pkt, alpha_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx),
|
||||
0x1ff);
|
||||
mtk_ddp_write(cmdq_pkt, alpha_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx));
|
||||
mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base, mixer->regs, MIX_SRC_CON,
|
||||
BIT(idx));
|
||||
}
|
||||
|
@ -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,
|
||||
unsigned long possible_crtcs, enum drm_plane_type type,
|
||||
unsigned int supported_rotations, const u32 *formats,
|
||||
size_t num_formats)
|
||||
size_t num_formats, unsigned int plane_idx)
|
||||
{
|
||||
int err;
|
||||
|
||||
@ -338,6 +338,22 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
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) {
|
||||
err = drm_plane_create_rotation_property(plane,
|
||||
DRM_MODE_ROTATE_0,
|
||||
@ -346,6 +362,17 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
@ -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,
|
||||
unsigned long possible_crtcs, enum drm_plane_type type,
|
||||
unsigned int supported_rotations, const u32 *formats,
|
||||
size_t num_formats);
|
||||
|
||||
size_t num_formats, unsigned int plane_idx);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user