brintos

brintos / linux-shallow public Read only

0
0
Text · 52.3 KiB · ba301f3 Raw
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