Skip to content

Commit

Permalink
WIP: drm/bridge/synopsys: dw-hdmi: set drm infoframe
Browse files Browse the repository at this point in the history
  • Loading branch information
Kwiboo committed May 12, 2019
1 parent d11b92d commit a9ccea6
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 0 deletions.
110 changes: 110 additions & 0 deletions drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
Expand Up @@ -24,6 +24,7 @@

#include <drm/drm_of.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder_slave.h>
Expand Down Expand Up @@ -1622,6 +1623,92 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi,
HDMI_FC_DATAUTO0_VSD_MASK);
}

#define HDR_LSB(n) ((n) & 0xff)
#define HDR_MSB(n) (((n) & 0xff00) >> 8)

static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi)
{
struct hdmi_drm_infoframe frame;
struct hdr_output_metadata *hdr_metadata;
struct drm_connector_state *conn_state = hdmi->connector.state;
struct drm_connector *connector = conn_state->connector;
int ret;

if (hdmi->version < 0x200a || !hdmi->plat_data->drm_infoframe)
return;

hdmi_modb(hdmi, HDMI_FC_PACKET_TX_EN_DRM_DISABLE,
HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN);

if (!conn_state->hdr_output_metadata ||
conn_state->hdr_output_metadata->length == 0)
return;

hdr_metadata = (struct hdr_output_metadata *)
conn_state->hdr_output_metadata->data;

/* Sink EOTF is Bit map while infoframe is absolute values */
if (!(connector->hdr_sink_metadata.hdmi_type1.eotf &
BIT(hdr_metadata->hdmi_metadata_type1.eotf))) {
DRM_ERROR("EOTF Not supported by sink\n");
return;
}

ret = drm_hdmi_infoframe_set_hdr_metadata(&frame, hdr_metadata);
if (ret < 0) {
DRM_ERROR("couldn't set HDR metadata in infoframe\n");
return;
}

hdmi_writeb(hdmi, frame.version, HDMI_FC_DRM_HB0);
hdmi_writeb(hdmi, frame.length, HDMI_FC_DRM_HB1);
hdmi_writeb(hdmi, frame.eotf, HDMI_FC_DRM_PB0);
hdmi_writeb(hdmi, frame.metadata_type, HDMI_FC_DRM_PB1);
hdmi_writeb(hdmi, HDR_LSB(frame.display_primaries[0].x),
HDMI_FC_DRM_PB2);
hdmi_writeb(hdmi, HDR_MSB(frame.display_primaries[0].x),
HDMI_FC_DRM_PB3);
hdmi_writeb(hdmi, HDR_LSB(frame.display_primaries[0].y),
HDMI_FC_DRM_PB4);
hdmi_writeb(hdmi, HDR_MSB(frame.display_primaries[0].y),
HDMI_FC_DRM_PB5);
hdmi_writeb(hdmi, HDR_LSB(frame.display_primaries[1].x),
HDMI_FC_DRM_PB6);
hdmi_writeb(hdmi, HDR_MSB(frame.display_primaries[1].x),
HDMI_FC_DRM_PB7);
hdmi_writeb(hdmi, HDR_LSB(frame.display_primaries[1].y),
HDMI_FC_DRM_PB8);
hdmi_writeb(hdmi, HDR_MSB(frame.display_primaries[1].y),
HDMI_FC_DRM_PB9);
hdmi_writeb(hdmi, HDR_LSB(frame.display_primaries[2].x),
HDMI_FC_DRM_PB10);
hdmi_writeb(hdmi, HDR_MSB(frame.display_primaries[2].x),
HDMI_FC_DRM_PB11);
hdmi_writeb(hdmi, HDR_LSB(frame.display_primaries[2].y),
HDMI_FC_DRM_PB12);
hdmi_writeb(hdmi, HDR_MSB(frame.display_primaries[2].y),
HDMI_FC_DRM_PB13);
hdmi_writeb(hdmi, HDR_LSB(frame.white_point.x), HDMI_FC_DRM_PB14);
hdmi_writeb(hdmi, HDR_MSB(frame.white_point.x), HDMI_FC_DRM_PB15);
hdmi_writeb(hdmi, HDR_LSB(frame.white_point.y), HDMI_FC_DRM_PB16);
hdmi_writeb(hdmi, HDR_MSB(frame.white_point.y), HDMI_FC_DRM_PB17);
hdmi_writeb(hdmi, HDR_LSB(frame.max_display_mastering_luminance),
HDMI_FC_DRM_PB18);
hdmi_writeb(hdmi, HDR_MSB(frame.max_display_mastering_luminance),
HDMI_FC_DRM_PB19);
hdmi_writeb(hdmi, HDR_LSB(frame.min_display_mastering_luminance),
HDMI_FC_DRM_PB20);
hdmi_writeb(hdmi, HDR_MSB(frame.min_display_mastering_luminance),
HDMI_FC_DRM_PB21);
hdmi_writeb(hdmi, HDR_LSB(frame.max_cll), HDMI_FC_DRM_PB22);
hdmi_writeb(hdmi, HDR_MSB(frame.max_cll), HDMI_FC_DRM_PB23);
hdmi_writeb(hdmi, HDR_LSB(frame.max_fall), HDMI_FC_DRM_PB24);
hdmi_writeb(hdmi, HDR_MSB(frame.max_fall), HDMI_FC_DRM_PB25);
hdmi_writeb(hdmi, 1, HDMI_FC_DRM_UP);
hdmi_modb(hdmi, HDMI_FC_PACKET_TX_EN_DRM_ENABLE,
HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN);
}

static void hdmi_av_composer(struct dw_hdmi *hdmi,
const struct drm_display_mode *mode)
{
Expand Down Expand Up @@ -1943,6 +2030,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
/* HDMI Initialization Step F - Configure AVI InfoFrame */
hdmi_config_AVI(hdmi, mode);
hdmi_config_vendor_specific_infoframe(hdmi, mode);
hdmi_config_drm_infoframe(hdmi);
} else {
dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
}
Expand Down Expand Up @@ -2137,6 +2225,23 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
return dw_hdmi_connector_update_edid(connector, true);
}

static int dw_hdmi_connector_atomic_check(struct drm_connector *conn,
struct drm_connector_state *new_state)
{
struct drm_crtc_state *crtc_state;

if (!new_state->crtc)
return 0;

crtc_state = drm_atomic_get_new_crtc_state(new_state->state,
new_state->crtc);

if (new_state->hdr_metadata_changed)
crtc_state->mode_changed = true;

return 0;
}

static void dw_hdmi_connector_force(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
Expand All @@ -2161,6 +2266,7 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {

static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
.get_modes = dw_hdmi_connector_get_modes,
.atomic_check = dw_hdmi_connector_atomic_check,
};

static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
Expand All @@ -2177,6 +2283,10 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);

if (hdmi->version >= 0x200a && hdmi->plat_data->drm_infoframe)
drm_object_attach_property(&connector->base,
connector->dev->mode_config.hdr_output_metadata_property, 0);

drm_connector_attach_encoder(connector, encoder);

return 0;
Expand Down
37 changes: 37 additions & 0 deletions drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
Expand Up @@ -265,6 +265,7 @@
#define HDMI_FC_POL2 0x10DB
#define HDMI_FC_PRCONF 0x10E0
#define HDMI_FC_SCRAMBLER_CTRL 0x10E1
#define HDMI_FC_PACKET_TX_EN 0x10E3

#define HDMI_FC_GMD_STAT 0x1100
#define HDMI_FC_GMD_EN 0x1101
Expand Down Expand Up @@ -300,6 +301,37 @@
#define HDMI_FC_GMD_PB26 0x111F
#define HDMI_FC_GMD_PB27 0x1120

#define HDMI_FC_DRM_UP 0x1167
#define HDMI_FC_DRM_HB0 0x1168
#define HDMI_FC_DRM_HB1 0x1169
#define HDMI_FC_DRM_PB0 0x116A
#define HDMI_FC_DRM_PB1 0x116B
#define HDMI_FC_DRM_PB2 0x116C
#define HDMI_FC_DRM_PB3 0x116D
#define HDMI_FC_DRM_PB4 0x116E
#define HDMI_FC_DRM_PB5 0x116F
#define HDMI_FC_DRM_PB6 0x1170
#define HDMI_FC_DRM_PB7 0x1171
#define HDMI_FC_DRM_PB8 0x1172
#define HDMI_FC_DRM_PB9 0x1173
#define HDMI_FC_DRM_PB10 0x1174
#define HDMI_FC_DRM_PB11 0x1175
#define HDMI_FC_DRM_PB12 0x1176
#define HDMI_FC_DRM_PB13 0x1177
#define HDMI_FC_DRM_PB14 0x1178
#define HDMI_FC_DRM_PB15 0x1179
#define HDMI_FC_DRM_PB16 0x117A
#define HDMI_FC_DRM_PB17 0x117B
#define HDMI_FC_DRM_PB18 0x117C
#define HDMI_FC_DRM_PB19 0x117D
#define HDMI_FC_DRM_PB20 0x117E
#define HDMI_FC_DRM_PB21 0x117F
#define HDMI_FC_DRM_PB22 0x1180
#define HDMI_FC_DRM_PB23 0x1181
#define HDMI_FC_DRM_PB24 0x1182
#define HDMI_FC_DRM_PB25 0x1183
#define HDMI_FC_DRM_PB26 0x1184

#define HDMI_FC_DBGFORCE 0x1200
#define HDMI_FC_DBGAUD0CH0 0x1201
#define HDMI_FC_DBGAUD1CH0 0x1202
Expand Down Expand Up @@ -766,6 +798,11 @@ enum {
HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F,
HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0,

/* FC_PACKET_TX_EN field values */
HDMI_FC_PACKET_TX_EN_DRM_MASK = 0x80,
HDMI_FC_PACKET_TX_EN_DRM_ENABLE = 0x80,
HDMI_FC_PACKET_TX_EN_DRM_DISABLE = 0x00,

/* FC_AVICONF0-FC_AVICONF3 field values */
HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03,
HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00,
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/meson/meson_dw_hdmi.c
Expand Up @@ -886,6 +886,10 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;

if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi"))
dw_plat_data->drm_infoframe = true;

platform_set_drvdata(pdev, meson_dw_hdmi);

meson_dw_hdmi->hdmi = dw_hdmi_bind(pdev, encoder,
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
Expand Up @@ -405,6 +405,7 @@ static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = {
.phy_ops = &rk3328_hdmi_phy_ops,
.phy_name = "inno_dw_hdmi_phy2",
.phy_force_vendor = true,
.drm_infoframe = true,
};

static struct rockchip_hdmi_chip_data rk3399_chip_data = {
Expand All @@ -419,6 +420,7 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
.cur_ctr = rockchip_cur_ctr,
.phy_config = rockchip_phy_config,
.phy_data = &rk3399_chip_data,
.drm_infoframe = true,
};

static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
Expand Up @@ -189,6 +189,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
sun8i_hdmi_phy_init(hdmi->phy);

plat_data->mode_valid = hdmi->quirks->mode_valid;
plat_data->drm_infoframe = hdmi->quirks->drm_infoframe;
sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data);

platform_set_drvdata(pdev, hdmi);
Expand Down Expand Up @@ -255,6 +256,7 @@ static const struct sun8i_dw_hdmi_quirks sun8i_a83t_quirks = {

static const struct sun8i_dw_hdmi_quirks sun50i_h6_quirks = {
.mode_valid = sun8i_dw_hdmi_mode_valid_h6,
.drm_infoframe = true,
};

static const struct of_device_id sun8i_dw_hdmi_dt_ids[] = {
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
Expand Up @@ -178,6 +178,7 @@ struct sun8i_dw_hdmi_quirks {
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
const struct drm_display_mode *mode);
unsigned int set_rate : 1;
unsigned int drm_infoframe : 1;
};

struct sun8i_dw_hdmi {
Expand Down
1 change: 1 addition & 0 deletions include/drm/bridge/dw_hdmi.h
Expand Up @@ -130,6 +130,7 @@ struct dw_hdmi_plat_data {
const struct drm_display_mode *mode);
unsigned long input_bus_format;
unsigned long input_bus_encoding;
bool drm_infoframe;

/* Vendor PHY support */
const struct dw_hdmi_phy_ops *phy_ops;
Expand Down

0 comments on commit a9ccea6

Please sign in to comment.