Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5136fd3 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "fb/msm: add support for HDR playback control sequence"

parents 1269ad62 9154d123
Loading
Loading
Loading
Loading
+97 −47
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ static void hdmi_tx_fps_work(struct work_struct *work);
static int hdmi_tx_pinctrl_set_state(struct hdmi_tx_ctrl *hdmi_ctrl,
			enum hdmi_tx_power_module_type module, bool active);
static void hdmi_panel_set_hdr_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl);
static void hdmi_panel_clear_hdr_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl);
static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
	struct msm_ext_disp_audio_setup_params *params);
static int hdmi_tx_get_audio_edid_blk(struct platform_device *pdev,
@@ -1276,6 +1277,7 @@ static ssize_t hdmi_tx_sysfs_wta_hdr_stream(struct device *dev,
{
	int ret = 0;
	struct hdmi_tx_ctrl *ctrl = NULL;
	u8 hdr_op;

	ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);
	if (!ctrl) {
@@ -1296,36 +1298,43 @@ static ssize_t hdmi_tx_sysfs_wta_hdr_stream(struct device *dev,
		goto end;
	}

	memcpy(&ctrl->hdr_data, buf, sizeof(struct mdp_hdr_stream));
	memcpy(&ctrl->hdr_ctrl, buf, sizeof(struct mdp_hdr_stream_ctrl));

	pr_debug("%s: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n",
			__func__,
			ctrl->hdr_data.eotf,
			ctrl->hdr_data.display_primaries_x[0],
			ctrl->hdr_data.display_primaries_y[0],
			ctrl->hdr_data.display_primaries_x[1],
			ctrl->hdr_data.display_primaries_y[1],
			ctrl->hdr_data.display_primaries_x[2],
			ctrl->hdr_data.display_primaries_y[2]);
			ctrl->hdr_ctrl.hdr_stream.eotf,
			ctrl->hdr_ctrl.hdr_stream.display_primaries_x[0],
			ctrl->hdr_ctrl.hdr_stream.display_primaries_y[0],
			ctrl->hdr_ctrl.hdr_stream.display_primaries_x[1],
			ctrl->hdr_ctrl.hdr_stream.display_primaries_y[1],
			ctrl->hdr_ctrl.hdr_stream.display_primaries_x[2],
			ctrl->hdr_ctrl.hdr_stream.display_primaries_y[2]);

	pr_debug("%s: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n",
			__func__,
			ctrl->hdr_data.white_point_x,
			ctrl->hdr_data.white_point_y,
			ctrl->hdr_data.max_luminance,
			ctrl->hdr_data.min_luminance,
			ctrl->hdr_data.max_content_light_level,
			ctrl->hdr_data.max_average_light_level);
			ctrl->hdr_ctrl.hdr_stream.white_point_x,
			ctrl->hdr_ctrl.hdr_stream.white_point_y,
			ctrl->hdr_ctrl.hdr_stream.max_luminance,
			ctrl->hdr_ctrl.hdr_stream.min_luminance,
			ctrl->hdr_ctrl.hdr_stream.max_content_light_level,
			ctrl->hdr_ctrl.hdr_stream.max_average_light_level);

	pr_debug("%s: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n",
			__func__,
			ctrl->hdr_data.pixel_encoding,
			ctrl->hdr_data.colorimetry,
			ctrl->hdr_data.range,
			ctrl->hdr_data.bits_per_component,
			ctrl->hdr_data.content_type);

			ctrl->hdr_ctrl.hdr_stream.pixel_encoding,
			ctrl->hdr_ctrl.hdr_stream.colorimetry,
			ctrl->hdr_ctrl.hdr_stream.range,
			ctrl->hdr_ctrl.hdr_stream.bits_per_component,
			ctrl->hdr_ctrl.hdr_stream.content_type);
	hdr_op = hdmi_hdr_get_ops(ctrl->curr_hdr_state,
					ctrl->hdr_ctrl.hdr_state);

	if (hdr_op == HDR_SEND_INFO)
		hdmi_panel_set_hdr_infoframe(ctrl);
	else if (hdr_op == HDR_CLEAR_INFO)
		hdmi_panel_clear_hdr_infoframe(ctrl);

	ctrl->curr_hdr_state = ctrl->hdr_ctrl.hdr_state;

	ret = strnlen(buf, PAGE_SIZE);
end:
@@ -2113,6 +2122,8 @@ static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
		goto err;
	}

	/* reset HDR state */
	hdmi_ctrl->curr_hdr_state = HDR_DISABLE;
	return 0;
err:
	hdmi_tx_deinit_features(hdmi_ctrl, deinit_features);
@@ -2871,11 +2882,12 @@ static void hdmi_panel_set_hdr_infoframe(struct hdmi_tx_ctrl *ctrl)
	packet_header = type_code | (version << 8) | (length << 16);
	DSS_REG_W(io, HDMI_GENERIC0_HDR, packet_header);

	packet_payload = (ctrl->hdr_data.eotf << 8);
	packet_payload = (ctrl->hdr_ctrl.hdr_stream.eotf << 8);
	if (hdmi_tx_metadata_type_one(ctrl)) {
		packet_payload |= (descriptor_id << 16)
			| (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[0])
					<< 24);
		packet_payload |=
			(descriptor_id << 16)
			| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.
					display_primaries_x[0]) << 24);
		DSS_REG_W(io, HDMI_GENERIC0_0, packet_payload);
	} else {
		pr_debug("%s: Metadata Type 1 not supported\n", __func__);
@@ -2884,44 +2896,56 @@ static void hdmi_panel_set_hdr_infoframe(struct hdmi_tx_ctrl *ctrl)
	}

	packet_payload =
		(HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[0]))
		| (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[0]) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[0]) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[1]) << 24);
		(HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.display_primaries_x[0]))
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.
				display_primaries_y[0]) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.
				display_primaries_y[0]) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.
				display_primaries_x[1]) << 24);
	DSS_REG_W(io, HDMI_GENERIC0_1, packet_payload);

	packet_payload =
		(HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[1]))
		| (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[1]) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[1]) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[2]) << 24);
		(HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.display_primaries_x[1]))
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.
				display_primaries_y[1]) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.
				display_primaries_y[1]) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.
				display_primaries_x[2]) << 24);
	DSS_REG_W(io, HDMI_GENERIC0_2, packet_payload);

	packet_payload =
		(HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[2]))
		| (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[2]) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[2]) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_data.white_point_x) << 24);
		(HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.display_primaries_x[2]))
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.
				display_primaries_y[2]) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.
				display_primaries_y[2]) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.white_point_x) << 24);
	DSS_REG_W(io, HDMI_GENERIC0_3, packet_payload);

	packet_payload =
		(HDMI_GET_MSB(ctrl->hdr_data.white_point_x))
		| (HDMI_GET_LSB(ctrl->hdr_data.white_point_y) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_data.white_point_y) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_data.max_luminance) << 24);
		(HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.white_point_x))
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.white_point_y) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.white_point_y) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.max_luminance) << 24);
	DSS_REG_W(io, HDMI_GENERIC0_4, packet_payload);

	packet_payload =
		(HDMI_GET_MSB(ctrl->hdr_data.max_luminance))
		| (HDMI_GET_LSB(ctrl->hdr_data.min_luminance) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_data.min_luminance) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_data.max_content_light_level) << 24);
		(HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.max_luminance))
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.min_luminance) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.min_luminance) << 16)
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.
					max_content_light_level) << 24);
	DSS_REG_W(io, HDMI_GENERIC0_5, packet_payload);

	packet_payload =
		(HDMI_GET_MSB(ctrl->hdr_data.max_content_light_level))
		| (HDMI_GET_LSB(ctrl->hdr_data.max_average_light_level) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_data.max_average_light_level) << 16);
		(HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.
				max_content_light_level))
		| (HDMI_GET_LSB(ctrl->hdr_ctrl.hdr_stream.
				max_average_light_level) << 8)
		| (HDMI_GET_MSB(ctrl->hdr_ctrl.hdr_stream.
				max_average_light_level) << 16);
	DSS_REG_W(io, HDMI_GENERIC0_6, packet_payload);

enable_packet_control:
@@ -2936,6 +2960,32 @@ enable_packet_control:
	DSS_REG_W(io, HDMI_GEN_PKT_CTRL, packet_control);
}

static void hdmi_panel_clear_hdr_infoframe(struct hdmi_tx_ctrl *ctrl)
{
	u32 packet_control = 0;
	struct dss_io_data *io = NULL;

	if (!ctrl) {
		pr_err("%s: invalid input\n", __func__);
		return;
	}

	if (!hdmi_tx_is_hdr_supported(ctrl)) {
		pr_err("%s: Sink does not support HDR\n", __func__);
		return;
	}

	io = &ctrl->pdata.io[HDMI_TX_CORE_IO];
	if (!io->base) {
		pr_err("%s: core io not inititalized\n", __func__);
		return;
	}

	packet_control = DSS_REG_R_ND(io, HDMI_GEN_PKT_CTRL);
	packet_control &= ~HDMI_GEN_PKT_CTRL_CLR_MASK;
	DSS_REG_W(io, HDMI_GEN_PKT_CTRL, packet_control);
}

static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
	struct msm_ext_disp_audio_setup_params *params)
{
+3 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "mdss_hdmi_audio.h"

#define MAX_SWITCH_NAME_SIZE        5
#define HDMI_GEN_PKT_CTRL_CLR_MASK  0x7

enum hdmi_tx_io_type {
	HDMI_TX_CORE_IO,
@@ -90,7 +91,7 @@ struct hdmi_tx_ctrl {
	struct msm_ext_disp_audio_setup_params audio_params;
	struct msm_ext_disp_init_data ext_audio_data;
	struct work_struct fps_work;
	struct mdp_hdr_stream hdr_data;
	struct mdp_hdr_stream_ctrl hdr_ctrl;

	spinlock_t hpd_state_lock;

@@ -116,6 +117,7 @@ struct hdmi_tx_ctrl {
	u8 hdcp_status;
	u8 spd_vendor_name[9];
	u8 spd_product_description[17];
	u8 curr_hdr_state;

	bool hdcp_feature_on;
	bool hpd_disabled;
+49 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/msm_mdp.h>
#include <linux/msm_mdp_ext.h>
#include "mdss_hdmi_util.h"

#define RESOLUTION_NAME_STR_LEN 30
@@ -1811,3 +1812,51 @@ int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl)

	return rc;
}

u8 hdmi_hdr_get_ops(u8 curr_state, u8 new_state)
{

	/** There could be 3 valid state transitions:
	* 1. HDR_DISABLE -> HDR_ENABLE
	*
	* In this transition, we shall start sending
	* HDR metadata with metadata from the HDR clip
	*
	* 2. HDR_ENABLE -> HDR_RESET
	*
	* In this transition, we will keep sending
	* HDR metadata but with EOTF and metadata as 0
	*
	* 3. HDR_RESET -> HDR_ENABLE
	*
	* In this transition, we will start sending
	* HDR metadata with metadata from the HDR clip
	*
	* 4. HDR_RESET -> HDR_DISABLE
	*
	* In this transition, we will stop sending
	* metadata to the sink and clear PKT_CTRL register
	* bits.
	*/

	if ((curr_state == HDR_DISABLE)
		&& (new_state == HDR_ENABLE)) {
		pr_debug("State changed HDR_DISABLE ---> HDR_ENABLE\n");
		return HDR_SEND_INFO;
	} else if ((curr_state == HDR_ENABLE)
		&& (new_state == HDR_RESET)) {
		pr_debug("State changed HDR_ENABLE ---> HDR_RESET\n");
		return HDR_SEND_INFO;
	} else if ((curr_state == HDR_RESET)
		&& (new_state == HDR_ENABLE)) {
		pr_debug("State changed HDR_RESET ---> HDR_ENABLE\n");
		return HDR_SEND_INFO;
	} else if ((curr_state == HDR_RESET)
		&& (new_state == HDR_DISABLE)) {
		pr_debug("State changed HDR_RESET ---> HDR_DISABLE\n");
		return HDR_CLEAR_INFO;
	}

	pr_debug("Unsupported OR no state change\n");
	return HDR_UNSUPPORTED_OP;
}
+8 −2
Original line number Diff line number Diff line
/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -425,6 +425,12 @@ enum hdmi_tx_hdcp2p2_rxstatus_intr_mask {
	RXSTATUS_REAUTH_REQ = BIT(14),
};

enum hdmi_hdr_op {
	HDR_UNSUPPORTED_OP,
	HDR_SEND_INFO,
	HDR_CLEAR_INFO
};

struct hdmi_tx_hdcp2p2_ddc_data {
	enum hdmi_tx_hdcp2p2_rxstatus_intr_mask intr_mask;
	u32 timeout_ms;
@@ -518,5 +524,5 @@ void hdmi_hdcp2p2_ddc_disable(struct hdmi_tx_ddc_ctrl *ctrl);
int hdmi_hdcp2p2_ddc_read_rxstatus(struct hdmi_tx_ddc_ctrl *ctrl);
int hdmi_utils_get_timeout_in_hysnc(struct msm_hdmi_mode_timing_info *timing,
	u32 timeout_ms);

u8 hdmi_hdr_get_ops(u8 curr_state, u8 new_state);
#endif /* __HDMI_UTIL_H__ */
+22 −0
Original line number Diff line number Diff line
@@ -821,4 +821,26 @@ struct mdp_hdr_stream {
	uint32_t content_type;
	uint32_t reserved[5];
};

/* hdr hdmi state takes possible values of 1, 2 and 4 respectively */
#define HDR_ENABLE  (1 << 0)
#define HDR_DISABLE (1 << 1)
#define HDR_RESET   (1 << 2)

/*
 * HDR Control
 * This encapsulates the HDR metadata as well as a state control
 * for the HDR metadata as required by the HDMI spec to send the
 * relevant metadata depending on the state of the HDR playback.
 * hdr_state: Controls HDR state, takes values HDR_ENABLE, HDR_DISABLE
 * and HDR_RESET.
 * hdr_meta: Metadata sent by the userspace for the HDR clip.
 */

#define DRM_MSM_EXT_PANEL_HDR_CTRL
struct mdp_hdr_stream_ctrl {
	__u8 hdr_state;                   /* HDR state */
	struct mdp_hdr_stream hdr_stream; /* HDR metadata */
};

#endif