drv_hdmi.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-10-26 bigmagic first version
  9. */
  10. #include <stdint.h>
  11. #include <rtthread.h>
  12. #include "mbox.h"
  13. #include "drv_hdmi.h"
  14. #ifdef USING_LCD_CONSOLE
  15. #include "lcd_console.h"
  16. #endif
  17. #if defined(BSP_USING_HDMI_DISPLAY) || defined(BSP_USING_DSI_DISPLAY)
  18. #define LCD_WIDTH (800)
  19. #define LCD_HEIGHT (480)
  20. #define LCD_DEPTH (4)
  21. #define LCD_BPP (32)
  22. #define TAG_ALLOCATE_BUFFER 0x00040001
  23. #define TAG_SET_PHYS_WIDTH_HEIGHT 0x00048003
  24. #define TAG_SET_VIRT_WIDTH_HEIGHT 0x00048004
  25. #define TAG_SET_DEPTH 0x00048005
  26. #define TAG_SET_PIXEL_ORDER 0x00048006
  27. #define TAG_GET_PITCH 0x00040008
  28. #define TAG_SET_VIRT_OFFSET 0x00048009
  29. #define TAG_END 0x00000000
  30. enum {
  31. MBOX_TAG_FB_GET_GPIOVIRT = 0x00040010,
  32. MBOX_TAG_FB_ALLOCATE_BUFFER = 0x00040001,
  33. MBOX_TAG_FB_RELEASE_BUFFER = 0x00048001,
  34. MBOX_TAG_FB_BLANK_SCREEN = 0x00040002,
  35. MBOX_TAG_FB_GET_PHYS_WH = 0x00040003,
  36. MBOX_TAG_FB_TEST_PHYS_WH = 0x00044003,
  37. MBOX_TAG_FB_SET_PHYS_WH = 0x00048003,
  38. MBOX_TAG_FB_GET_VIRT_WH = 0x00040004,
  39. MBOX_TAG_FB_TEST_VIRT_WH = 0x00044004,
  40. MBOX_TAG_FB_SET_VIRT_WH = 0x00048004,
  41. MBOX_TAG_FB_GET_DEPTH = 0x00040005,
  42. MBOX_TAG_FB_TEST_DEPTH = 0x00044005,
  43. MBOX_TAG_FB_SET_DEPTH = 0x00048005,
  44. MBOX_TAG_FB_GET_PIXEL_ORDER = 0x00040006,
  45. MBOX_TAG_FB_TEST_PIXEL_ORDER = 0x00044006,
  46. MBOX_TAG_FB_SET_PIXEL_ORDER = 0x00048006,
  47. MBOX_TAG_FB_GET_ALPHA_MODE = 0x00040007,
  48. MBOX_TAG_FB_TEST_ALPHA_MODE = 0x00044007,
  49. MBOX_TAG_FB_SET_ALPHA_MODE = 0x00048007,
  50. MBOX_TAG_FB_GET_PITCH = 0x00040008,
  51. MBOX_TAG_FB_GET_VIRT_OFFSET = 0x00040009,
  52. MBOX_TAG_FB_TEST_VIRT_OFFSET = 0x00044009,
  53. MBOX_TAG_FB_SET_VIRT_OFFSET = 0x00048009,
  54. MBOX_TAG_FB_GET_OVERSCAN = 0x0004000a,
  55. MBOX_TAG_FB_TEST_OVERSCAN = 0x0004400a,
  56. MBOX_TAG_FB_SET_OVERSCAN = 0x0004800a,
  57. MBOX_TAG_FB_GET_PALETTE = 0x0004000b,
  58. MBOX_TAG_FB_TEST_PALETTE = 0x0004400b,
  59. MBOX_TAG_FB_SET_PALETTE = 0x0004800b,
  60. };
  61. #define LCD_DEVICE(dev) (struct rt_hdmi_fb_device*)(dev)
  62. static struct rt_hdmi_fb_device _hdmi;
  63. typedef rt_uint16_t color_t;
  64. rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag)
  65. {
  66. return RT_EOK;
  67. }
  68. rt_err_t hdmi_fb_close(rt_device_t dev)
  69. {
  70. return RT_EOK;
  71. }
  72. rt_size_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size)
  73. {
  74. return 0;
  75. }
  76. rt_size_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  77. {
  78. #ifdef USING_LCD_CONSOLE
  79. fb_print((char*)buffer);
  80. #endif
  81. return size;
  82. }
  83. rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args)
  84. {
  85. struct rt_hdmi_fb_device *lcd = LCD_DEVICE(dev);
  86. switch (cmd)
  87. {
  88. case RTGRAPHIC_CTRL_RECT_UPDATE:
  89. {
  90. struct rt_device_rect_info *info = (struct rt_device_rect_info*)args;
  91. info = info;
  92. }
  93. break;
  94. case RTGRAPHIC_CTRL_GET_INFO:
  95. {
  96. struct rt_device_graphic_info* info = (struct rt_device_graphic_info*)args;
  97. RT_ASSERT(info != RT_NULL);
  98. info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
  99. info->bits_per_pixel= 32;
  100. info->width = lcd->width;
  101. info->height = lcd->height;
  102. info->framebuffer = lcd->fb;
  103. }
  104. break;
  105. }
  106. return RT_EOK;
  107. }
  108. #ifdef RT_USING_DEVICE_OPS
  109. const static struct rt_device_ops hdmi_fb_ops =
  110. {
  111. RT_NULL,
  112. hdmi_fb_open,
  113. hdmi_fb_close,
  114. hdmi_fb_read,
  115. hdmi_fb_write,
  116. hdmi_fb_control,
  117. };
  118. #endif
  119. rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name)
  120. {
  121. struct rt_device *device;
  122. RT_ASSERT(hdmi_fb != RT_NULL);
  123. device = &hdmi_fb->parent;
  124. /* set device type */
  125. device->type = RT_Device_Class_Graphic;
  126. /* initialize device interface */
  127. #ifdef RT_USING_DEVICE_OPS
  128. device->ops = &hdmi_fb_ops;
  129. #else
  130. device->init = RT_NULL;
  131. device->open = hdmi_fb_open;
  132. device->close = hdmi_fb_close;
  133. device->read = hdmi_fb_read;
  134. device->write = hdmi_fb_write;
  135. device->control = hdmi_fb_control;
  136. #endif
  137. /* register to device manager */
  138. rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
  139. return RT_EOK;
  140. }
  141. rt_uint32_t bcm271x_mbox_fb_get_gpiovirt(void)
  142. {
  143. mbox[0] = 8*4; // length of the message
  144. mbox[1] = MBOX_REQUEST; // this is a request message
  145. mbox[2] = MBOX_TAG_FB_GET_GPIOVIRT;
  146. mbox[3] = 4; // buffer size
  147. mbox[4] = 0; // len
  148. mbox[5] = 0; // id
  149. mbox[6] = 0;
  150. mbox[7] = MBOX_TAG_LAST;
  151. mbox_call(8, MMU_DISABLE);
  152. return (mbox[5] & 0x3fffffff);
  153. }
  154. rt_uint32_t bcm271x_mbox_fb_get_pitch(void)
  155. {
  156. mbox[0] = 8*4; // length of the message
  157. mbox[1] = MBOX_REQUEST; // this is a request message
  158. mbox[2] = MBOX_TAG_FB_GET_PITCH;
  159. mbox[3] = 4; // buffer size
  160. mbox[4] = 0; // len
  161. mbox[5] = 0; // id
  162. mbox[6] = 0;
  163. mbox[7] = MBOX_TAG_LAST;
  164. mbox_call(8, MMU_DISABLE);
  165. return mbox[5];
  166. }
  167. void bcm271x_mbox_fb_set_porder(int rgb)
  168. {
  169. mbox[0] = 8*4; // length of the message
  170. mbox[1] = MBOX_REQUEST; // this is a request message
  171. mbox[2] = MBOX_TAG_FB_SET_PIXEL_ORDER;
  172. mbox[3] = 4; // buffer size
  173. mbox[4] = 4; // len
  174. mbox[5] = rgb; // id
  175. mbox[6] = 0;
  176. mbox[7] = MBOX_TAG_LAST;
  177. mbox_call(8, MMU_DISABLE);
  178. }
  179. void bcm271x_mbox_fb_setoffset(int xoffset, int yoffset)
  180. {
  181. mbox[0] = 8*4; // length of the message
  182. mbox[1] = MBOX_REQUEST; // this is a request message
  183. mbox[2] = MBOX_TAG_FB_SET_VIRT_OFFSET;
  184. mbox[3] = 8; // buffer size
  185. mbox[4] = 8; // len
  186. mbox[5] = xoffset; // id
  187. mbox[6] = yoffset;
  188. mbox[7] = MBOX_TAG_LAST;
  189. mbox_call(8, MMU_DISABLE);
  190. }
  191. void bcm271x_mbox_fb_setalpha(int alpha)
  192. {
  193. mbox[0] = 8*4; // length of the message
  194. mbox[1] = MBOX_REQUEST; // this is a request message
  195. mbox[2] = MBOX_TAG_FB_SET_ALPHA_MODE;
  196. mbox[3] = 4; // buffer size
  197. mbox[4] = 4; // len
  198. mbox[5] = alpha; // id
  199. mbox[6] = 0;
  200. mbox[7] = MBOX_TAG_LAST;
  201. mbox_call(8, MMU_DISABLE);
  202. }
  203. void *bcm271x_mbox_fb_alloc(int width, int height, int bpp, int nrender)
  204. {
  205. mbox[0] = 4 * 35;
  206. mbox[1] = MBOX_REQUEST;
  207. mbox[2] = TAG_ALLOCATE_BUFFER;//get framebuffer, gets alignment on request
  208. mbox[3] = 8; //size
  209. mbox[4] = 4; //len
  210. mbox[5] = 4096; //The design of MBOX driver forces us to give the virtual address 0x3C100000
  211. mbox[6] = 0; //FrameBufferInfo.size
  212. mbox[7] = TAG_SET_PHYS_WIDTH_HEIGHT;
  213. mbox[8] = 8;
  214. mbox[9] = 8;
  215. mbox[10] = width;
  216. mbox[11] = height;
  217. mbox[12] = TAG_SET_VIRT_WIDTH_HEIGHT;
  218. mbox[13] = 8;
  219. mbox[14] = 8;
  220. mbox[15] = width;
  221. mbox[16] = height * nrender;
  222. mbox[17] = TAG_SET_DEPTH;
  223. mbox[18] = 4;
  224. mbox[19] = 4;
  225. mbox[20] = bpp;
  226. mbox[21] = TAG_SET_PIXEL_ORDER;
  227. mbox[22] = 4;
  228. mbox[23] = 0;
  229. mbox[24] = 0; //RGB, not BGR preferably
  230. mbox[25] = TAG_GET_PITCH;
  231. mbox[26] = 4;
  232. mbox[27] = 0;
  233. mbox[28] = 0;
  234. mbox[29] = TAG_SET_VIRT_OFFSET;
  235. mbox[30] = 8;
  236. mbox[31] = 8;
  237. mbox[32] = 0;
  238. mbox[33] = 0;
  239. mbox[34] = TAG_END;
  240. mbox_call(8, MMU_DISABLE);
  241. return (void *)((rt_uint32_t)(mbox[5] & 0x3fffffff));
  242. }
  243. int hdmi_fb_init(void)
  244. {
  245. _hdmi.fb = (rt_uint8_t *)bcm271x_mbox_fb_alloc(LCD_WIDTH, LCD_HEIGHT, LCD_BPP, 1);
  246. if(_hdmi.fb == RT_NULL)
  247. {
  248. rt_kprintf("init dsi or hdmi err!\n");
  249. return 0;
  250. }
  251. bcm271x_mbox_fb_setoffset(0, 0);
  252. bcm271x_mbox_fb_set_porder(0);
  253. _hdmi.width = LCD_WIDTH;
  254. _hdmi.height = LCD_HEIGHT;
  255. _hdmi.depth = LCD_DEPTH;
  256. _hdmi.pitch = 0;
  257. _hdmi.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
  258. rt_memset(_hdmi.fb, 0, LCD_WIDTH*LCD_HEIGHT*(LCD_BPP/8));
  259. //rt_kprintf("_hdmi.fb is %p\n", _hdmi.fb);
  260. rt_hdmi_fb_device_init(&_hdmi, "hdmi");
  261. return 0;
  262. }
  263. INIT_DEVICE_EXPORT(hdmi_fb_init);
  264. #endif /*BSP_USING_HDMI */