1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015 MediaTek Inc. 4 */ 5 6 #include <drm/drm_fourcc.h> 7 8 #include <linux/clk.h> 9 #include <linux/component.h> 10 #include <linux/module.h> 11 #include <linux/of_device.h> 12 #include <linux/of_irq.h> 13 #include <linux/platform_device.h> 14 #include <linux/soc/mediatek/mtk-cmdq.h> 15 16 #include "mtk_drm_crtc.h" 17 #include "mtk_drm_ddp_comp.h" 18 19 #define DISP_REG_OVL_INTEN 0x0004 20 #define OVL_FME_CPL_INT BIT(1) 21 #define DISP_REG_OVL_INTSTA 0x0008 22 #define DISP_REG_OVL_EN 0x000c 23 #define DISP_REG_OVL_RST 0x0014 24 #define DISP_REG_OVL_ROI_SIZE 0x0020 25 #define DISP_REG_OVL_DATAPATH_CON 0x0024 26 #define OVL_BGCLR_SEL_IN BIT(2) 27 #define DISP_REG_OVL_ROI_BGCLR 0x0028 28 #define DISP_REG_OVL_SRC_CON 0x002c 29 #define DISP_REG_OVL_CON(n) (0x0030 + 0x20 * (n)) 30 #define DISP_REG_OVL_SRC_SIZE(n) (0x0038 + 0x20 * (n)) 31 #define DISP_REG_OVL_OFFSET(n) (0x003c + 0x20 * (n)) 32 #define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n)) 33 #define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n)) 34 #define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n)) 35 #define DISP_REG_OVL_ADDR_MT2701 0x0040 36 #define DISP_REG_OVL_ADDR_MT8173 0x0f40 37 #define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n)) 38 39 #define GMC_THRESHOLD_BITS 16 40 #define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4) 41 #define GMC_THRESHOLD_LOW ((1 << GMC_THRESHOLD_BITS) / 8) 42 43 #define OVL_CON_BYTE_SWAP BIT(24) 44 #define OVL_CON_MTX_YUV_TO_RGB (6 << 16) 45 #define OVL_CON_CLRFMT_RGB (1 << 12) 46 #define OVL_CON_CLRFMT_RGBA8888 (2 << 12) 47 #define OVL_CON_CLRFMT_ARGB8888 (3 << 12) 48 #define OVL_CON_CLRFMT_UYVY (4 << 12) 49 #define OVL_CON_CLRFMT_YUYV (5 << 12) 50 #define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ 51 0 : OVL_CON_CLRFMT_RGB) 52 #define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ 53 OVL_CON_CLRFMT_RGB : 0) 54 #define OVL_CON_AEN BIT(8) 55 #define OVL_CON_ALPHA 0xff 56 #define OVL_CON_VIRT_FLIP BIT(9) 57 #define OVL_CON_HORZ_FLIP BIT(10) 58 59 struct mtk_disp_ovl_data { 60 unsigned int addr; 61 unsigned int gmc_bits; 62 unsigned int layer_nr; 63 bool fmt_rgb565_is_0; 64 }; 65 66 /** 67 * struct mtk_disp_ovl - DISP_OVL driver structure 68 * @ddp_comp: structure containing type enum and hardware resources 69 * @crtc: associated crtc to report vblank events to 70 * @data: platform data 71 */ 72 struct mtk_disp_ovl { 73 struct mtk_ddp_comp ddp_comp; 74 struct drm_crtc *crtc; 75 const struct mtk_disp_ovl_data *data; 76 }; 77 78 static inline struct mtk_disp_ovl *comp_to_ovl(struct mtk_ddp_comp *comp) 79 { 80 return container_of(comp, struct mtk_disp_ovl, ddp_comp); 81 } 82 83 static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id) 84 { 85 struct mtk_disp_ovl *priv = dev_id; 86 struct mtk_ddp_comp *ovl = &priv->ddp_comp; 87 88 /* Clear frame completion interrupt */ 89 writel(0x0, ovl->regs + DISP_REG_OVL_INTSTA); 90 91 if (!priv->crtc) 92 return IRQ_NONE; 93 94 mtk_crtc_ddp_irq(priv->crtc, ovl); 95 96 return IRQ_HANDLED; 97 } 98 99 static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp, 100 struct drm_crtc *crtc) 101 { 102 struct mtk_disp_ovl *ovl = comp_to_ovl(comp); 103 104 ovl->crtc = crtc; 105 writel(0x0, comp->regs + DISP_REG_OVL_INTSTA); 106 writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN); 107 } 108 109 static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp) 110 { 111 struct mtk_disp_ovl *ovl = comp_to_ovl(comp); 112 113 ovl->crtc = NULL; 114 writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN); 115 } 116 117 static void mtk_ovl_start(struct mtk_ddp_comp *comp) 118 { 119 writel_relaxed(0x1, comp->regs + DISP_REG_OVL_EN); 120 } 121 122 static void mtk_ovl_stop(struct mtk_ddp_comp *comp) 123 { 124 writel_relaxed(0x0, comp->regs + DISP_REG_OVL_EN); 125 } 126 127 static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w, 128 unsigned int h, unsigned int vrefresh, 129 unsigned int bpc, struct cmdq_pkt *cmdq_pkt) 130 { 131 if (w != 0 && h != 0) 132 mtk_ddp_write_relaxed(cmdq_pkt, h << 16 | w, comp, 133 DISP_REG_OVL_ROI_SIZE); 134 mtk_ddp_write_relaxed(cmdq_pkt, 0x0, comp, DISP_REG_OVL_ROI_BGCLR); 135 136 mtk_ddp_write(cmdq_pkt, 0x1, comp, DISP_REG_OVL_RST); 137 mtk_ddp_write(cmdq_pkt, 0x0, comp, DISP_REG_OVL_RST); 138 } 139 140 static unsigned int mtk_ovl_layer_nr(struct mtk_ddp_comp *comp) 141 { 142 struct mtk_disp_ovl *ovl = comp_to_ovl(comp); 143 144 return ovl->data->layer_nr; 145 } 146 147 static unsigned int mtk_ovl_supported_rotations(struct mtk_ddp_comp *comp) 148 { 149 return DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | 150 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; 151 } 152 153 static int mtk_ovl_layer_check(struct mtk_ddp_comp *comp, unsigned int idx, 154 struct mtk_plane_state *mtk_state) 155 { 156 struct drm_plane_state *state = &mtk_state->base; 157 unsigned int rotation = 0; 158 159 rotation = drm_rotation_simplify(state->rotation, 160 DRM_MODE_ROTATE_0 | 161 DRM_MODE_REFLECT_X | 162 DRM_MODE_REFLECT_Y); 163 rotation &= ~DRM_MODE_ROTATE_0; 164 165 /* We can only do reflection, not rotation */ 166 if ((rotation & DRM_MODE_ROTATE_MASK) != 0) 167 return -EINVAL; 168 169 /* 170 * TODO: Rotating/reflecting YUV buffers is not supported at this time. 171 * Only RGB[AX] variants are supported. 172 */ 173 if (state->fb->format->is_yuv && rotation != 0) 174 return -EINVAL; 175 176 state->rotation = rotation; 177 178 return 0; 179 } 180 181 static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx, 182 struct cmdq_pkt *cmdq_pkt) 183 { 184 unsigned int gmc_thrshd_l; 185 unsigned int gmc_thrshd_h; 186 unsigned int gmc_value; 187 struct mtk_disp_ovl *ovl = comp_to_ovl(comp); 188 189 mtk_ddp_write(cmdq_pkt, 0x1, comp, 190 DISP_REG_OVL_RDMA_CTRL(idx)); 191 gmc_thrshd_l = GMC_THRESHOLD_LOW >> 192 (GMC_THRESHOLD_BITS - ovl->data->gmc_bits); 193 gmc_thrshd_h = GMC_THRESHOLD_HIGH >> 194 (GMC_THRESHOLD_BITS - ovl->data->gmc_bits); 195 if (ovl->data->gmc_bits == 10) 196 gmc_value = gmc_thrshd_h | gmc_thrshd_h << 16; 197 else 198 gmc_value = gmc_thrshd_l | gmc_thrshd_l << 8 | 199 gmc_thrshd_h << 16 | gmc_thrshd_h << 24; 200 mtk_ddp_write(cmdq_pkt, gmc_value, 201 comp, DISP_REG_OVL_RDMA_GMC(idx)); 202 mtk_ddp_write_mask(cmdq_pkt, BIT(idx), comp, 203 DISP_REG_OVL_SRC_CON, BIT(idx)); 204 } 205 206 static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx, 207 struct cmdq_pkt *cmdq_pkt) 208 { 209 mtk_ddp_write_mask(cmdq_pkt, 0, comp, 210 DISP_REG_OVL_SRC_CON, BIT(idx)); 211 mtk_ddp_write(cmdq_pkt, 0, comp, 212 DISP_REG_OVL_RDMA_CTRL(idx)); 213 } 214 215 static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) 216 { 217 /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" 218 * is defined in mediatek HW data sheet. 219 * The alphabet order in XXX is no relation to data 220 * arrangement in memory. 221 */ 222 switch (fmt) { 223 default: 224 case DRM_FORMAT_RGB565: 225 return OVL_CON_CLRFMT_RGB565(ovl); 226 case DRM_FORMAT_BGR565: 227 return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP; 228 case DRM_FORMAT_RGB888: 229 return OVL_CON_CLRFMT_RGB888(ovl); 230 case DRM_FORMAT_BGR888: 231 return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP; 232 case DRM_FORMAT_RGBX8888: 233 case DRM_FORMAT_RGBA8888: 234 return OVL_CON_CLRFMT_ARGB8888; 235 case DRM_FORMAT_BGRX8888: 236 case DRM_FORMAT_BGRA8888: 237 return OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP; 238 case DRM_FORMAT_XRGB8888: 239 case DRM_FORMAT_ARGB8888: 240 return OVL_CON_CLRFMT_RGBA8888; 241 case DRM_FORMAT_XBGR8888: 242 case DRM_FORMAT_ABGR8888: 243 return OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP; 244 case DRM_FORMAT_UYVY: 245 return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB; 246 case DRM_FORMAT_YUYV: 247 return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB; 248 } 249 } 250 251 static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, 252 struct mtk_plane_state *state, 253 struct cmdq_pkt *cmdq_pkt) 254 { 255 struct mtk_disp_ovl *ovl = comp_to_ovl(comp); 256 struct mtk_plane_pending_state *pending = &state->pending; 257 unsigned int addr = pending->addr; 258 unsigned int pitch = pending->pitch & 0xffff; 259 unsigned int fmt = pending->format; 260 unsigned int offset = (pending->y << 16) | pending->x; 261 unsigned int src_size = (pending->height << 16) | pending->width; 262 unsigned int con; 263 264 if (!pending->enable) { 265 mtk_ovl_layer_off(comp, idx, cmdq_pkt); 266 return; 267 } 268 269 con = ovl_fmt_convert(ovl, fmt); 270 if (state->base.fb->format->has_alpha) 271 con |= OVL_CON_AEN | OVL_CON_ALPHA; 272 273 if (pending->rotation & DRM_MODE_REFLECT_Y) { 274 con |= OVL_CON_VIRT_FLIP; 275 addr += (pending->height - 1) * pending->pitch; 276 } 277 278 if (pending->rotation & DRM_MODE_REFLECT_X) { 279 con |= OVL_CON_HORZ_FLIP; 280 addr += pending->pitch - 1; 281 } 282 283 mtk_ddp_write_relaxed(cmdq_pkt, con, comp, 284 DISP_REG_OVL_CON(idx)); 285 mtk_ddp_write_relaxed(cmdq_pkt, pitch, comp, 286 DISP_REG_OVL_PITCH(idx)); 287 mtk_ddp_write_relaxed(cmdq_pkt, src_size, comp, 288 DISP_REG_OVL_SRC_SIZE(idx)); 289 mtk_ddp_write_relaxed(cmdq_pkt, offset, comp, 290 DISP_REG_OVL_OFFSET(idx)); 291 mtk_ddp_write_relaxed(cmdq_pkt, addr, comp, 292 DISP_REG_OVL_ADDR(ovl, idx)); 293 294 mtk_ovl_layer_on(comp, idx, cmdq_pkt); 295 } 296 297 static void mtk_ovl_bgclr_in_on(struct mtk_ddp_comp *comp) 298 { 299 unsigned int reg; 300 301 reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON); 302 reg = reg | OVL_BGCLR_SEL_IN; 303 writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON); 304 } 305 306 static void mtk_ovl_bgclr_in_off(struct mtk_ddp_comp *comp) 307 { 308 unsigned int reg; 309 310 reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON); 311 reg = reg & ~OVL_BGCLR_SEL_IN; 312 writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON); 313 } 314 315 static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = { 316 .config = mtk_ovl_config, 317 .start = mtk_ovl_start, 318 .stop = mtk_ovl_stop, 319 .enable_vblank = mtk_ovl_enable_vblank, 320 .disable_vblank = mtk_ovl_disable_vblank, 321 .supported_rotations = mtk_ovl_supported_rotations, 322 .layer_nr = mtk_ovl_layer_nr, 323 .layer_check = mtk_ovl_layer_check, 324 .layer_config = mtk_ovl_layer_config, 325 .bgclr_in_on = mtk_ovl_bgclr_in_on, 326 .bgclr_in_off = mtk_ovl_bgclr_in_off, 327 }; 328 329 static int mtk_disp_ovl_bind(struct device *dev, struct device *master, 330 void *data) 331 { 332 struct mtk_disp_ovl *priv = dev_get_drvdata(dev); 333 struct drm_device *drm_dev = data; 334 int ret; 335 336 ret = mtk_ddp_comp_register(drm_dev, &priv->ddp_comp); 337 if (ret < 0) { 338 dev_err(dev, "Failed to register component %pOF: %d\n", 339 dev->of_node, ret); 340 return ret; 341 } 342 343 return 0; 344 } 345 346 static void mtk_disp_ovl_unbind(struct device *dev, struct device *master, 347 void *data) 348 { 349 struct mtk_disp_ovl *priv = dev_get_drvdata(dev); 350 struct drm_device *drm_dev = data; 351 352 mtk_ddp_comp_unregister(drm_dev, &priv->ddp_comp); 353 } 354 355 static const struct component_ops mtk_disp_ovl_component_ops = { 356 .bind = mtk_disp_ovl_bind, 357 .unbind = mtk_disp_ovl_unbind, 358 }; 359 360 static int mtk_disp_ovl_probe(struct platform_device *pdev) 361 { 362 struct device *dev = &pdev->dev; 363 struct mtk_disp_ovl *priv; 364 int comp_id; 365 int irq; 366 int ret; 367 368 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 369 if (!priv) 370 return -ENOMEM; 371 372 irq = platform_get_irq(pdev, 0); 373 if (irq < 0) 374 return irq; 375 376 priv->data = of_device_get_match_data(dev); 377 378 comp_id = mtk_ddp_comp_get_id(dev->of_node, 379 priv->data->layer_nr == 4 ? 380 MTK_DISP_OVL : 381 MTK_DISP_OVL_2L); 382 if (comp_id < 0) { 383 dev_err(dev, "Failed to identify by alias: %d\n", comp_id); 384 return comp_id; 385 } 386 387 ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id, 388 &mtk_disp_ovl_funcs); 389 if (ret) { 390 if (ret != -EPROBE_DEFER) 391 dev_err(dev, "Failed to initialize component: %d\n", 392 ret); 393 394 return ret; 395 } 396 397 platform_set_drvdata(pdev, priv); 398 399 ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler, 400 IRQF_TRIGGER_NONE, dev_name(dev), priv); 401 if (ret < 0) { 402 dev_err(dev, "Failed to request irq %d: %d\n", irq, ret); 403 return ret; 404 } 405 406 ret = component_add(dev, &mtk_disp_ovl_component_ops); 407 if (ret) 408 dev_err(dev, "Failed to add component: %d\n", ret); 409 410 return ret; 411 } 412 413 static int mtk_disp_ovl_remove(struct platform_device *pdev) 414 { 415 component_del(&pdev->dev, &mtk_disp_ovl_component_ops); 416 417 return 0; 418 } 419 420 static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { 421 .addr = DISP_REG_OVL_ADDR_MT2701, 422 .gmc_bits = 8, 423 .layer_nr = 4, 424 .fmt_rgb565_is_0 = false, 425 }; 426 427 static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = { 428 .addr = DISP_REG_OVL_ADDR_MT8173, 429 .gmc_bits = 8, 430 .layer_nr = 4, 431 .fmt_rgb565_is_0 = true, 432 }; 433 434 static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = { 435 { .compatible = "mediatek,mt2701-disp-ovl", 436 .data = &mt2701_ovl_driver_data}, 437 { .compatible = "mediatek,mt8173-disp-ovl", 438 .data = &mt8173_ovl_driver_data}, 439 {}, 440 }; 441 MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match); 442 443 struct platform_driver mtk_disp_ovl_driver = { 444 .probe = mtk_disp_ovl_probe, 445 .remove = mtk_disp_ovl_remove, 446 .driver = { 447 .name = "mediatek-disp-ovl", 448 .owner = THIS_MODULE, 449 .of_match_table = mtk_disp_ovl_driver_dt_match, 450 }, 451 }; 452