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