Subversion Repositories Kolibri OS

Rev

Rev 5056 | Details | Compare with Previous | Last modification | View Log | RSS feed

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