Merge "msm: mdss: refine the calculation of tmds clock rate"
This commit is contained in:
commit
c7690d6901
7 changed files with 205 additions and 133 deletions
|
@ -134,6 +134,7 @@ struct hdmi_edid_ctrl {
|
|||
u8 it_scan_info;
|
||||
u8 ce_scan_info;
|
||||
u8 cea_blks;
|
||||
/* DC: MSB -> LSB: Y420_48|Y420_36|Y420_30|RGB48|RGB36|RGB30|Y444 */
|
||||
u8 deep_color;
|
||||
u16 physical_address;
|
||||
u32 video_resolution; /* selected by user */
|
||||
|
@ -858,6 +859,43 @@ static const u8 *hdmi_edid_find_block(const u8 *in_buf, u32 start_offset,
|
|||
return NULL;
|
||||
} /* hdmi_edid_find_block */
|
||||
|
||||
static const u8 *hdmi_edid_find_hfvsdb(const u8 *in_buf)
|
||||
{
|
||||
u8 len = 0, i = 0;
|
||||
const u8 *vsd = NULL;
|
||||
u32 vsd_offset = DBC_START_OFFSET;
|
||||
u32 hf_ieee_oui = 0;
|
||||
|
||||
/* Find HF-VSDB with HF-OUI */
|
||||
do {
|
||||
vsd = hdmi_edid_find_block(in_buf, vsd_offset,
|
||||
VENDOR_SPECIFIC_DATA_BLOCK, &len);
|
||||
|
||||
if (!vsd || !len || len > MAX_DATA_BLOCK_SIZE) {
|
||||
if (i == 0)
|
||||
pr_debug("%s: VSDB not found\n", __func__);
|
||||
else
|
||||
pr_debug("%s: no more VSDB found\n", __func__);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hf_ieee_oui = (vsd[1] << 16) | (vsd[2] << 8) | vsd[3];
|
||||
|
||||
if (hf_ieee_oui == HDMI_FORUM_IEEE_OUI) {
|
||||
pr_debug("%s: found HF-VSDB\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
pr_debug("%s: Not a HF OUI 0x%x\n", __func__, hf_ieee_oui);
|
||||
|
||||
i++;
|
||||
vsd_offset = vsd - in_buf + len + 1;
|
||||
} while (1);
|
||||
|
||||
return vsd;
|
||||
}
|
||||
|
||||
static void hdmi_edid_set_y420_support(struct hdmi_edid_ctrl *edid_ctrl,
|
||||
u32 video_format)
|
||||
{
|
||||
|
@ -1251,62 +1289,32 @@ static void hdmi_edid_extract_speaker_allocation_data(
|
|||
static void hdmi_edid_extract_sink_caps(struct hdmi_edid_ctrl *edid_ctrl,
|
||||
const u8 *in_buf)
|
||||
{
|
||||
u8 len = 0, i = 0;
|
||||
const u8 *vsd = NULL;
|
||||
u32 vsd_offset = DBC_START_OFFSET;
|
||||
u32 hf_ieee_oui = 0;
|
||||
|
||||
if (!edid_ctrl) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
pr_err("%s: invalid input\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find HF-VSDB with HF-OUI */
|
||||
do {
|
||||
vsd = hdmi_edid_find_block(in_buf, vsd_offset,
|
||||
VENDOR_SPECIFIC_DATA_BLOCK, &len);
|
||||
vsd = hdmi_edid_find_hfvsdb(in_buf);
|
||||
|
||||
if (!vsd || !len || len > MAX_DATA_BLOCK_SIZE) {
|
||||
if (i == 0)
|
||||
DEV_ERR("%s: VSDB not found\n", __func__);
|
||||
else
|
||||
DEV_DBG("%s: no more VSDB found\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
hf_ieee_oui = (vsd[1] << 16) | (vsd[2] << 8) | vsd[3];
|
||||
|
||||
if (hf_ieee_oui == HDMI_FORUM_IEEE_OUI) {
|
||||
DEV_DBG("%s: found HF-VSDB\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
DEV_DBG("%s: Not a HF OUI 0x%x\n", __func__, hf_ieee_oui);
|
||||
|
||||
i++;
|
||||
vsd_offset = vsd - in_buf + len + 1;
|
||||
} while (1);
|
||||
|
||||
if (!vsd) {
|
||||
DEV_DBG("%s: HF-VSDB not found\n", __func__);
|
||||
return;
|
||||
if (vsd) {
|
||||
/* Max pixel clock is in multiples of 5Mhz. */
|
||||
edid_ctrl->sink_caps.max_pclk_in_hz =
|
||||
vsd[5]*5000000;
|
||||
edid_ctrl->sink_caps.scdc_present =
|
||||
(vsd[6] & 0x80) ? true : false;
|
||||
edid_ctrl->sink_caps.scramble_support =
|
||||
(vsd[6] & 0x08) ? true : false;
|
||||
edid_ctrl->sink_caps.read_req_support =
|
||||
(vsd[6] & 0x40) ? true : false;
|
||||
edid_ctrl->sink_caps.osd_disparity =
|
||||
(vsd[6] & 0x01) ? true : false;
|
||||
edid_ctrl->sink_caps.dual_view_support =
|
||||
(vsd[6] & 0x02) ? true : false;
|
||||
edid_ctrl->sink_caps.ind_view_support =
|
||||
(vsd[6] & 0x04) ? true : false;
|
||||
}
|
||||
|
||||
/* Max pixel clock is in multiples of 5Mhz. */
|
||||
edid_ctrl->sink_caps.max_pclk_in_hz =
|
||||
vsd[5]*5000000;
|
||||
edid_ctrl->sink_caps.scdc_present =
|
||||
(vsd[6] & 0x80) ? true : false;
|
||||
edid_ctrl->sink_caps.scramble_support =
|
||||
(vsd[6] & 0x08) ? true : false;
|
||||
edid_ctrl->sink_caps.read_req_support =
|
||||
(vsd[6] & 0x40) ? true : false;
|
||||
edid_ctrl->sink_caps.osd_disparity =
|
||||
(vsd[6] & 0x01) ? true : false;
|
||||
edid_ctrl->sink_caps.dual_view_support =
|
||||
(vsd[6] & 0x02) ? true : false;
|
||||
edid_ctrl->sink_caps.ind_view_support =
|
||||
(vsd[6] & 0x04) ? true : false;
|
||||
}
|
||||
|
||||
static void hdmi_edid_extract_latency_fields(struct hdmi_edid_ctrl *edid_ctrl,
|
||||
|
@ -1404,12 +1412,19 @@ static void hdmi_edid_extract_dc(struct hdmi_edid_ctrl *edid_ctrl,
|
|||
|
||||
edid_ctrl->deep_color = (vsd[6] >> 0x3) & 0xF;
|
||||
|
||||
DEV_DBG("%s: deep color: Y444|RGB30|RGB36|RGB48: (%d|%d|%d|%d)\n",
|
||||
__func__,
|
||||
vsd = hdmi_edid_find_hfvsdb(in_buf);
|
||||
|
||||
if (vsd)
|
||||
edid_ctrl->deep_color |= (vsd[7] & 0x07) << 4;
|
||||
|
||||
pr_debug("deep color: Y444|RGB30|RGB36|RGB48|Y420_30|Y420_36|Y420_48: (%d|%d|%d|%d|%d|%d|%d)\n",
|
||||
(int) (edid_ctrl->deep_color & BIT(0)) >> 0,
|
||||
(int) (edid_ctrl->deep_color & BIT(1)) >> 1,
|
||||
(int) (edid_ctrl->deep_color & BIT(2)) >> 2,
|
||||
(int) (edid_ctrl->deep_color & BIT(3)) >> 3);
|
||||
(int) (edid_ctrl->deep_color & BIT(3)) >> 3,
|
||||
(int) (edid_ctrl->deep_color & BIT(4)) >> 4,
|
||||
(int) (edid_ctrl->deep_color & BIT(5)) >> 5,
|
||||
(int) (edid_ctrl->deep_color & BIT(6)) >> 6);
|
||||
}
|
||||
|
||||
static u32 hdmi_edid_check_header(const u8 *edid_buf)
|
||||
|
@ -2398,8 +2413,8 @@ u32 hdmi_edid_get_sink_mode(void *input)
|
|||
*
|
||||
* This API returns deep color for different formats supported by sink.
|
||||
* Deep color support for Y444 (BIT(0)), RGB30 (BIT(1)), RGB36 (BIT(2),
|
||||
* RGB 48 (BIT(3)) is provided in a 8 bit integer. The MSB 8 bits are
|
||||
* not used.
|
||||
* RGB 48 (BIT(3)), Y420_30 (BIT(4)), Y420_36 (BIT(5)), Y420_48 (BIT(6))
|
||||
* is provided in a 8 bit integer. The MSB 8 bits are not used.
|
||||
*
|
||||
* Return: deep color data.
|
||||
*/
|
||||
|
@ -2415,6 +2430,25 @@ u8 hdmi_edid_get_deep_color(void *input)
|
|||
return edid_ctrl->deep_color;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdmi_edid_get_max_pclk() - get max pclk supported. Sink side's limitation
|
||||
* should be concerned as well.
|
||||
* @input: edid parser data
|
||||
*
|
||||
* Return: max pclk rate
|
||||
*/
|
||||
u32 hdmi_edid_get_max_pclk(void *input)
|
||||
{
|
||||
struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
|
||||
|
||||
if (!edid_ctrl) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return edid_ctrl->init_data.max_pclk_khz;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdmi_edid_get_hdr_data() - get the HDR capabiliies of the sink
|
||||
* @input: edid parser data
|
||||
|
|
|
@ -60,6 +60,7 @@ 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);
|
||||
u8 hdmi_edid_get_deep_color(void *edid_ctrl);
|
||||
u32 hdmi_edid_get_max_pclk(void *edid_ctrl);
|
||||
void hdmi_edid_get_hdr_data(void *edid_ctrl,
|
||||
struct hdmi_edid_hdr_data **hdr_data);
|
||||
|
||||
|
|
|
@ -602,14 +602,51 @@ end:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int hdmi_panel_setup_dc(struct hdmi_panel *panel)
|
||||
{
|
||||
u32 hdmi_ctrl_reg;
|
||||
u32 vbi_pkt_reg;
|
||||
int rc = 0;
|
||||
|
||||
pr_debug("Deep Color: %s\n", panel->data->dc_enable ? "ON" : "OFF");
|
||||
|
||||
/* enable deep color if supported */
|
||||
if (panel->data->dc_enable) {
|
||||
hdmi_ctrl_reg = DSS_REG_R(panel->io, HDMI_CTRL);
|
||||
|
||||
/* GC CD override */
|
||||
hdmi_ctrl_reg |= BIT(27);
|
||||
|
||||
/* enable deep color for RGB888 30 bits */
|
||||
hdmi_ctrl_reg |= BIT(24);
|
||||
DSS_REG_W(panel->io, HDMI_CTRL, hdmi_ctrl_reg);
|
||||
|
||||
/* Enable GC_CONT and GC_SEND in General Control Packet
|
||||
* (GCP) register so that deep color data is
|
||||
* transmitted to the sink on every frame, allowing
|
||||
* the sink to decode the data correctly.
|
||||
*
|
||||
* GC_CONT: 0x1 - Send GCP on every frame
|
||||
* GC_SEND: 0x1 - Enable GCP Transmission
|
||||
*/
|
||||
vbi_pkt_reg = DSS_REG_R(panel->io, HDMI_VBI_PKT_CTRL);
|
||||
vbi_pkt_reg |= BIT(5) | BIT(4);
|
||||
DSS_REG_W(panel->io, HDMI_VBI_PKT_CTRL, vbi_pkt_reg);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int hdmi_panel_setup_scrambler(struct hdmi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
int timeout_hsync;
|
||||
u32 reg_val = 0;
|
||||
u32 tmds_clock_ratio = 0;
|
||||
u32 tmds_clock = 0;
|
||||
bool scrambler_on = false;
|
||||
struct msm_hdmi_mode_timing_info *timing = NULL;
|
||||
struct mdss_panel_info *pinfo = NULL;
|
||||
|
||||
if (!panel) {
|
||||
pr_err("invalid input\n");
|
||||
|
@ -622,13 +659,22 @@ static int hdmi_panel_setup_scrambler(struct hdmi_panel *panel)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
pinfo = panel->data->pinfo;
|
||||
if (!pinfo) {
|
||||
pr_err("invalid panel data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Scrambling is supported from HDMI TX 4.0 */
|
||||
if (panel->version < HDMI_TX_SCRAMBLER_MIN_TX_VERSION) {
|
||||
pr_debug("scrambling not supported by tx\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (timing->pixel_freq > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) {
|
||||
tmds_clock = hdmi_tx_setup_tmds_clk_rate(timing->pixel_freq,
|
||||
pinfo->out_format, panel->data->dc_enable);
|
||||
|
||||
if (tmds_clock > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) {
|
||||
scrambler_on = true;
|
||||
tmds_clock_ratio = 1;
|
||||
} else {
|
||||
|
@ -798,6 +844,12 @@ static int hdmi_panel_power_on(void *input)
|
|||
pr_err("scrambler setup failed. rc=%d\n", rc);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = hdmi_panel_setup_dc(panel);
|
||||
if (rc) {
|
||||
pr_err("Deep Color setup failed. rc=%d\n", rc);
|
||||
goto err;
|
||||
}
|
||||
end:
|
||||
panel->on = true;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
* @infoframe: set to true if infoframes should be sent to sink
|
||||
* @is_it_content: set to true if content is IT
|
||||
* @scrambler: set to true if scrambler needs to be enabled
|
||||
* @dc_enable: set to true if deep color is enabled
|
||||
*/
|
||||
struct hdmi_panel_data {
|
||||
struct mdss_panel_info *pinfo;
|
||||
|
@ -39,6 +40,7 @@ struct hdmi_panel_data {
|
|||
bool infoframe;
|
||||
bool is_it_content;
|
||||
bool scrambler;
|
||||
bool dc_enable;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "mdss.h"
|
||||
#include "mdss_panel.h"
|
||||
#include "mdss_hdmi_mhl.h"
|
||||
#include "mdss_hdmi_util.h"
|
||||
|
||||
#define DRV_NAME "hdmi-tx"
|
||||
#define COMPATIBLE_NAME "qcom,hdmi-tx"
|
||||
|
@ -58,13 +59,6 @@
|
|||
#define AUDIO_POLL_SLEEP_US (5 * 1000)
|
||||
#define AUDIO_POLL_TIMEOUT_US (AUDIO_POLL_SLEEP_US * 1000)
|
||||
|
||||
#define HDMI_TX_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO 2
|
||||
#define HDMI_TX_YUV422_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
|
||||
#define HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
|
||||
|
||||
#define HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ 340000
|
||||
#define HDMI_TX_SCRAMBLER_TIMEOUT_MSEC 200
|
||||
|
||||
/* Maximum pixel clock rates for hdmi tx */
|
||||
#define HDMI_DEFAULT_MAX_PCLK_RATE 148500
|
||||
#define HDMI_TX_3_MAX_PCLK_RATE 297000
|
||||
|
@ -111,7 +105,6 @@ static irqreturn_t hdmi_tx_isr(int irq, void *data);
|
|||
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_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);
|
||||
|
@ -318,11 +311,29 @@ static inline bool hdmi_tx_metadata_type_one(struct hdmi_tx_ctrl *hdmi_ctrl)
|
|||
return hdr_data->metadata_type_one;
|
||||
}
|
||||
|
||||
static inline bool hdmix_tx_sink_dc_support(struct hdmi_tx_ctrl *hdmi_ctrl)
|
||||
{
|
||||
void *edid_fd = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
|
||||
|
||||
if (hdmi_ctrl->panel_data.panel_info.out_format == MDP_Y_CBCR_H2V2)
|
||||
return (hdmi_edid_get_deep_color(edid_fd) & BIT(4));
|
||||
else
|
||||
return (hdmi_edid_get_deep_color(edid_fd) & BIT(1));
|
||||
}
|
||||
|
||||
static inline bool hdmi_tx_dc_support(struct hdmi_tx_ctrl *hdmi_ctrl)
|
||||
{
|
||||
return hdmi_ctrl->dc_feature_on && hdmi_ctrl->dc_support &&
|
||||
(hdmi_edid_get_deep_color(
|
||||
hdmi_tx_get_fd(HDMI_TX_FEAT_EDID)) & BIT(1));
|
||||
/* actual pixel clock if deep color is enabled */
|
||||
void *edid_fd = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
|
||||
u32 tmds_clk_with_dc = hdmi_tx_setup_tmds_clk_rate(
|
||||
hdmi_ctrl->timing.pixel_freq,
|
||||
hdmi_ctrl->panel.pinfo->out_format,
|
||||
true);
|
||||
|
||||
return hdmi_ctrl->dc_feature_on &&
|
||||
hdmi_ctrl->dc_support &&
|
||||
hdmix_tx_sink_dc_support(hdmi_ctrl) &&
|
||||
(tmds_clk_with_dc <= hdmi_edid_get_max_pclk(edid_fd));
|
||||
}
|
||||
|
||||
static const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
|
||||
|
@ -349,7 +360,10 @@ static const char *hdmi_tx_io_name(u32 type)
|
|||
static void hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
|
||||
{
|
||||
if (hdmi_ctrl && hdmi_ctrl->audio_ops.on) {
|
||||
u32 pclk = hdmi_tx_setup_tmds_clk_rate(hdmi_ctrl);
|
||||
u32 pclk = hdmi_tx_setup_tmds_clk_rate(
|
||||
hdmi_ctrl->timing.pixel_freq,
|
||||
hdmi_ctrl->panel.pinfo->out_format,
|
||||
hdmi_ctrl->panel.dc_enable);
|
||||
|
||||
hdmi_ctrl->audio_ops.on(hdmi_ctrl->audio_data,
|
||||
pclk, &hdmi_ctrl->audio_params);
|
||||
|
@ -2345,7 +2359,6 @@ static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
|
|||
struct dss_io_data *io = NULL;
|
||||
/* Defaults: Disable block, HDMI mode */
|
||||
u32 hdmi_ctrl_reg = BIT(1);
|
||||
u32 vbi_pkt_reg;
|
||||
|
||||
if (!hdmi_ctrl) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
|
@ -2383,27 +2396,6 @@ static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
|
|||
* longer be used
|
||||
*/
|
||||
hdmi_ctrl_reg |= BIT(31);
|
||||
|
||||
/* enable deep color if supported */
|
||||
if (hdmi_tx_dc_support(hdmi_ctrl)) {
|
||||
/* GC CD override */
|
||||
hdmi_ctrl_reg |= BIT(27);
|
||||
|
||||
/* enable deep color for RGB888 30 bits */
|
||||
hdmi_ctrl_reg |= BIT(24);
|
||||
|
||||
/* Enable GC_CONT and GC_SEND in General Control Packet
|
||||
* (GCP) register so that deep color data is
|
||||
* transmitted to the sink on every frame, allowing
|
||||
* the sink to decode the data correctly.
|
||||
*
|
||||
* GC_CONT: 0x1 - Send GCP on every frame
|
||||
* GC_SEND: 0x1 - Enable GCP Transmission
|
||||
*/
|
||||
vbi_pkt_reg = DSS_REG_R(io, HDMI_VBI_PKT_CTRL);
|
||||
vbi_pkt_reg |= BIT(5) | BIT(4);
|
||||
DSS_REG_W(io, HDMI_VBI_PKT_CTRL, vbi_pkt_reg);
|
||||
}
|
||||
}
|
||||
|
||||
DSS_REG_W(io, HDMI_CTRL, hdmi_ctrl_reg);
|
||||
|
@ -2973,44 +2965,6 @@ static int hdmi_tx_get_cable_status(struct platform_device *pdev, u32 vote)
|
|||
return hpd;
|
||||
}
|
||||
|
||||
static int hdmi_tx_setup_tmds_clk_rate(struct hdmi_tx_ctrl *hdmi_ctrl)
|
||||
{
|
||||
u32 rate = 0;
|
||||
struct msm_hdmi_mode_timing_info *timing = NULL;
|
||||
u32 rate_ratio;
|
||||
|
||||
if (!hdmi_ctrl) {
|
||||
DEV_ERR("%s: Bad input parameters\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
timing = &hdmi_ctrl->timing;
|
||||
if (!timing) {
|
||||
DEV_ERR("%s: Invalid timing info\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch (hdmi_ctrl->panel_data.panel_info.out_format) {
|
||||
case MDP_Y_CBCR_H2V2:
|
||||
rate_ratio = HDMI_TX_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO;
|
||||
break;
|
||||
case MDP_Y_CBCR_H2V1:
|
||||
rate_ratio = HDMI_TX_YUV422_24BPP_PCLK_TMDS_CH_RATE_RATIO;
|
||||
break;
|
||||
default:
|
||||
rate_ratio = HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO;
|
||||
break;
|
||||
}
|
||||
|
||||
rate = timing->pixel_freq / rate_ratio;
|
||||
|
||||
if (hdmi_tx_dc_support(hdmi_ctrl))
|
||||
rate += rate >> 2;
|
||||
|
||||
end:
|
||||
return rate;
|
||||
}
|
||||
|
||||
static inline bool hdmi_tx_hw_is_cable_connected(struct hdmi_tx_ctrl *hdmi_ctrl)
|
||||
{
|
||||
return DSS_REG_R(&hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO],
|
||||
|
@ -3117,7 +3071,7 @@ static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl)
|
|||
void *pdata = hdmi_tx_get_fd(HDMI_TX_FEAT_PANEL);
|
||||
void *edata = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
|
||||
|
||||
hdmi_panel_get_vic(&panel_data->panel_info,
|
||||
hdmi_ctrl->vic = hdmi_panel_get_vic(&panel_data->panel_info,
|
||||
&hdmi_ctrl->ds_data);
|
||||
|
||||
if (hdmi_ctrl->vic <= 0) {
|
||||
|
@ -3144,16 +3098,14 @@ static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl)
|
|||
hdmi_ctrl->vic);
|
||||
hdmi_ctrl->panel.scrambler = hdmi_edid_get_sink_scrambler_support(
|
||||
edata);
|
||||
hdmi_ctrl->panel.dc_enable = hdmi_tx_dc_support(hdmi_ctrl);
|
||||
|
||||
if (hdmi_ctrl->panel_ops.on)
|
||||
hdmi_ctrl->panel_ops.on(pdata);
|
||||
|
||||
pixel_clk = hdmi_ctrl->timing.pixel_freq * 1000;
|
||||
|
||||
if (panel_data->panel_info.out_format == MDP_Y_CBCR_H2V2)
|
||||
pixel_clk >>= 1;
|
||||
else if (hdmi_tx_dc_support(hdmi_ctrl))
|
||||
pixel_clk += pixel_clk >> 2;
|
||||
pixel_clk = hdmi_tx_setup_tmds_clk_rate(hdmi_ctrl->timing.pixel_freq,
|
||||
hdmi_ctrl->panel.pinfo->out_format,
|
||||
hdmi_ctrl->panel.dc_enable) * 1000;
|
||||
|
||||
DEV_DBG("%s: setting pixel clk %d\n", __func__, pixel_clk);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/msm_mdp.h>
|
||||
#include "mdss_hdmi_util.h"
|
||||
|
||||
#define RESOLUTION_NAME_STR_LEN 30
|
||||
|
@ -26,6 +27,10 @@
|
|||
|
||||
#define HDMI_SCDC_UNKNOWN_REGISTER "Unknown register"
|
||||
|
||||
#define HDMI_TX_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO 2
|
||||
#define HDMI_TX_YUV422_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
|
||||
#define HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
|
||||
|
||||
static char res_buf[RESOLUTION_NAME_STR_LEN];
|
||||
|
||||
enum trigger_mode {
|
||||
|
@ -738,6 +743,30 @@ ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf, u32 size)
|
|||
return len;
|
||||
} /* hdmi_get_video_3d_fmt_2string */
|
||||
|
||||
int hdmi_tx_setup_tmds_clk_rate(u32 pixel_freq, u32 out_format, bool dc_enable)
|
||||
{
|
||||
u32 rate_ratio;
|
||||
|
||||
switch (out_format) {
|
||||
case MDP_Y_CBCR_H2V2:
|
||||
rate_ratio = HDMI_TX_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO;
|
||||
break;
|
||||
case MDP_Y_CBCR_H2V1:
|
||||
rate_ratio = HDMI_TX_YUV422_24BPP_PCLK_TMDS_CH_RATE_RATIO;
|
||||
break;
|
||||
default:
|
||||
rate_ratio = HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO;
|
||||
break;
|
||||
}
|
||||
|
||||
pixel_freq /= rate_ratio;
|
||||
|
||||
if (dc_enable)
|
||||
pixel_freq += pixel_freq >> 2;
|
||||
|
||||
return pixel_freq;
|
||||
}
|
||||
|
||||
static void hdmi_ddc_trigger(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
|
||||
enum trigger_mode mode, bool seg)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "video/msm_hdmi_modes.h"
|
||||
|
||||
#include "mdss_panel.h"
|
||||
#include "mdss_hdmi_panel.h"
|
||||
|
||||
/* HDMI_TX Registers */
|
||||
#define HDMI_CTRL (0x00000000)
|
||||
|
@ -495,6 +496,7 @@ bool hdmi_is_valid_resv_timing(int mode);
|
|||
void hdmi_reset_resv_timing_info(void);
|
||||
int hdmi_panel_get_vic(struct mdss_panel_info *pinfo,
|
||||
struct hdmi_util_ds_data *ds_data);
|
||||
int hdmi_tx_setup_tmds_clk_rate(u32 pixel_freq, u32 out_format, bool dc_enable);
|
||||
|
||||
/* todo: Fix this. Right now this is defined in mdss_hdmi_tx.c */
|
||||
void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, u32 type);
|
||||
|
|
Loading…
Add table
Reference in a new issue