1/* $Id: hdafg_dd.c,v 1.1 2011/02/12 15:15:34 jmcneill Exp $ */
2
3/*
4 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. The name of the author may not be used to endorse or promote products
13 *    derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28/*
29 * HD audio Digital Display support
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$Id: hdafg_dd.c,v 1.1 2011/02/12 15:15:34 jmcneill Exp $");
34
35#include <sys/types.h>
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/device.h>
40#include <sys/conf.h>
41#include <sys/bus.h>
42
43#include "hdaudioreg.h"
44#include "hdaudiovar.h"
45#include "hdaudio_pci.h"
46#include "hdafg_dd.h"
47
48int
49hdafg_dd_parse_info(uint8_t *data, size_t datalen, struct hdafg_dd_info *hdi)
50{
51	struct eld_baseline_block *block = &hdi->eld;
52	unsigned int i;
53
54	printf("hdafg_dd_parse_info: datalen=%u\n", (unsigned int)datalen);
55
56	memset(hdi, 0, sizeof(*hdi));
57
58	if (datalen < sizeof(block->header)) {
59		printf(" no room for header\n");
60		return EINVAL;
61	}
62
63	memcpy(&block->header, data, sizeof(block->header));
64	data += sizeof(block->header);
65	datalen -= sizeof(block->header);
66
67	if (datalen < block->header.baseline_eld_len * 4 ||
68	    datalen < sizeof(*block) - sizeof(block->header)) {
69		printf(" ack!\n");
70		return EINVAL;
71	}
72
73	datalen = block->header.baseline_eld_len * 4;
74
75	memcpy(&block->flags[0], data, sizeof(*block) - sizeof(block->header));
76	data += sizeof(*block) - sizeof(block->header);
77	datalen -= sizeof(*block) - sizeof(block->header);
78
79	if (datalen < ELD_MNL(block)) {
80		printf(" MNL=%u\n", ELD_MNL(block));
81		return EINVAL;
82	}
83
84	memcpy(hdi->monitor, data, ELD_MNL(block));
85	data += ELD_MNL(block);
86	datalen -= ELD_MNL(block);
87
88	if (datalen != ELD_SAD_COUNT(block) * sizeof(hdi->sad[0])) {
89		printf(" datalen %u sadcount %u sizeof sad %u\n",
90		    (unsigned int)datalen,
91		    ELD_SAD_COUNT(block),
92		    (unsigned int)sizeof(hdi->sad[0]));
93		return EINVAL;
94	}
95	hdi->nsad = ELD_SAD_COUNT(block);
96	for (i = 0; i < hdi->nsad; i++) {
97		memcpy(&hdi->sad[i], data, sizeof(hdi->sad[i]));
98		data += sizeof(hdi->sad[i]);
99		datalen -= sizeof(hdi->sad[i]);
100	}
101
102	printf("datalen = %u\n", (unsigned int)datalen);
103	KASSERT(datalen == 0);
104
105	return 0;
106}
107
108void
109hdafg_dd_hdmi_ai_cksum(struct hdmi_audio_infoframe *hdmi)
110{
111	uint8_t *dip = (uint8_t *)hdmi, c = 0;
112	int i;
113
114	hdmi->checksum = 0;
115	for (i = 0; i < sizeof(*hdmi); i++)
116		c += dip[i];
117	hdmi->checksum = -c;
118}
119