mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 21:22:09 -04:00
disp: msm: dp: add support for eDP display
Changes to support eDP display detection and bringup through panel power sequencing. Change-Id: Ie20906467c209872296e8b5475cee0ca98a3b232 Signed-off-by: Soutrik Mukhopadhyay <quic_mukhopad@quicinc.com> Signed-off-by: Nilesh Laad <quic_nlaad@quicinc.com>
This commit is contained in:
parent
372aa23cee
commit
fc6b8eb5d0
10 changed files with 269 additions and 13 deletions
|
|
@ -11,6 +11,8 @@
|
|||
#include "dp_catalog.h"
|
||||
#include "dp_reg.h"
|
||||
#include "dp_debug.h"
|
||||
#include "dp_link.h"
|
||||
#include "dp_lphw_hpd.h"
|
||||
|
||||
#define DP_GET_MSB(x) (x >> 8)
|
||||
#define DP_GET_LSB(x) (x & 0xff)
|
||||
|
|
@ -2342,6 +2344,32 @@ static u32 dp_catalog_hpd_get_interrupt(struct dp_catalog_hpd *hpd)
|
|||
return isr;
|
||||
}
|
||||
|
||||
static bool dp_catalog_hpd_wait_for_edp_panel_ready(struct dp_catalog_hpd *hpd)
|
||||
{
|
||||
u32 reg, state;
|
||||
void __iomem *base;
|
||||
bool success = true;
|
||||
u32 const poll_sleep_us = 2000;
|
||||
u32 const pll_timeout_us = 1000000;
|
||||
struct dp_catalog_private *catalog;
|
||||
|
||||
catalog = dp_catalog_get_priv(hpd);
|
||||
|
||||
base = catalog->io.dp_aux->io.base;
|
||||
|
||||
reg = DP_DP_HPD_INT_STATUS;
|
||||
|
||||
if (readl_poll_timeout_atomic((base + reg), state,
|
||||
((state & DP_HPD_STATE_STATUS_CONNECTED) > 0),
|
||||
poll_sleep_us, pll_timeout_us)) {
|
||||
DP_ERR("DP_HPD_STATE_STATUS CONNECTED bit is still low, status=%x\n", state);
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void dp_catalog_audio_init(struct dp_catalog_audio *audio)
|
||||
{
|
||||
struct dp_catalog_private *catalog;
|
||||
|
|
@ -2836,6 +2864,7 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
|
|||
struct dp_catalog_hpd hpd = {
|
||||
.config_hpd = dp_catalog_hpd_config_hpd,
|
||||
.get_interrupt = dp_catalog_hpd_get_interrupt,
|
||||
.wait_for_edp_panel_ready = dp_catalog_hpd_wait_for_edp_panel_ready,
|
||||
};
|
||||
struct dp_catalog_audio audio = {
|
||||
.init = dp_catalog_audio_init,
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ struct dp_catalog_ctrl {
|
|||
struct dp_catalog_hpd {
|
||||
void (*config_hpd)(struct dp_catalog_hpd *hpd, bool en);
|
||||
u32 (*get_interrupt)(struct dp_catalog_hpd *hpd);
|
||||
bool (*wait_for_edp_panel_ready)(struct dp_catalog_hpd *hpd);
|
||||
};
|
||||
|
||||
#define HEADER_BYTE_2_BIT 0
|
||||
|
|
|
|||
|
|
@ -1069,6 +1069,32 @@ error_ctrl:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int dp_display_panel_ready(struct dp_display_private *dp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (dp->dp_display.is_edp) {
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_VCC_EN, true);
|
||||
if (rc) {
|
||||
DP_ERR("Cannot turn edp panel power on");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!(dp->catalog->hpd.wait_for_edp_panel_ready(&dp->catalog->hpd))) {
|
||||
DP_ERR("EDP PANEL is not ready yet, powering off panel\n");
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_VCC_EN, false);
|
||||
if (rc) {
|
||||
DP_ERR("Cannot turn edp panel power off");
|
||||
return rc;
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
dp->panel->init(dp->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_display_host_ready(struct dp_display_private *dp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -1106,7 +1132,6 @@ static int dp_display_host_ready(struct dp_display_private *dp)
|
|||
dp->ctrl->abort(dp->ctrl, false);
|
||||
|
||||
dp->aux->init(dp->aux, dp->parser->aux_cfg);
|
||||
dp->panel->init(dp->panel);
|
||||
|
||||
dp_display_state_add(DP_STATE_READY);
|
||||
/* log this as it results from user action of cable connection */
|
||||
|
|
@ -1220,6 +1245,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
|
|||
goto end;
|
||||
}
|
||||
|
||||
rc = dp_display_panel_ready(dp);
|
||||
|
||||
dp->link->psm_config(dp->link, &dp->panel->link_info, false);
|
||||
dp->debug->psm_enabled = false;
|
||||
|
||||
|
|
@ -2164,6 +2191,7 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel)
|
|||
struct dp_display_private *dp;
|
||||
struct dp_panel *dp_panel;
|
||||
int rc = 0;
|
||||
bool shallow_mode = true;
|
||||
|
||||
if (!dp_display || !panel) {
|
||||
DP_ERR("invalid input\n");
|
||||
|
|
@ -2243,6 +2271,13 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel)
|
|||
goto end;
|
||||
}
|
||||
|
||||
rc = dp_display_panel_ready(dp);
|
||||
if (rc) {
|
||||
dp_display_host_unready(dp);
|
||||
dp_display_host_deinit(dp);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (dp->debug->psm_enabled) {
|
||||
dp->link->psm_config(dp->link, &dp->panel->link_info, false);
|
||||
dp->debug->psm_enabled = false;
|
||||
|
|
@ -2259,7 +2294,7 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel)
|
|||
* and required things.
|
||||
*/
|
||||
rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, dp_panel->fec_en,
|
||||
dp_panel->dsc_en, true);
|
||||
dp_panel->dsc_en, shallow_mode);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
|
|
@ -2381,6 +2416,23 @@ static int dp_display_enable(struct dp_display *dp_display, void *panel)
|
|||
if (rc)
|
||||
goto end;
|
||||
|
||||
/*edp backlight enable and edp pwm enable*/
|
||||
if (dp_display->is_edp) {
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_BACKLIGHT_PWR, true);
|
||||
if (rc) {
|
||||
DP_ERR("Cannot turn edp backlight power on");
|
||||
goto end;
|
||||
}
|
||||
|
||||
usleep_range(99000, 100000);
|
||||
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_PWM, true);
|
||||
if (rc) {
|
||||
DP_ERR("Cannot turn edp PWM on ");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
dp_display_update_dsc_resources(dp, panel, true);
|
||||
dp_display_state_add(DP_STATE_ENABLED);
|
||||
end:
|
||||
|
|
@ -2400,6 +2452,7 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
|
|||
{
|
||||
struct dp_display_private *dp;
|
||||
struct dp_panel *dp_panel;
|
||||
int rc = 0;
|
||||
|
||||
if (!dp_display || !panel) {
|
||||
DP_ERR("invalid input\n");
|
||||
|
|
@ -2438,6 +2491,14 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
|
|||
|
||||
dp_display_stream_post_enable(dp, dp_panel);
|
||||
|
||||
if (dp_display->is_edp) {
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_BACKLIGHT_EN, true);
|
||||
if (rc) {
|
||||
DP_ERR("Cannot turn edp backlight power on");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&dp->hdcp_cb_work);
|
||||
queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ);
|
||||
|
||||
|
|
@ -2491,6 +2552,14 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (dp_display->is_edp) {
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_BACKLIGHT_EN, false);
|
||||
if (rc) {
|
||||
DP_ERR("Cannot turn edp backlight power off");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
dp_display_state_add(DP_STATE_HDCP_ABORTED);
|
||||
cancel_delayed_work_sync(&dp->hdcp_cb_work);
|
||||
if (dp_display_is_hdcp_enabled(dp) &&
|
||||
|
|
@ -2539,7 +2608,7 @@ end:
|
|||
|
||||
static int dp_display_disable(struct dp_display *dp_display, void *panel)
|
||||
{
|
||||
int i;
|
||||
int i, rc = 0;
|
||||
struct dp_display_private *dp = NULL;
|
||||
struct dp_panel *dp_panel = NULL;
|
||||
struct dp_link_hdcp_status *status;
|
||||
|
|
@ -2566,6 +2635,16 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (dp_display->is_edp) {
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_BACKLIGHT_PWR, false);
|
||||
if (rc)
|
||||
DP_ERR("Cannot turn edp backlight power off\n");
|
||||
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_PWM, false);
|
||||
if (rc)
|
||||
DP_ERR("Cannot turn edp PWM off\n");
|
||||
}
|
||||
|
||||
dp_display_stream_disable(dp, dp_panel);
|
||||
dp_display_update_dsc_resources(dp, dp_panel, false);
|
||||
|
||||
|
|
@ -2634,6 +2713,7 @@ static int dp_display_unprepare(struct dp_display *dp_display, void *panel)
|
|||
struct dp_display_private *dp;
|
||||
struct dp_panel *dp_panel = panel;
|
||||
u32 flags = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (!dp_display || !panel) {
|
||||
DP_ERR("invalid input\n");
|
||||
|
|
@ -2671,6 +2751,13 @@ static int dp_display_unprepare(struct dp_display *dp_display, void *panel)
|
|||
dp_display_state_add(DP_STATE_SRC_PWRDN);
|
||||
}
|
||||
|
||||
if (dp_display->is_edp) {
|
||||
rc = dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_VCC_EN, false);
|
||||
if (rc) {
|
||||
DP_ERR("Cannot turn edp panel power off\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
dp_display_state_remove(DP_STATE_ENABLED);
|
||||
dp->aux->state = DP_STATE_CTRL_POWERED_OFF;
|
||||
|
||||
|
|
@ -2689,18 +2776,25 @@ end:
|
|||
static int dp_display_validate_link_clock(struct dp_display_private *dp,
|
||||
struct drm_display_mode *mode, struct dp_display_mode dp_mode)
|
||||
{
|
||||
u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
|
||||
u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0, lane_count = 0;
|
||||
bool dsc_en;
|
||||
int rate;
|
||||
int rate = 0;
|
||||
|
||||
dsc_en = (dp_mode.timing.comp_info.comp_ratio > 1) ? true : false;
|
||||
mode_bpp = dsc_en ?
|
||||
DSC_BPP(dp_mode.timing.comp_info.dsc_info.config)
|
||||
: dp_mode.timing.bpp;
|
||||
|
||||
if (dp->dp_display.is_edp) {
|
||||
rate = dp->panel->link_info.rate;
|
||||
lane_count = dp->panel->link_info.num_lanes;
|
||||
} else {
|
||||
rate = drm_dp_bw_code_to_link_rate(dp->link->link_params.bw_code);
|
||||
lane_count = dp->link->link_params.lane_count;
|
||||
}
|
||||
|
||||
mode_rate_khz = mode->clock * mode_bpp;
|
||||
rate = drm_dp_bw_code_to_link_rate(dp->link->link_params.bw_code);
|
||||
supported_rate_khz = dp->link->link_params.lane_count * rate * 8;
|
||||
supported_rate_khz = lane_count * rate * 8;
|
||||
|
||||
if (mode_rate_khz > supported_rate_khz) {
|
||||
DP_DEBUG("mode_rate: %d kHz, supported_rate: %d kHz\n",
|
||||
|
|
@ -3607,6 +3701,71 @@ static int dp_display_mst_get_fixed_topology_display_type(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dp_display_edp_detect(struct dp_display *dp_display)
|
||||
{
|
||||
struct device *dev;
|
||||
struct dp_display_private *dp;
|
||||
int rc = 0;
|
||||
|
||||
dp = container_of(dp_display, struct dp_display_private, dp_display);
|
||||
dev = &dp->pdev->dev;
|
||||
|
||||
if (dp->dp_display.is_sst_connected)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&dp->session_lock);
|
||||
|
||||
rc = dp_display_host_init(dp);
|
||||
if (rc) {
|
||||
DP_ERR("Host init Failed");
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp->dp_display.is_sst_connected = true;
|
||||
dp->hpd->hpd_high = true;
|
||||
dp->hpd->alt_mode_cfg_done = true;
|
||||
|
||||
dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz, dp->debug->max_pclk_khz);
|
||||
|
||||
rc = dp_display_host_ready(dp);
|
||||
if (rc) {
|
||||
dp_display_state_show("[ready failed]");
|
||||
dp_display_host_deinit(dp);
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = dp_display_panel_ready(dp);
|
||||
if (rc) {
|
||||
dp_display_host_unready(dp);
|
||||
dp_display_host_deinit(dp);
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp->link->psm_config(dp->link, &dp->panel->link_info, false);
|
||||
dp->debug->psm_enabled = false;
|
||||
|
||||
rc = dp->panel->read_sink_caps(dp->panel,
|
||||
dp->dp_display.base_connector, dp->hpd->multi_func);
|
||||
|
||||
if (rc == -ETIMEDOUT || rc == -ENOTCONN)
|
||||
goto end;
|
||||
|
||||
dp_display_state_remove(DP_STATE_ABORTED);
|
||||
dp_display_state_add(DP_STATE_CONFIGURED);
|
||||
dp_display_state_add(DP_STATE_CONNECTED);
|
||||
|
||||
dp->link->process_request(dp->link);
|
||||
dp->panel->handle_sink_request(dp->panel);
|
||||
|
||||
dp_display_state_add(DP_STATE_CONNECT_NOTIFIED);
|
||||
dp_display_state_remove(DP_STATE_DISCONNECT_NOTIFIED);
|
||||
|
||||
dp->power->edp_panel_set_gpio(dp->power, DP_GPIO_EDP_VCC_EN, false);
|
||||
end:
|
||||
mutex_unlock(&dp->session_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_display_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -3697,6 +3856,7 @@ static int dp_display_probe(struct platform_device *pdev)
|
|||
dp_display_mst_get_fixed_topology_display_type;
|
||||
|
||||
g_dp_display->is_edp = (info->display_type == DRM_MODE_CONNECTOR_eDP) ? true : false;
|
||||
g_dp_display->edp_detect = dp_display_edp_detect;
|
||||
|
||||
rc = component_add(&pdev->dev, &dp_display_comp_ops);
|
||||
if (rc) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <drm/sde_drm.h>
|
||||
|
||||
#include "dp_panel.h"
|
||||
#include "dp_parser.h"
|
||||
|
||||
#define DP_MST_SIM_MAX_PORTS 8
|
||||
|
||||
|
|
@ -138,6 +139,7 @@ struct dp_display {
|
|||
const char **display_type);
|
||||
int (*mst_get_fixed_topology_display_type)(struct dp_display *dp_display,
|
||||
u32 strm_id, const char **display_type);
|
||||
int (*edp_detect)(struct dp_display *dp_display);
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_MSM_DP)
|
||||
|
|
|
|||
|
|
@ -476,11 +476,13 @@ enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
|
|||
{
|
||||
enum drm_connector_status status = connector_status_unknown;
|
||||
struct msm_display_info info;
|
||||
struct dp_display *dp_disp;
|
||||
int rc;
|
||||
|
||||
if (!conn || !display)
|
||||
return status;
|
||||
|
||||
dp_disp = display;
|
||||
/* get display dp_info */
|
||||
memset(&info, 0x0, sizeof(info));
|
||||
rc = dp_connector_get_info(conn, &info, display);
|
||||
|
|
@ -489,12 +491,18 @@ enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
|
|||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (info.capabilities & MSM_DISPLAY_CAP_HOT_PLUG)
|
||||
if (info.capabilities & MSM_DISPLAY_CAP_HOT_PLUG) {
|
||||
status = (info.is_connected ? connector_status_connected :
|
||||
connector_status_disconnected);
|
||||
else
|
||||
} else {
|
||||
status = connector_status_connected;
|
||||
|
||||
rc = dp_disp->edp_detect(dp_disp);
|
||||
if (rc) {
|
||||
DP_ERR("error in turning on panel power sequence rc:%d\n", rc);
|
||||
return connector_status_unknown;
|
||||
}
|
||||
}
|
||||
conn->display_info.width_mm = info.width_mm;
|
||||
conn->display_info.height_mm = info.height_mm;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
@ -12,6 +13,7 @@
|
|||
#define DP_IRQ_HPD_INT_STATUS BIT(1)
|
||||
#define DP_HPD_REPLUG_INT_STATUS BIT(2)
|
||||
#define DP_HPD_UNPLUG_INT_STATUS BIT(3)
|
||||
#define DP_HPD_STATE_STATUS_CONNECTED BIT(30)
|
||||
|
||||
/**
|
||||
* dp_lphw_hpd_get() - configure and get the DisplayPlot HPD module data
|
||||
|
|
|
|||
|
|
@ -258,23 +258,26 @@ static int dp_parser_gpio(struct dp_parser *parser)
|
|||
struct device *dev = &parser->pdev->dev;
|
||||
struct device_node *of_node = dev->of_node;
|
||||
struct dss_module_power *mp = &parser->mp[DP_CORE_PM];
|
||||
static const char * const dp_gpios[] = {
|
||||
static const char * const dp_gpios[DP_GPIO_MAX] = {
|
||||
"qcom,aux-en-gpio",
|
||||
"qcom,aux-sel-gpio",
|
||||
"qcom,usbplug-cc-gpio",
|
||||
"qcom,edp-vcc-en-gpio",
|
||||
"qcom,edp-backlight-pwr-gpio",
|
||||
"qcom,edp-pwm-en-gpio",
|
||||
"qcom,edp-backlight-en-gpio",
|
||||
};
|
||||
|
||||
if (of_find_property(of_node, "qcom,dp-hpd-gpio", NULL)) {
|
||||
parser->no_aux_switch = true;
|
||||
parser->lphw_hpd = of_find_property(of_node,
|
||||
"qcom,dp-low-power-hw-hpd", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (of_find_property(of_node, "qcom,dp-gpio-aux-switch", NULL))
|
||||
parser->gpio_aux_switch = true;
|
||||
mp->gpio_config = devm_kzalloc(dev,
|
||||
sizeof(struct dss_gpio) * ARRAY_SIZE(dp_gpios), GFP_KERNEL);
|
||||
sizeof(struct dss_gpio) * DP_GPIO_MAX, GFP_KERNEL);
|
||||
if (!mp->gpio_config)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,20 @@ enum dp_pm_type {
|
|||
DP_MAX_PM
|
||||
};
|
||||
|
||||
enum dp_pin_states {
|
||||
DP_GPIO_AUX_ENABLE,
|
||||
DP_GPIO_AUX_SEL,
|
||||
DP_GPIO_USBPLUG_CC,
|
||||
DP_GPIO_CMN_MAX = DP_GPIO_USBPLUG_CC,
|
||||
DP_GPIO_EDP_VCC_EN,
|
||||
DP_GPIO_EDP_MIN = DP_GPIO_EDP_VCC_EN,
|
||||
DP_GPIO_EDP_BACKLIGHT_PWR,
|
||||
DP_GPIO_EDP_PWM,
|
||||
DP_GPIO_EDP_BACKLIGHT_EN,
|
||||
DP_GPIO_EDP_MAX,
|
||||
DP_GPIO_MAX = DP_GPIO_EDP_MAX,
|
||||
};
|
||||
|
||||
static inline const char *dp_parser_pm_name(enum dp_pm_type module)
|
||||
{
|
||||
switch (module) {
|
||||
|
|
|
|||
|
|
@ -388,6 +388,7 @@ static int dp_power_request_gpios(struct dp_power_private *power)
|
|||
struct dss_module_power *mp;
|
||||
static const char * const gpio_names[] = {
|
||||
"aux_enable", "aux_sel", "usbplug_cc",
|
||||
"edp_vcc_enable", "edp_backlight_pwr", "edp_pwm_en", "edp_backlight_en",
|
||||
};
|
||||
|
||||
if (!power) {
|
||||
|
|
@ -410,6 +411,7 @@ static int dp_power_request_gpios(struct dp_power_private *power)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
for (i = 0; i < ARRAY_SIZE(gpio_names); i++) {
|
||||
|
|
@ -432,7 +434,7 @@ static void dp_power_set_gpio(struct dp_power_private *power, bool flip)
|
|||
struct dss_module_power *mp = &power->parser->mp[DP_CORE_PM];
|
||||
struct dss_gpio *config = mp->gpio_config;
|
||||
|
||||
for (i = 0; i < mp->num_gpio; i++) {
|
||||
for (i = 0; i <= DP_GPIO_CMN_MAX; i++) {
|
||||
if (dp_power_find_gpio(config->gpio_name, "aux-sel"))
|
||||
config->value = flip;
|
||||
|
||||
|
|
@ -689,6 +691,37 @@ exit:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int dp_power_edp_panel_set_gpio(struct dp_power *dp_power,
|
||||
enum dp_pin_states pin_state, bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_power_private *power;
|
||||
struct dss_module_power *mp;
|
||||
struct dss_gpio *config;
|
||||
|
||||
if (!dp_power) {
|
||||
DP_ERR("invalid power data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
power = container_of(dp_power, struct dp_power_private, dp_power);
|
||||
|
||||
mp = &power->parser->mp[DP_CORE_PM];
|
||||
config = mp->gpio_config;
|
||||
|
||||
if (config == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if ((pin_state >= DP_GPIO_EDP_MIN) && (pin_state < DP_GPIO_EDP_MAX)) {
|
||||
gpio_direction_output(config[pin_state].gpio, enable);
|
||||
} else {
|
||||
pr_err(" Invalid GPIO call\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct dp_power *dp_power_get(struct dp_parser *parser, struct dp_pll *pll)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -720,6 +753,7 @@ struct dp_power *dp_power_get(struct dp_parser *parser, struct dp_pll *pll)
|
|||
dp_power->clk_get_rate = dp_power_clk_get_rate;
|
||||
dp_power->power_client_init = dp_power_client_init;
|
||||
dp_power->power_client_deinit = dp_power_client_deinit;
|
||||
dp_power->edp_panel_set_gpio = dp_power_edp_panel_set_gpio;
|
||||
|
||||
return dp_power;
|
||||
error:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
@ -34,6 +35,8 @@ struct dp_power {
|
|||
struct sde_power_handle *phandle,
|
||||
struct drm_device *drm_dev);
|
||||
void (*power_client_deinit)(struct dp_power *power);
|
||||
int (*edp_panel_set_gpio)(struct dp_power *power, enum dp_pin_states pin_state,
|
||||
bool enable);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue