linux/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015 MediaTek Inc.
   4 */
   5
   6#include <linux/clk.h>
   7#include <linux/iopoll.h>
   8#include <linux/module.h>
   9#include <linux/of_device.h>
  10#include <linux/platform_device.h>
  11#include <linux/regmap.h>
  12
  13#include "mtk_drm_ddp.h"
  14#include "mtk_drm_ddp_comp.h"
  15
  16#define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN       0x040
  17#define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN       0x044
  18#define DISP_REG_CONFIG_DISP_OD_MOUT_EN         0x048
  19#define DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN      0x04c
  20#define DISP_REG_CONFIG_DISP_UFOE_MOUT_EN       0x050
  21#define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN      0x084
  22#define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN      0x088
  23#define DISP_REG_CONFIG_DSIE_SEL_IN             0x0a4
  24#define DISP_REG_CONFIG_DSIO_SEL_IN             0x0a8
  25#define DISP_REG_CONFIG_DPI_SEL_IN              0x0ac
  26#define DISP_REG_CONFIG_DISP_RDMA2_SOUT         0x0b8
  27#define DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN      0x0c4
  28#define DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN      0x0c8
  29#define DISP_REG_CONFIG_MMSYS_CG_CON0           0x100
  30
  31#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN        0x030
  32#define DISP_REG_CONFIG_OUT_SEL                 0x04c
  33#define DISP_REG_CONFIG_DSI_SEL                 0x050
  34#define DISP_REG_CONFIG_DPI_SEL                 0x064
  35
  36#define DISP_REG_MUTEX_EN(n)    (0x20 + 0x20 * (n))
  37#define DISP_REG_MUTEX(n)       (0x24 + 0x20 * (n))
  38#define DISP_REG_MUTEX_RST(n)   (0x28 + 0x20 * (n))
  39#define DISP_REG_MUTEX_MOD(n)   (0x2c + 0x20 * (n))
  40#define DISP_REG_MUTEX_SOF(n)   (0x30 + 0x20 * (n))
  41#define DISP_REG_MUTEX_MOD2(n)  (0x34 + 0x20 * (n))
  42
  43#define INT_MUTEX                               BIT(1)
  44
  45#define MT8173_MUTEX_MOD_DISP_OVL0              11
  46#define MT8173_MUTEX_MOD_DISP_OVL1              12
  47#define MT8173_MUTEX_MOD_DISP_RDMA0             13
  48#define MT8173_MUTEX_MOD_DISP_RDMA1             14
  49#define MT8173_MUTEX_MOD_DISP_RDMA2             15
  50#define MT8173_MUTEX_MOD_DISP_WDMA0             16
  51#define MT8173_MUTEX_MOD_DISP_WDMA1             17
  52#define MT8173_MUTEX_MOD_DISP_COLOR0            18
  53#define MT8173_MUTEX_MOD_DISP_COLOR1            19
  54#define MT8173_MUTEX_MOD_DISP_AAL               20
  55#define MT8173_MUTEX_MOD_DISP_GAMMA             21
  56#define MT8173_MUTEX_MOD_DISP_UFOE              22
  57#define MT8173_MUTEX_MOD_DISP_PWM0              23
  58#define MT8173_MUTEX_MOD_DISP_PWM1              24
  59#define MT8173_MUTEX_MOD_DISP_OD                25
  60
  61#define MT2712_MUTEX_MOD_DISP_PWM2              10
  62#define MT2712_MUTEX_MOD_DISP_OVL0              11
  63#define MT2712_MUTEX_MOD_DISP_OVL1              12
  64#define MT2712_MUTEX_MOD_DISP_RDMA0             13
  65#define MT2712_MUTEX_MOD_DISP_RDMA1             14
  66#define MT2712_MUTEX_MOD_DISP_RDMA2             15
  67#define MT2712_MUTEX_MOD_DISP_WDMA0             16
  68#define MT2712_MUTEX_MOD_DISP_WDMA1             17
  69#define MT2712_MUTEX_MOD_DISP_COLOR0            18
  70#define MT2712_MUTEX_MOD_DISP_COLOR1            19
  71#define MT2712_MUTEX_MOD_DISP_AAL0              20
  72#define MT2712_MUTEX_MOD_DISP_UFOE              22
  73#define MT2712_MUTEX_MOD_DISP_PWM0              23
  74#define MT2712_MUTEX_MOD_DISP_PWM1              24
  75#define MT2712_MUTEX_MOD_DISP_OD0               25
  76#define MT2712_MUTEX_MOD2_DISP_AAL1             33
  77#define MT2712_MUTEX_MOD2_DISP_OD1              34
  78
  79#define MT2701_MUTEX_MOD_DISP_OVL               3
  80#define MT2701_MUTEX_MOD_DISP_WDMA              6
  81#define MT2701_MUTEX_MOD_DISP_COLOR             7
  82#define MT2701_MUTEX_MOD_DISP_BLS               9
  83#define MT2701_MUTEX_MOD_DISP_RDMA0             10
  84#define MT2701_MUTEX_MOD_DISP_RDMA1             12
  85
  86#define MUTEX_SOF_SINGLE_MODE           0
  87#define MUTEX_SOF_DSI0                  1
  88#define MUTEX_SOF_DSI1                  2
  89#define MUTEX_SOF_DPI0                  3
  90#define MUTEX_SOF_DPI1                  4
  91#define MUTEX_SOF_DSI2                  5
  92#define MUTEX_SOF_DSI3                  6
  93
  94#define OVL0_MOUT_EN_COLOR0             0x1
  95#define OD_MOUT_EN_RDMA0                0x1
  96#define OD1_MOUT_EN_RDMA1               BIT(16)
  97#define UFOE_MOUT_EN_DSI0               0x1
  98#define COLOR0_SEL_IN_OVL0              0x1
  99#define OVL1_MOUT_EN_COLOR1             0x1
 100#define GAMMA_MOUT_EN_RDMA1             0x1
 101#define RDMA0_SOUT_DPI0                 0x2
 102#define RDMA0_SOUT_DPI1                 0x3
 103#define RDMA0_SOUT_DSI1                 0x1
 104#define RDMA0_SOUT_DSI2                 0x4
 105#define RDMA0_SOUT_DSI3                 0x5
 106#define RDMA1_SOUT_DPI0                 0x2
 107#define RDMA1_SOUT_DPI1                 0x3
 108#define RDMA1_SOUT_DSI1                 0x1
 109#define RDMA1_SOUT_DSI2                 0x4
 110#define RDMA1_SOUT_DSI3                 0x5
 111#define RDMA2_SOUT_DPI0                 0x2
 112#define RDMA2_SOUT_DPI1                 0x3
 113#define RDMA2_SOUT_DSI1                 0x1
 114#define RDMA2_SOUT_DSI2                 0x4
 115#define RDMA2_SOUT_DSI3                 0x5
 116#define DPI0_SEL_IN_RDMA1               0x1
 117#define DPI0_SEL_IN_RDMA2               0x3
 118#define DPI1_SEL_IN_RDMA1               (0x1 << 8)
 119#define DPI1_SEL_IN_RDMA2               (0x3 << 8)
 120#define DSI0_SEL_IN_RDMA1               0x1
 121#define DSI0_SEL_IN_RDMA2               0x4
 122#define DSI1_SEL_IN_RDMA1               0x1
 123#define DSI1_SEL_IN_RDMA2               0x4
 124#define DSI2_SEL_IN_RDMA1               (0x1 << 16)
 125#define DSI2_SEL_IN_RDMA2               (0x4 << 16)
 126#define DSI3_SEL_IN_RDMA1               (0x1 << 16)
 127#define DSI3_SEL_IN_RDMA2               (0x4 << 16)
 128#define COLOR1_SEL_IN_OVL1              0x1
 129
 130#define OVL_MOUT_EN_RDMA                0x1
 131#define BLS_TO_DSI_RDMA1_TO_DPI1        0x8
 132#define BLS_TO_DPI_RDMA1_TO_DSI         0x2
 133#define DSI_SEL_IN_BLS                  0x0
 134#define DPI_SEL_IN_BLS                  0x0
 135#define DSI_SEL_IN_RDMA                 0x1
 136
 137struct mtk_disp_mutex {
 138        int id;
 139        bool claimed;
 140};
 141
 142struct mtk_ddp {
 143        struct device                   *dev;
 144        struct clk                      *clk;
 145        void __iomem                    *regs;
 146        struct mtk_disp_mutex           mutex[10];
 147        const unsigned int              *mutex_mod;
 148};
 149
 150static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
 151        [DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS,
 152        [DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR,
 153        [DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL,
 154        [DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0,
 155        [DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1,
 156        [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
 157};
 158
 159static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
 160        [DDP_COMPONENT_AAL0] = MT2712_MUTEX_MOD_DISP_AAL0,
 161        [DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1,
 162        [DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0,
 163        [DDP_COMPONENT_COLOR1] = MT2712_MUTEX_MOD_DISP_COLOR1,
 164        [DDP_COMPONENT_OD0] = MT2712_MUTEX_MOD_DISP_OD0,
 165        [DDP_COMPONENT_OD1] = MT2712_MUTEX_MOD2_DISP_OD1,
 166        [DDP_COMPONENT_OVL0] = MT2712_MUTEX_MOD_DISP_OVL0,
 167        [DDP_COMPONENT_OVL1] = MT2712_MUTEX_MOD_DISP_OVL1,
 168        [DDP_COMPONENT_PWM0] = MT2712_MUTEX_MOD_DISP_PWM0,
 169        [DDP_COMPONENT_PWM1] = MT2712_MUTEX_MOD_DISP_PWM1,
 170        [DDP_COMPONENT_PWM2] = MT2712_MUTEX_MOD_DISP_PWM2,
 171        [DDP_COMPONENT_RDMA0] = MT2712_MUTEX_MOD_DISP_RDMA0,
 172        [DDP_COMPONENT_RDMA1] = MT2712_MUTEX_MOD_DISP_RDMA1,
 173        [DDP_COMPONENT_RDMA2] = MT2712_MUTEX_MOD_DISP_RDMA2,
 174        [DDP_COMPONENT_UFOE] = MT2712_MUTEX_MOD_DISP_UFOE,
 175        [DDP_COMPONENT_WDMA0] = MT2712_MUTEX_MOD_DISP_WDMA0,
 176        [DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1,
 177};
 178
 179static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
 180        [DDP_COMPONENT_AAL0] = MT8173_MUTEX_MOD_DISP_AAL,
 181        [DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
 182        [DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
 183        [DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA,
 184        [DDP_COMPONENT_OD0] = MT8173_MUTEX_MOD_DISP_OD,
 185        [DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0,
 186        [DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1,
 187        [DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0,
 188        [DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1,
 189        [DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0,
 190        [DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1,
 191        [DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2,
 192        [DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE,
 193        [DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0,
 194        [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
 195};
 196
 197static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
 198                                    enum mtk_ddp_comp_id next,
 199                                    unsigned int *addr)
 200{
 201        unsigned int value;
 202
 203        if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
 204                *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
 205                value = OVL0_MOUT_EN_COLOR0;
 206        } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) {
 207                *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN;
 208                value = OVL_MOUT_EN_RDMA;
 209        } else if (cur == DDP_COMPONENT_OD0 && next == DDP_COMPONENT_RDMA0) {
 210                *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
 211                value = OD_MOUT_EN_RDMA0;
 212        } else if (cur == DDP_COMPONENT_UFOE && next == DDP_COMPONENT_DSI0) {
 213                *addr = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN;
 214                value = UFOE_MOUT_EN_DSI0;
 215        } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
 216                *addr = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN;
 217                value = OVL1_MOUT_EN_COLOR1;
 218        } else if (cur == DDP_COMPONENT_GAMMA && next == DDP_COMPONENT_RDMA1) {
 219                *addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN;
 220                value = GAMMA_MOUT_EN_RDMA1;
 221        } else if (cur == DDP_COMPONENT_OD1 && next == DDP_COMPONENT_RDMA1) {
 222                *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
 223                value = OD1_MOUT_EN_RDMA1;
 224        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI0) {
 225                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 226                value = RDMA0_SOUT_DPI0;
 227        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI1) {
 228                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 229                value = RDMA0_SOUT_DPI1;
 230        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI1) {
 231                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 232                value = RDMA0_SOUT_DSI1;
 233        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI2) {
 234                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 235                value = RDMA0_SOUT_DSI2;
 236        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI3) {
 237                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 238                value = RDMA0_SOUT_DSI3;
 239        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) {
 240                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 241                value = RDMA1_SOUT_DSI1;
 242        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) {
 243                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 244                value = RDMA1_SOUT_DSI2;
 245        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) {
 246                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 247                value = RDMA1_SOUT_DSI3;
 248        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
 249                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 250                value = RDMA1_SOUT_DPI0;
 251        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) {
 252                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 253                value = RDMA1_SOUT_DPI1;
 254        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) {
 255                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 256                value = RDMA2_SOUT_DPI0;
 257        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) {
 258                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 259                value = RDMA2_SOUT_DPI1;
 260        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) {
 261                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 262                value = RDMA2_SOUT_DSI1;
 263        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) {
 264                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 265                value = RDMA2_SOUT_DSI2;
 266        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) {
 267                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 268                value = RDMA2_SOUT_DSI3;
 269        } else {
 270                value = 0;
 271        }
 272
 273        return value;
 274}
 275
 276static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
 277                                   enum mtk_ddp_comp_id next,
 278                                   unsigned int *addr)
 279{
 280        unsigned int value;
 281
 282        if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
 283                *addr = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN;
 284                value = COLOR0_SEL_IN_OVL0;
 285        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
 286                *addr = DISP_REG_CONFIG_DPI_SEL_IN;
 287                value = DPI0_SEL_IN_RDMA1;
 288        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) {
 289                *addr = DISP_REG_CONFIG_DPI_SEL_IN;
 290                value = DPI1_SEL_IN_RDMA1;
 291        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI0) {
 292                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 293                value = DSI0_SEL_IN_RDMA1;
 294        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) {
 295                *addr = DISP_REG_CONFIG_DSIO_SEL_IN;
 296                value = DSI1_SEL_IN_RDMA1;
 297        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) {
 298                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 299                value = DSI2_SEL_IN_RDMA1;
 300        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) {
 301                *addr = DISP_REG_CONFIG_DSIO_SEL_IN;
 302                value = DSI3_SEL_IN_RDMA1;
 303        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) {
 304                *addr = DISP_REG_CONFIG_DPI_SEL_IN;
 305                value = DPI0_SEL_IN_RDMA2;
 306        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) {
 307                *addr = DISP_REG_CONFIG_DPI_SEL_IN;
 308                value = DPI1_SEL_IN_RDMA2;
 309        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI0) {
 310                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 311                value = DSI0_SEL_IN_RDMA2;
 312        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) {
 313                *addr = DISP_REG_CONFIG_DSIO_SEL_IN;
 314                value = DSI1_SEL_IN_RDMA2;
 315        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) {
 316                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 317                value = DSI2_SEL_IN_RDMA2;
 318        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) {
 319                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 320                value = DSI3_SEL_IN_RDMA2;
 321        } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
 322                *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
 323                value = COLOR1_SEL_IN_OVL1;
 324        } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
 325                *addr = DISP_REG_CONFIG_DSI_SEL;
 326                value = DSI_SEL_IN_BLS;
 327        } else {
 328                value = 0;
 329        }
 330
 331        return value;
 332}
 333
 334static void mtk_ddp_sout_sel(void __iomem *config_regs,
 335                             enum mtk_ddp_comp_id cur,
 336                             enum mtk_ddp_comp_id next)
 337{
 338        if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
 339                writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
 340                               config_regs + DISP_REG_CONFIG_OUT_SEL);
 341        } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DPI0) {
 342                writel_relaxed(BLS_TO_DPI_RDMA1_TO_DSI,
 343                               config_regs + DISP_REG_CONFIG_OUT_SEL);
 344                writel_relaxed(DSI_SEL_IN_RDMA,
 345                               config_regs + DISP_REG_CONFIG_DSI_SEL);
 346                writel_relaxed(DPI_SEL_IN_BLS,
 347                               config_regs + DISP_REG_CONFIG_DPI_SEL);
 348        }
 349}
 350
 351void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
 352                              enum mtk_ddp_comp_id cur,
 353                              enum mtk_ddp_comp_id next)
 354{
 355        unsigned int addr, value, reg;
 356
 357        value = mtk_ddp_mout_en(cur, next, &addr);
 358        if (value) {
 359                reg = readl_relaxed(config_regs + addr) | value;
 360                writel_relaxed(reg, config_regs + addr);
 361        }
 362
 363        mtk_ddp_sout_sel(config_regs, cur, next);
 364
 365        value = mtk_ddp_sel_in(cur, next, &addr);
 366        if (value) {
 367                reg = readl_relaxed(config_regs + addr) | value;
 368                writel_relaxed(reg, config_regs + addr);
 369        }
 370}
 371
 372void mtk_ddp_remove_comp_from_path(void __iomem *config_regs,
 373                                   enum mtk_ddp_comp_id cur,
 374                                   enum mtk_ddp_comp_id next)
 375{
 376        unsigned int addr, value, reg;
 377
 378        value = mtk_ddp_mout_en(cur, next, &addr);
 379        if (value) {
 380                reg = readl_relaxed(config_regs + addr) & ~value;
 381                writel_relaxed(reg, config_regs + addr);
 382        }
 383
 384        value = mtk_ddp_sel_in(cur, next, &addr);
 385        if (value) {
 386                reg = readl_relaxed(config_regs + addr) & ~value;
 387                writel_relaxed(reg, config_regs + addr);
 388        }
 389}
 390
 391struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id)
 392{
 393        struct mtk_ddp *ddp = dev_get_drvdata(dev);
 394
 395        if (id >= 10)
 396                return ERR_PTR(-EINVAL);
 397        if (ddp->mutex[id].claimed)
 398                return ERR_PTR(-EBUSY);
 399
 400        ddp->mutex[id].claimed = true;
 401
 402        return &ddp->mutex[id];
 403}
 404
 405void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex)
 406{
 407        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 408                                           mutex[mutex->id]);
 409
 410        WARN_ON(&ddp->mutex[mutex->id] != mutex);
 411
 412        mutex->claimed = false;
 413}
 414
 415int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex)
 416{
 417        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 418                                           mutex[mutex->id]);
 419        return clk_prepare_enable(ddp->clk);
 420}
 421
 422void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex)
 423{
 424        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 425                                           mutex[mutex->id]);
 426        clk_disable_unprepare(ddp->clk);
 427}
 428
 429void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
 430                             enum mtk_ddp_comp_id id)
 431{
 432        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 433                                           mutex[mutex->id]);
 434        unsigned int reg;
 435        unsigned int offset;
 436
 437        WARN_ON(&ddp->mutex[mutex->id] != mutex);
 438
 439        switch (id) {
 440        case DDP_COMPONENT_DSI0:
 441                reg = MUTEX_SOF_DSI0;
 442                break;
 443        case DDP_COMPONENT_DSI1:
 444                reg = MUTEX_SOF_DSI0;
 445                break;
 446        case DDP_COMPONENT_DSI2:
 447                reg = MUTEX_SOF_DSI2;
 448                break;
 449        case DDP_COMPONENT_DSI3:
 450                reg = MUTEX_SOF_DSI3;
 451                break;
 452        case DDP_COMPONENT_DPI0:
 453                reg = MUTEX_SOF_DPI0;
 454                break;
 455        case DDP_COMPONENT_DPI1:
 456                reg = MUTEX_SOF_DPI1;
 457                break;
 458        default:
 459                if (ddp->mutex_mod[id] < 32) {
 460                        offset = DISP_REG_MUTEX_MOD(mutex->id);
 461                        reg = readl_relaxed(ddp->regs + offset);
 462                        reg |= 1 << ddp->mutex_mod[id];
 463                        writel_relaxed(reg, ddp->regs + offset);
 464                } else {
 465                        offset = DISP_REG_MUTEX_MOD2(mutex->id);
 466                        reg = readl_relaxed(ddp->regs + offset);
 467                        reg |= 1 << (ddp->mutex_mod[id] - 32);
 468                        writel_relaxed(reg, ddp->regs + offset);
 469                }
 470                return;
 471        }
 472
 473        writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
 474}
 475
 476void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
 477                                enum mtk_ddp_comp_id id)
 478{
 479        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 480                                           mutex[mutex->id]);
 481        unsigned int reg;
 482        unsigned int offset;
 483
 484        WARN_ON(&ddp->mutex[mutex->id] != mutex);
 485
 486        switch (id) {
 487        case DDP_COMPONENT_DSI0:
 488        case DDP_COMPONENT_DSI1:
 489        case DDP_COMPONENT_DSI2:
 490        case DDP_COMPONENT_DSI3:
 491        case DDP_COMPONENT_DPI0:
 492        case DDP_COMPONENT_DPI1:
 493                writel_relaxed(MUTEX_SOF_SINGLE_MODE,
 494                               ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
 495                break;
 496        default:
 497                if (ddp->mutex_mod[id] < 32) {
 498                        offset = DISP_REG_MUTEX_MOD(mutex->id);
 499                        reg = readl_relaxed(ddp->regs + offset);
 500                        reg &= ~(1 << ddp->mutex_mod[id]);
 501                        writel_relaxed(reg, ddp->regs + offset);
 502                } else {
 503                        offset = DISP_REG_MUTEX_MOD2(mutex->id);
 504                        reg = readl_relaxed(ddp->regs + offset);
 505                        reg &= ~(1 << (ddp->mutex_mod[id] - 32));
 506                        writel_relaxed(reg, ddp->regs + offset);
 507                }
 508                break;
 509        }
 510}
 511
 512void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex)
 513{
 514        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 515                                           mutex[mutex->id]);
 516
 517        WARN_ON(&ddp->mutex[mutex->id] != mutex);
 518
 519        writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
 520}
 521
 522void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
 523{
 524        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 525                                           mutex[mutex->id]);
 526
 527        WARN_ON(&ddp->mutex[mutex->id] != mutex);
 528
 529        writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
 530}
 531
 532void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex)
 533{
 534        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 535                                           mutex[mutex->id]);
 536        u32 tmp;
 537
 538        writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
 539        writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id));
 540        if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id),
 541                                      tmp, tmp & INT_MUTEX, 1, 10000))
 542                pr_err("could not acquire mutex %d\n", mutex->id);
 543}
 544
 545void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex)
 546{
 547        struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
 548                                           mutex[mutex->id]);
 549
 550        writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id));
 551}
 552
 553static int mtk_ddp_probe(struct platform_device *pdev)
 554{
 555        struct device *dev = &pdev->dev;
 556        struct mtk_ddp *ddp;
 557        struct resource *regs;
 558        int i;
 559
 560        ddp = devm_kzalloc(dev, sizeof(*ddp), GFP_KERNEL);
 561        if (!ddp)
 562                return -ENOMEM;
 563
 564        for (i = 0; i < 10; i++)
 565                ddp->mutex[i].id = i;
 566
 567        ddp->clk = devm_clk_get(dev, NULL);
 568        if (IS_ERR(ddp->clk)) {
 569                dev_err(dev, "Failed to get clock\n");
 570                return PTR_ERR(ddp->clk);
 571        }
 572
 573        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 574        ddp->regs = devm_ioremap_resource(dev, regs);
 575        if (IS_ERR(ddp->regs)) {
 576                dev_err(dev, "Failed to map mutex registers\n");
 577                return PTR_ERR(ddp->regs);
 578        }
 579
 580        ddp->mutex_mod = of_device_get_match_data(dev);
 581
 582        platform_set_drvdata(pdev, ddp);
 583
 584        return 0;
 585}
 586
 587static int mtk_ddp_remove(struct platform_device *pdev)
 588{
 589        return 0;
 590}
 591
 592static const struct of_device_id ddp_driver_dt_match[] = {
 593        { .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod},
 594        { .compatible = "mediatek,mt2712-disp-mutex", .data = mt2712_mutex_mod},
 595        { .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
 596        {},
 597};
 598MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
 599
 600struct platform_driver mtk_ddp_driver = {
 601        .probe          = mtk_ddp_probe,
 602        .remove         = mtk_ddp_remove,
 603        .driver         = {
 604                .name   = "mediatek-ddp",
 605                .owner  = THIS_MODULE,
 606                .of_match_table = ddp_driver_dt_match,
 607        },
 608};
 609