Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'drm-next-4.12' of https://github.com/ckhu-mediatek/linux.git-tags into drm-next

This series is MT2701 DRM support.

* 'drm-next-4.12' of https://github.com/ckhu-mediatek/linux.git-tags:
drm/mediatek: add support for Mediatek SoC MT2701
drm/mediatek: update DSI sub driver flow for sending commands to panel
drm/mediatek: add non-continuous clock mode and EOT packet control
drm/mediatek: add dsi transfer function
drm/mediatek: add dsi interrupt control
drm/mediatek: cleaning up and refine
drm/mediatek: update display module connections
drm/mediatek: add BLS component
drm/mediatek: add shadow register support
drm/mediatek: add *driver_data for different hardware settings
drm/mediatek: add helpers for coverting from the generic components
dt-bindings: display: mediatek: update supported chips

+920 -330
+2
Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
··· 40 40 "mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt 41 41 "mediatek,<chip>-disp-mutex" - display mutex 42 42 "mediatek,<chip>-disp-od" - overdrive 43 + the supported chips are mt2701 and mt8173. 43 44 - reg: Physical base address and length of the function block register space 44 45 - interrupts: The interrupt signal from the function block (required, except for 45 46 merge and split function blocks). ··· 55 54 "mediatek,<chip>-disp-ovl" 56 55 "mediatek,<chip>-disp-rdma" 57 56 "mediatek,<chip>-disp-wdma" 57 + the supported chips are mt2701 and mt8173. 58 58 - larb: Should contain a phandle pointing to the local arbiter device as defined 59 59 in Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt 60 60 - iommus: Should point to the respective IOMMU block with master port as
+2
Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt
··· 7 7 8 8 Required properties: 9 9 - compatible: "mediatek,<chip>-dsi" 10 + the supported chips are mt2701 and mt8173. 10 11 - reg: Physical base address and length of the controller's registers 11 12 - interrupts: The interrupt signal from the function block. 12 13 - clocks: device clocks ··· 26 25 27 26 Required properties: 28 27 - compatible: "mediatek,<chip>-mipi-tx" 28 + the supported chips are mt2701 and mt8173. 29 29 - reg: Physical base address and length of the controller's registers 30 30 - clocks: PLL reference clock 31 31 - clock-output-names: name of the output clock line to the DSI encoder
+47 -17
drivers/gpu/drm/mediatek/mtk_disp_ovl.c
··· 35 35 #define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n)) 36 36 #define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n)) 37 37 #define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n)) 38 - #define DISP_REG_OVL_ADDR(n) (0x0f40 + 0x20 * (n)) 38 + #define DISP_REG_OVL_ADDR_MT2701 0x0040 39 + #define DISP_REG_OVL_ADDR_MT8173 0x0f40 40 + #define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n)) 39 41 40 42 #define OVL_RDMA_MEM_GMC 0x40402020 41 43 42 44 #define OVL_CON_BYTE_SWAP BIT(24) 43 - #define OVL_CON_CLRFMT_RGB565 (0 << 12) 44 - #define OVL_CON_CLRFMT_RGB888 (1 << 12) 45 + #define OVL_CON_CLRFMT_RGB (1 << 12) 45 46 #define OVL_CON_CLRFMT_RGBA8888 (2 << 12) 46 47 #define OVL_CON_CLRFMT_ARGB8888 (3 << 12) 48 + #define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ 49 + 0 : OVL_CON_CLRFMT_RGB) 50 + #define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ 51 + OVL_CON_CLRFMT_RGB : 0) 47 52 #define OVL_CON_AEN BIT(8) 48 53 #define OVL_CON_ALPHA 0xff 54 + 55 + struct mtk_disp_ovl_data { 56 + unsigned int addr; 57 + bool fmt_rgb565_is_0; 58 + }; 49 59 50 60 /** 51 61 * struct mtk_disp_ovl - DISP_OVL driver structure ··· 65 55 struct mtk_disp_ovl { 66 56 struct mtk_ddp_comp ddp_comp; 67 57 struct drm_crtc *crtc; 58 + const struct mtk_disp_ovl_data *data; 68 59 }; 60 + 61 + static inline struct mtk_disp_ovl *comp_to_ovl(struct mtk_ddp_comp *comp) 62 + { 63 + return container_of(comp, struct mtk_disp_ovl, ddp_comp); 64 + } 69 65 70 66 static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id) 71 67 { ··· 92 76 static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp, 93 77 struct drm_crtc *crtc) 94 78 { 95 - struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl, 96 - ddp_comp); 79 + struct mtk_disp_ovl *ovl = comp_to_ovl(comp); 97 80 98 - priv->crtc = crtc; 81 + ovl->crtc = crtc; 99 82 writel(0x0, comp->regs + DISP_REG_OVL_INTSTA); 100 83 writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN); 101 84 } 102 85 103 86 static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp) 104 87 { 105 - struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl, 106 - ddp_comp); 88 + struct mtk_disp_ovl *ovl = comp_to_ovl(comp); 107 89 108 - priv->crtc = NULL; 90 + ovl->crtc = NULL; 109 91 writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN); 110 92 } 111 93 ··· 152 138 writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx)); 153 139 } 154 140 155 - static unsigned int ovl_fmt_convert(unsigned int fmt) 141 + static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) 156 142 { 157 143 switch (fmt) { 158 144 default: 159 145 case DRM_FORMAT_RGB565: 160 - return OVL_CON_CLRFMT_RGB565; 146 + return OVL_CON_CLRFMT_RGB565(ovl); 161 147 case DRM_FORMAT_BGR565: 162 - return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP; 148 + return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP; 163 149 case DRM_FORMAT_RGB888: 164 - return OVL_CON_CLRFMT_RGB888; 150 + return OVL_CON_CLRFMT_RGB888(ovl); 165 151 case DRM_FORMAT_BGR888: 166 - return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP; 152 + return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP; 167 153 case DRM_FORMAT_RGBX8888: 168 154 case DRM_FORMAT_RGBA8888: 169 155 return OVL_CON_CLRFMT_ARGB8888; ··· 182 168 static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, 183 169 struct mtk_plane_state *state) 184 170 { 171 + struct mtk_disp_ovl *ovl = comp_to_ovl(comp); 185 172 struct mtk_plane_pending_state *pending = &state->pending; 186 173 unsigned int addr = pending->addr; 187 174 unsigned int pitch = pending->pitch & 0xffff; ··· 194 179 if (!pending->enable) 195 180 mtk_ovl_layer_off(comp, idx); 196 181 197 - con = ovl_fmt_convert(fmt); 182 + con = ovl_fmt_convert(ovl, fmt); 198 183 if (idx != 0) 199 184 con |= OVL_CON_AEN | OVL_CON_ALPHA; 200 185 ··· 202 187 writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx)); 203 188 writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx)); 204 189 writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx)); 205 - writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx)); 190 + writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(ovl, idx)); 206 191 207 192 if (pending->enable) 208 193 mtk_ovl_layer_on(comp, idx); ··· 279 264 return ret; 280 265 } 281 266 267 + priv->data = of_device_get_match_data(dev); 268 + 282 269 platform_set_drvdata(pdev, priv); 283 270 284 271 ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler, ··· 304 287 return 0; 305 288 } 306 289 290 + static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { 291 + .addr = DISP_REG_OVL_ADDR_MT2701, 292 + .fmt_rgb565_is_0 = false, 293 + }; 294 + 295 + static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = { 296 + .addr = DISP_REG_OVL_ADDR_MT8173, 297 + .fmt_rgb565_is_0 = true, 298 + }; 299 + 307 300 static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = { 308 - { .compatible = "mediatek,mt8173-disp-ovl", }, 301 + { .compatible = "mediatek,mt2701-disp-ovl", 302 + .data = &mt2701_ovl_driver_data}, 303 + { .compatible = "mediatek,mt8173-disp-ovl", 304 + .data = &mt8173_ovl_driver_data}, 309 305 {}, 310 306 }; 311 307 MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
+31 -8
drivers/gpu/drm/mediatek/mtk_disp_rdma.c
··· 38 38 #define RDMA_FIFO_UNDERFLOW_EN BIT(31) 39 39 #define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16) 40 40 #define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16) 41 + #define RDMA_FIFO_SIZE(rdma) ((rdma)->data->fifo_size) 42 + 43 + struct mtk_disp_rdma_data { 44 + unsigned int fifo_size; 45 + }; 41 46 42 47 /** 43 48 * struct mtk_disp_rdma - DISP_RDMA driver structure ··· 52 47 struct mtk_disp_rdma { 53 48 struct mtk_ddp_comp ddp_comp; 54 49 struct drm_crtc *crtc; 50 + const struct mtk_disp_rdma_data *data; 55 51 }; 52 + 53 + static inline struct mtk_disp_rdma *comp_to_rdma(struct mtk_ddp_comp *comp) 54 + { 55 + return container_of(comp, struct mtk_disp_rdma, ddp_comp); 56 + } 56 57 57 58 static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id) 58 59 { ··· 88 77 static void mtk_rdma_enable_vblank(struct mtk_ddp_comp *comp, 89 78 struct drm_crtc *crtc) 90 79 { 91 - struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma, 92 - ddp_comp); 80 + struct mtk_disp_rdma *rdma = comp_to_rdma(comp); 93 81 94 - priv->crtc = crtc; 82 + rdma->crtc = crtc; 95 83 rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 96 84 RDMA_FRAME_END_INT); 97 85 } 98 86 99 87 static void mtk_rdma_disable_vblank(struct mtk_ddp_comp *comp) 100 88 { 101 - struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma, 102 - ddp_comp); 89 + struct mtk_disp_rdma *rdma = comp_to_rdma(comp); 103 90 104 - priv->crtc = NULL; 91 + rdma->crtc = NULL; 105 92 rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0); 106 93 } 107 94 ··· 120 111 { 121 112 unsigned int threshold; 122 113 unsigned int reg; 114 + struct mtk_disp_rdma *rdma = comp_to_rdma(comp); 123 115 124 116 rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, 0xfff, width); 125 117 rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_1, 0xfffff, height); ··· 133 123 */ 134 124 threshold = width * height * vrefresh * 4 * 7 / 1000000; 135 125 reg = RDMA_FIFO_UNDERFLOW_EN | 136 - RDMA_FIFO_PSEUDO_SIZE(SZ_8K) | 126 + RDMA_FIFO_PSEUDO_SIZE(RDMA_FIFO_SIZE(rdma)) | 137 127 RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold); 138 128 writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON); 139 129 } ··· 218 208 return ret; 219 209 } 220 210 211 + priv->data = of_device_get_match_data(dev); 212 + 221 213 platform_set_drvdata(pdev, priv); 222 214 223 215 ret = component_add(dev, &mtk_disp_rdma_component_ops); ··· 236 224 return 0; 237 225 } 238 226 227 + static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = { 228 + .fifo_size = SZ_4K, 229 + }; 230 + 231 + static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = { 232 + .fifo_size = SZ_8K, 233 + }; 234 + 239 235 static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = { 240 - { .compatible = "mediatek,mt8173-disp-rdma", }, 236 + { .compatible = "mediatek,mt2701-disp-rdma", 237 + .data = &mt2701_rdma_driver_data}, 238 + { .compatible = "mediatek,mt8173-disp-rdma", 239 + .data = &mt8173_rdma_driver_data}, 241 240 {}, 242 241 }; 243 242 MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
+46 -29
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
··· 327 327 pm_runtime_put(drm->dev); 328 328 } 329 329 330 + static void mtk_crtc_ddp_config(struct drm_crtc *crtc) 331 + { 332 + struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); 333 + struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state); 334 + struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; 335 + unsigned int i; 336 + 337 + /* 338 + * TODO: instead of updating the registers here, we should prepare 339 + * working registers in atomic_commit and let the hardware command 340 + * queue update module registers on vblank. 341 + */ 342 + if (state->pending_config) { 343 + mtk_ddp_comp_config(ovl, state->pending_width, 344 + state->pending_height, 345 + state->pending_vrefresh, 0); 346 + 347 + state->pending_config = false; 348 + } 349 + 350 + if (mtk_crtc->pending_planes) { 351 + for (i = 0; i < OVL_LAYER_NR; i++) { 352 + struct drm_plane *plane = &mtk_crtc->planes[i]; 353 + struct mtk_plane_state *plane_state; 354 + 355 + plane_state = to_mtk_plane_state(plane->state); 356 + 357 + if (plane_state->pending.config) { 358 + mtk_ddp_comp_layer_config(ovl, i, plane_state); 359 + plane_state->pending.config = false; 360 + } 361 + } 362 + mtk_crtc->pending_planes = false; 363 + } 364 + } 365 + 330 366 static void mtk_drm_crtc_enable(struct drm_crtc *crtc) 331 367 { 332 368 struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); ··· 439 403 struct drm_crtc_state *old_crtc_state) 440 404 { 441 405 struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); 406 + struct mtk_drm_private *priv = crtc->dev->dev_private; 442 407 unsigned int pending_planes = 0; 443 408 int i; 444 409 ··· 461 424 if (crtc->state->color_mgmt_changed) 462 425 for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) 463 426 mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state); 427 + 428 + if (priv->data->shadow_register) { 429 + mtk_disp_mutex_acquire(mtk_crtc->mutex); 430 + mtk_crtc_ddp_config(crtc); 431 + mtk_disp_mutex_release(mtk_crtc->mutex); 432 + } 464 433 } 465 434 466 435 static const struct drm_crtc_funcs mtk_crtc_funcs = { ··· 514 471 void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl) 515 472 { 516 473 struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); 517 - struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state); 518 - unsigned int i; 474 + struct mtk_drm_private *priv = crtc->dev->dev_private; 519 475 520 - /* 521 - * TODO: instead of updating the registers here, we should prepare 522 - * working registers in atomic_commit and let the hardware command 523 - * queue update module registers on vblank. 524 - */ 525 - if (state->pending_config) { 526 - mtk_ddp_comp_config(ovl, state->pending_width, 527 - state->pending_height, 528 - state->pending_vrefresh, 0); 529 - 530 - state->pending_config = false; 531 - } 532 - 533 - if (mtk_crtc->pending_planes) { 534 - for (i = 0; i < OVL_LAYER_NR; i++) { 535 - struct drm_plane *plane = &mtk_crtc->planes[i]; 536 - struct mtk_plane_state *plane_state; 537 - 538 - plane_state = to_mtk_plane_state(plane->state); 539 - 540 - if (plane_state->pending.config) { 541 - mtk_ddp_comp_layer_config(ovl, i, plane_state); 542 - plane_state->pending.config = false; 543 - } 544 - } 545 - mtk_crtc->pending_planes = false; 546 - } 476 + if (!priv->data->shadow_register) 477 + mtk_crtc_ddp_config(crtc); 547 478 548 479 mtk_drm_finish_page_flip(mtk_crtc); 549 480 }
+104 -34
drivers/gpu/drm/mediatek/mtk_drm_ddp.c
··· 12 12 */ 13 13 14 14 #include <linux/clk.h> 15 + #include <linux/iopoll.h> 15 16 #include <linux/module.h> 16 17 #include <linux/of_device.h> 17 18 #include <linux/platform_device.h> ··· 32 31 #define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN 0x0c8 33 32 #define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100 34 33 34 + #define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030 35 + #define DISP_REG_CONFIG_OUT_SEL 0x04c 36 + #define DISP_REG_CONFIG_DSI_SEL 0x050 37 + 35 38 #define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) 39 + #define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n)) 36 40 #define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n)) 37 41 #define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n)) 38 42 #define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n)) 39 43 40 - #define MUTEX_MOD_DISP_OVL0 BIT(11) 41 - #define MUTEX_MOD_DISP_OVL1 BIT(12) 42 - #define MUTEX_MOD_DISP_RDMA0 BIT(13) 43 - #define MUTEX_MOD_DISP_RDMA1 BIT(14) 44 - #define MUTEX_MOD_DISP_RDMA2 BIT(15) 45 - #define MUTEX_MOD_DISP_WDMA0 BIT(16) 46 - #define MUTEX_MOD_DISP_WDMA1 BIT(17) 47 - #define MUTEX_MOD_DISP_COLOR0 BIT(18) 48 - #define MUTEX_MOD_DISP_COLOR1 BIT(19) 49 - #define MUTEX_MOD_DISP_AAL BIT(20) 50 - #define MUTEX_MOD_DISP_GAMMA BIT(21) 51 - #define MUTEX_MOD_DISP_UFOE BIT(22) 52 - #define MUTEX_MOD_DISP_PWM0 BIT(23) 53 - #define MUTEX_MOD_DISP_PWM1 BIT(24) 54 - #define MUTEX_MOD_DISP_OD BIT(25) 44 + #define INT_MUTEX BIT(1) 45 + 46 + #define MT8173_MUTEX_MOD_DISP_OVL0 BIT(11) 47 + #define MT8173_MUTEX_MOD_DISP_OVL1 BIT(12) 48 + #define MT8173_MUTEX_MOD_DISP_RDMA0 BIT(13) 49 + #define MT8173_MUTEX_MOD_DISP_RDMA1 BIT(14) 50 + #define MT8173_MUTEX_MOD_DISP_RDMA2 BIT(15) 51 + #define MT8173_MUTEX_MOD_DISP_WDMA0 BIT(16) 52 + #define MT8173_MUTEX_MOD_DISP_WDMA1 BIT(17) 53 + #define MT8173_MUTEX_MOD_DISP_COLOR0 BIT(18) 54 + #define MT8173_MUTEX_MOD_DISP_COLOR1 BIT(19) 55 + #define MT8173_MUTEX_MOD_DISP_AAL BIT(20) 56 + #define MT8173_MUTEX_MOD_DISP_GAMMA BIT(21) 57 + #define MT8173_MUTEX_MOD_DISP_UFOE BIT(22) 58 + #define MT8173_MUTEX_MOD_DISP_PWM0 BIT(23) 59 + #define MT8173_MUTEX_MOD_DISP_PWM1 BIT(24) 60 + #define MT8173_MUTEX_MOD_DISP_OD BIT(25) 61 + 62 + #define MT2701_MUTEX_MOD_DISP_OVL BIT(3) 63 + #define MT2701_MUTEX_MOD_DISP_WDMA BIT(6) 64 + #define MT2701_MUTEX_MOD_DISP_COLOR BIT(7) 65 + #define MT2701_MUTEX_MOD_DISP_BLS BIT(9) 66 + #define MT2701_MUTEX_MOD_DISP_RDMA0 BIT(10) 67 + #define MT2701_MUTEX_MOD_DISP_RDMA1 BIT(12) 55 68 56 69 #define MUTEX_SOF_SINGLE_MODE 0 57 70 #define MUTEX_SOF_DSI0 1 ··· 82 67 #define DPI0_SEL_IN_RDMA1 0x1 83 68 #define COLOR1_SEL_IN_OVL1 0x1 84 69 70 + #define OVL_MOUT_EN_RDMA 0x1 71 + #define BLS_TO_DSI_RDMA1_TO_DPI1 0x8 72 + #define DSI_SEL_IN_BLS 0x0 73 + 85 74 struct mtk_disp_mutex { 86 75 int id; 87 76 bool claimed; ··· 96 77 struct clk *clk; 97 78 void __iomem *regs; 98 79 struct mtk_disp_mutex mutex[10]; 80 + const unsigned int *mutex_mod; 99 81 }; 100 82 101 - static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = { 102 - [DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL, 103 - [DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0, 104 - [DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1, 105 - [DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA, 106 - [DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD, 107 - [DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0, 108 - [DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1, 109 - [DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0, 110 - [DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1, 111 - [DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0, 112 - [DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1, 113 - [DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2, 114 - [DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE, 115 - [DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0, 116 - [DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1, 83 + static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = { 84 + [DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS, 85 + [DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR, 86 + [DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL, 87 + [DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0, 88 + [DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1, 89 + [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA, 90 + }; 91 + 92 + static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = { 93 + [DDP_COMPONENT_AAL] = MT8173_MUTEX_MOD_DISP_AAL, 94 + [DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0, 95 + [DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1, 96 + [DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA, 97 + [DDP_COMPONENT_OD] = MT8173_MUTEX_MOD_DISP_OD, 98 + [DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0, 99 + [DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1, 100 + [DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0, 101 + [DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1, 102 + [DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0, 103 + [DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1, 104 + [DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2, 105 + [DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE, 106 + [DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0, 107 + [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1, 117 108 }; 118 109 119 110 static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, ··· 135 106 if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) { 136 107 *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN; 137 108 value = OVL0_MOUT_EN_COLOR0; 109 + } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) { 110 + *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN; 111 + value = OVL_MOUT_EN_RDMA; 138 112 } else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) { 139 113 *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN; 140 114 value = OD_MOUT_EN_RDMA0; ··· 175 143 } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) { 176 144 *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN; 177 145 value = COLOR1_SEL_IN_OVL1; 146 + } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) { 147 + *addr = DISP_REG_CONFIG_DSI_SEL; 148 + value = DSI_SEL_IN_BLS; 178 149 } else { 179 150 value = 0; 180 151 } 181 152 182 153 return value; 154 + } 155 + 156 + static void mtk_ddp_sout_sel(void __iomem *config_regs, 157 + enum mtk_ddp_comp_id cur, 158 + enum mtk_ddp_comp_id next) 159 + { 160 + if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) 161 + writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1, 162 + config_regs + DISP_REG_CONFIG_OUT_SEL); 183 163 } 184 164 185 165 void mtk_ddp_add_comp_to_path(void __iomem *config_regs, ··· 205 161 reg = readl_relaxed(config_regs + addr) | value; 206 162 writel_relaxed(reg, config_regs + addr); 207 163 } 164 + 165 + mtk_ddp_sout_sel(config_regs, cur, next); 208 166 209 167 value = mtk_ddp_sel_in(cur, next, &addr); 210 168 if (value) { ··· 293 247 break; 294 248 default: 295 249 reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); 296 - reg |= mutex_mod[id]; 250 + reg |= ddp->mutex_mod[id]; 297 251 writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); 298 252 return; 299 253 } ··· 319 273 break; 320 274 default: 321 275 reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); 322 - reg &= ~mutex_mod[id]; 276 + reg &= ~(ddp->mutex_mod[id]); 323 277 writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); 324 278 break; 325 279 } ··· 343 297 WARN_ON(&ddp->mutex[mutex->id] != mutex); 344 298 345 299 writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); 300 + } 301 + 302 + void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex) 303 + { 304 + struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 305 + mutex[mutex->id]); 306 + u32 tmp; 307 + 308 + writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); 309 + writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id)); 310 + if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id), 311 + tmp, tmp & INT_MUTEX, 1, 10000)) 312 + pr_err("could not acquire mutex %d\n", mutex->id); 313 + } 314 + 315 + void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex) 316 + { 317 + struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 318 + mutex[mutex->id]); 319 + 320 + writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id)); 346 321 } 347 322 348 323 static int mtk_ddp_probe(struct platform_device *pdev) ··· 393 326 return PTR_ERR(ddp->regs); 394 327 } 395 328 329 + ddp->mutex_mod = of_device_get_match_data(dev); 330 + 396 331 platform_set_drvdata(pdev, ddp); 397 332 398 333 return 0; ··· 406 337 } 407 338 408 339 static const struct of_device_id ddp_driver_dt_match[] = { 409 - { .compatible = "mediatek,mt8173-disp-mutex" }, 340 + { .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod}, 341 + { .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod}, 410 342 {}, 411 343 }; 412 344 MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
+2
drivers/gpu/drm/mediatek/mtk_drm_ddp.h
··· 37 37 enum mtk_ddp_comp_id id); 38 38 void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex); 39 39 void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex); 40 + void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex); 41 + void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex); 40 42 41 43 #endif /* MTK_DRM_DDP_H */
+60 -9
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
··· 39 39 #define DISP_REG_UFO_START 0x0000 40 40 41 41 #define DISP_COLOR_CFG_MAIN 0x0400 42 - #define DISP_COLOR_START 0x0c00 43 - #define DISP_COLOR_WIDTH 0x0c50 44 - #define DISP_COLOR_HEIGHT 0x0c54 42 + #define DISP_COLOR_START_MT2701 0x0f00 43 + #define DISP_COLOR_START_MT8173 0x0c00 44 + #define DISP_COLOR_START(comp) ((comp)->data->color_offset) 45 + #define DISP_COLOR_WIDTH(comp) (DISP_COLOR_START(comp) + 0x50) 46 + #define DISP_COLOR_HEIGHT(comp) (DISP_COLOR_START(comp) + 0x54) 45 47 46 48 #define DISP_AAL_EN 0x0000 47 49 #define DISP_AAL_SIZE 0x0030 ··· 82 80 #define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4) 83 81 #define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0) 84 82 83 + struct mtk_disp_color_data { 84 + unsigned int color_offset; 85 + }; 86 + 87 + struct mtk_disp_color { 88 + struct mtk_ddp_comp ddp_comp; 89 + const struct mtk_disp_color_data *data; 90 + }; 91 + 92 + static inline struct mtk_disp_color *comp_to_color(struct mtk_ddp_comp *comp) 93 + { 94 + return container_of(comp, struct mtk_disp_color, ddp_comp); 95 + } 96 + 85 97 void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc, 86 98 unsigned int CFG) 87 99 { ··· 123 107 unsigned int h, unsigned int vrefresh, 124 108 unsigned int bpc) 125 109 { 126 - writel(w, comp->regs + DISP_COLOR_WIDTH); 127 - writel(h, comp->regs + DISP_COLOR_HEIGHT); 110 + struct mtk_disp_color *color = comp_to_color(comp); 111 + 112 + writel(w, comp->regs + DISP_COLOR_WIDTH(color)); 113 + writel(h, comp->regs + DISP_COLOR_HEIGHT(color)); 128 114 } 129 115 130 116 static void mtk_color_start(struct mtk_ddp_comp *comp) 131 117 { 118 + struct mtk_disp_color *color = comp_to_color(comp); 119 + 132 120 writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL, 133 121 comp->regs + DISP_COLOR_CFG_MAIN); 134 - writel(0x1, comp->regs + DISP_COLOR_START); 122 + writel(0x1, comp->regs + DISP_COLOR_START(color)); 135 123 } 136 124 137 125 static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w, ··· 256 236 [MTK_DISP_PWM] = "pwm", 257 237 [MTK_DISP_MUTEX] = "mutex", 258 238 [MTK_DISP_OD] = "od", 239 + [MTK_DISP_BLS] = "bls", 259 240 }; 260 241 261 242 struct mtk_ddp_comp_match { ··· 267 246 268 247 static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { 269 248 [DDP_COMPONENT_AAL] = { MTK_DISP_AAL, 0, &ddp_aal }, 249 + [DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL }, 270 250 [DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color }, 271 251 [DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color }, 272 252 [DDP_COMPONENT_DPI0] = { MTK_DPI, 0, NULL }, ··· 284 262 [DDP_COMPONENT_UFOE] = { MTK_DISP_UFOE, 0, &ddp_ufoe }, 285 263 [DDP_COMPONENT_WDMA0] = { MTK_DISP_WDMA, 0, NULL }, 286 264 [DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL }, 265 + }; 266 + 267 + static const struct mtk_disp_color_data mt2701_color_driver_data = { 268 + .color_offset = DISP_COLOR_START_MT2701, 269 + }; 270 + 271 + static const struct mtk_disp_color_data mt8173_color_driver_data = { 272 + .color_offset = DISP_COLOR_START_MT8173, 273 + }; 274 + 275 + static const struct of_device_id mtk_disp_color_driver_dt_match[] = { 276 + { .compatible = "mediatek,mt2701-disp-color", 277 + .data = &mt2701_color_driver_data}, 278 + { .compatible = "mediatek,mt8173-disp-color", 279 + .data = &mt8173_color_driver_data}, 280 + {}, 287 281 }; 288 282 289 283 int mtk_ddp_comp_get_id(struct device_node *node, ··· 324 286 enum mtk_ddp_comp_type type; 325 287 struct device_node *larb_node; 326 288 struct platform_device *larb_pdev; 289 + const struct of_device_id *match; 290 + struct mtk_disp_color *color; 327 291 328 292 if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) 329 293 return -EINVAL; 330 294 295 + type = mtk_ddp_matches[comp_id].type; 296 + if (type == MTK_DISP_COLOR) { 297 + devm_kfree(dev, comp); 298 + color = devm_kzalloc(dev, sizeof(*color), GFP_KERNEL); 299 + if (!color) 300 + return -ENOMEM; 301 + 302 + match = of_match_node(mtk_disp_color_driver_dt_match, node); 303 + color->data = match->data; 304 + comp = &color->ddp_comp; 305 + } 306 + 331 307 comp->id = comp_id; 332 308 comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs; 333 309 334 - if (comp_id == DDP_COMPONENT_DPI0 || 310 + if (comp_id == DDP_COMPONENT_BLS || 311 + comp_id == DDP_COMPONENT_DPI0 || 335 312 comp_id == DDP_COMPONENT_DSI0 || 336 313 comp_id == DDP_COMPONENT_PWM0) { 337 314 comp->regs = NULL; ··· 360 307 comp->clk = of_clk_get(node, 0); 361 308 if (IS_ERR(comp->clk)) 362 309 comp->clk = NULL; 363 - 364 - type = mtk_ddp_matches[comp_id].type; 365 310 366 311 /* Only DMA capable components need the LARB property */ 367 312 comp->larb_dev = NULL;
+2
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
··· 36 36 MTK_DISP_PWM, 37 37 MTK_DISP_MUTEX, 38 38 MTK_DISP_OD, 39 + MTK_DISP_BLS, 39 40 MTK_DDP_COMP_TYPE_MAX, 40 41 }; 41 42 42 43 enum mtk_ddp_comp_id { 43 44 DDP_COMPONENT_AAL, 45 + DDP_COMPONENT_BLS, 44 46 DDP_COMPONENT_COLOR0, 45 47 DDP_COMPONENT_COLOR1, 46 48 DDP_COMPONENT_DPI0,
+47 -7
drivers/gpu/drm/mediatek/mtk_drm_drv.c
··· 128 128 .atomic_commit = mtk_atomic_commit, 129 129 }; 130 130 131 - static const enum mtk_ddp_comp_id mtk_ddp_main[] = { 131 + static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { 132 + DDP_COMPONENT_OVL0, 133 + DDP_COMPONENT_RDMA0, 134 + DDP_COMPONENT_COLOR0, 135 + DDP_COMPONENT_BLS, 136 + DDP_COMPONENT_DSI0, 137 + }; 138 + 139 + static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = { 140 + DDP_COMPONENT_RDMA1, 141 + DDP_COMPONENT_DPI0, 142 + }; 143 + 144 + static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = { 132 145 DDP_COMPONENT_OVL0, 133 146 DDP_COMPONENT_COLOR0, 134 147 DDP_COMPONENT_AAL, ··· 152 139 DDP_COMPONENT_PWM0, 153 140 }; 154 141 155 - static const enum mtk_ddp_comp_id mtk_ddp_ext[] = { 142 + static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = { 156 143 DDP_COMPONENT_OVL1, 157 144 DDP_COMPONENT_COLOR1, 158 145 DDP_COMPONENT_GAMMA, 159 146 DDP_COMPONENT_RDMA1, 160 147 DDP_COMPONENT_DPI0, 148 + }; 149 + 150 + static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { 151 + .main_path = mt2701_mtk_ddp_main, 152 + .main_len = ARRAY_SIZE(mt2701_mtk_ddp_main), 153 + .ext_path = mt2701_mtk_ddp_ext, 154 + .ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext), 155 + .shadow_register = true, 156 + }; 157 + 158 + static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { 159 + .main_path = mt8173_mtk_ddp_main, 160 + .main_len = ARRAY_SIZE(mt8173_mtk_ddp_main), 161 + .ext_path = mt8173_mtk_ddp_ext, 162 + .ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext), 161 163 }; 162 164 163 165 static int mtk_drm_kms_init(struct drm_device *drm) ··· 217 189 * and each statically assigned to a crtc: 218 190 * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ... 219 191 */ 220 - ret = mtk_drm_crtc_create(drm, mtk_ddp_main, ARRAY_SIZE(mtk_ddp_main)); 192 + ret = mtk_drm_crtc_create(drm, private->data->main_path, 193 + private->data->main_len); 221 194 if (ret < 0) 222 195 goto err_component_unbind; 223 196 /* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */ 224 - ret = mtk_drm_crtc_create(drm, mtk_ddp_ext, ARRAY_SIZE(mtk_ddp_ext)); 197 + ret = mtk_drm_crtc_create(drm, private->data->ext_path, 198 + private->data->ext_len); 225 199 if (ret < 0) 226 200 goto err_component_unbind; 227 201 228 202 /* Use OVL device for all DMA memory allocations */ 229 - np = private->comp_node[mtk_ddp_main[0]] ?: 230 - private->comp_node[mtk_ddp_ext[0]]; 203 + np = private->comp_node[private->data->main_path[0]] ?: 204 + private->comp_node[private->data->ext_path[0]]; 231 205 pdev = of_find_device_by_node(np); 232 206 if (!pdev) { 233 207 ret = -ENODEV; ··· 358 328 }; 359 329 360 330 static const struct of_device_id mtk_ddp_comp_dt_ids[] = { 331 + { .compatible = "mediatek,mt2701-disp-ovl", .data = (void *)MTK_DISP_OVL }, 361 332 { .compatible = "mediatek,mt8173-disp-ovl", .data = (void *)MTK_DISP_OVL }, 333 + { .compatible = "mediatek,mt2701-disp-rdma", .data = (void *)MTK_DISP_RDMA }, 362 334 { .compatible = "mediatek,mt8173-disp-rdma", .data = (void *)MTK_DISP_RDMA }, 363 335 { .compatible = "mediatek,mt8173-disp-wdma", .data = (void *)MTK_DISP_WDMA }, 336 + { .compatible = "mediatek,mt2701-disp-color", .data = (void *)MTK_DISP_COLOR }, 364 337 { .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR }, 365 338 { .compatible = "mediatek,mt8173-disp-aal", .data = (void *)MTK_DISP_AAL}, 366 339 { .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, }, 367 340 { .compatible = "mediatek,mt8173-disp-ufoe", .data = (void *)MTK_DISP_UFOE }, 341 + { .compatible = "mediatek,mt2701-dsi", .data = (void *)MTK_DSI }, 368 342 { .compatible = "mediatek,mt8173-dsi", .data = (void *)MTK_DSI }, 369 343 { .compatible = "mediatek,mt8173-dpi", .data = (void *)MTK_DPI }, 344 + { .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX }, 370 345 { .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX }, 346 + { .compatible = "mediatek,mt2701-disp-pwm", .data = (void *)MTK_DISP_BLS }, 371 347 { .compatible = "mediatek,mt8173-disp-pwm", .data = (void *)MTK_DISP_PWM }, 372 348 { .compatible = "mediatek,mt8173-disp-od", .data = (void *)MTK_DISP_OD }, 373 349 { } ··· 395 359 396 360 mutex_init(&private->commit.lock); 397 361 INIT_WORK(&private->commit.work, mtk_atomic_work); 362 + private->data = of_device_get_match_data(dev); 398 363 399 364 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 400 365 private->config_regs = devm_ioremap_resource(dev, mem); ··· 547 510 mtk_drm_sys_resume); 548 511 549 512 static const struct of_device_id mtk_drm_of_ids[] = { 550 - { .compatible = "mediatek,mt8173-mmsys", }, 513 + { .compatible = "mediatek,mt2701-mmsys", 514 + .data = &mt2701_mmsys_driver_data}, 515 + { .compatible = "mediatek,mt8173-mmsys", 516 + .data = &mt8173_mmsys_driver_data}, 551 517 { } 552 518 }; 553 519
+9
drivers/gpu/drm/mediatek/mtk_drm_drv.h
··· 28 28 struct drm_property; 29 29 struct regmap; 30 30 31 + struct mtk_mmsys_driver_data { 32 + const enum mtk_ddp_comp_id *main_path; 33 + unsigned int main_len; 34 + const enum mtk_ddp_comp_id *ext_path; 35 + unsigned int ext_len; 36 + bool shadow_register; 37 + }; 38 + 31 39 struct mtk_drm_private { 32 40 struct drm_device *drm; 33 41 struct device *dma_dev; ··· 47 39 void __iomem *config_regs; 48 40 struct device_node *comp_node[DDP_COMPONENT_ID_MAX]; 49 41 struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX]; 42 + const struct mtk_mmsys_driver_data *data; 50 43 51 44 struct { 52 45 struct drm_atomic_state *state;
+535 -221
drivers/gpu/drm/mediatek/mtk_dsi.c
··· 18 18 #include <drm/drm_panel.h> 19 19 #include <linux/clk.h> 20 20 #include <linux/component.h> 21 + #include <linux/irq.h> 21 22 #include <linux/of.h> 22 23 #include <linux/of_platform.h> 23 24 #include <linux/of_graph.h> 24 25 #include <linux/phy/phy.h> 25 26 #include <linux/platform_device.h> 27 + #include <video/mipi_display.h> 26 28 #include <video/videomode.h> 27 29 28 30 #include "mtk_drm_ddp_comp.h" 29 31 30 - #define DSI_VIDEO_FIFO_DEPTH (1920 / 4) 31 - #define DSI_HOST_FIFO_DEPTH 64 32 - 33 32 #define DSI_START 0x00 33 + 34 + #define DSI_INTEN 0x08 35 + 36 + #define DSI_INTSTA 0x0c 37 + #define LPRX_RD_RDY_INT_FLAG BIT(0) 38 + #define CMD_DONE_INT_FLAG BIT(1) 39 + #define TE_RDY_INT_FLAG BIT(2) 40 + #define VM_DONE_INT_FLAG BIT(3) 41 + #define EXT_TE_RDY_INT_FLAG BIT(4) 42 + #define DSI_BUSY BIT(31) 34 43 35 44 #define DSI_CON_CTRL 0x10 36 45 #define DSI_RESET BIT(0) ··· 55 46 #define MIX_MODE BIT(17) 56 47 57 48 #define DSI_TXRX_CTRL 0x18 58 - #define VC_NUM (2 << 0) 49 + #define VC_NUM BIT(1) 59 50 #define LANE_NUM (0xf << 2) 60 51 #define DIS_EOT BIT(6) 61 52 #define NULL_EN BIT(7) ··· 81 72 #define DSI_HBP_WC 0x54 82 73 #define DSI_HFP_WC 0x58 83 74 75 + #define DSI_CMDQ_SIZE 0x60 76 + #define CMDQ_SIZE 0x3f 77 + 84 78 #define DSI_HSTX_CKL_WC 0x64 79 + 80 + #define DSI_RX_DATA0 0x74 81 + #define DSI_RX_DATA1 0x78 82 + #define DSI_RX_DATA2 0x7c 83 + #define DSI_RX_DATA3 0x80 84 + 85 + #define DSI_RACK 0x84 86 + #define RACK BIT(0) 85 87 86 88 #define DSI_PHY_LCCON 0x104 87 89 #define LC_HS_TX_EN BIT(0) ··· 126 106 #define CLK_HS_POST (0xff << 8) 127 107 #define CLK_HS_EXIT (0xff << 16) 128 108 109 + #define DSI_VM_CMD_CON 0x130 110 + #define VM_CMD_EN BIT(0) 111 + #define TS_VFP_EN BIT(5) 112 + 113 + #define DSI_CMDQ0 0x180 114 + #define CONFIG (0xff << 0) 115 + #define SHORT_PACKET 0 116 + #define LONG_PACKET 2 117 + #define BTA BIT(2) 118 + #define DATA_ID (0xff << 8) 119 + #define DATA_0 (0xff << 16) 120 + #define DATA_1 (0xff << 24) 121 + 129 122 #define T_LPX 5 130 123 #define T_HS_PREP 6 131 124 #define T_HS_TRAIL 8 ··· 146 113 #define T_HS_ZERO 10 147 114 148 115 #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) 116 + 117 + #define MTK_DSI_HOST_IS_READ(type) \ 118 + ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \ 119 + (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \ 120 + (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \ 121 + (type == MIPI_DSI_DCS_READ)) 149 122 150 123 struct phy; 151 124 ··· 179 140 struct videomode vm; 180 141 int refcount; 181 142 bool enabled; 143 + u32 irq_data; 144 + wait_queue_head_t irq_wait_queue; 182 145 }; 183 146 184 147 static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e) ··· 205 164 writel((temp & ~mask) | (data & mask), dsi->regs + offset); 206 165 } 207 166 208 - static void dsi_phy_timconfig(struct mtk_dsi *dsi) 167 + static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi) 209 168 { 210 169 u32 timcon0, timcon1, timcon2, timcon3; 211 170 u32 ui, cycle_time; ··· 237 196 mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0); 238 197 } 239 198 240 - static void mtk_dsi_reset(struct mtk_dsi *dsi) 199 + static void mtk_dsi_reset_engine(struct mtk_dsi *dsi) 241 200 { 242 201 mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET); 243 202 mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0); 203 + } 204 + 205 + static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi) 206 + { 207 + mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); 208 + mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); 209 + } 210 + 211 + static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi) 212 + { 213 + mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); 214 + mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN); 215 + mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0); 216 + } 217 + 218 + static void mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi) 219 + { 220 + mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0); 221 + mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); 222 + } 223 + 224 + static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi) 225 + { 226 + mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); 227 + mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN); 228 + mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0); 229 + } 230 + 231 + static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi) 232 + { 233 + u32 tmp_reg1; 234 + 235 + tmp_reg1 = readl(dsi->regs + DSI_PHY_LCCON); 236 + return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false; 237 + } 238 + 239 + static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter) 240 + { 241 + if (enter && !mtk_dsi_clk_hs_state(dsi)) 242 + mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN); 243 + else if (!enter && mtk_dsi_clk_hs_state(dsi)) 244 + mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); 245 + } 246 + 247 + static void mtk_dsi_set_mode(struct mtk_dsi *dsi) 248 + { 249 + u32 vid_mode = CMD_MODE; 250 + 251 + if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { 252 + if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) 253 + vid_mode = BURST_MODE; 254 + else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) 255 + vid_mode = SYNC_PULSE_MODE; 256 + else 257 + vid_mode = SYNC_EVENT_MODE; 258 + } 259 + 260 + writel(vid_mode, dsi->regs + DSI_MODE_CTRL); 261 + } 262 + 263 + static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi) 264 + { 265 + mtk_dsi_mask(dsi, DSI_VM_CMD_CON, VM_CMD_EN, VM_CMD_EN); 266 + mtk_dsi_mask(dsi, DSI_VM_CMD_CON, TS_VFP_EN, TS_VFP_EN); 267 + } 268 + 269 + static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi) 270 + { 271 + struct videomode *vm = &dsi->vm; 272 + u32 dsi_buf_bpp, ps_wc; 273 + u32 ps_bpp_mode; 274 + 275 + if (dsi->format == MIPI_DSI_FMT_RGB565) 276 + dsi_buf_bpp = 2; 277 + else 278 + dsi_buf_bpp = 3; 279 + 280 + ps_wc = vm->hactive * dsi_buf_bpp; 281 + ps_bpp_mode = ps_wc; 282 + 283 + switch (dsi->format) { 284 + case MIPI_DSI_FMT_RGB888: 285 + ps_bpp_mode |= PACKED_PS_24BIT_RGB888; 286 + break; 287 + case MIPI_DSI_FMT_RGB666: 288 + ps_bpp_mode |= PACKED_PS_18BIT_RGB666; 289 + break; 290 + case MIPI_DSI_FMT_RGB666_PACKED: 291 + ps_bpp_mode |= LOOSELY_PS_18BIT_RGB666; 292 + break; 293 + case MIPI_DSI_FMT_RGB565: 294 + ps_bpp_mode |= PACKED_PS_16BIT_RGB565; 295 + break; 296 + } 297 + 298 + writel(vm->vactive, dsi->regs + DSI_VACT_NL); 299 + writel(ps_bpp_mode, dsi->regs + DSI_PSCTRL); 300 + writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC); 301 + } 302 + 303 + static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi) 304 + { 305 + u32 tmp_reg; 306 + 307 + switch (dsi->lanes) { 308 + case 1: 309 + tmp_reg = 1 << 2; 310 + break; 311 + case 2: 312 + tmp_reg = 3 << 2; 313 + break; 314 + case 3: 315 + tmp_reg = 7 << 2; 316 + break; 317 + case 4: 318 + tmp_reg = 0xf << 2; 319 + break; 320 + default: 321 + tmp_reg = 0xf << 2; 322 + break; 323 + } 324 + 325 + tmp_reg |= (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6; 326 + tmp_reg |= (dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3; 327 + 328 + writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL); 329 + } 330 + 331 + static void mtk_dsi_ps_control(struct mtk_dsi *dsi) 332 + { 333 + u32 dsi_tmp_buf_bpp; 334 + u32 tmp_reg; 335 + 336 + switch (dsi->format) { 337 + case MIPI_DSI_FMT_RGB888: 338 + tmp_reg = PACKED_PS_24BIT_RGB888; 339 + dsi_tmp_buf_bpp = 3; 340 + break; 341 + case MIPI_DSI_FMT_RGB666: 342 + tmp_reg = LOOSELY_PS_18BIT_RGB666; 343 + dsi_tmp_buf_bpp = 3; 344 + break; 345 + case MIPI_DSI_FMT_RGB666_PACKED: 346 + tmp_reg = PACKED_PS_18BIT_RGB666; 347 + dsi_tmp_buf_bpp = 3; 348 + break; 349 + case MIPI_DSI_FMT_RGB565: 350 + tmp_reg = PACKED_PS_16BIT_RGB565; 351 + dsi_tmp_buf_bpp = 2; 352 + break; 353 + default: 354 + tmp_reg = PACKED_PS_24BIT_RGB888; 355 + dsi_tmp_buf_bpp = 3; 356 + break; 357 + } 358 + 359 + tmp_reg += dsi->vm.hactive * dsi_tmp_buf_bpp & DSI_PS_WC; 360 + writel(tmp_reg, dsi->regs + DSI_PSCTRL); 361 + } 362 + 363 + static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) 364 + { 365 + u32 horizontal_sync_active_byte; 366 + u32 horizontal_backporch_byte; 367 + u32 horizontal_frontporch_byte; 368 + u32 dsi_tmp_buf_bpp; 369 + 370 + struct videomode *vm = &dsi->vm; 371 + 372 + if (dsi->format == MIPI_DSI_FMT_RGB565) 373 + dsi_tmp_buf_bpp = 2; 374 + else 375 + dsi_tmp_buf_bpp = 3; 376 + 377 + writel(vm->vsync_len, dsi->regs + DSI_VSA_NL); 378 + writel(vm->vback_porch, dsi->regs + DSI_VBP_NL); 379 + writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL); 380 + writel(vm->vactive, dsi->regs + DSI_VACT_NL); 381 + 382 + horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10); 383 + 384 + if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) 385 + horizontal_backporch_byte = 386 + (vm->hback_porch * dsi_tmp_buf_bpp - 10); 387 + else 388 + horizontal_backporch_byte = ((vm->hback_porch + vm->hsync_len) * 389 + dsi_tmp_buf_bpp - 10); 390 + 391 + horizontal_frontporch_byte = (vm->hfront_porch * dsi_tmp_buf_bpp - 12); 392 + 393 + writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC); 394 + writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC); 395 + writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC); 396 + 397 + mtk_dsi_ps_control(dsi); 398 + } 399 + 400 + static void mtk_dsi_start(struct mtk_dsi *dsi) 401 + { 402 + writel(0, dsi->regs + DSI_START); 403 + writel(1, dsi->regs + DSI_START); 404 + } 405 + 406 + static void mtk_dsi_stop(struct mtk_dsi *dsi) 407 + { 408 + writel(0, dsi->regs + DSI_START); 409 + } 410 + 411 + static void mtk_dsi_set_cmd_mode(struct mtk_dsi *dsi) 412 + { 413 + writel(CMD_MODE, dsi->regs + DSI_MODE_CTRL); 414 + } 415 + 416 + static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi) 417 + { 418 + u32 inten = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; 419 + 420 + writel(inten, dsi->regs + DSI_INTEN); 421 + } 422 + 423 + static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit) 424 + { 425 + dsi->irq_data |= irq_bit; 426 + } 427 + 428 + static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit) 429 + { 430 + dsi->irq_data &= ~irq_bit; 431 + } 432 + 433 + static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag, 434 + unsigned int timeout) 435 + { 436 + s32 ret = 0; 437 + unsigned long jiffies = msecs_to_jiffies(timeout); 438 + 439 + ret = wait_event_interruptible_timeout(dsi->irq_wait_queue, 440 + dsi->irq_data & irq_flag, 441 + jiffies); 442 + if (ret == 0) { 443 + DRM_WARN("Wait DSI IRQ(0x%08x) Timeout\n", irq_flag); 444 + 445 + mtk_dsi_enable(dsi); 446 + mtk_dsi_reset_engine(dsi); 447 + } 448 + 449 + return ret; 450 + } 451 + 452 + static irqreturn_t mtk_dsi_irq(int irq, void *dev_id) 453 + { 454 + struct mtk_dsi *dsi = dev_id; 455 + u32 status, tmp; 456 + u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; 457 + 458 + status = readl(dsi->regs + DSI_INTSTA) & flag; 459 + 460 + if (status) { 461 + do { 462 + mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK); 463 + tmp = readl(dsi->regs + DSI_INTSTA); 464 + } while (tmp & DSI_BUSY); 465 + 466 + mtk_dsi_mask(dsi, DSI_INTSTA, status, 0); 467 + mtk_dsi_irq_data_set(dsi, status); 468 + wake_up_interruptible(&dsi->irq_wait_queue); 469 + } 470 + 471 + return IRQ_HANDLED; 472 + } 473 + 474 + static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t) 475 + { 476 + mtk_dsi_irq_data_clear(dsi, irq_flag); 477 + mtk_dsi_set_cmd_mode(dsi); 478 + 479 + if (!mtk_dsi_wait_for_irq_done(dsi, irq_flag, t)) { 480 + DRM_ERROR("failed to switch cmd mode\n"); 481 + return -ETIME; 482 + } else { 483 + return 0; 484 + } 244 485 } 245 486 246 487 static int mtk_dsi_poweron(struct mtk_dsi *dsi) ··· 590 267 } 591 268 592 269 mtk_dsi_enable(dsi); 593 - mtk_dsi_reset(dsi); 594 - dsi_phy_timconfig(dsi); 270 + mtk_dsi_reset_engine(dsi); 271 + mtk_dsi_phy_timconfig(dsi); 272 + 273 + mtk_dsi_rxtx_control(dsi); 274 + mtk_dsi_ps_control_vact(dsi); 275 + mtk_dsi_set_vm_cmd(dsi); 276 + mtk_dsi_config_vdo_timing(dsi); 277 + mtk_dsi_set_interrupt_enable(dsi); 278 + 279 + mtk_dsi_clk_ulp_mode_leave(dsi); 280 + mtk_dsi_lane0_ulp_mode_leave(dsi); 281 + mtk_dsi_clk_hs_mode(dsi, 0); 282 + 283 + if (dsi->panel) { 284 + if (drm_panel_prepare(dsi->panel)) { 285 + DRM_ERROR("failed to prepare the panel\n"); 286 + goto err_disable_digital_clk; 287 + } 288 + } 595 289 596 290 return 0; 597 - 291 + err_disable_digital_clk: 292 + clk_disable_unprepare(dsi->digital_clk); 598 293 err_disable_engine_clk: 599 294 clk_disable_unprepare(dsi->engine_clk); 600 295 err_phy_power_off: ··· 620 279 err_refcount: 621 280 dsi->refcount--; 622 281 return ret; 623 - } 624 - 625 - static void dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi) 626 - { 627 - mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); 628 - mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); 629 - } 630 - 631 - static void dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi) 632 - { 633 - mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); 634 - mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN); 635 - mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0); 636 - } 637 - 638 - static void dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi) 639 - { 640 - mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0); 641 - mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); 642 - } 643 - 644 - static void dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi) 645 - { 646 - mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); 647 - mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN); 648 - mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0); 649 - } 650 - 651 - static bool dsi_clk_hs_state(struct mtk_dsi *dsi) 652 - { 653 - u32 tmp_reg1; 654 - 655 - tmp_reg1 = readl(dsi->regs + DSI_PHY_LCCON); 656 - return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false; 657 - } 658 - 659 - static void dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter) 660 - { 661 - if (enter && !dsi_clk_hs_state(dsi)) 662 - mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN); 663 - else if (!enter && dsi_clk_hs_state(dsi)) 664 - mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); 665 - } 666 - 667 - static void dsi_set_mode(struct mtk_dsi *dsi) 668 - { 669 - u32 vid_mode = CMD_MODE; 670 - 671 - if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { 672 - vid_mode = SYNC_PULSE_MODE; 673 - 674 - if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) && 675 - !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) 676 - vid_mode = BURST_MODE; 677 - } 678 - 679 - writel(vid_mode, dsi->regs + DSI_MODE_CTRL); 680 - } 681 - 682 - static void dsi_ps_control_vact(struct mtk_dsi *dsi) 683 - { 684 - struct videomode *vm = &dsi->vm; 685 - u32 dsi_buf_bpp, ps_wc; 686 - u32 ps_bpp_mode; 687 - 688 - if (dsi->format == MIPI_DSI_FMT_RGB565) 689 - dsi_buf_bpp = 2; 690 - else 691 - dsi_buf_bpp = 3; 692 - 693 - ps_wc = vm->hactive * dsi_buf_bpp; 694 - ps_bpp_mode = ps_wc; 695 - 696 - switch (dsi->format) { 697 - case MIPI_DSI_FMT_RGB888: 698 - ps_bpp_mode |= PACKED_PS_24BIT_RGB888; 699 - break; 700 - case MIPI_DSI_FMT_RGB666: 701 - ps_bpp_mode |= PACKED_PS_18BIT_RGB666; 702 - break; 703 - case MIPI_DSI_FMT_RGB666_PACKED: 704 - ps_bpp_mode |= LOOSELY_PS_18BIT_RGB666; 705 - break; 706 - case MIPI_DSI_FMT_RGB565: 707 - ps_bpp_mode |= PACKED_PS_16BIT_RGB565; 708 - break; 709 - } 710 - 711 - writel(vm->vactive, dsi->regs + DSI_VACT_NL); 712 - writel(ps_bpp_mode, dsi->regs + DSI_PSCTRL); 713 - writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC); 714 - } 715 - 716 - static void dsi_rxtx_control(struct mtk_dsi *dsi) 717 - { 718 - u32 tmp_reg; 719 - 720 - switch (dsi->lanes) { 721 - case 1: 722 - tmp_reg = 1 << 2; 723 - break; 724 - case 2: 725 - tmp_reg = 3 << 2; 726 - break; 727 - case 3: 728 - tmp_reg = 7 << 2; 729 - break; 730 - case 4: 731 - tmp_reg = 0xf << 2; 732 - break; 733 - default: 734 - tmp_reg = 0xf << 2; 735 - break; 736 - } 737 - 738 - writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL); 739 - } 740 - 741 - static void dsi_ps_control(struct mtk_dsi *dsi) 742 - { 743 - unsigned int dsi_tmp_buf_bpp; 744 - u32 tmp_reg; 745 - 746 - switch (dsi->format) { 747 - case MIPI_DSI_FMT_RGB888: 748 - tmp_reg = PACKED_PS_24BIT_RGB888; 749 - dsi_tmp_buf_bpp = 3; 750 - break; 751 - case MIPI_DSI_FMT_RGB666: 752 - tmp_reg = LOOSELY_PS_18BIT_RGB666; 753 - dsi_tmp_buf_bpp = 3; 754 - break; 755 - case MIPI_DSI_FMT_RGB666_PACKED: 756 - tmp_reg = PACKED_PS_18BIT_RGB666; 757 - dsi_tmp_buf_bpp = 3; 758 - break; 759 - case MIPI_DSI_FMT_RGB565: 760 - tmp_reg = PACKED_PS_16BIT_RGB565; 761 - dsi_tmp_buf_bpp = 2; 762 - break; 763 - default: 764 - tmp_reg = PACKED_PS_24BIT_RGB888; 765 - dsi_tmp_buf_bpp = 3; 766 - break; 767 - } 768 - 769 - tmp_reg += dsi->vm.hactive * dsi_tmp_buf_bpp & DSI_PS_WC; 770 - writel(tmp_reg, dsi->regs + DSI_PSCTRL); 771 - } 772 - 773 - static void dsi_config_vdo_timing(struct mtk_dsi *dsi) 774 - { 775 - unsigned int horizontal_sync_active_byte; 776 - unsigned int horizontal_backporch_byte; 777 - unsigned int horizontal_frontporch_byte; 778 - unsigned int dsi_tmp_buf_bpp; 779 - 780 - struct videomode *vm = &dsi->vm; 781 - 782 - if (dsi->format == MIPI_DSI_FMT_RGB565) 783 - dsi_tmp_buf_bpp = 2; 784 - else 785 - dsi_tmp_buf_bpp = 3; 786 - 787 - writel(vm->vsync_len, dsi->regs + DSI_VSA_NL); 788 - writel(vm->vback_porch, dsi->regs + DSI_VBP_NL); 789 - writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL); 790 - writel(vm->vactive, dsi->regs + DSI_VACT_NL); 791 - 792 - horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10); 793 - 794 - if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) 795 - horizontal_backporch_byte = 796 - (vm->hback_porch * dsi_tmp_buf_bpp - 10); 797 - else 798 - horizontal_backporch_byte = ((vm->hback_porch + vm->hsync_len) * 799 - dsi_tmp_buf_bpp - 10); 800 - 801 - horizontal_frontporch_byte = (vm->hfront_porch * dsi_tmp_buf_bpp - 12); 802 - 803 - writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC); 804 - writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC); 805 - writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC); 806 - 807 - dsi_ps_control(dsi); 808 - } 809 - 810 - static void mtk_dsi_start(struct mtk_dsi *dsi) 811 - { 812 - writel(0, dsi->regs + DSI_START); 813 - writel(1, dsi->regs + DSI_START); 814 282 } 815 283 816 284 static void mtk_dsi_poweroff(struct mtk_dsi *dsi) ··· 630 480 if (--dsi->refcount != 0) 631 481 return; 632 482 633 - dsi_lane0_ulp_mode_enter(dsi); 634 - dsi_clk_ulp_mode_enter(dsi); 483 + if (!mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500)) { 484 + if (dsi->panel) { 485 + if (drm_panel_unprepare(dsi->panel)) { 486 + DRM_ERROR("failed to unprepare the panel\n"); 487 + return; 488 + } 489 + } 490 + } 491 + 492 + mtk_dsi_reset_engine(dsi); 493 + mtk_dsi_lane0_ulp_mode_enter(dsi); 494 + mtk_dsi_clk_ulp_mode_enter(dsi); 635 495 636 496 mtk_dsi_disable(dsi); 637 497 ··· 658 498 if (dsi->enabled) 659 499 return; 660 500 661 - if (dsi->panel) { 662 - if (drm_panel_prepare(dsi->panel)) { 663 - DRM_ERROR("failed to setup the panel\n"); 664 - return; 665 - } 666 - } 667 - 668 501 ret = mtk_dsi_poweron(dsi); 669 502 if (ret < 0) { 670 503 DRM_ERROR("failed to power on dsi\n"); 671 504 return; 672 505 } 673 506 674 - dsi_rxtx_control(dsi); 675 - 676 - dsi_clk_ulp_mode_leave(dsi); 677 - dsi_lane0_ulp_mode_leave(dsi); 678 - dsi_clk_hs_mode(dsi, 0); 679 - dsi_set_mode(dsi); 680 - 681 - dsi_ps_control_vact(dsi); 682 - dsi_config_vdo_timing(dsi); 683 - 684 - dsi_set_mode(dsi); 685 - dsi_clk_hs_mode(dsi, 1); 507 + mtk_dsi_set_mode(dsi); 508 + mtk_dsi_clk_hs_mode(dsi, 1); 686 509 687 510 mtk_dsi_start(dsi); 688 511 512 + if (dsi->panel) { 513 + if (drm_panel_enable(dsi->panel)) { 514 + DRM_ERROR("failed to enable the panel\n"); 515 + goto err_dsi_power_off; 516 + } 517 + } 518 + 689 519 dsi->enabled = true; 520 + 521 + return; 522 + err_dsi_power_off: 523 + mtk_dsi_stop(dsi); 524 + mtk_dsi_poweroff(dsi); 690 525 } 691 526 692 527 static void mtk_output_dsi_disable(struct mtk_dsi *dsi) ··· 696 541 } 697 542 } 698 543 544 + mtk_dsi_stop(dsi); 699 545 mtk_dsi_poweroff(dsi); 700 546 701 547 dsi->enabled = false; ··· 898 742 return 0; 899 743 } 900 744 745 + static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi) 746 + { 747 + u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */ 748 + 749 + while (timeout_ms--) { 750 + if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY)) 751 + break; 752 + 753 + usleep_range(2, 4); 754 + } 755 + 756 + if (timeout_ms == 0) { 757 + DRM_WARN("polling dsi wait not busy timeout!\n"); 758 + 759 + mtk_dsi_enable(dsi); 760 + mtk_dsi_reset_engine(dsi); 761 + } 762 + } 763 + 764 + static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data) 765 + { 766 + switch (type) { 767 + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: 768 + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: 769 + return 1; 770 + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: 771 + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: 772 + return 2; 773 + case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: 774 + case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: 775 + return read_data[1] + read_data[2] * 16; 776 + case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: 777 + DRM_INFO("type is 0x02, try again\n"); 778 + break; 779 + default: 780 + DRM_INFO("type(0x%x) cannot be non-recognite\n", type); 781 + break; 782 + } 783 + 784 + return 0; 785 + } 786 + 787 + static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg) 788 + { 789 + const char *tx_buf = msg->tx_buf; 790 + u8 config, cmdq_size, cmdq_off, type = msg->type; 791 + u32 reg_val, cmdq_mask, i; 792 + 793 + if (MTK_DSI_HOST_IS_READ(type)) 794 + config = BTA; 795 + else 796 + config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET; 797 + 798 + if (msg->tx_len > 2) { 799 + cmdq_size = 1 + (msg->tx_len + 3) / 4; 800 + cmdq_off = 4; 801 + cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1; 802 + reg_val = (msg->tx_len << 16) | (type << 8) | config; 803 + } else { 804 + cmdq_size = 1; 805 + cmdq_off = 2; 806 + cmdq_mask = CONFIG | DATA_ID; 807 + reg_val = (type << 8) | config; 808 + } 809 + 810 + for (i = 0; i < msg->tx_len; i++) 811 + writeb(tx_buf[i], dsi->regs + DSI_CMDQ0 + cmdq_off + i); 812 + 813 + mtk_dsi_mask(dsi, DSI_CMDQ0, cmdq_mask, reg_val); 814 + mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size); 815 + } 816 + 817 + static ssize_t mtk_dsi_host_send_cmd(struct mtk_dsi *dsi, 818 + const struct mipi_dsi_msg *msg, u8 flag) 819 + { 820 + mtk_dsi_wait_for_idle(dsi); 821 + mtk_dsi_irq_data_clear(dsi, flag); 822 + mtk_dsi_cmdq(dsi, msg); 823 + mtk_dsi_start(dsi); 824 + 825 + if (!mtk_dsi_wait_for_irq_done(dsi, flag, 2000)) 826 + return -ETIME; 827 + else 828 + return 0; 829 + } 830 + 831 + static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host, 832 + const struct mipi_dsi_msg *msg) 833 + { 834 + struct mtk_dsi *dsi = host_to_dsi(host); 835 + u32 recv_cnt, i; 836 + u8 read_data[16]; 837 + void *src_addr; 838 + u8 irq_flag = CMD_DONE_INT_FLAG; 839 + 840 + if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) { 841 + DRM_ERROR("dsi engine is not command mode\n"); 842 + return -EINVAL; 843 + } 844 + 845 + if (MTK_DSI_HOST_IS_READ(msg->type)) 846 + irq_flag |= LPRX_RD_RDY_INT_FLAG; 847 + 848 + if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0) 849 + return -ETIME; 850 + 851 + if (!MTK_DSI_HOST_IS_READ(msg->type)) 852 + return 0; 853 + 854 + if (!msg->rx_buf) { 855 + DRM_ERROR("dsi receive buffer size may be NULL\n"); 856 + return -EINVAL; 857 + } 858 + 859 + for (i = 0; i < 16; i++) 860 + *(read_data + i) = readb(dsi->regs + DSI_RX_DATA0 + i); 861 + 862 + recv_cnt = mtk_dsi_recv_cnt(read_data[0], read_data); 863 + 864 + if (recv_cnt > 2) 865 + src_addr = &read_data[4]; 866 + else 867 + src_addr = &read_data[1]; 868 + 869 + if (recv_cnt > 10) 870 + recv_cnt = 10; 871 + 872 + if (recv_cnt > msg->rx_len) 873 + recv_cnt = msg->rx_len; 874 + 875 + if (recv_cnt) 876 + memcpy(msg->rx_buf, src_addr, recv_cnt); 877 + 878 + DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n", 879 + recv_cnt, *((u8 *)(msg->tx_buf))); 880 + 881 + return recv_cnt; 882 + } 883 + 901 884 static const struct mipi_dsi_host_ops mtk_dsi_ops = { 902 885 .attach = mtk_dsi_host_attach, 903 886 .detach = mtk_dsi_host_detach, 887 + .transfer = mtk_dsi_host_transfer, 904 888 }; 905 889 906 890 static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) ··· 1099 803 struct device *dev = &pdev->dev; 1100 804 struct device_node *remote_node, *endpoint; 1101 805 struct resource *regs; 806 + int irq_num; 1102 807 int comp_id; 1103 808 int ret; 1104 809 ··· 1176 879 return ret; 1177 880 } 1178 881 882 + irq_num = platform_get_irq(pdev, 0); 883 + if (irq_num < 0) { 884 + dev_err(&pdev->dev, "failed to request dsi irq resource\n"); 885 + return -EPROBE_DEFER; 886 + } 887 + 888 + irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_LOW); 889 + ret = devm_request_irq(&pdev->dev, irq_num, mtk_dsi_irq, 890 + IRQF_TRIGGER_LOW, dev_name(&pdev->dev), dsi); 891 + if (ret) { 892 + dev_err(&pdev->dev, "failed to request mediatek dsi irq\n"); 893 + return -EPROBE_DEFER; 894 + } 895 + 896 + init_waitqueue_head(&dsi->irq_wait_queue); 897 + 1179 898 platform_set_drvdata(pdev, dsi); 1180 899 1181 900 return component_add(&pdev->dev, &mtk_dsi_component_ops); ··· 1208 895 } 1209 896 1210 897 static const struct of_device_id mtk_dsi_of_match[] = { 898 + { .compatible = "mediatek,mt2701-dsi" }, 1211 899 { .compatible = "mediatek,mt8173-dsi" }, 1212 900 { }, 1213 901 };
+33 -5
drivers/gpu/drm/mediatek/mtk_mipi_tx.c
··· 16 16 #include <linux/delay.h> 17 17 #include <linux/io.h> 18 18 #include <linux/module.h> 19 + #include <linux/of_device.h> 19 20 #include <linux/platform_device.h> 20 21 #include <linux/phy/phy.h> 21 22 ··· 88 87 89 88 #define MIPITX_DSI_PLL_CON2 0x58 90 89 90 + #define MIPITX_DSI_PLL_TOP 0x64 91 + #define RG_DSI_MPPLL_PRESERVE (0xff << 8) 92 + 91 93 #define MIPITX_DSI_PLL_PWR 0x68 92 94 #define RG_DSI_MPPLL_SDM_PWR_ON BIT(0) 93 95 #define RG_DSI_MPPLL_SDM_ISO_EN BIT(1) ··· 127 123 #define SW_LNT2_HSTX_PRE_OE BIT(24) 128 124 #define SW_LNT2_HSTX_OE BIT(25) 129 125 126 + struct mtk_mipitx_data { 127 + const u32 mppll_preserve; 128 + }; 129 + 130 130 struct mtk_mipi_tx { 131 131 struct device *dev; 132 132 void __iomem *regs; 133 - unsigned int data_rate; 133 + u32 data_rate; 134 + const struct mtk_mipitx_data *driver_data; 134 135 struct clk_hw pll_hw; 135 136 struct clk *pll; 136 137 }; ··· 172 163 static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw) 173 164 { 174 165 struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); 175 - unsigned int txdiv, txdiv0, txdiv1; 166 + u8 txdiv, txdiv0, txdiv1; 176 167 u64 pcw; 177 168 178 169 dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate); ··· 252 243 mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1, 253 244 RG_DSI_MPPLL_SDM_SSC_EN); 254 245 246 + mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP, 247 + RG_DSI_MPPLL_PRESERVE, 248 + mipi_tx->driver_data->mppll_preserve); 249 + 255 250 return 0; 256 251 } 257 252 ··· 267 254 268 255 mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, 269 256 RG_DSI_MPPLL_PLL_EN); 257 + 258 + mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP, 259 + RG_DSI_MPPLL_PRESERVE, 0); 270 260 271 261 mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR, 272 262 RG_DSI_MPPLL_SDM_ISO_EN | ··· 326 310 static int mtk_mipi_tx_power_on_signal(struct phy *phy) 327 311 { 328 312 struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); 329 - unsigned int reg; 313 + u32 reg; 330 314 331 315 for (reg = MIPITX_DSI_CLOCK_LANE; 332 316 reg <= MIPITX_DSI_DATA_LANE3; reg += 4) ··· 357 341 static void mtk_mipi_tx_power_off_signal(struct phy *phy) 358 342 { 359 343 struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); 360 - unsigned int reg; 344 + u32 reg; 361 345 362 346 mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON, 363 347 RG_DSI_PAD_TIE_LOW_EN); ··· 407 391 if (!mipi_tx) 408 392 return -ENOMEM; 409 393 394 + mipi_tx->driver_data = of_device_get_match_data(dev); 410 395 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 411 396 mipi_tx->regs = devm_ioremap_resource(dev, mem); 412 397 if (IS_ERR(mipi_tx->regs)) { ··· 465 448 return 0; 466 449 } 467 450 451 + static const struct mtk_mipitx_data mt2701_mipitx_data = { 452 + .mppll_preserve = (3 << 8) 453 + }; 454 + 455 + static const struct mtk_mipitx_data mt8173_mipitx_data = { 456 + .mppll_preserve = (0 << 8) 457 + }; 458 + 468 459 static const struct of_device_id mtk_mipi_tx_match[] = { 469 - { .compatible = "mediatek,mt8173-mipi-tx", }, 460 + { .compatible = "mediatek,mt2701-mipi-tx", 461 + .data = &mt2701_mipitx_data }, 462 + { .compatible = "mediatek,mt8173-mipi-tx", 463 + .data = &mt8173_mipitx_data }, 470 464 {}, 471 465 }; 472 466