linux/drivers/soc/mediatek/mtk-mmsys.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2014 MediaTek Inc.
   4 * Author: James Liao <jamesjj.liao@mediatek.com>
   5 */
   6
   7#include <linux/device.h>
   8#include <linux/io.h>
   9#include <linux/of_device.h>
  10#include <linux/platform_device.h>
  11#include <linux/soc/mediatek/mtk-mmsys.h>
  12
  13#define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN       0x040
  14#define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN       0x044
  15#define DISP_REG_CONFIG_DISP_OD_MOUT_EN         0x048
  16#define DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN      0x04c
  17#define DISP_REG_CONFIG_DISP_UFOE_MOUT_EN       0x050
  18#define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN      0x084
  19#define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN      0x088
  20#define DISP_REG_CONFIG_DSIE_SEL_IN             0x0a4
  21#define DISP_REG_CONFIG_DSIO_SEL_IN             0x0a8
  22#define DISP_REG_CONFIG_DPI_SEL_IN              0x0ac
  23#define DISP_REG_CONFIG_DISP_RDMA2_SOUT         0x0b8
  24#define DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN      0x0c4
  25#define DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN      0x0c8
  26#define DISP_REG_CONFIG_MMSYS_CG_CON0           0x100
  27
  28#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN        0x030
  29#define DISP_REG_CONFIG_OUT_SEL                 0x04c
  30#define DISP_REG_CONFIG_DSI_SEL                 0x050
  31#define DISP_REG_CONFIG_DPI_SEL                 0x064
  32
  33#define OVL0_MOUT_EN_COLOR0                     0x1
  34#define OD_MOUT_EN_RDMA0                        0x1
  35#define OD1_MOUT_EN_RDMA1                       BIT(16)
  36#define UFOE_MOUT_EN_DSI0                       0x1
  37#define COLOR0_SEL_IN_OVL0                      0x1
  38#define OVL1_MOUT_EN_COLOR1                     0x1
  39#define GAMMA_MOUT_EN_RDMA1                     0x1
  40#define RDMA0_SOUT_DPI0                         0x2
  41#define RDMA0_SOUT_DPI1                         0x3
  42#define RDMA0_SOUT_DSI1                         0x1
  43#define RDMA0_SOUT_DSI2                         0x4
  44#define RDMA0_SOUT_DSI3                         0x5
  45#define RDMA1_SOUT_DPI0                         0x2
  46#define RDMA1_SOUT_DPI1                         0x3
  47#define RDMA1_SOUT_DSI1                         0x1
  48#define RDMA1_SOUT_DSI2                         0x4
  49#define RDMA1_SOUT_DSI3                         0x5
  50#define RDMA2_SOUT_DPI0                         0x2
  51#define RDMA2_SOUT_DPI1                         0x3
  52#define RDMA2_SOUT_DSI1                         0x1
  53#define RDMA2_SOUT_DSI2                         0x4
  54#define RDMA2_SOUT_DSI3                         0x5
  55#define DPI0_SEL_IN_RDMA1                       0x1
  56#define DPI0_SEL_IN_RDMA2                       0x3
  57#define DPI1_SEL_IN_RDMA1                       (0x1 << 8)
  58#define DPI1_SEL_IN_RDMA2                       (0x3 << 8)
  59#define DSI0_SEL_IN_RDMA1                       0x1
  60#define DSI0_SEL_IN_RDMA2                       0x4
  61#define DSI1_SEL_IN_RDMA1                       0x1
  62#define DSI1_SEL_IN_RDMA2                       0x4
  63#define DSI2_SEL_IN_RDMA1                       (0x1 << 16)
  64#define DSI2_SEL_IN_RDMA2                       (0x4 << 16)
  65#define DSI3_SEL_IN_RDMA1                       (0x1 << 16)
  66#define DSI3_SEL_IN_RDMA2                       (0x4 << 16)
  67#define COLOR1_SEL_IN_OVL1                      0x1
  68
  69#define OVL_MOUT_EN_RDMA                        0x1
  70#define BLS_TO_DSI_RDMA1_TO_DPI1                0x8
  71#define BLS_TO_DPI_RDMA1_TO_DSI                 0x2
  72#define DSI_SEL_IN_BLS                          0x0
  73#define DPI_SEL_IN_BLS                          0x0
  74#define DSI_SEL_IN_RDMA                         0x1
  75
  76struct mtk_mmsys_driver_data {
  77        const char *clk_driver;
  78};
  79
  80static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
  81        .clk_driver = "clk-mt2701-mm",
  82};
  83
  84static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
  85        .clk_driver = "clk-mt2712-mm",
  86};
  87
  88static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = {
  89        .clk_driver = "clk-mt6779-mm",
  90};
  91
  92static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = {
  93        .clk_driver = "clk-mt6797-mm",
  94};
  95
  96static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
  97        .clk_driver = "clk-mt8173-mm",
  98};
  99
 100static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
 101        .clk_driver = "clk-mt8183-mm",
 102};
 103
 104static unsigned int mtk_mmsys_ddp_mout_en(enum mtk_ddp_comp_id cur,
 105                                          enum mtk_ddp_comp_id next,
 106                                          unsigned int *addr)
 107{
 108        unsigned int value;
 109
 110        if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
 111                *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
 112                value = OVL0_MOUT_EN_COLOR0;
 113        } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) {
 114                *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN;
 115                value = OVL_MOUT_EN_RDMA;
 116        } else if (cur == DDP_COMPONENT_OD0 && next == DDP_COMPONENT_RDMA0) {
 117                *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
 118                value = OD_MOUT_EN_RDMA0;
 119        } else if (cur == DDP_COMPONENT_UFOE && next == DDP_COMPONENT_DSI0) {
 120                *addr = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN;
 121                value = UFOE_MOUT_EN_DSI0;
 122        } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
 123                *addr = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN;
 124                value = OVL1_MOUT_EN_COLOR1;
 125        } else if (cur == DDP_COMPONENT_GAMMA && next == DDP_COMPONENT_RDMA1) {
 126                *addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN;
 127                value = GAMMA_MOUT_EN_RDMA1;
 128        } else if (cur == DDP_COMPONENT_OD1 && next == DDP_COMPONENT_RDMA1) {
 129                *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
 130                value = OD1_MOUT_EN_RDMA1;
 131        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI0) {
 132                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 133                value = RDMA0_SOUT_DPI0;
 134        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI1) {
 135                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 136                value = RDMA0_SOUT_DPI1;
 137        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI1) {
 138                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 139                value = RDMA0_SOUT_DSI1;
 140        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI2) {
 141                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 142                value = RDMA0_SOUT_DSI2;
 143        } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI3) {
 144                *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
 145                value = RDMA0_SOUT_DSI3;
 146        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) {
 147                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 148                value = RDMA1_SOUT_DSI1;
 149        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) {
 150                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 151                value = RDMA1_SOUT_DSI2;
 152        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) {
 153                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 154                value = RDMA1_SOUT_DSI3;
 155        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
 156                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 157                value = RDMA1_SOUT_DPI0;
 158        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) {
 159                *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
 160                value = RDMA1_SOUT_DPI1;
 161        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) {
 162                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 163                value = RDMA2_SOUT_DPI0;
 164        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) {
 165                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 166                value = RDMA2_SOUT_DPI1;
 167        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) {
 168                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 169                value = RDMA2_SOUT_DSI1;
 170        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) {
 171                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 172                value = RDMA2_SOUT_DSI2;
 173        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) {
 174                *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
 175                value = RDMA2_SOUT_DSI3;
 176        } else {
 177                value = 0;
 178        }
 179
 180        return value;
 181}
 182
 183static unsigned int mtk_mmsys_ddp_sel_in(enum mtk_ddp_comp_id cur,
 184                                         enum mtk_ddp_comp_id next,
 185                                         unsigned int *addr)
 186{
 187        unsigned int value;
 188
 189        if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
 190                *addr = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN;
 191                value = COLOR0_SEL_IN_OVL0;
 192        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
 193                *addr = DISP_REG_CONFIG_DPI_SEL_IN;
 194                value = DPI0_SEL_IN_RDMA1;
 195        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) {
 196                *addr = DISP_REG_CONFIG_DPI_SEL_IN;
 197                value = DPI1_SEL_IN_RDMA1;
 198        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI0) {
 199                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 200                value = DSI0_SEL_IN_RDMA1;
 201        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) {
 202                *addr = DISP_REG_CONFIG_DSIO_SEL_IN;
 203                value = DSI1_SEL_IN_RDMA1;
 204        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) {
 205                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 206                value = DSI2_SEL_IN_RDMA1;
 207        } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) {
 208                *addr = DISP_REG_CONFIG_DSIO_SEL_IN;
 209                value = DSI3_SEL_IN_RDMA1;
 210        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) {
 211                *addr = DISP_REG_CONFIG_DPI_SEL_IN;
 212                value = DPI0_SEL_IN_RDMA2;
 213        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) {
 214                *addr = DISP_REG_CONFIG_DPI_SEL_IN;
 215                value = DPI1_SEL_IN_RDMA2;
 216        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI0) {
 217                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 218                value = DSI0_SEL_IN_RDMA2;
 219        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) {
 220                *addr = DISP_REG_CONFIG_DSIO_SEL_IN;
 221                value = DSI1_SEL_IN_RDMA2;
 222        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) {
 223                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 224                value = DSI2_SEL_IN_RDMA2;
 225        } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) {
 226                *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
 227                value = DSI3_SEL_IN_RDMA2;
 228        } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
 229                *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
 230                value = COLOR1_SEL_IN_OVL1;
 231        } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
 232                *addr = DISP_REG_CONFIG_DSI_SEL;
 233                value = DSI_SEL_IN_BLS;
 234        } else {
 235                value = 0;
 236        }
 237
 238        return value;
 239}
 240
 241static void mtk_mmsys_ddp_sout_sel(void __iomem *config_regs,
 242                                   enum mtk_ddp_comp_id cur,
 243                                   enum mtk_ddp_comp_id next)
 244{
 245        if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
 246                writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
 247                               config_regs + DISP_REG_CONFIG_OUT_SEL);
 248        } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DPI0) {
 249                writel_relaxed(BLS_TO_DPI_RDMA1_TO_DSI,
 250                               config_regs + DISP_REG_CONFIG_OUT_SEL);
 251                writel_relaxed(DSI_SEL_IN_RDMA,
 252                               config_regs + DISP_REG_CONFIG_DSI_SEL);
 253                writel_relaxed(DPI_SEL_IN_BLS,
 254                               config_regs + DISP_REG_CONFIG_DPI_SEL);
 255        }
 256}
 257
 258void mtk_mmsys_ddp_connect(struct device *dev,
 259                           enum mtk_ddp_comp_id cur,
 260                           enum mtk_ddp_comp_id next)
 261{
 262        void __iomem *config_regs = dev_get_drvdata(dev);
 263        unsigned int addr, value, reg;
 264
 265        value = mtk_mmsys_ddp_mout_en(cur, next, &addr);
 266        if (value) {
 267                reg = readl_relaxed(config_regs + addr) | value;
 268                writel_relaxed(reg, config_regs + addr);
 269        }
 270
 271        mtk_mmsys_ddp_sout_sel(config_regs, cur, next);
 272
 273        value = mtk_mmsys_ddp_sel_in(cur, next, &addr);
 274        if (value) {
 275                reg = readl_relaxed(config_regs + addr) | value;
 276                writel_relaxed(reg, config_regs + addr);
 277        }
 278}
 279EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect);
 280
 281void mtk_mmsys_ddp_disconnect(struct device *dev,
 282                              enum mtk_ddp_comp_id cur,
 283                              enum mtk_ddp_comp_id next)
 284{
 285        void __iomem *config_regs = dev_get_drvdata(dev);
 286        unsigned int addr, value, reg;
 287
 288        value = mtk_mmsys_ddp_mout_en(cur, next, &addr);
 289        if (value) {
 290                reg = readl_relaxed(config_regs + addr) & ~value;
 291                writel_relaxed(reg, config_regs + addr);
 292        }
 293
 294        value = mtk_mmsys_ddp_sel_in(cur, next, &addr);
 295        if (value) {
 296                reg = readl_relaxed(config_regs + addr) & ~value;
 297                writel_relaxed(reg, config_regs + addr);
 298        }
 299}
 300EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect);
 301
 302static int mtk_mmsys_probe(struct platform_device *pdev)
 303{
 304        const struct mtk_mmsys_driver_data *data;
 305        struct device *dev = &pdev->dev;
 306        struct platform_device *clks;
 307        struct platform_device *drm;
 308        void __iomem *config_regs;
 309        int ret;
 310
 311        config_regs = devm_platform_ioremap_resource(pdev, 0);
 312        if (IS_ERR(config_regs)) {
 313                ret = PTR_ERR(config_regs);
 314                dev_err(dev, "Failed to ioremap mmsys registers: %d\n", ret);
 315                return ret;
 316        }
 317
 318        platform_set_drvdata(pdev, config_regs);
 319
 320        data = of_device_get_match_data(&pdev->dev);
 321
 322        clks = platform_device_register_data(&pdev->dev, data->clk_driver,
 323                                             PLATFORM_DEVID_AUTO, NULL, 0);
 324        if (IS_ERR(clks))
 325                return PTR_ERR(clks);
 326
 327        drm = platform_device_register_data(&pdev->dev, "mediatek-drm",
 328                                            PLATFORM_DEVID_AUTO, NULL, 0);
 329        if (IS_ERR(drm)) {
 330                platform_device_unregister(clks);
 331                return PTR_ERR(drm);
 332        }
 333
 334        return 0;
 335}
 336
 337static const struct of_device_id of_match_mtk_mmsys[] = {
 338        {
 339                .compatible = "mediatek,mt2701-mmsys",
 340                .data = &mt2701_mmsys_driver_data,
 341        },
 342        {
 343                .compatible = "mediatek,mt2712-mmsys",
 344                .data = &mt2712_mmsys_driver_data,
 345        },
 346        {
 347                .compatible = "mediatek,mt6779-mmsys",
 348                .data = &mt6779_mmsys_driver_data,
 349        },
 350        {
 351                .compatible = "mediatek,mt6797-mmsys",
 352                .data = &mt6797_mmsys_driver_data,
 353        },
 354        {
 355                .compatible = "mediatek,mt8173-mmsys",
 356                .data = &mt8173_mmsys_driver_data,
 357        },
 358        {
 359                .compatible = "mediatek,mt8183-mmsys",
 360                .data = &mt8183_mmsys_driver_data,
 361        },
 362        { }
 363};
 364
 365static struct platform_driver mtk_mmsys_drv = {
 366        .driver = {
 367                .name = "mtk-mmsys",
 368                .of_match_table = of_match_mtk_mmsys,
 369        },
 370        .probe = mtk_mmsys_probe,
 371};
 372
 373builtin_platform_driver(mtk_mmsys_drv);
 374