drv_hdmi.c 8.3 KB

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