LCOV - code coverage report
Current view: top level - dev/pci/drm - linux_hdmi.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 159 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: linux_hdmi.c,v 1.1 2015/09/23 23:12:11 kettenis Exp $ */
       2             : /*
       3             :  * Copyright (C) 2012 Avionic Design GmbH
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining a
       6             :  * copy of this software and associated documentation files (the "Software"),
       7             :  * to deal in the Software without restriction, including without limitation
       8             :  * the rights to use, copy, modify, merge, publish, distribute, sub license,
       9             :  * and/or sell copies of the Software, and to permit persons to whom the
      10             :  * Software is furnished to do so, subject to the following conditions:
      11             :  *
      12             :  * The above copyright notice and this permission notice (including the
      13             :  * next paragraph) shall be included in all copies or substantial portions
      14             :  * of the Software.
      15             :  *
      16             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      17             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      18             :  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
      19             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      20             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      21             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      22             :  * DEALINGS IN THE SOFTWARE.
      23             :  */
      24             : 
      25             : #include "drmP.h"
      26             : #include "linux_hdmi.h"
      27             : 
      28           0 : static void hdmi_infoframe_checksum(void *buffer, size_t size)
      29             : {
      30             :         u8 *ptr = buffer;
      31             :         u8 csum = 0;
      32             :         size_t i;
      33             : 
      34             :         /* compute checksum */
      35           0 :         for (i = 0; i < size; i++)
      36           0 :                 csum += ptr[i];
      37             : 
      38           0 :         ptr[3] = 256 - csum;
      39           0 : }
      40             : 
      41             : /**
      42             :  * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
      43             :  * @frame: HDMI AVI infoframe
      44             :  *
      45             :  * Returns 0 on success or a negative error code on failure.
      46             :  */
      47           0 : int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
      48             : {
      49           0 :         memset(frame, 0, sizeof(*frame));
      50             : 
      51           0 :         frame->type = HDMI_INFOFRAME_TYPE_AVI;
      52           0 :         frame->version = 2;
      53           0 :         frame->length = HDMI_AVI_INFOFRAME_SIZE;
      54             : 
      55           0 :         return 0;
      56             : }
      57             : EXPORT_SYMBOL(hdmi_avi_infoframe_init);
      58             : 
      59             : /**
      60             :  * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
      61             :  * @frame: HDMI AVI infoframe
      62             :  * @buffer: destination buffer
      63             :  * @size: size of buffer
      64             :  *
      65             :  * Packs the information contained in the @frame structure into a binary
      66             :  * representation that can be written into the corresponding controller
      67             :  * registers. Also computes the checksum as required by section 5.3.5 of
      68             :  * the HDMI 1.4 specification.
      69             :  *
      70             :  * Returns the number of bytes packed into the binary buffer or a negative
      71             :  * error code on failure.
      72             :  */
      73           0 : ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
      74             :                                 size_t size)
      75             : {
      76             :         u8 *ptr = buffer;
      77             :         size_t length;
      78             : 
      79           0 :         length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
      80             : 
      81           0 :         if (size < length)
      82           0 :                 return -ENOSPC;
      83             : 
      84           0 :         memset(buffer, 0, size);
      85             : 
      86           0 :         ptr[0] = frame->type;
      87           0 :         ptr[1] = frame->version;
      88           0 :         ptr[2] = frame->length;
      89           0 :         ptr[3] = 0; /* checksum */
      90             : 
      91             :         /* start infoframe payload */
      92           0 :         ptr += HDMI_INFOFRAME_HEADER_SIZE;
      93             : 
      94           0 :         ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
      95             : 
      96             :         /*
      97             :          * Data byte 1, bit 4 has to be set if we provide the active format
      98             :          * aspect ratio
      99             :          */
     100           0 :         if (frame->active_aspect & 0xf)
     101           0 :                 ptr[0] |= BIT(4);
     102             : 
     103             :         /* Bit 3 and 2 indicate if we transmit horizontal/vertical bar data */
     104           0 :         if (frame->top_bar || frame->bottom_bar)
     105           0 :                 ptr[0] |= BIT(3);
     106             : 
     107           0 :         if (frame->left_bar || frame->right_bar)
     108           0 :                 ptr[0] |= BIT(2);
     109             : 
     110           0 :         ptr[1] = ((frame->colorimetry & 0x3) << 6) |
     111           0 :                  ((frame->picture_aspect & 0x3) << 4) |
     112           0 :                  (frame->active_aspect & 0xf);
     113             : 
     114           0 :         ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |
     115           0 :                  ((frame->quantization_range & 0x3) << 2) |
     116           0 :                  (frame->nups & 0x3);
     117             : 
     118           0 :         if (frame->itc)
     119           0 :                 ptr[2] |= BIT(7);
     120             : 
     121           0 :         ptr[3] = frame->video_code & 0x7f;
     122             : 
     123           0 :         ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |
     124           0 :                  ((frame->content_type & 0x3) << 4) |
     125           0 :                  (frame->pixel_repeat & 0xf);
     126             : 
     127           0 :         ptr[5] = frame->top_bar & 0xff;
     128           0 :         ptr[6] = (frame->top_bar >> 8) & 0xff;
     129           0 :         ptr[7] = frame->bottom_bar & 0xff;
     130           0 :         ptr[8] = (frame->bottom_bar >> 8) & 0xff;
     131           0 :         ptr[9] = frame->left_bar & 0xff;
     132           0 :         ptr[10] = (frame->left_bar >> 8) & 0xff;
     133           0 :         ptr[11] = frame->right_bar & 0xff;
     134           0 :         ptr[12] = (frame->right_bar >> 8) & 0xff;
     135             : 
     136           0 :         hdmi_infoframe_checksum(buffer, length);
     137             : 
     138           0 :         return length;
     139           0 : }
     140             : EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
     141             : 
     142             : /**
     143             :  * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe
     144             :  * @frame: HDMI SPD infoframe
     145             :  * @vendor: vendor string
     146             :  * @product: product string
     147             :  *
     148             :  * Returns 0 on success or a negative error code on failure.
     149             :  */
     150           0 : int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
     151             :                             const char *vendor, const char *product)
     152             : {
     153           0 :         memset(frame, 0, sizeof(*frame));
     154             : 
     155           0 :         frame->type = HDMI_INFOFRAME_TYPE_SPD;
     156           0 :         frame->version = 1;
     157           0 :         frame->length = HDMI_SPD_INFOFRAME_SIZE;
     158             : 
     159           0 :         strncpy(frame->vendor, vendor, sizeof(frame->vendor));
     160           0 :         strncpy(frame->product, product, sizeof(frame->product));
     161             : 
     162           0 :         return 0;
     163             : }
     164             : EXPORT_SYMBOL(hdmi_spd_infoframe_init);
     165             : 
     166             : /**
     167             :  * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer
     168             :  * @frame: HDMI SPD infoframe
     169             :  * @buffer: destination buffer
     170             :  * @size: size of buffer
     171             :  *
     172             :  * Packs the information contained in the @frame structure into a binary
     173             :  * representation that can be written into the corresponding controller
     174             :  * registers. Also computes the checksum as required by section 5.3.5 of
     175             :  * the HDMI 1.4 specification.
     176             :  *
     177             :  * Returns the number of bytes packed into the binary buffer or a negative
     178             :  * error code on failure.
     179             :  */
     180           0 : ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
     181             :                                 size_t size)
     182             : {
     183             :         u8 *ptr = buffer;
     184             :         size_t length;
     185             : 
     186           0 :         length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
     187             : 
     188           0 :         if (size < length)
     189           0 :                 return -ENOSPC;
     190             : 
     191           0 :         memset(buffer, 0, size);
     192             : 
     193           0 :         ptr[0] = frame->type;
     194           0 :         ptr[1] = frame->version;
     195           0 :         ptr[2] = frame->length;
     196           0 :         ptr[3] = 0; /* checksum */
     197             : 
     198             :         /* start infoframe payload */
     199           0 :         ptr += HDMI_INFOFRAME_HEADER_SIZE;
     200             : 
     201           0 :         memcpy(ptr, frame->vendor, sizeof(frame->vendor));
     202           0 :         memcpy(ptr + 8, frame->product, sizeof(frame->product));
     203             : 
     204           0 :         ptr[24] = frame->sdi;
     205             : 
     206           0 :         hdmi_infoframe_checksum(buffer, length);
     207             : 
     208           0 :         return length;
     209           0 : }
     210             : EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
     211             : 
     212             : /**
     213             :  * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe
     214             :  * @frame: HDMI audio infoframe
     215             :  *
     216             :  * Returns 0 on success or a negative error code on failure.
     217             :  */
     218           0 : int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
     219             : {
     220           0 :         memset(frame, 0, sizeof(*frame));
     221             : 
     222           0 :         frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
     223           0 :         frame->version = 1;
     224           0 :         frame->length = HDMI_AUDIO_INFOFRAME_SIZE;
     225             : 
     226           0 :         return 0;
     227             : }
     228             : EXPORT_SYMBOL(hdmi_audio_infoframe_init);
     229             : 
     230             : /**
     231             :  * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
     232             :  * @frame: HDMI audio infoframe
     233             :  * @buffer: destination buffer
     234             :  * @size: size of buffer
     235             :  *
     236             :  * Packs the information contained in the @frame structure into a binary
     237             :  * representation that can be written into the corresponding controller
     238             :  * registers. Also computes the checksum as required by section 5.3.5 of
     239             :  * the HDMI 1.4 specification.
     240             :  *
     241             :  * Returns the number of bytes packed into the binary buffer or a negative
     242             :  * error code on failure.
     243             :  */
     244           0 : ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
     245             :                                   void *buffer, size_t size)
     246             : {
     247             :         unsigned char channels;
     248             :         u8 *ptr = buffer;
     249             :         size_t length;
     250             : 
     251           0 :         length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
     252             : 
     253           0 :         if (size < length)
     254           0 :                 return -ENOSPC;
     255             : 
     256           0 :         memset(buffer, 0, size);
     257             : 
     258           0 :         if (frame->channels >= 2)
     259           0 :                 channels = frame->channels - 1;
     260             :         else
     261             :                 channels = 0;
     262             : 
     263           0 :         ptr[0] = frame->type;
     264           0 :         ptr[1] = frame->version;
     265           0 :         ptr[2] = frame->length;
     266           0 :         ptr[3] = 0; /* checksum */
     267             : 
     268             :         /* start infoframe payload */
     269           0 :         ptr += HDMI_INFOFRAME_HEADER_SIZE;
     270             : 
     271           0 :         ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
     272           0 :         ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
     273           0 :                  (frame->sample_size & 0x3);
     274           0 :         ptr[2] = frame->coding_type_ext & 0x1f;
     275           0 :         ptr[3] = frame->channel_allocation;
     276           0 :         ptr[4] = (frame->level_shift_value & 0xf) << 3;
     277             : 
     278           0 :         if (frame->downmix_inhibit)
     279           0 :                 ptr[4] |= BIT(7);
     280             : 
     281           0 :         hdmi_infoframe_checksum(buffer, length);
     282             : 
     283           0 :         return length;
     284           0 : }
     285             : EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
     286             : 
     287             : /**
     288             :  * hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe
     289             :  * @frame: HDMI vendor infoframe
     290             :  *
     291             :  * Returns 0 on success or a negative error code on failure.
     292             :  */
     293           0 : int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)
     294             : {
     295           0 :         memset(frame, 0, sizeof(*frame));
     296             : 
     297           0 :         frame->type = HDMI_INFOFRAME_TYPE_VENDOR;
     298           0 :         frame->version = 1;
     299             : 
     300           0 :         frame->oui = HDMI_IEEE_OUI;
     301             : 
     302             :         /*
     303             :          * 0 is a valid value for s3d_struct, so we use a special "not set"
     304             :          * value
     305             :          */
     306           0 :         frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID;
     307             : 
     308           0 :         return 0;
     309             : }
     310             : EXPORT_SYMBOL(hdmi_vendor_infoframe_init);
     311             : 
     312             : /**
     313             :  * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary buffer
     314             :  * @frame: HDMI infoframe
     315             :  * @buffer: destination buffer
     316             :  * @size: size of buffer
     317             :  *
     318             :  * Packs the information contained in the @frame structure into a binary
     319             :  * representation that can be written into the corresponding controller
     320             :  * registers. Also computes the checksum as required by section 5.3.5 of
     321             :  * the HDMI 1.4 specification.
     322             :  *
     323             :  * Returns the number of bytes packed into the binary buffer or a negative
     324             :  * error code on failure.
     325             :  */
     326           0 : ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
     327             :                                  void *buffer, size_t size)
     328             : {
     329             :         u8 *ptr = buffer;
     330             :         size_t length;
     331             : 
     332             :         /* empty info frame */
     333           0 :         if (frame->vic == 0 && frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID)
     334           0 :                 return -EINVAL;
     335             : 
     336             :         /* only one of those can be supplied */
     337           0 :         if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
     338           0 :                 return -EINVAL;
     339             : 
     340             :         /* for side by side (half) we also need to provide 3D_Ext_Data */
     341           0 :         if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
     342           0 :                 frame->length = 6;
     343             :         else
     344           0 :                 frame->length = 5;
     345             : 
     346           0 :         length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
     347             : 
     348           0 :         if (size < length)
     349           0 :                 return -ENOSPC;
     350             : 
     351           0 :         memset(buffer, 0, size);
     352             : 
     353           0 :         ptr[0] = frame->type;
     354           0 :         ptr[1] = frame->version;
     355           0 :         ptr[2] = frame->length;
     356           0 :         ptr[3] = 0; /* checksum */
     357             : 
     358             :         /* HDMI OUI */
     359           0 :         ptr[4] = 0x03;
     360           0 :         ptr[5] = 0x0c;
     361           0 :         ptr[6] = 0x00;
     362             : 
     363           0 :         if (frame->vic) {
     364           0 :                 ptr[7] = 0x1 << 5;        /* video format */
     365           0 :                 ptr[8] = frame->vic;
     366           0 :         } else {
     367           0 :                 ptr[7] = 0x2 << 5;        /* video format */
     368           0 :                 ptr[8] = (frame->s3d_struct & 0xf) << 4;
     369           0 :                 if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
     370           0 :                         ptr[9] = (frame->s3d_ext_data & 0xf) << 4;
     371             :         }
     372             : 
     373           0 :         hdmi_infoframe_checksum(buffer, length);
     374             : 
     375           0 :         return length;
     376           0 : }
     377             : EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
     378             : 
     379             : /*
     380             :  * hdmi_vendor_any_infoframe_pack() - write a vendor infoframe to binary buffer
     381             :  */
     382             : static ssize_t
     383           0 : hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame,
     384             :                            void *buffer, size_t size)
     385             : {
     386             :         /* we only know about HDMI vendor infoframes */
     387           0 :         if (frame->any.oui != HDMI_IEEE_OUI)
     388           0 :                 return -EINVAL;
     389             : 
     390           0 :         return hdmi_vendor_infoframe_pack(&frame->hdmi, buffer, size);
     391           0 : }
     392             : 
     393             : /**
     394             :  * hdmi_infoframe_pack() - write a HDMI infoframe to binary buffer
     395             :  * @frame: HDMI infoframe
     396             :  * @buffer: destination buffer
     397             :  * @size: size of buffer
     398             :  *
     399             :  * Packs the information contained in the @frame structure into a binary
     400             :  * representation that can be written into the corresponding controller
     401             :  * registers. Also computes the checksum as required by section 5.3.5 of
     402             :  * the HDMI 1.4 specification.
     403             :  *
     404             :  * Returns the number of bytes packed into the binary buffer or a negative
     405             :  * error code on failure.
     406             :  */
     407             : ssize_t
     408           0 : hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size)
     409             : {
     410             :         ssize_t length;
     411             : 
     412           0 :         switch (frame->any.type) {
     413             :         case HDMI_INFOFRAME_TYPE_AVI:
     414           0 :                 length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size);
     415           0 :                 break;
     416             :         case HDMI_INFOFRAME_TYPE_SPD:
     417           0 :                 length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);
     418           0 :                 break;
     419             :         case HDMI_INFOFRAME_TYPE_AUDIO:
     420           0 :                 length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size);
     421           0 :                 break;
     422             :         case HDMI_INFOFRAME_TYPE_VENDOR:
     423           0 :                 length = hdmi_vendor_any_infoframe_pack(&frame->vendor,
     424             :                                                         buffer, size);
     425           0 :                 break;
     426             :         default:
     427           0 :                 WARN(1, "Bad infoframe type %d\n", frame->any.type);
     428             :                 length = -EINVAL;
     429           0 :         }
     430             : 
     431           0 :         return length;
     432             : }
     433             : EXPORT_SYMBOL(hdmi_infoframe_pack);

Generated by: LCOV version 1.13