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

Commit ca161748 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: clean up cn/itc bit set/unset"

parents f7a76a88 ddaee9dd
Loading
Loading
Loading
Loading
+72 −79
Original line number Diff line number Diff line
@@ -70,6 +70,24 @@ static bool hdcp_feature_on = true;
#define MSM_HDMI_AUDIO_CHANNEL_7	7
#define MSM_HDMI_AUDIO_CHANNEL_8	8

#define NUM_MODES_AVI 20

/* AVI Infoframe data byte 3, bit 7 (msb) represents ITC bit */
#define SET_ITC_BIT(byte)  (byte = (byte | BIT(7)))
#define CLR_ITC_BIT(byte)  (byte = (byte & ~BIT(7)))

/*
 * CN represents IT content type, if ITC bit in infoframe data byte 3
 * is set, CN bits will represent content type as below:
 * 0b00 Graphics
 * 0b01 Photo
 * 0b10 Cinema
 * 0b11 Game
*/
#define CONFIG_CN_BITS(bits, byte) \
		(byte = (byte & ~(BIT(4) | BIT(5))) |\
			((bits & (BIT(0) | BIT(1))) << 4))

enum msm_hdmi_supported_audio_sample_rates {
	AUDIO_SAMPLE_RATE_32KHZ,
	AUDIO_SAMPLE_RATE_44_1KHZ,
@@ -138,12 +156,6 @@ const char *hdmi_pm_name(enum hdmi_tx_power_module_type module)
	}
} /* hdmi_pm_name */

static DEFINE_MUTEX(avi_iframe_lut_lock);
#define NUM_MODES_AVI 20
#define SET_ITC_BIT(byte)  (byte | 0x80)
#define CLR_ITC_BIT(byte)  (byte & 0x7F)
#define CONFIG_CN_BITS(bits, byte)  ((byte & ~(0x03 << 4)) | (bits << 4))

static u8 hdmi_tx_avi_iframe_lut[][NUM_MODES_AVI] = {
	{0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,
	 0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,
@@ -211,55 +223,6 @@ static const struct hdmi_tx_audio_acr_arry hdmi_tx_audio_acr_lut[] = {
		{20480, 247500} } },
};

/* To statically config ITC bit from sysfs attribute */
static int hdmi_tx_config_itc_bit(int itc)
{
	int ret = 0, loop = NUM_MODES_AVI;

	if (mutex_lock_interruptible(&avi_iframe_lut_lock)) {
		ret = -ERESTARTSYS;
		goto signal_intr;
	}

	do {
		--loop;
		if (itc == 0)
			hdmi_tx_avi_iframe_lut[2][loop] =
				CLR_ITC_BIT(hdmi_tx_avi_iframe_lut[2][loop]);
		if (itc == 1)
			hdmi_tx_avi_iframe_lut[2][loop] =
				SET_ITC_BIT(hdmi_tx_avi_iframe_lut[2][loop]);
	} while (loop);

	mutex_unlock(&avi_iframe_lut_lock);

signal_intr:
	return ret;
}

/* To configure CN0_1 bits from sysfs attribute */
static int hdmi_tx_config_cn_bits(int cns)
{
	int ret = 0, loop = NUM_MODES_AVI;

	if (mutex_lock_interruptible(&avi_iframe_lut_lock)) {
		ret = -ERESTARTSYS;
		goto signal_intr;
	}

	do {
		--loop;
		hdmi_tx_avi_iframe_lut[4][loop] =
			CONFIG_CN_BITS(cns, hdmi_tx_avi_iframe_lut[4][loop]);
	} while (loop);

	mutex_unlock(&avi_iframe_lut_lock);

signal_intr:
	return ret;
}


static bool hdmi_tx_is_cea_format(int mode)
{
	bool cea_fmt;
@@ -683,8 +646,16 @@ static ssize_t hdmi_tx_sysfs_wta_avi_itc(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{
	ssize_t ret = strnlen(buf, PAGE_SIZE);
	int err = 0;
	int itc = 0, rc = 0;
	u8 *avi_byte3 = hdmi_tx_avi_iframe_lut[2];
	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
	int loop = 0, itc = 0, rc = 0;

	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);

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

	rc = kstrtoint(buf, 10, &itc);
	if (rc) {
@@ -692,44 +663,63 @@ static ssize_t hdmi_tx_sysfs_wta_avi_itc(struct device *dev,
		return rc;
	}

	if (itc == 0 || itc == 1) {
		if (hdmi_tx_config_itc_bit(itc))
			ret = err;
	if (itc < 0 || itc > 1) {
		DEV_ERR("%s: Invalid ITC %d\n", __func__, itc);
		return ret;
	}

	if (mutex_lock_interruptible(&hdmi_ctrl->lut_lock))
		return -ERESTARTSYS;

	for (loop = 0; loop < NUM_MODES_AVI; loop++) {
		if (itc)
			SET_ITC_BIT(avi_byte3[loop]);
		else
			DEV_DBG("%s: '%d is configured'!\n", __func__, itc);
	} else {
		DEV_ERR("%s: unknown ITC '%d', should be either 0 or 1\n",
				__func__, itc);
			CLR_ITC_BIT(avi_byte3[loop]);
	}

	mutex_unlock(&hdmi_ctrl->lut_lock);

	return ret;
} /* hdmi_tx_sysfs_wta_avi_itc */

static ssize_t hdmi_tx_sysfs_wta_avi_cn0_1(struct device *dev,
static ssize_t hdmi_tx_sysfs_wta_avi_cn_bits(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{
	ssize_t ret = strnlen(buf, PAGE_SIZE);
	int err = 0;
	int cns = 0, rc = 0;
	u8 *avi_byte5 = hdmi_tx_avi_iframe_lut[4];
	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
	int loop = 0, cn_bits = 0, rc = 0;

	rc = kstrtoint(buf, 10, &cns);
	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);

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

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

	if (cns == 0 || cns == 1 || cns == 2 || cns == 3) {
		if (hdmi_tx_config_cn_bits(cns))
			ret = err;
		else
			DEV_DBG("%s: '%d is configured'!\n", __func__, cns);
	} else {
		DEV_ERR("%s: unknown CN '%d' should be either 0 or 1, 2 ,3\n",
				__func__, cns);
	/* As per CEA-861-E, CN is a positive number and can be max 3 */
	if (cn_bits < 0 || cn_bits > 3) {
		DEV_ERR("%s: Invalid CN %d\n", __func__, cn_bits);
		return ret;
	}

	if (mutex_lock_interruptible(&hdmi_ctrl->lut_lock))
		return -ERESTARTSYS;

	for (loop = 0; loop < NUM_MODES_AVI; loop++)
		CONFIG_CN_BITS(cn_bits, avi_byte5[loop]);

	mutex_unlock(&hdmi_ctrl->lut_lock);

	return ret;
} /* hdmi_tx_sysfs_wta_avi_cn0_1 */
} /* hdmi_tx_sysfs_wta_cn_bits */

static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd,
@@ -740,7 +730,7 @@ static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR,
	hdmi_tx_sysfs_rda_product_description,
	hdmi_tx_sysfs_wta_product_description);
static DEVICE_ATTR(avi_itc, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_itc);
static DEVICE_ATTR(avi_cn0_1, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_cn0_1);
static DEVICE_ATTR(avi_cn0_1, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_cn_bits);

static struct attribute *hdmi_tx_fs_attrs[] = {
	&dev_attr_connected.attr,
@@ -2852,6 +2842,7 @@ static void hdmi_tx_dev_deinit(struct hdmi_tx_ctrl *hdmi_ctrl)
	switch_dev_unregister(&hdmi_ctrl->sdev);
	if (hdmi_ctrl->workq)
		destroy_workqueue(hdmi_ctrl->workq);
	mutex_destroy(&hdmi_ctrl->lut_lock);
	mutex_destroy(&hdmi_ctrl->mutex);

	hdmi_tx_hw.ptr = NULL;
@@ -2880,6 +2871,7 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl)

	hdmi_setup_video_mode_lut();
	mutex_init(&hdmi_ctrl->mutex);
	mutex_init(&hdmi_ctrl->lut_lock);
	hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
	if (!hdmi_ctrl->workq) {
		DEV_ERR("%s: hdmi_tx_workq creation failed.\n", __func__);
@@ -2928,6 +2920,7 @@ fail_audio_switch_dev:
fail_create_workq:
	if (hdmi_ctrl->workq)
		destroy_workqueue(hdmi_ctrl->workq);
	mutex_destroy(&hdmi_ctrl->lut_lock);
	mutex_destroy(&hdmi_ctrl->mutex);
fail_no_hdmi:
	return rc;
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ struct hdmi_tx_ctrl {
	struct hdmi_audio audio_data;

	struct mutex mutex;
	struct mutex lut_lock;
	struct kobject *kobj;
	struct switch_dev sdev;
	struct switch_dev audio_sdev;