1 /* 2 * Copyright (c) 2016-2017 Lucas Stach, Pengutronix 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 */ 13 14 #include <drm/drm_fourcc.h> 15 #include <linux/clk.h> 16 #include <linux/err.h> 17 #include <linux/mfd/syscon.h> 18 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 19 #include <linux/module.h> 20 #include <linux/of.h> 21 #include <linux/platform_device.h> 22 #include <linux/regmap.h> 23 #include <video/imx-ipu-v3.h> 24 25 #include "ipu-prv.h" 26 27 #define IPU_PRG_CTL 0x00 28 #define IPU_PRG_CTL_BYPASS(i) (1 << (0 + i)) 29 #define IPU_PRG_CTL_SOFT_ARID_MASK 0x3 30 #define IPU_PRG_CTL_SOFT_ARID_SHIFT(i) (8 + i * 2) 31 #define IPU_PRG_CTL_SOFT_ARID(i, v) ((v & 0x3) << (8 + 2 * i)) 32 #define IPU_PRG_CTL_SO(i) (1 << (16 + i)) 33 #define IPU_PRG_CTL_VFLIP(i) (1 << (19 + i)) 34 #define IPU_PRG_CTL_BLOCK_MODE(i) (1 << (22 + i)) 35 #define IPU_PRG_CTL_CNT_LOAD_EN(i) (1 << (25 + i)) 36 #define IPU_PRG_CTL_SOFTRST (1 << 30) 37 #define IPU_PRG_CTL_SHADOW_EN (1 << 31) 38 39 #define IPU_PRG_STATUS 0x04 40 #define IPU_PRG_STATUS_BUFFER0_READY(i) (1 << (0 + i * 2)) 41 #define IPU_PRG_STATUS_BUFFER1_READY(i) (1 << (1 + i * 2)) 42 43 #define IPU_PRG_QOS 0x08 44 #define IPU_PRG_QOS_ARID_MASK 0xf 45 #define IPU_PRG_QOS_ARID_SHIFT(i) (0 + i * 4) 46 47 #define IPU_PRG_REG_UPDATE 0x0c 48 #define IPU_PRG_REG_UPDATE_REG_UPDATE (1 << 0) 49 50 #define IPU_PRG_STRIDE(i) (0x10 + i * 0x4) 51 #define IPU_PRG_STRIDE_STRIDE_MASK 0x3fff 52 53 #define IPU_PRG_CROP_LINE 0x1c 54 55 #define IPU_PRG_THD 0x20 56 57 #define IPU_PRG_BADDR(i) (0x24 + i * 0x4) 58 59 #define IPU_PRG_OFFSET(i) (0x30 + i * 0x4) 60 61 #define IPU_PRG_ILO(i) (0x3c + i * 0x4) 62 63 #define IPU_PRG_HEIGHT(i) (0x48 + i * 0x4) 64 #define IPU_PRG_HEIGHT_PRE_HEIGHT_MASK 0xfff 65 #define IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT 0 66 #define IPU_PRG_HEIGHT_IPU_HEIGHT_MASK 0xfff 67 #define IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT 16 68 69 struct ipu_prg_channel { 70 bool enabled; 71 int used_pre; 72 }; 73 74 struct ipu_prg { 75 struct list_head list; 76 struct device *dev; 77 int id; 78 79 void __iomem *regs; 80 struct clk *clk_ipg, *clk_axi; 81 struct regmap *iomuxc_gpr; 82 struct ipu_pre *pres[3]; 83 84 struct ipu_prg_channel chan[3]; 85 }; 86 87 static DEFINE_MUTEX(ipu_prg_list_mutex); 88 static LIST_HEAD(ipu_prg_list); 89 90 struct ipu_prg * 91 ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id) 92 { 93 struct device_node *prg_node = of_parse_phandle(dev->of_node, 94 name, 0); 95 struct ipu_prg *prg; 96 97 mutex_lock(&ipu_prg_list_mutex); 98 list_for_each_entry(prg, &ipu_prg_list, list) { 99 if (prg_node == prg->dev->of_node) { 100 mutex_unlock(&ipu_prg_list_mutex); 101 device_link_add(dev, prg->dev, DL_FLAG_AUTOREMOVE); 102 prg->id = ipu_id; 103 return prg; 104 } 105 } 106 mutex_unlock(&ipu_prg_list_mutex); 107 108 return NULL; 109 } 110 111 int ipu_prg_max_active_channels(void) 112 { 113 return ipu_pre_get_available_count(); 114 } 115 EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels); 116 117 bool ipu_prg_present(struct ipu_soc *ipu) 118 { 119 if (ipu->prg_priv) 120 return true; 121 122 return false; 123 } 124 EXPORT_SYMBOL_GPL(ipu_prg_present); 125 126 bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format, 127 uint64_t modifier) 128 { 129 const struct drm_format_info *info = drm_format_info(format); 130 131 if (info->num_planes != 1) 132 return false; 133 134 return true; 135 } 136 EXPORT_SYMBOL_GPL(ipu_prg_format_supported); 137 138 int ipu_prg_enable(struct ipu_soc *ipu) 139 { 140 struct ipu_prg *prg = ipu->prg_priv; 141 int ret; 142 143 if (!prg) 144 return 0; 145 146 ret = clk_prepare_enable(prg->clk_axi); 147 if (ret) 148 goto fail_disable_ipg; 149 150 return 0; 151 152 fail_disable_ipg: 153 clk_disable_unprepare(prg->clk_ipg); 154 155 return ret; 156 } 157 EXPORT_SYMBOL_GPL(ipu_prg_enable); 158 159 void ipu_prg_disable(struct ipu_soc *ipu) 160 { 161 struct ipu_prg *prg = ipu->prg_priv; 162 163 if (!prg) 164 return; 165 166 clk_disable_unprepare(prg->clk_axi); 167 } 168 EXPORT_SYMBOL_GPL(ipu_prg_disable); 169 170 /* 171 * The channel configuartion functions below are not thread safe, as they 172 * must be only called from the atomic commit path in the DRM driver, which 173 * is properly serialized. 174 */ 175 static int ipu_prg_ipu_to_prg_chan(int ipu_chan) 176 { 177 /* 178 * This isn't clearly documented in the RM, but IPU to PRG channel 179 * assignment is fixed, as only with this mapping the control signals 180 * match up. 181 */ 182 switch (ipu_chan) { 183 case IPUV3_CHANNEL_MEM_BG_SYNC: 184 return 0; 185 case IPUV3_CHANNEL_MEM_FG_SYNC: 186 return 1; 187 case IPUV3_CHANNEL_MEM_DC_SYNC: 188 return 2; 189 default: 190 return -EINVAL; 191 } 192 } 193 194 static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan) 195 { 196 int i, ret; 197 198 /* channel 0 is special as it is hardwired to one of the PREs */ 199 if (prg_chan == 0) { 200 ret = ipu_pre_get(prg->pres[0]); 201 if (ret) 202 goto fail; 203 prg->chan[prg_chan].used_pre = 0; 204 return 0; 205 } 206 207 for (i = 1; i < 3; i++) { 208 ret = ipu_pre_get(prg->pres[i]); 209 if (!ret) { 210 u32 val, mux; 211 int shift; 212 213 prg->chan[prg_chan].used_pre = i; 214 215 /* configure the PRE to PRG channel mux */ 216 shift = (i == 1) ? 12 : 14; 217 mux = (prg->id << 1) | (prg_chan - 1); 218 regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5, 219 0x3 << shift, mux << shift); 220 221 /* check other mux, must not point to same channel */ 222 shift = (i == 1) ? 14 : 12; 223 regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val); 224 if (((val >> shift) & 0x3) == mux) { 225 regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5, 226 0x3 << shift, 227 (mux ^ 0x1) << shift); 228 } 229 230 return 0; 231 } 232 } 233 234 fail: 235 dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan); 236 return ret; 237 } 238 239 static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan) 240 { 241 struct ipu_prg_channel *chan = &prg->chan[prg_chan]; 242 243 ipu_pre_put(prg->pres[chan->used_pre]); 244 chan->used_pre = -1; 245 } 246 247 void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan) 248 { 249 int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); 250 struct ipu_prg *prg = ipu_chan->ipu->prg_priv; 251 struct ipu_prg_channel *chan = &prg->chan[prg_chan]; 252 u32 val; 253 254 if (!chan->enabled || prg_chan < 0) 255 return; 256 257 clk_prepare_enable(prg->clk_ipg); 258 259 val = readl(prg->regs + IPU_PRG_CTL); 260 val |= IPU_PRG_CTL_BYPASS(prg_chan); 261 writel(val, prg->regs + IPU_PRG_CTL); 262 263 val = IPU_PRG_REG_UPDATE_REG_UPDATE; 264 writel(val, prg->regs + IPU_PRG_REG_UPDATE); 265 266 clk_disable_unprepare(prg->clk_ipg); 267 268 ipu_prg_put_pre(prg, prg_chan); 269 270 chan->enabled = false; 271 } 272 EXPORT_SYMBOL_GPL(ipu_prg_channel_disable); 273 274 int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan, 275 unsigned int axi_id, unsigned int width, 276 unsigned int height, unsigned int stride, 277 u32 format, unsigned long *eba) 278 { 279 int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); 280 struct ipu_prg *prg = ipu_chan->ipu->prg_priv; 281 struct ipu_prg_channel *chan = &prg->chan[prg_chan]; 282 u32 val; 283 int ret; 284 285 if (prg_chan < 0) 286 return prg_chan; 287 288 if (chan->enabled) { 289 ipu_pre_update(prg->pres[chan->used_pre], *eba); 290 return 0; 291 } 292 293 ret = ipu_prg_get_pre(prg, prg_chan); 294 if (ret) 295 return ret; 296 297 ipu_pre_configure(prg->pres[chan->used_pre], 298 width, height, stride, format, *eba); 299 300 301 ret = clk_prepare_enable(prg->clk_ipg); 302 if (ret) { 303 ipu_prg_put_pre(prg, prg_chan); 304 return ret; 305 } 306 307 val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK; 308 writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan)); 309 310 val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) << 311 IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) | 312 ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) << 313 IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT); 314 writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan)); 315 316 val = ipu_pre_get_baddr(prg->pres[chan->used_pre]); 317 *eba = val; 318 writel(val, prg->regs + IPU_PRG_BADDR(prg_chan)); 319 320 val = readl(prg->regs + IPU_PRG_CTL); 321 /* config AXI ID */ 322 val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK << 323 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan)); 324 val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id); 325 /* enable channel */ 326 val &= ~IPU_PRG_CTL_BYPASS(prg_chan); 327 writel(val, prg->regs + IPU_PRG_CTL); 328 329 val = IPU_PRG_REG_UPDATE_REG_UPDATE; 330 writel(val, prg->regs + IPU_PRG_REG_UPDATE); 331 332 clk_disable_unprepare(prg->clk_ipg); 333 334 chan->enabled = true; 335 return 0; 336 } 337 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure); 338 339 static int ipu_prg_probe(struct platform_device *pdev) 340 { 341 struct device *dev = &pdev->dev; 342 struct resource *res; 343 struct ipu_prg *prg; 344 u32 val; 345 int i, ret; 346 347 prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL); 348 if (!prg) 349 return -ENOMEM; 350 351 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 352 prg->regs = devm_ioremap_resource(&pdev->dev, res); 353 if (IS_ERR(prg->regs)) 354 return PTR_ERR(prg->regs); 355 356 357 prg->clk_ipg = devm_clk_get(dev, "ipg"); 358 if (IS_ERR(prg->clk_ipg)) 359 return PTR_ERR(prg->clk_ipg); 360 361 prg->clk_axi = devm_clk_get(dev, "axi"); 362 if (IS_ERR(prg->clk_axi)) 363 return PTR_ERR(prg->clk_axi); 364 365 prg->iomuxc_gpr = 366 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); 367 if (IS_ERR(prg->iomuxc_gpr)) 368 return PTR_ERR(prg->iomuxc_gpr); 369 370 for (i = 0; i < 3; i++) { 371 prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i); 372 if (!prg->pres[i]) 373 return -EPROBE_DEFER; 374 } 375 376 ret = clk_prepare_enable(prg->clk_ipg); 377 if (ret) 378 return ret; 379 380 /* init to free running mode */ 381 val = readl(prg->regs + IPU_PRG_CTL); 382 val |= IPU_PRG_CTL_SHADOW_EN; 383 writel(val, prg->regs + IPU_PRG_CTL); 384 385 /* disable address threshold */ 386 writel(0xffffffff, prg->regs + IPU_PRG_THD); 387 388 clk_disable_unprepare(prg->clk_ipg); 389 390 prg->dev = dev; 391 platform_set_drvdata(pdev, prg); 392 mutex_lock(&ipu_prg_list_mutex); 393 list_add(&prg->list, &ipu_prg_list); 394 mutex_unlock(&ipu_prg_list_mutex); 395 396 return 0; 397 } 398 399 static int ipu_prg_remove(struct platform_device *pdev) 400 { 401 struct ipu_prg *prg = platform_get_drvdata(pdev); 402 403 mutex_lock(&ipu_prg_list_mutex); 404 list_del(&prg->list); 405 mutex_unlock(&ipu_prg_list_mutex); 406 407 return 0; 408 } 409 410 static const struct of_device_id ipu_prg_dt_ids[] = { 411 { .compatible = "fsl,imx6qp-prg", }, 412 { /* sentinel */ }, 413 }; 414 415 struct platform_driver ipu_prg_drv = { 416 .probe = ipu_prg_probe, 417 .remove = ipu_prg_remove, 418 .driver = { 419 .name = "imx-ipu-prg", 420 .of_match_table = ipu_prg_dt_ids, 421 }, 422 }; 423