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 MT2701_DISP_MUTEX0_MOD0 0x2c 17#define MT2701_DISP_MUTEX0_SOF0 0x30 18 19#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) 20#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n)) 21#define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n)) 22#define DISP_REG_MUTEX_MOD(mutex_mod_reg, n) (mutex_mod_reg + 0x20 * (n)) 23#define DISP_REG_MUTEX_SOF(mutex_sof_reg, n) (mutex_sof_reg + 0x20 * (n)) 24#define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n)) 25 26#define INT_MUTEX BIT(1) 27 28#define MT8173_MUTEX_MOD_DISP_OVL0 11 29#define MT8173_MUTEX_MOD_DISP_OVL1 12 30#define MT8173_MUTEX_MOD_DISP_RDMA0 13 31#define MT8173_MUTEX_MOD_DISP_RDMA1 14 32#define MT8173_MUTEX_MOD_DISP_RDMA2 15 33#define MT8173_MUTEX_MOD_DISP_WDMA0 16 34#define MT8173_MUTEX_MOD_DISP_WDMA1 17 35#define MT8173_MUTEX_MOD_DISP_COLOR0 18 36#define MT8173_MUTEX_MOD_DISP_COLOR1 19 37#define MT8173_MUTEX_MOD_DISP_AAL 20 38#define MT8173_MUTEX_MOD_DISP_GAMMA 21 39#define MT8173_MUTEX_MOD_DISP_UFOE 22 40#define MT8173_MUTEX_MOD_DISP_PWM0 23 41#define MT8173_MUTEX_MOD_DISP_PWM1 24 42#define MT8173_MUTEX_MOD_DISP_OD 25 43 44#define MT2712_MUTEX_MOD_DISP_PWM2 10 45#define MT2712_MUTEX_MOD_DISP_OVL0 11 46#define MT2712_MUTEX_MOD_DISP_OVL1 12 47#define MT2712_MUTEX_MOD_DISP_RDMA0 13 48#define MT2712_MUTEX_MOD_DISP_RDMA1 14 49#define MT2712_MUTEX_MOD_DISP_RDMA2 15 50#define MT2712_MUTEX_MOD_DISP_WDMA0 16 51#define MT2712_MUTEX_MOD_DISP_WDMA1 17 52#define MT2712_MUTEX_MOD_DISP_COLOR0 18 53#define MT2712_MUTEX_MOD_DISP_COLOR1 19 54#define MT2712_MUTEX_MOD_DISP_AAL0 20 55#define MT2712_MUTEX_MOD_DISP_UFOE 22 56#define MT2712_MUTEX_MOD_DISP_PWM0 23 57#define MT2712_MUTEX_MOD_DISP_PWM1 24 58#define MT2712_MUTEX_MOD_DISP_OD0 25 59#define MT2712_MUTEX_MOD2_DISP_AAL1 33 60#define MT2712_MUTEX_MOD2_DISP_OD1 34 61 62#define MT2701_MUTEX_MOD_DISP_OVL 3 63#define MT2701_MUTEX_MOD_DISP_WDMA 6 64#define MT2701_MUTEX_MOD_DISP_COLOR 7 65#define MT2701_MUTEX_MOD_DISP_BLS 9 66#define MT2701_MUTEX_MOD_DISP_RDMA0 10 67#define MT2701_MUTEX_MOD_DISP_RDMA1 12 68 69#define MUTEX_SOF_SINGLE_MODE 0 70#define MUTEX_SOF_DSI0 1 71#define MUTEX_SOF_DSI1 2 72#define MUTEX_SOF_DPI0 3 73#define MUTEX_SOF_DPI1 4 74#define MUTEX_SOF_DSI2 5 75#define MUTEX_SOF_DSI3 6 76 77 78struct mtk_disp_mutex { 79 int id; 80 bool claimed; 81}; 82 83enum mtk_ddp_mutex_sof_id { 84 DDP_MUTEX_SOF_SINGLE_MODE, 85 DDP_MUTEX_SOF_DSI0, 86 DDP_MUTEX_SOF_DSI1, 87 DDP_MUTEX_SOF_DPI0, 88 DDP_MUTEX_SOF_DPI1, 89 DDP_MUTEX_SOF_DSI2, 90 DDP_MUTEX_SOF_DSI3, 91}; 92 93struct mtk_ddp_data { 94 const unsigned int *mutex_mod; 95 const unsigned int *mutex_sof; 96 const unsigned int mutex_mod_reg; 97 const unsigned int mutex_sof_reg; 98 const bool no_clk; 99}; 100 101struct mtk_ddp { 102 struct device *dev; 103 struct clk *clk; 104 void __iomem *regs; 105 struct mtk_disp_mutex mutex[10]; 106 const struct mtk_ddp_data *data; 107}; 108 109static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = { 110 [DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS, 111 [DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR, 112 [DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL, 113 [DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0, 114 [DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1, 115 [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA, 116}; 117 118static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = { 119 [DDP_COMPONENT_AAL0] = MT2712_MUTEX_MOD_DISP_AAL0, 120 [DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1, 121 [DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0, 122 [DDP_COMPONENT_COLOR1] = MT2712_MUTEX_MOD_DISP_COLOR1, 123 [DDP_COMPONENT_OD0] = MT2712_MUTEX_MOD_DISP_OD0, 124 [DDP_COMPONENT_OD1] = MT2712_MUTEX_MOD2_DISP_OD1, 125 [DDP_COMPONENT_OVL0] = MT2712_MUTEX_MOD_DISP_OVL0, 126 [DDP_COMPONENT_OVL1] = MT2712_MUTEX_MOD_DISP_OVL1, 127 [DDP_COMPONENT_PWM0] = MT2712_MUTEX_MOD_DISP_PWM0, 128 [DDP_COMPONENT_PWM1] = MT2712_MUTEX_MOD_DISP_PWM1, 129 [DDP_COMPONENT_PWM2] = MT2712_MUTEX_MOD_DISP_PWM2, 130 [DDP_COMPONENT_RDMA0] = MT2712_MUTEX_MOD_DISP_RDMA0, 131 [DDP_COMPONENT_RDMA1] = MT2712_MUTEX_MOD_DISP_RDMA1, 132 [DDP_COMPONENT_RDMA2] = MT2712_MUTEX_MOD_DISP_RDMA2, 133 [DDP_COMPONENT_UFOE] = MT2712_MUTEX_MOD_DISP_UFOE, 134 [DDP_COMPONENT_WDMA0] = MT2712_MUTEX_MOD_DISP_WDMA0, 135 [DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1, 136}; 137 138static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = { 139 [DDP_COMPONENT_AAL0] = MT8173_MUTEX_MOD_DISP_AAL, 140 [DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0, 141 [DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1, 142 [DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA, 143 [DDP_COMPONENT_OD0] = MT8173_MUTEX_MOD_DISP_OD, 144 [DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0, 145 [DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1, 146 [DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0, 147 [DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1, 148 [DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0, 149 [DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1, 150 [DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2, 151 [DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE, 152 [DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0, 153 [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1, 154}; 155 156static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_DSI3 + 1] = { 157 [DDP_MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, 158 [DDP_MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0, 159 [DDP_MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1, 160 [DDP_MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0, 161 [DDP_MUTEX_SOF_DPI1] = MUTEX_SOF_DPI1, 162 [DDP_MUTEX_SOF_DSI2] = MUTEX_SOF_DSI2, 163 [DDP_MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3, 164}; 165 166static const struct mtk_ddp_data mt2701_ddp_driver_data = { 167 .mutex_mod = mt2701_mutex_mod, 168 .mutex_sof = mt2712_mutex_sof, 169 .mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0, 170 .mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0, 171}; 172 173static const struct mtk_ddp_data mt2712_ddp_driver_data = { 174 .mutex_mod = mt2712_mutex_mod, 175 .mutex_sof = mt2712_mutex_sof, 176 .mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0, 177 .mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0, 178}; 179 180static const struct mtk_ddp_data mt8173_ddp_driver_data = { 181 .mutex_mod = mt8173_mutex_mod, 182 .mutex_sof = mt2712_mutex_sof, 183 .mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0, 184 .mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0, 185}; 186 187struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id) 188{ 189 struct mtk_ddp *ddp = dev_get_drvdata(dev); 190 191 if (id >= 10) 192 return ERR_PTR(-EINVAL); 193 if (ddp->mutex[id].claimed) 194 return ERR_PTR(-EBUSY); 195 196 ddp->mutex[id].claimed = true; 197 198 return &ddp->mutex[id]; 199} 200 201void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex) 202{ 203 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 204 mutex[mutex->id]); 205 206 WARN_ON(&ddp->mutex[mutex->id] != mutex); 207 208 mutex->claimed = false; 209} 210 211int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex) 212{ 213 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 214 mutex[mutex->id]); 215 return clk_prepare_enable(ddp->clk); 216} 217 218void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex) 219{ 220 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 221 mutex[mutex->id]); 222 clk_disable_unprepare(ddp->clk); 223} 224 225void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex, 226 enum mtk_ddp_comp_id id) 227{ 228 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 229 mutex[mutex->id]); 230 unsigned int reg; 231 unsigned int sof_id; 232 unsigned int offset; 233 234 WARN_ON(&ddp->mutex[mutex->id] != mutex); 235 236 switch (id) { 237 case DDP_COMPONENT_DSI0: 238 sof_id = DDP_MUTEX_SOF_DSI0; 239 break; 240 case DDP_COMPONENT_DSI1: 241 sof_id = DDP_MUTEX_SOF_DSI0; 242 break; 243 case DDP_COMPONENT_DSI2: 244 sof_id = DDP_MUTEX_SOF_DSI2; 245 break; 246 case DDP_COMPONENT_DSI3: 247 sof_id = DDP_MUTEX_SOF_DSI3; 248 break; 249 case DDP_COMPONENT_DPI0: 250 sof_id = DDP_MUTEX_SOF_DPI0; 251 break; 252 case DDP_COMPONENT_DPI1: 253 sof_id = DDP_MUTEX_SOF_DPI1; 254 break; 255 default: 256 if (ddp->data->mutex_mod[id] < 32) { 257 offset = DISP_REG_MUTEX_MOD(ddp->data->mutex_mod_reg, 258 mutex->id); 259 reg = readl_relaxed(ddp->regs + offset); 260 reg |= 1 << ddp->data->mutex_mod[id]; 261 writel_relaxed(reg, ddp->regs + offset); 262 } else { 263 offset = DISP_REG_MUTEX_MOD2(mutex->id); 264 reg = readl_relaxed(ddp->regs + offset); 265 reg |= 1 << (ddp->data->mutex_mod[id] - 32); 266 writel_relaxed(reg, ddp->regs + offset); 267 } 268 return; 269 } 270 271 writel_relaxed(ddp->data->mutex_sof[sof_id], 272 ddp->regs + 273 DISP_REG_MUTEX_SOF(ddp->data->mutex_sof_reg, mutex->id)); 274} 275 276void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex, 277 enum mtk_ddp_comp_id id) 278{ 279 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 280 mutex[mutex->id]); 281 unsigned int reg; 282 unsigned int offset; 283 284 WARN_ON(&ddp->mutex[mutex->id] != mutex); 285 286 switch (id) { 287 case DDP_COMPONENT_DSI0: 288 case DDP_COMPONENT_DSI1: 289 case DDP_COMPONENT_DSI2: 290 case DDP_COMPONENT_DSI3: 291 case DDP_COMPONENT_DPI0: 292 case DDP_COMPONENT_DPI1: 293 writel_relaxed(MUTEX_SOF_SINGLE_MODE, 294 ddp->regs + 295 DISP_REG_MUTEX_SOF(ddp->data->mutex_sof_reg, 296 mutex->id)); 297 break; 298 default: 299 if (ddp->data->mutex_mod[id] < 32) { 300 offset = DISP_REG_MUTEX_MOD(ddp->data->mutex_mod_reg, 301 mutex->id); 302 reg = readl_relaxed(ddp->regs + offset); 303 reg &= ~(1 << ddp->data->mutex_mod[id]); 304 writel_relaxed(reg, ddp->regs + offset); 305 } else { 306 offset = DISP_REG_MUTEX_MOD2(mutex->id); 307 reg = readl_relaxed(ddp->regs + offset); 308 reg &= ~(1 << (ddp->data->mutex_mod[id] - 32)); 309 writel_relaxed(reg, ddp->regs + offset); 310 } 311 break; 312 } 313} 314 315void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex) 316{ 317 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 318 mutex[mutex->id]); 319 320 WARN_ON(&ddp->mutex[mutex->id] != mutex); 321 322 writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); 323} 324 325void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex) 326{ 327 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 328 mutex[mutex->id]); 329 330 WARN_ON(&ddp->mutex[mutex->id] != mutex); 331 332 writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); 333} 334 335void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex) 336{ 337 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 338 mutex[mutex->id]); 339 u32 tmp; 340 341 writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); 342 writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id)); 343 if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id), 344 tmp, tmp & INT_MUTEX, 1, 10000)) 345 pr_err("could not acquire mutex %d\n", mutex->id); 346} 347 348void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex) 349{ 350 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 351 mutex[mutex->id]); 352 353 writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id)); 354} 355 356static int mtk_ddp_probe(struct platform_device *pdev) 357{ 358 struct device *dev = &pdev->dev; 359 struct mtk_ddp *ddp; 360 struct resource *regs; 361 int i; 362 363 ddp = devm_kzalloc(dev, sizeof(*ddp), GFP_KERNEL); 364 if (!ddp) 365 return -ENOMEM; 366 367 for (i = 0; i < 10; i++) 368 ddp->mutex[i].id = i; 369 370 ddp->data = of_device_get_match_data(dev); 371 372 if (!ddp->data->no_clk) { 373 ddp->clk = devm_clk_get(dev, NULL); 374 if (IS_ERR(ddp->clk)) { 375 if (PTR_ERR(ddp->clk) != -EPROBE_DEFER) 376 dev_err(dev, "Failed to get clock\n"); 377 return PTR_ERR(ddp->clk); 378 } 379 } 380 381 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 382 ddp->regs = devm_ioremap_resource(dev, regs); 383 if (IS_ERR(ddp->regs)) { 384 dev_err(dev, "Failed to map mutex registers\n"); 385 return PTR_ERR(ddp->regs); 386 } 387 388 platform_set_drvdata(pdev, ddp); 389 390 return 0; 391} 392 393static int mtk_ddp_remove(struct platform_device *pdev) 394{ 395 return 0; 396} 397 398static const struct of_device_id ddp_driver_dt_match[] = { 399 { .compatible = "mediatek,mt2701-disp-mutex", 400 .data = &mt2701_ddp_driver_data}, 401 { .compatible = "mediatek,mt2712-disp-mutex", 402 .data = &mt2712_ddp_driver_data}, 403 { .compatible = "mediatek,mt8173-disp-mutex", 404 .data = &mt8173_ddp_driver_data}, 405 {}, 406}; 407MODULE_DEVICE_TABLE(of, ddp_driver_dt_match); 408 409struct platform_driver mtk_ddp_driver = { 410 .probe = mtk_ddp_probe, 411 .remove = mtk_ddp_remove, 412 .driver = { 413 .name = "mediatek-ddp", 414 .owner = THIS_MODULE, 415 .of_match_table = ddp_driver_dt_match, 416 }, 417}; 418