1f1d7ae31SEmmanuel Vadot /* 2f1d7ae31SEmmanuel Vadot * Copyright (C) 2012 Avionic Design GmbH 3f1d7ae31SEmmanuel Vadot * 4f1d7ae31SEmmanuel Vadot * Permission is hereby granted, free of charge, to any person obtaining a 5f1d7ae31SEmmanuel Vadot * copy of this software and associated documentation files (the "Software"), 6f1d7ae31SEmmanuel Vadot * to deal in the Software without restriction, including without limitation 7f1d7ae31SEmmanuel Vadot * the rights to use, copy, modify, merge, publish, distribute, sub license, 8f1d7ae31SEmmanuel Vadot * and/or sell copies of the Software, and to permit persons to whom the 9f1d7ae31SEmmanuel Vadot * Software is furnished to do so, subject to the following conditions: 10f1d7ae31SEmmanuel Vadot * 11f1d7ae31SEmmanuel Vadot * The above copyright notice and this permission notice (including the 12f1d7ae31SEmmanuel Vadot * next paragraph) shall be included in all copies or substantial portions 13f1d7ae31SEmmanuel Vadot * of the Software. 14f1d7ae31SEmmanuel Vadot * 15f1d7ae31SEmmanuel Vadot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16f1d7ae31SEmmanuel Vadot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17f1d7ae31SEmmanuel Vadot * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18f1d7ae31SEmmanuel Vadot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19f1d7ae31SEmmanuel Vadot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20f1d7ae31SEmmanuel Vadot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21f1d7ae31SEmmanuel Vadot * DEALINGS IN THE SOFTWARE. 22f1d7ae31SEmmanuel Vadot */ 23f1d7ae31SEmmanuel Vadot 24*c89d94adSVladimir Kondratyev #ifdef __linux__ 25*c89d94adSVladimir Kondratyev #include <drm/display/drm_dp.h> 26*c89d94adSVladimir Kondratyev #endif 27f1d7ae31SEmmanuel Vadot #include <linux/bitops.h> 28f1d7ae31SEmmanuel Vadot #include <linux/bug.h> 29f1d7ae31SEmmanuel Vadot #include <linux/errno.h> 30f1d7ae31SEmmanuel Vadot #include <linux/export.h> 31f1d7ae31SEmmanuel Vadot #include <linux/hdmi.h> 32f1d7ae31SEmmanuel Vadot #include <linux/string.h> 33f1d7ae31SEmmanuel Vadot #include <linux/device.h> 34f1d7ae31SEmmanuel Vadot 35f1d7ae31SEmmanuel Vadot #define hdmi_log(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__) 36f1d7ae31SEmmanuel Vadot 37f1d7ae31SEmmanuel Vadot static u8 hdmi_infoframe_checksum(const u8 *ptr, size_t size) 38f1d7ae31SEmmanuel Vadot { 39f1d7ae31SEmmanuel Vadot u8 csum = 0; 40f1d7ae31SEmmanuel Vadot size_t i; 41f1d7ae31SEmmanuel Vadot 42f1d7ae31SEmmanuel Vadot /* compute checksum */ 43f1d7ae31SEmmanuel Vadot for (i = 0; i < size; i++) 44f1d7ae31SEmmanuel Vadot csum += ptr[i]; 45f1d7ae31SEmmanuel Vadot 46f1d7ae31SEmmanuel Vadot return 256 - csum; 47f1d7ae31SEmmanuel Vadot } 48f1d7ae31SEmmanuel Vadot 49f1d7ae31SEmmanuel Vadot static void hdmi_infoframe_set_checksum(void *buffer, size_t size) 50f1d7ae31SEmmanuel Vadot { 51f1d7ae31SEmmanuel Vadot u8 *ptr = buffer; 52f1d7ae31SEmmanuel Vadot 53f1d7ae31SEmmanuel Vadot ptr[3] = hdmi_infoframe_checksum(buffer, size); 54f1d7ae31SEmmanuel Vadot } 55f1d7ae31SEmmanuel Vadot 56f1d7ae31SEmmanuel Vadot /** 57f1d7ae31SEmmanuel Vadot * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe 58f1d7ae31SEmmanuel Vadot * @frame: HDMI AVI infoframe 59f1d7ae31SEmmanuel Vadot */ 60f1d7ae31SEmmanuel Vadot void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame) 61f1d7ae31SEmmanuel Vadot { 62f1d7ae31SEmmanuel Vadot memset(frame, 0, sizeof(*frame)); 63f1d7ae31SEmmanuel Vadot 64f1d7ae31SEmmanuel Vadot frame->type = HDMI_INFOFRAME_TYPE_AVI; 65f1d7ae31SEmmanuel Vadot frame->version = 2; 66f1d7ae31SEmmanuel Vadot frame->length = HDMI_AVI_INFOFRAME_SIZE; 67f1d7ae31SEmmanuel Vadot } 68f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_avi_infoframe_init); 69f1d7ae31SEmmanuel Vadot 70f1d7ae31SEmmanuel Vadot static int hdmi_avi_infoframe_check_only(const struct hdmi_avi_infoframe *frame) 71f1d7ae31SEmmanuel Vadot { 72f1d7ae31SEmmanuel Vadot if (frame->type != HDMI_INFOFRAME_TYPE_AVI || 73f1d7ae31SEmmanuel Vadot frame->version != 2 || 74f1d7ae31SEmmanuel Vadot frame->length != HDMI_AVI_INFOFRAME_SIZE) 75f1d7ae31SEmmanuel Vadot return -EINVAL; 76f1d7ae31SEmmanuel Vadot 77f1d7ae31SEmmanuel Vadot if (frame->picture_aspect > HDMI_PICTURE_ASPECT_16_9) 78f1d7ae31SEmmanuel Vadot return -EINVAL; 79f1d7ae31SEmmanuel Vadot 80f1d7ae31SEmmanuel Vadot return 0; 81f1d7ae31SEmmanuel Vadot } 82f1d7ae31SEmmanuel Vadot 83f1d7ae31SEmmanuel Vadot /** 84f1d7ae31SEmmanuel Vadot * hdmi_avi_infoframe_check() - check a HDMI AVI infoframe 85f1d7ae31SEmmanuel Vadot * @frame: HDMI AVI infoframe 86f1d7ae31SEmmanuel Vadot * 87f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 88f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields. 89f1d7ae31SEmmanuel Vadot * 90f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 91f1d7ae31SEmmanuel Vadot */ 92f1d7ae31SEmmanuel Vadot int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame) 93f1d7ae31SEmmanuel Vadot { 94f1d7ae31SEmmanuel Vadot return hdmi_avi_infoframe_check_only(frame); 95f1d7ae31SEmmanuel Vadot } 96f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_avi_infoframe_check); 97f1d7ae31SEmmanuel Vadot 98f1d7ae31SEmmanuel Vadot /** 99f1d7ae31SEmmanuel Vadot * hdmi_avi_infoframe_pack_only() - write HDMI AVI infoframe to binary buffer 100f1d7ae31SEmmanuel Vadot * @frame: HDMI AVI infoframe 101f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 102f1d7ae31SEmmanuel Vadot * @size: size of buffer 103f1d7ae31SEmmanuel Vadot * 104f1d7ae31SEmmanuel Vadot * Packs the information contained in the @frame structure into a binary 105f1d7ae31SEmmanuel Vadot * representation that can be written into the corresponding controller 106f1d7ae31SEmmanuel Vadot * registers. Also computes the checksum as required by section 5.3.5 of 107f1d7ae31SEmmanuel Vadot * the HDMI 1.4 specification. 108f1d7ae31SEmmanuel Vadot * 109f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 110f1d7ae31SEmmanuel Vadot * error code on failure. 111f1d7ae31SEmmanuel Vadot */ 112f1d7ae31SEmmanuel Vadot ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame, 113f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 114f1d7ae31SEmmanuel Vadot { 115f1d7ae31SEmmanuel Vadot u8 *ptr = buffer; 116f1d7ae31SEmmanuel Vadot size_t length; 117f1d7ae31SEmmanuel Vadot int ret; 118f1d7ae31SEmmanuel Vadot 119f1d7ae31SEmmanuel Vadot ret = hdmi_avi_infoframe_check_only(frame); 120f1d7ae31SEmmanuel Vadot if (ret) 121f1d7ae31SEmmanuel Vadot return ret; 122f1d7ae31SEmmanuel Vadot 123f1d7ae31SEmmanuel Vadot length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; 124f1d7ae31SEmmanuel Vadot 125f1d7ae31SEmmanuel Vadot if (size < length) 126f1d7ae31SEmmanuel Vadot return -ENOSPC; 127f1d7ae31SEmmanuel Vadot 128f1d7ae31SEmmanuel Vadot memset(buffer, 0, size); 129f1d7ae31SEmmanuel Vadot 130f1d7ae31SEmmanuel Vadot ptr[0] = frame->type; 131f1d7ae31SEmmanuel Vadot ptr[1] = frame->version; 132f1d7ae31SEmmanuel Vadot ptr[2] = frame->length; 133f1d7ae31SEmmanuel Vadot ptr[3] = 0; /* checksum */ 134f1d7ae31SEmmanuel Vadot 135f1d7ae31SEmmanuel Vadot /* start infoframe payload */ 136f1d7ae31SEmmanuel Vadot ptr += HDMI_INFOFRAME_HEADER_SIZE; 137f1d7ae31SEmmanuel Vadot 138f1d7ae31SEmmanuel Vadot ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3); 139f1d7ae31SEmmanuel Vadot 140f1d7ae31SEmmanuel Vadot /* 141f1d7ae31SEmmanuel Vadot * Data byte 1, bit 4 has to be set if we provide the active format 142f1d7ae31SEmmanuel Vadot * aspect ratio 143f1d7ae31SEmmanuel Vadot */ 144f1d7ae31SEmmanuel Vadot if (frame->active_aspect & 0xf) 145f1d7ae31SEmmanuel Vadot ptr[0] |= BIT(4); 146f1d7ae31SEmmanuel Vadot 147f1d7ae31SEmmanuel Vadot /* Bit 3 and 2 indicate if we transmit horizontal/vertical bar data */ 148f1d7ae31SEmmanuel Vadot if (frame->top_bar || frame->bottom_bar) 149f1d7ae31SEmmanuel Vadot ptr[0] |= BIT(3); 150f1d7ae31SEmmanuel Vadot 151f1d7ae31SEmmanuel Vadot if (frame->left_bar || frame->right_bar) 152f1d7ae31SEmmanuel Vadot ptr[0] |= BIT(2); 153f1d7ae31SEmmanuel Vadot 154f1d7ae31SEmmanuel Vadot ptr[1] = ((frame->colorimetry & 0x3) << 6) | 155f1d7ae31SEmmanuel Vadot ((frame->picture_aspect & 0x3) << 4) | 156f1d7ae31SEmmanuel Vadot (frame->active_aspect & 0xf); 157f1d7ae31SEmmanuel Vadot 158f1d7ae31SEmmanuel Vadot ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) | 159f1d7ae31SEmmanuel Vadot ((frame->quantization_range & 0x3) << 2) | 160f1d7ae31SEmmanuel Vadot (frame->nups & 0x3); 161f1d7ae31SEmmanuel Vadot 162f1d7ae31SEmmanuel Vadot if (frame->itc) 163f1d7ae31SEmmanuel Vadot ptr[2] |= BIT(7); 164f1d7ae31SEmmanuel Vadot 165f1d7ae31SEmmanuel Vadot ptr[3] = frame->video_code & 0x7f; 166f1d7ae31SEmmanuel Vadot 167f1d7ae31SEmmanuel Vadot ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) | 168f1d7ae31SEmmanuel Vadot ((frame->content_type & 0x3) << 4) | 169f1d7ae31SEmmanuel Vadot (frame->pixel_repeat & 0xf); 170f1d7ae31SEmmanuel Vadot 171f1d7ae31SEmmanuel Vadot ptr[5] = frame->top_bar & 0xff; 172f1d7ae31SEmmanuel Vadot ptr[6] = (frame->top_bar >> 8) & 0xff; 173f1d7ae31SEmmanuel Vadot ptr[7] = frame->bottom_bar & 0xff; 174f1d7ae31SEmmanuel Vadot ptr[8] = (frame->bottom_bar >> 8) & 0xff; 175f1d7ae31SEmmanuel Vadot ptr[9] = frame->left_bar & 0xff; 176f1d7ae31SEmmanuel Vadot ptr[10] = (frame->left_bar >> 8) & 0xff; 177f1d7ae31SEmmanuel Vadot ptr[11] = frame->right_bar & 0xff; 178f1d7ae31SEmmanuel Vadot ptr[12] = (frame->right_bar >> 8) & 0xff; 179f1d7ae31SEmmanuel Vadot 180f1d7ae31SEmmanuel Vadot hdmi_infoframe_set_checksum(buffer, length); 181f1d7ae31SEmmanuel Vadot 182f1d7ae31SEmmanuel Vadot return length; 183f1d7ae31SEmmanuel Vadot } 184f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_avi_infoframe_pack_only); 185f1d7ae31SEmmanuel Vadot 186f1d7ae31SEmmanuel Vadot /** 187f1d7ae31SEmmanuel Vadot * hdmi_avi_infoframe_pack() - check a HDMI AVI infoframe, 188f1d7ae31SEmmanuel Vadot * and write it to binary buffer 189f1d7ae31SEmmanuel Vadot * @frame: HDMI AVI infoframe 190f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 191f1d7ae31SEmmanuel Vadot * @size: size of buffer 192f1d7ae31SEmmanuel Vadot * 193f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 194f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields, after which it packs the information 195f1d7ae31SEmmanuel Vadot * contained in the @frame structure into a binary representation that 196f1d7ae31SEmmanuel Vadot * can be written into the corresponding controller registers. This function 197f1d7ae31SEmmanuel Vadot * also computes the checksum as required by section 5.3.5 of the HDMI 1.4 198f1d7ae31SEmmanuel Vadot * specification. 199f1d7ae31SEmmanuel Vadot * 200f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 201f1d7ae31SEmmanuel Vadot * error code on failure. 202f1d7ae31SEmmanuel Vadot */ 203f1d7ae31SEmmanuel Vadot ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, 204f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 205f1d7ae31SEmmanuel Vadot { 206f1d7ae31SEmmanuel Vadot int ret; 207f1d7ae31SEmmanuel Vadot 208f1d7ae31SEmmanuel Vadot ret = hdmi_avi_infoframe_check(frame); 209f1d7ae31SEmmanuel Vadot if (ret) 210f1d7ae31SEmmanuel Vadot return ret; 211f1d7ae31SEmmanuel Vadot 212f1d7ae31SEmmanuel Vadot return hdmi_avi_infoframe_pack_only(frame, buffer, size); 213f1d7ae31SEmmanuel Vadot } 214f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_avi_infoframe_pack); 215f1d7ae31SEmmanuel Vadot 216f1d7ae31SEmmanuel Vadot /** 217f1d7ae31SEmmanuel Vadot * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe 218f1d7ae31SEmmanuel Vadot * @frame: HDMI SPD infoframe 219f1d7ae31SEmmanuel Vadot * @vendor: vendor string 220f1d7ae31SEmmanuel Vadot * @product: product string 221f1d7ae31SEmmanuel Vadot * 222f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 223f1d7ae31SEmmanuel Vadot */ 224f1d7ae31SEmmanuel Vadot int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame, 225f1d7ae31SEmmanuel Vadot const char *vendor, const char *product) 226f1d7ae31SEmmanuel Vadot { 227f1d7ae31SEmmanuel Vadot size_t len; 228f1d7ae31SEmmanuel Vadot 229f1d7ae31SEmmanuel Vadot memset(frame, 0, sizeof(*frame)); 230f1d7ae31SEmmanuel Vadot 231f1d7ae31SEmmanuel Vadot frame->type = HDMI_INFOFRAME_TYPE_SPD; 232f1d7ae31SEmmanuel Vadot frame->version = 1; 233f1d7ae31SEmmanuel Vadot frame->length = HDMI_SPD_INFOFRAME_SIZE; 234f1d7ae31SEmmanuel Vadot 235f1d7ae31SEmmanuel Vadot len = strlen(vendor); 236f1d7ae31SEmmanuel Vadot memcpy(frame->vendor, vendor, min(len, sizeof(frame->vendor))); 237f1d7ae31SEmmanuel Vadot len = strlen(product); 238f1d7ae31SEmmanuel Vadot memcpy(frame->product, product, min(len, sizeof(frame->product))); 239f1d7ae31SEmmanuel Vadot 240f1d7ae31SEmmanuel Vadot return 0; 241f1d7ae31SEmmanuel Vadot } 242f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_spd_infoframe_init); 243f1d7ae31SEmmanuel Vadot 244f1d7ae31SEmmanuel Vadot static int hdmi_spd_infoframe_check_only(const struct hdmi_spd_infoframe *frame) 245f1d7ae31SEmmanuel Vadot { 246f1d7ae31SEmmanuel Vadot if (frame->type != HDMI_INFOFRAME_TYPE_SPD || 247f1d7ae31SEmmanuel Vadot frame->version != 1 || 248f1d7ae31SEmmanuel Vadot frame->length != HDMI_SPD_INFOFRAME_SIZE) 249f1d7ae31SEmmanuel Vadot return -EINVAL; 250f1d7ae31SEmmanuel Vadot 251f1d7ae31SEmmanuel Vadot return 0; 252f1d7ae31SEmmanuel Vadot } 253f1d7ae31SEmmanuel Vadot 254f1d7ae31SEmmanuel Vadot /** 255f1d7ae31SEmmanuel Vadot * hdmi_spd_infoframe_check() - check a HDMI SPD infoframe 256f1d7ae31SEmmanuel Vadot * @frame: HDMI SPD infoframe 257f1d7ae31SEmmanuel Vadot * 258f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 259f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields. 260f1d7ae31SEmmanuel Vadot * 261f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 262f1d7ae31SEmmanuel Vadot */ 263f1d7ae31SEmmanuel Vadot int hdmi_spd_infoframe_check(struct hdmi_spd_infoframe *frame) 264f1d7ae31SEmmanuel Vadot { 265f1d7ae31SEmmanuel Vadot return hdmi_spd_infoframe_check_only(frame); 266f1d7ae31SEmmanuel Vadot } 267f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_spd_infoframe_check); 268f1d7ae31SEmmanuel Vadot 269f1d7ae31SEmmanuel Vadot /** 270f1d7ae31SEmmanuel Vadot * hdmi_spd_infoframe_pack_only() - write HDMI SPD infoframe to binary buffer 271f1d7ae31SEmmanuel Vadot * @frame: HDMI SPD infoframe 272f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 273f1d7ae31SEmmanuel Vadot * @size: size of buffer 274f1d7ae31SEmmanuel Vadot * 275f1d7ae31SEmmanuel Vadot * Packs the information contained in the @frame structure into a binary 276f1d7ae31SEmmanuel Vadot * representation that can be written into the corresponding controller 277f1d7ae31SEmmanuel Vadot * registers. Also computes the checksum as required by section 5.3.5 of 278f1d7ae31SEmmanuel Vadot * the HDMI 1.4 specification. 279f1d7ae31SEmmanuel Vadot * 280f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 281f1d7ae31SEmmanuel Vadot * error code on failure. 282f1d7ae31SEmmanuel Vadot */ 283f1d7ae31SEmmanuel Vadot ssize_t hdmi_spd_infoframe_pack_only(const struct hdmi_spd_infoframe *frame, 284f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 285f1d7ae31SEmmanuel Vadot { 286f1d7ae31SEmmanuel Vadot u8 *ptr = buffer; 287f1d7ae31SEmmanuel Vadot size_t length; 288f1d7ae31SEmmanuel Vadot int ret; 289f1d7ae31SEmmanuel Vadot 290f1d7ae31SEmmanuel Vadot ret = hdmi_spd_infoframe_check_only(frame); 291f1d7ae31SEmmanuel Vadot if (ret) 292f1d7ae31SEmmanuel Vadot return ret; 293f1d7ae31SEmmanuel Vadot 294f1d7ae31SEmmanuel Vadot length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; 295f1d7ae31SEmmanuel Vadot 296f1d7ae31SEmmanuel Vadot if (size < length) 297f1d7ae31SEmmanuel Vadot return -ENOSPC; 298f1d7ae31SEmmanuel Vadot 299f1d7ae31SEmmanuel Vadot memset(buffer, 0, size); 300f1d7ae31SEmmanuel Vadot 301f1d7ae31SEmmanuel Vadot ptr[0] = frame->type; 302f1d7ae31SEmmanuel Vadot ptr[1] = frame->version; 303f1d7ae31SEmmanuel Vadot ptr[2] = frame->length; 304f1d7ae31SEmmanuel Vadot ptr[3] = 0; /* checksum */ 305f1d7ae31SEmmanuel Vadot 306f1d7ae31SEmmanuel Vadot /* start infoframe payload */ 307f1d7ae31SEmmanuel Vadot ptr += HDMI_INFOFRAME_HEADER_SIZE; 308f1d7ae31SEmmanuel Vadot 309f1d7ae31SEmmanuel Vadot memcpy(ptr, frame->vendor, sizeof(frame->vendor)); 310f1d7ae31SEmmanuel Vadot memcpy(ptr + 8, frame->product, sizeof(frame->product)); 311f1d7ae31SEmmanuel Vadot 312f1d7ae31SEmmanuel Vadot ptr[24] = frame->sdi; 313f1d7ae31SEmmanuel Vadot 314f1d7ae31SEmmanuel Vadot hdmi_infoframe_set_checksum(buffer, length); 315f1d7ae31SEmmanuel Vadot 316f1d7ae31SEmmanuel Vadot return length; 317f1d7ae31SEmmanuel Vadot } 318f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_spd_infoframe_pack_only); 319f1d7ae31SEmmanuel Vadot 320f1d7ae31SEmmanuel Vadot /** 321f1d7ae31SEmmanuel Vadot * hdmi_spd_infoframe_pack() - check a HDMI SPD infoframe, 322f1d7ae31SEmmanuel Vadot * and write it to binary buffer 323f1d7ae31SEmmanuel Vadot * @frame: HDMI SPD infoframe 324f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 325f1d7ae31SEmmanuel Vadot * @size: size of buffer 326f1d7ae31SEmmanuel Vadot * 327f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 328f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields, after which it packs the information 329f1d7ae31SEmmanuel Vadot * contained in the @frame structure into a binary representation that 330f1d7ae31SEmmanuel Vadot * can be written into the corresponding controller registers. This function 331f1d7ae31SEmmanuel Vadot * also computes the checksum as required by section 5.3.5 of the HDMI 1.4 332f1d7ae31SEmmanuel Vadot * specification. 333f1d7ae31SEmmanuel Vadot * 334f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 335f1d7ae31SEmmanuel Vadot * error code on failure. 336f1d7ae31SEmmanuel Vadot */ 337f1d7ae31SEmmanuel Vadot ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, 338f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 339f1d7ae31SEmmanuel Vadot { 340f1d7ae31SEmmanuel Vadot int ret; 341f1d7ae31SEmmanuel Vadot 342f1d7ae31SEmmanuel Vadot ret = hdmi_spd_infoframe_check(frame); 343f1d7ae31SEmmanuel Vadot if (ret) 344f1d7ae31SEmmanuel Vadot return ret; 345f1d7ae31SEmmanuel Vadot 346f1d7ae31SEmmanuel Vadot return hdmi_spd_infoframe_pack_only(frame, buffer, size); 347f1d7ae31SEmmanuel Vadot } 348f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_spd_infoframe_pack); 349f1d7ae31SEmmanuel Vadot 350f1d7ae31SEmmanuel Vadot /** 351f1d7ae31SEmmanuel Vadot * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe 352f1d7ae31SEmmanuel Vadot * @frame: HDMI audio infoframe 353f1d7ae31SEmmanuel Vadot * 354f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 355f1d7ae31SEmmanuel Vadot */ 356f1d7ae31SEmmanuel Vadot int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame) 357f1d7ae31SEmmanuel Vadot { 358f1d7ae31SEmmanuel Vadot memset(frame, 0, sizeof(*frame)); 359f1d7ae31SEmmanuel Vadot 360f1d7ae31SEmmanuel Vadot frame->type = HDMI_INFOFRAME_TYPE_AUDIO; 361f1d7ae31SEmmanuel Vadot frame->version = 1; 362f1d7ae31SEmmanuel Vadot frame->length = HDMI_AUDIO_INFOFRAME_SIZE; 363f1d7ae31SEmmanuel Vadot 364f1d7ae31SEmmanuel Vadot return 0; 365f1d7ae31SEmmanuel Vadot } 366f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_audio_infoframe_init); 367f1d7ae31SEmmanuel Vadot 368f1d7ae31SEmmanuel Vadot static int hdmi_audio_infoframe_check_only(const struct hdmi_audio_infoframe *frame) 369f1d7ae31SEmmanuel Vadot { 370f1d7ae31SEmmanuel Vadot if (frame->type != HDMI_INFOFRAME_TYPE_AUDIO || 371f1d7ae31SEmmanuel Vadot frame->version != 1 || 372f1d7ae31SEmmanuel Vadot frame->length != HDMI_AUDIO_INFOFRAME_SIZE) 373f1d7ae31SEmmanuel Vadot return -EINVAL; 374f1d7ae31SEmmanuel Vadot 375f1d7ae31SEmmanuel Vadot return 0; 376f1d7ae31SEmmanuel Vadot } 377f1d7ae31SEmmanuel Vadot 378f1d7ae31SEmmanuel Vadot /** 379f1d7ae31SEmmanuel Vadot * hdmi_audio_infoframe_check() - check a HDMI audio infoframe 380f1d7ae31SEmmanuel Vadot * @frame: HDMI audio infoframe 381f1d7ae31SEmmanuel Vadot * 382f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 383f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields. 384f1d7ae31SEmmanuel Vadot * 385f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 386f1d7ae31SEmmanuel Vadot */ 387*c89d94adSVladimir Kondratyev int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame) 388f1d7ae31SEmmanuel Vadot { 389f1d7ae31SEmmanuel Vadot return hdmi_audio_infoframe_check_only(frame); 390f1d7ae31SEmmanuel Vadot } 391f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_audio_infoframe_check); 392f1d7ae31SEmmanuel Vadot 393*c89d94adSVladimir Kondratyev static void 394*c89d94adSVladimir Kondratyev hdmi_audio_infoframe_pack_payload(const struct hdmi_audio_infoframe *frame, 395*c89d94adSVladimir Kondratyev u8 *buffer) 396*c89d94adSVladimir Kondratyev { 397*c89d94adSVladimir Kondratyev u8 channels; 398*c89d94adSVladimir Kondratyev 399*c89d94adSVladimir Kondratyev if (frame->channels >= 2) 400*c89d94adSVladimir Kondratyev channels = frame->channels - 1; 401*c89d94adSVladimir Kondratyev else 402*c89d94adSVladimir Kondratyev channels = 0; 403*c89d94adSVladimir Kondratyev 404*c89d94adSVladimir Kondratyev buffer[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7); 405*c89d94adSVladimir Kondratyev buffer[1] = ((frame->sample_frequency & 0x7) << 2) | 406*c89d94adSVladimir Kondratyev (frame->sample_size & 0x3); 407*c89d94adSVladimir Kondratyev buffer[2] = frame->coding_type_ext & 0x1f; 408*c89d94adSVladimir Kondratyev buffer[3] = frame->channel_allocation; 409*c89d94adSVladimir Kondratyev buffer[4] = (frame->level_shift_value & 0xf) << 3; 410*c89d94adSVladimir Kondratyev 411*c89d94adSVladimir Kondratyev if (frame->downmix_inhibit) 412*c89d94adSVladimir Kondratyev buffer[4] |= BIT(7); 413*c89d94adSVladimir Kondratyev } 414*c89d94adSVladimir Kondratyev 415f1d7ae31SEmmanuel Vadot /** 416f1d7ae31SEmmanuel Vadot * hdmi_audio_infoframe_pack_only() - write HDMI audio infoframe to binary buffer 417f1d7ae31SEmmanuel Vadot * @frame: HDMI audio infoframe 418f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 419f1d7ae31SEmmanuel Vadot * @size: size of buffer 420f1d7ae31SEmmanuel Vadot * 421f1d7ae31SEmmanuel Vadot * Packs the information contained in the @frame structure into a binary 422f1d7ae31SEmmanuel Vadot * representation that can be written into the corresponding controller 423f1d7ae31SEmmanuel Vadot * registers. Also computes the checksum as required by section 5.3.5 of 424f1d7ae31SEmmanuel Vadot * the HDMI 1.4 specification. 425f1d7ae31SEmmanuel Vadot * 426f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 427f1d7ae31SEmmanuel Vadot * error code on failure. 428f1d7ae31SEmmanuel Vadot */ 429f1d7ae31SEmmanuel Vadot ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, 430f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 431f1d7ae31SEmmanuel Vadot { 432f1d7ae31SEmmanuel Vadot u8 *ptr = buffer; 433f1d7ae31SEmmanuel Vadot size_t length; 434f1d7ae31SEmmanuel Vadot int ret; 435f1d7ae31SEmmanuel Vadot 436f1d7ae31SEmmanuel Vadot ret = hdmi_audio_infoframe_check_only(frame); 437f1d7ae31SEmmanuel Vadot if (ret) 438f1d7ae31SEmmanuel Vadot return ret; 439f1d7ae31SEmmanuel Vadot 440f1d7ae31SEmmanuel Vadot length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; 441f1d7ae31SEmmanuel Vadot 442f1d7ae31SEmmanuel Vadot if (size < length) 443f1d7ae31SEmmanuel Vadot return -ENOSPC; 444f1d7ae31SEmmanuel Vadot 445f1d7ae31SEmmanuel Vadot memset(buffer, 0, size); 446f1d7ae31SEmmanuel Vadot 447f1d7ae31SEmmanuel Vadot ptr[0] = frame->type; 448f1d7ae31SEmmanuel Vadot ptr[1] = frame->version; 449f1d7ae31SEmmanuel Vadot ptr[2] = frame->length; 450f1d7ae31SEmmanuel Vadot ptr[3] = 0; /* checksum */ 451f1d7ae31SEmmanuel Vadot 452*c89d94adSVladimir Kondratyev hdmi_audio_infoframe_pack_payload(frame, 453*c89d94adSVladimir Kondratyev ptr + HDMI_INFOFRAME_HEADER_SIZE); 454f1d7ae31SEmmanuel Vadot 455f1d7ae31SEmmanuel Vadot hdmi_infoframe_set_checksum(buffer, length); 456f1d7ae31SEmmanuel Vadot 457f1d7ae31SEmmanuel Vadot return length; 458f1d7ae31SEmmanuel Vadot } 459f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_audio_infoframe_pack_only); 460f1d7ae31SEmmanuel Vadot 461f1d7ae31SEmmanuel Vadot /** 462f1d7ae31SEmmanuel Vadot * hdmi_audio_infoframe_pack() - check a HDMI Audio infoframe, 463f1d7ae31SEmmanuel Vadot * and write it to binary buffer 464f1d7ae31SEmmanuel Vadot * @frame: HDMI Audio infoframe 465f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 466f1d7ae31SEmmanuel Vadot * @size: size of buffer 467f1d7ae31SEmmanuel Vadot * 468f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 469f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields, after which it packs the information 470f1d7ae31SEmmanuel Vadot * contained in the @frame structure into a binary representation that 471f1d7ae31SEmmanuel Vadot * can be written into the corresponding controller registers. This function 472f1d7ae31SEmmanuel Vadot * also computes the checksum as required by section 5.3.5 of the HDMI 1.4 473f1d7ae31SEmmanuel Vadot * specification. 474f1d7ae31SEmmanuel Vadot * 475f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 476f1d7ae31SEmmanuel Vadot * error code on failure. 477f1d7ae31SEmmanuel Vadot */ 478f1d7ae31SEmmanuel Vadot ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, 479f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 480f1d7ae31SEmmanuel Vadot { 481f1d7ae31SEmmanuel Vadot int ret; 482f1d7ae31SEmmanuel Vadot 483f1d7ae31SEmmanuel Vadot ret = hdmi_audio_infoframe_check(frame); 484f1d7ae31SEmmanuel Vadot if (ret) 485f1d7ae31SEmmanuel Vadot return ret; 486f1d7ae31SEmmanuel Vadot 487f1d7ae31SEmmanuel Vadot return hdmi_audio_infoframe_pack_only(frame, buffer, size); 488f1d7ae31SEmmanuel Vadot } 489f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_audio_infoframe_pack); 490f1d7ae31SEmmanuel Vadot 491*c89d94adSVladimir Kondratyev #ifdef __linux__ 492*c89d94adSVladimir Kondratyev /** 493*c89d94adSVladimir Kondratyev * hdmi_audio_infoframe_pack_for_dp - Pack a HDMI Audio infoframe for DisplayPort 494*c89d94adSVladimir Kondratyev * 495*c89d94adSVladimir Kondratyev * @frame: HDMI Audio infoframe 496*c89d94adSVladimir Kondratyev * @sdp: Secondary data packet for DisplayPort. 497*c89d94adSVladimir Kondratyev * @dp_version: DisplayPort version to be encoded in the header 498*c89d94adSVladimir Kondratyev * 499*c89d94adSVladimir Kondratyev * Packs a HDMI Audio Infoframe to be sent over DisplayPort. This function 500*c89d94adSVladimir Kondratyev * fills the secondary data packet to be used for DisplayPort. 501*c89d94adSVladimir Kondratyev * 502*c89d94adSVladimir Kondratyev * Return: Number of total written bytes or a negative errno on failure. 503*c89d94adSVladimir Kondratyev */ 504*c89d94adSVladimir Kondratyev ssize_t 505*c89d94adSVladimir Kondratyev hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame, 506*c89d94adSVladimir Kondratyev struct dp_sdp *sdp, u8 dp_version) 507*c89d94adSVladimir Kondratyev { 508*c89d94adSVladimir Kondratyev int ret; 509*c89d94adSVladimir Kondratyev 510*c89d94adSVladimir Kondratyev ret = hdmi_audio_infoframe_check(frame); 511*c89d94adSVladimir Kondratyev if (ret) 512*c89d94adSVladimir Kondratyev return ret; 513*c89d94adSVladimir Kondratyev 514*c89d94adSVladimir Kondratyev memset(sdp->db, 0, sizeof(sdp->db)); 515*c89d94adSVladimir Kondratyev 516*c89d94adSVladimir Kondratyev /* Secondary-data packet header */ 517*c89d94adSVladimir Kondratyev sdp->sdp_header.HB0 = 0; 518*c89d94adSVladimir Kondratyev sdp->sdp_header.HB1 = frame->type; 519*c89d94adSVladimir Kondratyev sdp->sdp_header.HB2 = DP_SDP_AUDIO_INFOFRAME_HB2; 520*c89d94adSVladimir Kondratyev sdp->sdp_header.HB3 = (dp_version & 0x3f) << 2; 521*c89d94adSVladimir Kondratyev 522*c89d94adSVladimir Kondratyev hdmi_audio_infoframe_pack_payload(frame, sdp->db); 523*c89d94adSVladimir Kondratyev 524*c89d94adSVladimir Kondratyev /* Return size = frame length + four HB for sdp_header */ 525*c89d94adSVladimir Kondratyev return frame->length + 4; 526*c89d94adSVladimir Kondratyev } 527*c89d94adSVladimir Kondratyev EXPORT_SYMBOL(hdmi_audio_infoframe_pack_for_dp); 528*c89d94adSVladimir Kondratyev #endif 529*c89d94adSVladimir Kondratyev 530f1d7ae31SEmmanuel Vadot /** 531f1d7ae31SEmmanuel Vadot * hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe 532f1d7ae31SEmmanuel Vadot * @frame: HDMI vendor infoframe 533f1d7ae31SEmmanuel Vadot * 534f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 535f1d7ae31SEmmanuel Vadot */ 536f1d7ae31SEmmanuel Vadot int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame) 537f1d7ae31SEmmanuel Vadot { 538f1d7ae31SEmmanuel Vadot memset(frame, 0, sizeof(*frame)); 539f1d7ae31SEmmanuel Vadot 540f1d7ae31SEmmanuel Vadot frame->type = HDMI_INFOFRAME_TYPE_VENDOR; 541f1d7ae31SEmmanuel Vadot frame->version = 1; 542f1d7ae31SEmmanuel Vadot 543f1d7ae31SEmmanuel Vadot frame->oui = HDMI_IEEE_OUI; 544f1d7ae31SEmmanuel Vadot 545f1d7ae31SEmmanuel Vadot /* 546f1d7ae31SEmmanuel Vadot * 0 is a valid value for s3d_struct, so we use a special "not set" 547f1d7ae31SEmmanuel Vadot * value 548f1d7ae31SEmmanuel Vadot */ 549f1d7ae31SEmmanuel Vadot frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID; 550f1d7ae31SEmmanuel Vadot frame->length = HDMI_VENDOR_INFOFRAME_SIZE; 551f1d7ae31SEmmanuel Vadot 552f1d7ae31SEmmanuel Vadot return 0; 553f1d7ae31SEmmanuel Vadot } 554f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_vendor_infoframe_init); 555f1d7ae31SEmmanuel Vadot 556f1d7ae31SEmmanuel Vadot static int hdmi_vendor_infoframe_length(const struct hdmi_vendor_infoframe *frame) 557f1d7ae31SEmmanuel Vadot { 558f1d7ae31SEmmanuel Vadot /* for side by side (half) we also need to provide 3D_Ext_Data */ 559f1d7ae31SEmmanuel Vadot if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) 560f1d7ae31SEmmanuel Vadot return 6; 561f1d7ae31SEmmanuel Vadot else if (frame->vic != 0 || frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) 562f1d7ae31SEmmanuel Vadot return 5; 563f1d7ae31SEmmanuel Vadot else 564f1d7ae31SEmmanuel Vadot return 4; 565f1d7ae31SEmmanuel Vadot } 566f1d7ae31SEmmanuel Vadot 567f1d7ae31SEmmanuel Vadot static int hdmi_vendor_infoframe_check_only(const struct hdmi_vendor_infoframe *frame) 568f1d7ae31SEmmanuel Vadot { 569f1d7ae31SEmmanuel Vadot if (frame->type != HDMI_INFOFRAME_TYPE_VENDOR || 570f1d7ae31SEmmanuel Vadot frame->version != 1 || 571f1d7ae31SEmmanuel Vadot frame->oui != HDMI_IEEE_OUI) 572f1d7ae31SEmmanuel Vadot return -EINVAL; 573f1d7ae31SEmmanuel Vadot 574f1d7ae31SEmmanuel Vadot /* only one of those can be supplied */ 575f1d7ae31SEmmanuel Vadot if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) 576f1d7ae31SEmmanuel Vadot return -EINVAL; 577f1d7ae31SEmmanuel Vadot 578f1d7ae31SEmmanuel Vadot if (frame->length != hdmi_vendor_infoframe_length(frame)) 579f1d7ae31SEmmanuel Vadot return -EINVAL; 580f1d7ae31SEmmanuel Vadot 581f1d7ae31SEmmanuel Vadot return 0; 582f1d7ae31SEmmanuel Vadot } 583f1d7ae31SEmmanuel Vadot 584f1d7ae31SEmmanuel Vadot /** 585f1d7ae31SEmmanuel Vadot * hdmi_vendor_infoframe_check() - check a HDMI vendor infoframe 586f1d7ae31SEmmanuel Vadot * @frame: HDMI infoframe 587f1d7ae31SEmmanuel Vadot * 588f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 589f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields. 590f1d7ae31SEmmanuel Vadot * 591f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 592f1d7ae31SEmmanuel Vadot */ 593f1d7ae31SEmmanuel Vadot int hdmi_vendor_infoframe_check(struct hdmi_vendor_infoframe *frame) 594f1d7ae31SEmmanuel Vadot { 595f1d7ae31SEmmanuel Vadot frame->length = hdmi_vendor_infoframe_length(frame); 596f1d7ae31SEmmanuel Vadot 597f1d7ae31SEmmanuel Vadot return hdmi_vendor_infoframe_check_only(frame); 598f1d7ae31SEmmanuel Vadot } 599f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_vendor_infoframe_check); 600f1d7ae31SEmmanuel Vadot 601f1d7ae31SEmmanuel Vadot /** 602f1d7ae31SEmmanuel Vadot * hdmi_vendor_infoframe_pack_only() - write a HDMI vendor infoframe to binary buffer 603f1d7ae31SEmmanuel Vadot * @frame: HDMI infoframe 604f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 605f1d7ae31SEmmanuel Vadot * @size: size of buffer 606f1d7ae31SEmmanuel Vadot * 607f1d7ae31SEmmanuel Vadot * Packs the information contained in the @frame structure into a binary 608f1d7ae31SEmmanuel Vadot * representation that can be written into the corresponding controller 609f1d7ae31SEmmanuel Vadot * registers. Also computes the checksum as required by section 5.3.5 of 610f1d7ae31SEmmanuel Vadot * the HDMI 1.4 specification. 611f1d7ae31SEmmanuel Vadot * 612f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 613f1d7ae31SEmmanuel Vadot * error code on failure. 614f1d7ae31SEmmanuel Vadot */ 615f1d7ae31SEmmanuel Vadot ssize_t hdmi_vendor_infoframe_pack_only(const struct hdmi_vendor_infoframe *frame, 616f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 617f1d7ae31SEmmanuel Vadot { 618f1d7ae31SEmmanuel Vadot u8 *ptr = buffer; 619f1d7ae31SEmmanuel Vadot size_t length; 620f1d7ae31SEmmanuel Vadot int ret; 621f1d7ae31SEmmanuel Vadot 622f1d7ae31SEmmanuel Vadot ret = hdmi_vendor_infoframe_check_only(frame); 623f1d7ae31SEmmanuel Vadot if (ret) 624f1d7ae31SEmmanuel Vadot return ret; 625f1d7ae31SEmmanuel Vadot 626f1d7ae31SEmmanuel Vadot length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; 627f1d7ae31SEmmanuel Vadot 628f1d7ae31SEmmanuel Vadot if (size < length) 629f1d7ae31SEmmanuel Vadot return -ENOSPC; 630f1d7ae31SEmmanuel Vadot 631f1d7ae31SEmmanuel Vadot memset(buffer, 0, size); 632f1d7ae31SEmmanuel Vadot 633f1d7ae31SEmmanuel Vadot ptr[0] = frame->type; 634f1d7ae31SEmmanuel Vadot ptr[1] = frame->version; 635f1d7ae31SEmmanuel Vadot ptr[2] = frame->length; 636f1d7ae31SEmmanuel Vadot ptr[3] = 0; /* checksum */ 637f1d7ae31SEmmanuel Vadot 638f1d7ae31SEmmanuel Vadot /* HDMI OUI */ 639f1d7ae31SEmmanuel Vadot ptr[4] = 0x03; 640f1d7ae31SEmmanuel Vadot ptr[5] = 0x0c; 641f1d7ae31SEmmanuel Vadot ptr[6] = 0x00; 642f1d7ae31SEmmanuel Vadot 643f1d7ae31SEmmanuel Vadot if (frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) { 644f1d7ae31SEmmanuel Vadot ptr[7] = 0x2 << 5; /* video format */ 645f1d7ae31SEmmanuel Vadot ptr[8] = (frame->s3d_struct & 0xf) << 4; 646f1d7ae31SEmmanuel Vadot if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) 647f1d7ae31SEmmanuel Vadot ptr[9] = (frame->s3d_ext_data & 0xf) << 4; 648f1d7ae31SEmmanuel Vadot } else if (frame->vic) { 649f1d7ae31SEmmanuel Vadot ptr[7] = 0x1 << 5; /* video format */ 650f1d7ae31SEmmanuel Vadot ptr[8] = frame->vic; 651f1d7ae31SEmmanuel Vadot } else { 652f1d7ae31SEmmanuel Vadot ptr[7] = 0x0 << 5; /* video format */ 653f1d7ae31SEmmanuel Vadot } 654f1d7ae31SEmmanuel Vadot 655f1d7ae31SEmmanuel Vadot hdmi_infoframe_set_checksum(buffer, length); 656f1d7ae31SEmmanuel Vadot 657f1d7ae31SEmmanuel Vadot return length; 658f1d7ae31SEmmanuel Vadot } 659f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_vendor_infoframe_pack_only); 660f1d7ae31SEmmanuel Vadot 661f1d7ae31SEmmanuel Vadot /** 662f1d7ae31SEmmanuel Vadot * hdmi_vendor_infoframe_pack() - check a HDMI Vendor infoframe, 663f1d7ae31SEmmanuel Vadot * and write it to binary buffer 664f1d7ae31SEmmanuel Vadot * @frame: HDMI Vendor infoframe 665f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 666f1d7ae31SEmmanuel Vadot * @size: size of buffer 667f1d7ae31SEmmanuel Vadot * 668f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 669f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields, after which it packs the information 670f1d7ae31SEmmanuel Vadot * contained in the @frame structure into a binary representation that 671f1d7ae31SEmmanuel Vadot * can be written into the corresponding controller registers. This function 672f1d7ae31SEmmanuel Vadot * also computes the checksum as required by section 5.3.5 of the HDMI 1.4 673f1d7ae31SEmmanuel Vadot * specification. 674f1d7ae31SEmmanuel Vadot * 675f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 676f1d7ae31SEmmanuel Vadot * error code on failure. 677f1d7ae31SEmmanuel Vadot */ 678f1d7ae31SEmmanuel Vadot ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, 679f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 680f1d7ae31SEmmanuel Vadot { 681f1d7ae31SEmmanuel Vadot int ret; 682f1d7ae31SEmmanuel Vadot 683f1d7ae31SEmmanuel Vadot ret = hdmi_vendor_infoframe_check(frame); 684f1d7ae31SEmmanuel Vadot if (ret) 685f1d7ae31SEmmanuel Vadot return ret; 686f1d7ae31SEmmanuel Vadot 687f1d7ae31SEmmanuel Vadot return hdmi_vendor_infoframe_pack_only(frame, buffer, size); 688f1d7ae31SEmmanuel Vadot } 689f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_vendor_infoframe_pack); 690f1d7ae31SEmmanuel Vadot 691f1d7ae31SEmmanuel Vadot static int 692f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_check_only(const union hdmi_vendor_any_infoframe *frame) 693f1d7ae31SEmmanuel Vadot { 694f1d7ae31SEmmanuel Vadot if (frame->any.type != HDMI_INFOFRAME_TYPE_VENDOR || 695f1d7ae31SEmmanuel Vadot frame->any.version != 1) 696f1d7ae31SEmmanuel Vadot return -EINVAL; 697f1d7ae31SEmmanuel Vadot 698f1d7ae31SEmmanuel Vadot return 0; 699f1d7ae31SEmmanuel Vadot } 700f1d7ae31SEmmanuel Vadot 701f1d7ae31SEmmanuel Vadot /** 702f1d7ae31SEmmanuel Vadot * hdmi_drm_infoframe_init() - initialize an HDMI Dynaminc Range and 703f1d7ae31SEmmanuel Vadot * mastering infoframe 704f1d7ae31SEmmanuel Vadot * @frame: HDMI DRM infoframe 705f1d7ae31SEmmanuel Vadot * 706f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 707f1d7ae31SEmmanuel Vadot */ 708f1d7ae31SEmmanuel Vadot int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame) 709f1d7ae31SEmmanuel Vadot { 710f1d7ae31SEmmanuel Vadot memset(frame, 0, sizeof(*frame)); 711f1d7ae31SEmmanuel Vadot 712f1d7ae31SEmmanuel Vadot frame->type = HDMI_INFOFRAME_TYPE_DRM; 713f1d7ae31SEmmanuel Vadot frame->version = 1; 714f1d7ae31SEmmanuel Vadot frame->length = HDMI_DRM_INFOFRAME_SIZE; 715f1d7ae31SEmmanuel Vadot 716f1d7ae31SEmmanuel Vadot return 0; 717f1d7ae31SEmmanuel Vadot } 718f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_init); 719f1d7ae31SEmmanuel Vadot 720f1d7ae31SEmmanuel Vadot static int hdmi_drm_infoframe_check_only(const struct hdmi_drm_infoframe *frame) 721f1d7ae31SEmmanuel Vadot { 722f1d7ae31SEmmanuel Vadot if (frame->type != HDMI_INFOFRAME_TYPE_DRM || 723f1d7ae31SEmmanuel Vadot frame->version != 1) 724f1d7ae31SEmmanuel Vadot return -EINVAL; 725f1d7ae31SEmmanuel Vadot 726f1d7ae31SEmmanuel Vadot if (frame->length != HDMI_DRM_INFOFRAME_SIZE) 727f1d7ae31SEmmanuel Vadot return -EINVAL; 728f1d7ae31SEmmanuel Vadot 729f1d7ae31SEmmanuel Vadot return 0; 730f1d7ae31SEmmanuel Vadot } 731f1d7ae31SEmmanuel Vadot 732f1d7ae31SEmmanuel Vadot /** 733f1d7ae31SEmmanuel Vadot * hdmi_drm_infoframe_check() - check a HDMI DRM infoframe 734f1d7ae31SEmmanuel Vadot * @frame: HDMI DRM infoframe 735f1d7ae31SEmmanuel Vadot * 736f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent. 737f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 738f1d7ae31SEmmanuel Vadot */ 739f1d7ae31SEmmanuel Vadot int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame) 740f1d7ae31SEmmanuel Vadot { 741f1d7ae31SEmmanuel Vadot return hdmi_drm_infoframe_check_only(frame); 742f1d7ae31SEmmanuel Vadot } 743f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_check); 744f1d7ae31SEmmanuel Vadot 745f1d7ae31SEmmanuel Vadot /** 746f1d7ae31SEmmanuel Vadot * hdmi_drm_infoframe_pack_only() - write HDMI DRM infoframe to binary buffer 747f1d7ae31SEmmanuel Vadot * @frame: HDMI DRM infoframe 748f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 749f1d7ae31SEmmanuel Vadot * @size: size of buffer 750f1d7ae31SEmmanuel Vadot * 751f1d7ae31SEmmanuel Vadot * Packs the information contained in the @frame structure into a binary 752f1d7ae31SEmmanuel Vadot * representation that can be written into the corresponding controller 753f1d7ae31SEmmanuel Vadot * registers. Also computes the checksum as required by section 5.3.5 of 754f1d7ae31SEmmanuel Vadot * the HDMI 1.4 specification. 755f1d7ae31SEmmanuel Vadot * 756f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 757f1d7ae31SEmmanuel Vadot * error code on failure. 758f1d7ae31SEmmanuel Vadot */ 759f1d7ae31SEmmanuel Vadot ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame, 760f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 761f1d7ae31SEmmanuel Vadot { 762f1d7ae31SEmmanuel Vadot u8 *ptr = buffer; 763f1d7ae31SEmmanuel Vadot size_t length; 764f1d7ae31SEmmanuel Vadot int i; 765f1d7ae31SEmmanuel Vadot 766f1d7ae31SEmmanuel Vadot length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; 767f1d7ae31SEmmanuel Vadot 768f1d7ae31SEmmanuel Vadot if (size < length) 769f1d7ae31SEmmanuel Vadot return -ENOSPC; 770f1d7ae31SEmmanuel Vadot 771f1d7ae31SEmmanuel Vadot memset(buffer, 0, size); 772f1d7ae31SEmmanuel Vadot 773f1d7ae31SEmmanuel Vadot ptr[0] = frame->type; 774f1d7ae31SEmmanuel Vadot ptr[1] = frame->version; 775f1d7ae31SEmmanuel Vadot ptr[2] = frame->length; 776f1d7ae31SEmmanuel Vadot ptr[3] = 0; /* checksum */ 777f1d7ae31SEmmanuel Vadot 778f1d7ae31SEmmanuel Vadot /* start infoframe payload */ 779f1d7ae31SEmmanuel Vadot ptr += HDMI_INFOFRAME_HEADER_SIZE; 780f1d7ae31SEmmanuel Vadot 781f1d7ae31SEmmanuel Vadot *ptr++ = frame->eotf; 782f1d7ae31SEmmanuel Vadot *ptr++ = frame->metadata_type; 783f1d7ae31SEmmanuel Vadot 784f1d7ae31SEmmanuel Vadot for (i = 0; i < 3; i++) { 785f1d7ae31SEmmanuel Vadot *ptr++ = frame->display_primaries[i].x; 786f1d7ae31SEmmanuel Vadot *ptr++ = frame->display_primaries[i].x >> 8; 787f1d7ae31SEmmanuel Vadot *ptr++ = frame->display_primaries[i].y; 788f1d7ae31SEmmanuel Vadot *ptr++ = frame->display_primaries[i].y >> 8; 789f1d7ae31SEmmanuel Vadot } 790f1d7ae31SEmmanuel Vadot 791f1d7ae31SEmmanuel Vadot *ptr++ = frame->white_point.x; 792f1d7ae31SEmmanuel Vadot *ptr++ = frame->white_point.x >> 8; 793f1d7ae31SEmmanuel Vadot 794f1d7ae31SEmmanuel Vadot *ptr++ = frame->white_point.y; 795f1d7ae31SEmmanuel Vadot *ptr++ = frame->white_point.y >> 8; 796f1d7ae31SEmmanuel Vadot 797f1d7ae31SEmmanuel Vadot *ptr++ = frame->max_display_mastering_luminance; 798f1d7ae31SEmmanuel Vadot *ptr++ = frame->max_display_mastering_luminance >> 8; 799f1d7ae31SEmmanuel Vadot 800f1d7ae31SEmmanuel Vadot *ptr++ = frame->min_display_mastering_luminance; 801f1d7ae31SEmmanuel Vadot *ptr++ = frame->min_display_mastering_luminance >> 8; 802f1d7ae31SEmmanuel Vadot 803f1d7ae31SEmmanuel Vadot *ptr++ = frame->max_cll; 804f1d7ae31SEmmanuel Vadot *ptr++ = frame->max_cll >> 8; 805f1d7ae31SEmmanuel Vadot 806f1d7ae31SEmmanuel Vadot *ptr++ = frame->max_fall; 807f1d7ae31SEmmanuel Vadot *ptr++ = frame->max_fall >> 8; 808f1d7ae31SEmmanuel Vadot 809f1d7ae31SEmmanuel Vadot hdmi_infoframe_set_checksum(buffer, length); 810f1d7ae31SEmmanuel Vadot 811f1d7ae31SEmmanuel Vadot return length; 812f1d7ae31SEmmanuel Vadot } 813f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_pack_only); 814f1d7ae31SEmmanuel Vadot 815f1d7ae31SEmmanuel Vadot /** 816f1d7ae31SEmmanuel Vadot * hdmi_drm_infoframe_pack() - check a HDMI DRM infoframe, 817f1d7ae31SEmmanuel Vadot * and write it to binary buffer 818f1d7ae31SEmmanuel Vadot * @frame: HDMI DRM infoframe 819f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 820f1d7ae31SEmmanuel Vadot * @size: size of buffer 821f1d7ae31SEmmanuel Vadot * 822f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 823f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields, after which it packs the information 824f1d7ae31SEmmanuel Vadot * contained in the @frame structure into a binary representation that 825f1d7ae31SEmmanuel Vadot * can be written into the corresponding controller registers. This function 826f1d7ae31SEmmanuel Vadot * also computes the checksum as required by section 5.3.5 of the HDMI 1.4 827f1d7ae31SEmmanuel Vadot * specification. 828f1d7ae31SEmmanuel Vadot * 829f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 830f1d7ae31SEmmanuel Vadot * error code on failure. 831f1d7ae31SEmmanuel Vadot */ 832f1d7ae31SEmmanuel Vadot ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame, 833f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 834f1d7ae31SEmmanuel Vadot { 835f1d7ae31SEmmanuel Vadot int ret; 836f1d7ae31SEmmanuel Vadot 837f1d7ae31SEmmanuel Vadot ret = hdmi_drm_infoframe_check(frame); 838f1d7ae31SEmmanuel Vadot if (ret) 839f1d7ae31SEmmanuel Vadot return ret; 840f1d7ae31SEmmanuel Vadot 841f1d7ae31SEmmanuel Vadot return hdmi_drm_infoframe_pack_only(frame, buffer, size); 842f1d7ae31SEmmanuel Vadot } 843f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_pack); 844f1d7ae31SEmmanuel Vadot 845f1d7ae31SEmmanuel Vadot /* 846f1d7ae31SEmmanuel Vadot * hdmi_vendor_any_infoframe_check() - check a vendor infoframe 847f1d7ae31SEmmanuel Vadot */ 848f1d7ae31SEmmanuel Vadot static int 849f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_check(union hdmi_vendor_any_infoframe *frame) 850f1d7ae31SEmmanuel Vadot { 851f1d7ae31SEmmanuel Vadot int ret; 852f1d7ae31SEmmanuel Vadot 853f1d7ae31SEmmanuel Vadot ret = hdmi_vendor_any_infoframe_check_only(frame); 854f1d7ae31SEmmanuel Vadot if (ret) 855f1d7ae31SEmmanuel Vadot return ret; 856f1d7ae31SEmmanuel Vadot 857f1d7ae31SEmmanuel Vadot /* we only know about HDMI vendor infoframes */ 858f1d7ae31SEmmanuel Vadot if (frame->any.oui != HDMI_IEEE_OUI) 859f1d7ae31SEmmanuel Vadot return -EINVAL; 860f1d7ae31SEmmanuel Vadot 861f1d7ae31SEmmanuel Vadot return hdmi_vendor_infoframe_check(&frame->hdmi); 862f1d7ae31SEmmanuel Vadot } 863f1d7ae31SEmmanuel Vadot 864f1d7ae31SEmmanuel Vadot /* 865f1d7ae31SEmmanuel Vadot * hdmi_vendor_any_infoframe_pack_only() - write a vendor infoframe to binary buffer 866f1d7ae31SEmmanuel Vadot */ 867f1d7ae31SEmmanuel Vadot static ssize_t 868f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_pack_only(const union hdmi_vendor_any_infoframe *frame, 869f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 870f1d7ae31SEmmanuel Vadot { 871f1d7ae31SEmmanuel Vadot int ret; 872f1d7ae31SEmmanuel Vadot 873f1d7ae31SEmmanuel Vadot ret = hdmi_vendor_any_infoframe_check_only(frame); 874f1d7ae31SEmmanuel Vadot if (ret) 875f1d7ae31SEmmanuel Vadot return ret; 876f1d7ae31SEmmanuel Vadot 877f1d7ae31SEmmanuel Vadot /* we only know about HDMI vendor infoframes */ 878f1d7ae31SEmmanuel Vadot if (frame->any.oui != HDMI_IEEE_OUI) 879f1d7ae31SEmmanuel Vadot return -EINVAL; 880f1d7ae31SEmmanuel Vadot 881f1d7ae31SEmmanuel Vadot return hdmi_vendor_infoframe_pack_only(&frame->hdmi, buffer, size); 882f1d7ae31SEmmanuel Vadot } 883f1d7ae31SEmmanuel Vadot 884f1d7ae31SEmmanuel Vadot /* 885f1d7ae31SEmmanuel Vadot * hdmi_vendor_any_infoframe_pack() - check a vendor infoframe, 886f1d7ae31SEmmanuel Vadot * and write it to binary buffer 887f1d7ae31SEmmanuel Vadot */ 888f1d7ae31SEmmanuel Vadot static ssize_t 889f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame, 890f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 891f1d7ae31SEmmanuel Vadot { 892f1d7ae31SEmmanuel Vadot int ret; 893f1d7ae31SEmmanuel Vadot 894f1d7ae31SEmmanuel Vadot ret = hdmi_vendor_any_infoframe_check(frame); 895f1d7ae31SEmmanuel Vadot if (ret) 896f1d7ae31SEmmanuel Vadot return ret; 897f1d7ae31SEmmanuel Vadot 898f1d7ae31SEmmanuel Vadot return hdmi_vendor_any_infoframe_pack_only(frame, buffer, size); 899f1d7ae31SEmmanuel Vadot } 900f1d7ae31SEmmanuel Vadot 901f1d7ae31SEmmanuel Vadot /** 902f1d7ae31SEmmanuel Vadot * hdmi_infoframe_check() - check a HDMI infoframe 903f1d7ae31SEmmanuel Vadot * @frame: HDMI infoframe 904f1d7ae31SEmmanuel Vadot * 905f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 906f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields. 907f1d7ae31SEmmanuel Vadot * 908f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 909f1d7ae31SEmmanuel Vadot */ 910f1d7ae31SEmmanuel Vadot int 911f1d7ae31SEmmanuel Vadot hdmi_infoframe_check(union hdmi_infoframe *frame) 912f1d7ae31SEmmanuel Vadot { 913f1d7ae31SEmmanuel Vadot switch (frame->any.type) { 914f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AVI: 915f1d7ae31SEmmanuel Vadot return hdmi_avi_infoframe_check(&frame->avi); 916f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_SPD: 917f1d7ae31SEmmanuel Vadot return hdmi_spd_infoframe_check(&frame->spd); 918f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AUDIO: 919f1d7ae31SEmmanuel Vadot return hdmi_audio_infoframe_check(&frame->audio); 920f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_VENDOR: 921f1d7ae31SEmmanuel Vadot return hdmi_vendor_any_infoframe_check(&frame->vendor); 922f1d7ae31SEmmanuel Vadot default: 923f1d7ae31SEmmanuel Vadot WARN(1, "Bad infoframe type %d\n", frame->any.type); 924f1d7ae31SEmmanuel Vadot return -EINVAL; 925f1d7ae31SEmmanuel Vadot } 926f1d7ae31SEmmanuel Vadot } 927f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_check); 928f1d7ae31SEmmanuel Vadot 929f1d7ae31SEmmanuel Vadot /** 930f1d7ae31SEmmanuel Vadot * hdmi_infoframe_pack_only() - write a HDMI infoframe to binary buffer 931f1d7ae31SEmmanuel Vadot * @frame: HDMI infoframe 932f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 933f1d7ae31SEmmanuel Vadot * @size: size of buffer 934f1d7ae31SEmmanuel Vadot * 935f1d7ae31SEmmanuel Vadot * Packs the information contained in the @frame structure into a binary 936f1d7ae31SEmmanuel Vadot * representation that can be written into the corresponding controller 937f1d7ae31SEmmanuel Vadot * registers. Also computes the checksum as required by section 5.3.5 of 938f1d7ae31SEmmanuel Vadot * the HDMI 1.4 specification. 939f1d7ae31SEmmanuel Vadot * 940f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 941f1d7ae31SEmmanuel Vadot * error code on failure. 942f1d7ae31SEmmanuel Vadot */ 943f1d7ae31SEmmanuel Vadot ssize_t 944f1d7ae31SEmmanuel Vadot hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, void *buffer, size_t size) 945f1d7ae31SEmmanuel Vadot { 946f1d7ae31SEmmanuel Vadot ssize_t length; 947f1d7ae31SEmmanuel Vadot 948f1d7ae31SEmmanuel Vadot switch (frame->any.type) { 949f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AVI: 950f1d7ae31SEmmanuel Vadot length = hdmi_avi_infoframe_pack_only(&frame->avi, 951f1d7ae31SEmmanuel Vadot buffer, size); 952f1d7ae31SEmmanuel Vadot break; 953f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_DRM: 954f1d7ae31SEmmanuel Vadot length = hdmi_drm_infoframe_pack_only(&frame->drm, 955f1d7ae31SEmmanuel Vadot buffer, size); 956f1d7ae31SEmmanuel Vadot break; 957f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_SPD: 958f1d7ae31SEmmanuel Vadot length = hdmi_spd_infoframe_pack_only(&frame->spd, 959f1d7ae31SEmmanuel Vadot buffer, size); 960f1d7ae31SEmmanuel Vadot break; 961f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AUDIO: 962f1d7ae31SEmmanuel Vadot length = hdmi_audio_infoframe_pack_only(&frame->audio, 963f1d7ae31SEmmanuel Vadot buffer, size); 964f1d7ae31SEmmanuel Vadot break; 965f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_VENDOR: 966f1d7ae31SEmmanuel Vadot length = hdmi_vendor_any_infoframe_pack_only(&frame->vendor, 967f1d7ae31SEmmanuel Vadot buffer, size); 968f1d7ae31SEmmanuel Vadot break; 969f1d7ae31SEmmanuel Vadot default: 970f1d7ae31SEmmanuel Vadot WARN(1, "Bad infoframe type %d\n", frame->any.type); 971f1d7ae31SEmmanuel Vadot length = -EINVAL; 972f1d7ae31SEmmanuel Vadot } 973f1d7ae31SEmmanuel Vadot 974f1d7ae31SEmmanuel Vadot return length; 975f1d7ae31SEmmanuel Vadot } 976f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_pack_only); 977f1d7ae31SEmmanuel Vadot 978f1d7ae31SEmmanuel Vadot /** 979f1d7ae31SEmmanuel Vadot * hdmi_infoframe_pack() - check a HDMI infoframe, 980f1d7ae31SEmmanuel Vadot * and write it to binary buffer 981f1d7ae31SEmmanuel Vadot * @frame: HDMI infoframe 982f1d7ae31SEmmanuel Vadot * @buffer: destination buffer 983f1d7ae31SEmmanuel Vadot * @size: size of buffer 984f1d7ae31SEmmanuel Vadot * 985f1d7ae31SEmmanuel Vadot * Validates that the infoframe is consistent and updates derived fields 986f1d7ae31SEmmanuel Vadot * (eg. length) based on other fields, after which it packs the information 987f1d7ae31SEmmanuel Vadot * contained in the @frame structure into a binary representation that 988f1d7ae31SEmmanuel Vadot * can be written into the corresponding controller registers. This function 989f1d7ae31SEmmanuel Vadot * also computes the checksum as required by section 5.3.5 of the HDMI 1.4 990f1d7ae31SEmmanuel Vadot * specification. 991f1d7ae31SEmmanuel Vadot * 992f1d7ae31SEmmanuel Vadot * Returns the number of bytes packed into the binary buffer or a negative 993f1d7ae31SEmmanuel Vadot * error code on failure. 994f1d7ae31SEmmanuel Vadot */ 995f1d7ae31SEmmanuel Vadot ssize_t 996f1d7ae31SEmmanuel Vadot hdmi_infoframe_pack(union hdmi_infoframe *frame, 997f1d7ae31SEmmanuel Vadot void *buffer, size_t size) 998f1d7ae31SEmmanuel Vadot { 999f1d7ae31SEmmanuel Vadot ssize_t length; 1000f1d7ae31SEmmanuel Vadot 1001f1d7ae31SEmmanuel Vadot switch (frame->any.type) { 1002f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AVI: 1003f1d7ae31SEmmanuel Vadot length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size); 1004f1d7ae31SEmmanuel Vadot break; 1005f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_DRM: 1006f1d7ae31SEmmanuel Vadot length = hdmi_drm_infoframe_pack(&frame->drm, buffer, size); 1007f1d7ae31SEmmanuel Vadot break; 1008f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_SPD: 1009f1d7ae31SEmmanuel Vadot length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size); 1010f1d7ae31SEmmanuel Vadot break; 1011f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AUDIO: 1012f1d7ae31SEmmanuel Vadot length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size); 1013f1d7ae31SEmmanuel Vadot break; 1014f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_VENDOR: 1015f1d7ae31SEmmanuel Vadot length = hdmi_vendor_any_infoframe_pack(&frame->vendor, 1016f1d7ae31SEmmanuel Vadot buffer, size); 1017f1d7ae31SEmmanuel Vadot break; 1018f1d7ae31SEmmanuel Vadot default: 1019f1d7ae31SEmmanuel Vadot WARN(1, "Bad infoframe type %d\n", frame->any.type); 1020f1d7ae31SEmmanuel Vadot length = -EINVAL; 1021f1d7ae31SEmmanuel Vadot } 1022f1d7ae31SEmmanuel Vadot 1023f1d7ae31SEmmanuel Vadot return length; 1024f1d7ae31SEmmanuel Vadot } 1025f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_pack); 1026f1d7ae31SEmmanuel Vadot 1027f1d7ae31SEmmanuel Vadot static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type) 1028f1d7ae31SEmmanuel Vadot { 1029f1d7ae31SEmmanuel Vadot if (type < 0x80 || type > 0x9f) 1030f1d7ae31SEmmanuel Vadot return "Invalid"; 1031f1d7ae31SEmmanuel Vadot switch (type) { 1032f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_VENDOR: 1033f1d7ae31SEmmanuel Vadot return "Vendor"; 1034f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AVI: 1035f1d7ae31SEmmanuel Vadot return "Auxiliary Video Information (AVI)"; 1036f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_SPD: 1037f1d7ae31SEmmanuel Vadot return "Source Product Description (SPD)"; 1038f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AUDIO: 1039f1d7ae31SEmmanuel Vadot return "Audio"; 1040f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_DRM: 1041f1d7ae31SEmmanuel Vadot return "Dynamic Range and Mastering"; 1042f1d7ae31SEmmanuel Vadot } 1043f1d7ae31SEmmanuel Vadot return "Reserved"; 1044f1d7ae31SEmmanuel Vadot } 1045f1d7ae31SEmmanuel Vadot 1046f1d7ae31SEmmanuel Vadot static void hdmi_infoframe_log_header(const char *level, 1047f1d7ae31SEmmanuel Vadot struct device *dev, 1048f1d7ae31SEmmanuel Vadot const struct hdmi_any_infoframe *frame) 1049f1d7ae31SEmmanuel Vadot { 1050f1d7ae31SEmmanuel Vadot hdmi_log("HDMI infoframe: %s, version %u, length %u\n", 1051f1d7ae31SEmmanuel Vadot hdmi_infoframe_type_get_name(frame->type), 1052f1d7ae31SEmmanuel Vadot frame->version, frame->length); 1053f1d7ae31SEmmanuel Vadot } 1054f1d7ae31SEmmanuel Vadot 1055f1d7ae31SEmmanuel Vadot static const char *hdmi_colorspace_get_name(enum hdmi_colorspace colorspace) 1056f1d7ae31SEmmanuel Vadot { 1057f1d7ae31SEmmanuel Vadot switch (colorspace) { 1058f1d7ae31SEmmanuel Vadot case HDMI_COLORSPACE_RGB: 1059f1d7ae31SEmmanuel Vadot return "RGB"; 1060f1d7ae31SEmmanuel Vadot case HDMI_COLORSPACE_YUV422: 1061f1d7ae31SEmmanuel Vadot return "YCbCr 4:2:2"; 1062f1d7ae31SEmmanuel Vadot case HDMI_COLORSPACE_YUV444: 1063f1d7ae31SEmmanuel Vadot return "YCbCr 4:4:4"; 1064f1d7ae31SEmmanuel Vadot case HDMI_COLORSPACE_YUV420: 1065f1d7ae31SEmmanuel Vadot return "YCbCr 4:2:0"; 1066f1d7ae31SEmmanuel Vadot case HDMI_COLORSPACE_RESERVED4: 1067f1d7ae31SEmmanuel Vadot return "Reserved (4)"; 1068f1d7ae31SEmmanuel Vadot case HDMI_COLORSPACE_RESERVED5: 1069f1d7ae31SEmmanuel Vadot return "Reserved (5)"; 1070f1d7ae31SEmmanuel Vadot case HDMI_COLORSPACE_RESERVED6: 1071f1d7ae31SEmmanuel Vadot return "Reserved (6)"; 1072f1d7ae31SEmmanuel Vadot case HDMI_COLORSPACE_IDO_DEFINED: 1073f1d7ae31SEmmanuel Vadot return "IDO Defined"; 1074f1d7ae31SEmmanuel Vadot } 1075f1d7ae31SEmmanuel Vadot return "Invalid"; 1076f1d7ae31SEmmanuel Vadot } 1077f1d7ae31SEmmanuel Vadot 1078f1d7ae31SEmmanuel Vadot static const char *hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode) 1079f1d7ae31SEmmanuel Vadot { 1080f1d7ae31SEmmanuel Vadot switch (scan_mode) { 1081f1d7ae31SEmmanuel Vadot case HDMI_SCAN_MODE_NONE: 1082f1d7ae31SEmmanuel Vadot return "No Data"; 1083f1d7ae31SEmmanuel Vadot case HDMI_SCAN_MODE_OVERSCAN: 1084f1d7ae31SEmmanuel Vadot return "Overscan"; 1085f1d7ae31SEmmanuel Vadot case HDMI_SCAN_MODE_UNDERSCAN: 1086f1d7ae31SEmmanuel Vadot return "Underscan"; 1087f1d7ae31SEmmanuel Vadot case HDMI_SCAN_MODE_RESERVED: 1088f1d7ae31SEmmanuel Vadot return "Reserved"; 1089f1d7ae31SEmmanuel Vadot } 1090f1d7ae31SEmmanuel Vadot return "Invalid"; 1091f1d7ae31SEmmanuel Vadot } 1092f1d7ae31SEmmanuel Vadot 1093f1d7ae31SEmmanuel Vadot static const char *hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry) 1094f1d7ae31SEmmanuel Vadot { 1095f1d7ae31SEmmanuel Vadot switch (colorimetry) { 1096f1d7ae31SEmmanuel Vadot case HDMI_COLORIMETRY_NONE: 1097f1d7ae31SEmmanuel Vadot return "No Data"; 1098f1d7ae31SEmmanuel Vadot case HDMI_COLORIMETRY_ITU_601: 1099f1d7ae31SEmmanuel Vadot return "ITU601"; 1100f1d7ae31SEmmanuel Vadot case HDMI_COLORIMETRY_ITU_709: 1101f1d7ae31SEmmanuel Vadot return "ITU709"; 1102f1d7ae31SEmmanuel Vadot case HDMI_COLORIMETRY_EXTENDED: 1103f1d7ae31SEmmanuel Vadot return "Extended"; 1104f1d7ae31SEmmanuel Vadot } 1105f1d7ae31SEmmanuel Vadot return "Invalid"; 1106f1d7ae31SEmmanuel Vadot } 1107f1d7ae31SEmmanuel Vadot 1108f1d7ae31SEmmanuel Vadot static const char * 1109f1d7ae31SEmmanuel Vadot hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect) 1110f1d7ae31SEmmanuel Vadot { 1111f1d7ae31SEmmanuel Vadot switch (picture_aspect) { 1112f1d7ae31SEmmanuel Vadot case HDMI_PICTURE_ASPECT_NONE: 1113f1d7ae31SEmmanuel Vadot return "No Data"; 1114f1d7ae31SEmmanuel Vadot case HDMI_PICTURE_ASPECT_4_3: 1115f1d7ae31SEmmanuel Vadot return "4:3"; 1116f1d7ae31SEmmanuel Vadot case HDMI_PICTURE_ASPECT_16_9: 1117f1d7ae31SEmmanuel Vadot return "16:9"; 1118f1d7ae31SEmmanuel Vadot case HDMI_PICTURE_ASPECT_64_27: 1119f1d7ae31SEmmanuel Vadot return "64:27"; 1120f1d7ae31SEmmanuel Vadot case HDMI_PICTURE_ASPECT_256_135: 1121f1d7ae31SEmmanuel Vadot return "256:135"; 1122f1d7ae31SEmmanuel Vadot case HDMI_PICTURE_ASPECT_RESERVED: 1123f1d7ae31SEmmanuel Vadot return "Reserved"; 1124f1d7ae31SEmmanuel Vadot } 1125f1d7ae31SEmmanuel Vadot return "Invalid"; 1126f1d7ae31SEmmanuel Vadot } 1127f1d7ae31SEmmanuel Vadot 1128f1d7ae31SEmmanuel Vadot static const char * 1129f1d7ae31SEmmanuel Vadot hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect) 1130f1d7ae31SEmmanuel Vadot { 1131f1d7ae31SEmmanuel Vadot if (active_aspect < 0 || active_aspect > 0xf) 1132f1d7ae31SEmmanuel Vadot return "Invalid"; 1133f1d7ae31SEmmanuel Vadot 1134f1d7ae31SEmmanuel Vadot switch (active_aspect) { 1135f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_16_9_TOP: 1136f1d7ae31SEmmanuel Vadot return "16:9 Top"; 1137f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_14_9_TOP: 1138f1d7ae31SEmmanuel Vadot return "14:9 Top"; 1139f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_16_9_CENTER: 1140f1d7ae31SEmmanuel Vadot return "16:9 Center"; 1141f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_PICTURE: 1142f1d7ae31SEmmanuel Vadot return "Same as Picture"; 1143f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_4_3: 1144f1d7ae31SEmmanuel Vadot return "4:3"; 1145f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_16_9: 1146f1d7ae31SEmmanuel Vadot return "16:9"; 1147f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_14_9: 1148f1d7ae31SEmmanuel Vadot return "14:9"; 1149f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_4_3_SP_14_9: 1150f1d7ae31SEmmanuel Vadot return "4:3 SP 14:9"; 1151f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_16_9_SP_14_9: 1152f1d7ae31SEmmanuel Vadot return "16:9 SP 14:9"; 1153f1d7ae31SEmmanuel Vadot case HDMI_ACTIVE_ASPECT_16_9_SP_4_3: 1154f1d7ae31SEmmanuel Vadot return "16:9 SP 4:3"; 1155f1d7ae31SEmmanuel Vadot } 1156f1d7ae31SEmmanuel Vadot return "Reserved"; 1157f1d7ae31SEmmanuel Vadot } 1158f1d7ae31SEmmanuel Vadot 1159f1d7ae31SEmmanuel Vadot static const char * 1160f1d7ae31SEmmanuel Vadot hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col) 1161f1d7ae31SEmmanuel Vadot { 1162f1d7ae31SEmmanuel Vadot switch (ext_col) { 1163f1d7ae31SEmmanuel Vadot case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601: 1164f1d7ae31SEmmanuel Vadot return "xvYCC 601"; 1165f1d7ae31SEmmanuel Vadot case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709: 1166f1d7ae31SEmmanuel Vadot return "xvYCC 709"; 1167f1d7ae31SEmmanuel Vadot case HDMI_EXTENDED_COLORIMETRY_S_YCC_601: 1168f1d7ae31SEmmanuel Vadot return "sYCC 601"; 1169f1d7ae31SEmmanuel Vadot case HDMI_EXTENDED_COLORIMETRY_OPYCC_601: 1170f1d7ae31SEmmanuel Vadot return "opYCC 601"; 1171f1d7ae31SEmmanuel Vadot case HDMI_EXTENDED_COLORIMETRY_OPRGB: 1172f1d7ae31SEmmanuel Vadot return "opRGB"; 1173f1d7ae31SEmmanuel Vadot case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM: 1174f1d7ae31SEmmanuel Vadot return "BT.2020 Constant Luminance"; 1175f1d7ae31SEmmanuel Vadot case HDMI_EXTENDED_COLORIMETRY_BT2020: 1176f1d7ae31SEmmanuel Vadot return "BT.2020"; 1177f1d7ae31SEmmanuel Vadot case HDMI_EXTENDED_COLORIMETRY_RESERVED: 1178f1d7ae31SEmmanuel Vadot return "Reserved"; 1179f1d7ae31SEmmanuel Vadot } 1180f1d7ae31SEmmanuel Vadot return "Invalid"; 1181f1d7ae31SEmmanuel Vadot } 1182f1d7ae31SEmmanuel Vadot 1183f1d7ae31SEmmanuel Vadot static const char * 1184f1d7ae31SEmmanuel Vadot hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange) 1185f1d7ae31SEmmanuel Vadot { 1186f1d7ae31SEmmanuel Vadot switch (qrange) { 1187f1d7ae31SEmmanuel Vadot case HDMI_QUANTIZATION_RANGE_DEFAULT: 1188f1d7ae31SEmmanuel Vadot return "Default"; 1189f1d7ae31SEmmanuel Vadot case HDMI_QUANTIZATION_RANGE_LIMITED: 1190f1d7ae31SEmmanuel Vadot return "Limited"; 1191f1d7ae31SEmmanuel Vadot case HDMI_QUANTIZATION_RANGE_FULL: 1192f1d7ae31SEmmanuel Vadot return "Full"; 1193f1d7ae31SEmmanuel Vadot case HDMI_QUANTIZATION_RANGE_RESERVED: 1194f1d7ae31SEmmanuel Vadot return "Reserved"; 1195f1d7ae31SEmmanuel Vadot } 1196f1d7ae31SEmmanuel Vadot return "Invalid"; 1197f1d7ae31SEmmanuel Vadot } 1198f1d7ae31SEmmanuel Vadot 1199f1d7ae31SEmmanuel Vadot static const char *hdmi_nups_get_name(enum hdmi_nups nups) 1200f1d7ae31SEmmanuel Vadot { 1201f1d7ae31SEmmanuel Vadot switch (nups) { 1202f1d7ae31SEmmanuel Vadot case HDMI_NUPS_UNKNOWN: 1203f1d7ae31SEmmanuel Vadot return "Unknown Non-uniform Scaling"; 1204f1d7ae31SEmmanuel Vadot case HDMI_NUPS_HORIZONTAL: 1205f1d7ae31SEmmanuel Vadot return "Horizontally Scaled"; 1206f1d7ae31SEmmanuel Vadot case HDMI_NUPS_VERTICAL: 1207f1d7ae31SEmmanuel Vadot return "Vertically Scaled"; 1208f1d7ae31SEmmanuel Vadot case HDMI_NUPS_BOTH: 1209f1d7ae31SEmmanuel Vadot return "Horizontally and Vertically Scaled"; 1210f1d7ae31SEmmanuel Vadot } 1211f1d7ae31SEmmanuel Vadot return "Invalid"; 1212f1d7ae31SEmmanuel Vadot } 1213f1d7ae31SEmmanuel Vadot 1214f1d7ae31SEmmanuel Vadot static const char * 1215f1d7ae31SEmmanuel Vadot hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange) 1216f1d7ae31SEmmanuel Vadot { 1217f1d7ae31SEmmanuel Vadot switch (qrange) { 1218f1d7ae31SEmmanuel Vadot case HDMI_YCC_QUANTIZATION_RANGE_LIMITED: 1219f1d7ae31SEmmanuel Vadot return "Limited"; 1220f1d7ae31SEmmanuel Vadot case HDMI_YCC_QUANTIZATION_RANGE_FULL: 1221f1d7ae31SEmmanuel Vadot return "Full"; 1222f1d7ae31SEmmanuel Vadot } 1223f1d7ae31SEmmanuel Vadot return "Invalid"; 1224f1d7ae31SEmmanuel Vadot } 1225f1d7ae31SEmmanuel Vadot 1226f1d7ae31SEmmanuel Vadot static const char * 1227f1d7ae31SEmmanuel Vadot hdmi_content_type_get_name(enum hdmi_content_type content_type) 1228f1d7ae31SEmmanuel Vadot { 1229f1d7ae31SEmmanuel Vadot switch (content_type) { 1230f1d7ae31SEmmanuel Vadot case HDMI_CONTENT_TYPE_GRAPHICS: 1231f1d7ae31SEmmanuel Vadot return "Graphics"; 1232f1d7ae31SEmmanuel Vadot case HDMI_CONTENT_TYPE_PHOTO: 1233f1d7ae31SEmmanuel Vadot return "Photo"; 1234f1d7ae31SEmmanuel Vadot case HDMI_CONTENT_TYPE_CINEMA: 1235f1d7ae31SEmmanuel Vadot return "Cinema"; 1236f1d7ae31SEmmanuel Vadot case HDMI_CONTENT_TYPE_GAME: 1237f1d7ae31SEmmanuel Vadot return "Game"; 1238f1d7ae31SEmmanuel Vadot } 1239f1d7ae31SEmmanuel Vadot return "Invalid"; 1240f1d7ae31SEmmanuel Vadot } 1241f1d7ae31SEmmanuel Vadot 1242f1d7ae31SEmmanuel Vadot static void hdmi_avi_infoframe_log(const char *level, 1243f1d7ae31SEmmanuel Vadot struct device *dev, 1244f1d7ae31SEmmanuel Vadot const struct hdmi_avi_infoframe *frame) 1245f1d7ae31SEmmanuel Vadot { 1246f1d7ae31SEmmanuel Vadot hdmi_infoframe_log_header(level, dev, 1247f1d7ae31SEmmanuel Vadot (const struct hdmi_any_infoframe *)frame); 1248f1d7ae31SEmmanuel Vadot 1249f1d7ae31SEmmanuel Vadot hdmi_log(" colorspace: %s\n", 1250f1d7ae31SEmmanuel Vadot hdmi_colorspace_get_name(frame->colorspace)); 1251f1d7ae31SEmmanuel Vadot hdmi_log(" scan mode: %s\n", 1252f1d7ae31SEmmanuel Vadot hdmi_scan_mode_get_name(frame->scan_mode)); 1253f1d7ae31SEmmanuel Vadot hdmi_log(" colorimetry: %s\n", 1254f1d7ae31SEmmanuel Vadot hdmi_colorimetry_get_name(frame->colorimetry)); 1255f1d7ae31SEmmanuel Vadot hdmi_log(" picture aspect: %s\n", 1256f1d7ae31SEmmanuel Vadot hdmi_picture_aspect_get_name(frame->picture_aspect)); 1257f1d7ae31SEmmanuel Vadot hdmi_log(" active aspect: %s\n", 1258f1d7ae31SEmmanuel Vadot hdmi_active_aspect_get_name(frame->active_aspect)); 1259f1d7ae31SEmmanuel Vadot hdmi_log(" itc: %s\n", frame->itc ? "IT Content" : "No Data"); 1260f1d7ae31SEmmanuel Vadot hdmi_log(" extended colorimetry: %s\n", 1261f1d7ae31SEmmanuel Vadot hdmi_extended_colorimetry_get_name(frame->extended_colorimetry)); 1262f1d7ae31SEmmanuel Vadot hdmi_log(" quantization range: %s\n", 1263f1d7ae31SEmmanuel Vadot hdmi_quantization_range_get_name(frame->quantization_range)); 1264f1d7ae31SEmmanuel Vadot hdmi_log(" nups: %s\n", hdmi_nups_get_name(frame->nups)); 1265f1d7ae31SEmmanuel Vadot hdmi_log(" video code: %u\n", frame->video_code); 1266f1d7ae31SEmmanuel Vadot hdmi_log(" ycc quantization range: %s\n", 1267f1d7ae31SEmmanuel Vadot hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range)); 1268f1d7ae31SEmmanuel Vadot hdmi_log(" hdmi content type: %s\n", 1269f1d7ae31SEmmanuel Vadot hdmi_content_type_get_name(frame->content_type)); 1270f1d7ae31SEmmanuel Vadot hdmi_log(" pixel repeat: %u\n", frame->pixel_repeat); 1271f1d7ae31SEmmanuel Vadot hdmi_log(" bar top %u, bottom %u, left %u, right %u\n", 1272f1d7ae31SEmmanuel Vadot frame->top_bar, frame->bottom_bar, 1273f1d7ae31SEmmanuel Vadot frame->left_bar, frame->right_bar); 1274f1d7ae31SEmmanuel Vadot } 1275f1d7ae31SEmmanuel Vadot 1276f1d7ae31SEmmanuel Vadot static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi) 1277f1d7ae31SEmmanuel Vadot { 1278f1d7ae31SEmmanuel Vadot if (sdi < 0 || sdi > 0xff) 1279f1d7ae31SEmmanuel Vadot return "Invalid"; 1280f1d7ae31SEmmanuel Vadot switch (sdi) { 1281f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_UNKNOWN: 1282f1d7ae31SEmmanuel Vadot return "Unknown"; 1283f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_DSTB: 1284f1d7ae31SEmmanuel Vadot return "Digital STB"; 1285f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_DVDP: 1286f1d7ae31SEmmanuel Vadot return "DVD Player"; 1287f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_DVHS: 1288f1d7ae31SEmmanuel Vadot return "D-VHS"; 1289f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_HDDVR: 1290f1d7ae31SEmmanuel Vadot return "HDD Videorecorder"; 1291f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_DVC: 1292f1d7ae31SEmmanuel Vadot return "DVC"; 1293f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_DSC: 1294f1d7ae31SEmmanuel Vadot return "DSC"; 1295f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_VCD: 1296f1d7ae31SEmmanuel Vadot return "Video CD"; 1297f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_GAME: 1298f1d7ae31SEmmanuel Vadot return "Game"; 1299f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_PC: 1300f1d7ae31SEmmanuel Vadot return "PC General"; 1301f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_BD: 1302f1d7ae31SEmmanuel Vadot return "Blu-Ray Disc (BD)"; 1303f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_SACD: 1304f1d7ae31SEmmanuel Vadot return "Super Audio CD"; 1305f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_HDDVD: 1306f1d7ae31SEmmanuel Vadot return "HD DVD"; 1307f1d7ae31SEmmanuel Vadot case HDMI_SPD_SDI_PMP: 1308f1d7ae31SEmmanuel Vadot return "PMP"; 1309f1d7ae31SEmmanuel Vadot } 1310f1d7ae31SEmmanuel Vadot return "Reserved"; 1311f1d7ae31SEmmanuel Vadot } 1312f1d7ae31SEmmanuel Vadot 1313f1d7ae31SEmmanuel Vadot static void hdmi_spd_infoframe_log(const char *level, 1314f1d7ae31SEmmanuel Vadot struct device *dev, 1315f1d7ae31SEmmanuel Vadot const struct hdmi_spd_infoframe *frame) 1316f1d7ae31SEmmanuel Vadot { 1317f1d7ae31SEmmanuel Vadot u8 buf[17]; 1318f1d7ae31SEmmanuel Vadot 1319f1d7ae31SEmmanuel Vadot hdmi_infoframe_log_header(level, dev, 1320f1d7ae31SEmmanuel Vadot (const struct hdmi_any_infoframe *)frame); 1321f1d7ae31SEmmanuel Vadot 1322f1d7ae31SEmmanuel Vadot memset(buf, 0, sizeof(buf)); 1323f1d7ae31SEmmanuel Vadot 1324f1d7ae31SEmmanuel Vadot strncpy(buf, frame->vendor, 8); 1325f1d7ae31SEmmanuel Vadot hdmi_log(" vendor: %s\n", buf); 1326f1d7ae31SEmmanuel Vadot strncpy(buf, frame->product, 16); 1327f1d7ae31SEmmanuel Vadot hdmi_log(" product: %s\n", buf); 1328f1d7ae31SEmmanuel Vadot hdmi_log(" source device information: %s (0x%x)\n", 1329f1d7ae31SEmmanuel Vadot hdmi_spd_sdi_get_name(frame->sdi), frame->sdi); 1330f1d7ae31SEmmanuel Vadot } 1331f1d7ae31SEmmanuel Vadot 1332f1d7ae31SEmmanuel Vadot static const char * 1333f1d7ae31SEmmanuel Vadot hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type) 1334f1d7ae31SEmmanuel Vadot { 1335f1d7ae31SEmmanuel Vadot switch (coding_type) { 1336f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_STREAM: 1337f1d7ae31SEmmanuel Vadot return "Refer to Stream Header"; 1338f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_PCM: 1339f1d7ae31SEmmanuel Vadot return "PCM"; 1340f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_AC3: 1341f1d7ae31SEmmanuel Vadot return "AC-3"; 1342f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_MPEG1: 1343f1d7ae31SEmmanuel Vadot return "MPEG1"; 1344f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_MP3: 1345f1d7ae31SEmmanuel Vadot return "MP3"; 1346f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_MPEG2: 1347f1d7ae31SEmmanuel Vadot return "MPEG2"; 1348f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_AAC_LC: 1349f1d7ae31SEmmanuel Vadot return "AAC"; 1350f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_DTS: 1351f1d7ae31SEmmanuel Vadot return "DTS"; 1352f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_ATRAC: 1353f1d7ae31SEmmanuel Vadot return "ATRAC"; 1354f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_DSD: 1355f1d7ae31SEmmanuel Vadot return "One Bit Audio"; 1356f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EAC3: 1357f1d7ae31SEmmanuel Vadot return "Dolby Digital +"; 1358f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_DTS_HD: 1359f1d7ae31SEmmanuel Vadot return "DTS-HD"; 1360f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_MLP: 1361f1d7ae31SEmmanuel Vadot return "MAT (MLP)"; 1362f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_DST: 1363f1d7ae31SEmmanuel Vadot return "DST"; 1364f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_WMA_PRO: 1365f1d7ae31SEmmanuel Vadot return "WMA PRO"; 1366f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_CXT: 1367f1d7ae31SEmmanuel Vadot return "Refer to CXT"; 1368f1d7ae31SEmmanuel Vadot } 1369f1d7ae31SEmmanuel Vadot return "Invalid"; 1370f1d7ae31SEmmanuel Vadot } 1371f1d7ae31SEmmanuel Vadot 1372f1d7ae31SEmmanuel Vadot static const char * 1373f1d7ae31SEmmanuel Vadot hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size) 1374f1d7ae31SEmmanuel Vadot { 1375f1d7ae31SEmmanuel Vadot switch (sample_size) { 1376f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_SIZE_STREAM: 1377f1d7ae31SEmmanuel Vadot return "Refer to Stream Header"; 1378f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_SIZE_16: 1379f1d7ae31SEmmanuel Vadot return "16 bit"; 1380f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_SIZE_20: 1381f1d7ae31SEmmanuel Vadot return "20 bit"; 1382f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_SIZE_24: 1383f1d7ae31SEmmanuel Vadot return "24 bit"; 1384f1d7ae31SEmmanuel Vadot } 1385f1d7ae31SEmmanuel Vadot return "Invalid"; 1386f1d7ae31SEmmanuel Vadot } 1387f1d7ae31SEmmanuel Vadot 1388f1d7ae31SEmmanuel Vadot static const char * 1389f1d7ae31SEmmanuel Vadot hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq) 1390f1d7ae31SEmmanuel Vadot { 1391f1d7ae31SEmmanuel Vadot switch (freq) { 1392f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM: 1393f1d7ae31SEmmanuel Vadot return "Refer to Stream Header"; 1394f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_FREQUENCY_32000: 1395f1d7ae31SEmmanuel Vadot return "32 kHz"; 1396f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_FREQUENCY_44100: 1397f1d7ae31SEmmanuel Vadot return "44.1 kHz (CD)"; 1398f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_FREQUENCY_48000: 1399f1d7ae31SEmmanuel Vadot return "48 kHz"; 1400f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_FREQUENCY_88200: 1401f1d7ae31SEmmanuel Vadot return "88.2 kHz"; 1402f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_FREQUENCY_96000: 1403f1d7ae31SEmmanuel Vadot return "96 kHz"; 1404f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_FREQUENCY_176400: 1405f1d7ae31SEmmanuel Vadot return "176.4 kHz"; 1406f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_SAMPLE_FREQUENCY_192000: 1407f1d7ae31SEmmanuel Vadot return "192 kHz"; 1408f1d7ae31SEmmanuel Vadot } 1409f1d7ae31SEmmanuel Vadot return "Invalid"; 1410f1d7ae31SEmmanuel Vadot } 1411f1d7ae31SEmmanuel Vadot 1412f1d7ae31SEmmanuel Vadot static const char * 1413f1d7ae31SEmmanuel Vadot hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx) 1414f1d7ae31SEmmanuel Vadot { 1415f1d7ae31SEmmanuel Vadot if (ctx < 0 || ctx > 0x1f) 1416f1d7ae31SEmmanuel Vadot return "Invalid"; 1417f1d7ae31SEmmanuel Vadot 1418f1d7ae31SEmmanuel Vadot switch (ctx) { 1419f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_CT: 1420f1d7ae31SEmmanuel Vadot return "Refer to CT"; 1421f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC: 1422f1d7ae31SEmmanuel Vadot return "HE AAC"; 1423f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2: 1424f1d7ae31SEmmanuel Vadot return "HE AAC v2"; 1425f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND: 1426f1d7ae31SEmmanuel Vadot return "MPEG SURROUND"; 1427f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC: 1428f1d7ae31SEmmanuel Vadot return "MPEG-4 HE AAC"; 1429f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2: 1430f1d7ae31SEmmanuel Vadot return "MPEG-4 HE AAC v2"; 1431f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC: 1432f1d7ae31SEmmanuel Vadot return "MPEG-4 AAC LC"; 1433f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_DRA: 1434f1d7ae31SEmmanuel Vadot return "DRA"; 1435f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND: 1436f1d7ae31SEmmanuel Vadot return "MPEG-4 HE AAC + MPEG Surround"; 1437f1d7ae31SEmmanuel Vadot case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND: 1438f1d7ae31SEmmanuel Vadot return "MPEG-4 AAC LC + MPEG Surround"; 1439f1d7ae31SEmmanuel Vadot } 1440f1d7ae31SEmmanuel Vadot return "Reserved"; 1441f1d7ae31SEmmanuel Vadot } 1442f1d7ae31SEmmanuel Vadot 1443f1d7ae31SEmmanuel Vadot static void hdmi_audio_infoframe_log(const char *level, 1444f1d7ae31SEmmanuel Vadot struct device *dev, 1445f1d7ae31SEmmanuel Vadot const struct hdmi_audio_infoframe *frame) 1446f1d7ae31SEmmanuel Vadot { 1447f1d7ae31SEmmanuel Vadot hdmi_infoframe_log_header(level, dev, 1448f1d7ae31SEmmanuel Vadot (const struct hdmi_any_infoframe *)frame); 1449f1d7ae31SEmmanuel Vadot 1450f1d7ae31SEmmanuel Vadot if (frame->channels) 1451f1d7ae31SEmmanuel Vadot hdmi_log(" channels: %u\n", frame->channels - 1); 1452f1d7ae31SEmmanuel Vadot else 1453f1d7ae31SEmmanuel Vadot hdmi_log(" channels: Refer to stream header\n"); 1454f1d7ae31SEmmanuel Vadot hdmi_log(" coding type: %s\n", 1455f1d7ae31SEmmanuel Vadot hdmi_audio_coding_type_get_name(frame->coding_type)); 1456f1d7ae31SEmmanuel Vadot hdmi_log(" sample size: %s\n", 1457f1d7ae31SEmmanuel Vadot hdmi_audio_sample_size_get_name(frame->sample_size)); 1458f1d7ae31SEmmanuel Vadot hdmi_log(" sample frequency: %s\n", 1459f1d7ae31SEmmanuel Vadot hdmi_audio_sample_frequency_get_name(frame->sample_frequency)); 1460f1d7ae31SEmmanuel Vadot hdmi_log(" coding type ext: %s\n", 1461f1d7ae31SEmmanuel Vadot hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext)); 1462f1d7ae31SEmmanuel Vadot hdmi_log(" channel allocation: 0x%x\n", 1463f1d7ae31SEmmanuel Vadot frame->channel_allocation); 1464f1d7ae31SEmmanuel Vadot hdmi_log(" level shift value: %u dB\n", 1465f1d7ae31SEmmanuel Vadot frame->level_shift_value); 1466f1d7ae31SEmmanuel Vadot hdmi_log(" downmix inhibit: %s\n", 1467f1d7ae31SEmmanuel Vadot frame->downmix_inhibit ? "Yes" : "No"); 1468f1d7ae31SEmmanuel Vadot } 1469f1d7ae31SEmmanuel Vadot 1470f1d7ae31SEmmanuel Vadot static void hdmi_drm_infoframe_log(const char *level, 1471f1d7ae31SEmmanuel Vadot struct device *dev, 1472f1d7ae31SEmmanuel Vadot const struct hdmi_drm_infoframe *frame) 1473f1d7ae31SEmmanuel Vadot { 1474f1d7ae31SEmmanuel Vadot int i; 1475f1d7ae31SEmmanuel Vadot 1476f1d7ae31SEmmanuel Vadot hdmi_infoframe_log_header(level, dev, 1477f1d7ae31SEmmanuel Vadot (struct hdmi_any_infoframe *)frame); 1478f1d7ae31SEmmanuel Vadot hdmi_log("length: %d\n", frame->length); 1479f1d7ae31SEmmanuel Vadot hdmi_log("metadata type: %d\n", frame->metadata_type); 1480f1d7ae31SEmmanuel Vadot hdmi_log("eotf: %d\n", frame->eotf); 1481f1d7ae31SEmmanuel Vadot for (i = 0; i < 3; i++) { 1482f1d7ae31SEmmanuel Vadot hdmi_log("x[%d]: %d\n", i, frame->display_primaries[i].x); 1483f1d7ae31SEmmanuel Vadot hdmi_log("y[%d]: %d\n", i, frame->display_primaries[i].y); 1484f1d7ae31SEmmanuel Vadot } 1485f1d7ae31SEmmanuel Vadot 1486f1d7ae31SEmmanuel Vadot hdmi_log("white point x: %d\n", frame->white_point.x); 1487f1d7ae31SEmmanuel Vadot hdmi_log("white point y: %d\n", frame->white_point.y); 1488f1d7ae31SEmmanuel Vadot 1489f1d7ae31SEmmanuel Vadot hdmi_log("max_display_mastering_luminance: %d\n", 1490f1d7ae31SEmmanuel Vadot frame->max_display_mastering_luminance); 1491f1d7ae31SEmmanuel Vadot hdmi_log("min_display_mastering_luminance: %d\n", 1492f1d7ae31SEmmanuel Vadot frame->min_display_mastering_luminance); 1493f1d7ae31SEmmanuel Vadot 1494f1d7ae31SEmmanuel Vadot hdmi_log("max_cll: %d\n", frame->max_cll); 1495f1d7ae31SEmmanuel Vadot hdmi_log("max_fall: %d\n", frame->max_fall); 1496f1d7ae31SEmmanuel Vadot } 1497f1d7ae31SEmmanuel Vadot 1498f1d7ae31SEmmanuel Vadot static const char * 1499f1d7ae31SEmmanuel Vadot hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct) 1500f1d7ae31SEmmanuel Vadot { 1501f1d7ae31SEmmanuel Vadot if (s3d_struct < 0 || s3d_struct > 0xf) 1502f1d7ae31SEmmanuel Vadot return "Invalid"; 1503f1d7ae31SEmmanuel Vadot 1504f1d7ae31SEmmanuel Vadot switch (s3d_struct) { 1505f1d7ae31SEmmanuel Vadot case HDMI_3D_STRUCTURE_FRAME_PACKING: 1506f1d7ae31SEmmanuel Vadot return "Frame Packing"; 1507f1d7ae31SEmmanuel Vadot case HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE: 1508f1d7ae31SEmmanuel Vadot return "Field Alternative"; 1509f1d7ae31SEmmanuel Vadot case HDMI_3D_STRUCTURE_LINE_ALTERNATIVE: 1510f1d7ae31SEmmanuel Vadot return "Line Alternative"; 1511f1d7ae31SEmmanuel Vadot case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL: 1512f1d7ae31SEmmanuel Vadot return "Side-by-side (Full)"; 1513f1d7ae31SEmmanuel Vadot case HDMI_3D_STRUCTURE_L_DEPTH: 1514f1d7ae31SEmmanuel Vadot return "L + Depth"; 1515f1d7ae31SEmmanuel Vadot case HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH: 1516f1d7ae31SEmmanuel Vadot return "L + Depth + Graphics + Graphics-depth"; 1517f1d7ae31SEmmanuel Vadot case HDMI_3D_STRUCTURE_TOP_AND_BOTTOM: 1518f1d7ae31SEmmanuel Vadot return "Top-and-Bottom"; 1519f1d7ae31SEmmanuel Vadot case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF: 1520f1d7ae31SEmmanuel Vadot return "Side-by-side (Half)"; 1521f1d7ae31SEmmanuel Vadot default: 1522f1d7ae31SEmmanuel Vadot break; 1523f1d7ae31SEmmanuel Vadot } 1524f1d7ae31SEmmanuel Vadot return "Reserved"; 1525f1d7ae31SEmmanuel Vadot } 1526f1d7ae31SEmmanuel Vadot 1527f1d7ae31SEmmanuel Vadot static void 1528f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_log(const char *level, 1529f1d7ae31SEmmanuel Vadot struct device *dev, 1530f1d7ae31SEmmanuel Vadot const union hdmi_vendor_any_infoframe *frame) 1531f1d7ae31SEmmanuel Vadot { 1532f1d7ae31SEmmanuel Vadot const struct hdmi_vendor_infoframe *hvf = &frame->hdmi; 1533f1d7ae31SEmmanuel Vadot 1534f1d7ae31SEmmanuel Vadot hdmi_infoframe_log_header(level, dev, 1535f1d7ae31SEmmanuel Vadot (const struct hdmi_any_infoframe *)frame); 1536f1d7ae31SEmmanuel Vadot 1537f1d7ae31SEmmanuel Vadot if (frame->any.oui != HDMI_IEEE_OUI) { 1538f1d7ae31SEmmanuel Vadot hdmi_log(" not a HDMI vendor infoframe\n"); 1539f1d7ae31SEmmanuel Vadot return; 1540f1d7ae31SEmmanuel Vadot } 1541f1d7ae31SEmmanuel Vadot if (hvf->vic == 0 && hvf->s3d_struct == HDMI_3D_STRUCTURE_INVALID) { 1542f1d7ae31SEmmanuel Vadot hdmi_log(" empty frame\n"); 1543f1d7ae31SEmmanuel Vadot return; 1544f1d7ae31SEmmanuel Vadot } 1545f1d7ae31SEmmanuel Vadot 1546f1d7ae31SEmmanuel Vadot if (hvf->vic) 1547f1d7ae31SEmmanuel Vadot hdmi_log(" HDMI VIC: %u\n", hvf->vic); 1548f1d7ae31SEmmanuel Vadot if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) { 1549f1d7ae31SEmmanuel Vadot hdmi_log(" 3D structure: %s\n", 1550f1d7ae31SEmmanuel Vadot hdmi_3d_structure_get_name(hvf->s3d_struct)); 1551f1d7ae31SEmmanuel Vadot if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) 1552f1d7ae31SEmmanuel Vadot hdmi_log(" 3D extension data: %d\n", 1553f1d7ae31SEmmanuel Vadot hvf->s3d_ext_data); 1554f1d7ae31SEmmanuel Vadot } 1555f1d7ae31SEmmanuel Vadot } 1556f1d7ae31SEmmanuel Vadot 1557f1d7ae31SEmmanuel Vadot /** 1558f1d7ae31SEmmanuel Vadot * hdmi_infoframe_log() - log info of HDMI infoframe 1559f1d7ae31SEmmanuel Vadot * @level: logging level 1560f1d7ae31SEmmanuel Vadot * @dev: device 1561f1d7ae31SEmmanuel Vadot * @frame: HDMI infoframe 1562f1d7ae31SEmmanuel Vadot */ 1563f1d7ae31SEmmanuel Vadot void hdmi_infoframe_log(const char *level, 1564f1d7ae31SEmmanuel Vadot struct device *dev, 1565f1d7ae31SEmmanuel Vadot const union hdmi_infoframe *frame) 1566f1d7ae31SEmmanuel Vadot { 1567f1d7ae31SEmmanuel Vadot switch (frame->any.type) { 1568f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AVI: 1569f1d7ae31SEmmanuel Vadot hdmi_avi_infoframe_log(level, dev, &frame->avi); 1570f1d7ae31SEmmanuel Vadot break; 1571f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_SPD: 1572f1d7ae31SEmmanuel Vadot hdmi_spd_infoframe_log(level, dev, &frame->spd); 1573f1d7ae31SEmmanuel Vadot break; 1574f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AUDIO: 1575f1d7ae31SEmmanuel Vadot hdmi_audio_infoframe_log(level, dev, &frame->audio); 1576f1d7ae31SEmmanuel Vadot break; 1577f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_VENDOR: 1578f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor); 1579f1d7ae31SEmmanuel Vadot break; 1580f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_DRM: 1581f1d7ae31SEmmanuel Vadot hdmi_drm_infoframe_log(level, dev, &frame->drm); 1582f1d7ae31SEmmanuel Vadot break; 1583f1d7ae31SEmmanuel Vadot } 1584f1d7ae31SEmmanuel Vadot } 1585f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_log); 1586f1d7ae31SEmmanuel Vadot 1587f1d7ae31SEmmanuel Vadot /** 1588f1d7ae31SEmmanuel Vadot * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe 1589f1d7ae31SEmmanuel Vadot * @frame: HDMI AVI infoframe 1590f1d7ae31SEmmanuel Vadot * @buffer: source buffer 1591f1d7ae31SEmmanuel Vadot * @size: size of buffer 1592f1d7ae31SEmmanuel Vadot * 1593f1d7ae31SEmmanuel Vadot * Unpacks the information contained in binary @buffer into a structured 1594f1d7ae31SEmmanuel Vadot * @frame of the HDMI Auxiliary Video (AVI) information frame. 1595f1d7ae31SEmmanuel Vadot * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 1596f1d7ae31SEmmanuel Vadot * specification. 1597f1d7ae31SEmmanuel Vadot * 1598f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 1599f1d7ae31SEmmanuel Vadot */ 1600f1d7ae31SEmmanuel Vadot static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, 1601f1d7ae31SEmmanuel Vadot const void *buffer, size_t size) 1602f1d7ae31SEmmanuel Vadot { 1603f1d7ae31SEmmanuel Vadot const u8 *ptr = buffer; 1604f1d7ae31SEmmanuel Vadot 1605f1d7ae31SEmmanuel Vadot if (size < HDMI_INFOFRAME_SIZE(AVI)) 1606f1d7ae31SEmmanuel Vadot return -EINVAL; 1607f1d7ae31SEmmanuel Vadot 1608f1d7ae31SEmmanuel Vadot if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI || 1609f1d7ae31SEmmanuel Vadot ptr[1] != 2 || 1610f1d7ae31SEmmanuel Vadot ptr[2] != HDMI_AVI_INFOFRAME_SIZE) 1611f1d7ae31SEmmanuel Vadot return -EINVAL; 1612f1d7ae31SEmmanuel Vadot 1613f1d7ae31SEmmanuel Vadot if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0) 1614f1d7ae31SEmmanuel Vadot return -EINVAL; 1615f1d7ae31SEmmanuel Vadot 1616f1d7ae31SEmmanuel Vadot hdmi_avi_infoframe_init(frame); 1617f1d7ae31SEmmanuel Vadot 1618f1d7ae31SEmmanuel Vadot ptr += HDMI_INFOFRAME_HEADER_SIZE; 1619f1d7ae31SEmmanuel Vadot 1620f1d7ae31SEmmanuel Vadot frame->colorspace = (ptr[0] >> 5) & 0x3; 1621f1d7ae31SEmmanuel Vadot if (ptr[0] & 0x10) 1622f1d7ae31SEmmanuel Vadot frame->active_aspect = ptr[1] & 0xf; 1623f1d7ae31SEmmanuel Vadot if (ptr[0] & 0x8) { 1624f1d7ae31SEmmanuel Vadot frame->top_bar = (ptr[6] << 8) | ptr[5]; 1625f1d7ae31SEmmanuel Vadot frame->bottom_bar = (ptr[8] << 8) | ptr[7]; 1626f1d7ae31SEmmanuel Vadot } 1627f1d7ae31SEmmanuel Vadot if (ptr[0] & 0x4) { 1628f1d7ae31SEmmanuel Vadot frame->left_bar = (ptr[10] << 8) | ptr[9]; 1629f1d7ae31SEmmanuel Vadot frame->right_bar = (ptr[12] << 8) | ptr[11]; 1630f1d7ae31SEmmanuel Vadot } 1631f1d7ae31SEmmanuel Vadot frame->scan_mode = ptr[0] & 0x3; 1632f1d7ae31SEmmanuel Vadot 1633f1d7ae31SEmmanuel Vadot frame->colorimetry = (ptr[1] >> 6) & 0x3; 1634f1d7ae31SEmmanuel Vadot frame->picture_aspect = (ptr[1] >> 4) & 0x3; 1635f1d7ae31SEmmanuel Vadot frame->active_aspect = ptr[1] & 0xf; 1636f1d7ae31SEmmanuel Vadot 1637f1d7ae31SEmmanuel Vadot frame->itc = ptr[2] & 0x80 ? true : false; 1638f1d7ae31SEmmanuel Vadot frame->extended_colorimetry = (ptr[2] >> 4) & 0x7; 1639f1d7ae31SEmmanuel Vadot frame->quantization_range = (ptr[2] >> 2) & 0x3; 1640f1d7ae31SEmmanuel Vadot frame->nups = ptr[2] & 0x3; 1641f1d7ae31SEmmanuel Vadot 1642f1d7ae31SEmmanuel Vadot frame->video_code = ptr[3] & 0x7f; 1643f1d7ae31SEmmanuel Vadot frame->ycc_quantization_range = (ptr[4] >> 6) & 0x3; 1644f1d7ae31SEmmanuel Vadot frame->content_type = (ptr[4] >> 4) & 0x3; 1645f1d7ae31SEmmanuel Vadot 1646f1d7ae31SEmmanuel Vadot frame->pixel_repeat = ptr[4] & 0xf; 1647f1d7ae31SEmmanuel Vadot 1648f1d7ae31SEmmanuel Vadot return 0; 1649f1d7ae31SEmmanuel Vadot } 1650f1d7ae31SEmmanuel Vadot 1651f1d7ae31SEmmanuel Vadot /** 1652f1d7ae31SEmmanuel Vadot * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe 1653f1d7ae31SEmmanuel Vadot * @frame: HDMI SPD infoframe 1654f1d7ae31SEmmanuel Vadot * @buffer: source buffer 1655f1d7ae31SEmmanuel Vadot * @size: size of buffer 1656f1d7ae31SEmmanuel Vadot * 1657f1d7ae31SEmmanuel Vadot * Unpacks the information contained in binary @buffer into a structured 1658f1d7ae31SEmmanuel Vadot * @frame of the HDMI Source Product Description (SPD) information frame. 1659f1d7ae31SEmmanuel Vadot * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 1660f1d7ae31SEmmanuel Vadot * specification. 1661f1d7ae31SEmmanuel Vadot * 1662f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 1663f1d7ae31SEmmanuel Vadot */ 1664f1d7ae31SEmmanuel Vadot static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, 1665f1d7ae31SEmmanuel Vadot const void *buffer, size_t size) 1666f1d7ae31SEmmanuel Vadot { 1667f1d7ae31SEmmanuel Vadot const u8 *ptr = buffer; 1668f1d7ae31SEmmanuel Vadot int ret; 1669f1d7ae31SEmmanuel Vadot 1670f1d7ae31SEmmanuel Vadot if (size < HDMI_INFOFRAME_SIZE(SPD)) 1671f1d7ae31SEmmanuel Vadot return -EINVAL; 1672f1d7ae31SEmmanuel Vadot 1673f1d7ae31SEmmanuel Vadot if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD || 1674f1d7ae31SEmmanuel Vadot ptr[1] != 1 || 1675f1d7ae31SEmmanuel Vadot ptr[2] != HDMI_SPD_INFOFRAME_SIZE) { 1676f1d7ae31SEmmanuel Vadot return -EINVAL; 1677f1d7ae31SEmmanuel Vadot } 1678f1d7ae31SEmmanuel Vadot 1679f1d7ae31SEmmanuel Vadot if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0) 1680f1d7ae31SEmmanuel Vadot return -EINVAL; 1681f1d7ae31SEmmanuel Vadot 1682f1d7ae31SEmmanuel Vadot ptr += HDMI_INFOFRAME_HEADER_SIZE; 1683f1d7ae31SEmmanuel Vadot 1684f1d7ae31SEmmanuel Vadot ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8); 1685f1d7ae31SEmmanuel Vadot if (ret) 1686f1d7ae31SEmmanuel Vadot return ret; 1687f1d7ae31SEmmanuel Vadot 1688f1d7ae31SEmmanuel Vadot frame->sdi = ptr[24]; 1689f1d7ae31SEmmanuel Vadot 1690f1d7ae31SEmmanuel Vadot return 0; 1691f1d7ae31SEmmanuel Vadot } 1692f1d7ae31SEmmanuel Vadot 1693f1d7ae31SEmmanuel Vadot /** 1694f1d7ae31SEmmanuel Vadot * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe 1695f1d7ae31SEmmanuel Vadot * @frame: HDMI Audio infoframe 1696f1d7ae31SEmmanuel Vadot * @buffer: source buffer 1697f1d7ae31SEmmanuel Vadot * @size: size of buffer 1698f1d7ae31SEmmanuel Vadot * 1699f1d7ae31SEmmanuel Vadot * Unpacks the information contained in binary @buffer into a structured 1700f1d7ae31SEmmanuel Vadot * @frame of the HDMI Audio information frame. 1701f1d7ae31SEmmanuel Vadot * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 1702f1d7ae31SEmmanuel Vadot * specification. 1703f1d7ae31SEmmanuel Vadot * 1704f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 1705f1d7ae31SEmmanuel Vadot */ 1706f1d7ae31SEmmanuel Vadot static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, 1707f1d7ae31SEmmanuel Vadot const void *buffer, size_t size) 1708f1d7ae31SEmmanuel Vadot { 1709f1d7ae31SEmmanuel Vadot const u8 *ptr = buffer; 1710f1d7ae31SEmmanuel Vadot int ret; 1711f1d7ae31SEmmanuel Vadot 1712f1d7ae31SEmmanuel Vadot if (size < HDMI_INFOFRAME_SIZE(AUDIO)) 1713f1d7ae31SEmmanuel Vadot return -EINVAL; 1714f1d7ae31SEmmanuel Vadot 1715f1d7ae31SEmmanuel Vadot if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO || 1716f1d7ae31SEmmanuel Vadot ptr[1] != 1 || 1717f1d7ae31SEmmanuel Vadot ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) { 1718f1d7ae31SEmmanuel Vadot return -EINVAL; 1719f1d7ae31SEmmanuel Vadot } 1720f1d7ae31SEmmanuel Vadot 1721f1d7ae31SEmmanuel Vadot if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0) 1722f1d7ae31SEmmanuel Vadot return -EINVAL; 1723f1d7ae31SEmmanuel Vadot 1724f1d7ae31SEmmanuel Vadot ret = hdmi_audio_infoframe_init(frame); 1725f1d7ae31SEmmanuel Vadot if (ret) 1726f1d7ae31SEmmanuel Vadot return ret; 1727f1d7ae31SEmmanuel Vadot 1728f1d7ae31SEmmanuel Vadot ptr += HDMI_INFOFRAME_HEADER_SIZE; 1729f1d7ae31SEmmanuel Vadot 1730f1d7ae31SEmmanuel Vadot frame->channels = ptr[0] & 0x7; 1731f1d7ae31SEmmanuel Vadot frame->coding_type = (ptr[0] >> 4) & 0xf; 1732f1d7ae31SEmmanuel Vadot frame->sample_size = ptr[1] & 0x3; 1733f1d7ae31SEmmanuel Vadot frame->sample_frequency = (ptr[1] >> 2) & 0x7; 1734f1d7ae31SEmmanuel Vadot frame->coding_type_ext = ptr[2] & 0x1f; 1735f1d7ae31SEmmanuel Vadot frame->channel_allocation = ptr[3]; 1736f1d7ae31SEmmanuel Vadot frame->level_shift_value = (ptr[4] >> 3) & 0xf; 1737f1d7ae31SEmmanuel Vadot frame->downmix_inhibit = ptr[4] & 0x80 ? true : false; 1738f1d7ae31SEmmanuel Vadot 1739f1d7ae31SEmmanuel Vadot return 0; 1740f1d7ae31SEmmanuel Vadot } 1741f1d7ae31SEmmanuel Vadot 1742f1d7ae31SEmmanuel Vadot /** 1743f1d7ae31SEmmanuel Vadot * hdmi_vendor_any_infoframe_unpack() - unpack binary buffer to a HDMI 1744f1d7ae31SEmmanuel Vadot * vendor infoframe 1745f1d7ae31SEmmanuel Vadot * @frame: HDMI Vendor infoframe 1746f1d7ae31SEmmanuel Vadot * @buffer: source buffer 1747f1d7ae31SEmmanuel Vadot * @size: size of buffer 1748f1d7ae31SEmmanuel Vadot * 1749f1d7ae31SEmmanuel Vadot * Unpacks the information contained in binary @buffer into a structured 1750f1d7ae31SEmmanuel Vadot * @frame of the HDMI Vendor information frame. 1751f1d7ae31SEmmanuel Vadot * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 1752f1d7ae31SEmmanuel Vadot * specification. 1753f1d7ae31SEmmanuel Vadot * 1754f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 1755f1d7ae31SEmmanuel Vadot */ 1756f1d7ae31SEmmanuel Vadot static int 1757f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, 1758f1d7ae31SEmmanuel Vadot const void *buffer, size_t size) 1759f1d7ae31SEmmanuel Vadot { 1760f1d7ae31SEmmanuel Vadot const u8 *ptr = buffer; 1761f1d7ae31SEmmanuel Vadot size_t length; 1762f1d7ae31SEmmanuel Vadot int ret; 1763f1d7ae31SEmmanuel Vadot u8 hdmi_video_format; 1764f1d7ae31SEmmanuel Vadot struct hdmi_vendor_infoframe *hvf = &frame->hdmi; 1765f1d7ae31SEmmanuel Vadot 1766f1d7ae31SEmmanuel Vadot if (size < HDMI_INFOFRAME_HEADER_SIZE) 1767f1d7ae31SEmmanuel Vadot return -EINVAL; 1768f1d7ae31SEmmanuel Vadot 1769f1d7ae31SEmmanuel Vadot if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR || 1770f1d7ae31SEmmanuel Vadot ptr[1] != 1 || 1771f1d7ae31SEmmanuel Vadot (ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6)) 1772f1d7ae31SEmmanuel Vadot return -EINVAL; 1773f1d7ae31SEmmanuel Vadot 1774f1d7ae31SEmmanuel Vadot length = ptr[2]; 1775f1d7ae31SEmmanuel Vadot 1776f1d7ae31SEmmanuel Vadot if (size < HDMI_INFOFRAME_HEADER_SIZE + length) 1777f1d7ae31SEmmanuel Vadot return -EINVAL; 1778f1d7ae31SEmmanuel Vadot 1779f1d7ae31SEmmanuel Vadot if (hdmi_infoframe_checksum(buffer, 1780f1d7ae31SEmmanuel Vadot HDMI_INFOFRAME_HEADER_SIZE + length) != 0) 1781f1d7ae31SEmmanuel Vadot return -EINVAL; 1782f1d7ae31SEmmanuel Vadot 1783f1d7ae31SEmmanuel Vadot ptr += HDMI_INFOFRAME_HEADER_SIZE; 1784f1d7ae31SEmmanuel Vadot 1785f1d7ae31SEmmanuel Vadot /* HDMI OUI */ 1786f1d7ae31SEmmanuel Vadot if ((ptr[0] != 0x03) || 1787f1d7ae31SEmmanuel Vadot (ptr[1] != 0x0c) || 1788f1d7ae31SEmmanuel Vadot (ptr[2] != 0x00)) 1789f1d7ae31SEmmanuel Vadot return -EINVAL; 1790f1d7ae31SEmmanuel Vadot 1791f1d7ae31SEmmanuel Vadot hdmi_video_format = ptr[3] >> 5; 1792f1d7ae31SEmmanuel Vadot 1793f1d7ae31SEmmanuel Vadot if (hdmi_video_format > 0x2) 1794f1d7ae31SEmmanuel Vadot return -EINVAL; 1795f1d7ae31SEmmanuel Vadot 1796f1d7ae31SEmmanuel Vadot ret = hdmi_vendor_infoframe_init(hvf); 1797f1d7ae31SEmmanuel Vadot if (ret) 1798f1d7ae31SEmmanuel Vadot return ret; 1799f1d7ae31SEmmanuel Vadot 1800f1d7ae31SEmmanuel Vadot hvf->length = length; 1801f1d7ae31SEmmanuel Vadot 1802f1d7ae31SEmmanuel Vadot if (hdmi_video_format == 0x2) { 1803f1d7ae31SEmmanuel Vadot if (length != 5 && length != 6) 1804f1d7ae31SEmmanuel Vadot return -EINVAL; 1805f1d7ae31SEmmanuel Vadot hvf->s3d_struct = ptr[4] >> 4; 1806f1d7ae31SEmmanuel Vadot if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) { 1807f1d7ae31SEmmanuel Vadot if (length != 6) 1808f1d7ae31SEmmanuel Vadot return -EINVAL; 1809f1d7ae31SEmmanuel Vadot hvf->s3d_ext_data = ptr[5] >> 4; 1810f1d7ae31SEmmanuel Vadot } 1811f1d7ae31SEmmanuel Vadot } else if (hdmi_video_format == 0x1) { 1812f1d7ae31SEmmanuel Vadot if (length != 5) 1813f1d7ae31SEmmanuel Vadot return -EINVAL; 1814f1d7ae31SEmmanuel Vadot hvf->vic = ptr[4]; 1815f1d7ae31SEmmanuel Vadot } else { 1816f1d7ae31SEmmanuel Vadot if (length != 4) 1817f1d7ae31SEmmanuel Vadot return -EINVAL; 1818f1d7ae31SEmmanuel Vadot } 1819f1d7ae31SEmmanuel Vadot 1820f1d7ae31SEmmanuel Vadot return 0; 1821f1d7ae31SEmmanuel Vadot } 1822f1d7ae31SEmmanuel Vadot 1823f1d7ae31SEmmanuel Vadot /** 1824f1d7ae31SEmmanuel Vadot * hdmi_drm_infoframe_unpack_only() - unpack binary buffer of CTA-861-G DRM 1825f1d7ae31SEmmanuel Vadot * infoframe DataBytes to a HDMI DRM 1826f1d7ae31SEmmanuel Vadot * infoframe 1827f1d7ae31SEmmanuel Vadot * @frame: HDMI DRM infoframe 1828f1d7ae31SEmmanuel Vadot * @buffer: source buffer 1829f1d7ae31SEmmanuel Vadot * @size: size of buffer 1830f1d7ae31SEmmanuel Vadot * 1831f1d7ae31SEmmanuel Vadot * Unpacks CTA-861-G DRM infoframe DataBytes contained in the binary @buffer 1832f1d7ae31SEmmanuel Vadot * into a structured @frame of the HDMI Dynamic Range and Mastering (DRM) 1833f1d7ae31SEmmanuel Vadot * infoframe. 1834f1d7ae31SEmmanuel Vadot * 1835f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 1836f1d7ae31SEmmanuel Vadot */ 1837f1d7ae31SEmmanuel Vadot int hdmi_drm_infoframe_unpack_only(struct hdmi_drm_infoframe *frame, 1838f1d7ae31SEmmanuel Vadot const void *buffer, size_t size) 1839f1d7ae31SEmmanuel Vadot { 1840f1d7ae31SEmmanuel Vadot const u8 *ptr = buffer; 1841f1d7ae31SEmmanuel Vadot const u8 *temp; 1842f1d7ae31SEmmanuel Vadot u8 x_lsb, x_msb; 1843f1d7ae31SEmmanuel Vadot u8 y_lsb, y_msb; 1844f1d7ae31SEmmanuel Vadot int ret; 1845f1d7ae31SEmmanuel Vadot int i; 1846f1d7ae31SEmmanuel Vadot 1847f1d7ae31SEmmanuel Vadot if (size < HDMI_DRM_INFOFRAME_SIZE) 1848f1d7ae31SEmmanuel Vadot return -EINVAL; 1849f1d7ae31SEmmanuel Vadot 1850f1d7ae31SEmmanuel Vadot ret = hdmi_drm_infoframe_init(frame); 1851f1d7ae31SEmmanuel Vadot if (ret) 1852f1d7ae31SEmmanuel Vadot return ret; 1853f1d7ae31SEmmanuel Vadot 1854f1d7ae31SEmmanuel Vadot frame->eotf = ptr[0] & 0x7; 1855f1d7ae31SEmmanuel Vadot frame->metadata_type = ptr[1] & 0x7; 1856f1d7ae31SEmmanuel Vadot 1857f1d7ae31SEmmanuel Vadot temp = ptr + 2; 1858f1d7ae31SEmmanuel Vadot for (i = 0; i < 3; i++) { 1859f1d7ae31SEmmanuel Vadot x_lsb = *temp++; 1860f1d7ae31SEmmanuel Vadot x_msb = *temp++; 1861f1d7ae31SEmmanuel Vadot frame->display_primaries[i].x = (x_msb << 8) | x_lsb; 1862f1d7ae31SEmmanuel Vadot y_lsb = *temp++; 1863f1d7ae31SEmmanuel Vadot y_msb = *temp++; 1864f1d7ae31SEmmanuel Vadot frame->display_primaries[i].y = (y_msb << 8) | y_lsb; 1865f1d7ae31SEmmanuel Vadot } 1866f1d7ae31SEmmanuel Vadot 1867f1d7ae31SEmmanuel Vadot frame->white_point.x = (ptr[15] << 8) | ptr[14]; 1868f1d7ae31SEmmanuel Vadot frame->white_point.y = (ptr[17] << 8) | ptr[16]; 1869f1d7ae31SEmmanuel Vadot 1870f1d7ae31SEmmanuel Vadot frame->max_display_mastering_luminance = (ptr[19] << 8) | ptr[18]; 1871f1d7ae31SEmmanuel Vadot frame->min_display_mastering_luminance = (ptr[21] << 8) | ptr[20]; 1872f1d7ae31SEmmanuel Vadot frame->max_cll = (ptr[23] << 8) | ptr[22]; 1873f1d7ae31SEmmanuel Vadot frame->max_fall = (ptr[25] << 8) | ptr[24]; 1874f1d7ae31SEmmanuel Vadot 1875f1d7ae31SEmmanuel Vadot return 0; 1876f1d7ae31SEmmanuel Vadot } 1877f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_unpack_only); 1878f1d7ae31SEmmanuel Vadot 1879f1d7ae31SEmmanuel Vadot /** 1880f1d7ae31SEmmanuel Vadot * hdmi_drm_infoframe_unpack() - unpack binary buffer to a HDMI DRM infoframe 1881f1d7ae31SEmmanuel Vadot * @frame: HDMI DRM infoframe 1882f1d7ae31SEmmanuel Vadot * @buffer: source buffer 1883f1d7ae31SEmmanuel Vadot * @size: size of buffer 1884f1d7ae31SEmmanuel Vadot * 1885f1d7ae31SEmmanuel Vadot * Unpacks the CTA-861-G DRM infoframe contained in the binary @buffer into 1886f1d7ae31SEmmanuel Vadot * a structured @frame of the HDMI Dynamic Range and Mastering (DRM) 1887f1d7ae31SEmmanuel Vadot * infoframe. It also verifies the checksum as required by section 5.3.5 of 1888f1d7ae31SEmmanuel Vadot * the HDMI 1.4 specification. 1889f1d7ae31SEmmanuel Vadot * 1890f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 1891f1d7ae31SEmmanuel Vadot */ 1892f1d7ae31SEmmanuel Vadot static int hdmi_drm_infoframe_unpack(struct hdmi_drm_infoframe *frame, 1893f1d7ae31SEmmanuel Vadot const void *buffer, size_t size) 1894f1d7ae31SEmmanuel Vadot { 1895f1d7ae31SEmmanuel Vadot const u8 *ptr = buffer; 1896f1d7ae31SEmmanuel Vadot int ret; 1897f1d7ae31SEmmanuel Vadot 1898f1d7ae31SEmmanuel Vadot if (size < HDMI_INFOFRAME_SIZE(DRM)) 1899f1d7ae31SEmmanuel Vadot return -EINVAL; 1900f1d7ae31SEmmanuel Vadot 1901f1d7ae31SEmmanuel Vadot if (ptr[0] != HDMI_INFOFRAME_TYPE_DRM || 1902f1d7ae31SEmmanuel Vadot ptr[1] != 1 || 1903f1d7ae31SEmmanuel Vadot ptr[2] != HDMI_DRM_INFOFRAME_SIZE) 1904f1d7ae31SEmmanuel Vadot return -EINVAL; 1905f1d7ae31SEmmanuel Vadot 1906f1d7ae31SEmmanuel Vadot if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(DRM)) != 0) 1907f1d7ae31SEmmanuel Vadot return -EINVAL; 1908f1d7ae31SEmmanuel Vadot 1909f1d7ae31SEmmanuel Vadot ret = hdmi_drm_infoframe_unpack_only(frame, ptr + HDMI_INFOFRAME_HEADER_SIZE, 1910f1d7ae31SEmmanuel Vadot size - HDMI_INFOFRAME_HEADER_SIZE); 1911f1d7ae31SEmmanuel Vadot return ret; 1912f1d7ae31SEmmanuel Vadot } 1913f1d7ae31SEmmanuel Vadot 1914f1d7ae31SEmmanuel Vadot /** 1915f1d7ae31SEmmanuel Vadot * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe 1916f1d7ae31SEmmanuel Vadot * @frame: HDMI infoframe 1917f1d7ae31SEmmanuel Vadot * @buffer: source buffer 1918f1d7ae31SEmmanuel Vadot * @size: size of buffer 1919f1d7ae31SEmmanuel Vadot * 1920f1d7ae31SEmmanuel Vadot * Unpacks the information contained in binary buffer @buffer into a structured 1921f1d7ae31SEmmanuel Vadot * @frame of a HDMI infoframe. 1922f1d7ae31SEmmanuel Vadot * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 1923f1d7ae31SEmmanuel Vadot * specification. 1924f1d7ae31SEmmanuel Vadot * 1925f1d7ae31SEmmanuel Vadot * Returns 0 on success or a negative error code on failure. 1926f1d7ae31SEmmanuel Vadot */ 1927f1d7ae31SEmmanuel Vadot int hdmi_infoframe_unpack(union hdmi_infoframe *frame, 1928f1d7ae31SEmmanuel Vadot const void *buffer, size_t size) 1929f1d7ae31SEmmanuel Vadot { 1930f1d7ae31SEmmanuel Vadot int ret; 1931f1d7ae31SEmmanuel Vadot const u8 *ptr = buffer; 1932f1d7ae31SEmmanuel Vadot 1933f1d7ae31SEmmanuel Vadot if (size < HDMI_INFOFRAME_HEADER_SIZE) 1934f1d7ae31SEmmanuel Vadot return -EINVAL; 1935f1d7ae31SEmmanuel Vadot 1936f1d7ae31SEmmanuel Vadot switch (ptr[0]) { 1937f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AVI: 1938f1d7ae31SEmmanuel Vadot ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer, size); 1939f1d7ae31SEmmanuel Vadot break; 1940f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_DRM: 1941f1d7ae31SEmmanuel Vadot ret = hdmi_drm_infoframe_unpack(&frame->drm, buffer, size); 1942f1d7ae31SEmmanuel Vadot break; 1943f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_SPD: 1944f1d7ae31SEmmanuel Vadot ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer, size); 1945f1d7ae31SEmmanuel Vadot break; 1946f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_AUDIO: 1947f1d7ae31SEmmanuel Vadot ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer, size); 1948f1d7ae31SEmmanuel Vadot break; 1949f1d7ae31SEmmanuel Vadot case HDMI_INFOFRAME_TYPE_VENDOR: 1950f1d7ae31SEmmanuel Vadot ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer, size); 1951f1d7ae31SEmmanuel Vadot break; 1952f1d7ae31SEmmanuel Vadot default: 1953f1d7ae31SEmmanuel Vadot ret = -EINVAL; 1954f1d7ae31SEmmanuel Vadot break; 1955f1d7ae31SEmmanuel Vadot } 1956f1d7ae31SEmmanuel Vadot 1957f1d7ae31SEmmanuel Vadot return ret; 1958f1d7ae31SEmmanuel Vadot } 1959f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_unpack); 1960