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