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