#define RK3588_HDMI1_LEVEL_INT BIT(24)
#define RK3588_GRF_VO1_CON3 0x000c
#define RK3588_GRF_VO1_CON6 0x0018
+#define RK3588_COLOR_DEPTH_MASK GENMASK(7, 4)
+#define RK3588_8BPC 0x0
+#define RK3588_10BPC 0x6
+#define RK3588_COLOR_FORMAT_MASK GENMASK(3, 0)
+#define RK3588_RGB 0x0
+#define RK3588_YUV420 0x3
#define RK3588_SCLIN_MASK BIT(9)
#define RK3588_SDAIN_MASK BIT(10)
#define RK3588_MODE_MASK BIT(11)
struct rockchip_hdmi_qp_ctrl_ops {
void (*io_init)(struct rockchip_hdmi_qp *hdmi);
+ void (*enc_init)(struct rockchip_hdmi_qp *hdmi, struct rockchip_crtc_state *state);
irqreturn_t (*irq_callback)(int irq, void *dev_id);
irqreturn_t (*hardirq_callback)(int irq, void *dev_id);
};
static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
{
struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
+ struct drm_crtc *crtc = encoder->crtc;
/* Unconditionally switch to TMDS as FRL is not yet supported */
gpiod_set_value(hdmi->frl_enable_gpio, 0);
+
+ if (!crtc || !crtc->state)
+ return;
+
+ if (hdmi->ctrl_ops->enc_init)
+ hdmi->ctrl_ops->enc_init(hdmi, to_rockchip_crtc_state(crtc->state));
}
static int
union phy_configure_opts phy_cfg = {};
int ret;
- if (hdmi->tmds_char_rate == conn_state->hdmi.tmds_char_rate)
+ if (hdmi->tmds_char_rate == conn_state->hdmi.tmds_char_rate &&
+ s->output_bpc == conn_state->hdmi.output_bpc)
return 0;
phy_cfg.hdmi.tmds_char_rate = conn_state->hdmi.tmds_char_rate;
+ phy_cfg.hdmi.bpc = conn_state->hdmi.output_bpc;
ret = phy_configure(hdmi->phy, &phy_cfg);
if (!ret) {
hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+ s->output_bpc = conn_state->hdmi.output_bpc;
} else {
dev_err(hdmi->dev, "Failed to configure phy: %d\n", ret);
}
regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
}
+static void dw_hdmi_qp_rk3576_enc_init(struct rockchip_hdmi_qp *hdmi,
+ struct rockchip_crtc_state *state)
+{
+ u32 val;
+
+ if (state->output_bpc == 10)
+ val = FIELD_PREP_WM16(RK3576_COLOR_DEPTH_MASK, RK3576_10BPC);
+ else
+ val = FIELD_PREP_WM16(RK3576_COLOR_DEPTH_MASK, RK3576_8BPC);
+
+ regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON8, val);
+}
+
+static void dw_hdmi_qp_rk3588_enc_init(struct rockchip_hdmi_qp *hdmi,
+ struct rockchip_crtc_state *state)
+{
+ u32 val;
+
+ if (state->output_bpc == 10)
+ val = FIELD_PREP_WM16(RK3588_COLOR_DEPTH_MASK, RK3588_10BPC);
+ else
+ val = FIELD_PREP_WM16(RK3588_COLOR_DEPTH_MASK, RK3588_8BPC);
+
+ regmap_write(hdmi->vo_regmap,
+ hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3,
+ val);
+}
+
static const struct rockchip_hdmi_qp_ctrl_ops rk3576_hdmi_ctrl_ops = {
.io_init = dw_hdmi_qp_rk3576_io_init,
- .irq_callback = dw_hdmi_qp_rk3576_irq,
+ .enc_init = dw_hdmi_qp_rk3576_enc_init,
+ .irq_callback = dw_hdmi_qp_rk3576_irq,
.hardirq_callback = dw_hdmi_qp_rk3576_hardirq,
};
static const struct rockchip_hdmi_qp_ctrl_ops rk3588_hdmi_ctrl_ops = {
.io_init = dw_hdmi_qp_rk3588_io_init,
- .irq_callback = dw_hdmi_qp_rk3588_irq,
+ .enc_init = dw_hdmi_qp_rk3588_enc_init,
+ .irq_callback = dw_hdmi_qp_rk3588_irq,
.hardirq_callback = dw_hdmi_qp_rk3588_hardirq,
};
plat_data.phy_ops = cfg->phy_ops;
plat_data.phy_data = hdmi;
+ plat_data.max_bpc = 10;
encoder = &hdmi->encoder.encoder;
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);