summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjay Singh Parmar <aparmar@codeaurora.org>2013-12-01 00:41:45 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:23:56 -0700
commit1d4a32fdf7ecf10371c2aa380e1ff820c1a11489 (patch)
treee7ebf3b0d13e21bb18b3f5bce904aba7ba21f8c8
parente9be7342901c7a1e55b118c5781522f116ef6419 (diff)
msm: mdss: hdmi: clean up cn/itc bit set/unset
Properly set/unset the ITC/CN bits by using proper mutex, error checks and other cleanup things. Change-Id: I2730689dc70df1bce65bb1699938ce7793937688 Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c151
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.h1
2 files changed, 73 insertions, 79 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index fc29ef2ca2af..2aa2d917b3fb 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -67,6 +67,24 @@ static bool hdcp_feature_on = true;
#define MSM_HDMI_AUDIO_CHANNEL_6 6
#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,
@@ -135,12 +153,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,
@@ -208,55 +220,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;
@@ -680,53 +643,80 @@ 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) {
- DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+ DEV_ERR("%s: kstrtoint failed. rc =%d\n", __func__, rc);
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,
@@ -737,7 +727,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,
@@ -2846,6 +2836,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;
@@ -2874,6 +2865,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__);
@@ -2922,6 +2914,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;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h
index 66071e94fce1..0787deeb491a 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h
@@ -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;