... | ... | ||
---|---|---|---|
8 | 8 | ||
9 | Modify training method improve compatibility to these DP devices. | 9 | Modify training method improve compatibility to these DP devices. |
10 | 10 | ||
11 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> | 11 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> |
12 | --- | 12 | --- |
13 | Hermes Wu (3): | 13 | Changes in v3: |
14 | - Patch 1/5 : add commit message for detial about changes | ||
15 | - Patch 2/5 : fix lost variable struct device *dev; | ||
16 | - Patch 3/5 : keep changes and remove refactoring | ||
17 | - Patch 5/5 : merge condition "it6505->step_train_only" check form if condiction into for loop. | ||
18 | - Link to v2: https://lore.kernel.org/r/20250326-fix-link-training-v2-0-756c8306f500@ite.com.tw | ||
19 | |||
20 | Changes in v2: | ||
21 | - 1. Split [PATCH 1/3] into 3 commits | ||
22 | - 2. Drop non necessary variable auto_ttrain_retry | ||
23 | - Link to v1: https://lore.kernel.org/all/20250318-fix-link-training-v1-0-19266711142c@ite.com.tw/ | ||
24 | |||
25 | --- | ||
26 | Hermes Wu (5): | ||
27 | drm/bridge: it6505: fix link training state HW register reset | ||
28 | drm/bridge: it6505: check INT_LINK_TRAIN_FAIL while link auto training | ||
14 | drm/bridge: it6505: modify DP link auto training | 29 | drm/bridge: it6505: modify DP link auto training |
15 | drm/bridge: it6505: modify DP link training work | 30 | drm/bridge: it6505: modify DP link training work |
16 | drm/bridge: it6505: skip auto training when previous try fail | 31 | drm/bridge: it6505: skip auto training when previous try fail |
17 | 32 | ||
18 | drivers/gpu/drm/bridge/ite-it6505.c | 106 ++++++++++++++++++++++-------------- | 33 | drivers/gpu/drm/bridge/ite-it6505.c | 88 +++++++++++++++++++++---------------- |
19 | 1 file changed, 66 insertions(+), 40 deletions(-) | 34 | 1 file changed, 50 insertions(+), 38 deletions(-) |
20 | --- | 35 | --- |
21 | base-commit: 938fbb16aba8f7b88e0fdcf56f315a5bbad41aad | 36 | base-commit: 938fbb16aba8f7b88e0fdcf56f315a5bbad41aad |
22 | change-id: 20250121-fix-link-training-461495494655 | 37 | change-id: 20250121-fix-link-training-461495494655 |
23 | 38 | ||
24 | Best regards, | 39 | Best regards, |
25 | -- | 40 | -- |
26 | Hermes Wu <Hermes.wu@ite.com.tw> | 41 | Hermes Wu <Hermes.wu@ite.com.tw> | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Hermes Wu <Hermes.wu@ite.com.tw> | ||
1 | 2 | ||
3 | When connect to a DP-to-HDMI device which does not connect | ||
4 | to HDMI sink, it will report DPCD 00200h with SINK_COUNT = "0", | ||
5 | and issue HPD_IRQ when SINK_COUNT change to "1". | ||
6 | |||
7 | IT6505 can not recive HPD_IRQ before training done and driver will | ||
8 | force HW enter training done state when connect to such devices. | ||
9 | |||
10 | When HW is force to training done state and restart link training, | ||
11 | bits FORCE_RETRAIN and MANUAL_TRAIN at REG_TRAIN_CTRL1 must be set | ||
12 | at the same time to reset HW state. | ||
13 | |||
14 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> | ||
15 | --- | ||
16 | drivers/gpu/drm/bridge/ite-it6505.c | 6 ++++-- | ||
17 | 1 file changed, 4 insertions(+), 2 deletions(-) | ||
18 | |||
19 | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/drivers/gpu/drm/bridge/ite-it6505.c | ||
22 | +++ b/drivers/gpu/drm/bridge/ite-it6505.c | ||
23 | @@ -XXX,XX +XXX,XX @@ static bool it6505_link_start_auto_train(struct it6505 *it6505) | ||
24 | mutex_lock(&it6505->aux_lock); | ||
25 | it6505_set_bits(it6505, REG_TRAIN_CTRL0, | ||
26 | FORCE_CR_DONE | FORCE_EQ_DONE, 0x00); | ||
27 | - it6505_write(it6505, REG_TRAIN_CTRL1, FORCE_RETRAIN); | ||
28 | + /* reset link state machine and re start training*/ | ||
29 | + it6505_write(it6505, REG_TRAIN_CTRL1, | ||
30 | + FORCE_RETRAIN | MANUAL_TRAIN); | ||
31 | it6505_write(it6505, REG_TRAIN_CTRL1, AUTO_TRAIN); | ||
32 | |||
33 | while (timeout > 0) { | ||
34 | @@ -XXX,XX +XXX,XX @@ static void it6505_stop_link_train(struct it6505 *it6505) | ||
35 | { | ||
36 | it6505->link_state = LINK_IDLE; | ||
37 | cancel_work_sync(&it6505->link_works); | ||
38 | - it6505_write(it6505, REG_TRAIN_CTRL1, FORCE_RETRAIN); | ||
39 | + it6505_write(it6505, REG_TRAIN_CTRL1, FORCE_RETRAIN | MANUAL_TRAIN); | ||
40 | } | ||
41 | |||
42 | static void it6505_link_train_ok(struct it6505 *it6505) | ||
43 | |||
44 | -- | ||
45 | 2.34.1 | diff view generated by jsdifflib |
1 | From: Hermes Wu <Hermes.wu@ite.com.tw> | 1 | From: Hermes Wu <Hermes.wu@ite.com.tw> |
---|---|---|---|
2 | 2 | ||
3 | IT6505 supports HW link training which will write DPCD and check | 3 | When start link training, interrupt status INT_LINK_TRAIN_FAIL can |
4 | training status automatically. | 4 | use to check link training fail and no need to wait until timeout. |
5 | 5 | ||
6 | In the case that driver set link rate at 2.7G and HW fail to training, | 6 | it6505_irq_link_train_fail() remove from interrupt and no longer used. |
7 | it will change link configuration and try 1.65G. And this will cause | ||
8 | INT_VID_FIFO_ERROR triggered when link clock is changed. | ||
9 | |||
10 | When video error occurs, video logic is reset and link training restart, | ||
11 | this will cause endless auto link training. | ||
12 | |||
13 | Modify link auto training with disable INT_VID_FIFO_ERROR to avoid loop | ||
14 | and check INT_LINK_TRAIN_FAIL event to abort wait training done. | ||
15 | |||
16 | Since INT_LINK_TRAIN_FAIL is checked when auto training, it is remove | ||
17 | from it6505_int_threaded_handler() | ||
18 | |||
19 | In order to reset HW link auto training state, | ||
20 | bits FORCE_RETRAIN and MANUAL_TRAIN at REG_TRAIN_CTRL1 must be set | ||
21 | at the same time. | ||
22 | 7 | ||
23 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> | 8 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> |
24 | --- | 9 | --- |
25 | drivers/gpu/drm/bridge/ite-it6505.c | 61 +++++++++++++++++++++++++------------ | 10 | drivers/gpu/drm/bridge/ite-it6505.c | 26 +++++++++++++++----------- |
26 | 1 file changed, 42 insertions(+), 19 deletions(-) | 11 | 1 file changed, 15 insertions(+), 11 deletions(-) |
27 | 12 | ||
28 | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c | 13 | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c |
29 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
30 | --- a/drivers/gpu/drm/bridge/ite-it6505.c | 15 | --- a/drivers/gpu/drm/bridge/ite-it6505.c |
31 | +++ b/drivers/gpu/drm/bridge/ite-it6505.c | 16 | +++ b/drivers/gpu/drm/bridge/ite-it6505.c |
32 | @@ -XXX,XX +XXX,XX @@ static void it6505_int_mask_enable(struct it6505 *it6505) | 17 | @@ -XXX,XX +XXX,XX @@ static void it6505_int_mask_enable(struct it6505 *it6505) |
33 | it6505_write(it6505, INT_MASK_02, BIT(INT_AUX_CMD_FAIL) | | 18 | it6505_write(it6505, INT_MASK_02, BIT(INT_AUX_CMD_FAIL) | |
34 | BIT(INT_HDCP_KSV_CHECK) | BIT(INT_AUDIO_FIFO_ERROR)); | 19 | BIT(INT_HDCP_KSV_CHECK) | BIT(INT_AUDIO_FIFO_ERROR)); |
35 | 20 | ||
36 | - it6505_write(it6505, INT_MASK_03, BIT(INT_LINK_TRAIN_FAIL) | | 21 | - it6505_write(it6505, INT_MASK_03, BIT(INT_LINK_TRAIN_FAIL) | |
37 | + it6505_write(it6505, INT_MASK_03, | 22 | - BIT(INT_VID_FIFO_ERROR) | BIT(INT_IO_LATCH_FIFO_OVERFLOW)); |
38 | BIT(INT_VID_FIFO_ERROR) | BIT(INT_IO_LATCH_FIFO_OVERFLOW)); | 23 | + it6505_write(it6505, INT_MASK_03, BIT(INT_VID_FIFO_ERROR) | |
24 | + BIT(INT_IO_LATCH_FIFO_OVERFLOW)); | ||
39 | } | 25 | } |
40 | 26 | ||
41 | @@ -XXX,XX +XXX,XX @@ static void it6505_link_training_setup(struct it6505 *it6505) | 27 | static void it6505_int_mask_disable(struct it6505 *it6505) |
42 | 28 | @@ -XXX,XX +XXX,XX @@ static bool it6505_link_start_auto_train(struct it6505 *it6505) | |
43 | static bool it6505_link_start_auto_train(struct it6505 *it6505) | ||
44 | { | 29 | { |
45 | - int timeout = 500, link_training_state; | 30 | int timeout = 500, link_training_state; |
46 | + int link_training_state; | ||
47 | bool state = false; | 31 | bool state = false; |
32 | + int int03; | ||
48 | + struct device *dev = it6505->dev; | 33 | + struct device *dev = it6505->dev; |
49 | + int int03; | 34 | |
50 | + unsigned long timeout; | 35 | mutex_lock(&it6505->aux_lock); |
51 | + | ||
52 | + guard(mutex)(&it6505->aux_lock); | ||
53 | + /* Disable FIFO error interrupt trigger */ | ||
54 | + /* to prevent training fail loop issue */ | ||
55 | + it6505_set_bits(it6505, INT_MASK_03, BIT(INT_VID_FIFO_ERROR), 0); | ||
56 | + | ||
57 | + it6505_write(it6505, INT_STATUS_03, | ||
58 | + BIT(INT_LINK_TRAIN_FAIL) | BIT(INT_VID_FIFO_ERROR)); | ||
59 | + int03 = it6505_read(it6505, INT_STATUS_03); | ||
60 | |||
61 | - mutex_lock(&it6505->aux_lock); | ||
62 | it6505_set_bits(it6505, REG_TRAIN_CTRL0, | 36 | it6505_set_bits(it6505, REG_TRAIN_CTRL0, |
63 | FORCE_CR_DONE | FORCE_EQ_DONE, 0x00); | 37 | @@ -XXX,XX +XXX,XX @@ static bool it6505_link_start_auto_train(struct it6505 *it6505) |
64 | - it6505_write(it6505, REG_TRAIN_CTRL1, FORCE_RETRAIN); | 38 | while (timeout > 0) { |
65 | + | ||
66 | + /* reset link state machine and re start training*/ | ||
67 | + it6505_write(it6505, REG_TRAIN_CTRL1, | ||
68 | + FORCE_RETRAIN | MANUAL_TRAIN); | ||
69 | it6505_write(it6505, REG_TRAIN_CTRL1, AUTO_TRAIN); | ||
70 | |||
71 | - while (timeout > 0) { | ||
72 | + timeout = jiffies + msecs_to_jiffies(100) + 1; | ||
73 | + for (;;) { | ||
74 | usleep_range(1000, 2000); | 39 | usleep_range(1000, 2000); |
75 | link_training_state = it6505_read(it6505, REG_LINK_TRAIN_STS); | 40 | link_training_state = it6505_read(it6505, REG_LINK_TRAIN_STS); |
76 | + int03 = it6505_read(it6505, INT_STATUS_03); | 41 | + int03 = it6505_read(it6505, INT_STATUS_03); |
77 | + if (int03 & BIT(INT_LINK_TRAIN_FAIL)) { | 42 | + if (int03 & BIT(INT_LINK_TRAIN_FAIL)) { |
78 | + /* Ignore INT_VID_FIFO_ERROR when auto training fail*/ | ||
79 | + it6505_write(it6505, INT_STATUS_03, | 43 | + it6505_write(it6505, INT_STATUS_03, |
80 | + BIT(INT_LINK_TRAIN_FAIL) | | 44 | + BIT(INT_LINK_TRAIN_FAIL)); |
81 | + BIT(INT_VID_FIFO_ERROR)); | ||
82 | + | 45 | + |
83 | + if (int03 & BIT(INT_VID_FIFO_ERROR)) { | 46 | + DRM_DEV_DEBUG_DRIVER(dev, |
84 | + DRM_DEV_DEBUG_DRIVER(dev, | 47 | + "INT_LINK_TRAIN_FAIL(%x)!", |
85 | + "video fifo error when training fail (%x)!", | 48 | + int03); |
86 | + int03); | ||
87 | + } | ||
88 | + | 49 | + |
89 | + break; | 50 | + break; |
90 | + } | 51 | + } |
91 | 52 | ||
92 | if (link_training_state > 0 && | 53 | if (link_training_state > 0 && |
93 | (link_training_state & LINK_STATE_NORP)) { | 54 | (link_training_state & LINK_STATE_NORP)) { |
94 | state = true; | ||
95 | - goto unlock; | ||
96 | + break; | ||
97 | } | ||
98 | |||
99 | - timeout--; | ||
100 | + if (time_after(jiffies, timeout)) | ||
101 | + break; | ||
102 | } | ||
103 | -unlock: | ||
104 | - mutex_unlock(&it6505->aux_lock); | ||
105 | |||
106 | + /* recover interrupt trigger*/ | ||
107 | + it6505_set_bits(it6505, INT_MASK_03, | ||
108 | + BIT(INT_VID_FIFO_ERROR), BIT(INT_VID_FIFO_ERROR)); | ||
109 | return state; | ||
110 | } | ||
111 | |||
112 | @@ -XXX,XX +XXX,XX @@ static void it6505_stop_link_train(struct it6505 *it6505) | ||
113 | { | ||
114 | it6505->link_state = LINK_IDLE; | ||
115 | cancel_work_sync(&it6505->link_works); | ||
116 | - it6505_write(it6505, REG_TRAIN_CTRL1, FORCE_RETRAIN); | ||
117 | + it6505_write(it6505, REG_TRAIN_CTRL1, FORCE_RETRAIN | MANUAL_TRAIN); | ||
118 | } | ||
119 | |||
120 | static void it6505_link_train_ok(struct it6505 *it6505) | ||
121 | @@ -XXX,XX +XXX,XX @@ static void it6505_irq_audio_fifo_error(struct it6505 *it6505) | 55 | @@ -XXX,XX +XXX,XX @@ static void it6505_irq_audio_fifo_error(struct it6505 *it6505) |
122 | it6505_enable_audio(it6505); | 56 | it6505_enable_audio(it6505); |
123 | } | 57 | } |
124 | 58 | ||
125 | -static void it6505_irq_link_train_fail(struct it6505 *it6505) | 59 | -static void it6505_irq_link_train_fail(struct it6505 *it6505) |
... | ... | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Hermes Wu <Hermes.wu@ite.com.tw> | ||
1 | 2 | ||
3 | IT6505 supports HW link training which will write DPCD and check | ||
4 | training status automatically. | ||
5 | |||
6 | In the case that driver set link rate at 2.7G and HW fail to training, | ||
7 | it will change link configuration and try 1.65G. And this will cause | ||
8 | INT_VID_FIFO_ERROR triggered when link clock is changed. | ||
9 | |||
10 | When video error occurs, video logic is reset and link training restart, | ||
11 | this will cause endless auto link training. | ||
12 | |||
13 | Modify link auto training with disable INT_VID_FIFO_ERROR to avoid loop | ||
14 | and check INT_LINK_TRAIN_FAIL event to abort wait training done. | ||
15 | |||
16 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> | ||
17 | --- | ||
18 | drivers/gpu/drm/bridge/ite-it6505.c | 14 +++++++++++++- | ||
19 | 1 file changed, 13 insertions(+), 1 deletion(-) | ||
20 | |||
21 | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/drivers/gpu/drm/bridge/ite-it6505.c | ||
24 | +++ b/drivers/gpu/drm/bridge/ite-it6505.c | ||
25 | @@ -XXX,XX +XXX,XX @@ static bool it6505_link_start_auto_train(struct it6505 *it6505) | ||
26 | struct device *dev = it6505->dev; | ||
27 | |||
28 | mutex_lock(&it6505->aux_lock); | ||
29 | + | ||
30 | + /* Disable FIFO error interrupt trigger */ | ||
31 | + /* to prevent training fail loop issue */ | ||
32 | + it6505_set_bits(it6505, INT_MASK_03, BIT(INT_VID_FIFO_ERROR), 0); | ||
33 | + | ||
34 | + it6505_write(it6505, INT_STATUS_03, | ||
35 | + BIT(INT_LINK_TRAIN_FAIL) | BIT(INT_VID_FIFO_ERROR)); | ||
36 | it6505_set_bits(it6505, REG_TRAIN_CTRL0, | ||
37 | FORCE_CR_DONE | FORCE_EQ_DONE, 0x00); | ||
38 | /* reset link state machine and re start training*/ | ||
39 | @@ -XXX,XX +XXX,XX @@ static bool it6505_link_start_auto_train(struct it6505 *it6505) | ||
40 | link_training_state = it6505_read(it6505, REG_LINK_TRAIN_STS); | ||
41 | int03 = it6505_read(it6505, INT_STATUS_03); | ||
42 | if (int03 & BIT(INT_LINK_TRAIN_FAIL)) { | ||
43 | + /* Ignore INT_VID_FIFO_ERROR when auto training fail*/ | ||
44 | it6505_write(it6505, INT_STATUS_03, | ||
45 | - BIT(INT_LINK_TRAIN_FAIL)); | ||
46 | + BIT(INT_LINK_TRAIN_FAIL) | | ||
47 | + BIT(INT_VID_FIFO_ERROR)); | ||
48 | |||
49 | DRM_DEV_DEBUG_DRIVER(dev, | ||
50 | "INT_LINK_TRAIN_FAIL(%x)!", | ||
51 | @@ -XXX,XX +XXX,XX @@ static bool it6505_link_start_auto_train(struct it6505 *it6505) | ||
52 | timeout--; | ||
53 | } | ||
54 | unlock: | ||
55 | + /* recover interrupt trigger*/ | ||
56 | + it6505_set_bits(it6505, INT_MASK_03, | ||
57 | + BIT(INT_VID_FIFO_ERROR), BIT(INT_VID_FIFO_ERROR)); | ||
58 | mutex_unlock(&it6505->aux_lock); | ||
59 | |||
60 | return state; | ||
61 | |||
62 | -- | ||
63 | 2.34.1 | diff view generated by jsdifflib |
1 | From: Hermes Wu <Hermes.wu@ite.com.tw> | 1 | From: Hermes Wu <Hermes.wu@ite.com.tw> |
---|---|---|---|
2 | 2 | ||
3 | The DP link training work include auto training and after | 3 | The DP link training work include auto training and after |
4 | auto training failed "auto_train_retry" times, it switch to | 4 | auto training failed "AUTO_TRAIN_RETRY" times, it switch to |
5 | step training mode. | 5 | step training mode. |
6 | 6 | ||
7 | It will more efficiency that finish link auto training, | 7 | It will more efficiency that finish link auto training, |
8 | include retry, and step training in a work, rather than | 8 | include retry, and step training in a work, rather than |
9 | re-schedule train work when each training fail. | 9 | re-schedule train work when each training fail. |
10 | 10 | ||
11 | it6505_dump() is remove from link trainig work, it takes too much | 11 | Drop auto_train_retry from it6505 structure, |
12 | time to read all register area, and is not necessary. | 12 | and it6505_dump() is remove from link trainig work, |
13 | it takes too much time to read all register area, | ||
14 | and is not necessary. | ||
13 | 15 | ||
14 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> | 16 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> |
15 | --- | 17 | --- |
16 | drivers/gpu/drm/bridge/ite-it6505.c | 35 ++++++++++++++++------------------- | 18 | drivers/gpu/drm/bridge/ite-it6505.c | 40 ++++++++++++++----------------------- |
17 | 1 file changed, 16 insertions(+), 19 deletions(-) | 19 | 1 file changed, 15 insertions(+), 25 deletions(-) |
18 | 20 | ||
19 | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c | 21 | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c |
20 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/drivers/gpu/drm/bridge/ite-it6505.c | 23 | --- a/drivers/gpu/drm/bridge/ite-it6505.c |
22 | +++ b/drivers/gpu/drm/bridge/ite-it6505.c | 24 | +++ b/drivers/gpu/drm/bridge/ite-it6505.c |
25 | @@ -XXX,XX +XXX,XX @@ struct it6505 { | ||
26 | struct delayed_work hdcp_work; | ||
27 | struct work_struct hdcp_wait_ksv_list; | ||
28 | struct completion extcon_completion; | ||
29 | - u8 auto_train_retry; | ||
30 | bool hdcp_desired; | ||
31 | bool is_repeater; | ||
32 | u8 hdcp_down_stream_count; | ||
23 | @@ -XXX,XX +XXX,XX @@ static int it6505_get_dpcd(struct it6505 *it6505, int offset, u8 *dpcd, int num) | 33 | @@ -XXX,XX +XXX,XX @@ static int it6505_get_dpcd(struct it6505 *it6505, int offset, u8 *dpcd, int num) |
24 | return 0; | 34 | return 0; |
25 | } | 35 | } |
26 | 36 | ||
27 | -static void it6505_dump(struct it6505 *it6505) | 37 | -static void it6505_dump(struct it6505 *it6505) |
28 | +static void __maybe_unused it6505_dump(struct it6505 *it6505) | 38 | +static void __maybe_unused it6505_dump(struct it6505 *it6505) |
29 | { | 39 | { |
30 | unsigned int i, j; | 40 | unsigned int i, j; |
31 | u8 regs[16]; | 41 | u8 regs[16]; |
42 | @@ -XXX,XX +XXX,XX @@ static void it6505_variable_config(struct it6505 *it6505) | ||
43 | it6505->lane_count = MAX_LANE_COUNT; | ||
44 | it6505->link_state = LINK_IDLE; | ||
45 | it6505->hdcp_desired = HDCP_DESIRED; | ||
46 | - it6505->auto_train_retry = AUTO_TRAIN_RETRY; | ||
47 | it6505->audio.select = AUDIO_SELECT; | ||
48 | it6505->audio.sample_rate = AUDIO_SAMPLE_RATE; | ||
49 | it6505->audio.channel_count = AUDIO_CHANNEL_COUNT; | ||
32 | @@ -XXX,XX +XXX,XX @@ static void it6505_link_training_work(struct work_struct *work) | 50 | @@ -XXX,XX +XXX,XX @@ static void it6505_link_training_work(struct work_struct *work) |
33 | { | 51 | { |
34 | struct it6505 *it6505 = container_of(work, struct it6505, link_works); | 52 | struct it6505 *it6505 = container_of(work, struct it6505, link_works); |
35 | struct device *dev = it6505->dev; | 53 | struct device *dev = it6505->dev; |
36 | - int ret; | 54 | - int ret; |
... | ... | ||
48 | - | 66 | - |
49 | - if (it6505->auto_train_retry < 1) { | 67 | - if (it6505->auto_train_retry < 1) { |
50 | - it6505_link_step_train_process(it6505); | 68 | - it6505_link_step_train_process(it6505); |
51 | - return; | 69 | - return; |
52 | - } | 70 | - } |
53 | + retry = it6505->auto_train_retry; | 71 | - |
54 | + do { | 72 | - ret = it6505_link_start_auto_train(it6505); |
73 | - DRM_DEV_DEBUG_DRIVER(dev, "auto train %s, auto_train_retry: %d", | ||
74 | - ret ? "pass" : "failed", it6505->auto_train_retry); | ||
75 | + for (retry = AUTO_TRAIN_RETRY; retry > 0; retry--) { | ||
55 | + it6505_link_training_setup(it6505); | 76 | + it6505_link_training_setup(it6505); |
56 | + it6505_reset_hdcp(it6505); | 77 | + it6505_reset_hdcp(it6505); |
57 | + it6505_aux_reset(it6505); | 78 | + it6505_aux_reset(it6505); |
58 | |||
59 | - ret = it6505_link_start_auto_train(it6505); | ||
60 | - DRM_DEV_DEBUG_DRIVER(dev, "auto train %s, auto_train_retry: %d", | ||
61 | + ret = it6505_link_start_auto_train(it6505); | ||
62 | + DRM_DEV_DEBUG_DRIVER(dev, "auto train %s, auto_train_retry: %d", | ||
63 | ret ? "pass" : "failed", it6505->auto_train_retry); | ||
64 | + if (ret) { | ||
65 | + it6505_link_train_ok(it6505); | ||
66 | + return; | ||
67 | + } | ||
68 | + } while (retry--); | ||
69 | 79 | ||
70 | - if (ret) { | 80 | - if (ret) { |
71 | - it6505->auto_train_retry = AUTO_TRAIN_RETRY; | 81 | - it6505->auto_train_retry = AUTO_TRAIN_RETRY; |
72 | - it6505_link_train_ok(it6505); | 82 | - it6505_link_train_ok(it6505); |
73 | - } else { | 83 | - } else { |
74 | - it6505->auto_train_retry--; | 84 | - it6505->auto_train_retry--; |
75 | - it6505_dump(it6505); | 85 | - it6505_dump(it6505); |
76 | - } | 86 | + ret = it6505_link_start_auto_train(it6505); |
87 | + DRM_DEV_DEBUG_DRIVER(dev, "auto train %s,", | ||
88 | + ret ? "pass" : "failed"); | ||
89 | + if (ret) { | ||
90 | + it6505_link_train_ok(it6505); | ||
91 | + return; | ||
92 | + } | ||
93 | } | ||
94 | |||
77 | + /*After HW auto training fail, try link training step by step*/ | 95 | + /*After HW auto training fail, try link training step by step*/ |
78 | + it6505_link_step_train_process(it6505); | 96 | + it6505_link_step_train_process(it6505); |
79 | |||
80 | } | 97 | } |
81 | 98 | ||
99 | static void it6505_plugged_status_to_codec(struct it6505 *it6505) | ||
100 | @@ -XXX,XX +XXX,XX @@ static int it6505_process_hpd_irq(struct it6505 *it6505) | ||
101 | (int)ARRAY_SIZE(link_status), link_status); | ||
102 | |||
103 | if (!drm_dp_channel_eq_ok(link_status, it6505->lane_count)) { | ||
104 | - it6505->auto_train_retry = AUTO_TRAIN_RETRY; | ||
105 | it6505_video_reset(it6505); | ||
106 | } | ||
107 | |||
108 | @@ -XXX,XX +XXX,XX @@ static void it6505_irq_hpd(struct it6505 *it6505) | ||
109 | it6505_variable_config(it6505); | ||
110 | it6505_parse_link_capabilities(it6505); | ||
111 | } | ||
112 | - it6505->auto_train_retry = AUTO_TRAIN_RETRY; | ||
113 | |||
114 | it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, | ||
115 | DP_SET_POWER_D0); | ||
116 | @@ -XXX,XX +XXX,XX @@ static void it6505_irq_video_handler(struct it6505 *it6505, const int *int_statu | ||
117 | (unsigned int *)int_status)) || | ||
118 | (it6505_test_bit(BIT_INT_VID_FIFO_ERROR, | ||
119 | (unsigned int *)int_status))) { | ||
120 | - it6505->auto_train_retry = AUTO_TRAIN_RETRY; | ||
121 | flush_work(&it6505->link_works); | ||
122 | it6505_stop_hdcp(it6505); | ||
123 | it6505_video_reset(it6505); | ||
82 | 124 | ||
83 | -- | 125 | -- |
84 | 2.34.1 | 126 | 2.34.1 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
4 | step training, skip auto training when link training restart, | 4 | step training, skip auto training when link training restart, |
5 | usually happen when display resolution is changed. | 5 | usually happen when display resolution is changed. |
6 | 6 | ||
7 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> | 7 | Signed-off-by: Hermes Wu <Hermes.wu@ite.com.tw> |
8 | --- | 8 | --- |
9 | drivers/gpu/drm/bridge/ite-it6505.c | 36 +++++++++++++++++++++--------------- | 9 | drivers/gpu/drm/bridge/ite-it6505.c | 8 ++++++-- |
10 | 1 file changed, 21 insertions(+), 15 deletions(-) | 10 | 1 file changed, 6 insertions(+), 2 deletions(-) |
11 | 11 | ||
12 | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c | 12 | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c |
13 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/drivers/gpu/drm/bridge/ite-it6505.c | 14 | --- a/drivers/gpu/drm/bridge/ite-it6505.c |
15 | +++ b/drivers/gpu/drm/bridge/ite-it6505.c | 15 | +++ b/drivers/gpu/drm/bridge/ite-it6505.c |
16 | @@ -XXX,XX +XXX,XX @@ struct it6505 { | 16 | @@ -XXX,XX +XXX,XX @@ struct it6505 { |
17 | struct delayed_work hdcp_work; | ||
17 | struct work_struct hdcp_wait_ksv_list; | 18 | struct work_struct hdcp_wait_ksv_list; |
18 | struct completion extcon_completion; | 19 | struct completion extcon_completion; |
19 | u8 auto_train_retry; | ||
20 | + u8 step_train_only; | 20 | + u8 step_train_only; |
21 | bool hdcp_desired; | 21 | bool hdcp_desired; |
22 | bool is_repeater; | 22 | bool is_repeater; |
23 | u8 hdcp_down_stream_count; | 23 | u8 hdcp_down_stream_count; |
24 | @@ -XXX,XX +XXX,XX @@ static void it6505_link_step_train_process(struct it6505 *it6505) | 24 | @@ -XXX,XX +XXX,XX @@ static void it6505_link_step_train_process(struct it6505 *it6505) |
... | ... | ||
34 | + it6505->step_train_only = false; | 34 | + it6505->step_train_only = false; |
35 | it6505->link_state = LINK_IDLE; | 35 | it6505->link_state = LINK_IDLE; |
36 | it6505_video_reset(it6505); | 36 | it6505_video_reset(it6505); |
37 | } | 37 | } |
38 | @@ -XXX,XX +XXX,XX @@ static void it6505_link_training_work(struct work_struct *work) | 38 | @@ -XXX,XX +XXX,XX @@ static void it6505_link_training_work(struct work_struct *work) |
39 | |||
40 | if (!it6505_get_sink_hpd_status(it6505)) | 39 | if (!it6505_get_sink_hpd_status(it6505)) |
41 | return; | 40 | return; |
42 | - | 41 | |
43 | - retry = it6505->auto_train_retry; | 42 | - for (retry = AUTO_TRAIN_RETRY; retry > 0; retry--) { |
44 | - do { | 43 | + for (retry = AUTO_TRAIN_RETRY; retry > 0 && !it6505->step_train_only; retry--) { |
45 | - it6505_link_training_setup(it6505); | 44 | it6505_link_training_setup(it6505); |
46 | - it6505_reset_hdcp(it6505); | 45 | it6505_reset_hdcp(it6505); |
47 | - it6505_aux_reset(it6505); | 46 | it6505_aux_reset(it6505); |
48 | - | 47 | |
49 | - ret = it6505_link_start_auto_train(it6505); | 48 | ret = it6505_link_start_auto_train(it6505); |
50 | - DRM_DEV_DEBUG_DRIVER(dev, "auto train %s, auto_train_retry: %d", | 49 | DRM_DEV_DEBUG_DRIVER(dev, "auto train %s,", |
51 | - ret ? "pass" : "failed", it6505->auto_train_retry); | 50 | - ret ? "pass" : "failed"); |
52 | - if (ret) { | 51 | + ret ? "pass" : "failed"); |
53 | - it6505_link_train_ok(it6505); | 52 | if (ret) { |
54 | - return; | 53 | it6505_link_train_ok(it6505); |
55 | - } | 54 | return; |
56 | - } while (retry--); | ||
57 | + /* skip auto training if previous auto train is fail*/ | ||
58 | + if (!it6505->step_train_only) { | ||
59 | + retry = it6505->auto_train_retry; | ||
60 | + do { | ||
61 | + it6505_link_training_setup(it6505); | ||
62 | + it6505_reset_hdcp(it6505); | ||
63 | + it6505_aux_reset(it6505); | ||
64 | + | ||
65 | + ret = it6505_link_start_auto_train(it6505); | ||
66 | + DRM_DEV_DEBUG_DRIVER(dev, "auto train %s, auto_train_retry: %d", | ||
67 | + ret ? "pass" : "failed", it6505->auto_train_retry); | ||
68 | + if (ret) { | ||
69 | + it6505_link_train_ok(it6505); | ||
70 | + return; | ||
71 | + } | ||
72 | + } while (retry--); | ||
73 | + } | ||
74 | |||
75 | /*After HW auto training fail, try link training step by step*/ | ||
76 | it6505_link_step_train_process(it6505); | ||
77 | @@ -XXX,XX +XXX,XX @@ static void it6505_irq_hpd(struct it6505 *it6505) | 55 | @@ -XXX,XX +XXX,XX @@ static void it6505_irq_hpd(struct it6505 *it6505) |
56 | it6505_variable_config(it6505); | ||
78 | it6505_parse_link_capabilities(it6505); | 57 | it6505_parse_link_capabilities(it6505); |
79 | } | 58 | } |
80 | it6505->auto_train_retry = AUTO_TRAIN_RETRY; | ||
81 | + it6505->step_train_only = false; | 59 | + it6505->step_train_only = false; |
82 | 60 | ||
83 | it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, | 61 | it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, |
84 | DP_SET_POWER_D0); | 62 | DP_SET_POWER_D0); |
85 | 63 | ||
86 | -- | 64 | -- |
87 | 2.34.1 | 65 | 2.34.1 | diff view generated by jsdifflib |