vs_simple_enc.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020 VeriSilicon Holdings Co., Ltd.
  4. */
  5. #include <linux/version.h>
  6. #include <linux/component.h>
  7. #include <linux/of_device.h>
  8. #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0)
  9. #include <linux/module.h>
  10. #include <drm/drm_bridge.h>
  11. #else
  12. #include <drm/drmP.h>
  13. #endif
  14. #include <drm/drm_crtc_helper.h>
  15. #include <drm/drm_of.h>
  16. #include <linux/regmap.h>
  17. #include <linux/mfd/syscon.h>
  18. #include "vs_crtc.h"
  19. #include "vs_simple_enc.h"
  20. static const struct simple_encoder_priv hdmi_priv = {
  21. .encoder_type = DRM_MODE_ENCODER_TMDS
  22. };
  23. static const struct simple_encoder_priv dsi_priv = {
  24. .encoder_type = DRM_MODE_ENCODER_DSI
  25. };
  26. static const struct simple_encoder_priv dpi_priv = {
  27. .encoder_type = DRM_MODE_ENCODER_DPI
  28. };
  29. static const struct drm_encoder_funcs encoder_funcs = {
  30. .destroy = drm_encoder_cleanup
  31. };
  32. static inline struct simple_encoder *to_simple_encoder(struct drm_encoder *enc)
  33. {
  34. return container_of(enc, struct simple_encoder, encoder);
  35. }
  36. static int encoder_parse_dt(struct device *dev)
  37. {
  38. struct simple_encoder *simple = dev_get_drvdata(dev);
  39. int ret = 0;
  40. int cnt, i;
  41. u32 *vals;
  42. u32 *masks;
  43. simple->dss_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
  44. "verisilicon,dss-syscon");
  45. if (IS_ERR(simple->dss_regmap)) {
  46. if (PTR_ERR(simple->dss_regmap) != -ENODEV) {
  47. dev_err(dev, "failed to get dss-syscon\n");
  48. ret = PTR_ERR(simple->dss_regmap);
  49. goto err;
  50. }
  51. simple->dss_regmap = NULL;
  52. goto err;
  53. }
  54. cnt = of_property_count_elems_of_size(dev->of_node,
  55. "verisilicon,mux-mask", 4);
  56. if (!cnt) {
  57. ret = cnt;
  58. goto err;
  59. }
  60. simple->dss_regdatas = devm_kzalloc(dev,
  61. sizeof(*simple->dss_regdatas) * cnt, GFP_KERNEL);
  62. masks = kcalloc(cnt, sizeof(*masks), GFP_KERNEL);
  63. if (!masks) {
  64. ret = -ENOMEM;
  65. goto err;
  66. }
  67. vals = kcalloc(cnt, sizeof(*vals), GFP_KERNEL);
  68. if (!vals) {
  69. ret = -ENOMEM;
  70. goto err_free_masks;
  71. }
  72. ret = of_property_read_u32_array(
  73. dev->of_node, "verisilicon,mux-mask", masks, cnt);
  74. if (ret)
  75. goto err_free_vals;
  76. ret = of_property_read_u32_array(
  77. dev->of_node, "verisilicon,mux-val", vals, cnt);
  78. if (ret)
  79. goto err_free_vals;
  80. for (i = 0; i < cnt; i++) {
  81. simple->dss_regdatas[i].mask = masks[i];
  82. simple->dss_regdatas[i].value = vals[i];
  83. }
  84. err_free_vals:
  85. kfree(vals);
  86. err_free_masks:
  87. kfree(masks);
  88. err:
  89. return ret;
  90. }
  91. void encoder_atomic_enable(struct drm_encoder *encoder,
  92. struct drm_atomic_state *state)
  93. {
  94. struct simple_encoder *simple = to_simple_encoder(encoder);
  95. struct dss_data *data = simple->dss_regdatas;
  96. int crtc_id;
  97. if (!simple->dss_regmap)
  98. return;
  99. crtc_id = drm_of_encoder_active_endpoint_id(
  100. simple->dev->of_node, encoder);
  101. regmap_update_bits(simple->dss_regmap, 0, data[crtc_id].mask,
  102. data[crtc_id].value);
  103. }
  104. int encoder_atomic_check(struct drm_encoder *encoder,
  105. struct drm_crtc_state *crtc_state,
  106. struct drm_connector_state *conn_state)
  107. {
  108. struct vs_crtc_state *vs_crtc_state = to_vs_crtc_state(crtc_state);
  109. struct drm_connector *connector = conn_state->connector;
  110. int ret = 0;
  111. #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
  112. struct drm_bridge *first_bridge = drm_bridge_chain_get_first_bridge(encoder);
  113. struct drm_bridge_state *bridge_state = ERR_PTR(-EINVAL);
  114. #endif
  115. vs_crtc_state->encoder_type = encoder->encoder_type;
  116. #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
  117. if (first_bridge && first_bridge->funcs->atomic_duplicate_state)
  118. bridge_state = drm_atomic_get_bridge_state(
  119. crtc_state->state, first_bridge);
  120. if (IS_ERR(bridge_state)) {
  121. if (connector->display_info.num_bus_formats)
  122. vs_crtc_state->output_fmt = connector->display_info.bus_formats[0];
  123. else
  124. vs_crtc_state->output_fmt = MEDIA_BUS_FMT_FIXED;
  125. } else {
  126. vs_crtc_state->output_fmt = bridge_state->input_bus_cfg.format;
  127. }
  128. #else
  129. if (connector->display_info.num_bus_formats)
  130. vs_crtc_state->output_fmt = connector->display_info.bus_formats[0];
  131. else
  132. vs_crtc_state->output_fmt = MEDIA_BUS_FMT_RGB888_1X24;
  133. #endif
  134. switch (vs_crtc_state->output_fmt) {
  135. case MEDIA_BUS_FMT_FIXED:
  136. case MEDIA_BUS_FMT_RGB565_1X16:
  137. case MEDIA_BUS_FMT_RGB666_1X18:
  138. case MEDIA_BUS_FMT_RGB888_1X24:
  139. case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
  140. case MEDIA_BUS_FMT_RGB101010_1X30:
  141. case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
  142. case MEDIA_BUS_FMT_UYVY8_1X16:
  143. case MEDIA_BUS_FMT_YUV8_1X24:
  144. case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
  145. case MEDIA_BUS_FMT_UYVY10_1X20:
  146. case MEDIA_BUS_FMT_YUV10_1X30:
  147. ret = 0;
  148. break;
  149. default:
  150. ret = -EINVAL;
  151. break;
  152. }
  153. /* If MEDIA_BUS_FMT_FIXED, set it to default value */
  154. if (vs_crtc_state->output_fmt == MEDIA_BUS_FMT_FIXED)
  155. vs_crtc_state->output_fmt = MEDIA_BUS_FMT_RGB888_1X24;
  156. return ret;
  157. }
  158. static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
  159. .atomic_enable = encoder_atomic_enable,
  160. .atomic_check = encoder_atomic_check,
  161. };
  162. static int encoder_bind(struct device *dev, struct device *master, void *data)
  163. {
  164. struct drm_device *drm_dev = data;
  165. struct simple_encoder *simple = dev_get_drvdata(dev);
  166. struct drm_encoder *encoder;
  167. struct drm_bridge *bridge;
  168. struct drm_panel *panel;
  169. int ret;
  170. encoder = &simple->encoder;
  171. /* Encoder. */
  172. ret = drm_encoder_init(drm_dev, encoder, &encoder_funcs,
  173. simple->priv->encoder_type, NULL);
  174. if (ret)
  175. return ret;
  176. drm_encoder_helper_add(encoder, &encoder_helper_funcs);
  177. encoder->possible_crtcs =
  178. drm_of_find_possible_crtcs(drm_dev, dev->of_node);
  179. /* output port is port1*/
  180. ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, &panel, &bridge);
  181. if (ret)
  182. goto err;
  183. if (panel) {
  184. bridge = drm_panel_bridge_add(panel);
  185. if (IS_ERR(bridge))
  186. return PTR_ERR(bridge);
  187. }
  188. #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
  189. ret = drm_bridge_attach(encoder, bridge, NULL, 0);
  190. #else
  191. ret = drm_bridge_attach(encoder, bridge, NULL);
  192. #endif
  193. if (ret)
  194. goto err;
  195. return 0;
  196. err:
  197. drm_encoder_cleanup(encoder);
  198. return ret;
  199. }
  200. static void encoder_unbind(struct device *dev, struct device *master,
  201. void *data)
  202. {
  203. struct simple_encoder *simple = dev_get_drvdata(dev);
  204. drm_encoder_cleanup(&simple->encoder);
  205. }
  206. static const struct component_ops encoder_component_ops = {
  207. .bind = encoder_bind,
  208. .unbind = encoder_unbind,
  209. };
  210. static const struct of_device_id simple_encoder_dt_match[] = {
  211. { .compatible = "verisilicon,hdmi-encoder", .data = &hdmi_priv},
  212. { .compatible = "verisilicon,dp-encoder", .data = &hdmi_priv},
  213. { .compatible = "verisilicon,dsi-encoder", .data = &dsi_priv},
  214. { .compatible = "verisilicon,dpi-encoder", .data = &dpi_priv},
  215. {},
  216. };
  217. MODULE_DEVICE_TABLE(of, simple_encoder_dt_match);
  218. static int encoder_probe(struct platform_device *pdev)
  219. {
  220. struct device *dev = &pdev->dev;
  221. struct simple_encoder *simple;
  222. int ret;
  223. simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
  224. if (!simple)
  225. return -ENOMEM;
  226. simple->priv = of_device_get_match_data(dev);
  227. simple->dev = dev;
  228. dev_set_drvdata(dev, simple);
  229. ret = encoder_parse_dt(dev);
  230. if (ret)
  231. return ret;
  232. return component_add(dev, &encoder_component_ops);
  233. }
  234. static int encoder_remove(struct platform_device *pdev)
  235. {
  236. struct device *dev = &pdev->dev;
  237. component_del(dev, &encoder_component_ops);
  238. dev_set_drvdata(dev, NULL);
  239. return 0;
  240. }
  241. struct platform_driver simple_encoder_driver = {
  242. .probe = encoder_probe,
  243. .remove = encoder_remove,
  244. .driver = {
  245. .name = "vs-simple-encoder",
  246. .of_match_table = of_match_ptr(simple_encoder_dt_match),
  247. },
  248. };
  249. MODULE_DESCRIPTION("Simple Encoder Driver");
  250. MODULE_LICENSE("GPL v2");