Loading drivers/video/fbdev/msm/mdss_hdmi_edid.c +7 −7 Original line number Diff line number Diff line Loading @@ -216,7 +216,7 @@ static int hdmi_edid_reset_parser(struct hdmi_edid_ctrl *edid_ctrl) /* reset HDR related data */ edid_ctrl->hdr_supported = false; edid_ctrl->hdr_data.eotf = 0; edid_ctrl->hdr_data.descriptor = 0; edid_ctrl->hdr_data.metadata_type_one = false; edid_ctrl->hdr_data.max_luminance = 0; edid_ctrl->hdr_data.avg_luminance = 0; edid_ctrl->hdr_data.min_luminance = 0; Loading Loading @@ -794,7 +794,7 @@ static ssize_t hdmi_edid_sysfs_rda_hdr_data(struct device *dev, ret = scnprintf(buf, PAGE_SIZE, "%d, %u, %u, %u, %u, %u\n", edid_ctrl->hdr_supported, edid_ctrl->hdr_data.eotf, edid_ctrl->hdr_data.descriptor, edid_ctrl->hdr_data.metadata_type_one, edid_ctrl->hdr_data.max_luminance, edid_ctrl->hdr_data.avg_luminance, edid_ctrl->hdr_data.min_luminance); Loading Loading @@ -964,8 +964,8 @@ static void hdmi_edid_parse_hdrdb(struct hdmi_edid_ctrl *edid_ctrl, /* Byte 3: Electro-Optical Transfer Functions */ edid_ctrl->hdr_data.eotf = data_block[2] & 0x3F; /* Byte 4: Static Metadata Descriptors */ edid_ctrl->hdr_data.descriptor = data_block[3] & 0x1; /* Byte 4: Static Metadata Descriptor Type 1 */ edid_ctrl->hdr_data.metadata_type_one = (data_block[3] & 0x1) & BIT(0); /* Byte 5: Desired Content Maximum Luminance */ if (hdmi_edid_is_luminance_value_present(len, MAXIMUM_LUMINANCE)) Loading Loading @@ -2458,16 +2458,16 @@ u8 hdmi_edid_get_deep_color(void *input) * Return: HDR data. */ void hdmi_edid_get_hdr_data(void *input, struct hdmi_edid_hdr_data *hdr_data) struct hdmi_edid_hdr_data **hdr_data) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; if (!edid_ctrl || !hdr_data) { if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return; } hdr_data = &edid_ctrl->hdr_data; *hdr_data = &edid_ctrl->hdr_data; } bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) Loading drivers/video/fbdev/msm/mdss_hdmi_edid.h +3 −3 Original line number Diff line number Diff line Loading @@ -31,14 +31,14 @@ struct hdmi_edid_init_data { /* * struct hdmi_edid_hdr_data - HDR Static Metadata * @eotf: Electro-Optical Transfer Function * @descriptor: Static Metadata Descriptor * @metadata_type_one: Static Metadata Type 1 support * @max_luminance: Desired Content Maximum Luminance * @avg_luminance: Desired Content Frame-average Luminance * @min_luminance: Desired Content Minimum Luminance */ struct hdmi_edid_hdr_data { u32 eotf; u32 descriptor; bool metadata_type_one; u32 max_luminance; u32 avg_luminance; u32 min_luminance; Loading @@ -61,6 +61,6 @@ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode); u8 hdmi_edid_get_deep_color(void *edid_ctrl); void hdmi_edid_get_hdr_data(void *edid_ctrl, struct hdmi_edid_hdr_data *hdr_data); struct hdmi_edid_hdr_data **hdr_data); #endif /* __HDMI_EDID_H__ */ drivers/video/fbdev/msm/mdss_hdmi_tx.c +208 −17 Original line number Diff line number Diff line Loading @@ -79,6 +79,8 @@ #define HDMI_TX_MAX_FPS 120000 #define HDMI_TX_VERSION_403 0x40000003 /* msmcobalt */ #define HDMI_GET_MSB(x) (x >> 8) #define HDMI_GET_LSB(x) (x & 0xff) /* Enable HDCP by default */ static bool hdcp_feature_on = true; Loading Loading @@ -111,6 +113,9 @@ 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_setup_tmds_clk_rate(struct hdmi_tx_ctrl *hdmi_ctrl); static void hdmi_tx_fps_work(struct work_struct *work); static int hdmi_tx_pinctrl_set_state(struct hdmi_tx_ctrl *hdmi_ctrl, enum hdmi_tx_power_module_type module, bool active); static void hdmi_panel_set_hdr_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl); static struct mdss_hw hdmi_tx_hw = { .hw_ndx = MDSS_HW_HDMI, Loading Loading @@ -285,6 +290,29 @@ static inline bool hdmi_tx_is_hdcp_enabled(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_ctrl->hdcp_ops; } /* * The sink must support at least one electro-optical transfer function for * HDMI controller to sendi the dynamic range and mastering infoframe. */ static inline bool hdmi_tx_is_hdr_supported(struct hdmi_tx_ctrl *hdmi_ctrl) { struct hdmi_edid_hdr_data *hdr_data; hdmi_edid_get_hdr_data(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID), &hdr_data); return (hdr_data->eotf & BIT(0)) || (hdr_data->eotf & BIT(1)) || (hdr_data->eotf & BIT(2)); } static inline bool hdmi_tx_metadata_type_one(struct hdmi_tx_ctrl *hdmi_ctrl) { struct hdmi_edid_hdr_data *hdr_data; hdmi_edid_get_hdr_data(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID), &hdr_data); return hdr_data->metadata_type_one; } static inline bool hdmi_tx_dc_support(struct hdmi_tx_ctrl *hdmi_ctrl) { return hdmi_ctrl->dc_feature_on && hdmi_ctrl->dc_support && Loading Loading @@ -478,25 +506,30 @@ void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, } /* hdmi_tx_get_featuredata_from_sysfs_dev */ EXPORT_SYMBOL(hdmi_get_featuredata_from_sysfs_dev); static int hdmi_tx_config_5v(struct hdmi_tx_ctrl *hdmi_ctrl, bool enable) static int hdmi_tx_config_5v(struct hdmi_tx_ctrl *ctrl, bool enable) { struct dss_module_power *pd = NULL; int ret = 0; struct dss_module_power *pd = NULL; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); if (!ctrl) { DEV_ERR("%s: Invalid HDMI ctrl\n", __func__); ret = -EINVAL; goto end; } pd = &hdmi_ctrl->pdata.power_data[HDMI_TX_HPD_PM]; if (ctrl->hdmi_tx_version >= HDMI_TX_VERSION_403) ret = hdmi_tx_pinctrl_set_state(ctrl, HDMI_TX_HPD_PM, enable); else { pd = &ctrl->pdata.power_data[HDMI_TX_HPD_PM]; if (!pd || !pd->gpio_config) { DEV_ERR("%s: Error: invalid power data\n", __func__); DEV_ERR("%s: Invalid power data\n", __func__); ret = -EINVAL; goto end; } gpio_set_value(pd->gpio_config->gpio, enable); } end: return ret; } Loading Loading @@ -1220,12 +1253,6 @@ static ssize_t hdmi_tx_sysfs_wta_5v(struct device *dev, } mutex_lock(&hdmi_ctrl->tx_lock); pd = &hdmi_ctrl->pdata.power_data[HDMI_TX_HPD_PM]; if (!pd || !pd->gpio_config) { DEV_ERR("%s: Error: invalid power data\n", __func__); ret = -EINVAL; goto end; } ret = kstrtoint(buf, 10, &read); if (ret) { Loading @@ -1245,6 +1272,72 @@ end: return ret; } static ssize_t hdmi_tx_sysfs_wta_hdr_stream(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int ret = 0; u32 const hdr_param_count = 13; struct hdmi_tx_ctrl *ctrl = NULL; ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev); if (!ctrl) { pr_err("%s: invalid input\n", __func__); ret = -EINVAL; goto end; } if (!hdmi_tx_is_hdr_supported(ctrl)) { pr_err("%s: Sink does not support HDR\n", __func__); ret = -EINVAL; goto end; } if (sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u %u", &ctrl->hdr_data.eotf, &ctrl->hdr_data.display_primaries_x[0], &ctrl->hdr_data.display_primaries_y[0], &ctrl->hdr_data.display_primaries_x[1], &ctrl->hdr_data.display_primaries_y[1], &ctrl->hdr_data.display_primaries_x[2], &ctrl->hdr_data.display_primaries_y[2], &ctrl->hdr_data.white_point_x, &ctrl->hdr_data.white_point_y, &ctrl->hdr_data.max_luminance, &ctrl->hdr_data.min_luminance, &ctrl->hdr_data.max_content_light_level, &ctrl->hdr_data.max_average_light_level) != hdr_param_count) { pr_err("%s: Invalid HDR stream data\n", __func__); ret = -EINVAL; goto end; } pr_debug("%s: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n", __func__, ctrl->hdr_data.eotf, ctrl->hdr_data.display_primaries_x[0], ctrl->hdr_data.display_primaries_y[0], ctrl->hdr_data.display_primaries_x[1], ctrl->hdr_data.display_primaries_y[1], ctrl->hdr_data.display_primaries_x[2], ctrl->hdr_data.display_primaries_y[2]); pr_debug("%s: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n", __func__, ctrl->hdr_data.white_point_x, ctrl->hdr_data.white_point_y, ctrl->hdr_data.max_luminance, ctrl->hdr_data.min_luminance, ctrl->hdr_data.max_content_light_level, ctrl->hdr_data.max_average_light_level); hdmi_panel_set_hdr_infoframe(ctrl); ret = strnlen(buf, PAGE_SIZE); end: return ret; } static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL); static DEVICE_ATTR(hdmi_audio_cb, S_IWUSR, NULL, hdmi_tx_sysfs_wta_audio_cb); static DEVICE_ATTR(hot_plug, S_IWUSR, NULL, hdmi_tx_sysfs_wta_hot_plug); Loading @@ -1265,6 +1358,7 @@ 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 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 struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_connected.attr, Loading @@ -1280,6 +1374,7 @@ static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_avi_cn0_1.attr, &dev_attr_s3d_mode.attr, &dev_attr_5v.attr, &dev_attr_hdr_stream.attr, NULL, }; static struct attribute_group hdmi_tx_fs_attrs_group = { Loading Loading @@ -2209,7 +2304,7 @@ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl) DEV_DBG("%s: Features <HDMI:%s, HDCP:%s, Deep Color:%s>\n", __func__, hdmi_disabled ? "OFF" : "ON", hdcp_disabled ? "OFF" : "ON", hdmi_ctrl->dc_feature_on ? "OFF" : "ON"); !hdmi_ctrl->dc_feature_on ? "OFF" : "ON"); if (hdmi_disabled) { DEV_ERR("%s: HDMI disabled\n", __func__); Loading Loading @@ -2635,6 +2730,102 @@ static void hdmi_tx_phy_reset(struct hdmi_tx_ctrl *hdmi_ctrl) DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET_PLL); } /* hdmi_tx_phy_reset */ static void hdmi_panel_set_hdr_infoframe(struct hdmi_tx_ctrl *ctrl) { u32 packet_payload = 0; u32 packet_header = 0; u32 packet_control = 0; u32 const type_code = 0x87; u32 const version = 0x01; u32 const length = 0x1a; u32 const descriptor_id = 0x00; struct dss_io_data *io = NULL; if (!ctrl) { pr_err("%s: invalid input\n", __func__); return; } if (!hdmi_tx_is_hdr_supported(ctrl)) { pr_err("%s: Sink does not support HDR\n", __func__); return; } io = &ctrl->pdata.io[HDMI_TX_CORE_IO]; if (!io->base) { pr_err("%s: core io not inititalized\n", __func__); return; } /* Setup Packet header and payload */ packet_header = type_code | (version << 8) | (length << 16); DSS_REG_W(io, HDMI_GENERIC0_HDR, packet_header); packet_payload = (ctrl->hdr_data.eotf << 8); if (hdmi_tx_metadata_type_one(ctrl)) { packet_payload |= (descriptor_id << 16) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[0]) << 24); DSS_REG_W(io, HDMI_GENERIC0_0, packet_payload); } else { pr_debug("%s: Metadata Type 1 not supported\n", __func__); DSS_REG_W(io, HDMI_GENERIC0_0, packet_payload); goto enable_packet_control; } packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[0])) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[0]) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[0]) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[1]) << 24); DSS_REG_W(io, HDMI_GENERIC0_1, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[1])) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[1]) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[1]) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[2]) << 24); DSS_REG_W(io, HDMI_GENERIC0_2, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[2])) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[2]) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[2]) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.white_point_x) << 24); DSS_REG_W(io, HDMI_GENERIC0_3, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.white_point_x)) | (HDMI_GET_LSB(ctrl->hdr_data.white_point_y) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.white_point_y) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.max_luminance) << 24); DSS_REG_W(io, HDMI_GENERIC0_4, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.max_luminance)) | (HDMI_GET_LSB(ctrl->hdr_data.min_luminance) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.min_luminance) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.max_content_light_level) << 24); DSS_REG_W(io, HDMI_GENERIC0_5, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.max_content_light_level)) | (HDMI_GET_LSB(ctrl->hdr_data.max_average_light_level) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.max_average_light_level) << 16); DSS_REG_W(io, HDMI_GENERIC0_6, packet_payload); enable_packet_control: /* * GENERIC0_LINE | GENERIC0_CONT | GENERIC0_SEND * Setup HDMI TX generic packet control * Enable this packet to transmit every frame * Enable HDMI TX engine to transmit Generic packet 1 */ packet_control = DSS_REG_R_ND(io, HDMI_GEN_PKT_CTRL); packet_control |= BIT(0) | BIT(1) | BIT(2) | BIT(16); DSS_REG_W(io, HDMI_GEN_PKT_CTRL, packet_control); } static int hdmi_tx_audio_info_setup(struct platform_device *pdev, struct msm_ext_disp_audio_setup_params *params) { Loading drivers/video/fbdev/msm/mdss_hdmi_tx.h +26 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "mdss_hdmi_audio.h" #define MAX_SWITCH_NAME_SIZE 5 #define HDR_PRIMARIES_COUNT 3 enum hdmi_tx_io_type { HDMI_TX_CORE_IO, Loading Loading @@ -61,6 +62,30 @@ struct hdmi_tx_pinctrl { struct hdmi_tx_ctrl; typedef int (*hdmi_tx_evt_handler) (struct hdmi_tx_ctrl *); /* * struct hdmi_tx_hdr_stream - HDR video stream characteristics * @eotf: Electro-Optical Transfer Function * @display_primaries_x: display primaries data for x-coordinate * @display_primaries_y: display primaries data for y-coordinate * @white_point_x: white point data for x-coordinate * @white_point_y: white point data for y-coordinate * @max_luminance: content maximum luminance * @min_luminance: content minimum luminance * @max_content_light_level: content maximum light level * @max_average_light_level: content average light level */ struct hdmi_tx_hdr_stream_data { u32 eotf; u32 display_primaries_x[HDR_PRIMARIES_COUNT]; u32 display_primaries_y[HDR_PRIMARIES_COUNT]; u32 white_point_x; u32 white_point_y; u32 max_luminance; u32 min_luminance; u32 max_content_light_level; u32 max_average_light_level; }; struct hdmi_tx_ctrl { struct platform_device *pdev; struct hdmi_tx_platform_data pdata; Loading Loading @@ -88,6 +113,7 @@ struct hdmi_tx_ctrl { struct hdmi_panel_ops panel_ops; struct msm_ext_disp_audio_setup_params audio_params; struct work_struct fps_work; struct hdmi_tx_hdr_stream_data hdr_data; spinlock_t hpd_state_lock; Loading Loading
drivers/video/fbdev/msm/mdss_hdmi_edid.c +7 −7 Original line number Diff line number Diff line Loading @@ -216,7 +216,7 @@ static int hdmi_edid_reset_parser(struct hdmi_edid_ctrl *edid_ctrl) /* reset HDR related data */ edid_ctrl->hdr_supported = false; edid_ctrl->hdr_data.eotf = 0; edid_ctrl->hdr_data.descriptor = 0; edid_ctrl->hdr_data.metadata_type_one = false; edid_ctrl->hdr_data.max_luminance = 0; edid_ctrl->hdr_data.avg_luminance = 0; edid_ctrl->hdr_data.min_luminance = 0; Loading Loading @@ -794,7 +794,7 @@ static ssize_t hdmi_edid_sysfs_rda_hdr_data(struct device *dev, ret = scnprintf(buf, PAGE_SIZE, "%d, %u, %u, %u, %u, %u\n", edid_ctrl->hdr_supported, edid_ctrl->hdr_data.eotf, edid_ctrl->hdr_data.descriptor, edid_ctrl->hdr_data.metadata_type_one, edid_ctrl->hdr_data.max_luminance, edid_ctrl->hdr_data.avg_luminance, edid_ctrl->hdr_data.min_luminance); Loading Loading @@ -964,8 +964,8 @@ static void hdmi_edid_parse_hdrdb(struct hdmi_edid_ctrl *edid_ctrl, /* Byte 3: Electro-Optical Transfer Functions */ edid_ctrl->hdr_data.eotf = data_block[2] & 0x3F; /* Byte 4: Static Metadata Descriptors */ edid_ctrl->hdr_data.descriptor = data_block[3] & 0x1; /* Byte 4: Static Metadata Descriptor Type 1 */ edid_ctrl->hdr_data.metadata_type_one = (data_block[3] & 0x1) & BIT(0); /* Byte 5: Desired Content Maximum Luminance */ if (hdmi_edid_is_luminance_value_present(len, MAXIMUM_LUMINANCE)) Loading Loading @@ -2458,16 +2458,16 @@ u8 hdmi_edid_get_deep_color(void *input) * Return: HDR data. */ void hdmi_edid_get_hdr_data(void *input, struct hdmi_edid_hdr_data *hdr_data) struct hdmi_edid_hdr_data **hdr_data) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; if (!edid_ctrl || !hdr_data) { if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return; } hdr_data = &edid_ctrl->hdr_data; *hdr_data = &edid_ctrl->hdr_data; } bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) Loading
drivers/video/fbdev/msm/mdss_hdmi_edid.h +3 −3 Original line number Diff line number Diff line Loading @@ -31,14 +31,14 @@ struct hdmi_edid_init_data { /* * struct hdmi_edid_hdr_data - HDR Static Metadata * @eotf: Electro-Optical Transfer Function * @descriptor: Static Metadata Descriptor * @metadata_type_one: Static Metadata Type 1 support * @max_luminance: Desired Content Maximum Luminance * @avg_luminance: Desired Content Frame-average Luminance * @min_luminance: Desired Content Minimum Luminance */ struct hdmi_edid_hdr_data { u32 eotf; u32 descriptor; bool metadata_type_one; u32 max_luminance; u32 avg_luminance; u32 min_luminance; Loading @@ -61,6 +61,6 @@ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode); u8 hdmi_edid_get_deep_color(void *edid_ctrl); void hdmi_edid_get_hdr_data(void *edid_ctrl, struct hdmi_edid_hdr_data *hdr_data); struct hdmi_edid_hdr_data **hdr_data); #endif /* __HDMI_EDID_H__ */
drivers/video/fbdev/msm/mdss_hdmi_tx.c +208 −17 Original line number Diff line number Diff line Loading @@ -79,6 +79,8 @@ #define HDMI_TX_MAX_FPS 120000 #define HDMI_TX_VERSION_403 0x40000003 /* msmcobalt */ #define HDMI_GET_MSB(x) (x >> 8) #define HDMI_GET_LSB(x) (x & 0xff) /* Enable HDCP by default */ static bool hdcp_feature_on = true; Loading Loading @@ -111,6 +113,9 @@ 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_setup_tmds_clk_rate(struct hdmi_tx_ctrl *hdmi_ctrl); static void hdmi_tx_fps_work(struct work_struct *work); static int hdmi_tx_pinctrl_set_state(struct hdmi_tx_ctrl *hdmi_ctrl, enum hdmi_tx_power_module_type module, bool active); static void hdmi_panel_set_hdr_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl); static struct mdss_hw hdmi_tx_hw = { .hw_ndx = MDSS_HW_HDMI, Loading Loading @@ -285,6 +290,29 @@ static inline bool hdmi_tx_is_hdcp_enabled(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_ctrl->hdcp_ops; } /* * The sink must support at least one electro-optical transfer function for * HDMI controller to sendi the dynamic range and mastering infoframe. */ static inline bool hdmi_tx_is_hdr_supported(struct hdmi_tx_ctrl *hdmi_ctrl) { struct hdmi_edid_hdr_data *hdr_data; hdmi_edid_get_hdr_data(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID), &hdr_data); return (hdr_data->eotf & BIT(0)) || (hdr_data->eotf & BIT(1)) || (hdr_data->eotf & BIT(2)); } static inline bool hdmi_tx_metadata_type_one(struct hdmi_tx_ctrl *hdmi_ctrl) { struct hdmi_edid_hdr_data *hdr_data; hdmi_edid_get_hdr_data(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID), &hdr_data); return hdr_data->metadata_type_one; } static inline bool hdmi_tx_dc_support(struct hdmi_tx_ctrl *hdmi_ctrl) { return hdmi_ctrl->dc_feature_on && hdmi_ctrl->dc_support && Loading Loading @@ -478,25 +506,30 @@ void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, } /* hdmi_tx_get_featuredata_from_sysfs_dev */ EXPORT_SYMBOL(hdmi_get_featuredata_from_sysfs_dev); static int hdmi_tx_config_5v(struct hdmi_tx_ctrl *hdmi_ctrl, bool enable) static int hdmi_tx_config_5v(struct hdmi_tx_ctrl *ctrl, bool enable) { struct dss_module_power *pd = NULL; int ret = 0; struct dss_module_power *pd = NULL; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); if (!ctrl) { DEV_ERR("%s: Invalid HDMI ctrl\n", __func__); ret = -EINVAL; goto end; } pd = &hdmi_ctrl->pdata.power_data[HDMI_TX_HPD_PM]; if (ctrl->hdmi_tx_version >= HDMI_TX_VERSION_403) ret = hdmi_tx_pinctrl_set_state(ctrl, HDMI_TX_HPD_PM, enable); else { pd = &ctrl->pdata.power_data[HDMI_TX_HPD_PM]; if (!pd || !pd->gpio_config) { DEV_ERR("%s: Error: invalid power data\n", __func__); DEV_ERR("%s: Invalid power data\n", __func__); ret = -EINVAL; goto end; } gpio_set_value(pd->gpio_config->gpio, enable); } end: return ret; } Loading Loading @@ -1220,12 +1253,6 @@ static ssize_t hdmi_tx_sysfs_wta_5v(struct device *dev, } mutex_lock(&hdmi_ctrl->tx_lock); pd = &hdmi_ctrl->pdata.power_data[HDMI_TX_HPD_PM]; if (!pd || !pd->gpio_config) { DEV_ERR("%s: Error: invalid power data\n", __func__); ret = -EINVAL; goto end; } ret = kstrtoint(buf, 10, &read); if (ret) { Loading @@ -1245,6 +1272,72 @@ end: return ret; } static ssize_t hdmi_tx_sysfs_wta_hdr_stream(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int ret = 0; u32 const hdr_param_count = 13; struct hdmi_tx_ctrl *ctrl = NULL; ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev); if (!ctrl) { pr_err("%s: invalid input\n", __func__); ret = -EINVAL; goto end; } if (!hdmi_tx_is_hdr_supported(ctrl)) { pr_err("%s: Sink does not support HDR\n", __func__); ret = -EINVAL; goto end; } if (sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u %u", &ctrl->hdr_data.eotf, &ctrl->hdr_data.display_primaries_x[0], &ctrl->hdr_data.display_primaries_y[0], &ctrl->hdr_data.display_primaries_x[1], &ctrl->hdr_data.display_primaries_y[1], &ctrl->hdr_data.display_primaries_x[2], &ctrl->hdr_data.display_primaries_y[2], &ctrl->hdr_data.white_point_x, &ctrl->hdr_data.white_point_y, &ctrl->hdr_data.max_luminance, &ctrl->hdr_data.min_luminance, &ctrl->hdr_data.max_content_light_level, &ctrl->hdr_data.max_average_light_level) != hdr_param_count) { pr_err("%s: Invalid HDR stream data\n", __func__); ret = -EINVAL; goto end; } pr_debug("%s: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n", __func__, ctrl->hdr_data.eotf, ctrl->hdr_data.display_primaries_x[0], ctrl->hdr_data.display_primaries_y[0], ctrl->hdr_data.display_primaries_x[1], ctrl->hdr_data.display_primaries_y[1], ctrl->hdr_data.display_primaries_x[2], ctrl->hdr_data.display_primaries_y[2]); pr_debug("%s: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n", __func__, ctrl->hdr_data.white_point_x, ctrl->hdr_data.white_point_y, ctrl->hdr_data.max_luminance, ctrl->hdr_data.min_luminance, ctrl->hdr_data.max_content_light_level, ctrl->hdr_data.max_average_light_level); hdmi_panel_set_hdr_infoframe(ctrl); ret = strnlen(buf, PAGE_SIZE); end: return ret; } static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL); static DEVICE_ATTR(hdmi_audio_cb, S_IWUSR, NULL, hdmi_tx_sysfs_wta_audio_cb); static DEVICE_ATTR(hot_plug, S_IWUSR, NULL, hdmi_tx_sysfs_wta_hot_plug); Loading @@ -1265,6 +1358,7 @@ 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 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 struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_connected.attr, Loading @@ -1280,6 +1374,7 @@ static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_avi_cn0_1.attr, &dev_attr_s3d_mode.attr, &dev_attr_5v.attr, &dev_attr_hdr_stream.attr, NULL, }; static struct attribute_group hdmi_tx_fs_attrs_group = { Loading Loading @@ -2209,7 +2304,7 @@ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl) DEV_DBG("%s: Features <HDMI:%s, HDCP:%s, Deep Color:%s>\n", __func__, hdmi_disabled ? "OFF" : "ON", hdcp_disabled ? "OFF" : "ON", hdmi_ctrl->dc_feature_on ? "OFF" : "ON"); !hdmi_ctrl->dc_feature_on ? "OFF" : "ON"); if (hdmi_disabled) { DEV_ERR("%s: HDMI disabled\n", __func__); Loading Loading @@ -2635,6 +2730,102 @@ static void hdmi_tx_phy_reset(struct hdmi_tx_ctrl *hdmi_ctrl) DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET_PLL); } /* hdmi_tx_phy_reset */ static void hdmi_panel_set_hdr_infoframe(struct hdmi_tx_ctrl *ctrl) { u32 packet_payload = 0; u32 packet_header = 0; u32 packet_control = 0; u32 const type_code = 0x87; u32 const version = 0x01; u32 const length = 0x1a; u32 const descriptor_id = 0x00; struct dss_io_data *io = NULL; if (!ctrl) { pr_err("%s: invalid input\n", __func__); return; } if (!hdmi_tx_is_hdr_supported(ctrl)) { pr_err("%s: Sink does not support HDR\n", __func__); return; } io = &ctrl->pdata.io[HDMI_TX_CORE_IO]; if (!io->base) { pr_err("%s: core io not inititalized\n", __func__); return; } /* Setup Packet header and payload */ packet_header = type_code | (version << 8) | (length << 16); DSS_REG_W(io, HDMI_GENERIC0_HDR, packet_header); packet_payload = (ctrl->hdr_data.eotf << 8); if (hdmi_tx_metadata_type_one(ctrl)) { packet_payload |= (descriptor_id << 16) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[0]) << 24); DSS_REG_W(io, HDMI_GENERIC0_0, packet_payload); } else { pr_debug("%s: Metadata Type 1 not supported\n", __func__); DSS_REG_W(io, HDMI_GENERIC0_0, packet_payload); goto enable_packet_control; } packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[0])) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[0]) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[0]) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[1]) << 24); DSS_REG_W(io, HDMI_GENERIC0_1, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[1])) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[1]) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[1]) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_x[2]) << 24); DSS_REG_W(io, HDMI_GENERIC0_2, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_x[2])) | (HDMI_GET_LSB(ctrl->hdr_data.display_primaries_y[2]) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.display_primaries_y[2]) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.white_point_x) << 24); DSS_REG_W(io, HDMI_GENERIC0_3, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.white_point_x)) | (HDMI_GET_LSB(ctrl->hdr_data.white_point_y) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.white_point_y) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.max_luminance) << 24); DSS_REG_W(io, HDMI_GENERIC0_4, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.max_luminance)) | (HDMI_GET_LSB(ctrl->hdr_data.min_luminance) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.min_luminance) << 16) | (HDMI_GET_LSB(ctrl->hdr_data.max_content_light_level) << 24); DSS_REG_W(io, HDMI_GENERIC0_5, packet_payload); packet_payload = (HDMI_GET_MSB(ctrl->hdr_data.max_content_light_level)) | (HDMI_GET_LSB(ctrl->hdr_data.max_average_light_level) << 8) | (HDMI_GET_MSB(ctrl->hdr_data.max_average_light_level) << 16); DSS_REG_W(io, HDMI_GENERIC0_6, packet_payload); enable_packet_control: /* * GENERIC0_LINE | GENERIC0_CONT | GENERIC0_SEND * Setup HDMI TX generic packet control * Enable this packet to transmit every frame * Enable HDMI TX engine to transmit Generic packet 1 */ packet_control = DSS_REG_R_ND(io, HDMI_GEN_PKT_CTRL); packet_control |= BIT(0) | BIT(1) | BIT(2) | BIT(16); DSS_REG_W(io, HDMI_GEN_PKT_CTRL, packet_control); } static int hdmi_tx_audio_info_setup(struct platform_device *pdev, struct msm_ext_disp_audio_setup_params *params) { Loading
drivers/video/fbdev/msm/mdss_hdmi_tx.h +26 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "mdss_hdmi_audio.h" #define MAX_SWITCH_NAME_SIZE 5 #define HDR_PRIMARIES_COUNT 3 enum hdmi_tx_io_type { HDMI_TX_CORE_IO, Loading Loading @@ -61,6 +62,30 @@ struct hdmi_tx_pinctrl { struct hdmi_tx_ctrl; typedef int (*hdmi_tx_evt_handler) (struct hdmi_tx_ctrl *); /* * struct hdmi_tx_hdr_stream - HDR video stream characteristics * @eotf: Electro-Optical Transfer Function * @display_primaries_x: display primaries data for x-coordinate * @display_primaries_y: display primaries data for y-coordinate * @white_point_x: white point data for x-coordinate * @white_point_y: white point data for y-coordinate * @max_luminance: content maximum luminance * @min_luminance: content minimum luminance * @max_content_light_level: content maximum light level * @max_average_light_level: content average light level */ struct hdmi_tx_hdr_stream_data { u32 eotf; u32 display_primaries_x[HDR_PRIMARIES_COUNT]; u32 display_primaries_y[HDR_PRIMARIES_COUNT]; u32 white_point_x; u32 white_point_y; u32 max_luminance; u32 min_luminance; u32 max_content_light_level; u32 max_average_light_level; }; struct hdmi_tx_ctrl { struct platform_device *pdev; struct hdmi_tx_platform_data pdata; Loading Loading @@ -88,6 +113,7 @@ struct hdmi_tx_ctrl { struct hdmi_panel_ops panel_ops; struct msm_ext_disp_audio_setup_params audio_params; struct work_struct fps_work; struct hdmi_tx_hdr_stream_data hdr_data; spinlock_t hpd_state_lock; Loading