1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2021 MediaTek Inc. 4 */ 5 6 #include <drm/drm_fourcc.h> 7 #include <linux/clk.h> 8 #include <linux/component.h> 9 #include <linux/of_address.h> 10 #include <linux/of_device.h> 11 #include <linux/platform_device.h> 12 #include <linux/pm_runtime.h> 13 #include <linux/soc/mediatek/mtk-cmdq.h> 14 15 #include "mtk_disp_drv.h" 16 #include "mtk_drm_drv.h" 17 #include "mtk_mdp_rdma.h" 18 19 #define MDP_RDMA_EN 0x000 20 #define FLD_ROT_ENABLE BIT(0) 21 #define MDP_RDMA_RESET 0x008 22 #define MDP_RDMA_CON 0x020 23 #define FLD_OUTPUT_10B BIT(5) 24 #define FLD_SIMPLE_MODE BIT(4) 25 #define MDP_RDMA_GMCIF_CON 0x028 26 #define FLD_COMMAND_DIV BIT(0) 27 #define FLD_EXT_PREULTRA_EN BIT(3) 28 #define FLD_RD_REQ_TYPE GENMASK(7, 4) 29 #define VAL_RD_REQ_TYPE_BURST_8_ACCESS 7 30 #define FLD_ULTRA_EN GENMASK(13, 12) 31 #define VAL_ULTRA_EN_ENABLE 1 32 #define FLD_PRE_ULTRA_EN GENMASK(17, 16) 33 #define VAL_PRE_ULTRA_EN_ENABLE 1 34 #define FLD_EXT_ULTRA_EN BIT(18) 35 #define MDP_RDMA_SRC_CON 0x030 36 #define FLD_OUTPUT_ARGB BIT(25) 37 #define FLD_BIT_NUMBER GENMASK(19, 18) 38 #define FLD_SWAP BIT(14) 39 #define FLD_UNIFORM_CONFIG BIT(17) 40 #define RDMA_INPUT_10BIT BIT(18) 41 #define FLD_SRC_FORMAT GENMASK(3, 0) 42 #define MDP_RDMA_COMP_CON 0x038 43 #define FLD_AFBC_EN BIT(22) 44 #define FLD_AFBC_YUV_TRANSFORM BIT(21) 45 #define FLD_UFBDC_EN BIT(12) 46 #define MDP_RDMA_MF_BKGD_SIZE_IN_BYTE 0x060 47 #define FLD_MF_BKGD_WB GENMASK(22, 0) 48 #define MDP_RDMA_MF_SRC_SIZE 0x070 49 #define FLD_MF_SRC_H GENMASK(30, 16) 50 #define FLD_MF_SRC_W GENMASK(14, 0) 51 #define MDP_RDMA_MF_CLIP_SIZE 0x078 52 #define FLD_MF_CLIP_H GENMASK(30, 16) 53 #define FLD_MF_CLIP_W GENMASK(14, 0) 54 #define MDP_RDMA_SRC_OFFSET_0 0x118 55 #define FLD_SRC_OFFSET_0 GENMASK(31, 0) 56 #define MDP_RDMA_TRANSFORM_0 0x200 57 #define FLD_INT_MATRIX_SEL GENMASK(27, 23) 58 #define FLD_TRANS_EN BIT(16) 59 #define MDP_RDMA_SRC_BASE_0 0xf00 60 #define FLD_SRC_BASE_0 GENMASK(31, 0) 61 62 #define RDMA_CSC_FULL709_TO_RGB 5 63 #define RDMA_CSC_BT601_TO_RGB 6 64 65 enum rdma_format { 66 RDMA_INPUT_FORMAT_RGB565 = 0, 67 RDMA_INPUT_FORMAT_RGB888 = 1, 68 RDMA_INPUT_FORMAT_RGBA8888 = 2, 69 RDMA_INPUT_FORMAT_ARGB8888 = 3, 70 RDMA_INPUT_FORMAT_UYVY = 4, 71 RDMA_INPUT_FORMAT_YUY2 = 5, 72 RDMA_INPUT_FORMAT_Y8 = 7, 73 RDMA_INPUT_FORMAT_YV12 = 8, 74 RDMA_INPUT_FORMAT_UYVY_3PL = 9, 75 RDMA_INPUT_FORMAT_NV12 = 12, 76 RDMA_INPUT_FORMAT_UYVY_2PL = 13, 77 RDMA_INPUT_FORMAT_Y410 = 14 78 }; 79 80 struct mtk_mdp_rdma { 81 void __iomem *regs; 82 struct clk *clk; 83 struct cmdq_client_reg cmdq_reg; 84 }; 85 86 static unsigned int rdma_fmt_convert(unsigned int fmt) 87 { 88 switch (fmt) { 89 default: 90 case DRM_FORMAT_RGB565: 91 return RDMA_INPUT_FORMAT_RGB565; 92 case DRM_FORMAT_BGR565: 93 return RDMA_INPUT_FORMAT_RGB565 | FLD_SWAP; 94 case DRM_FORMAT_RGB888: 95 return RDMA_INPUT_FORMAT_RGB888; 96 case DRM_FORMAT_BGR888: 97 return RDMA_INPUT_FORMAT_RGB888 | FLD_SWAP; 98 case DRM_FORMAT_RGBX8888: 99 case DRM_FORMAT_RGBA8888: 100 return RDMA_INPUT_FORMAT_ARGB8888; 101 case DRM_FORMAT_BGRX8888: 102 case DRM_FORMAT_BGRA8888: 103 return RDMA_INPUT_FORMAT_ARGB8888 | FLD_SWAP; 104 case DRM_FORMAT_XRGB8888: 105 case DRM_FORMAT_ARGB8888: 106 return RDMA_INPUT_FORMAT_RGBA8888; 107 case DRM_FORMAT_XBGR8888: 108 case DRM_FORMAT_ABGR8888: 109 return RDMA_INPUT_FORMAT_RGBA8888 | FLD_SWAP; 110 case DRM_FORMAT_ABGR2101010: 111 return RDMA_INPUT_FORMAT_RGBA8888 | FLD_SWAP | RDMA_INPUT_10BIT; 112 case DRM_FORMAT_ARGB2101010: 113 return RDMA_INPUT_FORMAT_RGBA8888 | RDMA_INPUT_10BIT; 114 case DRM_FORMAT_RGBA1010102: 115 return RDMA_INPUT_FORMAT_ARGB8888 | FLD_SWAP | RDMA_INPUT_10BIT; 116 case DRM_FORMAT_BGRA1010102: 117 return RDMA_INPUT_FORMAT_ARGB8888 | RDMA_INPUT_10BIT; 118 case DRM_FORMAT_UYVY: 119 return RDMA_INPUT_FORMAT_UYVY; 120 case DRM_FORMAT_YUYV: 121 return RDMA_INPUT_FORMAT_YUY2; 122 } 123 } 124 125 static unsigned int rdma_color_convert(unsigned int color_encoding) 126 { 127 switch (color_encoding) { 128 default: 129 case DRM_COLOR_YCBCR_BT709: 130 return RDMA_CSC_FULL709_TO_RGB; 131 case DRM_COLOR_YCBCR_BT601: 132 return RDMA_CSC_BT601_TO_RGB; 133 } 134 } 135 136 static void mtk_mdp_rdma_fifo_config(struct device *dev, struct cmdq_pkt *cmdq_pkt) 137 { 138 struct mtk_mdp_rdma *priv = dev_get_drvdata(dev); 139 140 mtk_ddp_write_mask(cmdq_pkt, FLD_EXT_ULTRA_EN | VAL_PRE_ULTRA_EN_ENABLE << 16 | 141 VAL_ULTRA_EN_ENABLE << 12 | VAL_RD_REQ_TYPE_BURST_8_ACCESS << 4 | 142 FLD_EXT_PREULTRA_EN | FLD_COMMAND_DIV, &priv->cmdq_reg, 143 priv->regs, MDP_RDMA_GMCIF_CON, FLD_EXT_ULTRA_EN | 144 FLD_PRE_ULTRA_EN | FLD_ULTRA_EN | FLD_RD_REQ_TYPE | 145 FLD_EXT_PREULTRA_EN | FLD_COMMAND_DIV); 146 } 147 148 void mtk_mdp_rdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt) 149 { 150 struct mtk_mdp_rdma *priv = dev_get_drvdata(dev); 151 152 mtk_ddp_write_mask(cmdq_pkt, FLD_ROT_ENABLE, &priv->cmdq_reg, 153 priv->regs, MDP_RDMA_EN, FLD_ROT_ENABLE); 154 } 155 156 void mtk_mdp_rdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt) 157 { 158 struct mtk_mdp_rdma *priv = dev_get_drvdata(dev); 159 160 mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, 161 priv->regs, MDP_RDMA_EN, FLD_ROT_ENABLE); 162 mtk_ddp_write(cmdq_pkt, 1, &priv->cmdq_reg, priv->regs, MDP_RDMA_RESET); 163 mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, MDP_RDMA_RESET); 164 } 165 166 void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg, 167 struct cmdq_pkt *cmdq_pkt) 168 { 169 struct mtk_mdp_rdma *priv = dev_get_drvdata(dev); 170 const struct drm_format_info *fmt_info = drm_format_info(cfg->fmt); 171 bool csc_enable = fmt_info->is_yuv ? true : false; 172 unsigned int src_pitch_y = cfg->pitch; 173 unsigned int offset_y = 0; 174 175 mtk_mdp_rdma_fifo_config(dev, cmdq_pkt); 176 177 mtk_ddp_write_mask(cmdq_pkt, FLD_UNIFORM_CONFIG, &priv->cmdq_reg, priv->regs, 178 MDP_RDMA_SRC_CON, FLD_UNIFORM_CONFIG); 179 mtk_ddp_write_mask(cmdq_pkt, rdma_fmt_convert(cfg->fmt), &priv->cmdq_reg, priv->regs, 180 MDP_RDMA_SRC_CON, FLD_SWAP | FLD_SRC_FORMAT | FLD_BIT_NUMBER); 181 182 if (!csc_enable && fmt_info->has_alpha) 183 mtk_ddp_write_mask(cmdq_pkt, FLD_OUTPUT_ARGB, &priv->cmdq_reg, 184 priv->regs, MDP_RDMA_SRC_CON, FLD_OUTPUT_ARGB); 185 else 186 mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, 187 MDP_RDMA_SRC_CON, FLD_OUTPUT_ARGB); 188 189 mtk_ddp_write_mask(cmdq_pkt, cfg->addr0, &priv->cmdq_reg, priv->regs, 190 MDP_RDMA_SRC_BASE_0, FLD_SRC_BASE_0); 191 192 mtk_ddp_write_mask(cmdq_pkt, src_pitch_y, &priv->cmdq_reg, priv->regs, 193 MDP_RDMA_MF_BKGD_SIZE_IN_BYTE, FLD_MF_BKGD_WB); 194 195 mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, MDP_RDMA_COMP_CON, 196 FLD_AFBC_YUV_TRANSFORM | FLD_UFBDC_EN | FLD_AFBC_EN); 197 mtk_ddp_write_mask(cmdq_pkt, FLD_OUTPUT_10B, &priv->cmdq_reg, priv->regs, 198 MDP_RDMA_CON, FLD_OUTPUT_10B); 199 mtk_ddp_write_mask(cmdq_pkt, FLD_SIMPLE_MODE, &priv->cmdq_reg, priv->regs, 200 MDP_RDMA_CON, FLD_SIMPLE_MODE); 201 if (csc_enable) 202 mtk_ddp_write_mask(cmdq_pkt, rdma_color_convert(cfg->color_encoding) << 23, 203 &priv->cmdq_reg, priv->regs, MDP_RDMA_TRANSFORM_0, 204 FLD_INT_MATRIX_SEL); 205 mtk_ddp_write_mask(cmdq_pkt, csc_enable << 16, &priv->cmdq_reg, priv->regs, 206 MDP_RDMA_TRANSFORM_0, FLD_TRANS_EN); 207 208 offset_y = cfg->x_left * fmt_info->cpp[0] + cfg->y_top * src_pitch_y; 209 210 mtk_ddp_write_mask(cmdq_pkt, offset_y, &priv->cmdq_reg, priv->regs, 211 MDP_RDMA_SRC_OFFSET_0, FLD_SRC_OFFSET_0); 212 mtk_ddp_write_mask(cmdq_pkt, cfg->width, &priv->cmdq_reg, priv->regs, 213 MDP_RDMA_MF_SRC_SIZE, FLD_MF_SRC_W); 214 mtk_ddp_write_mask(cmdq_pkt, cfg->height << 16, &priv->cmdq_reg, priv->regs, 215 MDP_RDMA_MF_SRC_SIZE, FLD_MF_SRC_H); 216 mtk_ddp_write_mask(cmdq_pkt, cfg->width, &priv->cmdq_reg, priv->regs, 217 MDP_RDMA_MF_CLIP_SIZE, FLD_MF_CLIP_W); 218 mtk_ddp_write_mask(cmdq_pkt, cfg->height << 16, &priv->cmdq_reg, priv->regs, 219 MDP_RDMA_MF_CLIP_SIZE, FLD_MF_CLIP_H); 220 } 221 222 int mtk_mdp_rdma_clk_enable(struct device *dev) 223 { 224 struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev); 225 226 clk_prepare_enable(rdma->clk); 227 return 0; 228 } 229 230 void mtk_mdp_rdma_clk_disable(struct device *dev) 231 { 232 struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev); 233 234 clk_disable_unprepare(rdma->clk); 235 } 236 237 static int mtk_mdp_rdma_bind(struct device *dev, struct device *master, 238 void *data) 239 { 240 return 0; 241 } 242 243 static void mtk_mdp_rdma_unbind(struct device *dev, struct device *master, 244 void *data) 245 { 246 } 247 248 static const struct component_ops mtk_mdp_rdma_component_ops = { 249 .bind = mtk_mdp_rdma_bind, 250 .unbind = mtk_mdp_rdma_unbind, 251 }; 252 253 static int mtk_mdp_rdma_probe(struct platform_device *pdev) 254 { 255 struct device *dev = &pdev->dev; 256 struct resource *res; 257 struct mtk_mdp_rdma *priv; 258 int ret = 0; 259 260 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 261 if (!priv) 262 return -ENOMEM; 263 264 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 265 priv->regs = devm_ioremap_resource(dev, res); 266 if (IS_ERR(priv->regs)) { 267 dev_err(dev, "failed to ioremap rdma\n"); 268 return PTR_ERR(priv->regs); 269 } 270 271 priv->clk = devm_clk_get(dev, NULL); 272 if (IS_ERR(priv->clk)) { 273 dev_err(dev, "failed to get rdma clk\n"); 274 return PTR_ERR(priv->clk); 275 } 276 277 #if IS_REACHABLE(CONFIG_MTK_CMDQ) 278 ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0); 279 if (ret) 280 dev_dbg(dev, "get mediatek,gce-client-reg fail!\n"); 281 #endif 282 platform_set_drvdata(pdev, priv); 283 284 pm_runtime_enable(dev); 285 286 ret = component_add(dev, &mtk_mdp_rdma_component_ops); 287 if (ret != 0) { 288 pm_runtime_disable(dev); 289 dev_err(dev, "Failed to add component: %d\n", ret); 290 } 291 return ret; 292 } 293 294 static int mtk_mdp_rdma_remove(struct platform_device *pdev) 295 { 296 component_del(&pdev->dev, &mtk_mdp_rdma_component_ops); 297 pm_runtime_disable(&pdev->dev); 298 return 0; 299 } 300 301 static const struct of_device_id mtk_mdp_rdma_driver_dt_match[] = { 302 { .compatible = "mediatek,mt8195-vdo1-rdma", }, 303 {}, 304 }; 305 MODULE_DEVICE_TABLE(of, mtk_mdp_rdma_driver_dt_match); 306 307 struct platform_driver mtk_mdp_rdma_driver = { 308 .probe = mtk_mdp_rdma_probe, 309 .remove = mtk_mdp_rdma_remove, 310 .driver = { 311 .name = "mediatek-mdp-rdma", 312 .owner = THIS_MODULE, 313 .of_match_table = mtk_mdp_rdma_driver_dt_match, 314 }, 315 }; 316