Loading drivers/video/msm/mdss/mdss_hdmi_edid.c +126 −61 Original line number Diff line number Diff line /* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2016, 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 @@ -114,6 +114,13 @@ struct hdmi_edid_sink_caps { bool ind_view_support; }; struct hdmi_edid_override_data { int scramble; int sink_mode; int format; int vic; }; struct hdmi_edid_ctrl { u8 pt_scan_info; u8 it_scan_info; Loading @@ -134,11 +141,12 @@ struct hdmi_edid_ctrl { u8 edid_buf[MAX_EDID_SIZE]; char vendor_id[EDID_VENDOR_ID_SIZE]; bool keep_resv_timings; u32 edid_override; bool edid_override; struct hdmi_edid_sink_data sink_data; struct hdmi_edid_init_data init_data; struct hdmi_edid_sink_caps sink_caps; struct hdmi_edid_override_data override_data; }; static bool hdmi_edid_is_mode_supported(struct hdmi_edid_ctrl *edid_ctrl, Loading Loading @@ -315,12 +323,8 @@ static DEVICE_ATTR(spkr_alloc_data_block, S_IRUGO, static ssize_t hdmi_edid_sysfs_wta_modes(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int scrambling, vic, format, sink; ssize_t ret = strnlen(buf, PAGE_SIZE); int rc; struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); struct hdmi_edid_sink_data *sd; struct msm_hdmi_mode_timing_info info = {0}; if (!edid_ctrl) { DEV_ERR("%s: invalid ctrl\n", __func__); Loading @@ -328,52 +332,16 @@ static ssize_t hdmi_edid_sysfs_wta_modes(struct device *dev, goto error; } sd = &edid_ctrl->sink_data; if (sscanf(buf, "%d %d %d %d", &scrambling, &sink, &format, &vic) != 4) { &edid_ctrl->override_data.scramble, &edid_ctrl->override_data.sink_mode, &edid_ctrl->override_data.format, &edid_ctrl->override_data.vic) != 4) { DEV_ERR("could not read input\n"); ret = -EINVAL; goto bail; } if ((sink != SINK_MODE_DVI && sink != SINK_MODE_HDMI) || !(format & (MSM_HDMI_RGB_888_24BPP_FORMAT | MSM_HDMI_YUV_420_12BPP_FORMAT)) || vic <= HDMI_VFRMT_UNKNOWN || vic >= HDMI_VFRMT_MAX) { DEV_ERR("%s: invalid input: sink %d, format %d, vic %d\n", __func__, sink, format, vic); ret = -EINVAL; goto bail; } rc = hdmi_get_supported_mode(&info, &edid_ctrl->init_data.ds_data, vic); if (rc) { DEV_ERR("%s: error getting res details\n", __func__); ret = -EINVAL; goto bail; } if (!hdmi_edid_is_mode_supported(edid_ctrl, &info)) { DEV_ERR("%s: %d vic not supported\n", __func__, vic); ret = -EINVAL; goto bail; } sd->num_of_elements = 1; sd->disp_mode_list[0].video_format = vic; if (format & MSM_HDMI_RGB_888_24BPP_FORMAT) sd->disp_mode_list[0].rgb_support = true; if (format & MSM_HDMI_YUV_420_12BPP_FORMAT) sd->disp_mode_list[0].y420_support = true; edid_ctrl->sink_mode = sink; edid_ctrl->sink_caps.scramble_support = !!scrambling; edid_ctrl->sink_caps.scdc_present = !!scrambling; edid_ctrl->edid_override = true; return ret; bail: Loading @@ -389,17 +357,26 @@ static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev, ssize_t ret = 0; int i; struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); u32 num_of_elements = 0; struct disp_mode_info *video_mode; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } num_of_elements = edid_ctrl->sink_data.num_of_elements; video_mode = edid_ctrl->sink_data.disp_mode_list; if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) { num_of_elements = 1; edid_ctrl->sink_data.disp_mode_list[0].video_format = edid_ctrl->override_data.vic; } buf[0] = 0; if (edid_ctrl->sink_data.num_of_elements) { struct disp_mode_info *video_mode = edid_ctrl->sink_data.disp_mode_list; for (i = 0; i < edid_ctrl->sink_data.num_of_elements; i++) { if (num_of_elements) { for (i = 0; i < num_of_elements; i++) { if (ret > 0) ret += scnprintf(buf + ret, PAGE_SIZE - ret, ",%d", video_mode[i].video_format); Loading @@ -420,6 +397,65 @@ static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev, static DEVICE_ATTR(edid_modes, S_IRUGO | S_IWUSR, hdmi_edid_sysfs_rda_modes, hdmi_edid_sysfs_wta_modes); static ssize_t hdmi_edid_sysfs_rda_res_info_data(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret; u32 i, no_of_elem, offset = 0; struct msm_hdmi_mode_timing_info info = {0}; struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); struct disp_mode_info *minfo = NULL; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } no_of_elem = edid_ctrl->sink_data.num_of_elements; minfo = edid_ctrl->sink_data.disp_mode_list; if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) { no_of_elem = 1; minfo[0].video_format = edid_ctrl->override_data.vic; } for (i = 0; i < no_of_elem; i++) { ret = hdmi_get_supported_mode(&info, &edid_ctrl->init_data.ds_data, minfo->video_format); if (edid_ctrl->edid_override && (edid_ctrl->override_data.format > 0)) info.pixel_formats = edid_ctrl->override_data.format; else info.pixel_formats = (minfo->rgb_support ? MSM_HDMI_RGB_888_24BPP_FORMAT : 0) | (minfo->y420_support ? MSM_HDMI_YUV_420_12BPP_FORMAT : 0); minfo++; if (ret || !info.supported) continue; offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", info.video_format, info.active_h, info.front_porch_h, info.pulse_width_h, info.back_porch_h, info.active_low_h, info.active_v, info.front_porch_v, info.pulse_width_v, info.back_porch_v, info.active_low_v, info.pixel_freq, info.refresh_rate, info.interlaced, info.supported, info.ar, info.pixel_formats); } return offset; } static DEVICE_ATTR(res_info_data, S_IRUGO, hdmi_edid_sysfs_rda_res_info_data, NULL); static ssize_t hdmi_edid_sysfs_wta_res_info(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { Loading Loading @@ -477,14 +513,25 @@ static ssize_t hdmi_edid_sysfs_rda_res_info(struct device *dev, } } if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) { no_of_elem = 1; minfo[0].video_format = edid_ctrl->override_data.vic; } for (; i < no_of_elem && size_to_write < PAGE_SIZE; i++) { ret = hdmi_get_supported_mode(&info, &edid_ctrl->init_data.ds_data, minfo->video_format); if (edid_ctrl->edid_override && (edid_ctrl->override_data.format > 0)) info.pixel_formats = edid_ctrl->override_data.format; else info.pixel_formats = (minfo->rgb_support ? MSM_HDMI_RGB_888_24BPP_FORMAT : 0) | (minfo->y420_support ? MSM_HDMI_YUV_420_12BPP_FORMAT : 0); (minfo->rgb_support ? MSM_HDMI_RGB_888_24BPP_FORMAT : 0) | (minfo->y420_support ? MSM_HDMI_YUV_420_12BPP_FORMAT : 0); minfo++; if (ret || !info.supported) Loading Loading @@ -725,6 +772,7 @@ static struct attribute *hdmi_edid_fs_attrs[] = { &dev_attr_edid_audio_latency.attr, &dev_attr_edid_video_latency.attr, &dev_attr_res_info.attr, &dev_attr_res_info_data.attr, &dev_attr_add_res.attr, NULL, }; Loading Loading @@ -2102,11 +2150,6 @@ int hdmi_edid_parser(void *input) goto err_invalid_data; } if (edid_ctrl->edid_override) { DEV_DBG("edid override enabled\n"); goto err_invalid_data; } /* reset edid data for new hdmi connection */ hdmi_edid_reset_parser(edid_ctrl); Loading Loading @@ -2244,13 +2287,20 @@ end: u32 hdmi_edid_get_sink_mode(void *input) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; bool sink_mode; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return 0; } return edid_ctrl->sink_mode; if (edid_ctrl->edid_override && (edid_ctrl->override_data.sink_mode != -1)) sink_mode = edid_ctrl->override_data.sink_mode; else sink_mode = edid_ctrl->sink_mode; return sink_mode; } /* hdmi_edid_get_sink_mode */ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) Loading Loading @@ -2280,24 +2330,39 @@ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) bool hdmi_edid_get_scdc_support(void *input) { struct hdmi_edid_ctrl *edid_ctrl = input; bool scdc_present; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return false; } return edid_ctrl->sink_caps.scdc_present; if (edid_ctrl->edid_override && (edid_ctrl->override_data.scramble != -1)) scdc_present = edid_ctrl->override_data.scramble; else scdc_present = edid_ctrl->sink_caps.scdc_present; return scdc_present; } bool hdmi_edid_get_sink_scrambler_support(void *input) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; bool scramble_support; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return 0; } return edid_ctrl->sink_caps.scramble_support; if (edid_ctrl->edid_override && (edid_ctrl->override_data.scramble != -1)) scramble_support = edid_ctrl->override_data.scramble; else scramble_support = edid_ctrl->sink_caps.scramble_support; return scramble_support; } int hdmi_edid_get_audio_blk(void *input, struct msm_hdmi_audio_edid_blk *blk) Loading drivers/video/msm/mdss/mdss_hdmi_tx.c +138 −11 Original line number Diff line number Diff line Loading @@ -717,6 +717,14 @@ static ssize_t hdmi_tx_sysfs_wta_edid(struct device *dev, } mutex_lock(&hdmi_ctrl->tx_lock); if (edid_size < EDID_BLOCK_SIZE) { DEV_DBG("%s: disabling custom edid\n", __func__); ret = -EINVAL; hdmi_ctrl->custom_edid = false; goto end; } memset(hdmi_ctrl->edid_buf, 0, hdmi_ctrl->edid_buf_size); while (edid_size--) { Loading Loading @@ -827,6 +835,108 @@ end: return ret; } static ssize_t hdmi_tx_sysfs_wta_hot_plug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int hot_plug, rc; 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; } mutex_lock(&hdmi_ctrl->tx_lock); rc = kstrtoint(buf, 10, &hot_plug); if (rc) { DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc); goto end; } hdmi_ctrl->hpd_state = !!hot_plug; queue_work(hdmi_ctrl->workq, &hdmi_ctrl->hpd_int_work); rc = strnlen(buf, PAGE_SIZE); end: mutex_unlock(&hdmi_ctrl->tx_lock); return rc; } static ssize_t hdmi_tx_sysfs_rda_sim_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; } mutex_lock(&hdmi_ctrl->tx_lock); ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->sim_mode); DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->sim_mode); mutex_unlock(&hdmi_ctrl->tx_lock); return ret; } static ssize_t hdmi_tx_sysfs_wta_sim_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int sim_mode, rc; struct hdmi_tx_ctrl *hdmi_ctrl = NULL; struct dss_io_data *io = NULL; hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev); if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } mutex_lock(&hdmi_ctrl->tx_lock); io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; if (!io->base) { DEV_ERR("%s: core io is not initialized\n", __func__); rc = -EINVAL; goto end; } if (!hdmi_ctrl->hpd_initialized) { DEV_ERR("%s: hpd not enabled\n", __func__); rc = -EINVAL; goto end; } rc = kstrtoint(buf, 10, &sim_mode); if (rc) { DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc); goto end; } hdmi_ctrl->sim_mode = !!sim_mode; if (hdmi_ctrl->sim_mode) { DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(0)); } else { int cable_sense = DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1); DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(0) | BIT(2) | (cable_sense ? 0 : BIT(1))); } rc = strnlen(buf, PAGE_SIZE); end: mutex_unlock(&hdmi_ctrl->tx_lock); return rc; } static ssize_t hdmi_tx_sysfs_rda_video_mode(struct device *dev, struct device_attribute *attr, char *buf) { Loading Loading @@ -1292,6 +1402,9 @@ end: 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); static DEVICE_ATTR(sim_mode, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_sim_mode, hdmi_tx_sysfs_wta_sim_mode); static DEVICE_ATTR(edid, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_edid, hdmi_tx_sysfs_wta_edid); static DEVICE_ATTR(video_mode, S_IRUGO, hdmi_tx_sysfs_rda_video_mode, NULL); Loading @@ -1311,6 +1424,8 @@ static DEVICE_ATTR(5v, S_IWUSR, NULL, hdmi_tx_sysfs_wta_5v); static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_connected.attr, &dev_attr_hdmi_audio_cb.attr, &dev_attr_hot_plug.attr, &dev_attr_sim_mode.attr, &dev_attr_edid.attr, &dev_attr_video_mode.attr, &dev_attr_hpd.attr, Loading Loading @@ -1894,20 +2009,23 @@ static int hdmi_tx_init_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl) static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl) { int status; int status = 0; void *data; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } data = hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]; if (!hdmi_tx_is_controller_on(hdmi_ctrl)) { DEV_ERR("%s: failed: HDMI controller is off", __func__); status = -ENXIO; goto error; } if (!hdmi_ctrl->custom_edid) { if (!hdmi_ctrl->custom_edid && !hdmi_ctrl->sim_mode) { hdmi_ddc_config(&hdmi_ctrl->ddc_ctrl); status = hdmi_tx_read_edid(hdmi_ctrl); Loading @@ -1915,13 +2033,14 @@ static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl) DEV_ERR("%s: error reading edid\n", __func__); goto error; } } else { hdmi_ctrl->custom_edid = false; } status = hdmi_edid_parser(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]); /* parse edid if a valid edid buffer is present */ if (hdmi_ctrl->custom_edid || !hdmi_ctrl->sim_mode) { status = hdmi_edid_parser(data); if (status) DEV_ERR("%s: edid parse failed\n", __func__); } error: return status; Loading Loading @@ -3800,6 +3919,11 @@ static void hdmi_tx_hpd_polarity_setup(struct hdmi_tx_ctrl *hdmi_ctrl, return; } if (hdmi_ctrl->sim_mode) { DEV_DBG("%s: sim mode enabled\n", __func__); return; } if (polarity) DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(2) | BIT(1)); else Loading Loading @@ -4513,11 +4637,14 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data, break; case MDSS_EVENT_PANEL_ON: if (!hdmi_ctrl->sim_mode) { hdmi_tx_update_hdcp_info(hdmi_ctrl); rc = hdmi_tx_start_hdcp(hdmi_ctrl); if (rc) DEV_ERR("%s: hdcp start failed rc=%d\n", __func__, rc); DEV_ERR("%s: hdcp start failed rc=%d\n", __func__, rc); } hdmi_ctrl->timing_gen_on = true; Loading drivers/video/msm/mdss/mdss_hdmi_tx.h +1 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,7 @@ struct hdmi_tx_ctrl { bool hdcp14_sw_keys; bool auth_state; bool custom_edid; bool sim_mode; u32 enc_lvl; u8 spd_vendor_name[9]; Loading Loading
drivers/video/msm/mdss/mdss_hdmi_edid.c +126 −61 Original line number Diff line number Diff line /* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2016, 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 @@ -114,6 +114,13 @@ struct hdmi_edid_sink_caps { bool ind_view_support; }; struct hdmi_edid_override_data { int scramble; int sink_mode; int format; int vic; }; struct hdmi_edid_ctrl { u8 pt_scan_info; u8 it_scan_info; Loading @@ -134,11 +141,12 @@ struct hdmi_edid_ctrl { u8 edid_buf[MAX_EDID_SIZE]; char vendor_id[EDID_VENDOR_ID_SIZE]; bool keep_resv_timings; u32 edid_override; bool edid_override; struct hdmi_edid_sink_data sink_data; struct hdmi_edid_init_data init_data; struct hdmi_edid_sink_caps sink_caps; struct hdmi_edid_override_data override_data; }; static bool hdmi_edid_is_mode_supported(struct hdmi_edid_ctrl *edid_ctrl, Loading Loading @@ -315,12 +323,8 @@ static DEVICE_ATTR(spkr_alloc_data_block, S_IRUGO, static ssize_t hdmi_edid_sysfs_wta_modes(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int scrambling, vic, format, sink; ssize_t ret = strnlen(buf, PAGE_SIZE); int rc; struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); struct hdmi_edid_sink_data *sd; struct msm_hdmi_mode_timing_info info = {0}; if (!edid_ctrl) { DEV_ERR("%s: invalid ctrl\n", __func__); Loading @@ -328,52 +332,16 @@ static ssize_t hdmi_edid_sysfs_wta_modes(struct device *dev, goto error; } sd = &edid_ctrl->sink_data; if (sscanf(buf, "%d %d %d %d", &scrambling, &sink, &format, &vic) != 4) { &edid_ctrl->override_data.scramble, &edid_ctrl->override_data.sink_mode, &edid_ctrl->override_data.format, &edid_ctrl->override_data.vic) != 4) { DEV_ERR("could not read input\n"); ret = -EINVAL; goto bail; } if ((sink != SINK_MODE_DVI && sink != SINK_MODE_HDMI) || !(format & (MSM_HDMI_RGB_888_24BPP_FORMAT | MSM_HDMI_YUV_420_12BPP_FORMAT)) || vic <= HDMI_VFRMT_UNKNOWN || vic >= HDMI_VFRMT_MAX) { DEV_ERR("%s: invalid input: sink %d, format %d, vic %d\n", __func__, sink, format, vic); ret = -EINVAL; goto bail; } rc = hdmi_get_supported_mode(&info, &edid_ctrl->init_data.ds_data, vic); if (rc) { DEV_ERR("%s: error getting res details\n", __func__); ret = -EINVAL; goto bail; } if (!hdmi_edid_is_mode_supported(edid_ctrl, &info)) { DEV_ERR("%s: %d vic not supported\n", __func__, vic); ret = -EINVAL; goto bail; } sd->num_of_elements = 1; sd->disp_mode_list[0].video_format = vic; if (format & MSM_HDMI_RGB_888_24BPP_FORMAT) sd->disp_mode_list[0].rgb_support = true; if (format & MSM_HDMI_YUV_420_12BPP_FORMAT) sd->disp_mode_list[0].y420_support = true; edid_ctrl->sink_mode = sink; edid_ctrl->sink_caps.scramble_support = !!scrambling; edid_ctrl->sink_caps.scdc_present = !!scrambling; edid_ctrl->edid_override = true; return ret; bail: Loading @@ -389,17 +357,26 @@ static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev, ssize_t ret = 0; int i; struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); u32 num_of_elements = 0; struct disp_mode_info *video_mode; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } num_of_elements = edid_ctrl->sink_data.num_of_elements; video_mode = edid_ctrl->sink_data.disp_mode_list; if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) { num_of_elements = 1; edid_ctrl->sink_data.disp_mode_list[0].video_format = edid_ctrl->override_data.vic; } buf[0] = 0; if (edid_ctrl->sink_data.num_of_elements) { struct disp_mode_info *video_mode = edid_ctrl->sink_data.disp_mode_list; for (i = 0; i < edid_ctrl->sink_data.num_of_elements; i++) { if (num_of_elements) { for (i = 0; i < num_of_elements; i++) { if (ret > 0) ret += scnprintf(buf + ret, PAGE_SIZE - ret, ",%d", video_mode[i].video_format); Loading @@ -420,6 +397,65 @@ static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev, static DEVICE_ATTR(edid_modes, S_IRUGO | S_IWUSR, hdmi_edid_sysfs_rda_modes, hdmi_edid_sysfs_wta_modes); static ssize_t hdmi_edid_sysfs_rda_res_info_data(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret; u32 i, no_of_elem, offset = 0; struct msm_hdmi_mode_timing_info info = {0}; struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); struct disp_mode_info *minfo = NULL; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } no_of_elem = edid_ctrl->sink_data.num_of_elements; minfo = edid_ctrl->sink_data.disp_mode_list; if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) { no_of_elem = 1; minfo[0].video_format = edid_ctrl->override_data.vic; } for (i = 0; i < no_of_elem; i++) { ret = hdmi_get_supported_mode(&info, &edid_ctrl->init_data.ds_data, minfo->video_format); if (edid_ctrl->edid_override && (edid_ctrl->override_data.format > 0)) info.pixel_formats = edid_ctrl->override_data.format; else info.pixel_formats = (minfo->rgb_support ? MSM_HDMI_RGB_888_24BPP_FORMAT : 0) | (minfo->y420_support ? MSM_HDMI_YUV_420_12BPP_FORMAT : 0); minfo++; if (ret || !info.supported) continue; offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", info.video_format, info.active_h, info.front_porch_h, info.pulse_width_h, info.back_porch_h, info.active_low_h, info.active_v, info.front_porch_v, info.pulse_width_v, info.back_porch_v, info.active_low_v, info.pixel_freq, info.refresh_rate, info.interlaced, info.supported, info.ar, info.pixel_formats); } return offset; } static DEVICE_ATTR(res_info_data, S_IRUGO, hdmi_edid_sysfs_rda_res_info_data, NULL); static ssize_t hdmi_edid_sysfs_wta_res_info(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { Loading Loading @@ -477,14 +513,25 @@ static ssize_t hdmi_edid_sysfs_rda_res_info(struct device *dev, } } if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) { no_of_elem = 1; minfo[0].video_format = edid_ctrl->override_data.vic; } for (; i < no_of_elem && size_to_write < PAGE_SIZE; i++) { ret = hdmi_get_supported_mode(&info, &edid_ctrl->init_data.ds_data, minfo->video_format); if (edid_ctrl->edid_override && (edid_ctrl->override_data.format > 0)) info.pixel_formats = edid_ctrl->override_data.format; else info.pixel_formats = (minfo->rgb_support ? MSM_HDMI_RGB_888_24BPP_FORMAT : 0) | (minfo->y420_support ? MSM_HDMI_YUV_420_12BPP_FORMAT : 0); (minfo->rgb_support ? MSM_HDMI_RGB_888_24BPP_FORMAT : 0) | (minfo->y420_support ? MSM_HDMI_YUV_420_12BPP_FORMAT : 0); minfo++; if (ret || !info.supported) Loading Loading @@ -725,6 +772,7 @@ static struct attribute *hdmi_edid_fs_attrs[] = { &dev_attr_edid_audio_latency.attr, &dev_attr_edid_video_latency.attr, &dev_attr_res_info.attr, &dev_attr_res_info_data.attr, &dev_attr_add_res.attr, NULL, }; Loading Loading @@ -2102,11 +2150,6 @@ int hdmi_edid_parser(void *input) goto err_invalid_data; } if (edid_ctrl->edid_override) { DEV_DBG("edid override enabled\n"); goto err_invalid_data; } /* reset edid data for new hdmi connection */ hdmi_edid_reset_parser(edid_ctrl); Loading Loading @@ -2244,13 +2287,20 @@ end: u32 hdmi_edid_get_sink_mode(void *input) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; bool sink_mode; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return 0; } return edid_ctrl->sink_mode; if (edid_ctrl->edid_override && (edid_ctrl->override_data.sink_mode != -1)) sink_mode = edid_ctrl->override_data.sink_mode; else sink_mode = edid_ctrl->sink_mode; return sink_mode; } /* hdmi_edid_get_sink_mode */ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) Loading Loading @@ -2280,24 +2330,39 @@ bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode) bool hdmi_edid_get_scdc_support(void *input) { struct hdmi_edid_ctrl *edid_ctrl = input; bool scdc_present; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return false; } return edid_ctrl->sink_caps.scdc_present; if (edid_ctrl->edid_override && (edid_ctrl->override_data.scramble != -1)) scdc_present = edid_ctrl->override_data.scramble; else scdc_present = edid_ctrl->sink_caps.scdc_present; return scdc_present; } bool hdmi_edid_get_sink_scrambler_support(void *input) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; bool scramble_support; if (!edid_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return 0; } return edid_ctrl->sink_caps.scramble_support; if (edid_ctrl->edid_override && (edid_ctrl->override_data.scramble != -1)) scramble_support = edid_ctrl->override_data.scramble; else scramble_support = edid_ctrl->sink_caps.scramble_support; return scramble_support; } int hdmi_edid_get_audio_blk(void *input, struct msm_hdmi_audio_edid_blk *blk) Loading
drivers/video/msm/mdss/mdss_hdmi_tx.c +138 −11 Original line number Diff line number Diff line Loading @@ -717,6 +717,14 @@ static ssize_t hdmi_tx_sysfs_wta_edid(struct device *dev, } mutex_lock(&hdmi_ctrl->tx_lock); if (edid_size < EDID_BLOCK_SIZE) { DEV_DBG("%s: disabling custom edid\n", __func__); ret = -EINVAL; hdmi_ctrl->custom_edid = false; goto end; } memset(hdmi_ctrl->edid_buf, 0, hdmi_ctrl->edid_buf_size); while (edid_size--) { Loading Loading @@ -827,6 +835,108 @@ end: return ret; } static ssize_t hdmi_tx_sysfs_wta_hot_plug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int hot_plug, rc; 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; } mutex_lock(&hdmi_ctrl->tx_lock); rc = kstrtoint(buf, 10, &hot_plug); if (rc) { DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc); goto end; } hdmi_ctrl->hpd_state = !!hot_plug; queue_work(hdmi_ctrl->workq, &hdmi_ctrl->hpd_int_work); rc = strnlen(buf, PAGE_SIZE); end: mutex_unlock(&hdmi_ctrl->tx_lock); return rc; } static ssize_t hdmi_tx_sysfs_rda_sim_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; } mutex_lock(&hdmi_ctrl->tx_lock); ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->sim_mode); DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->sim_mode); mutex_unlock(&hdmi_ctrl->tx_lock); return ret; } static ssize_t hdmi_tx_sysfs_wta_sim_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int sim_mode, rc; struct hdmi_tx_ctrl *hdmi_ctrl = NULL; struct dss_io_data *io = NULL; hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev); if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } mutex_lock(&hdmi_ctrl->tx_lock); io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; if (!io->base) { DEV_ERR("%s: core io is not initialized\n", __func__); rc = -EINVAL; goto end; } if (!hdmi_ctrl->hpd_initialized) { DEV_ERR("%s: hpd not enabled\n", __func__); rc = -EINVAL; goto end; } rc = kstrtoint(buf, 10, &sim_mode); if (rc) { DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc); goto end; } hdmi_ctrl->sim_mode = !!sim_mode; if (hdmi_ctrl->sim_mode) { DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(0)); } else { int cable_sense = DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1); DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(0) | BIT(2) | (cable_sense ? 0 : BIT(1))); } rc = strnlen(buf, PAGE_SIZE); end: mutex_unlock(&hdmi_ctrl->tx_lock); return rc; } static ssize_t hdmi_tx_sysfs_rda_video_mode(struct device *dev, struct device_attribute *attr, char *buf) { Loading Loading @@ -1292,6 +1402,9 @@ end: 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); static DEVICE_ATTR(sim_mode, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_sim_mode, hdmi_tx_sysfs_wta_sim_mode); static DEVICE_ATTR(edid, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_edid, hdmi_tx_sysfs_wta_edid); static DEVICE_ATTR(video_mode, S_IRUGO, hdmi_tx_sysfs_rda_video_mode, NULL); Loading @@ -1311,6 +1424,8 @@ static DEVICE_ATTR(5v, S_IWUSR, NULL, hdmi_tx_sysfs_wta_5v); static struct attribute *hdmi_tx_fs_attrs[] = { &dev_attr_connected.attr, &dev_attr_hdmi_audio_cb.attr, &dev_attr_hot_plug.attr, &dev_attr_sim_mode.attr, &dev_attr_edid.attr, &dev_attr_video_mode.attr, &dev_attr_hpd.attr, Loading Loading @@ -1894,20 +2009,23 @@ static int hdmi_tx_init_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl) static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl) { int status; int status = 0; void *data; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); return -EINVAL; } data = hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]; if (!hdmi_tx_is_controller_on(hdmi_ctrl)) { DEV_ERR("%s: failed: HDMI controller is off", __func__); status = -ENXIO; goto error; } if (!hdmi_ctrl->custom_edid) { if (!hdmi_ctrl->custom_edid && !hdmi_ctrl->sim_mode) { hdmi_ddc_config(&hdmi_ctrl->ddc_ctrl); status = hdmi_tx_read_edid(hdmi_ctrl); Loading @@ -1915,13 +2033,14 @@ static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl) DEV_ERR("%s: error reading edid\n", __func__); goto error; } } else { hdmi_ctrl->custom_edid = false; } status = hdmi_edid_parser(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]); /* parse edid if a valid edid buffer is present */ if (hdmi_ctrl->custom_edid || !hdmi_ctrl->sim_mode) { status = hdmi_edid_parser(data); if (status) DEV_ERR("%s: edid parse failed\n", __func__); } error: return status; Loading Loading @@ -3800,6 +3919,11 @@ static void hdmi_tx_hpd_polarity_setup(struct hdmi_tx_ctrl *hdmi_ctrl, return; } if (hdmi_ctrl->sim_mode) { DEV_DBG("%s: sim mode enabled\n", __func__); return; } if (polarity) DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(2) | BIT(1)); else Loading Loading @@ -4513,11 +4637,14 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data, break; case MDSS_EVENT_PANEL_ON: if (!hdmi_ctrl->sim_mode) { hdmi_tx_update_hdcp_info(hdmi_ctrl); rc = hdmi_tx_start_hdcp(hdmi_ctrl); if (rc) DEV_ERR("%s: hdcp start failed rc=%d\n", __func__, rc); DEV_ERR("%s: hdcp start failed rc=%d\n", __func__, rc); } hdmi_ctrl->timing_gen_on = true; Loading
drivers/video/msm/mdss/mdss_hdmi_tx.h +1 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,7 @@ struct hdmi_tx_ctrl { bool hdcp14_sw_keys; bool auth_state; bool custom_edid; bool sim_mode; u32 enc_lvl; u8 spd_vendor_name[9]; Loading