forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
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);
....@@ -449,10 +467,8 @@
449467 return PTR_ERR(dpaux->regs);
450468
451469 dpaux->irq = platform_get_irq(pdev, 0);
452
- if (dpaux->irq < 0) {
453
- dev_err(&pdev->dev, "failed to get IRQ\n");
454
- return -ENXIO;
455
- }
470
+ if (dpaux->irq < 0)
471
+ return dpaux->irq;
456472
457473 if (!pdev->dev.pm_domain) {
458474 dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
....@@ -485,11 +501,18 @@
485501 return err;
486502 }
487503
488
- dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
504
+ dpaux->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
489505 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);
506
+ if (PTR_ERR(dpaux->vdd) != -ENODEV) {
507
+ if (PTR_ERR(dpaux->vdd) != -EPROBE_DEFER)
508
+ dev_err(&pdev->dev,
509
+ "failed to get VDD supply: %ld\n",
510
+ PTR_ERR(dpaux->vdd));
511
+
512
+ return PTR_ERR(dpaux->vdd);
513
+ }
514
+
515
+ dpaux->vdd = NULL;
493516 }
494517
495518 platform_set_drvdata(pdev, dpaux);
....@@ -521,7 +544,7 @@
521544 * is no possibility to perform the I2C mode configuration in the
522545 * HDMI path.
523546 */
524
- err = tegra_dpaux_pad_config(dpaux, DPAUX_HYBRID_PADCTL_MODE_I2C);
547
+ err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C);
525548 if (err < 0)
526549 return err;
527550
....@@ -561,7 +584,7 @@
561584 /* make sure pads are powered down when not in use */
562585 tegra_dpaux_pad_power_down(dpaux);
563586
564
- pm_runtime_put(&pdev->dev);
587
+ pm_runtime_put_sync(&pdev->dev);
565588 pm_runtime_disable(&pdev->dev);
566589
567590 drm_dp_aux_unregister(&dpaux->aux);
....@@ -638,10 +661,29 @@
638661 SET_RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL)
639662 };
640663
664
+static const struct tegra_dpaux_soc tegra124_dpaux_soc = {
665
+ .cmh = 0x02,
666
+ .drvz = 0x04,
667
+ .drvi = 0x18,
668
+};
669
+
670
+static const struct tegra_dpaux_soc tegra210_dpaux_soc = {
671
+ .cmh = 0x02,
672
+ .drvz = 0x04,
673
+ .drvi = 0x30,
674
+};
675
+
676
+static const struct tegra_dpaux_soc tegra194_dpaux_soc = {
677
+ .cmh = 0x02,
678
+ .drvz = 0x04,
679
+ .drvi = 0x2c,
680
+};
681
+
641682 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", },
683
+ { .compatible = "nvidia,tegra194-dpaux", .data = &tegra194_dpaux_soc },
684
+ { .compatible = "nvidia,tegra186-dpaux", .data = &tegra210_dpaux_soc },
685
+ { .compatible = "nvidia,tegra210-dpaux", .data = &tegra210_dpaux_soc },
686
+ { .compatible = "nvidia,tegra124-dpaux", .data = &tegra124_dpaux_soc },
645687 { },
646688 };
647689 MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
....@@ -682,25 +724,32 @@
682724 output->connector.polled = DRM_CONNECTOR_POLL_HPD;
683725 dpaux->output = output;
684726
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)) {
727
+ if (output->panel) {
692728 enum drm_connector_status status;
693729
694
- status = drm_dp_aux_detect(aux);
695
- if (status == connector_status_connected) {
696
- enable_irq(dpaux->irq);
697
- return 0;
730
+ if (dpaux->vdd) {
731
+ err = regulator_enable(dpaux->vdd);
732
+ if (err < 0)
733
+ return err;
698734 }
699735
700
- usleep_range(1000, 2000);
736
+ timeout = jiffies + msecs_to_jiffies(250);
737
+
738
+ while (time_before(jiffies, timeout)) {
739
+ status = drm_dp_aux_detect(aux);
740
+
741
+ if (status == connector_status_connected)
742
+ break;
743
+
744
+ usleep_range(1000, 2000);
745
+ }
746
+
747
+ if (status != connector_status_connected)
748
+ return -ETIMEDOUT;
701749 }
702750
703
- return -ETIMEDOUT;
751
+ enable_irq(dpaux->irq);
752
+ return 0;
704753 }
705754
706755 int drm_dp_aux_detach(struct drm_dp_aux *aux)
....@@ -711,25 +760,33 @@
711760
712761 disable_irq(dpaux->irq);
713762
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)) {
763
+ if (dpaux->output->panel) {
721764 enum drm_connector_status status;
722765
723
- status = drm_dp_aux_detect(aux);
724
- if (status == connector_status_disconnected) {
725
- dpaux->output = NULL;
726
- return 0;
766
+ if (dpaux->vdd) {
767
+ err = regulator_disable(dpaux->vdd);
768
+ if (err < 0)
769
+ return err;
727770 }
728771
729
- usleep_range(1000, 2000);
772
+ timeout = jiffies + msecs_to_jiffies(250);
773
+
774
+ while (time_before(jiffies, timeout)) {
775
+ status = drm_dp_aux_detect(aux);
776
+
777
+ if (status == connector_status_disconnected)
778
+ break;
779
+
780
+ usleep_range(1000, 2000);
781
+ }
782
+
783
+ if (status != connector_status_disconnected)
784
+ return -ETIMEDOUT;
785
+
786
+ dpaux->output = NULL;
730787 }
731788
732
- return -ETIMEDOUT;
789
+ return 0;
733790 }
734791
735792 enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux)
....@@ -757,75 +814,6 @@
757814 struct tegra_dpaux *dpaux = to_dpaux(aux);
758815
759816 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;
829817
830818 return 0;
831819 }