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