0001
0002
0003
0004
0005
0006 #include <drm/drm_fourcc.h>
0007 #include <linux/clk.h>
0008 #include <linux/component.h>
0009 #include <linux/of_address.h>
0010 #include <linux/of_device.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/pm_runtime.h>
0013 #include <linux/soc/mediatek/mtk-cmdq.h>
0014
0015 #include "mtk_disp_drv.h"
0016 #include "mtk_drm_drv.h"
0017 #include "mtk_mdp_rdma.h"
0018
0019 #define MDP_RDMA_EN 0x000
0020 #define FLD_ROT_ENABLE BIT(0)
0021 #define MDP_RDMA_RESET 0x008
0022 #define MDP_RDMA_CON 0x020
0023 #define FLD_OUTPUT_10B BIT(5)
0024 #define FLD_SIMPLE_MODE BIT(4)
0025 #define MDP_RDMA_GMCIF_CON 0x028
0026 #define FLD_COMMAND_DIV BIT(0)
0027 #define FLD_EXT_PREULTRA_EN BIT(3)
0028 #define FLD_RD_REQ_TYPE GENMASK(7, 4)
0029 #define VAL_RD_REQ_TYPE_BURST_8_ACCESS 7
0030 #define FLD_ULTRA_EN GENMASK(13, 12)
0031 #define VAL_ULTRA_EN_ENABLE 1
0032 #define FLD_PRE_ULTRA_EN GENMASK(17, 16)
0033 #define VAL_PRE_ULTRA_EN_ENABLE 1
0034 #define FLD_EXT_ULTRA_EN BIT(18)
0035 #define MDP_RDMA_SRC_CON 0x030
0036 #define FLD_OUTPUT_ARGB BIT(25)
0037 #define FLD_BIT_NUMBER GENMASK(19, 18)
0038 #define FLD_SWAP BIT(14)
0039 #define FLD_UNIFORM_CONFIG BIT(17)
0040 #define RDMA_INPUT_10BIT BIT(18)
0041 #define FLD_SRC_FORMAT GENMASK(3, 0)
0042 #define MDP_RDMA_COMP_CON 0x038
0043 #define FLD_AFBC_EN BIT(22)
0044 #define FLD_AFBC_YUV_TRANSFORM BIT(21)
0045 #define FLD_UFBDC_EN BIT(12)
0046 #define MDP_RDMA_MF_BKGD_SIZE_IN_BYTE 0x060
0047 #define FLD_MF_BKGD_WB GENMASK(22, 0)
0048 #define MDP_RDMA_MF_SRC_SIZE 0x070
0049 #define FLD_MF_SRC_H GENMASK(30, 16)
0050 #define FLD_MF_SRC_W GENMASK(14, 0)
0051 #define MDP_RDMA_MF_CLIP_SIZE 0x078
0052 #define FLD_MF_CLIP_H GENMASK(30, 16)
0053 #define FLD_MF_CLIP_W GENMASK(14, 0)
0054 #define MDP_RDMA_SRC_OFFSET_0 0x118
0055 #define FLD_SRC_OFFSET_0 GENMASK(31, 0)
0056 #define MDP_RDMA_TRANSFORM_0 0x200
0057 #define FLD_INT_MATRIX_SEL GENMASK(27, 23)
0058 #define FLD_TRANS_EN BIT(16)
0059 #define MDP_RDMA_SRC_BASE_0 0xf00
0060 #define FLD_SRC_BASE_0 GENMASK(31, 0)
0061
0062 #define RDMA_CSC_FULL709_TO_RGB 5
0063 #define RDMA_CSC_BT601_TO_RGB 6
0064
0065 enum rdma_format {
0066 RDMA_INPUT_FORMAT_RGB565 = 0,
0067 RDMA_INPUT_FORMAT_RGB888 = 1,
0068 RDMA_INPUT_FORMAT_RGBA8888 = 2,
0069 RDMA_INPUT_FORMAT_ARGB8888 = 3,
0070 RDMA_INPUT_FORMAT_UYVY = 4,
0071 RDMA_INPUT_FORMAT_YUY2 = 5,
0072 RDMA_INPUT_FORMAT_Y8 = 7,
0073 RDMA_INPUT_FORMAT_YV12 = 8,
0074 RDMA_INPUT_FORMAT_UYVY_3PL = 9,
0075 RDMA_INPUT_FORMAT_NV12 = 12,
0076 RDMA_INPUT_FORMAT_UYVY_2PL = 13,
0077 RDMA_INPUT_FORMAT_Y410 = 14
0078 };
0079
0080 struct mtk_mdp_rdma {
0081 void __iomem *regs;
0082 struct clk *clk;
0083 struct cmdq_client_reg cmdq_reg;
0084 };
0085
0086 static unsigned int rdma_fmt_convert(unsigned int fmt)
0087 {
0088 switch (fmt) {
0089 default:
0090 case DRM_FORMAT_RGB565:
0091 return RDMA_INPUT_FORMAT_RGB565;
0092 case DRM_FORMAT_BGR565:
0093 return RDMA_INPUT_FORMAT_RGB565 | FLD_SWAP;
0094 case DRM_FORMAT_RGB888:
0095 return RDMA_INPUT_FORMAT_RGB888;
0096 case DRM_FORMAT_BGR888:
0097 return RDMA_INPUT_FORMAT_RGB888 | FLD_SWAP;
0098 case DRM_FORMAT_RGBX8888:
0099 case DRM_FORMAT_RGBA8888:
0100 return RDMA_INPUT_FORMAT_ARGB8888;
0101 case DRM_FORMAT_BGRX8888:
0102 case DRM_FORMAT_BGRA8888:
0103 return RDMA_INPUT_FORMAT_ARGB8888 | FLD_SWAP;
0104 case DRM_FORMAT_XRGB8888:
0105 case DRM_FORMAT_ARGB8888:
0106 return RDMA_INPUT_FORMAT_RGBA8888;
0107 case DRM_FORMAT_XBGR8888:
0108 case DRM_FORMAT_ABGR8888:
0109 return RDMA_INPUT_FORMAT_RGBA8888 | FLD_SWAP;
0110 case DRM_FORMAT_ABGR2101010:
0111 return RDMA_INPUT_FORMAT_RGBA8888 | FLD_SWAP | RDMA_INPUT_10BIT;
0112 case DRM_FORMAT_ARGB2101010:
0113 return RDMA_INPUT_FORMAT_RGBA8888 | RDMA_INPUT_10BIT;
0114 case DRM_FORMAT_RGBA1010102:
0115 return RDMA_INPUT_FORMAT_ARGB8888 | FLD_SWAP | RDMA_INPUT_10BIT;
0116 case DRM_FORMAT_BGRA1010102:
0117 return RDMA_INPUT_FORMAT_ARGB8888 | RDMA_INPUT_10BIT;
0118 case DRM_FORMAT_UYVY:
0119 return RDMA_INPUT_FORMAT_UYVY;
0120 case DRM_FORMAT_YUYV:
0121 return RDMA_INPUT_FORMAT_YUY2;
0122 }
0123 }
0124
0125 static unsigned int rdma_color_convert(unsigned int color_encoding)
0126 {
0127 switch (color_encoding) {
0128 default:
0129 case DRM_COLOR_YCBCR_BT709:
0130 return RDMA_CSC_FULL709_TO_RGB;
0131 case DRM_COLOR_YCBCR_BT601:
0132 return RDMA_CSC_BT601_TO_RGB;
0133 }
0134 }
0135
0136 static void mtk_mdp_rdma_fifo_config(struct device *dev, struct cmdq_pkt *cmdq_pkt)
0137 {
0138 struct mtk_mdp_rdma *priv = dev_get_drvdata(dev);
0139
0140 mtk_ddp_write_mask(cmdq_pkt, FLD_EXT_ULTRA_EN | VAL_PRE_ULTRA_EN_ENABLE << 16 |
0141 VAL_ULTRA_EN_ENABLE << 12 | VAL_RD_REQ_TYPE_BURST_8_ACCESS << 4 |
0142 FLD_EXT_PREULTRA_EN | FLD_COMMAND_DIV, &priv->cmdq_reg,
0143 priv->regs, MDP_RDMA_GMCIF_CON, FLD_EXT_ULTRA_EN |
0144 FLD_PRE_ULTRA_EN | FLD_ULTRA_EN | FLD_RD_REQ_TYPE |
0145 FLD_EXT_PREULTRA_EN | FLD_COMMAND_DIV);
0146 }
0147
0148 void mtk_mdp_rdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
0149 {
0150 struct mtk_mdp_rdma *priv = dev_get_drvdata(dev);
0151
0152 mtk_ddp_write_mask(cmdq_pkt, FLD_ROT_ENABLE, &priv->cmdq_reg,
0153 priv->regs, MDP_RDMA_EN, FLD_ROT_ENABLE);
0154 }
0155
0156 void mtk_mdp_rdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
0157 {
0158 struct mtk_mdp_rdma *priv = dev_get_drvdata(dev);
0159
0160 mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg,
0161 priv->regs, MDP_RDMA_EN, FLD_ROT_ENABLE);
0162 mtk_ddp_write(cmdq_pkt, 1, &priv->cmdq_reg, priv->regs, MDP_RDMA_RESET);
0163 mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, MDP_RDMA_RESET);
0164 }
0165
0166 void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg,
0167 struct cmdq_pkt *cmdq_pkt)
0168 {
0169 struct mtk_mdp_rdma *priv = dev_get_drvdata(dev);
0170 const struct drm_format_info *fmt_info = drm_format_info(cfg->fmt);
0171 bool csc_enable = fmt_info->is_yuv ? true : false;
0172 unsigned int src_pitch_y = cfg->pitch;
0173 unsigned int offset_y = 0;
0174
0175 mtk_mdp_rdma_fifo_config(dev, cmdq_pkt);
0176
0177 mtk_ddp_write_mask(cmdq_pkt, FLD_UNIFORM_CONFIG, &priv->cmdq_reg, priv->regs,
0178 MDP_RDMA_SRC_CON, FLD_UNIFORM_CONFIG);
0179 mtk_ddp_write_mask(cmdq_pkt, rdma_fmt_convert(cfg->fmt), &priv->cmdq_reg, priv->regs,
0180 MDP_RDMA_SRC_CON, FLD_SWAP | FLD_SRC_FORMAT | FLD_BIT_NUMBER);
0181
0182 if (!csc_enable && fmt_info->has_alpha)
0183 mtk_ddp_write_mask(cmdq_pkt, FLD_OUTPUT_ARGB, &priv->cmdq_reg,
0184 priv->regs, MDP_RDMA_SRC_CON, FLD_OUTPUT_ARGB);
0185 else
0186 mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
0187 MDP_RDMA_SRC_CON, FLD_OUTPUT_ARGB);
0188
0189 mtk_ddp_write_mask(cmdq_pkt, cfg->addr0, &priv->cmdq_reg, priv->regs,
0190 MDP_RDMA_SRC_BASE_0, FLD_SRC_BASE_0);
0191
0192 mtk_ddp_write_mask(cmdq_pkt, src_pitch_y, &priv->cmdq_reg, priv->regs,
0193 MDP_RDMA_MF_BKGD_SIZE_IN_BYTE, FLD_MF_BKGD_WB);
0194
0195 mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, MDP_RDMA_COMP_CON,
0196 FLD_AFBC_YUV_TRANSFORM | FLD_UFBDC_EN | FLD_AFBC_EN);
0197 mtk_ddp_write_mask(cmdq_pkt, FLD_OUTPUT_10B, &priv->cmdq_reg, priv->regs,
0198 MDP_RDMA_CON, FLD_OUTPUT_10B);
0199 mtk_ddp_write_mask(cmdq_pkt, FLD_SIMPLE_MODE, &priv->cmdq_reg, priv->regs,
0200 MDP_RDMA_CON, FLD_SIMPLE_MODE);
0201 if (csc_enable)
0202 mtk_ddp_write_mask(cmdq_pkt, rdma_color_convert(cfg->color_encoding) << 23,
0203 &priv->cmdq_reg, priv->regs, MDP_RDMA_TRANSFORM_0,
0204 FLD_INT_MATRIX_SEL);
0205 mtk_ddp_write_mask(cmdq_pkt, csc_enable << 16, &priv->cmdq_reg, priv->regs,
0206 MDP_RDMA_TRANSFORM_0, FLD_TRANS_EN);
0207
0208 offset_y = cfg->x_left * fmt_info->cpp[0] + cfg->y_top * src_pitch_y;
0209
0210 mtk_ddp_write_mask(cmdq_pkt, offset_y, &priv->cmdq_reg, priv->regs,
0211 MDP_RDMA_SRC_OFFSET_0, FLD_SRC_OFFSET_0);
0212 mtk_ddp_write_mask(cmdq_pkt, cfg->width, &priv->cmdq_reg, priv->regs,
0213 MDP_RDMA_MF_SRC_SIZE, FLD_MF_SRC_W);
0214 mtk_ddp_write_mask(cmdq_pkt, cfg->height << 16, &priv->cmdq_reg, priv->regs,
0215 MDP_RDMA_MF_SRC_SIZE, FLD_MF_SRC_H);
0216 mtk_ddp_write_mask(cmdq_pkt, cfg->width, &priv->cmdq_reg, priv->regs,
0217 MDP_RDMA_MF_CLIP_SIZE, FLD_MF_CLIP_W);
0218 mtk_ddp_write_mask(cmdq_pkt, cfg->height << 16, &priv->cmdq_reg, priv->regs,
0219 MDP_RDMA_MF_CLIP_SIZE, FLD_MF_CLIP_H);
0220 }
0221
0222 int mtk_mdp_rdma_clk_enable(struct device *dev)
0223 {
0224 struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev);
0225
0226 clk_prepare_enable(rdma->clk);
0227 return 0;
0228 }
0229
0230 void mtk_mdp_rdma_clk_disable(struct device *dev)
0231 {
0232 struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev);
0233
0234 clk_disable_unprepare(rdma->clk);
0235 }
0236
0237 static int mtk_mdp_rdma_bind(struct device *dev, struct device *master,
0238 void *data)
0239 {
0240 return 0;
0241 }
0242
0243 static void mtk_mdp_rdma_unbind(struct device *dev, struct device *master,
0244 void *data)
0245 {
0246 }
0247
0248 static const struct component_ops mtk_mdp_rdma_component_ops = {
0249 .bind = mtk_mdp_rdma_bind,
0250 .unbind = mtk_mdp_rdma_unbind,
0251 };
0252
0253 static int mtk_mdp_rdma_probe(struct platform_device *pdev)
0254 {
0255 struct device *dev = &pdev->dev;
0256 struct resource *res;
0257 struct mtk_mdp_rdma *priv;
0258 int ret = 0;
0259
0260 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0261 if (!priv)
0262 return -ENOMEM;
0263
0264 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0265 priv->regs = devm_ioremap_resource(dev, res);
0266 if (IS_ERR(priv->regs)) {
0267 dev_err(dev, "failed to ioremap rdma\n");
0268 return PTR_ERR(priv->regs);
0269 }
0270
0271 priv->clk = devm_clk_get(dev, NULL);
0272 if (IS_ERR(priv->clk)) {
0273 dev_err(dev, "failed to get rdma clk\n");
0274 return PTR_ERR(priv->clk);
0275 }
0276
0277 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
0278 ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
0279 if (ret)
0280 dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
0281 #endif
0282 platform_set_drvdata(pdev, priv);
0283
0284 pm_runtime_enable(dev);
0285
0286 ret = component_add(dev, &mtk_mdp_rdma_component_ops);
0287 if (ret != 0) {
0288 pm_runtime_disable(dev);
0289 dev_err(dev, "Failed to add component: %d\n", ret);
0290 }
0291 return ret;
0292 }
0293
0294 static int mtk_mdp_rdma_remove(struct platform_device *pdev)
0295 {
0296 component_del(&pdev->dev, &mtk_mdp_rdma_component_ops);
0297 pm_runtime_disable(&pdev->dev);
0298 return 0;
0299 }
0300
0301 static const struct of_device_id mtk_mdp_rdma_driver_dt_match[] = {
0302 { .compatible = "mediatek,mt8195-vdo1-rdma", },
0303 {},
0304 };
0305 MODULE_DEVICE_TABLE(of, mtk_mdp_rdma_driver_dt_match);
0306
0307 struct platform_driver mtk_mdp_rdma_driver = {
0308 .probe = mtk_mdp_rdma_probe,
0309 .remove = mtk_mdp_rdma_remove,
0310 .driver = {
0311 .name = "mediatek-mdp-rdma",
0312 .owner = THIS_MODULE,
0313 .of_match_table = mtk_mdp_rdma_driver_dt_match,
0314 },
0315 };