mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 23:24:22 -04:00
Merge "drm: msm: dp: Fix DSC and FEC handling"
This commit is contained in:
commit
8034367c13
4 changed files with 68 additions and 44 deletions
|
|
@ -69,6 +69,7 @@ struct dp_ctrl_private {
|
|||
bool power_on;
|
||||
bool mst_mode;
|
||||
bool fec_mode;
|
||||
bool dsc_mode;
|
||||
|
||||
atomic_t aborted;
|
||||
|
||||
|
|
@ -575,7 +576,6 @@ end:
|
|||
static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl)
|
||||
{
|
||||
int ret = 0;
|
||||
const unsigned int fec_cfg_dpcd = 0x120;
|
||||
|
||||
if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
|
||||
goto end;
|
||||
|
|
@ -588,7 +588,8 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl)
|
|||
ctrl->catalog->reset(ctrl->catalog);
|
||||
|
||||
if (ctrl->fec_mode)
|
||||
drm_dp_dpcd_writeb(ctrl->aux->drm_aux, fec_cfg_dpcd, 0x01);
|
||||
drm_dp_dpcd_writeb(ctrl->aux->drm_aux, DP_FEC_CONFIGURATION,
|
||||
0x01);
|
||||
|
||||
ret = dp_ctrl_link_train(ctrl);
|
||||
|
||||
|
|
@ -926,7 +927,7 @@ static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl)
|
|||
ctrl->aux->init(ctrl->aux, ctrl->parser->aux_cfg);
|
||||
|
||||
ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode,
|
||||
ctrl->fec_mode, false);
|
||||
ctrl->fec_mode, ctrl->dsc_mode, false);
|
||||
if (ret)
|
||||
DP_ERR("failed to enable DP controller\n");
|
||||
|
||||
|
|
@ -1138,19 +1139,18 @@ static void dp_ctrl_fec_dsc_setup(struct dp_ctrl_private *ctrl)
|
|||
u8 fec_sts = 0;
|
||||
int rlen;
|
||||
u32 dsc_enable;
|
||||
const unsigned int fec_sts_dpcd = 0x280;
|
||||
|
||||
if (ctrl->stream_count || !ctrl->fec_mode)
|
||||
if (!ctrl->fec_mode)
|
||||
return;
|
||||
|
||||
ctrl->catalog->fec_config(ctrl->catalog, ctrl->fec_mode);
|
||||
|
||||
/* wait for controller to start fec sequence */
|
||||
usleep_range(900, 1000);
|
||||
drm_dp_dpcd_readb(ctrl->aux->drm_aux, fec_sts_dpcd, &fec_sts);
|
||||
drm_dp_dpcd_readb(ctrl->aux->drm_aux, DP_FEC_STATUS, &fec_sts);
|
||||
DP_DEBUG("sink fec status:%d\n", fec_sts);
|
||||
|
||||
dsc_enable = ctrl->fec_mode ? 1 : 0;
|
||||
dsc_enable = ctrl->dsc_mode ? 1 : 0;
|
||||
rlen = drm_dp_dpcd_writeb(ctrl->aux->drm_aux, DP_DSC_ENABLE,
|
||||
dsc_enable);
|
||||
if (rlen < 1)
|
||||
|
|
@ -1191,13 +1191,14 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)
|
|||
|
||||
dp_ctrl_wait4video_ready(ctrl);
|
||||
|
||||
dp_ctrl_fec_dsc_setup(ctrl);
|
||||
|
||||
ctrl->stream_count++;
|
||||
|
||||
link_ready = ctrl->catalog->mainlink_ready(ctrl->catalog);
|
||||
DP_DEBUG("mainlink %s\n", link_ready ? "READY" : "NOT READY");
|
||||
|
||||
/* wait for link training completion before fec config as per spec */
|
||||
dp_ctrl_fec_dsc_setup(ctrl);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -1266,7 +1267,7 @@ static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)
|
|||
}
|
||||
|
||||
static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode,
|
||||
bool fec_mode, bool shallow)
|
||||
bool fec_mode, bool dsc_mode, bool shallow)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_ctrl_private *ctrl;
|
||||
|
|
@ -1285,7 +1286,11 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode,
|
|||
goto end;
|
||||
|
||||
ctrl->mst_mode = mst_mode;
|
||||
ctrl->fec_mode = fec_mode;
|
||||
if (fec_mode) {
|
||||
ctrl->fec_mode = fec_mode;
|
||||
ctrl->dsc_mode = dsc_mode;
|
||||
}
|
||||
|
||||
rate = ctrl->panel->link_info.rate;
|
||||
|
||||
if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
|
||||
|
|
@ -1323,6 +1328,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl)
|
|||
if (!ctrl->power_on)
|
||||
return;
|
||||
|
||||
ctrl->catalog->fec_config(ctrl->catalog, false);
|
||||
dp_ctrl_configure_source_link_params(ctrl, false);
|
||||
ctrl->catalog->reset(ctrl->catalog);
|
||||
|
||||
|
|
@ -1333,6 +1339,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl)
|
|||
|
||||
ctrl->mst_mode = false;
|
||||
ctrl->fec_mode = false;
|
||||
ctrl->dsc_mode = false;
|
||||
ctrl->power_on = false;
|
||||
memset(&ctrl->mst_ch_info, 0, sizeof(ctrl->mst_ch_info));
|
||||
DP_DEBUG("DP off done\n");
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ struct dp_ctrl {
|
|||
int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset);
|
||||
void (*deinit)(struct dp_ctrl *dp_ctrl);
|
||||
int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool fec_en,
|
||||
bool shallow);
|
||||
bool dsc_en, bool shallow);
|
||||
void (*off)(struct dp_ctrl *dp_ctrl);
|
||||
void (*abort)(struct dp_ctrl *dp_ctrl);
|
||||
void (*isr)(struct dp_ctrl *dp_ctrl);
|
||||
|
|
|
|||
|
|
@ -884,7 +884,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
|
|||
dp_display_process_mst_hpd_high(dp, false);
|
||||
|
||||
rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active,
|
||||
dp->panel->fec_en, false);
|
||||
dp->panel->fec_en, dp->panel->dsc_en, false);
|
||||
if (rc) {
|
||||
dp_display_state_remove(DP_STATE_CONNECTED);
|
||||
goto end;
|
||||
|
|
@ -1665,7 +1665,8 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel)
|
|||
* So, we execute in shallow mode here to do only minimal
|
||||
* and required things.
|
||||
*/
|
||||
rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, dp_panel->fec_en, true);
|
||||
rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, dp_panel->fec_en,
|
||||
dp_panel->dsc_en, true);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
|
|
|
|||
|
|
@ -2019,14 +2019,7 @@ end:
|
|||
|
||||
static void dp_panel_decode_dsc_dpcd(struct dp_panel *dp_panel)
|
||||
{
|
||||
s64 fec_overhead_fp = drm_fixp_from_fraction(1, 1);
|
||||
|
||||
if (!dp_panel->dsc_feature_enable || !dp_panel->fec_feature_enable) {
|
||||
DP_DEBUG("source dsc is not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dp_panel->dsc_dpcd[0] && dp_panel->fec_dpcd) {
|
||||
if (dp_panel->dsc_dpcd[0]) {
|
||||
dp_panel->sink_dsc_caps.dsc_capable = true;
|
||||
dp_panel->sink_dsc_caps.version = dp_panel->dsc_dpcd[1];
|
||||
dp_panel->sink_dsc_caps.block_pred_en =
|
||||
|
|
@ -2039,21 +2032,13 @@ static void dp_panel_decode_dsc_dpcd(struct dp_panel *dp_panel)
|
|||
dp_panel->dsc_en = false;
|
||||
}
|
||||
|
||||
dp_panel->fec_en = dp_panel->dsc_en;
|
||||
dp_panel->widebus_en = dp_panel->dsc_en;
|
||||
|
||||
/* fec_overhead = 1.00 / 0.97582 */
|
||||
if (dp_panel->fec_en)
|
||||
fec_overhead_fp = drm_fixp_from_fraction(100000, 97582);
|
||||
|
||||
dp_panel->fec_overhead_fp = fec_overhead_fp;
|
||||
}
|
||||
|
||||
static void dp_panel_read_sink_dsc_caps(struct dp_panel *dp_panel)
|
||||
{
|
||||
int rlen;
|
||||
struct dp_panel_private *panel;
|
||||
const int fec_cap = 0x90;
|
||||
int dpcd_rev;
|
||||
|
||||
if (!dp_panel) {
|
||||
|
|
@ -2061,14 +2046,9 @@ static void dp_panel_read_sink_dsc_caps(struct dp_panel *dp_panel)
|
|||
return;
|
||||
}
|
||||
|
||||
dp_panel->dsc_en = false;
|
||||
dp_panel->fec_en = false;
|
||||
|
||||
dpcd_rev = dp_panel->dpcd[DP_DPCD_REV];
|
||||
|
||||
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
|
||||
|
||||
dp_panel->fec_overhead_fp = 0;
|
||||
if (panel->parser->dsc_feature_enable && dpcd_rev >= 0x14) {
|
||||
rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_DSC_SUPPORT,
|
||||
dp_panel->dsc_dpcd, (DP_RECEIVER_DSC_CAP_SIZE + 1));
|
||||
|
|
@ -2081,17 +2061,38 @@ static void dp_panel_read_sink_dsc_caps(struct dp_panel *dp_panel)
|
|||
DUMP_PREFIX_NONE, 8, 1, dp_panel->dsc_dpcd, rlen,
|
||||
false);
|
||||
|
||||
rlen = drm_dp_dpcd_read(panel->aux->drm_aux, fec_cap,
|
||||
&dp_panel->fec_dpcd, 1);
|
||||
if (rlen < 1) {
|
||||
DP_ERR("fec dpcd read failed, rlen=%d\n", rlen);
|
||||
return;
|
||||
}
|
||||
|
||||
dp_panel_decode_dsc_dpcd(dp_panel);
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_panel_read_sink_fec_caps(struct dp_panel *dp_panel)
|
||||
{
|
||||
int rlen;
|
||||
struct dp_panel_private *panel;
|
||||
s64 fec_overhead_fp = drm_fixp_from_fraction(1, 1);
|
||||
|
||||
if (!dp_panel) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
|
||||
rlen = drm_dp_dpcd_readb(panel->aux->drm_aux, DP_FEC_CAPABILITY,
|
||||
&dp_panel->fec_dpcd);
|
||||
if (rlen < 1) {
|
||||
DP_ERR("fec capability read failed, rlen=%d\n", rlen);
|
||||
return;
|
||||
}
|
||||
|
||||
dp_panel->fec_en = dp_panel->fec_dpcd & DP_FEC_CAPABLE;
|
||||
if (dp_panel->fec_en)
|
||||
fec_overhead_fp = drm_fixp_from_fraction(100000, 97582);
|
||||
|
||||
dp_panel->fec_overhead_fp = fec_overhead_fp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
|
||||
struct drm_connector *connector, bool multi_func)
|
||||
{
|
||||
|
|
@ -2148,7 +2149,18 @@ static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
|
|||
dp_panel->dsc_feature_enable = panel->parser->dsc_feature_enable;
|
||||
dp_panel->fec_feature_enable = panel->parser->fec_feature_enable;
|
||||
|
||||
dp_panel_read_sink_dsc_caps(dp_panel);
|
||||
dp_panel->fec_en = false;
|
||||
dp_panel->dsc_en = false;
|
||||
|
||||
if (dp_panel->fec_feature_enable) {
|
||||
dp_panel_read_sink_fec_caps(dp_panel);
|
||||
|
||||
if (dp_panel->dsc_feature_enable && dp_panel->fec_en)
|
||||
dp_panel_read_sink_dsc_caps(dp_panel);
|
||||
}
|
||||
|
||||
DP_INFO("fec_en=%d, dsc_en=%d, widebus_en=%d\n", dp_panel->fec_en,
|
||||
dp_panel->dsc_en, dp_panel->widebus_en);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -2157,9 +2169,13 @@ static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel,
|
|||
u32 mode_edid_bpp, u32 mode_pclk_khz)
|
||||
{
|
||||
struct drm_dp_link *link_info;
|
||||
const u32 max_supported_bpp = 30, min_supported_bpp = 18;
|
||||
const u32 max_supported_bpp = 30;
|
||||
u32 min_supported_bpp = 18;
|
||||
u32 bpp = 0, data_rate_khz = 0;
|
||||
|
||||
if (dp_panel->dsc_en)
|
||||
min_supported_bpp = 24;
|
||||
|
||||
bpp = min_t(u32, mode_edid_bpp, max_supported_bpp);
|
||||
|
||||
link_info = &dp_panel->link_info;
|
||||
|
|
|
|||
Loading…
Reference in a new issue