6db4831e98
Android 14
585 lines
16 KiB
C
585 lines
16 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#include <drm/drmP.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/component.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/soc/mediatek/mtk-cmdq.h>
|
|
|
|
#include "mtk_drm_crtc.h"
|
|
#include "mtk_drm_ddp_comp.h"
|
|
#include "mtk_drm_drv.h"
|
|
#include "mtk_log.h"
|
|
#include "mtk_dump.h"
|
|
|
|
#define DISP_DITHER_EN 0x0
|
|
#define DISP_REG_DITHER_CFG 0x20
|
|
#define DISP_REG_DITHER_SIZE 0x30
|
|
#define DISP_DITHER_5 0x0114
|
|
#define DISP_DITHER_7 0x011c
|
|
#define DISP_DITHER_15 0x013c
|
|
#define DISP_DITHER_16 0x0140
|
|
|
|
#define DITHER_REG(idx) (0x100 + (idx)*4)
|
|
|
|
#define DITHER_BYPASS_SHADOW BIT(0)
|
|
#define DITHER_READ_WRK_REG BIT(2)
|
|
|
|
#define DISP_DITHERING BIT(2)
|
|
#define DITHER_LSB_ERR_SHIFT_R(x) (((x)&0x7) << 28)
|
|
#define DITHER_OVFLW_BIT_R(x) (((x)&0x7) << 24)
|
|
#define DITHER_ADD_LSHIFT_R(x) (((x)&0x7) << 20)
|
|
#define DITHER_ADD_RSHIFT_R(x) (((x)&0x7) << 16)
|
|
#define DITHER_NEW_BIT_MODE BIT(0)
|
|
#define DITHER_LSB_ERR_SHIFT_B(x) (((x)&0x7) << 28)
|
|
#define DITHER_OVFLW_BIT_B(x) (((x)&0x7) << 24)
|
|
#define DITHER_ADD_LSHIFT_B(x) (((x)&0x7) << 20)
|
|
#define DITHER_ADD_RSHIFT_B(x) (((x)&0x7) << 16)
|
|
#define DITHER_LSB_ERR_SHIFT_G(x) (((x)&0x7) << 12)
|
|
#define DITHER_OVFLW_BIT_G(x) (((x)&0x7) << 8)
|
|
#define DITHER_ADD_LSHIFT_G(x) (((x)&0x7) << 4)
|
|
#define DITHER_ADD_RSHIFT_G(x) (((x)&0x7) << 0)
|
|
|
|
#define DITHER_TOTAL_MODULE_NUM (2)
|
|
static unsigned int g_dither_relay_value[DITHER_TOTAL_MODULE_NUM];
|
|
#define index_of_dither(module) ((module == DDP_COMPONENT_DITHER0) ? 0 : 1)
|
|
static atomic_t g_dither_is_clock_on = ATOMIC_INIT(0);
|
|
static DEFINE_SPINLOCK(g_dither_clock_lock);
|
|
// It's a work around for no comp assigned in functions.
|
|
static struct mtk_ddp_comp *default_comp;
|
|
|
|
enum COLOR_IOCTL_CMD {
|
|
DITHER_SELECT = 0,
|
|
BYPASS_DITHER
|
|
};
|
|
|
|
struct mtk_disp_dither_data {
|
|
bool support_shadow;
|
|
};
|
|
|
|
struct mtk_disp_dither {
|
|
struct mtk_ddp_comp ddp_comp;
|
|
struct drm_crtc *crtc;
|
|
int pwr_sta;
|
|
unsigned int cfg_reg;
|
|
const struct mtk_disp_dither_data *data;
|
|
};
|
|
|
|
static void mtk_dither_config(struct mtk_ddp_comp *comp,
|
|
struct mtk_ddp_config *cfg,
|
|
struct cmdq_pkt *handle)
|
|
{
|
|
struct mtk_disp_dither *priv = dev_get_drvdata(comp->dev);
|
|
|
|
unsigned int enable = 1;
|
|
unsigned int width;
|
|
|
|
if (comp->mtk_crtc->is_dual_pipe)
|
|
width = cfg->w / 2;
|
|
else
|
|
width = cfg->w;
|
|
|
|
DDPINFO("%s: bbp = %u\n", __func__, cfg->bpc);
|
|
DDPINFO("%s: width = %u height = %u\n", __func__, cfg->w, cfg->h);
|
|
|
|
/* skip redundant config */
|
|
if (priv->pwr_sta != 0)
|
|
return;
|
|
|
|
priv->pwr_sta = 1;
|
|
|
|
if (cfg->bpc == 8) { /* 888 */
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(15),
|
|
0x20200001, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(16),
|
|
0x20202020, ~0);
|
|
} else if (cfg->bpc == 5) { /* 565 */
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(15),
|
|
0x50500001, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(16),
|
|
0x50504040, ~0);
|
|
} else if (cfg->bpc == 6) { /* 666 */
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(15),
|
|
0x40400001, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(16),
|
|
0x40404040, ~0);
|
|
} else if (cfg->bpc > 8) {
|
|
/* High depth LCM, no need dither */
|
|
DDPINFO("%s: High depth LCM (bpp = %u), no dither\n",
|
|
__func__, cfg->bpc);
|
|
} else {
|
|
/* Invalid dither bpp, bypass dither */
|
|
/* FIXME: this case would cause dither hang */
|
|
DDPINFO("%s: Invalid dither bpp = %u\n",
|
|
__func__, cfg->bpc);
|
|
enable = 0;
|
|
}
|
|
|
|
if (enable == 1) {
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(5),
|
|
0x00000000, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(6),
|
|
0x00003002, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(7),
|
|
0x00000000, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(8),
|
|
0x00000000, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(9),
|
|
0x00000000, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(10),
|
|
0x00000000, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(11),
|
|
0x00000000, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(12),
|
|
0x00000011, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(13),
|
|
0x00000000, ~0);
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DITHER_REG(14),
|
|
0x00000000, ~0);
|
|
}
|
|
|
|
priv->cfg_reg = enable << 1 | (priv->cfg_reg & ~(0x1 << 1));
|
|
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DISP_DITHER_EN, enable, ~0);
|
|
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DISP_REG_DITHER_CFG,
|
|
enable << 1 |
|
|
g_dither_relay_value[index_of_dither(comp->id)], 0x3);
|
|
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DISP_REG_DITHER_SIZE,
|
|
width << 16 | cfg->h, ~0);
|
|
|
|
}
|
|
|
|
static void mtk_dither_start(struct mtk_ddp_comp *comp,
|
|
struct cmdq_pkt *handle)
|
|
{
|
|
struct mtk_disp_dither *priv = dev_get_drvdata(comp->dev);
|
|
|
|
DDPINFO("%s\n", __func__);
|
|
|
|
priv->pwr_sta = 1;
|
|
}
|
|
|
|
static void mtk_dither_stop(struct mtk_ddp_comp *comp,
|
|
struct cmdq_pkt *handle)
|
|
{
|
|
struct mtk_disp_dither *priv = dev_get_drvdata(comp->dev);
|
|
|
|
DDPINFO("%s\n", __func__);
|
|
|
|
priv->pwr_sta = 0;
|
|
}
|
|
|
|
static void mtk_dither_bypass(struct mtk_ddp_comp *comp, int bypass,
|
|
struct cmdq_pkt *handle)
|
|
{
|
|
struct mtk_disp_dither *priv = dev_get_drvdata(comp->dev);
|
|
DDPINFO("%s\n", __func__);
|
|
g_dither_relay_value[index_of_dither(comp->id)] = bypass;
|
|
|
|
if (bypass)
|
|
priv->cfg_reg = 0x1 | (priv->cfg_reg & ~0x1);
|
|
else
|
|
priv->cfg_reg = ~0x1 & priv->cfg_reg;
|
|
|
|
cmdq_pkt_write(handle, comp->cmdq_base,
|
|
comp->regs_pa + DISP_REG_DITHER_CFG,
|
|
g_dither_relay_value[index_of_dither(comp->id)], 0x1);
|
|
|
|
}
|
|
|
|
struct dither_backup {
|
|
unsigned int REG_DITHER_CFG;
|
|
};
|
|
static struct dither_backup g_dither_backup;
|
|
|
|
static void ddp_dither_backup(struct mtk_ddp_comp *comp)
|
|
{
|
|
g_dither_backup.REG_DITHER_CFG =
|
|
readl(comp->regs + DISP_REG_DITHER_CFG);
|
|
}
|
|
|
|
static void ddp_dither_restore(struct mtk_ddp_comp *comp)
|
|
{
|
|
writel(g_dither_backup.REG_DITHER_CFG, comp->regs + DISP_REG_DITHER_CFG);
|
|
}
|
|
|
|
static void mtk_dither_prepare(struct mtk_ddp_comp *comp)
|
|
{
|
|
#if defined(CONFIG_DRM_MTK_SHADOW_REGISTER_SUPPORT)
|
|
struct mtk_disp_dither *priv = dev_get_drvdata(comp->dev);
|
|
#endif
|
|
|
|
mtk_ddp_comp_clk_prepare(comp);
|
|
atomic_set(&g_dither_is_clock_on, 1);
|
|
|
|
#if defined(CONFIG_DRM_MTK_SHADOW_REGISTER_SUPPORT)
|
|
if (priv->data->support_shadow) {
|
|
/* Enable shadow register and read shadow register */
|
|
mtk_ddp_write_mask_cpu(comp, 0x0,
|
|
DITHER_REG(0), DITHER_BYPASS_SHADOW);
|
|
} else {
|
|
/* Bypass shadow register and read shadow register */
|
|
mtk_ddp_write_mask_cpu(comp, DITHER_BYPASS_SHADOW,
|
|
DITHER_REG(0), DITHER_BYPASS_SHADOW);
|
|
}
|
|
#else
|
|
#if defined(CONFIG_MACH_MT6873) || defined(CONFIG_MACH_MT6853) \
|
|
|| defined(CONFIG_MACH_MT6833) || defined(CONFIG_MACH_MT6877) \
|
|
|| defined(CONFIG_MACH_MT6781)
|
|
/* Bypass shadow register and read shadow register */
|
|
mtk_ddp_write_mask_cpu(comp, DITHER_BYPASS_SHADOW,
|
|
DITHER_REG(0), DITHER_BYPASS_SHADOW);
|
|
#endif
|
|
#endif
|
|
ddp_dither_restore(comp);
|
|
}
|
|
|
|
static void mtk_dither_unprepare(struct mtk_ddp_comp *comp)
|
|
{
|
|
unsigned long flags;
|
|
|
|
DDPINFO("%s @ %d......... spin_lock_irqsave ++ ",
|
|
__func__, __LINE__);
|
|
spin_lock_irqsave(&g_dither_clock_lock, flags);
|
|
DDPINFO("%s @ %d......... spin_lock_irqsave -- ",
|
|
__func__, __LINE__);
|
|
atomic_set(&g_dither_is_clock_on, 0);
|
|
spin_unlock_irqrestore(&g_dither_clock_lock, flags);
|
|
DDPINFO("%s @ %d......... spin_unlock_irqrestore ",
|
|
__func__, __LINE__);
|
|
ddp_dither_backup(comp);
|
|
mtk_ddp_comp_clk_unprepare(comp);
|
|
}
|
|
|
|
/* TODO */
|
|
/* partial update
|
|
* static int _dither_partial_update(struct mtk_ddp_comp *comp, void *arg,
|
|
* struct cmdq_pkt *handle)
|
|
* {
|
|
* struct disp_rect *roi = (struct disp_rect *) arg;
|
|
* int width = roi->width;
|
|
* int height = roi->height;
|
|
*
|
|
* cmdq_pkt_write(handle, comp->cmdq_base,
|
|
* comp->regs_pa + DISP_REG_DITHER_SIZE, width << 16 | height, ~0);
|
|
* return 0;
|
|
* }
|
|
*
|
|
* static int mtk_dither_io_cmd(struct mtk_ddp_comp *comp,
|
|
* struct cmdq_pkt *handle,
|
|
* enum mtk_ddp_io_cmd io_cmd,
|
|
* void *params)
|
|
* {
|
|
* int ret = -1;
|
|
* if (io_cmd == DDP_PARTIAL_UPDATE) {
|
|
* _dither_partial_update(comp, params, handle);
|
|
* ret = 0;
|
|
* }
|
|
* return ret;
|
|
* }
|
|
*/
|
|
|
|
void mtk_dither_select(struct mtk_ddp_comp *comp,
|
|
struct cmdq_pkt *handle,
|
|
unsigned int bpc)
|
|
{
|
|
unsigned int enable = 0x1;
|
|
|
|
if (bpc == 8) { /* 888 */
|
|
writel(0x20200001, comp->regs + DITHER_REG(15));
|
|
writel(0x20202020, comp->regs + DITHER_REG(16));
|
|
} else if (bpc == 5) { /* 565 */
|
|
writel(0x50500001, comp->regs + DITHER_REG(15));
|
|
writel(0x50504040, comp->regs + DITHER_REG(16));
|
|
} else if (bpc == 6) { /* 666 */
|
|
writel(0x40400001, comp->regs + DITHER_REG(15));
|
|
writel(0x40404040, comp->regs + DITHER_REG(16));
|
|
} else if (bpc > 8) {
|
|
/* High depth LCM, no need dither */
|
|
DDPINFO("%s: High depth LCM (bpp = %u), no dither\n",
|
|
__func__, bpc);
|
|
} else {
|
|
/* Invalid dither bpp, bypass dither */
|
|
/* FIXME: this case would cause dither hang */
|
|
DDPINFO("%s: Invalid dither bpp = %u\n", __func__, bpc);
|
|
enable = 0;
|
|
}
|
|
|
|
if (enable == 1) {
|
|
writel(0x00000000, comp->regs + DITHER_REG(5));
|
|
writel(0x00003002, comp->regs + DITHER_REG(6));
|
|
writel(0x00000000, comp->regs + DITHER_REG(7));
|
|
writel(0x00000000, comp->regs + DITHER_REG(8));
|
|
writel(0x00000000, comp->regs + DITHER_REG(9));
|
|
writel(0x00000000, comp->regs + DITHER_REG(10));
|
|
writel(0x00000000, comp->regs + DITHER_REG(11));
|
|
writel(0x00000011, comp->regs + DITHER_REG(12));
|
|
writel(0x00000000, comp->regs + DITHER_REG(13));
|
|
writel(0x00000000, comp->regs + DITHER_REG(14));
|
|
}
|
|
|
|
writel(enable, comp->regs + DISP_DITHER_EN);
|
|
writel(enable << 1 | (~enable), comp->regs + DISP_REG_DITHER_CFG);
|
|
}
|
|
|
|
static int mtk_dither_user_cmd(struct mtk_ddp_comp *comp,
|
|
struct cmdq_pkt *handle, unsigned int cmd, void *data)
|
|
{
|
|
DDPINFO("%s: cmd: %d\n", __func__, cmd);
|
|
switch (cmd) {
|
|
|
|
case DITHER_SELECT:
|
|
{
|
|
unsigned int bpc = *((unsigned int *)data);
|
|
|
|
mtk_dither_select(comp, NULL, bpc);
|
|
}
|
|
break;
|
|
case BYPASS_DITHER:
|
|
{
|
|
int *value = data;
|
|
|
|
mtk_dither_bypass(comp, *value, handle);
|
|
}
|
|
break;
|
|
default:
|
|
DDPPR_ERR("%s: error cmd: %d\n", __func__, cmd);
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static const struct mtk_ddp_comp_funcs mtk_disp_dither_funcs = {
|
|
.config = mtk_dither_config,
|
|
.start = mtk_dither_start,
|
|
.stop = mtk_dither_stop,
|
|
.bypass = mtk_dither_bypass,
|
|
.user_cmd = mtk_dither_user_cmd,
|
|
.prepare = mtk_dither_prepare,
|
|
.unprepare = mtk_dither_unprepare,
|
|
/* partial update
|
|
* .io_cmd = mtk_dither_io_cmd,
|
|
*/
|
|
};
|
|
|
|
static int mtk_disp_dither_bind(struct device *dev, struct device *master,
|
|
void *data)
|
|
{
|
|
struct mtk_disp_dither *priv = dev_get_drvdata(dev);
|
|
struct drm_device *drm_dev = data;
|
|
int ret;
|
|
|
|
DDPINFO("%s\n", __func__);
|
|
|
|
ret = mtk_ddp_comp_register(drm_dev, &priv->ddp_comp);
|
|
if (ret < 0) {
|
|
dev_err(dev, "Failed to register component %s: %d\n",
|
|
dev->of_node->full_name, ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mtk_disp_dither_unbind(struct device *dev, struct device *master,
|
|
void *data)
|
|
{
|
|
struct mtk_disp_dither *priv = dev_get_drvdata(dev);
|
|
struct drm_device *drm_dev = data;
|
|
|
|
mtk_ddp_comp_unregister(drm_dev, &priv->ddp_comp);
|
|
}
|
|
|
|
static const struct component_ops mtk_disp_dither_component_ops = {
|
|
.bind = mtk_disp_dither_bind,
|
|
.unbind = mtk_disp_dither_unbind,
|
|
};
|
|
|
|
void mtk_dither_dump(struct mtk_ddp_comp *comp)
|
|
{
|
|
void __iomem *baddr = comp->regs;
|
|
|
|
DDPDUMP("== %s REGS ==\n", mtk_dump_comp_str(comp));
|
|
mtk_cust_dump_reg(baddr, 0x0, 0x20, 0x30, -1);
|
|
mtk_cust_dump_reg(baddr, 0x24, 0x28, -1, -1);
|
|
}
|
|
|
|
static int mtk_disp_dither_probe(struct platform_device *pdev)
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
struct mtk_disp_dither *priv;
|
|
enum mtk_ddp_comp_id comp_id;
|
|
int ret;
|
|
|
|
DDPINFO("%s+\n", __func__);
|
|
|
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
|
if (priv == NULL)
|
|
return -ENOMEM;
|
|
|
|
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_DITHER);
|
|
if ((int)comp_id < 0) {
|
|
DDPPR_ERR("Failed to identify by alias: %d\n", comp_id);
|
|
return comp_id;
|
|
}
|
|
|
|
if (!default_comp)
|
|
default_comp = &priv->ddp_comp;
|
|
|
|
ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id,
|
|
&mtk_disp_dither_funcs);
|
|
if (ret != 0) {
|
|
DDPPR_ERR("Failed to initialize component: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
priv->pwr_sta = 0;
|
|
priv->cfg_reg = 0x80000100;
|
|
|
|
platform_set_drvdata(pdev, priv);
|
|
|
|
pm_runtime_enable(dev);
|
|
|
|
ret = component_add(dev, &mtk_disp_dither_component_ops);
|
|
if (ret != 0) {
|
|
dev_err(dev, "Failed to add component: %d\n", ret);
|
|
pm_runtime_disable(dev);
|
|
}
|
|
DDPINFO("%s-\n", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mtk_disp_dither_remove(struct platform_device *pdev)
|
|
{
|
|
component_del(&pdev->dev, &mtk_disp_dither_component_ops);
|
|
|
|
pm_runtime_disable(&pdev->dev);
|
|
return 0;
|
|
}
|
|
|
|
static const struct mtk_disp_dither_data mt6779_dither_driver_data = {
|
|
.support_shadow = false,
|
|
};
|
|
|
|
static const struct mtk_disp_dither_data mt6885_dither_driver_data = {
|
|
.support_shadow = false,
|
|
};
|
|
|
|
static const struct mtk_disp_dither_data mt6873_dither_driver_data = {
|
|
.support_shadow = false,
|
|
};
|
|
|
|
static const struct mtk_disp_dither_data mt6853_dither_driver_data = {
|
|
.support_shadow = false,
|
|
};
|
|
|
|
static const struct mtk_disp_dither_data mt6877_dither_driver_data = {
|
|
.support_shadow = false,
|
|
};
|
|
|
|
static const struct mtk_disp_dither_data mt6833_dither_driver_data = {
|
|
.support_shadow = false,
|
|
};
|
|
|
|
static const struct mtk_disp_dither_data mt6781_dither_driver_data = {
|
|
.support_shadow = false,
|
|
};
|
|
|
|
static const struct of_device_id mtk_disp_dither_driver_dt_match[] = {
|
|
{ .compatible = "mediatek,mt6779-disp-dither",
|
|
.data = &mt6779_dither_driver_data},
|
|
{ .compatible = "mediatek,mt6885-disp-dither",
|
|
.data = &mt6885_dither_driver_data},
|
|
{ .compatible = "mediatek,mt6873-disp-dither",
|
|
.data = &mt6873_dither_driver_data},
|
|
{ .compatible = "mediatek,mt6853-disp-dither",
|
|
.data = &mt6853_dither_driver_data},
|
|
{ .compatible = "mediatek,mt6877-disp-dither",
|
|
.data = &mt6877_dither_driver_data},
|
|
{ .compatible = "mediatek,mt6833-disp-dither",
|
|
.data = &mt6833_dither_driver_data},
|
|
{ .compatible = "mediatek,mt6781-disp-dither",
|
|
.data = &mt6781_dither_driver_data},
|
|
{},
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(of, mtk_disp_dither_driver_dt_match);
|
|
|
|
struct platform_driver mtk_disp_dither_driver = {
|
|
.probe = mtk_disp_dither_probe,
|
|
.remove = mtk_disp_dither_remove,
|
|
.driver = {
|
|
|
|
.name = "mediatek-disp-dither",
|
|
.owner = THIS_MODULE,
|
|
.of_match_table = mtk_disp_dither_driver_dt_match,
|
|
},
|
|
};
|
|
|
|
|
|
void dither_test(const char *cmd, char *debug_output, struct mtk_ddp_comp *comp)
|
|
{
|
|
unsigned int bpc;
|
|
|
|
debug_output[0] = '\0';
|
|
DDPINFO("%s: %s\n", __func__, cmd);
|
|
|
|
if (strncmp(cmd, "sel:", 4) == 0) {
|
|
if (cmd[4] == '0') {
|
|
bpc = 0;
|
|
mtk_dither_user_cmd(comp, NULL, DITHER_SELECT, &bpc);
|
|
DDPINFO("bpc = 0\n");
|
|
} else if (cmd[4] == '1') {
|
|
bpc = 5;
|
|
mtk_dither_user_cmd(comp, NULL, DITHER_SELECT, &bpc);
|
|
DDPINFO("bpc = 5\n");
|
|
} else if (cmd[4] == '2') {
|
|
bpc = 6;
|
|
mtk_dither_user_cmd(comp, NULL, DITHER_SELECT, &bpc);
|
|
DDPINFO("bpc = 6\n");
|
|
} else if (cmd[4] == '3') {
|
|
bpc = 7;
|
|
mtk_dither_user_cmd(comp, NULL, DITHER_SELECT, &bpc);
|
|
DDPINFO("bpc = 7\n");
|
|
} else {
|
|
DDPINFO("unknown bpc\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void disp_dither_set_bypass(struct drm_crtc *crtc, int bypass)
|
|
{
|
|
int ret;
|
|
|
|
ret = mtk_crtc_user_cmd(crtc, default_comp, BYPASS_DITHER, &bypass);
|
|
DDPFUNC("ret = %d", ret);
|
|
}
|