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

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

Merge "msm: mdss: hdmi: add pll_enable property to support clock recovery"

parents 917c88ae c93c1652
Loading
Loading
Loading
Loading
+109 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ static int hdmi_tx_get_audio_edid_blk(struct platform_device *pdev,
	struct msm_ext_disp_audio_edid_blk *blk);
static int hdmi_tx_get_cable_status(struct platform_device *pdev, u32 vote);
static int hdmi_tx_update_ppm(struct hdmi_tx_ctrl *hdmi_ctrl, s32 ppm);
static int hdmi_tx_enable_pll_update(struct hdmi_tx_ctrl *hdmi_ctrl,
	int enable);

static struct mdss_hw hdmi_tx_hw = {
	.hw_ndx = MDSS_HW_HDMI,
@@ -1368,6 +1370,59 @@ end:
	return ret;
}

static ssize_t hdmi_tx_sysfs_rda_pll_enable(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	ssize_t ret;
	struct hdmi_tx_ctrl *hdmi_ctrl =
		hdmi_tx_get_drvdata_from_sysfs_dev(dev);

	if (!hdmi_ctrl) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	mutex_lock(&hdmi_ctrl->tx_lock);
	ret = snprintf(buf, PAGE_SIZE, "%d\n",
		hdmi_ctrl->pll_update_enable);
	pr_debug("HDMI PLL update: %s\n",
			hdmi_ctrl->pll_update_enable ? "enable" : "disable");

	mutex_unlock(&hdmi_ctrl->tx_lock);

	return ret;
} /* hdmi_tx_sysfs_rda_pll_enable */


static ssize_t hdmi_tx_sysfs_wta_pll_enable(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{
	int enable, rc;
	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;

	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);

	if (!hdmi_ctrl) {
		DEV_ERR("%s: invalid input\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&hdmi_ctrl->tx_lock);

	rc = kstrtoint(buf, 10, &enable);
	if (rc) {
		DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
		goto end;
	}

	hdmi_tx_enable_pll_update(hdmi_ctrl, enable);

	rc = strnlen(buf, PAGE_SIZE);
end:
	mutex_unlock(&hdmi_ctrl->tx_lock);
	return rc;
} /* hdmi_tx_sysfs_wta_pll_enable */

static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
static DEVICE_ATTR(hot_plug, S_IWUSR, NULL, hdmi_tx_sysfs_wta_hot_plug);
static DEVICE_ATTR(sim_mode, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_sim_mode,
@@ -1390,6 +1445,9 @@ static DEVICE_ATTR(5v, S_IWUSR, NULL, hdmi_tx_sysfs_wta_5v);
static DEVICE_ATTR(hdr_stream, S_IWUSR, NULL, hdmi_tx_sysfs_wta_hdr_stream);
static DEVICE_ATTR(hdmi_ppm, S_IRUGO | S_IWUSR, NULL,
	hdmi_tx_sysfs_wta_hdmi_ppm);
static DEVICE_ATTR(pll_enable, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_pll_enable,
	hdmi_tx_sysfs_wta_pll_enable);


static struct attribute *hdmi_tx_fs_attrs[] = {
	&dev_attr_connected.attr,
@@ -1406,6 +1464,7 @@ static struct attribute *hdmi_tx_fs_attrs[] = {
	&dev_attr_5v.attr,
	&dev_attr_hdr_stream.attr,
	&dev_attr_hdmi_ppm.attr,
	&dev_attr_pll_enable.attr,
	NULL,
};
static struct attribute_group hdmi_tx_fs_attrs_group = {
@@ -3628,6 +3687,7 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl)
	hdmi_ctrl->hpd_state = false;
	hdmi_ctrl->hpd_initialized = false;
	hdmi_ctrl->hpd_off_pending = false;
	hdmi_ctrl->pll_update_enable = false;
	init_completion(&hdmi_ctrl->hpd_int_done);

	INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
@@ -3801,6 +3861,11 @@ static int hdmi_tx_update_ppm(struct hdmi_tx_ctrl *hdmi_ctrl, s32 ppm)
		return -EINVAL;
	}

	if (!hdmi_ctrl->pll_update_enable) {
		pr_err("PLL update feature not enabled\n");
		return -EINVAL;
	}

	/* get current pclk */
	cur_pclk = pinfo->clk_rate;
	/* get desired pclk */
@@ -3824,6 +3889,49 @@ static int hdmi_tx_update_ppm(struct hdmi_tx_ctrl *hdmi_ctrl, s32 ppm)
	return rc;
}

static int hdmi_tx_enable_pll_update(struct hdmi_tx_ctrl *hdmi_ctrl,
	int enable)
{
	struct mdss_panel_info *pinfo = NULL;
	int rc = 0;

	if (!hdmi_ctrl) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	/* only available in case HDMI is up */
	if (!hdmi_tx_is_panel_on(hdmi_ctrl)) {
		pr_err("hdmi is not on\n");
		return -EINVAL;
	}

	enable = !!enable;
	if (hdmi_ctrl->pll_update_enable == enable) {
		pr_warn("HDMI PLL update already %s\n",
			hdmi_ctrl->pll_update_enable ? "enabled" : "disabled");
		return -EINVAL;
	}

	pinfo = &hdmi_ctrl->panel_data.panel_info;

	if (!enable && hdmi_ctrl->actual_clk_rate != pinfo->clk_rate) {
		if (hdmi_ctrl->actual_clk_rate) {
			/* reset pixel clock when disable */
			pinfo->clk_rate = hdmi_ctrl->actual_clk_rate;
			rc = hdmi_tx_update_pixel_clk(hdmi_ctrl);
		}
	}

	hdmi_ctrl->actual_clk_rate = pinfo->clk_rate;
	hdmi_ctrl->pll_update_enable = enable;

	pr_debug("HDMI PLL update: %s\n",
			hdmi_ctrl->pll_update_enable ? "enable" : "disable");

	return rc;
}

static int hdmi_tx_evt_handle_register(struct hdmi_tx_ctrl *hdmi_ctrl)
{
	int rc = 0;
@@ -3996,6 +4104,7 @@ static int hdmi_tx_evt_handle_panel_off(struct hdmi_tx_ctrl *hdmi_ctrl)
	}

	hdmi_ctrl->timing_gen_on = false;
	hdmi_ctrl->pll_update_enable = false;
end:
	return rc;
}
+3 −0
Original line number Diff line number Diff line
@@ -143,6 +143,9 @@ struct hdmi_tx_ctrl {

	char disp_switch_name[MAX_SWITCH_NAME_SIZE];

	u64 actual_clk_rate;
	bool pll_update_enable;

	/* pre/post is done in the context without tx_lock */
	hdmi_tx_evt_handler pre_evt_handler[MDSS_EVENT_MAX - 1];
	hdmi_tx_evt_handler evt_handler[MDSS_EVENT_MAX - 1];