106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark/* 206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * Copyright (C) 2013 Red Hat 306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * Author: Rob Clark <robdclark@gmail.com> 406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * 506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * This program is free software; you can redistribute it and/or modify it 606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * under the terms of the GNU General Public License version 2 as published by 706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * the Free Software Foundation. 806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * 906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 1006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * more details. 1306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * 1406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * You should have received a copy of the GNU General Public License along with 1506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 1606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark */ 1706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 1806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 1906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark#include "msm_drv.h" 2006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark#include "msm_mmu.h" 2106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark#include "mdp5_kms.h" 2206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 2387e956e9be0cdb832e90a4731b620286a8826842Stephane Viaustatic const char *iommu_ports[] = { 2487e956e9be0cdb832e90a4731b620286a8826842Stephane Viau "mdp_0", 2587e956e9be0cdb832e90a4731b620286a8826842Stephane Viau}; 2687e956e9be0cdb832e90a4731b620286a8826842Stephane Viau 2706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstatic struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev); 2806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 293d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viauconst struct mdp5_config *mdp5_cfg; 303d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 313d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viaustatic const struct mdp5_config msm8x74_config = { 323d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .name = "msm8x74", 333d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .ctl = { 343d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 5, 353d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, 363d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 373d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .pipe_vig = { 383d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 3, 393d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x01200, 0x01600, 0x01a00 }, 403d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 413d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .pipe_rgb = { 423d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 3, 433d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x01e00, 0x02200, 0x02600 }, 443d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 453d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .pipe_dma = { 463d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 2, 473d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x02a00, 0x02e00 }, 483d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 493d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .lm = { 503d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 5, 513d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x03200, 0x03600, 0x03a00, 0x03e00, 0x04200 }, 523d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 533d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .dspp = { 543d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 3, 553d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x04600, 0x04a00, 0x04e00 }, 563d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 573d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .ad = { 583d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 2, 593d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x13100, 0x13300 }, /* NOTE: no ad in v1.0 */ 603d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 613d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .intf = { 623d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 4, 633d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x12500, 0x12700, 0x12900, 0x12b00 }, 643d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 653d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau}; 663d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 673d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viaustatic const struct mdp5_config apq8084_config = { 683d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .name = "apq8084", 693d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .ctl = { 703d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 5, 713d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, 723d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 733d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .pipe_vig = { 743d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 4, 753d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 }, 763d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 773d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .pipe_rgb = { 783d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 4, 793d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x02200, 0x02600, 0x02a00, 0x02e00 }, 803d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 813d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .pipe_dma = { 823d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 2, 833d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x03200, 0x03600 }, 843d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 853d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .lm = { 863d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 6, 873d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x03a00, 0x03e00, 0x04200, 0x04600, 0x04a00, 0x04e00 }, 883d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 893d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .dspp = { 903d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 4, 913d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x05200, 0x05600, 0x05a00, 0x05e00 }, 923d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 933d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 943d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .ad = { 953d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 3, 963d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x13500, 0x13700, 0x13900 }, 973d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 983d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .intf = { 993d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .count = 5, 1003d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau .base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 }, 1013d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau }, 1023d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau}; 1033d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 1043d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viaustruct mdp5_config_entry { 1053d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau int revision; 1063d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau const struct mdp5_config *config; 1073d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau}; 1083d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 1093d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viaustatic const struct mdp5_config_entry mdp5_configs[] = { 1103d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau { .revision = 0, .config = &msm8x74_config }, 1113d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau { .revision = 2, .config = &msm8x74_config }, 1123d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau { .revision = 3, .config = &apq8084_config }, 1133d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau}; 1143d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 1153d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viaustatic int mdp5_select_hw_cfg(struct msm_kms *kms) 11606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 11706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); 11806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct drm_device *dev = mdp5_kms->dev; 11906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark uint32_t version, major, minor; 1203d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau int i, ret = 0; 12106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 12206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_enable(mdp5_kms); 12306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark version = mdp5_read(mdp5_kms, REG_MDP5_MDP_VERSION); 12406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_disable(mdp5_kms); 12506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 12606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark major = FIELD(version, MDP5_MDP_VERSION_MAJOR); 12706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark minor = FIELD(version, MDP5_MDP_VERSION_MINOR); 12806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 12906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark DBG("found MDP5 version v%d.%d", major, minor); 13006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 1313d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau if (major != 1) { 1323d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n", 13306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark major, minor); 13406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = -ENXIO; 13506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto out; 13606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 13706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 13806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms->rev = minor; 13906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 1403d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau /* only after mdp5_cfg global pointer's init can we access the hw */ 1413d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau for (i = 0; i < ARRAY_SIZE(mdp5_configs); i++) { 1423d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau if (mdp5_configs[i].revision != minor) 1433d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau continue; 1443d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau mdp5_kms->hw_cfg = mdp5_cfg = mdp5_configs[i].config; 1453d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau break; 1463d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau } 1473d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau if (unlikely(!mdp5_kms->hw_cfg)) { 1483d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n", 1493d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau major, minor); 1503d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau ret = -ENXIO; 1513d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau goto out; 1523d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau } 1533d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 1543d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau DBG("MDP5: %s config selected", mdp5_kms->hw_cfg->name); 1553d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 1563d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau return 0; 1573d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viauout: 1583d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau return ret; 1593d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau} 1603d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 1613d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viaustatic int mdp5_hw_init(struct msm_kms *kms) 1623d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau{ 1633d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); 1643d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau struct drm_device *dev = mdp5_kms->dev; 1653d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau int i; 1663d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 1673d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau pm_runtime_get_sync(dev->dev); 1683d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 16906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark /* Magic unknown register writes: 17006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * 17106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W VBIF:0x004 00000001 (mdss_mdp.c:839) 17206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W MDP5:0x2e0 0xe9 (mdss_mdp.c:839) 17306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W MDP5:0x2e4 0x55 (mdss_mdp.c:839) 17406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W MDP5:0x3ac 0xc0000ccc (mdss_mdp.c:839) 17506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W MDP5:0x3b4 0xc0000ccc (mdss_mdp.c:839) 17606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W MDP5:0x3bc 0xcccccc (mdss_mdp.c:839) 17706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W MDP5:0x4a8 0xcccc0c0 (mdss_mdp.c:839) 17806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W MDP5:0x4b0 0xccccc0c0 (mdss_mdp.c:839) 17906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * W MDP5:0x4b8 0xccccc000 (mdss_mdp.c:839) 18006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * 18106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * Downstream fbdev driver gets these register offsets/values 18206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * from DT.. not really sure what these registers are or if 18306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * different values for different boards/SoC's, etc. I guess 18406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * they are the golden registers. 18506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * 18606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * Not setting these does not seem to cause any problem. But 18706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * we may be getting lucky with the bootloader initializing 18806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * them for us. OTOH, if we can always count on the bootloader 18906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * setting the golden registers, then perhaps we don't need to 19006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * care. 19106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark */ 19206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 19306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, 0); 19406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 1953d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau for (i = 0; i < mdp5_kms->hw_cfg->ctl.count; i++) 1963d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(i), 0); 1973d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 19806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark pm_runtime_put_sync(dev->dev); 19906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 2003d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau return 0; 20106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 20206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 20306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstatic long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate, 20406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct drm_encoder *encoder) 20506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 20606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return rate; 20706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 20806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 20906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstatic void mdp5_preclose(struct msm_kms *kms, struct drm_file *file) 21006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 21106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); 21206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct msm_drm_private *priv = mdp5_kms->dev->dev_private; 21306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark unsigned i; 21406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 21506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark for (i = 0; i < priv->num_crtcs; i++) 21606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_crtc_cancel_pending_flip(priv->crtcs[i], file); 21706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 21806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 21906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstatic void mdp5_destroy(struct msm_kms *kms) 22006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 22106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); 22287e956e9be0cdb832e90a4731b620286a8826842Stephane Viau struct msm_mmu *mmu = mdp5_kms->mmu; 22387e956e9be0cdb832e90a4731b620286a8826842Stephane Viau 22487e956e9be0cdb832e90a4731b620286a8826842Stephane Viau if (mmu) { 22587e956e9be0cdb832e90a4731b620286a8826842Stephane Viau mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports)); 22687e956e9be0cdb832e90a4731b620286a8826842Stephane Viau mmu->funcs->destroy(mmu); 22787e956e9be0cdb832e90a4731b620286a8826842Stephane Viau } 22806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark kfree(mdp5_kms); 22906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 23006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 23106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstatic const struct mdp_kms_funcs kms_funcs = { 23206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .base = { 23306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .hw_init = mdp5_hw_init, 23406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .irq_preinstall = mdp5_irq_preinstall, 23506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .irq_postinstall = mdp5_irq_postinstall, 23606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .irq_uninstall = mdp5_irq_uninstall, 23706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .irq = mdp5_irq, 23806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .enable_vblank = mdp5_enable_vblank, 23906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .disable_vblank = mdp5_disable_vblank, 24006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .get_format = mdp_get_format, 24106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .round_pixclk = mdp5_round_pixclk, 24206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .preclose = mdp5_preclose, 24306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .destroy = mdp5_destroy, 24406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark }, 24506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark .set_irqmask = mdp5_set_irqmask, 24606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark}; 24706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 24806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkint mdp5_disable(struct mdp5_kms *mdp5_kms) 24906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 25006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark DBG(""); 25106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 25206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark clk_disable_unprepare(mdp5_kms->ahb_clk); 25306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark clk_disable_unprepare(mdp5_kms->axi_clk); 25406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark clk_disable_unprepare(mdp5_kms->core_clk); 25506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark clk_disable_unprepare(mdp5_kms->lut_clk); 25606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 25706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return 0; 25806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 25906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 26006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkint mdp5_enable(struct mdp5_kms *mdp5_kms) 26106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 26206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark DBG(""); 26306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 26406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark clk_prepare_enable(mdp5_kms->ahb_clk); 26506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark clk_prepare_enable(mdp5_kms->axi_clk); 26606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark clk_prepare_enable(mdp5_kms->core_clk); 26706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark clk_prepare_enable(mdp5_kms->lut_clk); 26806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 26906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return 0; 27006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 27106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 27206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstatic int modeset_init(struct mdp5_kms *mdp5_kms) 27306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 27406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark static const enum mdp5_pipe crtcs[] = { 2753d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3, 27606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark }; 27706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct drm_device *dev = mdp5_kms->dev; 27806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct msm_drm_private *priv = dev->dev_private; 27906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct drm_encoder *encoder; 28006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark int i, ret; 28106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 28206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark /* construct CRTCs: */ 2833d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau for (i = 0; i < mdp5_kms->hw_cfg->pipe_rgb.count; i++) { 28406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct drm_plane *plane; 28506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct drm_crtc *crtc; 28606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 28706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark plane = mdp5_plane_init(dev, crtcs[i], true); 28806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(plane)) { 28906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = PTR_ERR(plane); 29006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev->dev, "failed to construct plane for %s (%d)\n", 29106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark pipe2name(crtcs[i]), ret); 29206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 29306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 29406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 29506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark crtc = mdp5_crtc_init(dev, plane, i); 29606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(crtc)) { 29706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = PTR_ERR(crtc); 29806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev->dev, "failed to construct crtc for %s (%d)\n", 29906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark pipe2name(crtcs[i]), ret); 30006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 30106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 30206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark priv->crtcs[priv->num_crtcs++] = crtc; 30306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 30406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 30506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark /* Construct encoder for HDMI: */ 30606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark encoder = mdp5_encoder_init(dev, 3, INTF_HDMI); 30706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(encoder)) { 30806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev->dev, "failed to construct encoder\n"); 30906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = PTR_ERR(encoder); 31006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 31106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 31206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 31306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark /* NOTE: the vsync and error irq's are actually associated with 31406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * the INTF/encoder.. the easiest way to deal with this (ie. what 31506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * we do now) is assume a fixed relationship between crtc's and 31606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * encoders. I'm not sure if there is ever a need to more freely 31706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * assign crtcs to encoders, but if there is then we need to take 31806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * care of error and vblank irq's that the crtc has registered, 31906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * and also update user-requested vblank_mask. 32006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark */ 32106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark encoder->possible_crtcs = BIT(0); 32206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_crtc_set_intf(priv->crtcs[0], 3, INTF_HDMI); 32306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 32406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark priv->encoders[priv->num_encoders++] = encoder; 32506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 32606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark /* Construct bridge/connector for HDMI: */ 32706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms->hdmi = hdmi_init(dev, encoder); 32806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(mdp5_kms->hdmi)) { 32906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = PTR_ERR(mdp5_kms->hdmi); 33006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret); 33106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 33206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 33306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 33406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return 0; 33506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 33606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkfail: 33706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return ret; 33806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 33906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 34006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstatic int get_clk(struct platform_device *pdev, struct clk **clkp, 34106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark const char *name) 34206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 34306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct device *dev = &pdev->dev; 34406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct clk *clk = devm_clk_get(dev, name); 34506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(clk)) { 34606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk)); 34706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return PTR_ERR(clk); 34806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 34906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark *clkp = clk; 35006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return 0; 35106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 35206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 35306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstruct msm_kms *mdp5_kms_init(struct drm_device *dev) 35406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 35506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct platform_device *pdev = dev->platformdev; 35606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct mdp5_platform_config *config = mdp5_get_config(pdev); 35706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct mdp5_kms *mdp5_kms; 35806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct msm_kms *kms = NULL; 35906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark struct msm_mmu *mmu; 3603d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau int i, ret; 36106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 36206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms = kzalloc(sizeof(*mdp5_kms), GFP_KERNEL); 36306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (!mdp5_kms) { 36406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev->dev, "failed to allocate kms\n"); 36506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = -ENOMEM; 36606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 36706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 36806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 36906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp_kms_init(&mdp5_kms->base, &kms_funcs); 37006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 37106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark kms = &mdp5_kms->base.base; 37206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 37306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms->dev = dev; 37406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms->smp_blk_cnt = config->smp_blk_cnt; 37506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 37606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5"); 37706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(mdp5_kms->mmio)) { 37806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = PTR_ERR(mdp5_kms->mmio); 37906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 38006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 38106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 38206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); 38306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(mdp5_kms->vbif)) { 38406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = PTR_ERR(mdp5_kms->vbif); 38506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 38606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 38706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 38806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms->vdd = devm_regulator_get(&pdev->dev, "vdd"); 38906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(mdp5_kms->vdd)) { 39006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = PTR_ERR(mdp5_kms->vdd); 39106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 39206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 39306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 39406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = regulator_enable(mdp5_kms->vdd); 39506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (ret) { 39606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); 39706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 39806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 39906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 400a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk"); 401a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark if (ret) 402a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark goto fail; 403a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk"); 404a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark if (ret) 405a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark goto fail; 406a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark ret = get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src"); 407a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark if (ret) 408a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark goto fail; 409a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark ret = get_clk(pdev, &mdp5_kms->core_clk, "core_clk"); 410a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark if (ret) 411a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark goto fail; 412a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark ret = get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk"); 413a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark if (ret) 414a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark goto fail; 415a0906a023b02366b57eae71c5b9b542d9dd51e4cRob Clark ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk"); 41606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (ret) 41706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 41806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 41906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = clk_set_rate(mdp5_kms->src_clk, config->max_clk); 42006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 4213d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau ret = mdp5_select_hw_cfg(kms); 4223d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau if (ret) 4233d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau goto fail; 4243d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau 42506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark /* make sure things are off before attaching iommu (bootloader could 42606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * have left things on, in which case we'll start getting faults if 42706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark * we don't disable): 42806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark */ 42906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_enable(mdp5_kms); 4303d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau for (i = 0; i < mdp5_kms->hw_cfg->intf.count; i++) 4313d47fd47f28903f5a9167e95f32a906bd53e13e6Stephane Viau mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0); 43206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_disable(mdp5_kms); 43306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdelay(16); 43406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 43506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (config->iommu) { 436944fc36c31ed685cf8d3d125eb681ae7198f06fcRob Clark mmu = msm_iommu_new(&pdev->dev, config->iommu); 43706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (IS_ERR(mmu)) { 43806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = PTR_ERR(mmu); 43987e956e9be0cdb832e90a4731b620286a8826842Stephane Viau dev_err(dev->dev, "failed to init iommu: %d\n", ret); 44006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 44106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 44287e956e9be0cdb832e90a4731b620286a8826842Stephane Viau 44306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = mmu->funcs->attach(mmu, iommu_ports, 44406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ARRAY_SIZE(iommu_ports)); 44587e956e9be0cdb832e90a4731b620286a8826842Stephane Viau if (ret) { 44687e956e9be0cdb832e90a4731b620286a8826842Stephane Viau dev_err(dev->dev, "failed to attach iommu: %d\n", ret); 44787e956e9be0cdb832e90a4731b620286a8826842Stephane Viau mmu->funcs->destroy(mmu); 44806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 44987e956e9be0cdb832e90a4731b620286a8826842Stephane Viau } 45006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } else { 45106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_info(dev->dev, "no iommu, fallback to phys " 45206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark "contig buffers for scanout\n"); 45306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mmu = NULL; 45406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 45587e956e9be0cdb832e90a4731b620286a8826842Stephane Viau mdp5_kms->mmu = mmu; 45606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 45706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_kms->id = msm_register_mmu(dev, mmu); 45806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (mdp5_kms->id < 0) { 45906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = mdp5_kms->id; 46006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev->dev, "failed to register mdp5 iommu: %d\n", ret); 46106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 46206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 46306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 46406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark ret = modeset_init(mdp5_kms); 46506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (ret) { 46606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark dev_err(dev->dev, "modeset_init failed: %d\n", ret); 46706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark goto fail; 46806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark } 46906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 47006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return kms; 47106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 47206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkfail: 47306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark if (kms) 47406c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark mdp5_destroy(kms); 47506c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return ERR_PTR(ret); 47606c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 47706c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark 47806c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clarkstatic struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev) 47906c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark{ 48006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark static struct mdp5_platform_config config = {}; 48106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark#ifdef CONFIG_OF 48206c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark /* TODO */ 48306c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark#endif 4843bf6c1ecaecba6290afa6db23155cd8b9865fd6aStephane Viau config.iommu = iommu_domain_alloc(&platform_bus_type); 4853bf6c1ecaecba6290afa6db23155cd8b9865fd6aStephane Viau /* TODO hard-coded in downstream mdss, but should it be? */ 4863bf6c1ecaecba6290afa6db23155cd8b9865fd6aStephane Viau config.max_clk = 200000000; 4873bf6c1ecaecba6290afa6db23155cd8b9865fd6aStephane Viau /* TODO get from DT: */ 4883bf6c1ecaecba6290afa6db23155cd8b9865fd6aStephane Viau config.smp_blk_cnt = 22; 4893bf6c1ecaecba6290afa6db23155cd8b9865fd6aStephane Viau 49006c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark return &config; 49106c0dd96bfbba8a9368ffd7c4b12d3bfed37001dRob Clark} 492