Skip to content

Commit 58594a8

Browse files
algea.caorkhuangtao
authored andcommitted
drm: bridge: dw-hdmi: optimize edid reading process
1.change SDA high level holding time to 3us. 2.when plug in,add timer to avoid unstable state. Change-Id: Idc6faec710137ac9f8e589d75cbc1b85f7a45faf Signed-off-by: algea.cao <algea.cao@rock-chips.com>
1 parent fd415d5 commit 58594a8

2 files changed

Lines changed: 52 additions & 12 deletions

File tree

drivers/gpu/drm/bridge/dw-hdmi.c

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ static const struct dw_hdmi_audio_tmds_n common_tmds_n_table[] = {
117117
{ .tmds = 0, .n_32k = 0, .n_44k1 = 0, .n_48k = 0, },
118118
};
119119

120-
121120
static const u16 csc_coeff_default[3][4] = {
122121
{ 0x2000, 0x0000, 0x0000, 0x0000 },
123122
{ 0x0000, 0x2000, 0x0000, 0x0000 },
@@ -208,6 +207,10 @@ struct dw_hdmi {
208207
void __iomem *regs;
209208
bool sink_is_hdmi;
210209
bool sink_has_audio;
210+
bool hpd_state;
211+
212+
struct delayed_work work;
213+
struct workqueue_struct *workqueue;
211214

212215
struct mutex mutex; /* for state below and previous_mode */
213216
enum drm_connector_force force; /* mutex-protected force state */
@@ -284,6 +287,48 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
284287
hdmi_modb(hdmi, data << shift, mask, reg);
285288
}
286289

290+
static void repo_hpd_event(struct work_struct *p_work)
291+
{
292+
struct dw_hdmi *hdmi = container_of(p_work, struct dw_hdmi, work.work);
293+
294+
drm_helper_hpd_irq_event(hdmi->bridge->dev);
295+
#ifdef CONFIG_SWITCH
296+
if (hdmi->hpd_state)
297+
switch_set_state(&hdmi->switchdev, 1);
298+
else
299+
switch_set_state(&hdmi->switchdev, 0);
300+
#endif
301+
}
302+
303+
static bool check_hdmi_irq(struct dw_hdmi *hdmi, int intr_stat,
304+
int phy_int_pol)
305+
{
306+
int msecs;
307+
308+
/* To determine whether interrupt type is HPD */
309+
if (!(intr_stat & HDMI_IH_PHY_STAT0_HPD))
310+
return false;
311+
312+
if (phy_int_pol & HDMI_PHY_HPD) {
313+
dev_dbg(hdmi->dev, "dw hdmi plug in\n");
314+
msecs = 150;
315+
hdmi->hpd_state = true;
316+
} else {
317+
dev_dbg(hdmi->dev, "dw hdmi plug out\n");
318+
msecs = 20;
319+
hdmi->hpd_state = false;
320+
}
321+
mod_delayed_work(hdmi->workqueue, &hdmi->work, msecs_to_jiffies(msecs));
322+
323+
return true;
324+
}
325+
326+
static void init_hpd_work(struct dw_hdmi *hdmi)
327+
{
328+
hdmi->workqueue = create_workqueue("hpd_queue");
329+
INIT_DELAYED_WORK(&hdmi->work, repo_hpd_event);
330+
}
331+
287332
static void dw_hdmi_i2c_set_divs(struct dw_hdmi *hdmi)
288333
{
289334
unsigned long clk_rate_khz;
@@ -349,6 +394,9 @@ static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi)
349394
hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
350395
HDMI_IH_MUTE_I2CM_STAT0);
351396

397+
/* set SDA high level holding time */
398+
hdmi_writeb(hdmi, 0x48, HDMI_I2CM_SDA_HOLD);
399+
352400
dw_hdmi_i2c_set_divs(hdmi);
353401
}
354402

@@ -2172,17 +2220,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
21722220
mutex_unlock(&hdmi->mutex);
21732221
}
21742222

2175-
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
2176-
dev_dbg(hdmi->dev, "EVENT=%s\n",
2177-
phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
2178-
drm_helper_hpd_irq_event(hdmi->bridge->dev);
2179-
#ifdef CONFIG_SWITCH
2180-
if (phy_int_pol & HDMI_PHY_HPD)
2181-
switch_set_state(&hdmi->switchdev, 1);
2182-
else
2183-
switch_set_state(&hdmi->switchdev, 0);
2184-
#endif
2185-
}
2223+
check_hdmi_irq(hdmi, intr_stat, phy_int_pol);
21862224

21872225
hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
21882226
hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
@@ -2505,6 +2543,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
25052543
hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
25062544
hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
25072545

2546+
init_hpd_work(hdmi);
25082547
initialize_hdmi_ih_mutes(hdmi);
25092548

25102549
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,

drivers/gpu/drm/bridge/dw-hdmi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@
544544
#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10
545545
#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11
546546
#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
547+
#define HDMI_I2CM_SDA_HOLD 0x7E13
547548

548549
enum {
549550

0 commit comments

Comments
 (0)