mdp4_lcdc_encoder.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /*
  2. * Copyright (C) 2014 Red Hat
  3. * Author: Rob Clark <robdclark@gmail.com>
  4. * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License version 2 as published by
  8. * the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "mdp4_kms.h"
  19. #include "drm_crtc.h"
  20. #include "drm_crtc_helper.h"
  21. struct mdp4_lcdc_encoder {
  22. struct drm_encoder base;
  23. struct device_node *panel_node;
  24. struct drm_panel *panel;
  25. struct clk *lcdc_clk;
  26. unsigned long int pixclock;
  27. struct regulator *regs[3];
  28. bool enabled;
  29. uint32_t bsc;
  30. };
  31. #define to_mdp4_lcdc_encoder(x) container_of(x, struct mdp4_lcdc_encoder, base)
  32. static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
  33. {
  34. struct msm_drm_private *priv = encoder->dev->dev_private;
  35. return to_mdp4_kms(to_mdp_kms(priv->kms));
  36. }
  37. #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
  38. #include <mach/board.h>
  39. static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)
  40. {
  41. struct drm_device *dev = mdp4_lcdc_encoder->base.dev;
  42. struct lcdc_platform_data *lcdc_pdata = mdp4_find_pdata("lvds.0");
  43. if (!lcdc_pdata) {
  44. dev_err(dev->dev, "could not find lvds pdata\n");
  45. return;
  46. }
  47. if (lcdc_pdata->bus_scale_table) {
  48. mdp4_lcdc_encoder->bsc = msm_bus_scale_register_client(
  49. lcdc_pdata->bus_scale_table);
  50. DBG("lvds : bus scale client: %08x", mdp4_lcdc_encoder->bsc);
  51. }
  52. }
  53. static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)
  54. {
  55. if (mdp4_lcdc_encoder->bsc) {
  56. msm_bus_scale_unregister_client(mdp4_lcdc_encoder->bsc);
  57. mdp4_lcdc_encoder->bsc = 0;
  58. }
  59. }
  60. static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx)
  61. {
  62. if (mdp4_lcdc_encoder->bsc) {
  63. DBG("set bus scaling: %d", idx);
  64. msm_bus_scale_client_update_request(mdp4_lcdc_encoder->bsc, idx);
  65. }
  66. }
  67. #else
  68. static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {}
  69. static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {}
  70. static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx) {}
  71. #endif
  72. static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder)
  73. {
  74. struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
  75. to_mdp4_lcdc_encoder(encoder);
  76. bs_fini(mdp4_lcdc_encoder);
  77. drm_encoder_cleanup(encoder);
  78. kfree(mdp4_lcdc_encoder);
  79. }
  80. static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = {
  81. .destroy = mdp4_lcdc_encoder_destroy,
  82. };
  83. /* this should probably be a helper: */
  84. static struct drm_connector *get_connector(struct drm_encoder *encoder)
  85. {
  86. struct drm_device *dev = encoder->dev;
  87. struct drm_connector *connector;
  88. list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  89. if (connector->encoder == encoder)
  90. return connector;
  91. return NULL;
  92. }
  93. static void setup_phy(struct drm_encoder *encoder)
  94. {
  95. struct drm_device *dev = encoder->dev;
  96. struct drm_connector *connector = get_connector(encoder);
  97. struct mdp4_kms *mdp4_kms = get_kms(encoder);
  98. uint32_t lvds_intf = 0, lvds_phy_cfg0 = 0;
  99. int bpp, nchan, swap;
  100. if (!connector)
  101. return;
  102. bpp = 3 * connector->display_info.bpc;
  103. if (!bpp)
  104. bpp = 18;
  105. /* TODO, these should come from panel somehow: */
  106. nchan = 1;
  107. swap = 0;
  108. switch (bpp) {
  109. case 24:
  110. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0),
  111. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x08) |
  112. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x05) |
  113. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x04) |
  114. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x03));
  115. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0),
  116. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x02) |
  117. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x01) |
  118. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x00));
  119. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1),
  120. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x11) |
  121. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x10) |
  122. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0d) |
  123. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0c));
  124. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1),
  125. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0b) |
  126. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0a) |
  127. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x09));
  128. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2),
  129. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) |
  130. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) |
  131. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) |
  132. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x15));
  133. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2),
  134. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x14) |
  135. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x13) |
  136. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x12));
  137. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(3),
  138. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1b) |
  139. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x17) |
  140. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x16) |
  141. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0f));
  142. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(3),
  143. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0e) |
  144. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x07) |
  145. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x06));
  146. if (nchan == 2) {
  147. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE3_EN |
  148. MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN |
  149. MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN |
  150. MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN |
  151. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN |
  152. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
  153. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
  154. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
  155. } else {
  156. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN |
  157. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
  158. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
  159. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
  160. }
  161. break;
  162. case 18:
  163. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0),
  164. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x0a) |
  165. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x07) |
  166. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x06) |
  167. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x05));
  168. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0),
  169. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x04) |
  170. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x03) |
  171. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x02));
  172. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1),
  173. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x13) |
  174. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x12) |
  175. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0f) |
  176. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0e));
  177. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1),
  178. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0d) |
  179. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0c) |
  180. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x0b));
  181. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2),
  182. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) |
  183. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) |
  184. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) |
  185. MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x17));
  186. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2),
  187. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x16) |
  188. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x15) |
  189. MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x14));
  190. if (nchan == 2) {
  191. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN |
  192. MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN |
  193. MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN |
  194. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
  195. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
  196. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
  197. } else {
  198. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
  199. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
  200. MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
  201. }
  202. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_RGB_OUT;
  203. break;
  204. default:
  205. dev_err(dev->dev, "unknown bpp: %d\n", bpp);
  206. return;
  207. }
  208. switch (nchan) {
  209. case 1:
  210. lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0;
  211. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN |
  212. MDP4_LCDC_LVDS_INTF_CTL_MODE_SEL;
  213. break;
  214. case 2:
  215. lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0 |
  216. MDP4_LVDS_PHY_CFG0_CHANNEL1;
  217. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_CLK_LANE_EN |
  218. MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN;
  219. break;
  220. default:
  221. dev_err(dev->dev, "unknown # of channels: %d\n", nchan);
  222. return;
  223. }
  224. if (swap)
  225. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH_SWAP;
  226. lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_ENABLE;
  227. mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
  228. mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_INTF_CTL, lvds_intf);
  229. mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG2, 0x30);
  230. mb();
  231. udelay(1);
  232. lvds_phy_cfg0 |= MDP4_LVDS_PHY_CFG0_SERIALIZATION_ENBLE;
  233. mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
  234. }
  235. static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder,
  236. struct drm_display_mode *mode,
  237. struct drm_display_mode *adjusted_mode)
  238. {
  239. struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
  240. to_mdp4_lcdc_encoder(encoder);
  241. struct mdp4_kms *mdp4_kms = get_kms(encoder);
  242. uint32_t lcdc_hsync_skew, vsync_period, vsync_len, ctrl_pol;
  243. uint32_t display_v_start, display_v_end;
  244. uint32_t hsync_start_x, hsync_end_x;
  245. mode = adjusted_mode;
  246. DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
  247. mode->base.id, mode->name,
  248. mode->vrefresh, mode->clock,
  249. mode->hdisplay, mode->hsync_start,
  250. mode->hsync_end, mode->htotal,
  251. mode->vdisplay, mode->vsync_start,
  252. mode->vsync_end, mode->vtotal,
  253. mode->type, mode->flags);
  254. mdp4_lcdc_encoder->pixclock = mode->clock * 1000;
  255. DBG("pixclock=%lu", mdp4_lcdc_encoder->pixclock);
  256. ctrl_pol = 0;
  257. if (mode->flags & DRM_MODE_FLAG_NHSYNC)
  258. ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_HSYNC_LOW;
  259. if (mode->flags & DRM_MODE_FLAG_NVSYNC)
  260. ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW;
  261. /* probably need to get DATA_EN polarity from panel.. */
  262. lcdc_hsync_skew = 0; /* get this from panel? */
  263. hsync_start_x = (mode->htotal - mode->hsync_start);
  264. hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
  265. vsync_period = mode->vtotal * mode->htotal;
  266. vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
  267. display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + lcdc_hsync_skew;
  268. display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + lcdc_hsync_skew - 1;
  269. mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_CTRL,
  270. MDP4_LCDC_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
  271. MDP4_LCDC_HSYNC_CTRL_PERIOD(mode->htotal));
  272. mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_PERIOD, vsync_period);
  273. mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_LEN, vsync_len);
  274. mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_HCTRL,
  275. MDP4_LCDC_DISPLAY_HCTRL_START(hsync_start_x) |
  276. MDP4_LCDC_DISPLAY_HCTRL_END(hsync_end_x));
  277. mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VSTART, display_v_start);
  278. mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VEND, display_v_end);
  279. mdp4_write(mdp4_kms, REG_MDP4_LCDC_BORDER_CLR, 0);
  280. mdp4_write(mdp4_kms, REG_MDP4_LCDC_UNDERFLOW_CLR,
  281. MDP4_LCDC_UNDERFLOW_CLR_ENABLE_RECOVERY |
  282. MDP4_LCDC_UNDERFLOW_CLR_COLOR(0xff));
  283. mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_SKEW, lcdc_hsync_skew);
  284. mdp4_write(mdp4_kms, REG_MDP4_LCDC_CTRL_POLARITY, ctrl_pol);
  285. mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_HCTL,
  286. MDP4_LCDC_ACTIVE_HCTL_START(0) |
  287. MDP4_LCDC_ACTIVE_HCTL_END(0));
  288. mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VSTART, 0);
  289. mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0);
  290. }
  291. static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder)
  292. {
  293. struct drm_device *dev = encoder->dev;
  294. struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
  295. to_mdp4_lcdc_encoder(encoder);
  296. struct mdp4_kms *mdp4_kms = get_kms(encoder);
  297. struct drm_panel *panel;
  298. int i, ret;
  299. if (WARN_ON(!mdp4_lcdc_encoder->enabled))
  300. return;
  301. mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
  302. panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node);
  303. if (panel) {
  304. drm_panel_disable(panel);
  305. drm_panel_unprepare(panel);
  306. }
  307. /*
  308. * Wait for a vsync so we know the ENABLE=0 latched before
  309. * the (connector) source of the vsync's gets disabled,
  310. * otherwise we end up in a funny state if we re-enable
  311. * before the disable latches, which results that some of
  312. * the settings changes for the new modeset (like new
  313. * scanout buffer) don't latch properly..
  314. */
  315. mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC);
  316. clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk);
  317. for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
  318. ret = regulator_disable(mdp4_lcdc_encoder->regs[i]);
  319. if (ret)
  320. dev_err(dev->dev, "failed to disable regulator: %d\n", ret);
  321. }
  322. bs_set(mdp4_lcdc_encoder, 0);
  323. mdp4_lcdc_encoder->enabled = false;
  324. }
  325. static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder)
  326. {
  327. struct drm_device *dev = encoder->dev;
  328. struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
  329. to_mdp4_lcdc_encoder(encoder);
  330. unsigned long pc = mdp4_lcdc_encoder->pixclock;
  331. struct mdp4_kms *mdp4_kms = get_kms(encoder);
  332. struct drm_panel *panel;
  333. int i, ret;
  334. if (WARN_ON(mdp4_lcdc_encoder->enabled))
  335. return;
  336. /* TODO: hard-coded for 18bpp: */
  337. mdp4_crtc_set_config(encoder->crtc,
  338. MDP4_DMA_CONFIG_R_BPC(BPC6) |
  339. MDP4_DMA_CONFIG_G_BPC(BPC6) |
  340. MDP4_DMA_CONFIG_B_BPC(BPC6) |
  341. MDP4_DMA_CONFIG_PACK_ALIGN_MSB |
  342. MDP4_DMA_CONFIG_PACK(0x21) |
  343. MDP4_DMA_CONFIG_DEFLKR_EN |
  344. MDP4_DMA_CONFIG_DITHER_EN);
  345. mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0);
  346. bs_set(mdp4_lcdc_encoder, 1);
  347. for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
  348. ret = regulator_enable(mdp4_lcdc_encoder->regs[i]);
  349. if (ret)
  350. dev_err(dev->dev, "failed to enable regulator: %d\n", ret);
  351. }
  352. DBG("setting lcdc_clk=%lu", pc);
  353. ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc);
  354. if (ret)
  355. dev_err(dev->dev, "failed to configure lcdc_clk: %d\n", ret);
  356. ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk);
  357. if (ret)
  358. dev_err(dev->dev, "failed to enable lcdc_clk: %d\n", ret);
  359. panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node);
  360. if (panel) {
  361. drm_panel_prepare(panel);
  362. drm_panel_enable(panel);
  363. }
  364. setup_phy(encoder);
  365. mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1);
  366. mdp4_lcdc_encoder->enabled = true;
  367. }
  368. static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = {
  369. .mode_set = mdp4_lcdc_encoder_mode_set,
  370. .disable = mdp4_lcdc_encoder_disable,
  371. .enable = mdp4_lcdc_encoder_enable,
  372. };
  373. long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
  374. {
  375. struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
  376. to_mdp4_lcdc_encoder(encoder);
  377. return clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, rate);
  378. }
  379. /* initialize encoder */
  380. struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
  381. struct device_node *panel_node)
  382. {
  383. struct drm_encoder *encoder = NULL;
  384. struct mdp4_lcdc_encoder *mdp4_lcdc_encoder;
  385. struct regulator *reg;
  386. int ret;
  387. mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL);
  388. if (!mdp4_lcdc_encoder) {
  389. ret = -ENOMEM;
  390. goto fail;
  391. }
  392. mdp4_lcdc_encoder->panel_node = panel_node;
  393. encoder = &mdp4_lcdc_encoder->base;
  394. drm_encoder_init(dev, encoder, &mdp4_lcdc_encoder_funcs,
  395. DRM_MODE_ENCODER_LVDS, NULL);
  396. drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs);
  397. /* TODO: do we need different pll in other cases? */
  398. mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev);
  399. if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) {
  400. dev_err(dev->dev, "failed to get lvds_clk\n");
  401. ret = PTR_ERR(mdp4_lcdc_encoder->lcdc_clk);
  402. goto fail;
  403. }
  404. /* TODO: different regulators in other cases? */
  405. reg = devm_regulator_get(dev->dev, "lvds-vccs-3p3v");
  406. if (IS_ERR(reg)) {
  407. ret = PTR_ERR(reg);
  408. dev_err(dev->dev, "failed to get lvds-vccs-3p3v: %d\n", ret);
  409. goto fail;
  410. }
  411. mdp4_lcdc_encoder->regs[0] = reg;
  412. reg = devm_regulator_get(dev->dev, "lvds-pll-vdda");
  413. if (IS_ERR(reg)) {
  414. ret = PTR_ERR(reg);
  415. dev_err(dev->dev, "failed to get lvds-pll-vdda: %d\n", ret);
  416. goto fail;
  417. }
  418. mdp4_lcdc_encoder->regs[1] = reg;
  419. reg = devm_regulator_get(dev->dev, "lvds-vdda");
  420. if (IS_ERR(reg)) {
  421. ret = PTR_ERR(reg);
  422. dev_err(dev->dev, "failed to get lvds-vdda: %d\n", ret);
  423. goto fail;
  424. }
  425. mdp4_lcdc_encoder->regs[2] = reg;
  426. bs_init(mdp4_lcdc_encoder);
  427. return encoder;
  428. fail:
  429. if (encoder)
  430. mdp4_lcdc_encoder_destroy(encoder);
  431. return ERR_PTR(ret);
  432. }