linux/drivers/video/hdmi.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Avionic Design GmbH
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * 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 the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the
  12 * next paragraph) shall be included in all copies or substantial portions
  13 * of the Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21 * DEALINGS IN THE SOFTWARE.
  22 */
  23
  24#include <linux/bitops.h>
  25#include <linux/errno.h>
  26#include <linux/export.h>
  27#include <linux/hdmi.h>
  28#include <linux/string.h>
  29
  30static void hdmi_infoframe_checksum(void *buffer, size_t size)
  31{
  32        u8 *ptr = buffer;
  33        u8 csum = 0;
  34        size_t i;
  35
  36        /* compute checksum */
  37        for (i = 0; i < size; i++)
  38                csum += ptr[i];
  39
  40        ptr[3] = 256 - csum;
  41}
  42
  43/**
  44 * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
  45 * @frame: HDMI AVI infoframe
  46 *
  47 * Returns 0 on success or a negative error code on failure.
  48 */
  49int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
  50{
  51        memset(frame, 0, sizeof(*frame));
  52
  53        frame->type = HDMI_INFOFRAME_TYPE_AVI;
  54        frame->version = 2;
  55        frame->length = 13;
  56
  57        return 0;
  58}
  59EXPORT_SYMBOL(hdmi_avi_infoframe_init);
  60
  61/**
  62 * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
  63 * @frame: HDMI AVI infoframe
  64 * @buffer: destination buffer
  65 * @size: size of buffer
  66 *
  67 * Packs the information contained in the @frame structure into a binary
  68 * representation that can be written into the corresponding controller
  69 * registers. Also computes the checksum as required by section 5.3.5 of
  70 * the HDMI 1.4 specification.
  71 *
  72 * Returns the number of bytes packed into the binary buffer or a negative
  73 * error code on failure.
  74 */
  75ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
  76                                size_t size)
  77{
  78        u8 *ptr = buffer;
  79        size_t length;
  80
  81        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
  82
  83        if (size < length)
  84                return -ENOSPC;
  85
  86        memset(buffer, 0, length);
  87
  88        ptr[0] = frame->type;
  89        ptr[1] = frame->version;
  90        ptr[2] = frame->length;
  91        ptr[3] = 0; /* checksum */
  92
  93        /* start infoframe payload */
  94        ptr += HDMI_INFOFRAME_HEADER_SIZE;
  95
  96        ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
  97
  98        if (frame->active_info_valid)
  99                ptr[0] |= BIT(4);
 100
 101        if (frame->horizontal_bar_valid)
 102                ptr[0] |= BIT(3);
 103
 104        if (frame->vertical_bar_valid)
 105                ptr[0] |= BIT(2);
 106
 107        ptr[1] = ((frame->colorimetry & 0x3) << 6) |
 108                 ((frame->picture_aspect & 0x3) << 4) |
 109                 (frame->active_aspect & 0xf);
 110
 111        ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |
 112                 ((frame->quantization_range & 0x3) << 2) |
 113                 (frame->nups & 0x3);
 114
 115        if (frame->itc)
 116                ptr[2] |= BIT(7);
 117
 118        ptr[3] = frame->video_code & 0x7f;
 119
 120        ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |
 121                 ((frame->content_type & 0x3) << 4) |
 122                 (frame->pixel_repeat & 0xf);
 123
 124        ptr[5] = frame->top_bar & 0xff;
 125        ptr[6] = (frame->top_bar >> 8) & 0xff;
 126        ptr[7] = frame->bottom_bar & 0xff;
 127        ptr[8] = (frame->bottom_bar >> 8) & 0xff;
 128        ptr[9] = frame->left_bar & 0xff;
 129        ptr[10] = (frame->left_bar >> 8) & 0xff;
 130        ptr[11] = frame->right_bar & 0xff;
 131        ptr[12] = (frame->right_bar >> 8) & 0xff;
 132
 133        hdmi_infoframe_checksum(buffer, length);
 134
 135        return length;
 136}
 137EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
 138
 139/**
 140 * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe
 141 * @frame: HDMI SPD infoframe
 142 * @vendor: vendor string
 143 * @product: product string
 144 *
 145 * Returns 0 on success or a negative error code on failure.
 146 */
 147int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
 148                            const char *vendor, const char *product)
 149{
 150        memset(frame, 0, sizeof(*frame));
 151
 152        frame->type = HDMI_INFOFRAME_TYPE_SPD;
 153        frame->version = 1;
 154        frame->length = 25;
 155
 156        strncpy(frame->vendor, vendor, sizeof(frame->vendor));
 157        strncpy(frame->product, product, sizeof(frame->product));
 158
 159        return 0;
 160}
 161EXPORT_SYMBOL(hdmi_spd_infoframe_init);
 162
 163/**
 164 * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer
 165 * @frame: HDMI SPD infoframe
 166 * @buffer: destination buffer
 167 * @size: size of buffer
 168 *
 169 * Packs the information contained in the @frame structure into a binary
 170 * representation that can be written into the corresponding controller
 171 * registers. Also computes the checksum as required by section 5.3.5 of
 172 * the HDMI 1.4 specification.
 173 *
 174 * Returns the number of bytes packed into the binary buffer or a negative
 175 * error code on failure.
 176 */
 177ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
 178                                size_t size)
 179{
 180        u8 *ptr = buffer;
 181        size_t length;
 182
 183        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 184
 185        if (size < length)
 186                return -ENOSPC;
 187
 188        memset(buffer, 0, length);
 189
 190        ptr[0] = frame->type;
 191        ptr[1] = frame->version;
 192        ptr[2] = frame->length;
 193        ptr[3] = 0; /* checksum */
 194
 195        /* start infoframe payload */
 196        ptr += HDMI_INFOFRAME_HEADER_SIZE;
 197
 198        memcpy(ptr, frame->vendor, sizeof(frame->vendor));
 199        memcpy(ptr + 8, frame->product, sizeof(frame->product));
 200
 201        ptr[24] = frame->sdi;
 202
 203        hdmi_infoframe_checksum(buffer, length);
 204
 205        return length;
 206}
 207EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
 208
 209/**
 210 * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe
 211 * @frame: HDMI audio infoframe
 212 *
 213 * Returns 0 on success or a negative error code on failure.
 214 */
 215int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
 216{
 217        memset(frame, 0, sizeof(*frame));
 218
 219        frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
 220        frame->version = 1;
 221        frame->length = 10;
 222
 223        return 0;
 224}
 225EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 226
 227/**
 228 * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
 229 * @frame: HDMI audio infoframe
 230 * @buffer: destination buffer
 231 * @size: size of buffer
 232 *
 233 * Packs the information contained in the @frame structure into a binary
 234 * representation that can be written into the corresponding controller
 235 * registers. Also computes the checksum as required by section 5.3.5 of
 236 * the HDMI 1.4 specification.
 237 *
 238 * Returns the number of bytes packed into the binary buffer or a negative
 239 * error code on failure.
 240 */
 241ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
 242                                  void *buffer, size_t size)
 243{
 244        unsigned char channels;
 245        u8 *ptr = buffer;
 246        size_t length;
 247
 248        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 249
 250        if (size < length)
 251                return -ENOSPC;
 252
 253        memset(buffer, 0, length);
 254
 255        if (frame->channels >= 2)
 256                channels = frame->channels - 1;
 257        else
 258                channels = 0;
 259
 260        ptr[0] = frame->type;
 261        ptr[1] = frame->version;
 262        ptr[2] = frame->length;
 263        ptr[3] = 0; /* checksum */
 264
 265        /* start infoframe payload */
 266        ptr += HDMI_INFOFRAME_HEADER_SIZE;
 267
 268        ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
 269        ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
 270                 (frame->sample_size & 0x3);
 271        ptr[2] = frame->coding_type_ext & 0x1f;
 272        ptr[3] = frame->channel_allocation;
 273        ptr[4] = (frame->level_shift_value & 0xf) << 3;
 274
 275        if (frame->downmix_inhibit)
 276                ptr[4] |= BIT(7);
 277
 278        hdmi_infoframe_checksum(buffer, length);
 279
 280        return length;
 281}
 282EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
 283
 284/**
 285 * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary
 286 *                                buffer
 287 * @frame: HDMI vendor infoframe
 288 * @buffer: destination buffer
 289 * @size: size of buffer
 290 *
 291 * Packs the information contained in the @frame structure into a binary
 292 * representation that can be written into the corresponding controller
 293 * registers. Also computes the checksum as required by section 5.3.5 of
 294 * the HDMI 1.4 specification.
 295 *
 296 * Returns the number of bytes packed into the binary buffer or a negative
 297 * error code on failure.
 298 */
 299ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
 300                                   void *buffer, size_t size)
 301{
 302        u8 *ptr = buffer;
 303        size_t length;
 304
 305        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 306
 307        if (size < length)
 308                return -ENOSPC;
 309
 310        memset(buffer, 0, length);
 311
 312        ptr[0] = frame->type;
 313        ptr[1] = frame->version;
 314        ptr[2] = frame->length;
 315        ptr[3] = 0; /* checksum */
 316
 317        memcpy(&ptr[HDMI_INFOFRAME_HEADER_SIZE], frame->data, frame->length);
 318
 319        hdmi_infoframe_checksum(buffer, length);
 320
 321        return length;
 322}
 323EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
 324
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.