graphic_simple.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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 "graphic.simple"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. static rt_uint32_t edid_dpi_to_mm(rt_uint32_t dpi, rt_uint32_t res)
  17. {
  18. return res * 254 / 10 / dpi;
  19. }
  20. static void edid_checksum(rt_uint8_t *edid, rt_size_t len)
  21. {
  22. rt_uint32_t sum = 0;
  23. for (int i = 0; i < len; ++i)
  24. {
  25. sum += edid[i];
  26. }
  27. sum &= 0xff;
  28. if (sum)
  29. {
  30. edid[len] = 0x100 - sum;
  31. }
  32. }
  33. static void fill_edid(struct rt_graphic_device *gdev,
  34. rt_uint32_t width, rt_uint32_t height, rt_uint32_t refresh_hz)
  35. {
  36. union
  37. {
  38. rt_uint32_t u32;
  39. rt_uint16_t u16;
  40. } value;
  41. int dt_idx = 0;
  42. int width_mm, height_mm;
  43. rt_uint64_t clock;
  44. rt_uint32_t xfront, xsync, xblank, yfront, ysync, yblank;
  45. struct edid *edid = &gdev->edid;
  46. struct detailed_timing *dt;
  47. struct detailed_pixel_timing *dpt;
  48. struct detailed_non_pixel *dnp;
  49. refresh_hz = refresh_hz ? : 75000;
  50. width_mm = edid_dpi_to_mm(100, width);
  51. height_mm = edid_dpi_to_mm(100, height);
  52. /* EDID: timings */
  53. xfront = width * 25 / 100;
  54. xsync = width * 3 / 100;
  55. xblank = width * 35 / 100;
  56. yfront = height * 5 / 1000;
  57. ysync = height * 5 / 1000;
  58. yblank = height * 35 / 1000;
  59. clock = ((rt_uint64_t)refresh_hz * (width + xblank) * (height + yblank)) / 10000000;
  60. if (width >= 4096 || height >= 4096 || clock >= 65536)
  61. {
  62. LOG_E("%s: Large screen %ux%u@%uHz is not supported in simple",
  63. rt_dm_dev_get_name(&gdev->parent), width, height, clock);
  64. RT_ASSERT(0);
  65. }
  66. /* EDID: extensions */
  67. /* EDID: header information */
  68. edid->header[0] = 0x00;
  69. edid->header[1] = 0xff;
  70. edid->header[2] = 0xff;
  71. edid->header[3] = 0xff;
  72. edid->header[4] = 0xff;
  73. edid->header[5] = 0xff;
  74. edid->header[6] = 0xff;
  75. edid->header[7] = 0x00;
  76. /* Vendor id */
  77. value.u16 = rt_cpu_to_be16(
  78. ((('R' - '@') & 0x1f) << 10) |
  79. ((('T' - '@') & 0x1f) << 5) |
  80. ((('T' - '@') & 0x1f) << 0));
  81. rt_memcpy(edid->mfg_id, &value.u16, sizeof(edid->mfg_id));
  82. /* Product code */
  83. value.u16 = rt_cpu_to_le16(0x1234);
  84. rt_memcpy(edid->prod_code, &value.u16, sizeof(edid->prod_code));
  85. /* Serial number */
  86. edid->serial = rt_cpu_to_le32(0);
  87. /* Manufacture week and year */
  88. edid->mfg_week = 42;
  89. edid->mfg_year = 2014 - 1990;
  90. /* Version */
  91. edid->version = 1;
  92. edid->revision = 4;
  93. /* EDID: basic display parameters */
  94. /* Video input: digital, 8bpc, displayport */
  95. edid->input = 0xa5;
  96. /* Screen size */
  97. edid->width_cm = width_mm / 10;
  98. edid->height_cm = height_mm / 10;
  99. /* Gamma: 2.2 */
  100. edid->gamma = 220 - 100;
  101. /* Features: STD sRGB, preferred timing */
  102. edid->features = 0x06;
  103. /* EDID: chromaticity coordinates */
  104. /*
  105. * STD sRGB colorspace:
  106. * X Y
  107. * red: 0.6400, 0.3300
  108. * green: 0.3000, 0.6000
  109. * blue: 0.1500, 0.0600
  110. * white point: 0.3127, 0.3290
  111. *
  112. * value = (uint32_t)(value * 1024 + 0.5)
  113. *
  114. * red_x = 0.6400 * 1024 + 0.5 = 655.86 => 655
  115. * red_y = 0.3300 * 1024 + 0.5 = 338.42 => 338
  116. * green_x = 0.3000 * 1024 + 0.5 = 307.7 => 307
  117. * green_y = 0.6000 * 1024 + 0.5 = 614.9 => 614
  118. * blue_x = 0.1500 * 1024 + 0.5 = 154.1 => 154
  119. * blue_y = 0.0600 * 1024 + 0.5 = 61.94 => 61
  120. * white_x = 0.3127 * 1024 + 0.5 = 320.7048 => 320
  121. * white_y = 0.3290 * 1024 + 0.5 = 337.396 => 337
  122. */
  123. edid->red_green_lo = (((655 & 0x03) << 6) | /* red_x */
  124. ((338 & 0x03) << 4) | /* red_y */
  125. ((307 & 0x03) << 2) | /* green_x */
  126. ((614 & 0x03) << 0)); /* green_y */
  127. edid->black_white_lo = (((154 & 0x03) << 6) | /* blue_x */
  128. ((154 & 0x03) << 4) | /* blue_y */
  129. ((320 & 0x03) << 2) | /* white_x */
  130. ((337 & 0x03) << 0)); /* white_y */
  131. edid->red_x = 655 >> 2; /* red_x */
  132. edid->red_y = 338 >> 2; /* red_y */
  133. edid->green_x = 307 >> 2; /* green_x */
  134. edid->green_y = 614 >> 2; /* green_y */
  135. edid->blue_x = 154 >> 2; /* blue_x */
  136. edid->blue_y = 154 >> 2; /* blue_y */
  137. edid->white_x = 320 >> 2; /* white_x */
  138. edid->white_y = 337 >> 2; /* white_y */
  139. /* EDID: established timing bitmap */
  140. /* EDID: standard timing information */
  141. /* EDID: descriptor blocks */
  142. dt = &edid->detailed_timings[dt_idx++];
  143. dpt = &dt->data.pixel_data;
  144. dt->pixel_clock = rt_cpu_to_le16(clock);
  145. dpt->hactive_lo = width & 0xff;
  146. dpt->hblank_lo = xblank & 0xff;
  147. dpt->hactive_hblank_hi = (((width & 0xf00) >> 4) | ((xblank & 0xf00) >> 8));
  148. dpt->vactive_lo = height & 0xff;
  149. dpt->vblank_lo = yblank & 0xff;
  150. dpt->vactive_vblank_hi = (((height & 0xf00) >> 4) | ((yblank & 0xf00) >> 8));
  151. dpt->hsync_offset_lo = xfront & 0xff;
  152. dpt->hsync_pulse_width_lo = xsync & 0xff;
  153. dpt->vsync_offset_pulse_width_lo = (((yfront & 0x00f) << 4) |
  154. ((ysync & 0x00f) << 0));
  155. dpt->hsync_vsync_offset_pulse_width_hi = (((xfront & 0x300) >> 2) |
  156. ((xsync & 0x300) >> 4) |
  157. ((yfront & 0x030) >> 2) |
  158. ((ysync & 0x030) >> 4));
  159. dpt->width_mm_lo = width_mm & 0xff;
  160. dpt->height_mm_lo = height_mm & 0xff;
  161. dpt->width_height_mm_hi = (((width_mm & 0xf00) >> 4) |
  162. ((height_mm & 0xf00) >> 8));
  163. dpt->misc = 0x18;
  164. /* XTRA3 STD */
  165. dt = &edid->detailed_timings[dt_idx++];
  166. dnp = &dt->data.other_data;
  167. dnp->type = EDID_DETAIL_EST_TIMINGS;
  168. dnp->data.timings[0].hsize = 10;
  169. /* Ranges */
  170. dt = &edid->detailed_timings[dt_idx++];
  171. dnp = &dt->data.other_data;
  172. dnp->type = EDID_DETAIL_MONITOR_RANGE;
  173. dnp->data.range.min_vfreq = 50;
  174. dnp->data.range.max_vfreq = 125;
  175. dnp->data.range.min_hfreq_khz = 30;
  176. dnp->data.range.max_hfreq_khz = 160;
  177. dnp->data.range.pixel_clock_mhz = 2550 / 10;
  178. dnp->data.range.flags = 0x01;
  179. rt_memcpy(&dnp->data.range.flags + 1, "\n ", 7);
  180. while (dt_idx < RT_ARRAY_SIZE(edid->detailed_timings))
  181. {
  182. /* Dummy */
  183. dt = &edid->detailed_timings[dt_idx++];
  184. dnp = &dt->data.other_data;
  185. dnp->type = 0x10;
  186. }
  187. /* EDID: display id extensions */
  188. /* EDID: checksum */
  189. edid_checksum((void *)edid, 127);
  190. }
  191. rt_err_t rt_graphic_device_simple_edid(struct rt_graphic_device *gdev,
  192. rt_uint32_t width, rt_uint32_t height, rt_uint32_t refresh_hz)
  193. {
  194. if (!gdev || !width || !height)
  195. {
  196. return -RT_EINVAL;
  197. }
  198. fill_edid(gdev, width, height, refresh_hz);
  199. return RT_EOK;
  200. }
  201. static const struct rt_graphic_device_ops graphic_device_simple_ops =
  202. {
  203. };
  204. rt_err_t rt_graphic_device_simple_register(struct rt_graphic_device *gdev,
  205. rt_uint32_t width, rt_uint32_t height, rt_uint32_t refresh_hz,
  206. const struct rt_graphic_plane_ops *plane_ops,
  207. const rt_uint32_t *modes, rt_uint32_t modes_nr)
  208. {
  209. rt_err_t err;
  210. struct rt_graphic_plane *plane;
  211. if (!gdev || !width || !height || !plane_ops || !modes || !modes_nr)
  212. {
  213. return -RT_EINVAL;
  214. }
  215. if (!gdev->ops)
  216. {
  217. gdev->ops = &graphic_device_simple_ops;
  218. }
  219. plane = rt_graphic_device_alloc_plane(gdev, 0, plane_ops, modes, modes_nr,
  220. RT_GRAPHIC_PLANE_TYPE_PRIMARY);
  221. if (!plane)
  222. {
  223. return -RT_EINVAL;
  224. }
  225. if ((err = rt_graphic_device_add_plane(gdev, plane)))
  226. {
  227. goto _free_plane;
  228. }
  229. rt_graphic_device_simple_edid(gdev, width, height, refresh_hz);
  230. err = rt_graphic_device_register(gdev);
  231. _free_plane:
  232. if (err)
  233. {
  234. rt_free(plane);
  235. }
  236. return err;
  237. }
  238. rt_err_t rt_graphic_device_simple_unregister(struct rt_graphic_device *gdev)
  239. {
  240. return rt_graphic_device_unregister(gdev);
  241. }