1/* 2 * Copyright (C) 2013 Red Hat 3 * Author: Rob Clark <robdclark@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 as published by 7 * the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 19#include "msm_drv.h" 20#include "msm_mmu.h" 21#include "mdp4_kms.h" 22 23static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev); 24 25static int mdp4_hw_init(struct msm_kms *kms) 26{ 27 struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); 28 struct drm_device *dev = mdp4_kms->dev; 29 uint32_t version, major, minor, dmap_cfg, vg_cfg; 30 unsigned long clk; 31 int ret = 0; 32 33 pm_runtime_get_sync(dev->dev); 34 35 mdp4_enable(mdp4_kms); 36 version = mdp4_read(mdp4_kms, REG_MDP4_VERSION); 37 mdp4_disable(mdp4_kms); 38 39 major = FIELD(version, MDP4_VERSION_MAJOR); 40 minor = FIELD(version, MDP4_VERSION_MINOR); 41 42 DBG("found MDP4 version v%d.%d", major, minor); 43 44 if (major != 4) { 45 dev_err(dev->dev, "unexpected MDP version: v%d.%d\n", 46 major, minor); 47 ret = -ENXIO; 48 goto out; 49 } 50 51 mdp4_kms->rev = minor; 52 53 if (mdp4_kms->dsi_pll_vdda) { 54 if ((mdp4_kms->rev == 2) || (mdp4_kms->rev == 4)) { 55 ret = regulator_set_voltage(mdp4_kms->dsi_pll_vdda, 56 1200000, 1200000); 57 if (ret) { 58 dev_err(dev->dev, 59 "failed to set dsi_pll_vdda voltage: %d\n", ret); 60 goto out; 61 } 62 } 63 } 64 65 if (mdp4_kms->dsi_pll_vddio) { 66 if (mdp4_kms->rev == 2) { 67 ret = regulator_set_voltage(mdp4_kms->dsi_pll_vddio, 68 1800000, 1800000); 69 if (ret) { 70 dev_err(dev->dev, 71 "failed to set dsi_pll_vddio voltage: %d\n", ret); 72 goto out; 73 } 74 } 75 } 76 77 if (mdp4_kms->rev > 1) { 78 mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER0, 0x0707ffff); 79 mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER1, 0x03073f3f); 80 } 81 82 mdp4_write(mdp4_kms, REG_MDP4_PORTMAP_MODE, 0x3); 83 84 /* max read pending cmd config, 3 pending requests: */ 85 mdp4_write(mdp4_kms, REG_MDP4_READ_CNFG, 0x02222); 86 87 clk = clk_get_rate(mdp4_kms->clk); 88 89 if ((mdp4_kms->rev >= 1) || (clk >= 90000000)) { 90 dmap_cfg = 0x47; /* 16 bytes-burst x 8 req */ 91 vg_cfg = 0x47; /* 16 bytes-burs x 8 req */ 92 } else { 93 dmap_cfg = 0x27; /* 8 bytes-burst x 8 req */ 94 vg_cfg = 0x43; /* 16 bytes-burst x 4 req */ 95 } 96 97 DBG("fetch config: dmap=%02x, vg=%02x", dmap_cfg, vg_cfg); 98 99 mdp4_write(mdp4_kms, REG_MDP4_DMA_FETCH_CONFIG(DMA_P), dmap_cfg); 100 mdp4_write(mdp4_kms, REG_MDP4_DMA_FETCH_CONFIG(DMA_E), dmap_cfg); 101 102 mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(VG1), vg_cfg); 103 mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(VG2), vg_cfg); 104 mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(RGB1), vg_cfg); 105 mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(RGB2), vg_cfg); 106 107 if (mdp4_kms->rev >= 2) 108 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG_UPDATE_METHOD, 1); 109 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, 0); 110 111 /* disable CSC matrix / YUV by default: */ 112 mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(VG1), 0); 113 mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(VG2), 0); 114 mdp4_write(mdp4_kms, REG_MDP4_DMA_P_OP_MODE, 0); 115 mdp4_write(mdp4_kms, REG_MDP4_DMA_S_OP_MODE, 0); 116 mdp4_write(mdp4_kms, REG_MDP4_OVLP_CSC_CONFIG(1), 0); 117 mdp4_write(mdp4_kms, REG_MDP4_OVLP_CSC_CONFIG(2), 0); 118 119 if (mdp4_kms->rev > 1) 120 mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1); 121 122out: 123 pm_runtime_put_sync(dev->dev); 124 125 return ret; 126} 127 128static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate, 129 struct drm_encoder *encoder) 130{ 131 /* if we had >1 encoder, we'd need something more clever: */ 132 return mdp4_dtv_round_pixclk(encoder, rate); 133} 134 135static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file) 136{ 137 struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); 138 struct msm_drm_private *priv = mdp4_kms->dev->dev_private; 139 unsigned i; 140 141 for (i = 0; i < priv->num_crtcs; i++) 142 mdp4_crtc_cancel_pending_flip(priv->crtcs[i], file); 143} 144 145static void mdp4_destroy(struct msm_kms *kms) 146{ 147 struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); 148 if (mdp4_kms->blank_cursor_iova) 149 msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id); 150 if (mdp4_kms->blank_cursor_bo) 151 drm_gem_object_unreference_unlocked(mdp4_kms->blank_cursor_bo); 152 kfree(mdp4_kms); 153} 154 155static const struct mdp_kms_funcs kms_funcs = { 156 .base = { 157 .hw_init = mdp4_hw_init, 158 .irq_preinstall = mdp4_irq_preinstall, 159 .irq_postinstall = mdp4_irq_postinstall, 160 .irq_uninstall = mdp4_irq_uninstall, 161 .irq = mdp4_irq, 162 .enable_vblank = mdp4_enable_vblank, 163 .disable_vblank = mdp4_disable_vblank, 164 .get_format = mdp_get_format, 165 .round_pixclk = mdp4_round_pixclk, 166 .preclose = mdp4_preclose, 167 .destroy = mdp4_destroy, 168 }, 169 .set_irqmask = mdp4_set_irqmask, 170}; 171 172int mdp4_disable(struct mdp4_kms *mdp4_kms) 173{ 174 DBG(""); 175 176 clk_disable_unprepare(mdp4_kms->clk); 177 if (mdp4_kms->pclk) 178 clk_disable_unprepare(mdp4_kms->pclk); 179 clk_disable_unprepare(mdp4_kms->lut_clk); 180 if (mdp4_kms->axi_clk) 181 clk_disable_unprepare(mdp4_kms->axi_clk); 182 183 return 0; 184} 185 186int mdp4_enable(struct mdp4_kms *mdp4_kms) 187{ 188 DBG(""); 189 190 clk_prepare_enable(mdp4_kms->clk); 191 if (mdp4_kms->pclk) 192 clk_prepare_enable(mdp4_kms->pclk); 193 clk_prepare_enable(mdp4_kms->lut_clk); 194 if (mdp4_kms->axi_clk) 195 clk_prepare_enable(mdp4_kms->axi_clk); 196 197 return 0; 198} 199 200#ifdef CONFIG_OF 201static struct drm_panel *detect_panel(struct drm_device *dev, const char *name) 202{ 203 struct device_node *n; 204 struct drm_panel *panel = NULL; 205 206 n = of_parse_phandle(dev->dev->of_node, name, 0); 207 if (n) { 208 panel = of_drm_find_panel(n); 209 if (!panel) 210 panel = ERR_PTR(-EPROBE_DEFER); 211 } 212 213 return panel; 214} 215#else 216static struct drm_panel *detect_panel(struct drm_device *dev, const char *name) 217{ 218 // ??? maybe use a module param to specify which panel is attached? 219} 220#endif 221 222static int modeset_init(struct mdp4_kms *mdp4_kms) 223{ 224 struct drm_device *dev = mdp4_kms->dev; 225 struct msm_drm_private *priv = dev->dev_private; 226 struct drm_plane *plane; 227 struct drm_crtc *crtc; 228 struct drm_encoder *encoder; 229 struct drm_connector *connector; 230 struct drm_panel *panel; 231 struct hdmi *hdmi; 232 int ret; 233 234 /* construct non-private planes: */ 235 plane = mdp4_plane_init(dev, VG1, false); 236 if (IS_ERR(plane)) { 237 dev_err(dev->dev, "failed to construct plane for VG1\n"); 238 ret = PTR_ERR(plane); 239 goto fail; 240 } 241 priv->planes[priv->num_planes++] = plane; 242 243 plane = mdp4_plane_init(dev, VG2, false); 244 if (IS_ERR(plane)) { 245 dev_err(dev->dev, "failed to construct plane for VG2\n"); 246 ret = PTR_ERR(plane); 247 goto fail; 248 } 249 priv->planes[priv->num_planes++] = plane; 250 251 /* 252 * Setup the LCDC/LVDS path: RGB2 -> DMA_P -> LCDC -> LVDS: 253 */ 254 255 panel = detect_panel(dev, "qcom,lvds-panel"); 256 if (IS_ERR(panel)) { 257 ret = PTR_ERR(panel); 258 dev_err(dev->dev, "failed to detect LVDS panel: %d\n", ret); 259 goto fail; 260 } 261 262 plane = mdp4_plane_init(dev, RGB2, true); 263 if (IS_ERR(plane)) { 264 dev_err(dev->dev, "failed to construct plane for RGB2\n"); 265 ret = PTR_ERR(plane); 266 goto fail; 267 } 268 269 crtc = mdp4_crtc_init(dev, plane, priv->num_crtcs, 0, DMA_P); 270 if (IS_ERR(crtc)) { 271 dev_err(dev->dev, "failed to construct crtc for DMA_P\n"); 272 ret = PTR_ERR(crtc); 273 goto fail; 274 } 275 276 encoder = mdp4_lcdc_encoder_init(dev, panel); 277 if (IS_ERR(encoder)) { 278 dev_err(dev->dev, "failed to construct LCDC encoder\n"); 279 ret = PTR_ERR(encoder); 280 goto fail; 281 } 282 283 /* LCDC can be hooked to DMA_P: */ 284 encoder->possible_crtcs = 1 << priv->num_crtcs; 285 286 priv->crtcs[priv->num_crtcs++] = crtc; 287 priv->encoders[priv->num_encoders++] = encoder; 288 289 connector = mdp4_lvds_connector_init(dev, panel, encoder); 290 if (IS_ERR(connector)) { 291 ret = PTR_ERR(connector); 292 dev_err(dev->dev, "failed to initialize LVDS connector: %d\n", ret); 293 goto fail; 294 } 295 296 priv->connectors[priv->num_connectors++] = connector; 297 298 /* 299 * Setup DTV/HDMI path: RGB1 -> DMA_E -> DTV -> HDMI: 300 */ 301 302 plane = mdp4_plane_init(dev, RGB1, true); 303 if (IS_ERR(plane)) { 304 dev_err(dev->dev, "failed to construct plane for RGB1\n"); 305 ret = PTR_ERR(plane); 306 goto fail; 307 } 308 309 crtc = mdp4_crtc_init(dev, plane, priv->num_crtcs, 1, DMA_E); 310 if (IS_ERR(crtc)) { 311 dev_err(dev->dev, "failed to construct crtc for DMA_E\n"); 312 ret = PTR_ERR(crtc); 313 goto fail; 314 } 315 316 encoder = mdp4_dtv_encoder_init(dev); 317 if (IS_ERR(encoder)) { 318 dev_err(dev->dev, "failed to construct DTV encoder\n"); 319 ret = PTR_ERR(encoder); 320 goto fail; 321 } 322 323 /* DTV can be hooked to DMA_E: */ 324 encoder->possible_crtcs = 1 << priv->num_crtcs; 325 326 priv->crtcs[priv->num_crtcs++] = crtc; 327 priv->encoders[priv->num_encoders++] = encoder; 328 329 hdmi = hdmi_init(dev, encoder); 330 if (IS_ERR(hdmi)) { 331 ret = PTR_ERR(hdmi); 332 dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret); 333 goto fail; 334 } 335 336 return 0; 337 338fail: 339 return ret; 340} 341 342static const char *iommu_ports[] = { 343 "mdp_port0_cb0", "mdp_port1_cb0", 344}; 345 346struct msm_kms *mdp4_kms_init(struct drm_device *dev) 347{ 348 struct platform_device *pdev = dev->platformdev; 349 struct mdp4_platform_config *config = mdp4_get_config(pdev); 350 struct mdp4_kms *mdp4_kms; 351 struct msm_kms *kms = NULL; 352 struct msm_mmu *mmu; 353 int ret; 354 355 mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL); 356 if (!mdp4_kms) { 357 dev_err(dev->dev, "failed to allocate kms\n"); 358 ret = -ENOMEM; 359 goto fail; 360 } 361 362 mdp_kms_init(&mdp4_kms->base, &kms_funcs); 363 364 kms = &mdp4_kms->base.base; 365 366 mdp4_kms->dev = dev; 367 368 mdp4_kms->mmio = msm_ioremap(pdev, NULL, "MDP4"); 369 if (IS_ERR(mdp4_kms->mmio)) { 370 ret = PTR_ERR(mdp4_kms->mmio); 371 goto fail; 372 } 373 374 mdp4_kms->dsi_pll_vdda = 375 devm_regulator_get_optional(&pdev->dev, "dsi_pll_vdda"); 376 if (IS_ERR(mdp4_kms->dsi_pll_vdda)) 377 mdp4_kms->dsi_pll_vdda = NULL; 378 379 mdp4_kms->dsi_pll_vddio = 380 devm_regulator_get_optional(&pdev->dev, "dsi_pll_vddio"); 381 if (IS_ERR(mdp4_kms->dsi_pll_vddio)) 382 mdp4_kms->dsi_pll_vddio = NULL; 383 384 mdp4_kms->vdd = devm_regulator_get_exclusive(&pdev->dev, "vdd"); 385 if (IS_ERR(mdp4_kms->vdd)) 386 mdp4_kms->vdd = NULL; 387 388 if (mdp4_kms->vdd) { 389 ret = regulator_enable(mdp4_kms->vdd); 390 if (ret) { 391 dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); 392 goto fail; 393 } 394 } 395 396 mdp4_kms->clk = devm_clk_get(&pdev->dev, "core_clk"); 397 if (IS_ERR(mdp4_kms->clk)) { 398 dev_err(dev->dev, "failed to get core_clk\n"); 399 ret = PTR_ERR(mdp4_kms->clk); 400 goto fail; 401 } 402 403 mdp4_kms->pclk = devm_clk_get(&pdev->dev, "iface_clk"); 404 if (IS_ERR(mdp4_kms->pclk)) 405 mdp4_kms->pclk = NULL; 406 407 // XXX if (rev >= MDP_REV_42) { ??? 408 mdp4_kms->lut_clk = devm_clk_get(&pdev->dev, "lut_clk"); 409 if (IS_ERR(mdp4_kms->lut_clk)) { 410 dev_err(dev->dev, "failed to get lut_clk\n"); 411 ret = PTR_ERR(mdp4_kms->lut_clk); 412 goto fail; 413 } 414 415 mdp4_kms->axi_clk = devm_clk_get(&pdev->dev, "mdp_axi_clk"); 416 if (IS_ERR(mdp4_kms->axi_clk)) { 417 dev_err(dev->dev, "failed to get axi_clk\n"); 418 ret = PTR_ERR(mdp4_kms->axi_clk); 419 goto fail; 420 } 421 422 clk_set_rate(mdp4_kms->clk, config->max_clk); 423 clk_set_rate(mdp4_kms->lut_clk, config->max_clk); 424 425 /* make sure things are off before attaching iommu (bootloader could 426 * have left things on, in which case we'll start getting faults if 427 * we don't disable): 428 */ 429 mdp4_enable(mdp4_kms); 430 mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0); 431 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); 432 mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0); 433 mdp4_disable(mdp4_kms); 434 mdelay(16); 435 436 if (config->iommu) { 437 mmu = msm_iommu_new(&pdev->dev, config->iommu); 438 if (IS_ERR(mmu)) { 439 ret = PTR_ERR(mmu); 440 goto fail; 441 } 442 ret = mmu->funcs->attach(mmu, iommu_ports, 443 ARRAY_SIZE(iommu_ports)); 444 if (ret) 445 goto fail; 446 } else { 447 dev_info(dev->dev, "no iommu, fallback to phys " 448 "contig buffers for scanout\n"); 449 mmu = NULL; 450 } 451 452 mdp4_kms->id = msm_register_mmu(dev, mmu); 453 if (mdp4_kms->id < 0) { 454 ret = mdp4_kms->id; 455 dev_err(dev->dev, "failed to register mdp4 iommu: %d\n", ret); 456 goto fail; 457 } 458 459 ret = modeset_init(mdp4_kms); 460 if (ret) { 461 dev_err(dev->dev, "modeset_init failed: %d\n", ret); 462 goto fail; 463 } 464 465 mutex_lock(&dev->struct_mutex); 466 mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC); 467 mutex_unlock(&dev->struct_mutex); 468 if (IS_ERR(mdp4_kms->blank_cursor_bo)) { 469 ret = PTR_ERR(mdp4_kms->blank_cursor_bo); 470 dev_err(dev->dev, "could not allocate blank-cursor bo: %d\n", ret); 471 mdp4_kms->blank_cursor_bo = NULL; 472 goto fail; 473 } 474 475 ret = msm_gem_get_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id, 476 &mdp4_kms->blank_cursor_iova); 477 if (ret) { 478 dev_err(dev->dev, "could not pin blank-cursor bo: %d\n", ret); 479 goto fail; 480 } 481 482 return kms; 483 484fail: 485 if (kms) 486 mdp4_destroy(kms); 487 return ERR_PTR(ret); 488} 489 490static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev) 491{ 492 static struct mdp4_platform_config config = {}; 493#ifdef CONFIG_OF 494 /* TODO */ 495 config.max_clk = 266667000; 496 config.iommu = iommu_domain_alloc(&platform_bus_type); 497#else 498 if (cpu_is_apq8064()) 499 config.max_clk = 266667000; 500 else 501 config.max_clk = 200000000; 502 503 config.iommu = msm_get_iommu_domain(DISPLAY_READ_DOMAIN); 504#endif 505 return &config; 506} 507