aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c82
1 files changed, 73 insertions, 9 deletions
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index ff04ed2bb7a3..34e33a12984d 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -51,9 +51,18 @@
51#define HDMI_SW_DI_2_PKT_WORD4 0x0614 51#define HDMI_SW_DI_2_PKT_WORD4 0x0614
52#define HDMI_SW_DI_2_PKT_WORD5 0x0618 52#define HDMI_SW_DI_2_PKT_WORD5 0x0618
53#define HDMI_SW_DI_2_PKT_WORD6 0x061C 53#define HDMI_SW_DI_2_PKT_WORD6 0x061C
54#define HDMI_SW_DI_3_HEAD_WORD 0x0620
55#define HDMI_SW_DI_3_PKT_WORD0 0x0624
56#define HDMI_SW_DI_3_PKT_WORD1 0x0628
57#define HDMI_SW_DI_3_PKT_WORD2 0x062C
58#define HDMI_SW_DI_3_PKT_WORD3 0x0630
59#define HDMI_SW_DI_3_PKT_WORD4 0x0634
60#define HDMI_SW_DI_3_PKT_WORD5 0x0638
61#define HDMI_SW_DI_3_PKT_WORD6 0x063C
54 62
55#define HDMI_IFRAME_SLOT_AVI 1 63#define HDMI_IFRAME_SLOT_AVI 1
56#define HDMI_IFRAME_SLOT_AUDIO 2 64#define HDMI_IFRAME_SLOT_AUDIO 2
65#define HDMI_IFRAME_SLOT_VENDOR 3
57 66
58#define XCAT(prefix, x, suffix) prefix ## x ## suffix 67#define XCAT(prefix, x, suffix) prefix ## x ## suffix
59#define HDMI_SW_DI_N_HEAD_WORD(x) XCAT(HDMI_SW_DI_, x, _HEAD_WORD) 68#define HDMI_SW_DI_N_HEAD_WORD(x) XCAT(HDMI_SW_DI_, x, _HEAD_WORD)
@@ -264,6 +273,10 @@ static void hdmi_infoframe_reset(struct sti_hdmi *hdmi,
264 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO); 273 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);
265 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO); 274 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);
266 break; 275 break;
276 case HDMI_IFRAME_SLOT_VENDOR:
277 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_VENDOR);
278 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_VENDOR);
279 break;
267 default: 280 default:
268 DRM_ERROR("unsupported infoframe slot: %#x\n", slot); 281 DRM_ERROR("unsupported infoframe slot: %#x\n", slot);
269 return; 282 return;
@@ -305,12 +318,13 @@ static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size)
305 * @data: infoframe to write 318 * @data: infoframe to write
306 * @size: size to write 319 * @size: size to write
307 */ 320 */
308static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi, const u8 *data) 321static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi,
322 const u8 *data,
323 size_t size)
309{ 324{
310 const u8 *ptr = data; 325 const u8 *ptr = data;
311 u32 val, slot, mode, i; 326 u32 val, slot, mode, i;
312 u32 head_offset, pack_offset; 327 u32 head_offset, pack_offset;
313 size_t size;
314 328
315 switch (*ptr) { 329 switch (*ptr) {
316 case HDMI_INFOFRAME_TYPE_AVI: 330 case HDMI_INFOFRAME_TYPE_AVI:
@@ -318,17 +332,19 @@ static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi, const u8 *data)
318 mode = HDMI_IFRAME_FIELD; 332 mode = HDMI_IFRAME_FIELD;
319 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI); 333 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI);
320 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI); 334 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI);
321 size = HDMI_AVI_INFOFRAME_SIZE;
322 break; 335 break;
323
324 case HDMI_INFOFRAME_TYPE_AUDIO: 336 case HDMI_INFOFRAME_TYPE_AUDIO:
325 slot = HDMI_IFRAME_SLOT_AUDIO; 337 slot = HDMI_IFRAME_SLOT_AUDIO;
326 mode = HDMI_IFRAME_FRAME; 338 mode = HDMI_IFRAME_FRAME;
327 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO); 339 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);
328 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO); 340 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);
329 size = HDMI_AUDIO_INFOFRAME_SIZE;
330 break; 341 break;
331 342 case HDMI_INFOFRAME_TYPE_VENDOR:
343 slot = HDMI_IFRAME_SLOT_VENDOR;
344 mode = HDMI_IFRAME_FRAME;
345 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_VENDOR);
346 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_VENDOR);
347 break;
332 default: 348 default:
333 DRM_ERROR("unsupported infoframe type: %#x\n", *ptr); 349 DRM_ERROR("unsupported infoframe type: %#x\n", *ptr);
334 return; 350 return;
@@ -347,8 +363,9 @@ static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi, const u8 *data)
347 /* 363 /*
348 * Each subpack contains 4 bytes 364 * Each subpack contains 4 bytes
349 * The First Bytes of the first subpacket must contain the checksum 365 * The First Bytes of the first subpacket must contain the checksum
350 * Packet size in increase by one. 366 * Packet size is increase by one.
351 */ 367 */
368 size = size - HDMI_INFOFRAME_HEADER_SIZE + 1;
352 for (i = 0; i < size; i += sizeof(u32)) { 369 for (i = 0; i < size; i += sizeof(u32)) {
353 size_t num; 370 size_t num;
354 371
@@ -401,7 +418,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
401 return ret; 418 return ret;
402 } 419 }
403 420
404 hdmi_infoframe_write_infopack(hdmi, buffer); 421 hdmi_infoframe_write_infopack(hdmi, buffer, ret);
405 422
406 return 0; 423 return 0;
407} 424}
@@ -437,7 +454,49 @@ static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
437 return ret; 454 return ret;
438 } 455 }
439 456
440 hdmi_infoframe_write_infopack(hdmi, buffer); 457 hdmi_infoframe_write_infopack(hdmi, buffer, ret);
458
459 return 0;
460}
461
462/*
463 * Prepare and configure the VS infoframe
464 *
465 * Vendor Specific infoframe are transmitted once per frame and
466 * contains vendor specific information.
467 *
468 * @hdmi: pointer on the hdmi internal structure
469 *
470 * Return negative value if error occurs
471 */
472#define HDMI_VENDOR_INFOFRAME_MAX_SIZE 6
473static int hdmi_vendor_infoframe_config(struct sti_hdmi *hdmi)
474{
475 struct drm_display_mode *mode = &hdmi->mode;
476 struct hdmi_vendor_infoframe infoframe;
477 u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_VENDOR_INFOFRAME_MAX_SIZE];
478 int ret;
479
480 DRM_DEBUG_DRIVER("\n");
481
482 ret = drm_hdmi_vendor_infoframe_from_display_mode(&infoframe, mode);
483 if (ret < 0) {
484 /*
485 * Going into that statement does not means vendor infoframe
486 * fails. It just informed us that vendor infoframe is not
487 * needed for the selected mode. Only 4k or stereoscopic 3D
488 * mode requires vendor infoframe. So just simply return 0.
489 */
490 return 0;
491 }
492
493 ret = hdmi_vendor_infoframe_pack(&infoframe, buffer, sizeof(buffer));
494 if (ret < 0) {
495 DRM_ERROR("failed to pack VS infoframe: %d\n", ret);
496 return ret;
497 }
498
499 hdmi_infoframe_write_infopack(hdmi, buffer, ret);
441 500
442 return 0; 501 return 0;
443} 502}
@@ -510,6 +569,7 @@ static void sti_hdmi_disable(struct drm_bridge *bridge)
510 /* Reset info frame transmission */ 569 /* Reset info frame transmission */
511 hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_AVI); 570 hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_AVI);
512 hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_AUDIO); 571 hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_AUDIO);
572 hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_VENDOR);
513 573
514 /* Set the default channel data to be a dark red */ 574 /* Set the default channel data to be a dark red */
515 hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL0_DAT); 575 hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL0_DAT);
@@ -566,6 +626,10 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
566 if (hdmi_audio_infoframe_config(hdmi)) 626 if (hdmi_audio_infoframe_config(hdmi))
567 DRM_ERROR("Unable to configure AUDIO infoframe\n"); 627 DRM_ERROR("Unable to configure AUDIO infoframe\n");
568 628
629 /* Program VS infoframe */
630 if (hdmi_vendor_infoframe_config(hdmi))
631 DRM_ERROR("Unable to configure VS infoframe\n");
632
569 /* Sw reset */ 633 /* Sw reset */
570 hdmi_swreset(hdmi); 634 hdmi_swreset(hdmi);
571} 635}