Loading drivers/video/msm/mdss/mdss_hdmi_edid.c +33 −6 Original line number Diff line number Diff line Loading @@ -402,11 +402,15 @@ static ssize_t hdmi_edid_sysfs_rda_3d_modes(struct device *dev, if (edid_ctrl->sink_data.num_of_elements) { u32 *video_mode = edid_ctrl->sink_data.disp_mode_list; u32 *video_3d_mode = edid_ctrl->sink_data.disp_3d_mode_list; for (i = 0; i < edid_ctrl->sink_data.num_of_elements; ++i) { ret = hdmi_get_video_3d_fmt_2string(*video_3d_mode++, if (*video_3d_mode == 0) { video_3d_mode++; video_mode++; continue; } hdmi_get_video_3d_fmt_2string(*video_3d_mode++, buff_3d, sizeof(buff_3d)); if (ret > 0) if (ret) ret += scnprintf(buf + ret, PAGE_SIZE - ret, ",%d=%s", *video_mode++, buff_3d); Loading @@ -415,9 +419,6 @@ static ssize_t hdmi_edid_sysfs_rda_3d_modes(struct device *dev, "%d=%s", *video_mode++, buff_3d); } } else { ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%d", edid_ctrl->video_resolution); } DEV_DBG("%s: '%s'\n", __func__, buf); Loading Loading @@ -1860,6 +1861,32 @@ u32 hdmi_edid_get_sink_mode(void *input) return edid_ctrl->sink_mode; } /* hdmi_edid_get_sink_mode */ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) { int i; bool ret = false; struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; struct hdmi_edid_sink_data *sink_data; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return false; } sink_data = &edid_ctrl->sink_data; for (i = 0; i < sink_data->num_of_elements; ++i) { if (sink_data->disp_mode_list[i] != video_mode) continue; if (sink_data->disp_3d_mode_list[i] & (1 << s3d_mode)) ret = true; else DEV_DBG("%s: return false: vic=%d caps=%x s3d=%d\n", __func__, video_mode, sink_data->disp_3d_mode_list[i], s3d_mode); break; } return ret; } int hdmi_edid_get_audio_blk(void *input, struct msm_hdmi_audio_edid_blk *blk) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; Loading drivers/video/msm/mdss/mdss_hdmi_edid.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2015, 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 Loading Loading @@ -33,5 +33,7 @@ int hdmi_edid_get_audio_blk(void *edid_ctrl, void hdmi_edid_set_video_resolution(void *edid_ctrl, u32 resolution); void hdmi_edid_deinit(void *edid_ctrl); void *hdmi_edid_init(struct hdmi_edid_init_data *init_data); bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode); #endif /* __HDMI_EDID_H__ */ drivers/video/msm/mdss/mdss_hdmi_tx.c +107 −24 Original line number Diff line number Diff line Loading @@ -169,6 +169,8 @@ static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl); static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, enum hdmi_tx_power_module_type module, int enable); static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl); static void hdmi_tx_set_vendor_specific_infoframe( struct hdmi_tx_ctrl *hdmi_ctrl); static struct mdss_hw hdmi_tx_hw = { .hw_ndx = MDSS_HW_HDMI, Loading Loading @@ -1001,6 +1003,66 @@ static ssize_t hdmi_tx_sysfs_wta_avi_cn_bits(struct device *dev, return ret; } /* hdmi_tx_sysfs_wta_cn_bits */ static ssize_t hdmi_tx_sysfs_wta_s3d_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int rc, s3d_mode; ssize_t ret = strnlen(buf, PAGE_SIZE); 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; } rc = kstrtoint(buf, 10, &s3d_mode); if (rc) { DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc); return rc; } if (s3d_mode < HDMI_S3D_NONE || s3d_mode >= HDMI_S3D_MAX) { DEV_ERR("%s: invalide s3d mode = %d\n", __func__, s3d_mode); return -EINVAL; } if (s3d_mode > HDMI_S3D_NONE && !hdmi_edid_is_s3d_mode_supported( hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], hdmi_ctrl->video_resolution, s3d_mode)) { DEV_ERR("%s: s3d mode not supported in current video mode\n", __func__); return -EPERM; } hdmi_ctrl->s3d_mode = s3d_mode; hdmi_tx_set_vendor_specific_infoframe(hdmi_ctrl); DEV_DBG("%s: %d\n", __func__, hdmi_ctrl->s3d_mode); return ret; } static ssize_t hdmi_tx_sysfs_rda_s3d_mode(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) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->s3d_mode); DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->s3d_mode); return ret; } static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL); static DEVICE_ATTR(video_mode, S_IRUGO, hdmi_tx_sysfs_rda_video_mode, NULL); static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd, Loading @@ -1012,6 +1074,8 @@ static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR, 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_cn_bits); static DEVICE_ATTR(s3d_mode, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_s3d_mode, hdmi_tx_sysfs_wta_s3d_mode); static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_connected.attr, Loading @@ -1021,6 +1085,7 @@ static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_product_description.attr, &dev_attr_avi_itc.attr, &dev_attr_avi_cn0_1.attr, &dev_attr_s3d_mode.attr, NULL, }; static struct attribute_group hdmi_tx_fs_attrs_group = { Loading Loading @@ -1605,14 +1670,13 @@ static void hdmi_tx_set_avi_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl) DSS_REG_R(io, HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0)); } /* hdmi_tx_set_avi_infoframe */ /* todo: add 3D support */ static void hdmi_tx_set_vendor_specific_infoframe( struct hdmi_tx_ctrl *hdmi_ctrl) { int i; u8 vs_iframe[9]; /* two header + length + 6 data */ u32 sum, reg_val; u32 hdmi_vic, hdmi_video_format; u32 hdmi_vic, hdmi_video_format, s3d_struct = 0; struct dss_io_data *io = NULL; if (!hdmi_ctrl) { Loading @@ -1638,6 +1702,26 @@ static void hdmi_tx_set_vendor_specific_infoframe( vs_iframe[5] = 0x0C; vs_iframe[6] = 0x00; if ((hdmi_ctrl->s3d_mode != HDMI_S3D_NONE) && hdmi_edid_is_s3d_mode_supported( hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], hdmi_ctrl->video_resolution, hdmi_ctrl->s3d_mode)) { switch (hdmi_ctrl->s3d_mode) { case HDMI_S3D_SIDE_BY_SIDE: s3d_struct = 0x8; break; case HDMI_S3D_TOP_AND_BOTTOM: s3d_struct = 0x6; break; default: s3d_struct = 0; } hdmi_video_format = 0x2; hdmi_vic = 0; /* PB5: 3D_Structure[7:4], Reserved[3:0] */ vs_iframe[8] = s3d_struct << 4; } else { hdmi_video_format = 0x1; switch (hdmi_ctrl->video_resolution) { case HDMI_VFRMT_3840x2160p30_16_9: Loading @@ -1656,13 +1740,12 @@ static void hdmi_tx_set_vendor_specific_infoframe( hdmi_video_format = 0x0; hdmi_vic = 0x0; } /* PB5: HDMI_VIC */ vs_iframe[8] = hdmi_vic; } /* PB4: HDMI Video Format[7:5], Reserved[4:0] */ vs_iframe[7] = (hdmi_video_format << 5) & 0xE0; /* PB5: HDMI_VIC or 3D_Structure[7:4], Reserved[3:0] */ vs_iframe[8] = hdmi_vic; /* compute checksum */ sum = 0; for (i = 0; i < 9; i++) Loading @@ -1672,7 +1755,7 @@ static void hdmi_tx_set_vendor_specific_infoframe( sum = 256 - sum; vs_iframe[3] = (u8)sum; reg_val = (hdmi_vic << 16) | (vs_iframe[3] << 8) | reg_val = (s3d_struct << 24) | (hdmi_vic << 16) | (vs_iframe[3] << 8) | (hdmi_video_format << 5) | vs_iframe[2]; DSS_REG_W(io, HDMI_VENSPEC_INFO0, reg_val); Loading drivers/video/msm/mdss/mdss_hdmi_tx.h +1 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ struct hdmi_tx_ctrl { void *downstream_data; void *feature_data[HDMI_TX_FEAT_MAX]; u32 s3d_mode; }; #endif /* __MDSS_HDMI_TX_H__ */ drivers/video/msm/mdss/mdss_hdmi_util.h +3 −3 Original line number Diff line number Diff line Loading @@ -225,9 +225,9 @@ #define HDCP_KSV_LSB (0x000060D8) #define HDCP_KSV_MSB (0x000060DC) #define TOP_AND_BOTTOM 0x10 #define FRAME_PACKING 0x20 #define SIDE_BY_SIDE_HALF 0x40 #define TOP_AND_BOTTOM (1 << HDMI_S3D_TOP_AND_BOTTOM) #define FRAME_PACKING (1 << HDMI_S3D_FRAME_PACKING) #define SIDE_BY_SIDE_HALF (1 << HDMI_S3D_SIDE_BY_SIDE) #define LPASS_LPAIF_RDDMA_CTL0 (0xFE152000) #define LPASS_LPAIF_RDDMA_PER_CNT0 (0x00000014) Loading Loading
drivers/video/msm/mdss/mdss_hdmi_edid.c +33 −6 Original line number Diff line number Diff line Loading @@ -402,11 +402,15 @@ static ssize_t hdmi_edid_sysfs_rda_3d_modes(struct device *dev, if (edid_ctrl->sink_data.num_of_elements) { u32 *video_mode = edid_ctrl->sink_data.disp_mode_list; u32 *video_3d_mode = edid_ctrl->sink_data.disp_3d_mode_list; for (i = 0; i < edid_ctrl->sink_data.num_of_elements; ++i) { ret = hdmi_get_video_3d_fmt_2string(*video_3d_mode++, if (*video_3d_mode == 0) { video_3d_mode++; video_mode++; continue; } hdmi_get_video_3d_fmt_2string(*video_3d_mode++, buff_3d, sizeof(buff_3d)); if (ret > 0) if (ret) ret += scnprintf(buf + ret, PAGE_SIZE - ret, ",%d=%s", *video_mode++, buff_3d); Loading @@ -415,9 +419,6 @@ static ssize_t hdmi_edid_sysfs_rda_3d_modes(struct device *dev, "%d=%s", *video_mode++, buff_3d); } } else { ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%d", edid_ctrl->video_resolution); } DEV_DBG("%s: '%s'\n", __func__, buf); Loading Loading @@ -1860,6 +1861,32 @@ u32 hdmi_edid_get_sink_mode(void *input) return edid_ctrl->sink_mode; } /* hdmi_edid_get_sink_mode */ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) { int i; bool ret = false; struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; struct hdmi_edid_sink_data *sink_data; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return false; } sink_data = &edid_ctrl->sink_data; for (i = 0; i < sink_data->num_of_elements; ++i) { if (sink_data->disp_mode_list[i] != video_mode) continue; if (sink_data->disp_3d_mode_list[i] & (1 << s3d_mode)) ret = true; else DEV_DBG("%s: return false: vic=%d caps=%x s3d=%d\n", __func__, video_mode, sink_data->disp_3d_mode_list[i], s3d_mode); break; } return ret; } int hdmi_edid_get_audio_blk(void *input, struct msm_hdmi_audio_edid_blk *blk) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; Loading
drivers/video/msm/mdss/mdss_hdmi_edid.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2015, 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 Loading Loading @@ -33,5 +33,7 @@ int hdmi_edid_get_audio_blk(void *edid_ctrl, void hdmi_edid_set_video_resolution(void *edid_ctrl, u32 resolution); void hdmi_edid_deinit(void *edid_ctrl); void *hdmi_edid_init(struct hdmi_edid_init_data *init_data); bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode); #endif /* __HDMI_EDID_H__ */
drivers/video/msm/mdss/mdss_hdmi_tx.c +107 −24 Original line number Diff line number Diff line Loading @@ -169,6 +169,8 @@ static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl); static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, enum hdmi_tx_power_module_type module, int enable); static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl); static void hdmi_tx_set_vendor_specific_infoframe( struct hdmi_tx_ctrl *hdmi_ctrl); static struct mdss_hw hdmi_tx_hw = { .hw_ndx = MDSS_HW_HDMI, Loading Loading @@ -1001,6 +1003,66 @@ static ssize_t hdmi_tx_sysfs_wta_avi_cn_bits(struct device *dev, return ret; } /* hdmi_tx_sysfs_wta_cn_bits */ static ssize_t hdmi_tx_sysfs_wta_s3d_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int rc, s3d_mode; ssize_t ret = strnlen(buf, PAGE_SIZE); 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; } rc = kstrtoint(buf, 10, &s3d_mode); if (rc) { DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc); return rc; } if (s3d_mode < HDMI_S3D_NONE || s3d_mode >= HDMI_S3D_MAX) { DEV_ERR("%s: invalide s3d mode = %d\n", __func__, s3d_mode); return -EINVAL; } if (s3d_mode > HDMI_S3D_NONE && !hdmi_edid_is_s3d_mode_supported( hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], hdmi_ctrl->video_resolution, s3d_mode)) { DEV_ERR("%s: s3d mode not supported in current video mode\n", __func__); return -EPERM; } hdmi_ctrl->s3d_mode = s3d_mode; hdmi_tx_set_vendor_specific_infoframe(hdmi_ctrl); DEV_DBG("%s: %d\n", __func__, hdmi_ctrl->s3d_mode); return ret; } static ssize_t hdmi_tx_sysfs_rda_s3d_mode(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) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->s3d_mode); DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->s3d_mode); return ret; } static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL); static DEVICE_ATTR(video_mode, S_IRUGO, hdmi_tx_sysfs_rda_video_mode, NULL); static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd, Loading @@ -1012,6 +1074,8 @@ static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR, 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_cn_bits); static DEVICE_ATTR(s3d_mode, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_s3d_mode, hdmi_tx_sysfs_wta_s3d_mode); static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_connected.attr, Loading @@ -1021,6 +1085,7 @@ static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_product_description.attr, &dev_attr_avi_itc.attr, &dev_attr_avi_cn0_1.attr, &dev_attr_s3d_mode.attr, NULL, }; static struct attribute_group hdmi_tx_fs_attrs_group = { Loading Loading @@ -1605,14 +1670,13 @@ static void hdmi_tx_set_avi_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl) DSS_REG_R(io, HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0)); } /* hdmi_tx_set_avi_infoframe */ /* todo: add 3D support */ static void hdmi_tx_set_vendor_specific_infoframe( struct hdmi_tx_ctrl *hdmi_ctrl) { int i; u8 vs_iframe[9]; /* two header + length + 6 data */ u32 sum, reg_val; u32 hdmi_vic, hdmi_video_format; u32 hdmi_vic, hdmi_video_format, s3d_struct = 0; struct dss_io_data *io = NULL; if (!hdmi_ctrl) { Loading @@ -1638,6 +1702,26 @@ static void hdmi_tx_set_vendor_specific_infoframe( vs_iframe[5] = 0x0C; vs_iframe[6] = 0x00; if ((hdmi_ctrl->s3d_mode != HDMI_S3D_NONE) && hdmi_edid_is_s3d_mode_supported( hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], hdmi_ctrl->video_resolution, hdmi_ctrl->s3d_mode)) { switch (hdmi_ctrl->s3d_mode) { case HDMI_S3D_SIDE_BY_SIDE: s3d_struct = 0x8; break; case HDMI_S3D_TOP_AND_BOTTOM: s3d_struct = 0x6; break; default: s3d_struct = 0; } hdmi_video_format = 0x2; hdmi_vic = 0; /* PB5: 3D_Structure[7:4], Reserved[3:0] */ vs_iframe[8] = s3d_struct << 4; } else { hdmi_video_format = 0x1; switch (hdmi_ctrl->video_resolution) { case HDMI_VFRMT_3840x2160p30_16_9: Loading @@ -1656,13 +1740,12 @@ static void hdmi_tx_set_vendor_specific_infoframe( hdmi_video_format = 0x0; hdmi_vic = 0x0; } /* PB5: HDMI_VIC */ vs_iframe[8] = hdmi_vic; } /* PB4: HDMI Video Format[7:5], Reserved[4:0] */ vs_iframe[7] = (hdmi_video_format << 5) & 0xE0; /* PB5: HDMI_VIC or 3D_Structure[7:4], Reserved[3:0] */ vs_iframe[8] = hdmi_vic; /* compute checksum */ sum = 0; for (i = 0; i < 9; i++) Loading @@ -1672,7 +1755,7 @@ static void hdmi_tx_set_vendor_specific_infoframe( sum = 256 - sum; vs_iframe[3] = (u8)sum; reg_val = (hdmi_vic << 16) | (vs_iframe[3] << 8) | reg_val = (s3d_struct << 24) | (hdmi_vic << 16) | (vs_iframe[3] << 8) | (hdmi_video_format << 5) | vs_iframe[2]; DSS_REG_W(io, HDMI_VENSPEC_INFO0, reg_val); Loading
drivers/video/msm/mdss/mdss_hdmi_tx.h +1 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ struct hdmi_tx_ctrl { void *downstream_data; void *feature_data[HDMI_TX_FEAT_MAX]; u32 s3d_mode; }; #endif /* __MDSS_HDMI_TX_H__ */
drivers/video/msm/mdss/mdss_hdmi_util.h +3 −3 Original line number Diff line number Diff line Loading @@ -225,9 +225,9 @@ #define HDCP_KSV_LSB (0x000060D8) #define HDCP_KSV_MSB (0x000060DC) #define TOP_AND_BOTTOM 0x10 #define FRAME_PACKING 0x20 #define SIDE_BY_SIDE_HALF 0x40 #define TOP_AND_BOTTOM (1 << HDMI_S3D_TOP_AND_BOTTOM) #define FRAME_PACKING (1 << HDMI_S3D_FRAME_PACKING) #define SIDE_BY_SIDE_HALF (1 << HDMI_S3D_SIDE_BY_SIDE) #define LPASS_LPAIF_RDDMA_CTL0 (0xFE152000) #define LPASS_LPAIF_RDDMA_PER_CNT0 (0x00000014) Loading