aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2016-09-16 05:59:45 -0400
committerEric Anholt <eric@anholt.net>2016-10-06 14:58:26 -0400
commit6e1cbbad670cf9e9ee6fb58a8d77ca095f385eee (patch)
tree359f3c3aeadb66895382aa990dd147fd91314b6b
parent7edabee06a5622190d59689a64f5e17d1c343cc3 (diff)
drm/vc4: Enable limited range RGB output on HDMI with CEA modes.
Fixes broken grayscale ramps on many HDMI monitors, where large areas at the ends of the ramp would all appear as black or white. Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c31
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h9
2 files changed, 37 insertions, 3 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 68ad10634b29..29be7b7273df 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -298,6 +298,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
298 struct drm_display_mode *unadjusted_mode, 298 struct drm_display_mode *unadjusted_mode,
299 struct drm_display_mode *mode) 299 struct drm_display_mode *mode)
300{ 300{
301 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
301 struct drm_device *dev = encoder->dev; 302 struct drm_device *dev = encoder->dev;
302 struct vc4_dev *vc4 = to_vc4_dev(dev); 303 struct vc4_dev *vc4 = to_vc4_dev(dev);
303 bool debug_dump_regs = false; 304 bool debug_dump_regs = false;
@@ -313,6 +314,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
313 u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | 314 u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
314 VC4_SET_FIELD(mode->vtotal - mode->vsync_end, 315 VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
315 VC4_HDMI_VERTB_VBP)); 316 VC4_HDMI_VERTB_VBP));
317 u32 csc_ctl;
316 318
317 if (debug_dump_regs) { 319 if (debug_dump_regs) {
318 DRM_INFO("HDMI regs before:\n"); 320 DRM_INFO("HDMI regs before:\n");
@@ -351,9 +353,34 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
351 (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | 353 (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
352 (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); 354 (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
353 355
356 csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
357 VC4_HD_CSC_CTL_ORDER);
358
359 if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) {
360 /* CEA VICs other than #1 requre limited range RGB
361 * output. Apply a colorspace conversion to squash
362 * 0-255 down to 16-235. The matrix here is:
363 *
364 * [ 0 0 0.8594 16]
365 * [ 0 0.8594 0 16]
366 * [ 0.8594 0 0 16]
367 * [ 0 0 0 1]
368 */
369 csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
370 csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
371 csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
372 VC4_HD_CSC_CTL_MODE);
373
374 HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
375 HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
376 HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
377 HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
378 HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
379 HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
380 }
381
354 /* The RGB order applies even when CSC is disabled. */ 382 /* The RGB order applies even when CSC is disabled. */
355 HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, 383 HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
356 VC4_HD_CSC_CTL_ORDER));
357 384
358 HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); 385 HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
359 386
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 160942a9180e..9ecd6ff3d493 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -528,10 +528,17 @@
528# define VC4_HD_CSC_CTL_MODE_SHIFT 2 528# define VC4_HD_CSC_CTL_MODE_SHIFT 2
529# define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0 529# define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0
530# define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1 530# define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1
531# define VC4_HD_CSC_CTL_MODE_CUSTOM 2 531# define VC4_HD_CSC_CTL_MODE_CUSTOM 3
532# define VC4_HD_CSC_CTL_RGB2YCC BIT(1) 532# define VC4_HD_CSC_CTL_RGB2YCC BIT(1)
533# define VC4_HD_CSC_CTL_ENABLE BIT(0) 533# define VC4_HD_CSC_CTL_ENABLE BIT(0)
534 534
535#define VC4_HD_CSC_12_11 0x044
536#define VC4_HD_CSC_14_13 0x048
537#define VC4_HD_CSC_22_21 0x04c
538#define VC4_HD_CSC_24_23 0x050
539#define VC4_HD_CSC_32_31 0x054
540#define VC4_HD_CSC_34_33 0x058
541
535#define VC4_HD_FRAME_COUNT 0x068 542#define VC4_HD_FRAME_COUNT 0x068
536 543
537/* HVS display list information. */ 544/* HVS display list information. */