rockchip_lvds.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  4. * Author:
  5. * Mark Yao <[email protected]>
  6. * Sandy Huang <[email protected]>
  7. */
  8. #include <linux/clk.h>
  9. #include <linux/component.h>
  10. #include <linux/mfd/syscon.h>
  11. #include <linux/of_graph.h>
  12. #include <linux/phy/phy.h>
  13. #include <linux/pinctrl/devinfo.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/pm_runtime.h>
  16. #include <linux/regmap.h>
  17. #include <linux/reset.h>
  18. #include <drm/display/drm_dp_helper.h>
  19. #include <drm/drm_atomic_helper.h>
  20. #include <drm/drm_bridge.h>
  21. #include <drm/drm_bridge_connector.h>
  22. #include <drm/drm_of.h>
  23. #include <drm/drm_panel.h>
  24. #include <drm/drm_probe_helper.h>
  25. #include <drm/drm_simple_kms_helper.h>
  26. #include "rockchip_drm_drv.h"
  27. #include "rockchip_drm_vop.h"
  28. #include "rockchip_lvds.h"
  29. #define DISPLAY_OUTPUT_RGB 0
  30. #define DISPLAY_OUTPUT_LVDS 1
  31. #define DISPLAY_OUTPUT_DUAL_LVDS 2
  32. struct rockchip_lvds;
  33. /**
  34. * struct rockchip_lvds_soc_data - rockchip lvds Soc private data
  35. * @probe: LVDS platform probe function
  36. * @helper_funcs: LVDS connector helper functions
  37. */
  38. struct rockchip_lvds_soc_data {
  39. int (*probe)(struct platform_device *pdev, struct rockchip_lvds *lvds);
  40. const struct drm_encoder_helper_funcs *helper_funcs;
  41. };
  42. struct rockchip_lvds {
  43. struct device *dev;
  44. void __iomem *regs;
  45. struct regmap *grf;
  46. struct clk *pclk;
  47. struct phy *dphy;
  48. const struct rockchip_lvds_soc_data *soc_data;
  49. int output; /* rgb lvds or dual lvds output */
  50. int format; /* vesa or jeida format */
  51. struct drm_device *drm_dev;
  52. struct drm_panel *panel;
  53. struct drm_bridge *bridge;
  54. struct drm_connector connector;
  55. struct rockchip_encoder encoder;
  56. struct dev_pin_info *pins;
  57. };
  58. static inline struct rockchip_lvds *connector_to_lvds(struct drm_connector *connector)
  59. {
  60. return container_of(connector, struct rockchip_lvds, connector);
  61. }
  62. static inline struct rockchip_lvds *encoder_to_lvds(struct drm_encoder *encoder)
  63. {
  64. struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
  65. return container_of(rkencoder, struct rockchip_lvds, encoder);
  66. }
  67. static inline void rk3288_writel(struct rockchip_lvds *lvds, u32 offset,
  68. u32 val)
  69. {
  70. writel_relaxed(val, lvds->regs + offset);
  71. if (lvds->output == DISPLAY_OUTPUT_LVDS)
  72. return;
  73. writel_relaxed(val, lvds->regs + offset + RK3288_LVDS_CH1_OFFSET);
  74. }
  75. static inline int rockchip_lvds_name_to_format(const char *s)
  76. {
  77. if (strncmp(s, "jeida-18", 8) == 0)
  78. return LVDS_JEIDA_18;
  79. else if (strncmp(s, "jeida-24", 8) == 0)
  80. return LVDS_JEIDA_24;
  81. else if (strncmp(s, "vesa-24", 7) == 0)
  82. return LVDS_VESA_24;
  83. return -EINVAL;
  84. }
  85. static inline int rockchip_lvds_name_to_output(const char *s)
  86. {
  87. if (strncmp(s, "rgb", 3) == 0)
  88. return DISPLAY_OUTPUT_RGB;
  89. else if (strncmp(s, "lvds", 4) == 0)
  90. return DISPLAY_OUTPUT_LVDS;
  91. else if (strncmp(s, "duallvds", 8) == 0)
  92. return DISPLAY_OUTPUT_DUAL_LVDS;
  93. return -EINVAL;
  94. }
  95. static const struct drm_connector_funcs rockchip_lvds_connector_funcs = {
  96. .fill_modes = drm_helper_probe_single_connector_modes,
  97. .destroy = drm_connector_cleanup,
  98. .reset = drm_atomic_helper_connector_reset,
  99. .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  100. .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  101. };
  102. static int rockchip_lvds_connector_get_modes(struct drm_connector *connector)
  103. {
  104. struct rockchip_lvds *lvds = connector_to_lvds(connector);
  105. struct drm_panel *panel = lvds->panel;
  106. return drm_panel_get_modes(panel, connector);
  107. }
  108. static const
  109. struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs = {
  110. .get_modes = rockchip_lvds_connector_get_modes,
  111. };
  112. static int
  113. rockchip_lvds_encoder_atomic_check(struct drm_encoder *encoder,
  114. struct drm_crtc_state *crtc_state,
  115. struct drm_connector_state *conn_state)
  116. {
  117. struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
  118. s->output_mode = ROCKCHIP_OUT_MODE_P888;
  119. s->output_type = DRM_MODE_CONNECTOR_LVDS;
  120. return 0;
  121. }
  122. static int rk3288_lvds_poweron(struct rockchip_lvds *lvds)
  123. {
  124. int ret;
  125. u32 val;
  126. ret = clk_enable(lvds->pclk);
  127. if (ret < 0) {
  128. DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret);
  129. return ret;
  130. }
  131. ret = pm_runtime_resume_and_get(lvds->dev);
  132. if (ret < 0) {
  133. DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret);
  134. clk_disable(lvds->pclk);
  135. return ret;
  136. }
  137. val = RK3288_LVDS_CH0_REG0_LANE4_EN | RK3288_LVDS_CH0_REG0_LANE3_EN |
  138. RK3288_LVDS_CH0_REG0_LANE2_EN | RK3288_LVDS_CH0_REG0_LANE1_EN |
  139. RK3288_LVDS_CH0_REG0_LANE0_EN;
  140. if (lvds->output == DISPLAY_OUTPUT_RGB) {
  141. val |= RK3288_LVDS_CH0_REG0_TTL_EN |
  142. RK3288_LVDS_CH0_REG0_LANECK_EN;
  143. rk3288_writel(lvds, RK3288_LVDS_CH0_REG0, val);
  144. rk3288_writel(lvds, RK3288_LVDS_CH0_REG2,
  145. RK3288_LVDS_PLL_FBDIV_REG2(0x46));
  146. rk3288_writel(lvds, RK3288_LVDS_CH0_REG4,
  147. RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE |
  148. RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE |
  149. RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE |
  150. RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE |
  151. RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE |
  152. RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE);
  153. rk3288_writel(lvds, RK3288_LVDS_CH0_REG5,
  154. RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA |
  155. RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA |
  156. RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA |
  157. RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA |
  158. RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA |
  159. RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA);
  160. } else {
  161. val |= RK3288_LVDS_CH0_REG0_LVDS_EN |
  162. RK3288_LVDS_CH0_REG0_LANECK_EN;
  163. rk3288_writel(lvds, RK3288_LVDS_CH0_REG0, val);
  164. rk3288_writel(lvds, RK3288_LVDS_CH0_REG1,
  165. RK3288_LVDS_CH0_REG1_LANECK_BIAS |
  166. RK3288_LVDS_CH0_REG1_LANE4_BIAS |
  167. RK3288_LVDS_CH0_REG1_LANE3_BIAS |
  168. RK3288_LVDS_CH0_REG1_LANE2_BIAS |
  169. RK3288_LVDS_CH0_REG1_LANE1_BIAS |
  170. RK3288_LVDS_CH0_REG1_LANE0_BIAS);
  171. rk3288_writel(lvds, RK3288_LVDS_CH0_REG2,
  172. RK3288_LVDS_CH0_REG2_RESERVE_ON |
  173. RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE |
  174. RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE |
  175. RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE |
  176. RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE |
  177. RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE |
  178. RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE |
  179. RK3288_LVDS_PLL_FBDIV_REG2(0x46));
  180. rk3288_writel(lvds, RK3288_LVDS_CH0_REG4, 0x00);
  181. rk3288_writel(lvds, RK3288_LVDS_CH0_REG5, 0x00);
  182. }
  183. rk3288_writel(lvds, RK3288_LVDS_CH0_REG3,
  184. RK3288_LVDS_PLL_FBDIV_REG3(0x46));
  185. rk3288_writel(lvds, RK3288_LVDS_CH0_REGD,
  186. RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
  187. rk3288_writel(lvds, RK3288_LVDS_CH0_REG20,
  188. RK3288_LVDS_CH0_REG20_LSB);
  189. rk3288_writel(lvds, RK3288_LVDS_CFG_REGC,
  190. RK3288_LVDS_CFG_REGC_PLL_ENABLE);
  191. rk3288_writel(lvds, RK3288_LVDS_CFG_REG21,
  192. RK3288_LVDS_CFG_REG21_TX_ENABLE);
  193. return 0;
  194. }
  195. static void rk3288_lvds_poweroff(struct rockchip_lvds *lvds)
  196. {
  197. int ret;
  198. u32 val;
  199. rk3288_writel(lvds, RK3288_LVDS_CFG_REG21,
  200. RK3288_LVDS_CFG_REG21_TX_ENABLE);
  201. rk3288_writel(lvds, RK3288_LVDS_CFG_REGC,
  202. RK3288_LVDS_CFG_REGC_PLL_ENABLE);
  203. val = LVDS_DUAL | LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN | LVDS_PWRDN;
  204. val |= val << 16;
  205. ret = regmap_write(lvds->grf, RK3288_LVDS_GRF_SOC_CON7, val);
  206. if (ret != 0)
  207. DRM_DEV_ERROR(lvds->dev, "Could not write to GRF: %d\n", ret);
  208. pm_runtime_put(lvds->dev);
  209. clk_disable(lvds->pclk);
  210. }
  211. static int rk3288_lvds_grf_config(struct drm_encoder *encoder,
  212. struct drm_display_mode *mode)
  213. {
  214. struct rockchip_lvds *lvds = encoder_to_lvds(encoder);
  215. u8 pin_hsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0;
  216. u8 pin_dclk = (mode->flags & DRM_MODE_FLAG_PCSYNC) ? 1 : 0;
  217. u32 val;
  218. int ret;
  219. /* iomux to LCD data/sync mode */
  220. if (lvds->output == DISPLAY_OUTPUT_RGB)
  221. if (lvds->pins && !IS_ERR(lvds->pins->default_state))
  222. pinctrl_select_state(lvds->pins->p,
  223. lvds->pins->default_state);
  224. val = lvds->format | LVDS_CH0_EN;
  225. if (lvds->output == DISPLAY_OUTPUT_RGB)
  226. val |= LVDS_TTL_EN | LVDS_CH1_EN;
  227. else if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS)
  228. val |= LVDS_DUAL | LVDS_CH1_EN;
  229. if ((mode->htotal - mode->hsync_start) & 0x01)
  230. val |= LVDS_START_PHASE_RST_1;
  231. val |= (pin_dclk << 8) | (pin_hsync << 9);
  232. val |= (0xffff << 16);
  233. ret = regmap_write(lvds->grf, RK3288_LVDS_GRF_SOC_CON7, val);
  234. if (ret)
  235. DRM_DEV_ERROR(lvds->dev, "Could not write to GRF: %d\n", ret);
  236. return ret;
  237. }
  238. static int rk3288_lvds_set_vop_source(struct rockchip_lvds *lvds,
  239. struct drm_encoder *encoder)
  240. {
  241. u32 val;
  242. int ret;
  243. ret = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, encoder);
  244. if (ret < 0)
  245. return ret;
  246. val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16;
  247. if (ret)
  248. val |= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT;
  249. ret = regmap_write(lvds->grf, RK3288_LVDS_GRF_SOC_CON6, val);
  250. if (ret < 0)
  251. return ret;
  252. return 0;
  253. }
  254. static void rk3288_lvds_encoder_enable(struct drm_encoder *encoder)
  255. {
  256. struct rockchip_lvds *lvds = encoder_to_lvds(encoder);
  257. struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
  258. int ret;
  259. drm_panel_prepare(lvds->panel);
  260. ret = rk3288_lvds_poweron(lvds);
  261. if (ret < 0) {
  262. DRM_DEV_ERROR(lvds->dev, "failed to power on LVDS: %d\n", ret);
  263. drm_panel_unprepare(lvds->panel);
  264. return;
  265. }
  266. ret = rk3288_lvds_grf_config(encoder, mode);
  267. if (ret) {
  268. DRM_DEV_ERROR(lvds->dev, "failed to configure LVDS: %d\n", ret);
  269. drm_panel_unprepare(lvds->panel);
  270. return;
  271. }
  272. ret = rk3288_lvds_set_vop_source(lvds, encoder);
  273. if (ret) {
  274. DRM_DEV_ERROR(lvds->dev, "failed to set VOP source: %d\n", ret);
  275. drm_panel_unprepare(lvds->panel);
  276. return;
  277. }
  278. drm_panel_enable(lvds->panel);
  279. }
  280. static void rk3288_lvds_encoder_disable(struct drm_encoder *encoder)
  281. {
  282. struct rockchip_lvds *lvds = encoder_to_lvds(encoder);
  283. drm_panel_disable(lvds->panel);
  284. rk3288_lvds_poweroff(lvds);
  285. drm_panel_unprepare(lvds->panel);
  286. }
  287. static int px30_lvds_poweron(struct rockchip_lvds *lvds)
  288. {
  289. int ret;
  290. ret = pm_runtime_resume_and_get(lvds->dev);
  291. if (ret < 0) {
  292. DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret);
  293. return ret;
  294. }
  295. /* Enable LVDS mode */
  296. ret = regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1,
  297. PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
  298. PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1));
  299. if (ret)
  300. pm_runtime_put(lvds->dev);
  301. return ret;
  302. }
  303. static void px30_lvds_poweroff(struct rockchip_lvds *lvds)
  304. {
  305. regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1,
  306. PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
  307. PX30_LVDS_MODE_EN(0) | PX30_LVDS_P2S_EN(0));
  308. pm_runtime_put(lvds->dev);
  309. }
  310. static int px30_lvds_grf_config(struct drm_encoder *encoder,
  311. struct drm_display_mode *mode)
  312. {
  313. struct rockchip_lvds *lvds = encoder_to_lvds(encoder);
  314. if (lvds->output != DISPLAY_OUTPUT_LVDS) {
  315. DRM_DEV_ERROR(lvds->dev, "Unsupported display output %d\n",
  316. lvds->output);
  317. return -EINVAL;
  318. }
  319. /* Set format */
  320. return regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1,
  321. PX30_LVDS_FORMAT(lvds->format),
  322. PX30_LVDS_FORMAT(lvds->format));
  323. }
  324. static int px30_lvds_set_vop_source(struct rockchip_lvds *lvds,
  325. struct drm_encoder *encoder)
  326. {
  327. int vop;
  328. vop = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, encoder);
  329. if (vop < 0)
  330. return vop;
  331. return regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1,
  332. PX30_LVDS_VOP_SEL(1),
  333. PX30_LVDS_VOP_SEL(vop));
  334. }
  335. static void px30_lvds_encoder_enable(struct drm_encoder *encoder)
  336. {
  337. struct rockchip_lvds *lvds = encoder_to_lvds(encoder);
  338. struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
  339. int ret;
  340. drm_panel_prepare(lvds->panel);
  341. ret = px30_lvds_poweron(lvds);
  342. if (ret) {
  343. DRM_DEV_ERROR(lvds->dev, "failed to power on LVDS: %d\n", ret);
  344. drm_panel_unprepare(lvds->panel);
  345. return;
  346. }
  347. ret = px30_lvds_grf_config(encoder, mode);
  348. if (ret) {
  349. DRM_DEV_ERROR(lvds->dev, "failed to configure LVDS: %d\n", ret);
  350. drm_panel_unprepare(lvds->panel);
  351. return;
  352. }
  353. ret = px30_lvds_set_vop_source(lvds, encoder);
  354. if (ret) {
  355. DRM_DEV_ERROR(lvds->dev, "failed to set VOP source: %d\n", ret);
  356. drm_panel_unprepare(lvds->panel);
  357. return;
  358. }
  359. drm_panel_enable(lvds->panel);
  360. }
  361. static void px30_lvds_encoder_disable(struct drm_encoder *encoder)
  362. {
  363. struct rockchip_lvds *lvds = encoder_to_lvds(encoder);
  364. drm_panel_disable(lvds->panel);
  365. px30_lvds_poweroff(lvds);
  366. drm_panel_unprepare(lvds->panel);
  367. }
  368. static const
  369. struct drm_encoder_helper_funcs rk3288_lvds_encoder_helper_funcs = {
  370. .enable = rk3288_lvds_encoder_enable,
  371. .disable = rk3288_lvds_encoder_disable,
  372. .atomic_check = rockchip_lvds_encoder_atomic_check,
  373. };
  374. static const
  375. struct drm_encoder_helper_funcs px30_lvds_encoder_helper_funcs = {
  376. .enable = px30_lvds_encoder_enable,
  377. .disable = px30_lvds_encoder_disable,
  378. .atomic_check = rockchip_lvds_encoder_atomic_check,
  379. };
  380. static int rk3288_lvds_probe(struct platform_device *pdev,
  381. struct rockchip_lvds *lvds)
  382. {
  383. int ret;
  384. lvds->regs = devm_platform_ioremap_resource(pdev, 0);
  385. if (IS_ERR(lvds->regs))
  386. return PTR_ERR(lvds->regs);
  387. lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds");
  388. if (IS_ERR(lvds->pclk)) {
  389. DRM_DEV_ERROR(lvds->dev, "could not get pclk_lvds\n");
  390. return PTR_ERR(lvds->pclk);
  391. }
  392. lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins),
  393. GFP_KERNEL);
  394. if (!lvds->pins)
  395. return -ENOMEM;
  396. lvds->pins->p = devm_pinctrl_get(lvds->dev);
  397. if (IS_ERR(lvds->pins->p)) {
  398. DRM_DEV_ERROR(lvds->dev, "no pinctrl handle\n");
  399. devm_kfree(lvds->dev, lvds->pins);
  400. lvds->pins = NULL;
  401. } else {
  402. lvds->pins->default_state =
  403. pinctrl_lookup_state(lvds->pins->p, "lcdc");
  404. if (IS_ERR(lvds->pins->default_state)) {
  405. DRM_DEV_ERROR(lvds->dev, "no default pinctrl state\n");
  406. devm_kfree(lvds->dev, lvds->pins);
  407. lvds->pins = NULL;
  408. }
  409. }
  410. ret = clk_prepare(lvds->pclk);
  411. if (ret < 0) {
  412. DRM_DEV_ERROR(lvds->dev, "failed to prepare pclk_lvds\n");
  413. return ret;
  414. }
  415. return 0;
  416. }
  417. static int px30_lvds_probe(struct platform_device *pdev,
  418. struct rockchip_lvds *lvds)
  419. {
  420. int ret;
  421. /* MSB */
  422. ret = regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1,
  423. PX30_LVDS_MSBSEL(1),
  424. PX30_LVDS_MSBSEL(1));
  425. if (ret)
  426. return ret;
  427. /* PHY */
  428. lvds->dphy = devm_phy_get(&pdev->dev, "dphy");
  429. if (IS_ERR(lvds->dphy))
  430. return PTR_ERR(lvds->dphy);
  431. ret = phy_init(lvds->dphy);
  432. if (ret)
  433. return ret;
  434. ret = phy_set_mode(lvds->dphy, PHY_MODE_LVDS);
  435. if (ret)
  436. return ret;
  437. return phy_power_on(lvds->dphy);
  438. }
  439. static const struct rockchip_lvds_soc_data rk3288_lvds_data = {
  440. .probe = rk3288_lvds_probe,
  441. .helper_funcs = &rk3288_lvds_encoder_helper_funcs,
  442. };
  443. static const struct rockchip_lvds_soc_data px30_lvds_data = {
  444. .probe = px30_lvds_probe,
  445. .helper_funcs = &px30_lvds_encoder_helper_funcs,
  446. };
  447. static const struct of_device_id rockchip_lvds_dt_ids[] = {
  448. {
  449. .compatible = "rockchip,rk3288-lvds",
  450. .data = &rk3288_lvds_data
  451. },
  452. {
  453. .compatible = "rockchip,px30-lvds",
  454. .data = &px30_lvds_data
  455. },
  456. {}
  457. };
  458. MODULE_DEVICE_TABLE(of, rockchip_lvds_dt_ids);
  459. static int rockchip_lvds_bind(struct device *dev, struct device *master,
  460. void *data)
  461. {
  462. struct rockchip_lvds *lvds = dev_get_drvdata(dev);
  463. struct drm_device *drm_dev = data;
  464. struct drm_encoder *encoder;
  465. struct drm_connector *connector;
  466. struct device_node *remote = NULL;
  467. struct device_node *port, *endpoint;
  468. int ret = 0, child_count = 0;
  469. const char *name;
  470. u32 endpoint_id = 0;
  471. lvds->drm_dev = drm_dev;
  472. port = of_graph_get_port_by_id(dev->of_node, 1);
  473. if (!port) {
  474. DRM_DEV_ERROR(dev,
  475. "can't found port point, please init lvds panel port!\n");
  476. return -EINVAL;
  477. }
  478. for_each_child_of_node(port, endpoint) {
  479. child_count++;
  480. of_property_read_u32(endpoint, "reg", &endpoint_id);
  481. ret = drm_of_find_panel_or_bridge(dev->of_node, 1, endpoint_id,
  482. &lvds->panel, &lvds->bridge);
  483. if (!ret) {
  484. of_node_put(endpoint);
  485. break;
  486. }
  487. }
  488. if (!child_count) {
  489. DRM_DEV_ERROR(dev, "lvds port does not have any children\n");
  490. ret = -EINVAL;
  491. goto err_put_port;
  492. } else if (ret) {
  493. DRM_DEV_ERROR(dev, "failed to find panel and bridge node\n");
  494. ret = -EPROBE_DEFER;
  495. goto err_put_port;
  496. }
  497. if (lvds->panel)
  498. remote = lvds->panel->dev->of_node;
  499. else
  500. remote = lvds->bridge->of_node;
  501. if (of_property_read_string(dev->of_node, "rockchip,output", &name))
  502. /* default set it as output rgb */
  503. lvds->output = DISPLAY_OUTPUT_RGB;
  504. else
  505. lvds->output = rockchip_lvds_name_to_output(name);
  506. if (lvds->output < 0) {
  507. DRM_DEV_ERROR(dev, "invalid output type [%s]\n", name);
  508. ret = lvds->output;
  509. goto err_put_remote;
  510. }
  511. if (of_property_read_string(remote, "data-mapping", &name))
  512. /* default set it as format vesa 18 */
  513. lvds->format = LVDS_VESA_18;
  514. else
  515. lvds->format = rockchip_lvds_name_to_format(name);
  516. if (lvds->format < 0) {
  517. DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name);
  518. ret = lvds->format;
  519. goto err_put_remote;
  520. }
  521. encoder = &lvds->encoder.encoder;
  522. encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
  523. dev->of_node);
  524. ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_LVDS);
  525. if (ret < 0) {
  526. DRM_DEV_ERROR(drm_dev->dev,
  527. "failed to initialize encoder: %d\n", ret);
  528. goto err_put_remote;
  529. }
  530. drm_encoder_helper_add(encoder, lvds->soc_data->helper_funcs);
  531. connector = &lvds->connector;
  532. if (lvds->panel) {
  533. connector->dpms = DRM_MODE_DPMS_OFF;
  534. ret = drm_connector_init(drm_dev, connector,
  535. &rockchip_lvds_connector_funcs,
  536. DRM_MODE_CONNECTOR_LVDS);
  537. if (ret < 0) {
  538. DRM_DEV_ERROR(drm_dev->dev,
  539. "failed to initialize connector: %d\n", ret);
  540. goto err_free_encoder;
  541. }
  542. drm_connector_helper_add(connector,
  543. &rockchip_lvds_connector_helper_funcs);
  544. } else {
  545. ret = drm_bridge_attach(encoder, lvds->bridge, NULL,
  546. DRM_BRIDGE_ATTACH_NO_CONNECTOR);
  547. if (ret)
  548. goto err_free_encoder;
  549. connector = drm_bridge_connector_init(lvds->drm_dev, encoder);
  550. if (IS_ERR(connector)) {
  551. DRM_DEV_ERROR(drm_dev->dev,
  552. "failed to initialize bridge connector: %pe\n",
  553. connector);
  554. ret = PTR_ERR(connector);
  555. goto err_free_encoder;
  556. }
  557. }
  558. ret = drm_connector_attach_encoder(connector, encoder);
  559. if (ret < 0) {
  560. DRM_DEV_ERROR(drm_dev->dev,
  561. "failed to attach encoder: %d\n", ret);
  562. goto err_free_connector;
  563. }
  564. pm_runtime_enable(dev);
  565. of_node_put(remote);
  566. of_node_put(port);
  567. return 0;
  568. err_free_connector:
  569. drm_connector_cleanup(connector);
  570. err_free_encoder:
  571. drm_encoder_cleanup(encoder);
  572. err_put_remote:
  573. of_node_put(remote);
  574. err_put_port:
  575. of_node_put(port);
  576. return ret;
  577. }
  578. static void rockchip_lvds_unbind(struct device *dev, struct device *master,
  579. void *data)
  580. {
  581. struct rockchip_lvds *lvds = dev_get_drvdata(dev);
  582. const struct drm_encoder_helper_funcs *encoder_funcs;
  583. encoder_funcs = lvds->soc_data->helper_funcs;
  584. encoder_funcs->disable(&lvds->encoder.encoder);
  585. pm_runtime_disable(dev);
  586. drm_connector_cleanup(&lvds->connector);
  587. drm_encoder_cleanup(&lvds->encoder.encoder);
  588. }
  589. static const struct component_ops rockchip_lvds_component_ops = {
  590. .bind = rockchip_lvds_bind,
  591. .unbind = rockchip_lvds_unbind,
  592. };
  593. static int rockchip_lvds_probe(struct platform_device *pdev)
  594. {
  595. struct device *dev = &pdev->dev;
  596. struct rockchip_lvds *lvds;
  597. const struct of_device_id *match;
  598. int ret;
  599. if (!dev->of_node)
  600. return -ENODEV;
  601. lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
  602. if (!lvds)
  603. return -ENOMEM;
  604. lvds->dev = dev;
  605. match = of_match_node(rockchip_lvds_dt_ids, dev->of_node);
  606. if (!match)
  607. return -ENODEV;
  608. lvds->soc_data = match->data;
  609. lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
  610. "rockchip,grf");
  611. if (IS_ERR(lvds->grf)) {
  612. DRM_DEV_ERROR(dev, "missing rockchip,grf property\n");
  613. return PTR_ERR(lvds->grf);
  614. }
  615. ret = lvds->soc_data->probe(pdev, lvds);
  616. if (ret) {
  617. DRM_DEV_ERROR(dev, "Platform initialization failed\n");
  618. return ret;
  619. }
  620. dev_set_drvdata(dev, lvds);
  621. ret = component_add(&pdev->dev, &rockchip_lvds_component_ops);
  622. if (ret < 0) {
  623. DRM_DEV_ERROR(dev, "failed to add component\n");
  624. clk_unprepare(lvds->pclk);
  625. }
  626. return ret;
  627. }
  628. static int rockchip_lvds_remove(struct platform_device *pdev)
  629. {
  630. struct rockchip_lvds *lvds = platform_get_drvdata(pdev);
  631. component_del(&pdev->dev, &rockchip_lvds_component_ops);
  632. clk_unprepare(lvds->pclk);
  633. return 0;
  634. }
  635. struct platform_driver rockchip_lvds_driver = {
  636. .probe = rockchip_lvds_probe,
  637. .remove = rockchip_lvds_remove,
  638. .driver = {
  639. .name = "rockchip-lvds",
  640. .of_match_table = of_match_ptr(rockchip_lvds_dt_ids),
  641. },
  642. };