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

Configure Feed

Select the types of activity you want to include in your feed.

at v4.9-rc6 353 lines 9.7 kB view raw
1/* 2 * Copyright (c) 2015 MediaTek Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14#include <linux/clk.h> 15#include <linux/module.h> 16#include <linux/of_device.h> 17#include <linux/platform_device.h> 18#include <linux/regmap.h> 19 20#include "mtk_drm_ddp.h" 21#include "mtk_drm_ddp_comp.h" 22 23#define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0x040 24#define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN 0x044 25#define DISP_REG_CONFIG_DISP_OD_MOUT_EN 0x048 26#define DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN 0x04c 27#define DISP_REG_CONFIG_DISP_UFOE_MOUT_EN 0x050 28#define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0x084 29#define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN 0x088 30#define DISP_REG_CONFIG_DPI_SEL_IN 0x0ac 31#define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN 0x0c8 32#define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100 33 34#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) 35#define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n)) 36#define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n)) 37#define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n)) 38 39#define MUTEX_MOD_DISP_OVL0 BIT(11) 40#define MUTEX_MOD_DISP_OVL1 BIT(12) 41#define MUTEX_MOD_DISP_RDMA0 BIT(13) 42#define MUTEX_MOD_DISP_RDMA1 BIT(14) 43#define MUTEX_MOD_DISP_RDMA2 BIT(15) 44#define MUTEX_MOD_DISP_WDMA0 BIT(16) 45#define MUTEX_MOD_DISP_WDMA1 BIT(17) 46#define MUTEX_MOD_DISP_COLOR0 BIT(18) 47#define MUTEX_MOD_DISP_COLOR1 BIT(19) 48#define MUTEX_MOD_DISP_AAL BIT(20) 49#define MUTEX_MOD_DISP_GAMMA BIT(21) 50#define MUTEX_MOD_DISP_UFOE BIT(22) 51#define MUTEX_MOD_DISP_PWM0 BIT(23) 52#define MUTEX_MOD_DISP_PWM1 BIT(24) 53#define MUTEX_MOD_DISP_OD BIT(25) 54 55#define MUTEX_SOF_SINGLE_MODE 0 56#define MUTEX_SOF_DSI0 1 57#define MUTEX_SOF_DSI1 2 58#define MUTEX_SOF_DPI0 3 59 60#define OVL0_MOUT_EN_COLOR0 0x1 61#define OD_MOUT_EN_RDMA0 0x1 62#define UFOE_MOUT_EN_DSI0 0x1 63#define COLOR0_SEL_IN_OVL0 0x1 64#define OVL1_MOUT_EN_COLOR1 0x1 65#define GAMMA_MOUT_EN_RDMA1 0x1 66#define RDMA1_MOUT_DPI0 0x2 67#define DPI0_SEL_IN_RDMA1 0x1 68#define COLOR1_SEL_IN_OVL1 0x1 69 70struct mtk_disp_mutex { 71 int id; 72 bool claimed; 73}; 74 75struct mtk_ddp { 76 struct device *dev; 77 struct clk *clk; 78 void __iomem *regs; 79 struct mtk_disp_mutex mutex[10]; 80}; 81 82static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = { 83 [DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL, 84 [DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0, 85 [DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1, 86 [DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA, 87 [DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD, 88 [DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0, 89 [DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1, 90 [DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0, 91 [DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1, 92 [DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0, 93 [DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1, 94 [DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2, 95 [DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE, 96 [DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0, 97 [DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1, 98}; 99 100static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, 101 enum mtk_ddp_comp_id next, 102 unsigned int *addr) 103{ 104 unsigned int value; 105 106 if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) { 107 *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN; 108 value = OVL0_MOUT_EN_COLOR0; 109 } else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) { 110 *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN; 111 value = OD_MOUT_EN_RDMA0; 112 } else if (cur == DDP_COMPONENT_UFOE && next == DDP_COMPONENT_DSI0) { 113 *addr = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN; 114 value = UFOE_MOUT_EN_DSI0; 115 } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) { 116 *addr = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN; 117 value = OVL1_MOUT_EN_COLOR1; 118 } else if (cur == DDP_COMPONENT_GAMMA && next == DDP_COMPONENT_RDMA1) { 119 *addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN; 120 value = GAMMA_MOUT_EN_RDMA1; 121 } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) { 122 *addr = DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN; 123 value = RDMA1_MOUT_DPI0; 124 } else { 125 value = 0; 126 } 127 128 return value; 129} 130 131static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur, 132 enum mtk_ddp_comp_id next, 133 unsigned int *addr) 134{ 135 unsigned int value; 136 137 if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) { 138 *addr = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN; 139 value = COLOR0_SEL_IN_OVL0; 140 } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) { 141 *addr = DISP_REG_CONFIG_DPI_SEL_IN; 142 value = DPI0_SEL_IN_RDMA1; 143 } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) { 144 *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN; 145 value = COLOR1_SEL_IN_OVL1; 146 } else { 147 value = 0; 148 } 149 150 return value; 151} 152 153void mtk_ddp_add_comp_to_path(void __iomem *config_regs, 154 enum mtk_ddp_comp_id cur, 155 enum mtk_ddp_comp_id next) 156{ 157 unsigned int addr, value, reg; 158 159 value = mtk_ddp_mout_en(cur, next, &addr); 160 if (value) { 161 reg = readl_relaxed(config_regs + addr) | value; 162 writel_relaxed(reg, config_regs + addr); 163 } 164 165 value = mtk_ddp_sel_in(cur, next, &addr); 166 if (value) { 167 reg = readl_relaxed(config_regs + addr) | value; 168 writel_relaxed(reg, config_regs + addr); 169 } 170} 171 172void mtk_ddp_remove_comp_from_path(void __iomem *config_regs, 173 enum mtk_ddp_comp_id cur, 174 enum mtk_ddp_comp_id next) 175{ 176 unsigned int addr, value, reg; 177 178 value = mtk_ddp_mout_en(cur, next, &addr); 179 if (value) { 180 reg = readl_relaxed(config_regs + addr) & ~value; 181 writel_relaxed(reg, config_regs + addr); 182 } 183 184 value = mtk_ddp_sel_in(cur, next, &addr); 185 if (value) { 186 reg = readl_relaxed(config_regs + addr) & ~value; 187 writel_relaxed(reg, config_regs + addr); 188 } 189} 190 191struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id) 192{ 193 struct mtk_ddp *ddp = dev_get_drvdata(dev); 194 195 if (id >= 10) 196 return ERR_PTR(-EINVAL); 197 if (ddp->mutex[id].claimed) 198 return ERR_PTR(-EBUSY); 199 200 ddp->mutex[id].claimed = true; 201 202 return &ddp->mutex[id]; 203} 204 205void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex) 206{ 207 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 208 mutex[mutex->id]); 209 210 WARN_ON(&ddp->mutex[mutex->id] != mutex); 211 212 mutex->claimed = false; 213} 214 215int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex) 216{ 217 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 218 mutex[mutex->id]); 219 return clk_prepare_enable(ddp->clk); 220} 221 222void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex) 223{ 224 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 225 mutex[mutex->id]); 226 clk_disable_unprepare(ddp->clk); 227} 228 229void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex, 230 enum mtk_ddp_comp_id id) 231{ 232 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 233 mutex[mutex->id]); 234 unsigned int reg; 235 236 WARN_ON(&ddp->mutex[mutex->id] != mutex); 237 238 switch (id) { 239 case DDP_COMPONENT_DSI0: 240 reg = MUTEX_SOF_DSI0; 241 break; 242 case DDP_COMPONENT_DSI1: 243 reg = MUTEX_SOF_DSI0; 244 break; 245 case DDP_COMPONENT_DPI0: 246 reg = MUTEX_SOF_DPI0; 247 break; 248 default: 249 reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); 250 reg |= mutex_mod[id]; 251 writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); 252 return; 253 } 254 255 writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_SOF(mutex->id)); 256} 257 258void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex, 259 enum mtk_ddp_comp_id id) 260{ 261 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 262 mutex[mutex->id]); 263 unsigned int reg; 264 265 WARN_ON(&ddp->mutex[mutex->id] != mutex); 266 267 switch (id) { 268 case DDP_COMPONENT_DSI0: 269 case DDP_COMPONENT_DSI1: 270 case DDP_COMPONENT_DPI0: 271 writel_relaxed(MUTEX_SOF_SINGLE_MODE, 272 ddp->regs + DISP_REG_MUTEX_SOF(mutex->id)); 273 break; 274 default: 275 reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); 276 reg &= ~mutex_mod[id]; 277 writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); 278 break; 279 } 280} 281 282void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex) 283{ 284 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 285 mutex[mutex->id]); 286 287 WARN_ON(&ddp->mutex[mutex->id] != mutex); 288 289 writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); 290} 291 292void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex) 293{ 294 struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, 295 mutex[mutex->id]); 296 297 WARN_ON(&ddp->mutex[mutex->id] != mutex); 298 299 writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); 300} 301 302static int mtk_ddp_probe(struct platform_device *pdev) 303{ 304 struct device *dev = &pdev->dev; 305 struct mtk_ddp *ddp; 306 struct resource *regs; 307 int i; 308 309 ddp = devm_kzalloc(dev, sizeof(*ddp), GFP_KERNEL); 310 if (!ddp) 311 return -ENOMEM; 312 313 for (i = 0; i < 10; i++) 314 ddp->mutex[i].id = i; 315 316 ddp->clk = devm_clk_get(dev, NULL); 317 if (IS_ERR(ddp->clk)) { 318 dev_err(dev, "Failed to get clock\n"); 319 return PTR_ERR(ddp->clk); 320 } 321 322 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 323 ddp->regs = devm_ioremap_resource(dev, regs); 324 if (IS_ERR(ddp->regs)) { 325 dev_err(dev, "Failed to map mutex registers\n"); 326 return PTR_ERR(ddp->regs); 327 } 328 329 platform_set_drvdata(pdev, ddp); 330 331 return 0; 332} 333 334static int mtk_ddp_remove(struct platform_device *pdev) 335{ 336 return 0; 337} 338 339static const struct of_device_id ddp_driver_dt_match[] = { 340 { .compatible = "mediatek,mt8173-disp-mutex" }, 341 {}, 342}; 343MODULE_DEVICE_TABLE(of, ddp_driver_dt_match); 344 345struct platform_driver mtk_ddp_driver = { 346 .probe = mtk_ddp_probe, 347 .remove = mtk_ddp_remove, 348 .driver = { 349 .name = "mediatek-ddp", 350 .owner = THIS_MODULE, 351 .of_match_table = ddp_driver_dt_match, 352 }, 353};