hdmi.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /*
  2. * Copyright (C) 2012 Avionic Design GmbH
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sub license,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the
  12. * next paragraph) shall be included in all copies or substantial portions
  13. * of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <linux/bitops.h>
  24. #include <linux/bug.h>
  25. #include <linux/errno.h>
  26. #include <linux/export.h>
  27. #include <linux/hdmi.h>
  28. #include <linux/string.h>
  29. static void hdmi_infoframe_checksum(void *buffer, size_t size)
  30. {
  31. u8 *ptr = buffer;
  32. u8 csum = 0;
  33. size_t i;
  34. /* compute checksum */
  35. for (i = 0; i < size; i++)
  36. csum += ptr[i];
  37. ptr[3] = 256 - csum;
  38. }
  39. /**
  40. * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
  41. * @frame: HDMI AVI infoframe
  42. *
  43. * Returns 0 on success or a negative error code on failure.
  44. */
  45. int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
  46. {
  47. memset(frame, 0, sizeof(*frame));
  48. frame->type = HDMI_INFOFRAME_TYPE_AVI;
  49. frame->version = 2;
  50. frame->length = HDMI_AVI_INFOFRAME_SIZE;
  51. return 0;
  52. }
  53. EXPORT_SYMBOL(hdmi_avi_infoframe_init);
  54. /**
  55. * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
  56. * @frame: HDMI AVI infoframe
  57. * @buffer: destination buffer
  58. * @size: size of buffer
  59. *
  60. * Packs the information contained in the @frame structure into a binary
  61. * representation that can be written into the corresponding controller
  62. * registers. Also computes the checksum as required by section 5.3.5 of
  63. * the HDMI 1.4 specification.
  64. *
  65. * Returns the number of bytes packed into the binary buffer or a negative
  66. * error code on failure.
  67. */
  68. ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
  69. size_t size)
  70. {
  71. u8 *ptr = buffer;
  72. size_t length;
  73. length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
  74. if (size < length)
  75. return -ENOSPC;
  76. memset(buffer, 0, size);
  77. ptr[0] = frame->type;
  78. ptr[1] = frame->version;
  79. ptr[2] = frame->length;
  80. ptr[3] = 0; /* checksum */
  81. /* start infoframe payload */
  82. ptr += HDMI_INFOFRAME_HEADER_SIZE;
  83. ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
  84. /*
  85. * Data byte 1, bit 4 has to be set if we provide the active format
  86. * aspect ratio
  87. */
  88. if (frame->active_aspect & 0xf)
  89. ptr[0] |= BIT(4);
  90. if (frame->horizontal_bar_valid)
  91. ptr[0] |= BIT(3);
  92. if (frame->vertical_bar_valid)
  93. ptr[0] |= BIT(2);
  94. ptr[1] = ((frame->colorimetry & 0x3) << 6) |
  95. ((frame->picture_aspect & 0x3) << 4) |
  96. (frame->active_aspect & 0xf);
  97. ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |
  98. ((frame->quantization_range & 0x3) << 2) |
  99. (frame->nups & 0x3);
  100. if (frame->itc)
  101. ptr[2] |= BIT(7);
  102. ptr[3] = frame->video_code & 0x7f;
  103. ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |
  104. ((frame->content_type & 0x3) << 4) |
  105. (frame->pixel_repeat & 0xf);
  106. ptr[5] = frame->top_bar & 0xff;
  107. ptr[6] = (frame->top_bar >> 8) & 0xff;
  108. ptr[7] = frame->bottom_bar & 0xff;
  109. ptr[8] = (frame->bottom_bar >> 8) & 0xff;
  110. ptr[9] = frame->left_bar & 0xff;
  111. ptr[10] = (frame->left_bar >> 8) & 0xff;
  112. ptr[11] = frame->right_bar & 0xff;
  113. ptr[12] = (frame->right_bar >> 8) & 0xff;
  114. hdmi_infoframe_checksum(buffer, length);
  115. return length;
  116. }
  117. EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
  118. /**
  119. * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe
  120. * @frame: HDMI SPD infoframe
  121. * @vendor: vendor string
  122. * @product: product string
  123. *
  124. * Returns 0 on success or a negative error code on failure.
  125. */
  126. int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
  127. const char *vendor, const char *product)
  128. {
  129. memset(frame, 0, sizeof(*frame));
  130. frame->type = HDMI_INFOFRAME_TYPE_SPD;
  131. frame->version = 1;
  132. frame->length = HDMI_SPD_INFOFRAME_SIZE;
  133. strncpy(frame->vendor, vendor, sizeof(frame->vendor));
  134. strncpy(frame->product, product, sizeof(frame->product));
  135. return 0;
  136. }
  137. EXPORT_SYMBOL(hdmi_spd_infoframe_init);
  138. /**
  139. * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer
  140. * @frame: HDMI SPD infoframe
  141. * @buffer: destination buffer
  142. * @size: size of buffer
  143. *
  144. * Packs the information contained in the @frame structure into a binary
  145. * representation that can be written into the corresponding controller
  146. * registers. Also computes the checksum as required by section 5.3.5 of
  147. * the HDMI 1.4 specification.
  148. *
  149. * Returns the number of bytes packed into the binary buffer or a negative
  150. * error code on failure.
  151. */
  152. ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
  153. size_t size)
  154. {
  155. u8 *ptr = buffer;
  156. size_t length;
  157. length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
  158. if (size < length)
  159. return -ENOSPC;
  160. memset(buffer, 0, size);
  161. ptr[0] = frame->type;
  162. ptr[1] = frame->version;
  163. ptr[2] = frame->length;
  164. ptr[3] = 0; /* checksum */
  165. /* start infoframe payload */
  166. ptr += HDMI_INFOFRAME_HEADER_SIZE;
  167. memcpy(ptr, frame->vendor, sizeof(frame->vendor));
  168. memcpy(ptr + 8, frame->product, sizeof(frame->product));
  169. ptr[24] = frame->sdi;
  170. hdmi_infoframe_checksum(buffer, length);
  171. return length;
  172. }
  173. EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
  174. /**
  175. * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe
  176. * @frame: HDMI audio infoframe
  177. *
  178. * Returns 0 on success or a negative error code on failure.
  179. */
  180. int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
  181. {
  182. memset(frame, 0, sizeof(*frame));
  183. frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
  184. frame->version = 1;
  185. frame->length = HDMI_AUDIO_INFOFRAME_SIZE;
  186. return 0;
  187. }
  188. EXPORT_SYMBOL(hdmi_audio_infoframe_init);
  189. /**
  190. * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
  191. * @frame: HDMI audio infoframe
  192. * @buffer: destination buffer
  193. * @size: size of buffer
  194. *
  195. * Packs the information contained in the @frame structure into a binary
  196. * representation that can be written into the corresponding controller
  197. * registers. Also computes the checksum as required by section 5.3.5 of
  198. * the HDMI 1.4 specification.
  199. *
  200. * Returns the number of bytes packed into the binary buffer or a negative
  201. * error code on failure.
  202. */
  203. ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
  204. void *buffer, size_t size)
  205. {
  206. unsigned char channels;
  207. u8 *ptr = buffer;
  208. size_t length;
  209. length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
  210. if (size < length)
  211. return -ENOSPC;
  212. memset(buffer, 0, size);
  213. if (frame->channels >= 2)
  214. channels = frame->channels - 1;
  215. else
  216. channels = 0;
  217. ptr[0] = frame->type;
  218. ptr[1] = frame->version;
  219. ptr[2] = frame->length;
  220. ptr[3] = 0; /* checksum */
  221. /* start infoframe payload */
  222. ptr += HDMI_INFOFRAME_HEADER_SIZE;
  223. ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
  224. ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
  225. (frame->sample_size & 0x3);
  226. ptr[2] = frame->coding_type_ext & 0x1f;
  227. ptr[3] = frame->channel_allocation;
  228. ptr[4] = (frame->level_shift_value & 0xf) << 3;
  229. if (frame->downmix_inhibit)
  230. ptr[4] |= BIT(7);
  231. hdmi_infoframe_checksum(buffer, length);
  232. return length;
  233. }
  234. EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
  235. /**
  236. * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary
  237. * buffer
  238. * @frame: HDMI vendor infoframe
  239. * @buffer: destination buffer
  240. * @size: size of buffer
  241. *
  242. * Packs the information contained in the @frame structure into a binary
  243. * representation that can be written into the corresponding controller
  244. * registers. Also computes the checksum as required by section 5.3.5 of
  245. * the HDMI 1.4 specification.
  246. *
  247. * Returns the number of bytes packed into the binary buffer or a negative
  248. * error code on failure.
  249. */
  250. ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
  251. void *buffer, size_t size)
  252. {
  253. u8 *ptr = buffer;
  254. size_t length;
  255. length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
  256. if (size < length)
  257. return -ENOSPC;
  258. memset(buffer, 0, size);
  259. ptr[0] = frame->type;
  260. ptr[1] = frame->version;
  261. ptr[2] = frame->length;
  262. ptr[3] = 0; /* checksum */
  263. memcpy(&ptr[HDMI_INFOFRAME_HEADER_SIZE], frame->data, frame->length);
  264. hdmi_infoframe_checksum(buffer, length);
  265. return length;
  266. }
  267. EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
  268. /**
  269. * hdmi_infoframe_pack() - write a HDMI infoframe to binary buffer
  270. * @frame: HDMI infoframe
  271. * @buffer: destination buffer
  272. * @size: size of buffer
  273. *
  274. * Packs the information contained in the @frame structure into a binary
  275. * representation that can be written into the corresponding controller
  276. * registers. Also computes the checksum as required by section 5.3.5 of
  277. * the HDMI 1.4 specification.
  278. *
  279. * Returns the number of bytes packed into the binary buffer or a negative
  280. * error code on failure.
  281. */
  282. ssize_t
  283. hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size)
  284. {
  285. ssize_t length;
  286. switch (frame->any.type) {
  287. case HDMI_INFOFRAME_TYPE_AVI:
  288. length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size);
  289. break;
  290. case HDMI_INFOFRAME_TYPE_SPD:
  291. length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);
  292. break;
  293. case HDMI_INFOFRAME_TYPE_AUDIO:
  294. length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size);
  295. break;
  296. case HDMI_INFOFRAME_TYPE_VENDOR:
  297. length = hdmi_vendor_infoframe_pack(&frame->vendor,
  298. buffer, size);
  299. break;
  300. default:
  301. WARN(1, "Bad infoframe type %d\n", frame->any.type);
  302. length = -EINVAL;
  303. }
  304. return length;
  305. }
  306. EXPORT_SYMBOL(hdmi_infoframe_pack);