Path: blob/main/sys/compat/linuxkpi/common/src/linux_hdmi.c
39586 views
/*1* Copyright (C) 2012 Avionic Design GmbH2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sub license,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the11* next paragraph) shall be included in all copies or substantial portions12* of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*/2223#ifdef __linux__24#include <drm/display/drm_dp.h>25#endif26#include <linux/bitops.h>27#include <linux/bug.h>28#include <linux/errno.h>29#include <linux/export.h>30#include <linux/hdmi.h>31#include <linux/string.h>32#include <linux/device.h>3334#define hdmi_log(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__)3536static u8 hdmi_infoframe_checksum(const u8 *ptr, size_t size)37{38u8 csum = 0;39size_t i;4041/* compute checksum */42for (i = 0; i < size; i++)43csum += ptr[i];4445return 256 - csum;46}4748static void hdmi_infoframe_set_checksum(void *buffer, size_t size)49{50u8 *ptr = buffer;5152ptr[3] = hdmi_infoframe_checksum(buffer, size);53}5455/**56* hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe57* @frame: HDMI AVI infoframe58*/59void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)60{61memset(frame, 0, sizeof(*frame));6263frame->type = HDMI_INFOFRAME_TYPE_AVI;64frame->version = 2;65frame->length = HDMI_AVI_INFOFRAME_SIZE;66}67EXPORT_SYMBOL(hdmi_avi_infoframe_init);6869static int hdmi_avi_infoframe_check_only(const struct hdmi_avi_infoframe *frame)70{71if (frame->type != HDMI_INFOFRAME_TYPE_AVI ||72frame->version != 2 ||73frame->length != HDMI_AVI_INFOFRAME_SIZE)74return -EINVAL;7576if (frame->picture_aspect > HDMI_PICTURE_ASPECT_16_9)77return -EINVAL;7879return 0;80}8182/**83* hdmi_avi_infoframe_check() - check a HDMI AVI infoframe84* @frame: HDMI AVI infoframe85*86* Validates that the infoframe is consistent and updates derived fields87* (eg. length) based on other fields.88*89* Returns 0 on success or a negative error code on failure.90*/91int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame)92{93return hdmi_avi_infoframe_check_only(frame);94}95EXPORT_SYMBOL(hdmi_avi_infoframe_check);9697/**98* hdmi_avi_infoframe_pack_only() - write HDMI AVI infoframe to binary buffer99* @frame: HDMI AVI infoframe100* @buffer: destination buffer101* @size: size of buffer102*103* Packs the information contained in the @frame structure into a binary104* representation that can be written into the corresponding controller105* registers. Also computes the checksum as required by section 5.3.5 of106* the HDMI 1.4 specification.107*108* Returns the number of bytes packed into the binary buffer or a negative109* error code on failure.110*/111ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,112void *buffer, size_t size)113{114u8 *ptr = buffer;115size_t length;116int ret;117118ret = hdmi_avi_infoframe_check_only(frame);119if (ret)120return ret;121122length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;123124if (size < length)125return -ENOSPC;126127memset(buffer, 0, size);128129ptr[0] = frame->type;130ptr[1] = frame->version;131ptr[2] = frame->length;132ptr[3] = 0; /* checksum */133134/* start infoframe payload */135ptr += HDMI_INFOFRAME_HEADER_SIZE;136137ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);138139/*140* Data byte 1, bit 4 has to be set if we provide the active format141* aspect ratio142*/143if (frame->active_aspect & 0xf)144ptr[0] |= BIT(4);145146/* Bit 3 and 2 indicate if we transmit horizontal/vertical bar data */147if (frame->top_bar || frame->bottom_bar)148ptr[0] |= BIT(3);149150if (frame->left_bar || frame->right_bar)151ptr[0] |= BIT(2);152153ptr[1] = ((frame->colorimetry & 0x3) << 6) |154((frame->picture_aspect & 0x3) << 4) |155(frame->active_aspect & 0xf);156157ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |158((frame->quantization_range & 0x3) << 2) |159(frame->nups & 0x3);160161if (frame->itc)162ptr[2] |= BIT(7);163164ptr[3] = frame->video_code & 0x7f;165166ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |167((frame->content_type & 0x3) << 4) |168(frame->pixel_repeat & 0xf);169170ptr[5] = frame->top_bar & 0xff;171ptr[6] = (frame->top_bar >> 8) & 0xff;172ptr[7] = frame->bottom_bar & 0xff;173ptr[8] = (frame->bottom_bar >> 8) & 0xff;174ptr[9] = frame->left_bar & 0xff;175ptr[10] = (frame->left_bar >> 8) & 0xff;176ptr[11] = frame->right_bar & 0xff;177ptr[12] = (frame->right_bar >> 8) & 0xff;178179hdmi_infoframe_set_checksum(buffer, length);180181return length;182}183EXPORT_SYMBOL(hdmi_avi_infoframe_pack_only);184185/**186* hdmi_avi_infoframe_pack() - check a HDMI AVI infoframe,187* and write it to binary buffer188* @frame: HDMI AVI infoframe189* @buffer: destination buffer190* @size: size of buffer191*192* Validates that the infoframe is consistent and updates derived fields193* (eg. length) based on other fields, after which it packs the information194* contained in the @frame structure into a binary representation that195* can be written into the corresponding controller registers. This function196* also computes the checksum as required by section 5.3.5 of the HDMI 1.4197* specification.198*199* Returns the number of bytes packed into the binary buffer or a negative200* error code on failure.201*/202ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame,203void *buffer, size_t size)204{205int ret;206207ret = hdmi_avi_infoframe_check(frame);208if (ret)209return ret;210211return hdmi_avi_infoframe_pack_only(frame, buffer, size);212}213EXPORT_SYMBOL(hdmi_avi_infoframe_pack);214215/**216* hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe217* @frame: HDMI SPD infoframe218* @vendor: vendor string219* @product: product string220*221* Returns 0 on success or a negative error code on failure.222*/223int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,224const char *vendor, const char *product)225{226size_t len;227228memset(frame, 0, sizeof(*frame));229230frame->type = HDMI_INFOFRAME_TYPE_SPD;231frame->version = 1;232frame->length = HDMI_SPD_INFOFRAME_SIZE;233234len = strlen(vendor);235memcpy(frame->vendor, vendor, min(len, sizeof(frame->vendor)));236len = strlen(product);237memcpy(frame->product, product, min(len, sizeof(frame->product)));238239return 0;240}241EXPORT_SYMBOL(hdmi_spd_infoframe_init);242243static int hdmi_spd_infoframe_check_only(const struct hdmi_spd_infoframe *frame)244{245if (frame->type != HDMI_INFOFRAME_TYPE_SPD ||246frame->version != 1 ||247frame->length != HDMI_SPD_INFOFRAME_SIZE)248return -EINVAL;249250return 0;251}252253/**254* hdmi_spd_infoframe_check() - check a HDMI SPD infoframe255* @frame: HDMI SPD infoframe256*257* Validates that the infoframe is consistent and updates derived fields258* (eg. length) based on other fields.259*260* Returns 0 on success or a negative error code on failure.261*/262int hdmi_spd_infoframe_check(struct hdmi_spd_infoframe *frame)263{264return hdmi_spd_infoframe_check_only(frame);265}266EXPORT_SYMBOL(hdmi_spd_infoframe_check);267268/**269* hdmi_spd_infoframe_pack_only() - write HDMI SPD infoframe to binary buffer270* @frame: HDMI SPD infoframe271* @buffer: destination buffer272* @size: size of buffer273*274* Packs the information contained in the @frame structure into a binary275* representation that can be written into the corresponding controller276* registers. Also computes the checksum as required by section 5.3.5 of277* the HDMI 1.4 specification.278*279* Returns the number of bytes packed into the binary buffer or a negative280* error code on failure.281*/282ssize_t hdmi_spd_infoframe_pack_only(const struct hdmi_spd_infoframe *frame,283void *buffer, size_t size)284{285u8 *ptr = buffer;286size_t length;287int ret;288289ret = hdmi_spd_infoframe_check_only(frame);290if (ret)291return ret;292293length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;294295if (size < length)296return -ENOSPC;297298memset(buffer, 0, size);299300ptr[0] = frame->type;301ptr[1] = frame->version;302ptr[2] = frame->length;303ptr[3] = 0; /* checksum */304305/* start infoframe payload */306ptr += HDMI_INFOFRAME_HEADER_SIZE;307308memcpy(ptr, frame->vendor, sizeof(frame->vendor));309memcpy(ptr + 8, frame->product, sizeof(frame->product));310311ptr[24] = frame->sdi;312313hdmi_infoframe_set_checksum(buffer, length);314315return length;316}317EXPORT_SYMBOL(hdmi_spd_infoframe_pack_only);318319/**320* hdmi_spd_infoframe_pack() - check a HDMI SPD infoframe,321* and write it to binary buffer322* @frame: HDMI SPD infoframe323* @buffer: destination buffer324* @size: size of buffer325*326* Validates that the infoframe is consistent and updates derived fields327* (eg. length) based on other fields, after which it packs the information328* contained in the @frame structure into a binary representation that329* can be written into the corresponding controller registers. This function330* also computes the checksum as required by section 5.3.5 of the HDMI 1.4331* specification.332*333* Returns the number of bytes packed into the binary buffer or a negative334* error code on failure.335*/336ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame,337void *buffer, size_t size)338{339int ret;340341ret = hdmi_spd_infoframe_check(frame);342if (ret)343return ret;344345return hdmi_spd_infoframe_pack_only(frame, buffer, size);346}347EXPORT_SYMBOL(hdmi_spd_infoframe_pack);348349/**350* hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe351* @frame: HDMI audio infoframe352*353* Returns 0 on success or a negative error code on failure.354*/355int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)356{357memset(frame, 0, sizeof(*frame));358359frame->type = HDMI_INFOFRAME_TYPE_AUDIO;360frame->version = 1;361frame->length = HDMI_AUDIO_INFOFRAME_SIZE;362363return 0;364}365EXPORT_SYMBOL(hdmi_audio_infoframe_init);366367static int hdmi_audio_infoframe_check_only(const struct hdmi_audio_infoframe *frame)368{369if (frame->type != HDMI_INFOFRAME_TYPE_AUDIO ||370frame->version != 1 ||371frame->length != HDMI_AUDIO_INFOFRAME_SIZE)372return -EINVAL;373374return 0;375}376377/**378* hdmi_audio_infoframe_check() - check a HDMI audio infoframe379* @frame: HDMI audio infoframe380*381* Validates that the infoframe is consistent and updates derived fields382* (eg. length) based on other fields.383*384* Returns 0 on success or a negative error code on failure.385*/386int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame)387{388return hdmi_audio_infoframe_check_only(frame);389}390EXPORT_SYMBOL(hdmi_audio_infoframe_check);391392static void393hdmi_audio_infoframe_pack_payload(const struct hdmi_audio_infoframe *frame,394u8 *buffer)395{396u8 channels;397398if (frame->channels >= 2)399channels = frame->channels - 1;400else401channels = 0;402403buffer[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);404buffer[1] = ((frame->sample_frequency & 0x7) << 2) |405(frame->sample_size & 0x3);406buffer[2] = frame->coding_type_ext & 0x1f;407buffer[3] = frame->channel_allocation;408buffer[4] = (frame->level_shift_value & 0xf) << 3;409410if (frame->downmix_inhibit)411buffer[4] |= BIT(7);412}413414/**415* hdmi_audio_infoframe_pack_only() - write HDMI audio infoframe to binary buffer416* @frame: HDMI audio infoframe417* @buffer: destination buffer418* @size: size of buffer419*420* Packs the information contained in the @frame structure into a binary421* representation that can be written into the corresponding controller422* registers. Also computes the checksum as required by section 5.3.5 of423* the HDMI 1.4 specification.424*425* Returns the number of bytes packed into the binary buffer or a negative426* error code on failure.427*/428ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame,429void *buffer, size_t size)430{431u8 *ptr = buffer;432size_t length;433int ret;434435ret = hdmi_audio_infoframe_check_only(frame);436if (ret)437return ret;438439length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;440441if (size < length)442return -ENOSPC;443444memset(buffer, 0, size);445446ptr[0] = frame->type;447ptr[1] = frame->version;448ptr[2] = frame->length;449ptr[3] = 0; /* checksum */450451hdmi_audio_infoframe_pack_payload(frame,452ptr + HDMI_INFOFRAME_HEADER_SIZE);453454hdmi_infoframe_set_checksum(buffer, length);455456return length;457}458EXPORT_SYMBOL(hdmi_audio_infoframe_pack_only);459460/**461* hdmi_audio_infoframe_pack() - check a HDMI Audio infoframe,462* and write it to binary buffer463* @frame: HDMI Audio infoframe464* @buffer: destination buffer465* @size: size of buffer466*467* Validates that the infoframe is consistent and updates derived fields468* (eg. length) based on other fields, after which it packs the information469* contained in the @frame structure into a binary representation that470* can be written into the corresponding controller registers. This function471* also computes the checksum as required by section 5.3.5 of the HDMI 1.4472* specification.473*474* Returns the number of bytes packed into the binary buffer or a negative475* error code on failure.476*/477ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,478void *buffer, size_t size)479{480int ret;481482ret = hdmi_audio_infoframe_check(frame);483if (ret)484return ret;485486return hdmi_audio_infoframe_pack_only(frame, buffer, size);487}488EXPORT_SYMBOL(hdmi_audio_infoframe_pack);489490#ifdef __linux__491/**492* hdmi_audio_infoframe_pack_for_dp - Pack a HDMI Audio infoframe for DisplayPort493*494* @frame: HDMI Audio infoframe495* @sdp: Secondary data packet for DisplayPort.496* @dp_version: DisplayPort version to be encoded in the header497*498* Packs a HDMI Audio Infoframe to be sent over DisplayPort. This function499* fills the secondary data packet to be used for DisplayPort.500*501* Return: Number of total written bytes or a negative errno on failure.502*/503ssize_t504hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame,505struct dp_sdp *sdp, u8 dp_version)506{507int ret;508509ret = hdmi_audio_infoframe_check(frame);510if (ret)511return ret;512513memset(sdp->db, 0, sizeof(sdp->db));514515/* Secondary-data packet header */516sdp->sdp_header.HB0 = 0;517sdp->sdp_header.HB1 = frame->type;518sdp->sdp_header.HB2 = DP_SDP_AUDIO_INFOFRAME_HB2;519sdp->sdp_header.HB3 = (dp_version & 0x3f) << 2;520521hdmi_audio_infoframe_pack_payload(frame, sdp->db);522523/* Return size = frame length + four HB for sdp_header */524return frame->length + 4;525}526EXPORT_SYMBOL(hdmi_audio_infoframe_pack_for_dp);527#endif528529/**530* hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe531* @frame: HDMI vendor infoframe532*533* Returns 0 on success or a negative error code on failure.534*/535int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)536{537memset(frame, 0, sizeof(*frame));538539frame->type = HDMI_INFOFRAME_TYPE_VENDOR;540frame->version = 1;541542frame->oui = HDMI_IEEE_OUI;543544/*545* 0 is a valid value for s3d_struct, so we use a special "not set"546* value547*/548frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID;549frame->length = HDMI_VENDOR_INFOFRAME_SIZE;550551return 0;552}553EXPORT_SYMBOL(hdmi_vendor_infoframe_init);554555static int hdmi_vendor_infoframe_length(const struct hdmi_vendor_infoframe *frame)556{557/* for side by side (half) we also need to provide 3D_Ext_Data */558if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)559return 6;560else if (frame->vic != 0 || frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)561return 5;562else563return 4;564}565566static int hdmi_vendor_infoframe_check_only(const struct hdmi_vendor_infoframe *frame)567{568if (frame->type != HDMI_INFOFRAME_TYPE_VENDOR ||569frame->version != 1 ||570frame->oui != HDMI_IEEE_OUI)571return -EINVAL;572573/* only one of those can be supplied */574if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)575return -EINVAL;576577if (frame->length != hdmi_vendor_infoframe_length(frame))578return -EINVAL;579580return 0;581}582583/**584* hdmi_vendor_infoframe_check() - check a HDMI vendor infoframe585* @frame: HDMI infoframe586*587* Validates that the infoframe is consistent and updates derived fields588* (eg. length) based on other fields.589*590* Returns 0 on success or a negative error code on failure.591*/592int hdmi_vendor_infoframe_check(struct hdmi_vendor_infoframe *frame)593{594frame->length = hdmi_vendor_infoframe_length(frame);595596return hdmi_vendor_infoframe_check_only(frame);597}598EXPORT_SYMBOL(hdmi_vendor_infoframe_check);599600/**601* hdmi_vendor_infoframe_pack_only() - write a HDMI vendor infoframe to binary buffer602* @frame: HDMI infoframe603* @buffer: destination buffer604* @size: size of buffer605*606* Packs the information contained in the @frame structure into a binary607* representation that can be written into the corresponding controller608* registers. Also computes the checksum as required by section 5.3.5 of609* the HDMI 1.4 specification.610*611* Returns the number of bytes packed into the binary buffer or a negative612* error code on failure.613*/614ssize_t hdmi_vendor_infoframe_pack_only(const struct hdmi_vendor_infoframe *frame,615void *buffer, size_t size)616{617u8 *ptr = buffer;618size_t length;619int ret;620621ret = hdmi_vendor_infoframe_check_only(frame);622if (ret)623return ret;624625length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;626627if (size < length)628return -ENOSPC;629630memset(buffer, 0, size);631632ptr[0] = frame->type;633ptr[1] = frame->version;634ptr[2] = frame->length;635ptr[3] = 0; /* checksum */636637/* HDMI OUI */638ptr[4] = 0x03;639ptr[5] = 0x0c;640ptr[6] = 0x00;641642if (frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {643ptr[7] = 0x2 << 5; /* video format */644ptr[8] = (frame->s3d_struct & 0xf) << 4;645if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)646ptr[9] = (frame->s3d_ext_data & 0xf) << 4;647} else if (frame->vic) {648ptr[7] = 0x1 << 5; /* video format */649ptr[8] = frame->vic;650} else {651ptr[7] = 0x0 << 5; /* video format */652}653654hdmi_infoframe_set_checksum(buffer, length);655656return length;657}658EXPORT_SYMBOL(hdmi_vendor_infoframe_pack_only);659660/**661* hdmi_vendor_infoframe_pack() - check a HDMI Vendor infoframe,662* and write it to binary buffer663* @frame: HDMI Vendor infoframe664* @buffer: destination buffer665* @size: size of buffer666*667* Validates that the infoframe is consistent and updates derived fields668* (eg. length) based on other fields, after which it packs the information669* contained in the @frame structure into a binary representation that670* can be written into the corresponding controller registers. This function671* also computes the checksum as required by section 5.3.5 of the HDMI 1.4672* specification.673*674* Returns the number of bytes packed into the binary buffer or a negative675* error code on failure.676*/677ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,678void *buffer, size_t size)679{680int ret;681682ret = hdmi_vendor_infoframe_check(frame);683if (ret)684return ret;685686return hdmi_vendor_infoframe_pack_only(frame, buffer, size);687}688EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);689690static int691hdmi_vendor_any_infoframe_check_only(const union hdmi_vendor_any_infoframe *frame)692{693if (frame->any.type != HDMI_INFOFRAME_TYPE_VENDOR ||694frame->any.version != 1)695return -EINVAL;696697return 0;698}699700/**701* hdmi_drm_infoframe_init() - initialize an HDMI Dynaminc Range and702* mastering infoframe703* @frame: HDMI DRM infoframe704*705* Returns 0 on success or a negative error code on failure.706*/707int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame)708{709memset(frame, 0, sizeof(*frame));710711frame->type = HDMI_INFOFRAME_TYPE_DRM;712frame->version = 1;713frame->length = HDMI_DRM_INFOFRAME_SIZE;714715return 0;716}717EXPORT_SYMBOL(hdmi_drm_infoframe_init);718719static int hdmi_drm_infoframe_check_only(const struct hdmi_drm_infoframe *frame)720{721if (frame->type != HDMI_INFOFRAME_TYPE_DRM ||722frame->version != 1)723return -EINVAL;724725if (frame->length != HDMI_DRM_INFOFRAME_SIZE)726return -EINVAL;727728return 0;729}730731/**732* hdmi_drm_infoframe_check() - check a HDMI DRM infoframe733* @frame: HDMI DRM infoframe734*735* Validates that the infoframe is consistent.736* Returns 0 on success or a negative error code on failure.737*/738int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame)739{740return hdmi_drm_infoframe_check_only(frame);741}742EXPORT_SYMBOL(hdmi_drm_infoframe_check);743744/**745* hdmi_drm_infoframe_pack_only() - write HDMI DRM infoframe to binary buffer746* @frame: HDMI DRM infoframe747* @buffer: destination buffer748* @size: size of buffer749*750* Packs the information contained in the @frame structure into a binary751* representation that can be written into the corresponding controller752* registers. Also computes the checksum as required by section 5.3.5 of753* the HDMI 1.4 specification.754*755* Returns the number of bytes packed into the binary buffer or a negative756* error code on failure.757*/758ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame,759void *buffer, size_t size)760{761u8 *ptr = buffer;762size_t length;763int i;764765length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;766767if (size < length)768return -ENOSPC;769770memset(buffer, 0, size);771772ptr[0] = frame->type;773ptr[1] = frame->version;774ptr[2] = frame->length;775ptr[3] = 0; /* checksum */776777/* start infoframe payload */778ptr += HDMI_INFOFRAME_HEADER_SIZE;779780*ptr++ = frame->eotf;781*ptr++ = frame->metadata_type;782783for (i = 0; i < 3; i++) {784*ptr++ = frame->display_primaries[i].x;785*ptr++ = frame->display_primaries[i].x >> 8;786*ptr++ = frame->display_primaries[i].y;787*ptr++ = frame->display_primaries[i].y >> 8;788}789790*ptr++ = frame->white_point.x;791*ptr++ = frame->white_point.x >> 8;792793*ptr++ = frame->white_point.y;794*ptr++ = frame->white_point.y >> 8;795796*ptr++ = frame->max_display_mastering_luminance;797*ptr++ = frame->max_display_mastering_luminance >> 8;798799*ptr++ = frame->min_display_mastering_luminance;800*ptr++ = frame->min_display_mastering_luminance >> 8;801802*ptr++ = frame->max_cll;803*ptr++ = frame->max_cll >> 8;804805*ptr++ = frame->max_fall;806*ptr++ = frame->max_fall >> 8;807808hdmi_infoframe_set_checksum(buffer, length);809810return length;811}812EXPORT_SYMBOL(hdmi_drm_infoframe_pack_only);813814/**815* hdmi_drm_infoframe_pack() - check a HDMI DRM infoframe,816* and write it to binary buffer817* @frame: HDMI DRM infoframe818* @buffer: destination buffer819* @size: size of buffer820*821* Validates that the infoframe is consistent and updates derived fields822* (eg. length) based on other fields, after which it packs the information823* contained in the @frame structure into a binary representation that824* can be written into the corresponding controller registers. This function825* also computes the checksum as required by section 5.3.5 of the HDMI 1.4826* specification.827*828* Returns the number of bytes packed into the binary buffer or a negative829* error code on failure.830*/831ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame,832void *buffer, size_t size)833{834int ret;835836ret = hdmi_drm_infoframe_check(frame);837if (ret)838return ret;839840return hdmi_drm_infoframe_pack_only(frame, buffer, size);841}842EXPORT_SYMBOL(hdmi_drm_infoframe_pack);843844/*845* hdmi_vendor_any_infoframe_check() - check a vendor infoframe846*/847static int848hdmi_vendor_any_infoframe_check(union hdmi_vendor_any_infoframe *frame)849{850int ret;851852ret = hdmi_vendor_any_infoframe_check_only(frame);853if (ret)854return ret;855856/* we only know about HDMI vendor infoframes */857if (frame->any.oui != HDMI_IEEE_OUI)858return -EINVAL;859860return hdmi_vendor_infoframe_check(&frame->hdmi);861}862863/*864* hdmi_vendor_any_infoframe_pack_only() - write a vendor infoframe to binary buffer865*/866static ssize_t867hdmi_vendor_any_infoframe_pack_only(const union hdmi_vendor_any_infoframe *frame,868void *buffer, size_t size)869{870int ret;871872ret = hdmi_vendor_any_infoframe_check_only(frame);873if (ret)874return ret;875876/* we only know about HDMI vendor infoframes */877if (frame->any.oui != HDMI_IEEE_OUI)878return -EINVAL;879880return hdmi_vendor_infoframe_pack_only(&frame->hdmi, buffer, size);881}882883/*884* hdmi_vendor_any_infoframe_pack() - check a vendor infoframe,885* and write it to binary buffer886*/887static ssize_t888hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame,889void *buffer, size_t size)890{891int ret;892893ret = hdmi_vendor_any_infoframe_check(frame);894if (ret)895return ret;896897return hdmi_vendor_any_infoframe_pack_only(frame, buffer, size);898}899900/**901* hdmi_infoframe_check() - check a HDMI infoframe902* @frame: HDMI infoframe903*904* Validates that the infoframe is consistent and updates derived fields905* (eg. length) based on other fields.906*907* Returns 0 on success or a negative error code on failure.908*/909int910hdmi_infoframe_check(union hdmi_infoframe *frame)911{912switch (frame->any.type) {913case HDMI_INFOFRAME_TYPE_AVI:914return hdmi_avi_infoframe_check(&frame->avi);915case HDMI_INFOFRAME_TYPE_SPD:916return hdmi_spd_infoframe_check(&frame->spd);917case HDMI_INFOFRAME_TYPE_AUDIO:918return hdmi_audio_infoframe_check(&frame->audio);919case HDMI_INFOFRAME_TYPE_VENDOR:920return hdmi_vendor_any_infoframe_check(&frame->vendor);921default:922WARN(1, "Bad infoframe type %d\n", frame->any.type);923return -EINVAL;924}925}926EXPORT_SYMBOL(hdmi_infoframe_check);927928/**929* hdmi_infoframe_pack_only() - write a HDMI infoframe to binary buffer930* @frame: HDMI infoframe931* @buffer: destination buffer932* @size: size of buffer933*934* Packs the information contained in the @frame structure into a binary935* representation that can be written into the corresponding controller936* registers. Also computes the checksum as required by section 5.3.5 of937* the HDMI 1.4 specification.938*939* Returns the number of bytes packed into the binary buffer or a negative940* error code on failure.941*/942ssize_t943hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, void *buffer, size_t size)944{945ssize_t length;946947switch (frame->any.type) {948case HDMI_INFOFRAME_TYPE_AVI:949length = hdmi_avi_infoframe_pack_only(&frame->avi,950buffer, size);951break;952case HDMI_INFOFRAME_TYPE_DRM:953length = hdmi_drm_infoframe_pack_only(&frame->drm,954buffer, size);955break;956case HDMI_INFOFRAME_TYPE_SPD:957length = hdmi_spd_infoframe_pack_only(&frame->spd,958buffer, size);959break;960case HDMI_INFOFRAME_TYPE_AUDIO:961length = hdmi_audio_infoframe_pack_only(&frame->audio,962buffer, size);963break;964case HDMI_INFOFRAME_TYPE_VENDOR:965length = hdmi_vendor_any_infoframe_pack_only(&frame->vendor,966buffer, size);967break;968default:969WARN(1, "Bad infoframe type %d\n", frame->any.type);970length = -EINVAL;971}972973return length;974}975EXPORT_SYMBOL(hdmi_infoframe_pack_only);976977/**978* hdmi_infoframe_pack() - check a HDMI infoframe,979* and write it to binary buffer980* @frame: HDMI infoframe981* @buffer: destination buffer982* @size: size of buffer983*984* Validates that the infoframe is consistent and updates derived fields985* (eg. length) based on other fields, after which it packs the information986* contained in the @frame structure into a binary representation that987* can be written into the corresponding controller registers. This function988* also computes the checksum as required by section 5.3.5 of the HDMI 1.4989* specification.990*991* Returns the number of bytes packed into the binary buffer or a negative992* error code on failure.993*/994ssize_t995hdmi_infoframe_pack(union hdmi_infoframe *frame,996void *buffer, size_t size)997{998ssize_t length;9991000switch (frame->any.type) {1001case HDMI_INFOFRAME_TYPE_AVI:1002length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size);1003break;1004case HDMI_INFOFRAME_TYPE_DRM:1005length = hdmi_drm_infoframe_pack(&frame->drm, buffer, size);1006break;1007case HDMI_INFOFRAME_TYPE_SPD:1008length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);1009break;1010case HDMI_INFOFRAME_TYPE_AUDIO:1011length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size);1012break;1013case HDMI_INFOFRAME_TYPE_VENDOR:1014length = hdmi_vendor_any_infoframe_pack(&frame->vendor,1015buffer, size);1016break;1017default:1018WARN(1, "Bad infoframe type %d\n", frame->any.type);1019length = -EINVAL;1020}10211022return length;1023}1024EXPORT_SYMBOL(hdmi_infoframe_pack);10251026static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type)1027{1028if (type < 0x80 || type > 0x9f)1029return "Invalid";1030switch (type) {1031case HDMI_INFOFRAME_TYPE_VENDOR:1032return "Vendor";1033case HDMI_INFOFRAME_TYPE_AVI:1034return "Auxiliary Video Information (AVI)";1035case HDMI_INFOFRAME_TYPE_SPD:1036return "Source Product Description (SPD)";1037case HDMI_INFOFRAME_TYPE_AUDIO:1038return "Audio";1039case HDMI_INFOFRAME_TYPE_DRM:1040return "Dynamic Range and Mastering";1041}1042return "Reserved";1043}10441045static void hdmi_infoframe_log_header(const char *level,1046struct device *dev,1047const struct hdmi_any_infoframe *frame)1048{1049hdmi_log("HDMI infoframe: %s, version %u, length %u\n",1050hdmi_infoframe_type_get_name(frame->type),1051frame->version, frame->length);1052}10531054static const char *hdmi_colorspace_get_name(enum hdmi_colorspace colorspace)1055{1056switch (colorspace) {1057case HDMI_COLORSPACE_RGB:1058return "RGB";1059case HDMI_COLORSPACE_YUV422:1060return "YCbCr 4:2:2";1061case HDMI_COLORSPACE_YUV444:1062return "YCbCr 4:4:4";1063case HDMI_COLORSPACE_YUV420:1064return "YCbCr 4:2:0";1065case HDMI_COLORSPACE_RESERVED4:1066return "Reserved (4)";1067case HDMI_COLORSPACE_RESERVED5:1068return "Reserved (5)";1069case HDMI_COLORSPACE_RESERVED6:1070return "Reserved (6)";1071case HDMI_COLORSPACE_IDO_DEFINED:1072return "IDO Defined";1073}1074return "Invalid";1075}10761077static const char *hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode)1078{1079switch (scan_mode) {1080case HDMI_SCAN_MODE_NONE:1081return "No Data";1082case HDMI_SCAN_MODE_OVERSCAN:1083return "Overscan";1084case HDMI_SCAN_MODE_UNDERSCAN:1085return "Underscan";1086case HDMI_SCAN_MODE_RESERVED:1087return "Reserved";1088}1089return "Invalid";1090}10911092static const char *hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry)1093{1094switch (colorimetry) {1095case HDMI_COLORIMETRY_NONE:1096return "No Data";1097case HDMI_COLORIMETRY_ITU_601:1098return "ITU601";1099case HDMI_COLORIMETRY_ITU_709:1100return "ITU709";1101case HDMI_COLORIMETRY_EXTENDED:1102return "Extended";1103}1104return "Invalid";1105}11061107static const char *1108hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect)1109{1110switch (picture_aspect) {1111case HDMI_PICTURE_ASPECT_NONE:1112return "No Data";1113case HDMI_PICTURE_ASPECT_4_3:1114return "4:3";1115case HDMI_PICTURE_ASPECT_16_9:1116return "16:9";1117case HDMI_PICTURE_ASPECT_64_27:1118return "64:27";1119case HDMI_PICTURE_ASPECT_256_135:1120return "256:135";1121case HDMI_PICTURE_ASPECT_RESERVED:1122return "Reserved";1123}1124return "Invalid";1125}11261127static const char *1128hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect)1129{1130if (active_aspect < 0 || active_aspect > 0xf)1131return "Invalid";11321133switch (active_aspect) {1134case HDMI_ACTIVE_ASPECT_16_9_TOP:1135return "16:9 Top";1136case HDMI_ACTIVE_ASPECT_14_9_TOP:1137return "14:9 Top";1138case HDMI_ACTIVE_ASPECT_16_9_CENTER:1139return "16:9 Center";1140case HDMI_ACTIVE_ASPECT_PICTURE:1141return "Same as Picture";1142case HDMI_ACTIVE_ASPECT_4_3:1143return "4:3";1144case HDMI_ACTIVE_ASPECT_16_9:1145return "16:9";1146case HDMI_ACTIVE_ASPECT_14_9:1147return "14:9";1148case HDMI_ACTIVE_ASPECT_4_3_SP_14_9:1149return "4:3 SP 14:9";1150case HDMI_ACTIVE_ASPECT_16_9_SP_14_9:1151return "16:9 SP 14:9";1152case HDMI_ACTIVE_ASPECT_16_9_SP_4_3:1153return "16:9 SP 4:3";1154}1155return "Reserved";1156}11571158static const char *1159hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col)1160{1161switch (ext_col) {1162case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:1163return "xvYCC 601";1164case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:1165return "xvYCC 709";1166case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:1167return "sYCC 601";1168case HDMI_EXTENDED_COLORIMETRY_OPYCC_601:1169return "opYCC 601";1170case HDMI_EXTENDED_COLORIMETRY_OPRGB:1171return "opRGB";1172case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:1173return "BT.2020 Constant Luminance";1174case HDMI_EXTENDED_COLORIMETRY_BT2020:1175return "BT.2020";1176case HDMI_EXTENDED_COLORIMETRY_RESERVED:1177return "Reserved";1178}1179return "Invalid";1180}11811182static const char *1183hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange)1184{1185switch (qrange) {1186case HDMI_QUANTIZATION_RANGE_DEFAULT:1187return "Default";1188case HDMI_QUANTIZATION_RANGE_LIMITED:1189return "Limited";1190case HDMI_QUANTIZATION_RANGE_FULL:1191return "Full";1192case HDMI_QUANTIZATION_RANGE_RESERVED:1193return "Reserved";1194}1195return "Invalid";1196}11971198static const char *hdmi_nups_get_name(enum hdmi_nups nups)1199{1200switch (nups) {1201case HDMI_NUPS_UNKNOWN:1202return "Unknown Non-uniform Scaling";1203case HDMI_NUPS_HORIZONTAL:1204return "Horizontally Scaled";1205case HDMI_NUPS_VERTICAL:1206return "Vertically Scaled";1207case HDMI_NUPS_BOTH:1208return "Horizontally and Vertically Scaled";1209}1210return "Invalid";1211}12121213static const char *1214hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange)1215{1216switch (qrange) {1217case HDMI_YCC_QUANTIZATION_RANGE_LIMITED:1218return "Limited";1219case HDMI_YCC_QUANTIZATION_RANGE_FULL:1220return "Full";1221}1222return "Invalid";1223}12241225static const char *1226hdmi_content_type_get_name(enum hdmi_content_type content_type)1227{1228switch (content_type) {1229case HDMI_CONTENT_TYPE_GRAPHICS:1230return "Graphics";1231case HDMI_CONTENT_TYPE_PHOTO:1232return "Photo";1233case HDMI_CONTENT_TYPE_CINEMA:1234return "Cinema";1235case HDMI_CONTENT_TYPE_GAME:1236return "Game";1237}1238return "Invalid";1239}12401241static void hdmi_avi_infoframe_log(const char *level,1242struct device *dev,1243const struct hdmi_avi_infoframe *frame)1244{1245hdmi_infoframe_log_header(level, dev,1246(const struct hdmi_any_infoframe *)frame);12471248hdmi_log(" colorspace: %s\n",1249hdmi_colorspace_get_name(frame->colorspace));1250hdmi_log(" scan mode: %s\n",1251hdmi_scan_mode_get_name(frame->scan_mode));1252hdmi_log(" colorimetry: %s\n",1253hdmi_colorimetry_get_name(frame->colorimetry));1254hdmi_log(" picture aspect: %s\n",1255hdmi_picture_aspect_get_name(frame->picture_aspect));1256hdmi_log(" active aspect: %s\n",1257hdmi_active_aspect_get_name(frame->active_aspect));1258hdmi_log(" itc: %s\n", frame->itc ? "IT Content" : "No Data");1259hdmi_log(" extended colorimetry: %s\n",1260hdmi_extended_colorimetry_get_name(frame->extended_colorimetry));1261hdmi_log(" quantization range: %s\n",1262hdmi_quantization_range_get_name(frame->quantization_range));1263hdmi_log(" nups: %s\n", hdmi_nups_get_name(frame->nups));1264hdmi_log(" video code: %u\n", frame->video_code);1265hdmi_log(" ycc quantization range: %s\n",1266hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range));1267hdmi_log(" hdmi content type: %s\n",1268hdmi_content_type_get_name(frame->content_type));1269hdmi_log(" pixel repeat: %u\n", frame->pixel_repeat);1270hdmi_log(" bar top %u, bottom %u, left %u, right %u\n",1271frame->top_bar, frame->bottom_bar,1272frame->left_bar, frame->right_bar);1273}12741275static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi)1276{1277if (sdi < 0 || sdi > 0xff)1278return "Invalid";1279switch (sdi) {1280case HDMI_SPD_SDI_UNKNOWN:1281return "Unknown";1282case HDMI_SPD_SDI_DSTB:1283return "Digital STB";1284case HDMI_SPD_SDI_DVDP:1285return "DVD Player";1286case HDMI_SPD_SDI_DVHS:1287return "D-VHS";1288case HDMI_SPD_SDI_HDDVR:1289return "HDD Videorecorder";1290case HDMI_SPD_SDI_DVC:1291return "DVC";1292case HDMI_SPD_SDI_DSC:1293return "DSC";1294case HDMI_SPD_SDI_VCD:1295return "Video CD";1296case HDMI_SPD_SDI_GAME:1297return "Game";1298case HDMI_SPD_SDI_PC:1299return "PC General";1300case HDMI_SPD_SDI_BD:1301return "Blu-Ray Disc (BD)";1302case HDMI_SPD_SDI_SACD:1303return "Super Audio CD";1304case HDMI_SPD_SDI_HDDVD:1305return "HD DVD";1306case HDMI_SPD_SDI_PMP:1307return "PMP";1308}1309return "Reserved";1310}13111312static void hdmi_spd_infoframe_log(const char *level,1313struct device *dev,1314const struct hdmi_spd_infoframe *frame)1315{1316u8 buf[17];13171318hdmi_infoframe_log_header(level, dev,1319(const struct hdmi_any_infoframe *)frame);13201321memset(buf, 0, sizeof(buf));13221323strncpy(buf, frame->vendor, 8);1324hdmi_log(" vendor: %s\n", buf);1325strncpy(buf, frame->product, 16);1326hdmi_log(" product: %s\n", buf);1327hdmi_log(" source device information: %s (0x%x)\n",1328hdmi_spd_sdi_get_name(frame->sdi), frame->sdi);1329}13301331static const char *1332hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type)1333{1334switch (coding_type) {1335case HDMI_AUDIO_CODING_TYPE_STREAM:1336return "Refer to Stream Header";1337case HDMI_AUDIO_CODING_TYPE_PCM:1338return "PCM";1339case HDMI_AUDIO_CODING_TYPE_AC3:1340return "AC-3";1341case HDMI_AUDIO_CODING_TYPE_MPEG1:1342return "MPEG1";1343case HDMI_AUDIO_CODING_TYPE_MP3:1344return "MP3";1345case HDMI_AUDIO_CODING_TYPE_MPEG2:1346return "MPEG2";1347case HDMI_AUDIO_CODING_TYPE_AAC_LC:1348return "AAC";1349case HDMI_AUDIO_CODING_TYPE_DTS:1350return "DTS";1351case HDMI_AUDIO_CODING_TYPE_ATRAC:1352return "ATRAC";1353case HDMI_AUDIO_CODING_TYPE_DSD:1354return "One Bit Audio";1355case HDMI_AUDIO_CODING_TYPE_EAC3:1356return "Dolby Digital +";1357case HDMI_AUDIO_CODING_TYPE_DTS_HD:1358return "DTS-HD";1359case HDMI_AUDIO_CODING_TYPE_MLP:1360return "MAT (MLP)";1361case HDMI_AUDIO_CODING_TYPE_DST:1362return "DST";1363case HDMI_AUDIO_CODING_TYPE_WMA_PRO:1364return "WMA PRO";1365case HDMI_AUDIO_CODING_TYPE_CXT:1366return "Refer to CXT";1367}1368return "Invalid";1369}13701371static const char *1372hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size)1373{1374switch (sample_size) {1375case HDMI_AUDIO_SAMPLE_SIZE_STREAM:1376return "Refer to Stream Header";1377case HDMI_AUDIO_SAMPLE_SIZE_16:1378return "16 bit";1379case HDMI_AUDIO_SAMPLE_SIZE_20:1380return "20 bit";1381case HDMI_AUDIO_SAMPLE_SIZE_24:1382return "24 bit";1383}1384return "Invalid";1385}13861387static const char *1388hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq)1389{1390switch (freq) {1391case HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM:1392return "Refer to Stream Header";1393case HDMI_AUDIO_SAMPLE_FREQUENCY_32000:1394return "32 kHz";1395case HDMI_AUDIO_SAMPLE_FREQUENCY_44100:1396return "44.1 kHz (CD)";1397case HDMI_AUDIO_SAMPLE_FREQUENCY_48000:1398return "48 kHz";1399case HDMI_AUDIO_SAMPLE_FREQUENCY_88200:1400return "88.2 kHz";1401case HDMI_AUDIO_SAMPLE_FREQUENCY_96000:1402return "96 kHz";1403case HDMI_AUDIO_SAMPLE_FREQUENCY_176400:1404return "176.4 kHz";1405case HDMI_AUDIO_SAMPLE_FREQUENCY_192000:1406return "192 kHz";1407}1408return "Invalid";1409}14101411static const char *1412hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)1413{1414if (ctx < 0 || ctx > 0x1f)1415return "Invalid";14161417switch (ctx) {1418case HDMI_AUDIO_CODING_TYPE_EXT_CT:1419return "Refer to CT";1420case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC:1421return "HE AAC";1422case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2:1423return "HE AAC v2";1424case HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND:1425return "MPEG SURROUND";1426case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC:1427return "MPEG-4 HE AAC";1428case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2:1429return "MPEG-4 HE AAC v2";1430case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC:1431return "MPEG-4 AAC LC";1432case HDMI_AUDIO_CODING_TYPE_EXT_DRA:1433return "DRA";1434case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND:1435return "MPEG-4 HE AAC + MPEG Surround";1436case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND:1437return "MPEG-4 AAC LC + MPEG Surround";1438}1439return "Reserved";1440}14411442static void hdmi_audio_infoframe_log(const char *level,1443struct device *dev,1444const struct hdmi_audio_infoframe *frame)1445{1446hdmi_infoframe_log_header(level, dev,1447(const struct hdmi_any_infoframe *)frame);14481449if (frame->channels)1450hdmi_log(" channels: %u\n", frame->channels - 1);1451else1452hdmi_log(" channels: Refer to stream header\n");1453hdmi_log(" coding type: %s\n",1454hdmi_audio_coding_type_get_name(frame->coding_type));1455hdmi_log(" sample size: %s\n",1456hdmi_audio_sample_size_get_name(frame->sample_size));1457hdmi_log(" sample frequency: %s\n",1458hdmi_audio_sample_frequency_get_name(frame->sample_frequency));1459hdmi_log(" coding type ext: %s\n",1460hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext));1461hdmi_log(" channel allocation: 0x%x\n",1462frame->channel_allocation);1463hdmi_log(" level shift value: %u dB\n",1464frame->level_shift_value);1465hdmi_log(" downmix inhibit: %s\n",1466frame->downmix_inhibit ? "Yes" : "No");1467}14681469static void hdmi_drm_infoframe_log(const char *level,1470struct device *dev,1471const struct hdmi_drm_infoframe *frame)1472{1473int i;14741475hdmi_infoframe_log_header(level, dev,1476(struct hdmi_any_infoframe *)frame);1477hdmi_log("length: %d\n", frame->length);1478hdmi_log("metadata type: %d\n", frame->metadata_type);1479hdmi_log("eotf: %d\n", frame->eotf);1480for (i = 0; i < 3; i++) {1481hdmi_log("x[%d]: %d\n", i, frame->display_primaries[i].x);1482hdmi_log("y[%d]: %d\n", i, frame->display_primaries[i].y);1483}14841485hdmi_log("white point x: %d\n", frame->white_point.x);1486hdmi_log("white point y: %d\n", frame->white_point.y);14871488hdmi_log("max_display_mastering_luminance: %d\n",1489frame->max_display_mastering_luminance);1490hdmi_log("min_display_mastering_luminance: %d\n",1491frame->min_display_mastering_luminance);14921493hdmi_log("max_cll: %d\n", frame->max_cll);1494hdmi_log("max_fall: %d\n", frame->max_fall);1495}14961497static const char *1498hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)1499{1500if (s3d_struct < 0 || s3d_struct > 0xf)1501return "Invalid";15021503switch (s3d_struct) {1504case HDMI_3D_STRUCTURE_FRAME_PACKING:1505return "Frame Packing";1506case HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE:1507return "Field Alternative";1508case HDMI_3D_STRUCTURE_LINE_ALTERNATIVE:1509return "Line Alternative";1510case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL:1511return "Side-by-side (Full)";1512case HDMI_3D_STRUCTURE_L_DEPTH:1513return "L + Depth";1514case HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH:1515return "L + Depth + Graphics + Graphics-depth";1516case HDMI_3D_STRUCTURE_TOP_AND_BOTTOM:1517return "Top-and-Bottom";1518case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF:1519return "Side-by-side (Half)";1520default:1521break;1522}1523return "Reserved";1524}15251526static void1527hdmi_vendor_any_infoframe_log(const char *level,1528struct device *dev,1529const union hdmi_vendor_any_infoframe *frame)1530{1531const struct hdmi_vendor_infoframe *hvf = &frame->hdmi;15321533hdmi_infoframe_log_header(level, dev,1534(const struct hdmi_any_infoframe *)frame);15351536if (frame->any.oui != HDMI_IEEE_OUI) {1537hdmi_log(" not a HDMI vendor infoframe\n");1538return;1539}1540if (hvf->vic == 0 && hvf->s3d_struct == HDMI_3D_STRUCTURE_INVALID) {1541hdmi_log(" empty frame\n");1542return;1543}15441545if (hvf->vic)1546hdmi_log(" HDMI VIC: %u\n", hvf->vic);1547if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {1548hdmi_log(" 3D structure: %s\n",1549hdmi_3d_structure_get_name(hvf->s3d_struct));1550if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)1551hdmi_log(" 3D extension data: %d\n",1552hvf->s3d_ext_data);1553}1554}15551556/**1557* hdmi_infoframe_log() - log info of HDMI infoframe1558* @level: logging level1559* @dev: device1560* @frame: HDMI infoframe1561*/1562void hdmi_infoframe_log(const char *level,1563struct device *dev,1564const union hdmi_infoframe *frame)1565{1566switch (frame->any.type) {1567case HDMI_INFOFRAME_TYPE_AVI:1568hdmi_avi_infoframe_log(level, dev, &frame->avi);1569break;1570case HDMI_INFOFRAME_TYPE_SPD:1571hdmi_spd_infoframe_log(level, dev, &frame->spd);1572break;1573case HDMI_INFOFRAME_TYPE_AUDIO:1574hdmi_audio_infoframe_log(level, dev, &frame->audio);1575break;1576case HDMI_INFOFRAME_TYPE_VENDOR:1577hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor);1578break;1579case HDMI_INFOFRAME_TYPE_DRM:1580hdmi_drm_infoframe_log(level, dev, &frame->drm);1581break;1582}1583}1584EXPORT_SYMBOL(hdmi_infoframe_log);15851586/**1587* hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe1588* @frame: HDMI AVI infoframe1589* @buffer: source buffer1590* @size: size of buffer1591*1592* Unpacks the information contained in binary @buffer into a structured1593* @frame of the HDMI Auxiliary Video (AVI) information frame.1594* Also verifies the checksum as required by section 5.3.5 of the HDMI 1.41595* specification.1596*1597* Returns 0 on success or a negative error code on failure.1598*/1599static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,1600const void *buffer, size_t size)1601{1602const u8 *ptr = buffer;16031604if (size < HDMI_INFOFRAME_SIZE(AVI))1605return -EINVAL;16061607if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI ||1608ptr[1] != 2 ||1609ptr[2] != HDMI_AVI_INFOFRAME_SIZE)1610return -EINVAL;16111612if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)1613return -EINVAL;16141615hdmi_avi_infoframe_init(frame);16161617ptr += HDMI_INFOFRAME_HEADER_SIZE;16181619frame->colorspace = (ptr[0] >> 5) & 0x3;1620if (ptr[0] & 0x10)1621frame->active_aspect = ptr[1] & 0xf;1622if (ptr[0] & 0x8) {1623frame->top_bar = (ptr[6] << 8) | ptr[5];1624frame->bottom_bar = (ptr[8] << 8) | ptr[7];1625}1626if (ptr[0] & 0x4) {1627frame->left_bar = (ptr[10] << 8) | ptr[9];1628frame->right_bar = (ptr[12] << 8) | ptr[11];1629}1630frame->scan_mode = ptr[0] & 0x3;16311632frame->colorimetry = (ptr[1] >> 6) & 0x3;1633frame->picture_aspect = (ptr[1] >> 4) & 0x3;1634frame->active_aspect = ptr[1] & 0xf;16351636frame->itc = ptr[2] & 0x80 ? true : false;1637frame->extended_colorimetry = (ptr[2] >> 4) & 0x7;1638frame->quantization_range = (ptr[2] >> 2) & 0x3;1639frame->nups = ptr[2] & 0x3;16401641frame->video_code = ptr[3] & 0x7f;1642frame->ycc_quantization_range = (ptr[4] >> 6) & 0x3;1643frame->content_type = (ptr[4] >> 4) & 0x3;16441645frame->pixel_repeat = ptr[4] & 0xf;16461647return 0;1648}16491650/**1651* hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe1652* @frame: HDMI SPD infoframe1653* @buffer: source buffer1654* @size: size of buffer1655*1656* Unpacks the information contained in binary @buffer into a structured1657* @frame of the HDMI Source Product Description (SPD) information frame.1658* Also verifies the checksum as required by section 5.3.5 of the HDMI 1.41659* specification.1660*1661* Returns 0 on success or a negative error code on failure.1662*/1663static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,1664const void *buffer, size_t size)1665{1666const u8 *ptr = buffer;1667int ret;16681669if (size < HDMI_INFOFRAME_SIZE(SPD))1670return -EINVAL;16711672if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD ||1673ptr[1] != 1 ||1674ptr[2] != HDMI_SPD_INFOFRAME_SIZE) {1675return -EINVAL;1676}16771678if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0)1679return -EINVAL;16801681ptr += HDMI_INFOFRAME_HEADER_SIZE;16821683ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8);1684if (ret)1685return ret;16861687frame->sdi = ptr[24];16881689return 0;1690}16911692/**1693* hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe1694* @frame: HDMI Audio infoframe1695* @buffer: source buffer1696* @size: size of buffer1697*1698* Unpacks the information contained in binary @buffer into a structured1699* @frame of the HDMI Audio information frame.1700* Also verifies the checksum as required by section 5.3.5 of the HDMI 1.41701* specification.1702*1703* Returns 0 on success or a negative error code on failure.1704*/1705static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,1706const void *buffer, size_t size)1707{1708const u8 *ptr = buffer;1709int ret;17101711if (size < HDMI_INFOFRAME_SIZE(AUDIO))1712return -EINVAL;17131714if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO ||1715ptr[1] != 1 ||1716ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) {1717return -EINVAL;1718}17191720if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0)1721return -EINVAL;17221723ret = hdmi_audio_infoframe_init(frame);1724if (ret)1725return ret;17261727ptr += HDMI_INFOFRAME_HEADER_SIZE;17281729frame->channels = ptr[0] & 0x7;1730frame->coding_type = (ptr[0] >> 4) & 0xf;1731frame->sample_size = ptr[1] & 0x3;1732frame->sample_frequency = (ptr[1] >> 2) & 0x7;1733frame->coding_type_ext = ptr[2] & 0x1f;1734frame->channel_allocation = ptr[3];1735frame->level_shift_value = (ptr[4] >> 3) & 0xf;1736frame->downmix_inhibit = ptr[4] & 0x80 ? true : false;17371738return 0;1739}17401741/**1742* hdmi_vendor_any_infoframe_unpack() - unpack binary buffer to a HDMI1743* vendor infoframe1744* @frame: HDMI Vendor infoframe1745* @buffer: source buffer1746* @size: size of buffer1747*1748* Unpacks the information contained in binary @buffer into a structured1749* @frame of the HDMI Vendor information frame.1750* Also verifies the checksum as required by section 5.3.5 of the HDMI 1.41751* specification.1752*1753* Returns 0 on success or a negative error code on failure.1754*/1755static int1756hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,1757const void *buffer, size_t size)1758{1759const u8 *ptr = buffer;1760size_t length;1761int ret;1762u8 hdmi_video_format;1763struct hdmi_vendor_infoframe *hvf = &frame->hdmi;17641765if (size < HDMI_INFOFRAME_HEADER_SIZE)1766return -EINVAL;17671768if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||1769ptr[1] != 1 ||1770(ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6))1771return -EINVAL;17721773length = ptr[2];17741775if (size < HDMI_INFOFRAME_HEADER_SIZE + length)1776return -EINVAL;17771778if (hdmi_infoframe_checksum(buffer,1779HDMI_INFOFRAME_HEADER_SIZE + length) != 0)1780return -EINVAL;17811782ptr += HDMI_INFOFRAME_HEADER_SIZE;17831784/* HDMI OUI */1785if ((ptr[0] != 0x03) ||1786(ptr[1] != 0x0c) ||1787(ptr[2] != 0x00))1788return -EINVAL;17891790hdmi_video_format = ptr[3] >> 5;17911792if (hdmi_video_format > 0x2)1793return -EINVAL;17941795ret = hdmi_vendor_infoframe_init(hvf);1796if (ret)1797return ret;17981799hvf->length = length;18001801if (hdmi_video_format == 0x2) {1802if (length != 5 && length != 6)1803return -EINVAL;1804hvf->s3d_struct = ptr[4] >> 4;1805if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) {1806if (length != 6)1807return -EINVAL;1808hvf->s3d_ext_data = ptr[5] >> 4;1809}1810} else if (hdmi_video_format == 0x1) {1811if (length != 5)1812return -EINVAL;1813hvf->vic = ptr[4];1814} else {1815if (length != 4)1816return -EINVAL;1817}18181819return 0;1820}18211822/**1823* hdmi_drm_infoframe_unpack_only() - unpack binary buffer of CTA-861-G DRM1824* infoframe DataBytes to a HDMI DRM1825* infoframe1826* @frame: HDMI DRM infoframe1827* @buffer: source buffer1828* @size: size of buffer1829*1830* Unpacks CTA-861-G DRM infoframe DataBytes contained in the binary @buffer1831* into a structured @frame of the HDMI Dynamic Range and Mastering (DRM)1832* infoframe.1833*1834* Returns 0 on success or a negative error code on failure.1835*/1836int hdmi_drm_infoframe_unpack_only(struct hdmi_drm_infoframe *frame,1837const void *buffer, size_t size)1838{1839const u8 *ptr = buffer;1840const u8 *temp;1841u8 x_lsb, x_msb;1842u8 y_lsb, y_msb;1843int ret;1844int i;18451846if (size < HDMI_DRM_INFOFRAME_SIZE)1847return -EINVAL;18481849ret = hdmi_drm_infoframe_init(frame);1850if (ret)1851return ret;18521853frame->eotf = ptr[0] & 0x7;1854frame->metadata_type = ptr[1] & 0x7;18551856temp = ptr + 2;1857for (i = 0; i < 3; i++) {1858x_lsb = *temp++;1859x_msb = *temp++;1860frame->display_primaries[i].x = (x_msb << 8) | x_lsb;1861y_lsb = *temp++;1862y_msb = *temp++;1863frame->display_primaries[i].y = (y_msb << 8) | y_lsb;1864}18651866frame->white_point.x = (ptr[15] << 8) | ptr[14];1867frame->white_point.y = (ptr[17] << 8) | ptr[16];18681869frame->max_display_mastering_luminance = (ptr[19] << 8) | ptr[18];1870frame->min_display_mastering_luminance = (ptr[21] << 8) | ptr[20];1871frame->max_cll = (ptr[23] << 8) | ptr[22];1872frame->max_fall = (ptr[25] << 8) | ptr[24];18731874return 0;1875}1876EXPORT_SYMBOL(hdmi_drm_infoframe_unpack_only);18771878/**1879* hdmi_drm_infoframe_unpack() - unpack binary buffer to a HDMI DRM infoframe1880* @frame: HDMI DRM infoframe1881* @buffer: source buffer1882* @size: size of buffer1883*1884* Unpacks the CTA-861-G DRM infoframe contained in the binary @buffer into1885* a structured @frame of the HDMI Dynamic Range and Mastering (DRM)1886* infoframe. It also verifies the checksum as required by section 5.3.5 of1887* the HDMI 1.4 specification.1888*1889* Returns 0 on success or a negative error code on failure.1890*/1891static int hdmi_drm_infoframe_unpack(struct hdmi_drm_infoframe *frame,1892const void *buffer, size_t size)1893{1894const u8 *ptr = buffer;1895int ret;18961897if (size < HDMI_INFOFRAME_SIZE(DRM))1898return -EINVAL;18991900if (ptr[0] != HDMI_INFOFRAME_TYPE_DRM ||1901ptr[1] != 1 ||1902ptr[2] != HDMI_DRM_INFOFRAME_SIZE)1903return -EINVAL;19041905if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(DRM)) != 0)1906return -EINVAL;19071908ret = hdmi_drm_infoframe_unpack_only(frame, ptr + HDMI_INFOFRAME_HEADER_SIZE,1909size - HDMI_INFOFRAME_HEADER_SIZE);1910return ret;1911}19121913/**1914* hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe1915* @frame: HDMI infoframe1916* @buffer: source buffer1917* @size: size of buffer1918*1919* Unpacks the information contained in binary buffer @buffer into a structured1920* @frame of a HDMI infoframe.1921* Also verifies the checksum as required by section 5.3.5 of the HDMI 1.41922* specification.1923*1924* Returns 0 on success or a negative error code on failure.1925*/1926int hdmi_infoframe_unpack(union hdmi_infoframe *frame,1927const void *buffer, size_t size)1928{1929int ret;1930const u8 *ptr = buffer;19311932if (size < HDMI_INFOFRAME_HEADER_SIZE)1933return -EINVAL;19341935switch (ptr[0]) {1936case HDMI_INFOFRAME_TYPE_AVI:1937ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer, size);1938break;1939case HDMI_INFOFRAME_TYPE_DRM:1940ret = hdmi_drm_infoframe_unpack(&frame->drm, buffer, size);1941break;1942case HDMI_INFOFRAME_TYPE_SPD:1943ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer, size);1944break;1945case HDMI_INFOFRAME_TYPE_AUDIO:1946ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer, size);1947break;1948case HDMI_INFOFRAME_TYPE_VENDOR:1949ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer, size);1950break;1951default:1952ret = -EINVAL;1953break;1954}19551956return ret;1957}1958EXPORT_SYMBOL(hdmi_infoframe_unpack);195919601961