mtk_mdp_comp.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (c) 2016 MediaTek Inc.
  3. * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/clk.h>
  15. #include <linux/device.h>
  16. #include <linux/of.h>
  17. #include <linux/of_address.h>
  18. #include <linux/of_platform.h>
  19. #include <soc/mediatek/smi.h>
  20. #include "mtk_mdp_comp.h"
  21. static const char * const mtk_mdp_comp_stem[MTK_MDP_COMP_TYPE_MAX] = {
  22. "mdp_rdma",
  23. "mdp_rsz",
  24. "mdp_wdma",
  25. "mdp_wrot",
  26. };
  27. struct mtk_mdp_comp_match {
  28. enum mtk_mdp_comp_type type;
  29. int alias_id;
  30. };
  31. static const struct mtk_mdp_comp_match mtk_mdp_matches[MTK_MDP_COMP_ID_MAX] = {
  32. { MTK_MDP_RDMA, 0 },
  33. { MTK_MDP_RDMA, 1 },
  34. { MTK_MDP_RSZ, 0 },
  35. { MTK_MDP_RSZ, 1 },
  36. { MTK_MDP_RSZ, 2 },
  37. { MTK_MDP_WDMA, 0 },
  38. { MTK_MDP_WROT, 0 },
  39. { MTK_MDP_WROT, 1 },
  40. };
  41. int mtk_mdp_comp_get_id(struct device *dev, struct device_node *node,
  42. enum mtk_mdp_comp_type comp_type)
  43. {
  44. int id = of_alias_get_id(node, mtk_mdp_comp_stem[comp_type]);
  45. int i;
  46. for (i = 0; i < ARRAY_SIZE(mtk_mdp_matches); i++) {
  47. if (comp_type == mtk_mdp_matches[i].type &&
  48. id == mtk_mdp_matches[i].alias_id)
  49. return i;
  50. }
  51. dev_err(dev, "Failed to get id. type: %d, id: %d\n", comp_type, id);
  52. return -EINVAL;
  53. }
  54. void mtk_mdp_comp_clock_on(struct device *dev, struct mtk_mdp_comp *comp)
  55. {
  56. int i, err;
  57. if (comp->larb_dev) {
  58. err = mtk_smi_larb_get(comp->larb_dev);
  59. if (err)
  60. dev_err(dev,
  61. "failed to get larb, err %d. type:%d id:%d\n",
  62. err, comp->type, comp->id);
  63. }
  64. for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
  65. if (IS_ERR(comp->clk[i]))
  66. continue;
  67. err = clk_prepare_enable(comp->clk[i]);
  68. if (err)
  69. dev_err(dev,
  70. "failed to enable clock, err %d. type:%d id:%d i:%d\n",
  71. err, comp->type, comp->id, i);
  72. }
  73. }
  74. void mtk_mdp_comp_clock_off(struct device *dev, struct mtk_mdp_comp *comp)
  75. {
  76. int i;
  77. for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
  78. if (IS_ERR(comp->clk[i]))
  79. continue;
  80. clk_disable_unprepare(comp->clk[i]);
  81. }
  82. if (comp->larb_dev)
  83. mtk_smi_larb_put(comp->larb_dev);
  84. }
  85. int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
  86. struct mtk_mdp_comp *comp, enum mtk_mdp_comp_id comp_id)
  87. {
  88. struct device_node *larb_node;
  89. struct platform_device *larb_pdev;
  90. int i;
  91. if (comp_id < 0 || comp_id >= MTK_MDP_COMP_ID_MAX) {
  92. dev_err(dev, "Invalid comp_id %d\n", comp_id);
  93. return -EINVAL;
  94. }
  95. comp->dev_node = of_node_get(node);
  96. comp->id = comp_id;
  97. comp->type = mtk_mdp_matches[comp_id].type;
  98. comp->regs = of_iomap(node, 0);
  99. for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
  100. comp->clk[i] = of_clk_get(node, i);
  101. /* Only RDMA needs two clocks */
  102. if (comp->type != MTK_MDP_RDMA)
  103. break;
  104. }
  105. /* Only DMA capable components need the LARB property */
  106. comp->larb_dev = NULL;
  107. if (comp->type != MTK_MDP_RDMA &&
  108. comp->type != MTK_MDP_WDMA &&
  109. comp->type != MTK_MDP_WROT)
  110. return 0;
  111. larb_node = of_parse_phandle(node, "mediatek,larb", 0);
  112. if (!larb_node) {
  113. dev_err(dev,
  114. "Missing mediadek,larb phandle in %pOF node\n", node);
  115. return -EINVAL;
  116. }
  117. larb_pdev = of_find_device_by_node(larb_node);
  118. if (!larb_pdev) {
  119. dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
  120. of_node_put(larb_node);
  121. return -EPROBE_DEFER;
  122. }
  123. of_node_put(larb_node);
  124. comp->larb_dev = &larb_pdev->dev;
  125. return 0;
  126. }
  127. void mtk_mdp_comp_deinit(struct device *dev, struct mtk_mdp_comp *comp)
  128. {
  129. of_node_put(comp->dev_node);
  130. }