summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-11-13 13:51:10 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2016-11-13 13:51:09 -0800
commit24d0c1f91eb2850889cb27ef6fdcadc0c8ff2834 (patch)
treed67616ca5e112e3fb9673cf46697c4fe51e73aad /drivers/video
parent23bb5f214ec5b929b321a8c27e24cb4257da2a31 (diff)
parent44b187a8c5a21f13d0791c3b257e532d5523d589 (diff)
Merge "msm: mdss: dp: handle fast attention events"
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c144
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h5
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.c56
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.h11
5 files changed, 169 insertions, 49 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 75e42ca8cd88..29fc4e6fd65b 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -45,6 +45,11 @@
#define VDDA_UA_ON_LOAD 100000 /* uA units */
#define VDDA_UA_OFF_LOAD 100 /* uA units */
+struct mdss_dp_attention_node {
+ u32 vdo;
+ struct list_head list;
+};
+
#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3
static u32 supported_modes[] = {
HDMI_VFRMT_640x480p60_4_3,
@@ -60,6 +65,7 @@ static u32 supported_modes[] = {
static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv);
static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata);
static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp);
+static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp_drv);
static void mdss_dp_put_dt_clk_data(struct device *dev,
struct dss_module_power *module_power)
@@ -1133,7 +1139,7 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp,
mdss_dp_fill_link_cfg(dp);
mdss_dp_mainlink_ctrl(&dp->ctrl_io, true);
mdss_dp_config_ctrl(dp);
- mdss_dp_sw_mvid_nvid(&dp->ctrl_io);
+ mdss_dp_sw_config_msa(&dp->ctrl_io, dp->link_rate, &dp->dp_cc_io);
mdss_dp_timing_cfg(&dp->ctrl_io, &dp->panel_data.panel_info);
}
@@ -1290,7 +1296,6 @@ link_training:
dp_drv->cont_splash = 0;
dp_drv->power_on = true;
- mdss_dp_ack_state(dp_drv, true);
pr_debug("End-\n");
exit:
@@ -1559,6 +1564,7 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
goto edid_error;
}
+ mdss_dp_update_cable_status(dp_drv, true);
mdss_dp_notify_clients(dp_drv, true);
dp_drv->dp_initialized = true;
@@ -1883,8 +1889,13 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp)
}
/* update internal data about hdcp */
- dp->hdcp.data = fd;
- dp->hdcp.ops = ops;
+ if (dp->hdcp.hdcp2_present || dp->hdcp.hdcp1_present) {
+ dp->hdcp.data = fd;
+ dp->hdcp.ops = ops;
+ } else {
+ dp->hdcp.data = NULL;
+ dp->hdcp.ops = NULL;
+ }
}
static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv)
@@ -1920,6 +1931,8 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
if (dp->hdcp.ops && dp->hdcp.ops->authenticate)
rc = dp->hdcp.ops->authenticate(dp->hdcp.data);
+
+ mdss_dp_ack_state(dp, true);
break;
case MDSS_EVENT_PANEL_OFF:
rc = mdss_dp_off(pdata);
@@ -2041,6 +2054,12 @@ static int mdss_retrieve_dp_ctrl_resources(struct platform_device *pdev,
return rc;
}
+ if (msm_dss_ioremap_byname(pdev, &dp_drv->dp_cc_io, "dp_mmss_cc")) {
+ pr_err("%d unable to remap dp MMSS_CC resources\n",
+ __LINE__);
+ return rc;
+ }
+
if (msm_dss_ioremap_byname(pdev, &dp_drv->qfprom_io,
"qfprom_physical"))
pr_warn("unable to remap dp qfprom resources\n");
@@ -2117,6 +2136,9 @@ static void mdss_dp_event_work(struct work_struct *work)
case EV_IDLE_PATTERNS_SENT:
mdss_dp_idle_patterns_sent(dp);
break;
+ case EV_USBPD_ATTENTION:
+ mdss_dp_handle_attention(dp);
+ break;
case EV_USBPD_DISCOVER_MODES:
usbpd_send_svdm(dp->pd, USB_C_DP_SID, USBPD_SVDM_DISCOVER_MODES,
SVDM_CMD_TYPE_INITIATOR, 0x0, 0x0, 0x0);
@@ -2225,6 +2247,7 @@ static int mdss_dp_event_setup(struct mdss_dp_drv_pdata *dp)
INIT_WORK(&dp->work, mdss_dp_event_work);
INIT_DELAYED_WORK(&dp->hdcp_cb_work, mdss_dp_hdcp_cb_work);
+ INIT_LIST_HEAD(&dp->attention_head);
return 0;
}
@@ -2508,6 +2531,7 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
const u32 *vdos, int num_vdos)
{
struct mdss_dp_drv_pdata *dp_drv;
+ struct mdss_dp_attention_node *node;
dp_drv = container_of(hdlr, struct mdss_dp_drv_pdata, svid_handler);
if (!dp_drv->pd) {
@@ -2535,45 +2559,14 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
dp_send_events(dp_drv, EV_USBPD_DP_STATUS);
break;
case USBPD_SVDM_ATTENTION:
- dp_drv->alt_mode.dp_status.response = *vdos;
- mdss_dp_usbpd_ext_dp_status(&dp_drv->alt_mode.dp_status);
-
- dp_drv->hpd_irq_toggled = dp_drv->hpd_irq_on !=
- dp_drv->alt_mode.dp_status.hpd_irq;
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ node->vdo = *vdos;
- if (dp_drv->alt_mode.dp_status.hpd_irq) {
- pr_debug("Attention: hpd_irq high\n");
-
- if (dp_drv->power_on && dp_drv->hdcp.ops &&
- dp_drv->hdcp.ops->cp_irq)
- dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data);
-
- if (!mdss_dp_process_hpd_irq_high(dp_drv))
- break;
- } else if (dp_drv->hpd_irq_toggled) {
- if (!mdss_dp_process_hpd_irq_low(dp_drv))
- break;
- }
-
- if (!dp_drv->alt_mode.dp_status.hpd_high) {
- pr_debug("Attention: HPD low\n");
- mdss_dp_update_cable_status(dp_drv, false);
- mdss_dp_notify_clients(dp_drv, false);
- pr_debug("Attention: Notified clients\n");
- break;
- }
-
- pr_debug("Attention: HPD high\n");
-
- mdss_dp_update_cable_status(dp_drv, true);
-
- dp_drv->alt_mode.current_state |= DP_STATUS_DONE;
-
- if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE)
- mdss_dp_host_init(&dp_drv->panel_data);
- else
- dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE);
+ mutex_lock(&dp_drv->attention_lock);
+ list_add_tail(&node->list, &dp_drv->attention_head);
+ mutex_unlock(&dp_drv->attention_lock);
+ dp_send_events(dp_drv, EV_USBPD_ATTENTION);
break;
case DP_VDM_STATUS:
dp_drv->alt_mode.dp_status.response = *vdos;
@@ -2597,6 +2590,74 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
}
}
+static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
+{
+ dp_drv->hpd_irq_toggled = dp_drv->hpd_irq_on !=
+ dp_drv->alt_mode.dp_status.hpd_irq;
+
+ if (dp_drv->alt_mode.dp_status.hpd_irq) {
+ pr_debug("Attention: hpd_irq high\n");
+
+ if (dp_drv->power_on && dp_drv->hdcp.ops &&
+ dp_drv->hdcp.ops->cp_irq)
+ dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data);
+
+ if (!mdss_dp_process_hpd_irq_high(dp_drv))
+ return;
+ } else if (dp_drv->hpd_irq_toggled) {
+ if (!mdss_dp_process_hpd_irq_low(dp_drv))
+ return;
+ }
+
+ if (!dp_drv->alt_mode.dp_status.hpd_high) {
+ pr_debug("Attention: HPD low\n");
+ mdss_dp_update_cable_status(dp_drv, false);
+ mdss_dp_notify_clients(dp_drv, false);
+ pr_debug("Attention: Notified clients\n");
+ return;
+ }
+
+ pr_debug("Attention: HPD high\n");
+
+ mdss_dp_update_cable_status(dp_drv, true);
+
+ dp_drv->alt_mode.current_state |= DP_STATUS_DONE;
+
+ if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE)
+ mdss_dp_host_init(&dp_drv->panel_data);
+ else
+ dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE);
+
+ pr_debug("exit\n");
+}
+
+static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp)
+{
+ int i = 0;
+
+ while (!list_empty_careful(&dp->attention_head)) {
+ struct mdss_dp_attention_node *node;
+ u32 vdo;
+
+ pr_debug("processing item %d in the list\n", ++i);
+
+ mutex_lock(&dp->attention_lock);
+ node = list_first_entry(&dp->attention_head,
+ struct mdss_dp_attention_node, list);
+
+ vdo = node->vdo;
+ list_del(&node->list);
+ mutex_unlock(&dp->attention_lock);
+
+ kzfree(node);
+
+ dp->alt_mode.dp_status.response = vdo;
+ mdss_dp_usbpd_ext_dp_status(&dp->alt_mode.dp_status);
+ mdss_dp_process_attention(dp);
+ };
+
+}
+
static int mdss_dp_usbpd_setup(struct mdss_dp_drv_pdata *dp_drv)
{
int ret = 0;
@@ -2670,6 +2731,7 @@ static int mdss_dp_probe(struct platform_device *pdev)
dp_drv->mask2 = EDP_INTR_MASK2;
mutex_init(&dp_drv->emutex);
mutex_init(&dp_drv->pd_msg_mutex);
+ mutex_init(&dp_drv->attention_lock);
mutex_init(&dp_drv->hdcp_mutex);
spin_lock_init(&dp_drv->lock);
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index e801eceeef1b..04abe9221acc 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -205,6 +205,7 @@ struct dp_alt_mode {
#define EV_USBPD_DP_CONFIGURE BIT(10)
#define EV_USBPD_CC_PIN_POLARITY BIT(11)
#define EV_USBPD_EXIT_MODE BIT(12)
+#define EV_USBPD_ATTENTION BIT(13)
/* dp state ctrl */
#define ST_TRAIN_PATTERN_1 BIT(0)
@@ -406,6 +407,7 @@ struct mdss_dp_drv_pdata {
struct dss_io_data ctrl_io;
struct dss_io_data phy_io;
struct dss_io_data tcsr_reg_io;
+ struct dss_io_data dp_cc_io;
struct dss_io_data qfprom_io;
struct dss_io_data hdcp_io;
int base_size;
@@ -454,6 +456,7 @@ struct mdss_dp_drv_pdata {
struct mutex aux_mutex;
struct mutex train_mutex;
struct mutex pd_msg_mutex;
+ struct mutex attention_lock;
struct mutex hdcp_mutex;
bool cable_connected;
u32 s3d_mode;
@@ -497,6 +500,8 @@ struct mdss_dp_drv_pdata {
struct dpcd_test_request test_data;
struct dpcd_sink_count sink_count;
+
+ struct list_head attention_head;
};
enum dp_lane_count {
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index f9dba99a653d..e396dfff60ef 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -1647,6 +1647,8 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
clear:
dp_clear_training_pattern(dp);
if (ret != -EINVAL) {
+ mdss_dp_config_misc_settings(&dp->ctrl_io,
+ &dp->panel_data.panel_info);
mdss_dp_setup_tr_unit(&dp->ctrl_io, dp->link_rate,
dp->lane_cnt, dp->vic);
mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO);
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c
index 2d24d8499105..86edc4492599 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.c
+++ b/drivers/video/fbdev/msm/mdss_dp_util.c
@@ -253,10 +253,48 @@ void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io,
writel_relaxed(data, ctrl_io->base + DP_ACTIVE_HOR_VER);
}
-void mdss_dp_sw_mvid_nvid(struct dss_io_data *ctrl_io)
+void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io,
+ char lrate, struct dss_io_data *dp_cc_io)
{
- writel_relaxed(0x37, ctrl_io->base + DP_SOFTWARE_MVID);
- writel_relaxed(0x3c, ctrl_io->base + DP_SOFTWARE_NVID);
+ u32 pixel_m, pixel_n;
+ u32 mvid, nvid;
+
+ pixel_m = readl_relaxed(dp_cc_io->base + MMSS_DP_PIXEL_M);
+ pixel_n = readl_relaxed(dp_cc_io->base + MMSS_DP_PIXEL_N);
+ pr_debug("pixel_m=0x%x, pixel_n=0x%x\n",
+ pixel_m, pixel_n);
+
+ mvid = (pixel_m & 0xFFFF) * 5;
+ nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
+ if (lrate == DP_LINK_RATE_540)
+ nvid = nvid * 2;
+ pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
+ writel_relaxed(mvid, ctrl_io->base + DP_SOFTWARE_MVID);
+ writel_relaxed(nvid, ctrl_io->base + DP_SOFTWARE_NVID);
+}
+
+void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io,
+ struct mdss_panel_info *pinfo)
+{
+ u32 bpp = pinfo->bpp;
+ u32 misc_val = 0x0;
+
+ switch (bpp) {
+ case 18:
+ misc_val |= (0x0 << 5);
+ break;
+ case 30:
+ misc_val |= (0x2 << 5);
+ break;
+ case 24:
+ default:
+ misc_val |= (0x1 << 5);
+ }
+
+ misc_val |= BIT(0); /* Configure clock to synchronous mode */
+
+ pr_debug("Misc settings = 0x%x\n", misc_val);
+ writel_relaxed(misc_val, ctrl_io->base + DP_MISC1_MISC0);
}
void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
@@ -267,8 +305,6 @@ void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
u32 valid_boundary2 = 0x0;
struct dp_vc_tu_mapping_table const *tu_entry = tu_table;
- writel_relaxed(0x21, ctrl_io->base + DP_MISC1_MISC0);
-
for (; tu_entry != tu_table + ARRAY_SIZE(tu_table); ++tu_entry) {
if ((tu_entry->vic == res) &&
(tu_entry->lanes == ln_cnt) &&
@@ -454,8 +490,14 @@ u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp)
pin_cfg = dp->alt_mode.dp_cap.dlink_pin_config;
for (pin = PIN_ASSIGNMENT_A; pin < PIN_ASSIGNMENT_MAX; pin++) {
- if (pin_cfg & BIT(pin))
- break;
+ if (pin_cfg & BIT(pin)) {
+ if (dp->alt_mode.dp_status.multi_func) {
+ if (pin == PIN_ASSIGNMENT_D)
+ break;
+ } else {
+ break;
+ }
+ }
}
if (pin == PIN_ASSIGNMENT_MAX)
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h
index 334c0071050d..4b28d98177be 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.h
+++ b/drivers/video/fbdev/msm/mdss_dp_util.h
@@ -164,6 +164,12 @@
#define TCSR_USB3_DP_PHYMODE 0x48
#define EDID_START_ADDRESS 0x50
+/* DP MMSS_CC registers */
+#define MMSS_DP_LINK_CMD_RCGR 0x0000
+#define MMSS_DP_LINK_CFG_RCGR 0x0004
+#define MMSS_DP_PIXEL_M 0x0048
+#define MMSS_DP_PIXEL_N 0x004C
+
/* DP HDCP 1.3 registers */
#define DP_HDCP_CTRL (0x0A0)
#define DP_HDCP_STATUS (0x0A4)
@@ -271,6 +277,8 @@ void mdss_dp_switch_usb3_phy_to_dp_mode(struct dss_io_data *tcsr_reg_io);
void mdss_dp_assert_phy_reset(struct dss_io_data *ctrl_io, bool assert);
void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate,
u8 ln_cnt, u32 res);
+void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io,
+ struct mdss_panel_info *pinfo);
void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io);
void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable);
void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable);
@@ -285,7 +293,8 @@ void mdss_dp_state_ctrl(struct dss_io_data *ctrl_io, u32 data);
int mdss_dp_irq_setup(struct mdss_dp_drv_pdata *dp_drv);
void mdss_dp_irq_enable(struct mdss_dp_drv_pdata *dp_drv);
void mdss_dp_irq_disable(struct mdss_dp_drv_pdata *dp_drv);
-void mdss_dp_sw_mvid_nvid(struct dss_io_data *ctrl_io);
+void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io,
+ char lrate, struct dss_io_data *dp_cc_io);
void mdss_dp_usbpd_ext_capabilities(struct usbpd_dp_capabilities *dp_cap);
void mdss_dp_usbpd_ext_dp_status(struct usbpd_dp_status *dp_status);
u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp);