Skip to content

Commit ba8c0fa

Browse files
committed
drm/vc4: hdmi: Enable 10/12 bpc output
The BCM2711 supports higher bpc count than just 8, so let's support it in our driver. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/20201215154243.540115-10-maxime@cerno.tech
1 parent 24169a2 commit ba8c0fa

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

drivers/gpu/drm/vc4/vc4_hdmi.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@
7676
#define VC5_HDMI_VERTB_VSPO_SHIFT 16
7777
#define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16)
7878

79+
#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT 8
80+
#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK VC4_MASK(10, 8)
81+
82+
#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_SHIFT 0
83+
#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK VC4_MASK(3, 0)
84+
85+
#define VC5_HDMI_GCP_CONFIG_GCP_ENABLE BIT(31)
86+
87+
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_SHIFT 8
88+
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK VC4_MASK(15, 8)
89+
7990
# define VC4_HD_M_SW_RST BIT(2)
8091
# define VC4_HD_M_ENABLE BIT(0)
8192

@@ -186,6 +197,8 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
186197
if (!new_state)
187198
return;
188199

200+
new_state->base.max_bpc = 8;
201+
new_state->base.max_requested_bpc = 8;
189202
drm_atomic_helper_connector_tv_reset(connector);
190203
}
191204

@@ -232,12 +245,20 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
232245
vc4_hdmi->ddc);
233246
drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
234247

248+
/*
249+
* Some of the properties below require access to state, like bpc.
250+
* Allocate some default initial connector state with our reset helper.
251+
*/
252+
if (connector->funcs->reset)
253+
connector->funcs->reset(connector);
254+
235255
/* Create and attach TV margin props to this connector. */
236256
ret = drm_mode_create_tv_margin_properties(dev);
237257
if (ret)
238258
return ret;
239259

240260
drm_connector_attach_tv_margin_properties(connector);
261+
drm_connector_attach_max_bpc_property(connector, 8, 12);
241262

242263
connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
243264
DRM_CONNECTOR_POLL_DISCONNECT);
@@ -506,6 +527,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
506527
}
507528

508529
static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
530+
struct drm_connector_state *state,
509531
struct drm_display_mode *mode)
510532
{
511533
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -549,7 +571,9 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
549571
HDMI_WRITE(HDMI_VERTB0, vertb_even);
550572
HDMI_WRITE(HDMI_VERTB1, vertb);
551573
}
574+
552575
static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
576+
struct drm_connector_state *state,
553577
struct drm_display_mode *mode)
554578
{
555579
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -569,6 +593,9 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
569593
mode->crtc_vsync_end -
570594
interlaced,
571595
VC4_HDMI_VERTB_VBP));
596+
unsigned char gcp;
597+
bool gcp_en;
598+
u32 reg;
572599

573600
HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
574601
HDMI_WRITE(HDMI_HORZA,
@@ -594,6 +621,39 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
594621
HDMI_WRITE(HDMI_VERTB0, vertb_even);
595622
HDMI_WRITE(HDMI_VERTB1, vertb);
596623

624+
switch (state->max_bpc) {
625+
case 12:
626+
gcp = 6;
627+
gcp_en = true;
628+
break;
629+
case 10:
630+
gcp = 5;
631+
gcp_en = true;
632+
break;
633+
case 8:
634+
default:
635+
gcp = 4;
636+
gcp_en = false;
637+
break;
638+
}
639+
640+
reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1);
641+
reg &= ~(VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK |
642+
VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK);
643+
reg |= VC4_SET_FIELD(2, VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE) |
644+
VC4_SET_FIELD(gcp, VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH);
645+
HDMI_WRITE(HDMI_DEEP_COLOR_CONFIG_1, reg);
646+
647+
reg = HDMI_READ(HDMI_GCP_WORD_1);
648+
reg &= ~VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK;
649+
reg |= VC4_SET_FIELD(gcp, VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1);
650+
HDMI_WRITE(HDMI_GCP_WORD_1, reg);
651+
652+
reg = HDMI_READ(HDMI_GCP_CONFIG);
653+
reg &= ~VC5_HDMI_GCP_CONFIG_GCP_ENABLE;
654+
reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0;
655+
HDMI_WRITE(HDMI_GCP_CONFIG, reg);
656+
597657
HDMI_WRITE(HDMI_CLOCK_STOP, 0);
598658
}
599659

@@ -731,7 +791,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
731791
VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
732792

733793
if (vc4_hdmi->variant->set_timings)
734-
vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
794+
vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
735795
}
736796

737797
static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
@@ -852,6 +912,14 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
852912
pixel_rate = mode->clock * 1000;
853913
}
854914

915+
if (conn_state->max_bpc == 12) {
916+
pixel_rate = pixel_rate * 150;
917+
do_div(pixel_rate, 100);
918+
} else if (conn_state->max_bpc == 10) {
919+
pixel_rate = pixel_rate * 125;
920+
do_div(pixel_rate, 100);
921+
}
922+
855923
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
856924
pixel_rate = pixel_rate * 2;
857925

drivers/gpu/drm/vc4/vc4_hdmi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct vc4_hdmi_variant {
7777

7878
/* Callback to configure the video timings in the HDMI block */
7979
void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
80+
struct drm_connector_state *state,
8081
struct drm_display_mode *mode);
8182

8283
/* Callback to initialize the PHY according to the connector state */

drivers/gpu/drm/vc4/vc4_hdmi_regs.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ enum vc4_hdmi_field {
5959
*/
6060
HDMI_CTS_0,
6161
HDMI_CTS_1,
62+
HDMI_DEEP_COLOR_CONFIG_1,
6263
HDMI_DVP_CTL,
6364
HDMI_FIFO_CTL,
6465
HDMI_FRAME_COUNT,
66+
HDMI_GCP_CONFIG,
67+
HDMI_GCP_WORD_1,
6568
HDMI_HORZA,
6669
HDMI_HORZB,
6770
HDMI_HOTPLUG,
@@ -229,6 +232,9 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi0_fields[] = {
229232
VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
230233
VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
231234
VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
235+
VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170),
236+
VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178),
237+
VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c),
232238
VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
233239

234240
VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
@@ -305,6 +311,9 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi1_fields[] = {
305311
VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
306312
VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
307313
VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
314+
VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170),
315+
VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178),
316+
VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c),
308317
VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
309318

310319
VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),

0 commit comments

Comments
 (0)