sti_vtac.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (C) STMicroelectronics SA 2014
  3. * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
  4. * License terms: GNU General Public License (GPL), version 2
  5. */
  6. #include <linux/clk.h>
  7. #include <linux/io.h>
  8. #include <linux/module.h>
  9. #include <linux/of.h>
  10. #include <linux/platform_device.h>
  11. #include <drm/drmP.h>
  12. /* registers offset */
  13. #define VTAC_CONFIG 0x00
  14. #define VTAC_RX_FIFO_CONFIG 0x04
  15. #define VTAC_FIFO_CONFIG_VAL 0x04
  16. #define VTAC_SYS_CFG8521 0x824
  17. #define VTAC_SYS_CFG8522 0x828
  18. /* Number of phyts per pixel */
  19. #define VTAC_2_5_PPP 0x0005
  20. #define VTAC_3_PPP 0x0006
  21. #define VTAC_4_PPP 0x0008
  22. #define VTAC_5_PPP 0x000A
  23. #define VTAC_6_PPP 0x000C
  24. #define VTAC_13_PPP 0x001A
  25. #define VTAC_14_PPP 0x001C
  26. #define VTAC_15_PPP 0x001E
  27. #define VTAC_16_PPP 0x0020
  28. #define VTAC_17_PPP 0x0022
  29. #define VTAC_18_PPP 0x0024
  30. /* enable bits */
  31. #define VTAC_ENABLE 0x3003
  32. #define VTAC_TX_PHY_ENABLE_CLK_PHY BIT(0)
  33. #define VTAC_TX_PHY_ENABLE_CLK_DLL BIT(1)
  34. #define VTAC_TX_PHY_PLL_NOT_OSC_MODE BIT(3)
  35. #define VTAC_TX_PHY_RST_N_DLL_SWITCH BIT(4)
  36. #define VTAC_TX_PHY_PROG_N3 BIT(9)
  37. /**
  38. * VTAC mode structure
  39. *
  40. * @vid_in_width: Video Data Resolution
  41. * @phyts_width: Width of phyt buses(phyt low and phyt high).
  42. * @phyts_per_pixel: Number of phyts sent per pixel
  43. */
  44. struct sti_vtac_mode {
  45. u32 vid_in_width;
  46. u32 phyts_width;
  47. u32 phyts_per_pixel;
  48. };
  49. static const struct sti_vtac_mode vtac_mode_main = {0x2, 0x2, VTAC_5_PPP};
  50. static const struct sti_vtac_mode vtac_mode_aux = {0x1, 0x0, VTAC_17_PPP};
  51. /**
  52. * VTAC structure
  53. *
  54. * @dev: pointer to device structure
  55. * @regs: ioremapped registers for RX and TX devices
  56. * @phy_regs: phy registers for TX device
  57. * @clk: clock
  58. * @mode: main or auxillary configuration mode
  59. */
  60. struct sti_vtac {
  61. struct device *dev;
  62. void __iomem *regs;
  63. void __iomem *phy_regs;
  64. struct clk *clk;
  65. const struct sti_vtac_mode *mode;
  66. };
  67. static void sti_vtac_rx_set_config(struct sti_vtac *vtac)
  68. {
  69. u32 config;
  70. /* Enable VTAC clock */
  71. if (clk_prepare_enable(vtac->clk))
  72. DRM_ERROR("Failed to prepare/enable vtac_rx clock.\n");
  73. writel(VTAC_FIFO_CONFIG_VAL, vtac->regs + VTAC_RX_FIFO_CONFIG);
  74. config = VTAC_ENABLE;
  75. config |= vtac->mode->vid_in_width << 4;
  76. config |= vtac->mode->phyts_width << 16;
  77. config |= vtac->mode->phyts_per_pixel << 23;
  78. writel(config, vtac->regs + VTAC_CONFIG);
  79. }
  80. static void sti_vtac_tx_set_config(struct sti_vtac *vtac)
  81. {
  82. u32 phy_config;
  83. u32 config;
  84. /* Enable VTAC clock */
  85. if (clk_prepare_enable(vtac->clk))
  86. DRM_ERROR("Failed to prepare/enable vtac_tx clock.\n");
  87. /* Configure vtac phy */
  88. phy_config = 0x00000000;
  89. writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8522);
  90. phy_config = VTAC_TX_PHY_ENABLE_CLK_PHY;
  91. writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
  92. phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
  93. phy_config |= VTAC_TX_PHY_PROG_N3;
  94. writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
  95. phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
  96. phy_config |= VTAC_TX_PHY_ENABLE_CLK_DLL;
  97. writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
  98. phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
  99. phy_config |= VTAC_TX_PHY_RST_N_DLL_SWITCH;
  100. writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
  101. phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
  102. phy_config |= VTAC_TX_PHY_PLL_NOT_OSC_MODE;
  103. writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
  104. /* Configure vtac tx */
  105. config = VTAC_ENABLE;
  106. config |= vtac->mode->vid_in_width << 4;
  107. config |= vtac->mode->phyts_width << 16;
  108. config |= vtac->mode->phyts_per_pixel << 23;
  109. writel(config, vtac->regs + VTAC_CONFIG);
  110. }
  111. static const struct of_device_id vtac_of_match[] = {
  112. {
  113. .compatible = "st,vtac-main",
  114. .data = &vtac_mode_main,
  115. }, {
  116. .compatible = "st,vtac-aux",
  117. .data = &vtac_mode_aux,
  118. }, {
  119. /* end node */
  120. }
  121. };
  122. MODULE_DEVICE_TABLE(of, vtac_of_match);
  123. static int sti_vtac_probe(struct platform_device *pdev)
  124. {
  125. struct device *dev = &pdev->dev;
  126. struct device_node *np = dev->of_node;
  127. const struct of_device_id *id;
  128. struct sti_vtac *vtac;
  129. struct resource *res;
  130. vtac = devm_kzalloc(dev, sizeof(*vtac), GFP_KERNEL);
  131. if (!vtac)
  132. return -ENOMEM;
  133. vtac->dev = dev;
  134. id = of_match_node(vtac_of_match, np);
  135. if (!id)
  136. return -ENOMEM;
  137. vtac->mode = id->data;
  138. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  139. if (!res) {
  140. DRM_ERROR("Invalid resource\n");
  141. return -ENOMEM;
  142. }
  143. vtac->regs = devm_ioremap_resource(dev, res);
  144. if (IS_ERR(vtac->regs))
  145. return PTR_ERR(vtac->regs);
  146. vtac->clk = devm_clk_get(dev, "vtac");
  147. if (IS_ERR(vtac->clk)) {
  148. DRM_ERROR("Cannot get vtac clock\n");
  149. return PTR_ERR(vtac->clk);
  150. }
  151. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  152. if (res) {
  153. vtac->phy_regs = devm_ioremap_nocache(dev, res->start,
  154. resource_size(res));
  155. sti_vtac_tx_set_config(vtac);
  156. } else {
  157. sti_vtac_rx_set_config(vtac);
  158. }
  159. platform_set_drvdata(pdev, vtac);
  160. DRM_INFO("%s %s\n", __func__, dev_name(vtac->dev));
  161. return 0;
  162. }
  163. static int sti_vtac_remove(struct platform_device *pdev)
  164. {
  165. return 0;
  166. }
  167. struct platform_driver sti_vtac_driver = {
  168. .driver = {
  169. .name = "sti-vtac",
  170. .owner = THIS_MODULE,
  171. .of_match_table = vtac_of_match,
  172. },
  173. .probe = sti_vtac_probe,
  174. .remove = sti_vtac_remove,
  175. };
  176. module_platform_driver(sti_vtac_driver);
  177. MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
  178. MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
  179. MODULE_LICENSE("GPL");