fb-simple.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-02-25 GuEe-GUI the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #define DBG_TAG "fb.simple"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. struct simplefb_format
  17. {
  18. const char *name;
  19. rt_uint32_t mode;
  20. rt_uint32_t bits_per_pixel;
  21. };
  22. struct simplefb_params
  23. {
  24. rt_uint32_t width;
  25. rt_uint32_t height;
  26. rt_uint32_t stride;
  27. struct simplefb_format *format;
  28. };
  29. struct simplefb
  30. {
  31. struct rt_graphic_device parent;
  32. void *screen_base;
  33. rt_size_t screen_size;
  34. rt_size_t stride;
  35. #ifdef RT_USING_CLK
  36. rt_bool_t clk_arr_enabled;
  37. struct rt_clk_array *clk_arr;
  38. #endif
  39. #ifdef RT_USING_REGULATOR
  40. rt_bool_t supplys_enabled;
  41. rt_size_t supplys_nr;
  42. struct rt_regulator **supplys;
  43. #endif
  44. };
  45. #ifdef RT_USING_CLK
  46. static rt_err_t simplefb_clk_probe(struct simplefb *sfb,
  47. struct rt_platform_device *pdev)
  48. {
  49. sfb->clk_arr = rt_clk_get_array(&pdev->parent);
  50. if (rt_is_err(sfb->clk_arr))
  51. {
  52. return rt_ptr_err(sfb->clk_arr);
  53. }
  54. return RT_EOK;
  55. }
  56. static void simplefb_clk_enable(struct simplefb *sfb)
  57. {
  58. rt_clk_array_prepare_enable(sfb->clk_arr);
  59. sfb->clk_arr_enabled = RT_TRUE;
  60. }
  61. static void simplefb_clk_remove(struct simplefb *sfb)
  62. {
  63. if (!rt_is_err_or_null(sfb->clk_arr))
  64. {
  65. if (sfb->clk_arr_enabled)
  66. {
  67. rt_clk_array_disable_unprepare(sfb->clk_arr);
  68. }
  69. rt_clk_array_put(sfb->clk_arr);
  70. }
  71. }
  72. #else
  73. static rt_err_t simplefb_clk_probe(struct simplefb *sfb,
  74. struct rt_platform_device *pdev) { return RT_EOK; }
  75. static void simplefb_clk_enable(struct simplefb *sfb) { }
  76. static void simplefb_clk_remove(struct simplefb *sfb) { }
  77. #endif /* RT_USING_CLK */
  78. #ifdef RT_USING_REGULATOR
  79. #define SUPPLY_SUFFIX "-supply"
  80. static rt_err_t simplefb_regulator_probe(struct simplefb *sfb,
  81. struct rt_platform_device *pdev)
  82. {
  83. int i = 0;
  84. const char *name;
  85. struct rt_device *dev = &pdev->parent;
  86. struct rt_ofw_prop *prop;
  87. struct rt_ofw_node *np = dev->ofw_node;
  88. rt_ofw_foreach_prop(np, prop)
  89. {
  90. name = rt_strstr(prop->name, SUPPLY_SUFFIX);
  91. if (name && name != prop->name)
  92. {
  93. ++sfb->supplys_nr;
  94. }
  95. }
  96. sfb->supplys = rt_calloc(sfb->supplys_nr, sizeof(sfb->supplys[0]));
  97. if (!sfb->supplys)
  98. {
  99. return -RT_ENOMEM;
  100. }
  101. rt_ofw_foreach_prop(np, prop)
  102. {
  103. name = rt_strstr(prop->name, SUPPLY_SUFFIX);
  104. if (name && name != prop->name)
  105. {
  106. char name[32];
  107. int len = name - prop->name;
  108. rt_strncpy(name, prop->name, len);
  109. name[len] = '\0';
  110. sfb->supplys[i] = rt_regulator_get(dev, (const char *)name);
  111. if (rt_is_err(sfb->supplys[i]))
  112. {
  113. return rt_ptr_err(sfb->supplys[i]);
  114. }
  115. ++i;
  116. }
  117. }
  118. return RT_EOK;
  119. }
  120. static void simplefb_regulator_enable(struct simplefb *sfb)
  121. {
  122. if (sfb->supplys)
  123. {
  124. for (int i = 0; i < sfb->supplys_nr; ++i)
  125. {
  126. rt_regulator_enable(sfb->supplys[i]);
  127. }
  128. sfb->supplys_enabled = RT_TRUE;
  129. }
  130. }
  131. static void simplefb_regulator_remove(struct simplefb *sfb)
  132. {
  133. if (sfb->supplys && sfb->supplys_enabled)
  134. {
  135. for (int i = 0; i < sfb->supplys_nr; ++i)
  136. {
  137. struct rt_regulator *supply = sfb->supplys[i];
  138. if (!rt_is_err(supply))
  139. {
  140. rt_regulator_disable(supply);
  141. rt_regulator_put(supply);
  142. }
  143. }
  144. rt_free(sfb->supplys);
  145. }
  146. }
  147. #else
  148. static rt_err_t simplefb_regulator_probe(struct simplefb *sfb,
  149. struct rt_platform_device *pdev)
  150. {
  151. return RT_EOK;
  152. }
  153. static void simplefb_regulator_enable(struct simplefb *sfb)
  154. {
  155. }
  156. static void simplefb_regulator_remove(struct simplefb *sfb)
  157. {
  158. }
  159. #endif /* RT_USING_REGULATOR */
  160. static struct simplefb_format simplefb_formats[] =
  161. {
  162. { "r5g6b5", RTGRAPHIC_PIXEL_FORMAT_RGB565, 16 },
  163. { "r8g8b8", RTGRAPHIC_PIXEL_FORMAT_RGB888, 24 },
  164. { "x8r8g8b8", RTGRAPHIC_PIXEL_FORMAT_ARGB888, 32 },
  165. { "a8r8g8b8", RTGRAPHIC_PIXEL_FORMAT_ARGB888, 32 },
  166. { "x8b8g8r8", RTGRAPHIC_PIXEL_FORMAT_ABGR888, 32 },
  167. { "a8b8g8r8", RTGRAPHIC_PIXEL_FORMAT_ABGR888, 32 },
  168. };
  169. static rt_err_t simplefb_params_parse(struct simplefb_params *params,
  170. struct rt_platform_device *pdev)
  171. {
  172. rt_err_t err;
  173. const char *format;
  174. struct rt_device *dev = &pdev->parent;
  175. if ((err = rt_dm_dev_prop_read_u32(dev, "width", &params->width)))
  176. {
  177. LOG_E("Can't parse width property");
  178. return err;
  179. }
  180. if ((err = rt_dm_dev_prop_read_u32(dev, "height", &params->height)))
  181. {
  182. LOG_E("Can't parse height property");
  183. return err;
  184. }
  185. if ((err = rt_dm_dev_prop_read_u32(dev, "stride", &params->stride)))
  186. {
  187. LOG_E("Can't parse stride property");
  188. return err;
  189. }
  190. if ((err = rt_dm_dev_prop_read_string(dev, "format", &format)))
  191. {
  192. LOG_E("Can't parse format property");
  193. return err;
  194. }
  195. for (int i = 0; i < RT_ARRAY_SIZE(simplefb_formats); ++i)
  196. {
  197. if (rt_strcmp(format, simplefb_formats[i].name))
  198. {
  199. continue;
  200. }
  201. params->format = &simplefb_formats[i];
  202. return RT_EOK;
  203. }
  204. LOG_E("Unsupport format value");
  205. return -RT_EINVAL;
  206. }
  207. static rt_err_t simplefb_plane_fb_remap(struct rt_graphic_plane *plane,
  208. rt_uint32_t mode, struct rt_device_rect_info *rect)
  209. {
  210. struct simplefb *sfb = rt_container_of(plane->graphic, struct simplefb, parent);
  211. plane->line_length = sfb->stride;
  212. plane->bits_per_pixel = rt_graphic_mode_bpp(mode);
  213. plane->framebuffer = sfb->screen_base;
  214. plane->screen_len = sfb->screen_size;
  215. plane->framebuffer_len = sfb->screen_size;
  216. return RT_EOK;
  217. }
  218. static const struct rt_graphic_plane_ops simplefb_plane_ops =
  219. {
  220. .fb_remap = simplefb_plane_fb_remap,
  221. };
  222. static rt_err_t simplefb_probe(struct rt_platform_device *pdev)
  223. {
  224. rt_err_t err;
  225. rt_uint64_t addr, size;
  226. struct simplefb_params params = {};
  227. struct simplefb *sfb = rt_calloc(1, sizeof(*sfb));
  228. if (!sfb)
  229. {
  230. return -RT_ENOMEM;
  231. }
  232. if ((err = simplefb_params_parse(&params, pdev)))
  233. {
  234. goto _fail;
  235. }
  236. sfb->stride = params.stride;
  237. if ((err = rt_dm_dev_get_address(&pdev->parent, 0, &addr, &size)))
  238. {
  239. goto _fail;
  240. }
  241. sfb->screen_size = (rt_size_t)size;
  242. sfb->screen_base = rt_ioremap_wt((void *)addr, sfb->screen_size);
  243. if (!sfb->screen_base)
  244. {
  245. err = -RT_EIO;
  246. goto _fail;
  247. }
  248. if ((err = simplefb_clk_probe(sfb, pdev)))
  249. {
  250. LOG_E("Get %s error = %s", "clk", rt_strerror(err));
  251. goto _fail;
  252. }
  253. if ((err = simplefb_regulator_probe(sfb, pdev)))
  254. {
  255. LOG_E("Get %s error = %s", "regulator", rt_strerror(err));
  256. goto _fail;
  257. }
  258. simplefb_clk_enable(sfb);
  259. simplefb_regulator_enable(sfb);
  260. if ((err = rt_graphic_device_simple_register(&sfb->parent,
  261. params.width, params.height, 0, &simplefb_plane_ops,
  262. &params.format->mode, 1)))
  263. {
  264. goto _fail;
  265. }
  266. pdev->parent.user_data = sfb;
  267. return RT_EOK;
  268. _fail:
  269. if (sfb->screen_base)
  270. {
  271. rt_iounmap(sfb->screen_base);
  272. }
  273. simplefb_clk_remove(sfb);
  274. simplefb_regulator_remove(sfb);
  275. rt_free(sfb);
  276. return err;
  277. }
  278. static rt_err_t simplefb_remove(struct rt_platform_device *pdev)
  279. {
  280. struct simplefb *sfb = pdev->parent.user_data;
  281. rt_graphic_device_simple_unregister(&sfb->parent);
  282. simplefb_clk_remove(sfb);
  283. simplefb_regulator_remove(sfb);
  284. rt_iounmap(sfb->screen_base);
  285. rt_free(sfb);
  286. return RT_EOK;
  287. }
  288. static const struct rt_ofw_node_id simplefb_ofw_ids[] =
  289. {
  290. { .compatible = "simple-framebuffer" },
  291. { /* sentinel */ }
  292. };
  293. static struct rt_platform_driver simplefb_driver =
  294. {
  295. .name = "simple-framebuffer",
  296. .ids = simplefb_ofw_ids,
  297. .probe = simplefb_probe,
  298. .remove = simplefb_remove,
  299. };
  300. RT_PLATFORM_DRIVER_EXPORT(simplefb_driver);