mdp5_cfg.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
  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 and
  6. * only version 2 as 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. #include "mdp5_kms.h"
  14. #include "mdp5_cfg.h"
  15. struct mdp5_cfg_handler {
  16. int revision;
  17. struct mdp5_cfg config;
  18. };
  19. /* mdp5_cfg must be exposed (used in mdp5.xml.h) */
  20. const struct mdp5_cfg_hw *mdp5_cfg = NULL;
  21. const struct mdp5_cfg_hw msm8x74v1_config = {
  22. .name = "msm8x74v1",
  23. .mdp = {
  24. .count = 1,
  25. .caps = MDP_CAP_SMP |
  26. 0,
  27. },
  28. .smp = {
  29. .mmb_count = 22,
  30. .mmb_size = 4096,
  31. .clients = {
  32. [SSPP_VIG0] = 1, [SSPP_VIG1] = 4, [SSPP_VIG2] = 7,
  33. [SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
  34. [SSPP_RGB0] = 16, [SSPP_RGB1] = 17, [SSPP_RGB2] = 18,
  35. },
  36. },
  37. .ctl = {
  38. .count = 5,
  39. .base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
  40. .flush_hw_mask = 0x0003ffff,
  41. },
  42. .pipe_vig = {
  43. .count = 3,
  44. .base = { 0x01100, 0x01500, 0x01900 },
  45. .caps = MDP_PIPE_CAP_HFLIP |
  46. MDP_PIPE_CAP_VFLIP |
  47. MDP_PIPE_CAP_SCALE |
  48. MDP_PIPE_CAP_CSC |
  49. 0,
  50. },
  51. .pipe_rgb = {
  52. .count = 3,
  53. .base = { 0x01d00, 0x02100, 0x02500 },
  54. .caps = MDP_PIPE_CAP_HFLIP |
  55. MDP_PIPE_CAP_VFLIP |
  56. MDP_PIPE_CAP_SCALE |
  57. 0,
  58. },
  59. .pipe_dma = {
  60. .count = 2,
  61. .base = { 0x02900, 0x02d00 },
  62. .caps = MDP_PIPE_CAP_HFLIP |
  63. MDP_PIPE_CAP_VFLIP |
  64. 0,
  65. },
  66. .lm = {
  67. .count = 5,
  68. .base = { 0x03100, 0x03500, 0x03900, 0x03d00, 0x04100 },
  69. .nb_stages = 5,
  70. },
  71. .dspp = {
  72. .count = 3,
  73. .base = { 0x04500, 0x04900, 0x04d00 },
  74. },
  75. .pp = {
  76. .count = 3,
  77. .base = { 0x21a00, 0x21b00, 0x21c00 },
  78. },
  79. .intf = {
  80. .base = { 0x21000, 0x21200, 0x21400, 0x21600 },
  81. .connect = {
  82. [0] = INTF_eDP,
  83. [1] = INTF_DSI,
  84. [2] = INTF_DSI,
  85. [3] = INTF_HDMI,
  86. },
  87. },
  88. .max_clk = 200000000,
  89. };
  90. const struct mdp5_cfg_hw msm8x74v2_config = {
  91. .name = "msm8x74",
  92. .mdp = {
  93. .count = 1,
  94. .caps = MDP_CAP_SMP |
  95. 0,
  96. },
  97. .smp = {
  98. .mmb_count = 22,
  99. .mmb_size = 4096,
  100. .clients = {
  101. [SSPP_VIG0] = 1, [SSPP_VIG1] = 4, [SSPP_VIG2] = 7,
  102. [SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
  103. [SSPP_RGB0] = 16, [SSPP_RGB1] = 17, [SSPP_RGB2] = 18,
  104. },
  105. },
  106. .ctl = {
  107. .count = 5,
  108. .base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
  109. .flush_hw_mask = 0x0003ffff,
  110. },
  111. .pipe_vig = {
  112. .count = 3,
  113. .base = { 0x01100, 0x01500, 0x01900 },
  114. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
  115. MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
  116. MDP_PIPE_CAP_DECIMATION,
  117. },
  118. .pipe_rgb = {
  119. .count = 3,
  120. .base = { 0x01d00, 0x02100, 0x02500 },
  121. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
  122. MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
  123. },
  124. .pipe_dma = {
  125. .count = 2,
  126. .base = { 0x02900, 0x02d00 },
  127. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
  128. },
  129. .lm = {
  130. .count = 5,
  131. .base = { 0x03100, 0x03500, 0x03900, 0x03d00, 0x04100 },
  132. .nb_stages = 5,
  133. .max_width = 2048,
  134. .max_height = 0xFFFF,
  135. },
  136. .dspp = {
  137. .count = 3,
  138. .base = { 0x04500, 0x04900, 0x04d00 },
  139. },
  140. .ad = {
  141. .count = 2,
  142. .base = { 0x13000, 0x13200 },
  143. },
  144. .pp = {
  145. .count = 3,
  146. .base = { 0x12c00, 0x12d00, 0x12e00 },
  147. },
  148. .intf = {
  149. .base = { 0x12400, 0x12600, 0x12800, 0x12a00 },
  150. .connect = {
  151. [0] = INTF_eDP,
  152. [1] = INTF_DSI,
  153. [2] = INTF_DSI,
  154. [3] = INTF_HDMI,
  155. },
  156. },
  157. .max_clk = 200000000,
  158. };
  159. const struct mdp5_cfg_hw apq8084_config = {
  160. .name = "apq8084",
  161. .mdp = {
  162. .count = 1,
  163. .caps = MDP_CAP_SMP |
  164. 0,
  165. },
  166. .smp = {
  167. .mmb_count = 44,
  168. .mmb_size = 8192,
  169. .clients = {
  170. [SSPP_VIG0] = 1, [SSPP_VIG1] = 4,
  171. [SSPP_VIG2] = 7, [SSPP_VIG3] = 19,
  172. [SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
  173. [SSPP_RGB0] = 16, [SSPP_RGB1] = 17,
  174. [SSPP_RGB2] = 18, [SSPP_RGB3] = 22,
  175. },
  176. .reserved_state[0] = GENMASK(7, 0), /* first 8 MMBs */
  177. .reserved = {
  178. /* Two SMP blocks are statically tied to RGB pipes: */
  179. [16] = 2, [17] = 2, [18] = 2, [22] = 2,
  180. },
  181. },
  182. .ctl = {
  183. .count = 5,
  184. .base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
  185. .flush_hw_mask = 0x003fffff,
  186. },
  187. .pipe_vig = {
  188. .count = 4,
  189. .base = { 0x01100, 0x01500, 0x01900, 0x01d00 },
  190. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
  191. MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
  192. MDP_PIPE_CAP_DECIMATION,
  193. },
  194. .pipe_rgb = {
  195. .count = 4,
  196. .base = { 0x02100, 0x02500, 0x02900, 0x02d00 },
  197. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
  198. MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
  199. },
  200. .pipe_dma = {
  201. .count = 2,
  202. .base = { 0x03100, 0x03500 },
  203. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
  204. },
  205. .lm = {
  206. .count = 6,
  207. .base = { 0x03900, 0x03d00, 0x04100, 0x04500, 0x04900, 0x04d00 },
  208. .nb_stages = 5,
  209. .max_width = 2048,
  210. .max_height = 0xFFFF,
  211. },
  212. .dspp = {
  213. .count = 4,
  214. .base = { 0x05100, 0x05500, 0x05900, 0x05d00 },
  215. },
  216. .ad = {
  217. .count = 3,
  218. .base = { 0x13400, 0x13600, 0x13800 },
  219. },
  220. .pp = {
  221. .count = 4,
  222. .base = { 0x12e00, 0x12f00, 0x13000, 0x13100 },
  223. },
  224. .intf = {
  225. .base = { 0x12400, 0x12600, 0x12800, 0x12a00, 0x12c00 },
  226. .connect = {
  227. [0] = INTF_eDP,
  228. [1] = INTF_DSI,
  229. [2] = INTF_DSI,
  230. [3] = INTF_HDMI,
  231. },
  232. },
  233. .max_clk = 320000000,
  234. };
  235. const struct mdp5_cfg_hw msm8x16_config = {
  236. .name = "msm8x16",
  237. .mdp = {
  238. .count = 1,
  239. .base = { 0x0 },
  240. .caps = MDP_CAP_SMP |
  241. 0,
  242. },
  243. .smp = {
  244. .mmb_count = 8,
  245. .mmb_size = 8192,
  246. .clients = {
  247. [SSPP_VIG0] = 1, [SSPP_DMA0] = 4,
  248. [SSPP_RGB0] = 7, [SSPP_RGB1] = 8,
  249. },
  250. },
  251. .ctl = {
  252. .count = 5,
  253. .base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
  254. .flush_hw_mask = 0x4003ffff,
  255. },
  256. .pipe_vig = {
  257. .count = 1,
  258. .base = { 0x04000 },
  259. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
  260. MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
  261. MDP_PIPE_CAP_DECIMATION,
  262. },
  263. .pipe_rgb = {
  264. .count = 2,
  265. .base = { 0x14000, 0x16000 },
  266. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
  267. MDP_PIPE_CAP_DECIMATION,
  268. },
  269. .pipe_dma = {
  270. .count = 1,
  271. .base = { 0x24000 },
  272. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
  273. },
  274. .lm = {
  275. .count = 2, /* LM0 and LM3 */
  276. .base = { 0x44000, 0x47000 },
  277. .nb_stages = 8,
  278. .max_width = 2048,
  279. .max_height = 0xFFFF,
  280. },
  281. .dspp = {
  282. .count = 1,
  283. .base = { 0x54000 },
  284. },
  285. .intf = {
  286. .base = { 0x00000, 0x6a800 },
  287. .connect = {
  288. [0] = INTF_DISABLED,
  289. [1] = INTF_DSI,
  290. },
  291. },
  292. .max_clk = 320000000,
  293. };
  294. const struct mdp5_cfg_hw msm8x94_config = {
  295. .name = "msm8x94",
  296. .mdp = {
  297. .count = 1,
  298. .caps = MDP_CAP_SMP |
  299. 0,
  300. },
  301. .smp = {
  302. .mmb_count = 44,
  303. .mmb_size = 8192,
  304. .clients = {
  305. [SSPP_VIG0] = 1, [SSPP_VIG1] = 4,
  306. [SSPP_VIG2] = 7, [SSPP_VIG3] = 19,
  307. [SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
  308. [SSPP_RGB0] = 16, [SSPP_RGB1] = 17,
  309. [SSPP_RGB2] = 18, [SSPP_RGB3] = 22,
  310. },
  311. .reserved_state[0] = GENMASK(23, 0), /* first 24 MMBs */
  312. .reserved = {
  313. [1] = 1, [4] = 1, [7] = 1, [19] = 1,
  314. [16] = 5, [17] = 5, [18] = 5, [22] = 5,
  315. },
  316. },
  317. .ctl = {
  318. .count = 5,
  319. .base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
  320. .flush_hw_mask = 0xf0ffffff,
  321. },
  322. .pipe_vig = {
  323. .count = 4,
  324. .base = { 0x04000, 0x06000, 0x08000, 0x0a000 },
  325. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
  326. MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
  327. MDP_PIPE_CAP_DECIMATION,
  328. },
  329. .pipe_rgb = {
  330. .count = 4,
  331. .base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
  332. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
  333. MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
  334. },
  335. .pipe_dma = {
  336. .count = 2,
  337. .base = { 0x24000, 0x26000 },
  338. .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
  339. },
  340. .lm = {
  341. .count = 6,
  342. .base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
  343. .nb_stages = 8,
  344. .max_width = 2048,
  345. .max_height = 0xFFFF,
  346. },
  347. .dspp = {
  348. .count = 4,
  349. .base = { 0x54000, 0x56000, 0x58000, 0x5a000 },
  350. },
  351. .ad = {
  352. .count = 3,
  353. .base = { 0x78000, 0x78800, 0x79000 },
  354. },
  355. .pp = {
  356. .count = 4,
  357. .base = { 0x70000, 0x70800, 0x71000, 0x71800 },
  358. },
  359. .intf = {
  360. .base = { 0x6a000, 0x6a800, 0x6b000, 0x6b800, 0x6c000 },
  361. .connect = {
  362. [0] = INTF_DISABLED,
  363. [1] = INTF_DSI,
  364. [2] = INTF_DSI,
  365. [3] = INTF_HDMI,
  366. },
  367. },
  368. .max_clk = 400000000,
  369. };
  370. const struct mdp5_cfg_hw msm8x96_config = {
  371. .name = "msm8x96",
  372. .mdp = {
  373. .count = 1,
  374. .caps = MDP_CAP_DSC |
  375. MDP_CAP_CDM |
  376. 0,
  377. },
  378. .ctl = {
  379. .count = 5,
  380. .base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
  381. .flush_hw_mask = 0xf4ffffff,
  382. },
  383. .pipe_vig = {
  384. .count = 4,
  385. .base = { 0x04000, 0x06000, 0x08000, 0x0a000 },
  386. .caps = MDP_PIPE_CAP_HFLIP |
  387. MDP_PIPE_CAP_VFLIP |
  388. MDP_PIPE_CAP_SCALE |
  389. MDP_PIPE_CAP_CSC |
  390. MDP_PIPE_CAP_DECIMATION |
  391. MDP_PIPE_CAP_SW_PIX_EXT |
  392. 0,
  393. },
  394. .pipe_rgb = {
  395. .count = 4,
  396. .base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
  397. .caps = MDP_PIPE_CAP_HFLIP |
  398. MDP_PIPE_CAP_VFLIP |
  399. MDP_PIPE_CAP_SCALE |
  400. MDP_PIPE_CAP_DECIMATION |
  401. MDP_PIPE_CAP_SW_PIX_EXT |
  402. 0,
  403. },
  404. .pipe_dma = {
  405. .count = 2,
  406. .base = { 0x24000, 0x26000 },
  407. .caps = MDP_PIPE_CAP_HFLIP |
  408. MDP_PIPE_CAP_VFLIP |
  409. MDP_PIPE_CAP_SW_PIX_EXT |
  410. 0,
  411. },
  412. .lm = {
  413. .count = 6,
  414. .base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
  415. .nb_stages = 8,
  416. .max_width = 2560,
  417. .max_height = 0xFFFF,
  418. },
  419. .dspp = {
  420. .count = 2,
  421. .base = { 0x54000, 0x56000 },
  422. },
  423. .ad = {
  424. .count = 3,
  425. .base = { 0x78000, 0x78800, 0x79000 },
  426. },
  427. .pp = {
  428. .count = 4,
  429. .base = { 0x70000, 0x70800, 0x71000, 0x71800 },
  430. },
  431. .cdm = {
  432. .count = 1,
  433. .base = { 0x79200 },
  434. },
  435. .dsc = {
  436. .count = 2,
  437. .base = { 0x80000, 0x80400 },
  438. },
  439. .intf = {
  440. .base = { 0x6a000, 0x6a800, 0x6b000, 0x6b800, 0x6c000 },
  441. .connect = {
  442. [0] = INTF_DISABLED,
  443. [1] = INTF_DSI,
  444. [2] = INTF_DSI,
  445. [3] = INTF_HDMI,
  446. },
  447. },
  448. .max_clk = 412500000,
  449. };
  450. static const struct mdp5_cfg_handler cfg_handlers[] = {
  451. { .revision = 0, .config = { .hw = &msm8x74v1_config } },
  452. { .revision = 2, .config = { .hw = &msm8x74v2_config } },
  453. { .revision = 3, .config = { .hw = &apq8084_config } },
  454. { .revision = 6, .config = { .hw = &msm8x16_config } },
  455. { .revision = 9, .config = { .hw = &msm8x94_config } },
  456. { .revision = 7, .config = { .hw = &msm8x96_config } },
  457. };
  458. static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev);
  459. const struct mdp5_cfg_hw *mdp5_cfg_get_hw_config(struct mdp5_cfg_handler *cfg_handler)
  460. {
  461. return cfg_handler->config.hw;
  462. }
  463. struct mdp5_cfg *mdp5_cfg_get_config(struct mdp5_cfg_handler *cfg_handler)
  464. {
  465. return &cfg_handler->config;
  466. }
  467. int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_handler)
  468. {
  469. return cfg_handler->revision;
  470. }
  471. void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_handler)
  472. {
  473. kfree(cfg_handler);
  474. }
  475. struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
  476. uint32_t major, uint32_t minor)
  477. {
  478. struct drm_device *dev = mdp5_kms->dev;
  479. struct platform_device *pdev = dev->platformdev;
  480. struct mdp5_cfg_handler *cfg_handler;
  481. struct mdp5_cfg_platform *pconfig;
  482. int i, ret = 0;
  483. cfg_handler = kzalloc(sizeof(*cfg_handler), GFP_KERNEL);
  484. if (unlikely(!cfg_handler)) {
  485. ret = -ENOMEM;
  486. goto fail;
  487. }
  488. if (major != 1) {
  489. dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n",
  490. major, minor);
  491. ret = -ENXIO;
  492. goto fail;
  493. }
  494. /* only after mdp5_cfg global pointer's init can we access the hw */
  495. for (i = 0; i < ARRAY_SIZE(cfg_handlers); i++) {
  496. if (cfg_handlers[i].revision != minor)
  497. continue;
  498. mdp5_cfg = cfg_handlers[i].config.hw;
  499. break;
  500. }
  501. if (unlikely(!mdp5_cfg)) {
  502. dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n",
  503. major, minor);
  504. ret = -ENXIO;
  505. goto fail;
  506. }
  507. cfg_handler->revision = minor;
  508. cfg_handler->config.hw = mdp5_cfg;
  509. pconfig = mdp5_get_config(pdev);
  510. memcpy(&cfg_handler->config.platform, pconfig, sizeof(*pconfig));
  511. DBG("MDP5: %s hw config selected", mdp5_cfg->name);
  512. return cfg_handler;
  513. fail:
  514. if (cfg_handler)
  515. mdp5_cfg_destroy(cfg_handler);
  516. return NULL;
  517. }
  518. static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev)
  519. {
  520. static struct mdp5_cfg_platform config = {};
  521. config.iommu = iommu_domain_alloc(&platform_bus_type);
  522. if (config.iommu) {
  523. config.iommu->geometry.aperture_start = 0x1000;
  524. config.iommu->geometry.aperture_end = 0xffffffff;
  525. }
  526. return &config;
  527. }