Loading drivers/video/msm/mdss/mdss_hdmi_tx.c +72 −79 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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, Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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__); Loading Loading @@ -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; Loading drivers/video/msm/mdss/mdss_hdmi_tx.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
drivers/video/msm/mdss/mdss_hdmi_tx.c +72 −79 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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, Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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__); Loading Loading @@ -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; Loading
drivers/video/msm/mdss/mdss_hdmi_tx.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading