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