forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 223293205a7265c8b02882461ba8996650048ade
kernel/drivers/gpu/drm/tegra/dpaux.c
....@@ -1,29 +1,27 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2013 NVIDIA Corporation
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License version 2 as
6
- * published by the Free Software Foundation.
74 */
85
96 #include <linux/clk.h>
107 #include <linux/delay.h>
11
-#include <linux/gpio.h>
128 #include <linux/interrupt.h>
139 #include <linux/io.h>
14
-#include <linux/of_gpio.h>
10
+#include <linux/module.h>
11
+#include <linux/of_device.h>
1512 #include <linux/pinctrl/pinconf-generic.h>
1613 #include <linux/pinctrl/pinctrl.h>
1714 #include <linux/pinctrl/pinmux.h>
18
-#include <linux/pm_runtime.h>
1915 #include <linux/platform_device.h>
20
-#include <linux/reset.h>
16
+#include <linux/pm_runtime.h>
2117 #include <linux/regulator/consumer.h>
18
+#include <linux/reset.h>
2219 #include <linux/workqueue.h>
2320
2421 #include <drm/drm_dp_helper.h>
2522 #include <drm/drm_panel.h>
2623
24
+#include "dp.h"
2725 #include "dpaux.h"
2826 #include "drm.h"
2927 #include "trace.h"
....@@ -31,9 +29,17 @@
3129 static DEFINE_MUTEX(dpaux_lock);
3230 static LIST_HEAD(dpaux_list);
3331
32
+struct tegra_dpaux_soc {
33
+ unsigned int cmh;
34
+ unsigned int drvz;
35
+ unsigned int drvi;
36
+};
37
+
3438 struct tegra_dpaux {
3539 struct drm_dp_aux aux;
3640 struct device *dev;
41
+
42
+ const struct tegra_dpaux_soc *soc;
3743
3844 void __iomem *regs;
3945 int irq;
....@@ -122,6 +128,7 @@
122128 struct tegra_dpaux *dpaux = to_dpaux(aux);
123129 unsigned long status;
124130 ssize_t ret = 0;
131
+ u8 reply = 0;
125132 u32 value;
126133
127134 /* Tegra has 4x4 byte DP AUX transmit and receive FIFOs. */
....@@ -216,23 +223,23 @@
216223
217224 switch ((value & DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK) >> 16) {
218225 case 0x00:
219
- msg->reply = DP_AUX_NATIVE_REPLY_ACK;
226
+ reply = DP_AUX_NATIVE_REPLY_ACK;
220227 break;
221228
222229 case 0x01:
223
- msg->reply = DP_AUX_NATIVE_REPLY_NACK;
230
+ reply = DP_AUX_NATIVE_REPLY_NACK;
224231 break;
225232
226233 case 0x02:
227
- msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
234
+ reply = DP_AUX_NATIVE_REPLY_DEFER;
228235 break;
229236
230237 case 0x04:
231
- msg->reply = DP_AUX_I2C_REPLY_NACK;
238
+ reply = DP_AUX_I2C_REPLY_NACK;
232239 break;
233240
234241 case 0x08:
235
- msg->reply = DP_AUX_I2C_REPLY_DEFER;
242
+ reply = DP_AUX_I2C_REPLY_DEFER;
236243 break;
237244 }
238245
....@@ -240,14 +247,24 @@
240247 if (msg->request & DP_AUX_I2C_READ) {
241248 size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;
242249
243
- if (WARN_ON(count != msg->size))
244
- count = min_t(size_t, count, msg->size);
250
+ /*
251
+ * There might be a smarter way to do this, but since
252
+ * the DP helpers will already retry transactions for
253
+ * an -EBUSY return value, simply reuse that instead.
254
+ */
255
+ if (count != msg->size) {
256
+ ret = -EBUSY;
257
+ goto out;
258
+ }
245259
246260 tegra_dpaux_read_fifo(dpaux, msg->buffer, count);
247261 ret = count;
248262 }
249263 }
250264
265
+ msg->reply = reply;
266
+
267
+out:
251268 return ret;
252269 }
253270
....@@ -312,9 +329,9 @@
312329
313330 switch (function) {
314331 case DPAUX_PADCTL_FUNC_AUX:
315
- value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
316
- DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) |
317
- DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) |
332
+ value = DPAUX_HYBRID_PADCTL_AUX_CMH(dpaux->soc->cmh) |
333
+ DPAUX_HYBRID_PADCTL_AUX_DRVZ(dpaux->soc->drvz) |
334
+ DPAUX_HYBRID_PADCTL_AUX_DRVI(dpaux->soc->drvi) |
318335 DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV |
319336 DPAUX_HYBRID_PADCTL_MODE_AUX;
320337 break;
....@@ -322,9 +339,9 @@
322339 case DPAUX_PADCTL_FUNC_I2C:
323340 value = DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV |
324341 DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV |
325
- DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
326
- DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) |
327
- DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) |
342
+ DPAUX_HYBRID_PADCTL_AUX_CMH(dpaux->soc->cmh) |
343
+ DPAUX_HYBRID_PADCTL_AUX_DRVZ(dpaux->soc->drvz) |
344
+ DPAUX_HYBRID_PADCTL_AUX_DRVI(dpaux->soc->drvi) |
328345 DPAUX_HYBRID_PADCTL_MODE_I2C;
329346 break;
330347
....@@ -438,6 +455,7 @@
438455 if (!dpaux)
439456 return -ENOMEM;
440457
458
+ dpaux->soc = of_device_get_match_data(&pdev->dev);
441459 INIT_WORK(&dpaux->work, tegra_dpaux_hotplug);
442460 init_completion(&dpaux->complete);
443461 INIT_LIST_HEAD(&dpaux->list);
....@@ -485,11 +503,18 @@
485503 return err;
486504 }
487505
488
- dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
506
+ dpaux->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
489507 if (IS_ERR(dpaux->vdd)) {
490
- dev_err(&pdev->dev, "failed to get VDD supply: %ld\n",
491
- PTR_ERR(dpaux->vdd));
492
- return PTR_ERR(dpaux->vdd);
508
+ if (PTR_ERR(dpaux->vdd) != -ENODEV) {
509
+ if (PTR_ERR(dpaux->vdd) != -EPROBE_DEFER)
510
+ dev_err(&pdev->dev,
511
+ "failed to get VDD supply: %ld\n",
512
+ PTR_ERR(dpaux->vdd));
513
+
514
+ return PTR_ERR(dpaux->vdd);
515
+ }
516
+
517
+ dpaux->vdd = NULL;
493518 }
494519
495520 platform_set_drvdata(pdev, dpaux);
....@@ -521,7 +546,7 @@
521546 * is no possibility to perform the I2C mode configuration in the
522547 * HDMI path.
523548 */
524
- err = tegra_dpaux_pad_config(dpaux, DPAUX_HYBRID_PADCTL_MODE_I2C);
549
+ err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C);
525550 if (err < 0)
526551 return err;
527552
....@@ -561,7 +586,7 @@
561586 /* make sure pads are powered down when not in use */
562587 tegra_dpaux_pad_power_down(dpaux);
563588
564
- pm_runtime_put(&pdev->dev);
589
+ pm_runtime_put_sync(&pdev->dev);
565590 pm_runtime_disable(&pdev->dev);
566591
567592 drm_dp_aux_unregister(&dpaux->aux);
....@@ -638,10 +663,29 @@
638663 SET_RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL)
639664 };
640665
666
+static const struct tegra_dpaux_soc tegra124_dpaux_soc = {
667
+ .cmh = 0x02,
668
+ .drvz = 0x04,
669
+ .drvi = 0x18,
670
+};
671
+
672
+static const struct tegra_dpaux_soc tegra210_dpaux_soc = {
673
+ .cmh = 0x02,
674
+ .drvz = 0x04,
675
+ .drvi = 0x30,
676
+};
677
+
678
+static const struct tegra_dpaux_soc tegra194_dpaux_soc = {
679
+ .cmh = 0x02,
680
+ .drvz = 0x04,
681
+ .drvi = 0x2c,
682
+};
683
+
641684 static const struct of_device_id tegra_dpaux_of_match[] = {
642
- { .compatible = "nvidia,tegra186-dpaux", },
643
- { .compatible = "nvidia,tegra210-dpaux", },
644
- { .compatible = "nvidia,tegra124-dpaux", },
685
+ { .compatible = "nvidia,tegra194-dpaux", .data = &tegra194_dpaux_soc },
686
+ { .compatible = "nvidia,tegra186-dpaux", .data = &tegra210_dpaux_soc },
687
+ { .compatible = "nvidia,tegra210-dpaux", .data = &tegra210_dpaux_soc },
688
+ { .compatible = "nvidia,tegra124-dpaux", .data = &tegra124_dpaux_soc },
645689 { },
646690 };
647691 MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
....@@ -682,25 +726,32 @@
682726 output->connector.polled = DRM_CONNECTOR_POLL_HPD;
683727 dpaux->output = output;
684728
685
- err = regulator_enable(dpaux->vdd);
686
- if (err < 0)
687
- return err;
688
-
689
- timeout = jiffies + msecs_to_jiffies(250);
690
-
691
- while (time_before(jiffies, timeout)) {
729
+ if (output->panel) {
692730 enum drm_connector_status status;
693731
694
- status = drm_dp_aux_detect(aux);
695
- if (status == connector_status_connected) {
696
- enable_irq(dpaux->irq);
697
- return 0;
732
+ if (dpaux->vdd) {
733
+ err = regulator_enable(dpaux->vdd);
734
+ if (err < 0)
735
+ return err;
698736 }
699737
700
- usleep_range(1000, 2000);
738
+ timeout = jiffies + msecs_to_jiffies(250);
739
+
740
+ while (time_before(jiffies, timeout)) {
741
+ status = drm_dp_aux_detect(aux);
742
+
743
+ if (status == connector_status_connected)
744
+ break;
745
+
746
+ usleep_range(1000, 2000);
747
+ }
748
+
749
+ if (status != connector_status_connected)
750
+ return -ETIMEDOUT;
701751 }
702752
703
- return -ETIMEDOUT;
753
+ enable_irq(dpaux->irq);
754
+ return 0;
704755 }
705756
706757 int drm_dp_aux_detach(struct drm_dp_aux *aux)
....@@ -711,25 +762,33 @@
711762
712763 disable_irq(dpaux->irq);
713764
714
- err = regulator_disable(dpaux->vdd);
715
- if (err < 0)
716
- return err;
717
-
718
- timeout = jiffies + msecs_to_jiffies(250);
719
-
720
- while (time_before(jiffies, timeout)) {
765
+ if (dpaux->output->panel) {
721766 enum drm_connector_status status;
722767
723
- status = drm_dp_aux_detect(aux);
724
- if (status == connector_status_disconnected) {
725
- dpaux->output = NULL;
726
- return 0;
768
+ if (dpaux->vdd) {
769
+ err = regulator_disable(dpaux->vdd);
770
+ if (err < 0)
771
+ return err;
727772 }
728773
729
- usleep_range(1000, 2000);
774
+ timeout = jiffies + msecs_to_jiffies(250);
775
+
776
+ while (time_before(jiffies, timeout)) {
777
+ status = drm_dp_aux_detect(aux);
778
+
779
+ if (status == connector_status_disconnected)
780
+ break;
781
+
782
+ usleep_range(1000, 2000);
783
+ }
784
+
785
+ if (status != connector_status_disconnected)
786
+ return -ETIMEDOUT;
787
+
788
+ dpaux->output = NULL;
730789 }
731790
732
- return -ETIMEDOUT;
791
+ return 0;
733792 }
734793
735794 enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux)
....@@ -757,75 +816,6 @@
757816 struct tegra_dpaux *dpaux = to_dpaux(aux);
758817
759818 tegra_dpaux_pad_power_down(dpaux);
760
-
761
- return 0;
762
-}
763
-
764
-int drm_dp_aux_prepare(struct drm_dp_aux *aux, u8 encoding)
765
-{
766
- int err;
767
-
768
- err = drm_dp_dpcd_writeb(aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
769
- encoding);
770
- if (err < 0)
771
- return err;
772
-
773
- return 0;
774
-}
775
-
776
-int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link,
777
- u8 pattern)
778
-{
779
- u8 tp = pattern & DP_TRAINING_PATTERN_MASK;
780
- u8 status[DP_LINK_STATUS_SIZE], values[4];
781
- unsigned int i;
782
- int err;
783
-
784
- err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, pattern);
785
- if (err < 0)
786
- return err;
787
-
788
- if (tp == DP_TRAINING_PATTERN_DISABLE)
789
- return 0;
790
-
791
- for (i = 0; i < link->num_lanes; i++)
792
- values[i] = DP_TRAIN_MAX_PRE_EMPHASIS_REACHED |
793
- DP_TRAIN_PRE_EMPH_LEVEL_0 |
794
- DP_TRAIN_MAX_SWING_REACHED |
795
- DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
796
-
797
- err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_SET, values,
798
- link->num_lanes);
799
- if (err < 0)
800
- return err;
801
-
802
- usleep_range(500, 1000);
803
-
804
- err = drm_dp_dpcd_read_link_status(aux, status);
805
- if (err < 0)
806
- return err;
807
-
808
- switch (tp) {
809
- case DP_TRAINING_PATTERN_1:
810
- if (!drm_dp_clock_recovery_ok(status, link->num_lanes))
811
- return -EAGAIN;
812
-
813
- break;
814
-
815
- case DP_TRAINING_PATTERN_2:
816
- if (!drm_dp_channel_eq_ok(status, link->num_lanes))
817
- return -EAGAIN;
818
-
819
- break;
820
-
821
- default:
822
- dev_err(aux->dev, "unsupported training pattern %u\n", tp);
823
- return -EINVAL;
824
- }
825
-
826
- err = drm_dp_dpcd_writeb(aux, DP_EDP_CONFIGURATION_SET, 0);
827
- if (err < 0)
828
- return err;
829819
830820 return 0;
831821 }