diff options
author | Dave Airlie <airlied@redhat.com> | 2015-08-17 01:52:39 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-08-17 01:52:39 -0400 |
commit | bef2c7bd578e91c9c10983e0c15c4501127b77ca (patch) | |
tree | a1fe0d79d4efef5c5c522ee3d87a6d18b224fabd | |
parent | 3ff8e5090c337a4eb26952d68587f450e012bd72 (diff) | |
parent | 459cc2c6800b545a482e428a631d99bca8da7790 (diff) |
Merge tag 'drm/tegra/for-4.3-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/tegra: Changes for v4.3-rc1
There are a bunch of non-critical fixes here that I've collected over
the past few months, but the biggest part is Tegra210 support, in the
DC, DSI and SOR/HDMI drivers.
Also this finally restores DPMS with atomic mode-setting, something
that has been broken since the conversion and which I had originally
expected to take far less longer to fix.
* tag 'drm/tegra/for-4.3-rc1' of git://anongit.freedesktop.org/tegra/linux: (41 commits)
drm/tegra: sor: Add HDMI support
drm/tegra: sor: Add Tegra210 eDP support
drm/tegra: dc: Implement atomic DPMS
drm/tegra: sor: Restore DPMS
drm/tegra: dsi: Restore DPMS
drm/tegra: hdmi: Restore DPMS
drm/tegra: rgb: Restore DPMS
drm/tegra: sor: Use DRM debugfs infrastructure for CRC
drm/tegra: sor: Write correct head state registers
drm/tegra: sor: Constify display mode
drm/tegra: sor: Reset the correct debugfs fields
drm/tegra: sor: Set minor after debugfs initialization
drm/tegra: sor: Provide error messages in probe
drm/tegra: sor: Rename registers for consistency
drm/tegra: dpaux: Disable interrupt when detached
drm/tegra: dpaux: Configure pads as I2C by default
drm/tegra: dpaux: Provide error message in probe
drm/tegra: dsi: Add Tegra210 support
drm/tegra: dsi: Add Tegra132 support
drm/tegra: dsi: Add Tegra124 support
...
-rw-r--r-- | Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 294 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dpaux.c | 63 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dpaux.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dsi.c | 127 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dsi.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/hdmi.c | 79 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/output.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/rgb.c | 50 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 1607 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/sor.h | 298 | ||||
-rw-r--r-- | drivers/gpu/host1x/mipi.c | 253 |
15 files changed, 2075 insertions, 780 deletions
diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt index 009f4bfa1590..e685610d38e2 100644 --- a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt +++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt | |||
@@ -197,9 +197,11 @@ of the following host1x client modules: | |||
197 | - sor: serial output resource | 197 | - sor: serial output resource |
198 | 198 | ||
199 | Required properties: | 199 | Required properties: |
200 | - compatible: For Tegra124, must contain "nvidia,tegra124-sor". Otherwise, | 200 | - compatible: Should be: |
201 | must contain '"nvidia,<chip>-sor", "nvidia,tegra124-sor"', where <chip> | 201 | - "nvidia,tegra124-sor": for Tegra124 and Tegra132 |
202 | is tegra132. | 202 | - "nvidia,tegra132-sor": for Tegra132 |
203 | - "nvidia,tegra210-sor": for Tegra210 | ||
204 | - "nvidia,tegra210-sor1": for Tegra210 | ||
203 | - reg: Physical base address and length of the controller's registers. | 205 | - reg: Physical base address and length of the controller's registers. |
204 | - interrupts: The interrupt outputs from the controller. | 206 | - interrupts: The interrupt outputs from the controller. |
205 | - clocks: Must contain an entry for each entry in clock-names. | 207 | - clocks: Must contain an entry for each entry in clock-names. |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index bf8ef3133e5b..ddefb85dc4f7 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -76,6 +76,14 @@ to_tegra_plane_state(struct drm_plane_state *state) | |||
76 | return NULL; | 76 | return NULL; |
77 | } | 77 | } |
78 | 78 | ||
79 | static void tegra_dc_stats_reset(struct tegra_dc_stats *stats) | ||
80 | { | ||
81 | stats->frames = 0; | ||
82 | stats->vblank = 0; | ||
83 | stats->underflow = 0; | ||
84 | stats->overflow = 0; | ||
85 | } | ||
86 | |||
79 | /* | 87 | /* |
80 | * Reads the active copy of a register. This takes the dc->lock spinlock to | 88 | * Reads the active copy of a register. This takes the dc->lock spinlock to |
81 | * prevent races with the VBLANK processing which also needs access to the | 89 | * prevent races with the VBLANK processing which also needs access to the |
@@ -759,7 +767,6 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane, | |||
759 | /* position the cursor */ | 767 | /* position the cursor */ |
760 | value = (state->crtc_y & 0x3fff) << 16 | (state->crtc_x & 0x3fff); | 768 | value = (state->crtc_y & 0x3fff) << 16 | (state->crtc_x & 0x3fff); |
761 | tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION); | 769 | tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION); |
762 | |||
763 | } | 770 | } |
764 | 771 | ||
765 | static void tegra_cursor_atomic_disable(struct drm_plane *plane, | 772 | static void tegra_cursor_atomic_disable(struct drm_plane *plane, |
@@ -809,9 +816,11 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, | |||
809 | return ERR_PTR(-ENOMEM); | 816 | return ERR_PTR(-ENOMEM); |
810 | 817 | ||
811 | /* | 818 | /* |
812 | * We'll treat the cursor as an overlay plane with index 6 here so | 819 | * This index is kind of fake. The cursor isn't a regular plane, but |
813 | * that the update and activation request bits in DC_CMD_STATE_CONTROL | 820 | * its update and activation request bits in DC_CMD_STATE_CONTROL do |
814 | * match up. | 821 | * use the same programming. Setting this fake index here allows the |
822 | * code in tegra_add_plane_state() to do the right thing without the | ||
823 | * need to special-casing the cursor plane. | ||
815 | */ | 824 | */ |
816 | plane->index = 6; | 825 | plane->index = 6; |
817 | 826 | ||
@@ -1015,6 +1024,8 @@ static void tegra_crtc_reset(struct drm_crtc *crtc) | |||
1015 | crtc->state = &state->base; | 1024 | crtc->state = &state->base; |
1016 | crtc->state->crtc = crtc; | 1025 | crtc->state->crtc = crtc; |
1017 | } | 1026 | } |
1027 | |||
1028 | drm_crtc_vblank_reset(crtc); | ||
1018 | } | 1029 | } |
1019 | 1030 | ||
1020 | static struct drm_crtc_state * | 1031 | static struct drm_crtc_state * |
@@ -1052,90 +1063,6 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = { | |||
1052 | .atomic_destroy_state = tegra_crtc_atomic_destroy_state, | 1063 | .atomic_destroy_state = tegra_crtc_atomic_destroy_state, |
1053 | }; | 1064 | }; |
1054 | 1065 | ||
1055 | static void tegra_dc_stop(struct tegra_dc *dc) | ||
1056 | { | ||
1057 | u32 value; | ||
1058 | |||
1059 | /* stop the display controller */ | ||
1060 | value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); | ||
1061 | value &= ~DISP_CTRL_MODE_MASK; | ||
1062 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); | ||
1063 | |||
1064 | tegra_dc_commit(dc); | ||
1065 | } | ||
1066 | |||
1067 | static bool tegra_dc_idle(struct tegra_dc *dc) | ||
1068 | { | ||
1069 | u32 value; | ||
1070 | |||
1071 | value = tegra_dc_readl_active(dc, DC_CMD_DISPLAY_COMMAND); | ||
1072 | |||
1073 | return (value & DISP_CTRL_MODE_MASK) == 0; | ||
1074 | } | ||
1075 | |||
1076 | static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout) | ||
1077 | { | ||
1078 | timeout = jiffies + msecs_to_jiffies(timeout); | ||
1079 | |||
1080 | while (time_before(jiffies, timeout)) { | ||
1081 | if (tegra_dc_idle(dc)) | ||
1082 | return 0; | ||
1083 | |||
1084 | usleep_range(1000, 2000); | ||
1085 | } | ||
1086 | |||
1087 | dev_dbg(dc->dev, "timeout waiting for DC to become idle\n"); | ||
1088 | return -ETIMEDOUT; | ||
1089 | } | ||
1090 | |||
1091 | static void tegra_crtc_disable(struct drm_crtc *crtc) | ||
1092 | { | ||
1093 | struct tegra_dc *dc = to_tegra_dc(crtc); | ||
1094 | u32 value; | ||
1095 | |||
1096 | if (!tegra_dc_idle(dc)) { | ||
1097 | tegra_dc_stop(dc); | ||
1098 | |||
1099 | /* | ||
1100 | * Ignore the return value, there isn't anything useful to do | ||
1101 | * in case this fails. | ||
1102 | */ | ||
1103 | tegra_dc_wait_idle(dc, 100); | ||
1104 | } | ||
1105 | |||
1106 | /* | ||
1107 | * This should really be part of the RGB encoder driver, but clearing | ||
1108 | * these bits has the side-effect of stopping the display controller. | ||
1109 | * When that happens no VBLANK interrupts will be raised. At the same | ||
1110 | * time the encoder is disabled before the display controller, so the | ||
1111 | * above code is always going to timeout waiting for the controller | ||
1112 | * to go idle. | ||
1113 | * | ||
1114 | * Given the close coupling between the RGB encoder and the display | ||
1115 | * controller doing it here is still kind of okay. None of the other | ||
1116 | * encoder drivers require these bits to be cleared. | ||
1117 | * | ||
1118 | * XXX: Perhaps given that the display controller is switched off at | ||
1119 | * this point anyway maybe clearing these bits isn't even useful for | ||
1120 | * the RGB encoder? | ||
1121 | */ | ||
1122 | if (dc->rgb) { | ||
1123 | value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); | ||
1124 | value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | | ||
1125 | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE); | ||
1126 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); | ||
1127 | } | ||
1128 | |||
1129 | drm_crtc_vblank_off(crtc); | ||
1130 | } | ||
1131 | |||
1132 | static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc, | ||
1133 | const struct drm_display_mode *mode, | ||
1134 | struct drm_display_mode *adjusted) | ||
1135 | { | ||
1136 | return true; | ||
1137 | } | ||
1138 | |||
1139 | static int tegra_dc_set_timings(struct tegra_dc *dc, | 1066 | static int tegra_dc_set_timings(struct tegra_dc *dc, |
1140 | struct drm_display_mode *mode) | 1067 | struct drm_display_mode *mode) |
1141 | { | 1068 | { |
@@ -1229,7 +1156,85 @@ static void tegra_dc_commit_state(struct tegra_dc *dc, | |||
1229 | tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); | 1156 | tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); |
1230 | } | 1157 | } |
1231 | 1158 | ||
1232 | static void tegra_crtc_mode_set_nofb(struct drm_crtc *crtc) | 1159 | static void tegra_dc_stop(struct tegra_dc *dc) |
1160 | { | ||
1161 | u32 value; | ||
1162 | |||
1163 | /* stop the display controller */ | ||
1164 | value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); | ||
1165 | value &= ~DISP_CTRL_MODE_MASK; | ||
1166 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); | ||
1167 | |||
1168 | tegra_dc_commit(dc); | ||
1169 | } | ||
1170 | |||
1171 | static bool tegra_dc_idle(struct tegra_dc *dc) | ||
1172 | { | ||
1173 | u32 value; | ||
1174 | |||
1175 | value = tegra_dc_readl_active(dc, DC_CMD_DISPLAY_COMMAND); | ||
1176 | |||
1177 | return (value & DISP_CTRL_MODE_MASK) == 0; | ||
1178 | } | ||
1179 | |||
1180 | static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout) | ||
1181 | { | ||
1182 | timeout = jiffies + msecs_to_jiffies(timeout); | ||
1183 | |||
1184 | while (time_before(jiffies, timeout)) { | ||
1185 | if (tegra_dc_idle(dc)) | ||
1186 | return 0; | ||
1187 | |||
1188 | usleep_range(1000, 2000); | ||
1189 | } | ||
1190 | |||
1191 | dev_dbg(dc->dev, "timeout waiting for DC to become idle\n"); | ||
1192 | return -ETIMEDOUT; | ||
1193 | } | ||
1194 | |||
1195 | static void tegra_crtc_disable(struct drm_crtc *crtc) | ||
1196 | { | ||
1197 | struct tegra_dc *dc = to_tegra_dc(crtc); | ||
1198 | u32 value; | ||
1199 | |||
1200 | if (!tegra_dc_idle(dc)) { | ||
1201 | tegra_dc_stop(dc); | ||
1202 | |||
1203 | /* | ||
1204 | * Ignore the return value, there isn't anything useful to do | ||
1205 | * in case this fails. | ||
1206 | */ | ||
1207 | tegra_dc_wait_idle(dc, 100); | ||
1208 | } | ||
1209 | |||
1210 | /* | ||
1211 | * This should really be part of the RGB encoder driver, but clearing | ||
1212 | * these bits has the side-effect of stopping the display controller. | ||
1213 | * When that happens no VBLANK interrupts will be raised. At the same | ||
1214 | * time the encoder is disabled before the display controller, so the | ||
1215 | * above code is always going to timeout waiting for the controller | ||
1216 | * to go idle. | ||
1217 | * | ||
1218 | * Given the close coupling between the RGB encoder and the display | ||
1219 | * controller doing it here is still kind of okay. None of the other | ||
1220 | * encoder drivers require these bits to be cleared. | ||
1221 | * | ||
1222 | * XXX: Perhaps given that the display controller is switched off at | ||
1223 | * this point anyway maybe clearing these bits isn't even useful for | ||
1224 | * the RGB encoder? | ||
1225 | */ | ||
1226 | if (dc->rgb) { | ||
1227 | value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); | ||
1228 | value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | | ||
1229 | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE); | ||
1230 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); | ||
1231 | } | ||
1232 | |||
1233 | tegra_dc_stats_reset(&dc->stats); | ||
1234 | drm_crtc_vblank_off(crtc); | ||
1235 | } | ||
1236 | |||
1237 | static void tegra_crtc_enable(struct drm_crtc *crtc) | ||
1233 | { | 1238 | { |
1234 | struct drm_display_mode *mode = &crtc->state->adjusted_mode; | 1239 | struct drm_display_mode *mode = &crtc->state->adjusted_mode; |
1235 | struct tegra_dc_state *state = to_dc_state(crtc->state); | 1240 | struct tegra_dc_state *state = to_dc_state(crtc->state); |
@@ -1259,15 +1264,7 @@ static void tegra_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
1259 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); | 1264 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); |
1260 | 1265 | ||
1261 | tegra_dc_commit(dc); | 1266 | tegra_dc_commit(dc); |
1262 | } | ||
1263 | |||
1264 | static void tegra_crtc_prepare(struct drm_crtc *crtc) | ||
1265 | { | ||
1266 | drm_crtc_vblank_off(crtc); | ||
1267 | } | ||
1268 | 1267 | ||
1269 | static void tegra_crtc_commit(struct drm_crtc *crtc) | ||
1270 | { | ||
1271 | drm_crtc_vblank_on(crtc); | 1268 | drm_crtc_vblank_on(crtc); |
1272 | } | 1269 | } |
1273 | 1270 | ||
@@ -1304,10 +1301,7 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc, | |||
1304 | 1301 | ||
1305 | static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { | 1302 | static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { |
1306 | .disable = tegra_crtc_disable, | 1303 | .disable = tegra_crtc_disable, |
1307 | .mode_fixup = tegra_crtc_mode_fixup, | 1304 | .enable = tegra_crtc_enable, |
1308 | .mode_set_nofb = tegra_crtc_mode_set_nofb, | ||
1309 | .prepare = tegra_crtc_prepare, | ||
1310 | .commit = tegra_crtc_commit, | ||
1311 | .atomic_check = tegra_crtc_atomic_check, | 1305 | .atomic_check = tegra_crtc_atomic_check, |
1312 | .atomic_begin = tegra_crtc_atomic_begin, | 1306 | .atomic_begin = tegra_crtc_atomic_begin, |
1313 | .atomic_flush = tegra_crtc_atomic_flush, | 1307 | .atomic_flush = tegra_crtc_atomic_flush, |
@@ -1325,6 +1319,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) | |||
1325 | /* | 1319 | /* |
1326 | dev_dbg(dc->dev, "%s(): frame end\n", __func__); | 1320 | dev_dbg(dc->dev, "%s(): frame end\n", __func__); |
1327 | */ | 1321 | */ |
1322 | dc->stats.frames++; | ||
1328 | } | 1323 | } |
1329 | 1324 | ||
1330 | if (status & VBLANK_INT) { | 1325 | if (status & VBLANK_INT) { |
@@ -1333,12 +1328,21 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) | |||
1333 | */ | 1328 | */ |
1334 | drm_crtc_handle_vblank(&dc->base); | 1329 | drm_crtc_handle_vblank(&dc->base); |
1335 | tegra_dc_finish_page_flip(dc); | 1330 | tegra_dc_finish_page_flip(dc); |
1331 | dc->stats.vblank++; | ||
1336 | } | 1332 | } |
1337 | 1333 | ||
1338 | if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) { | 1334 | if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) { |
1339 | /* | 1335 | /* |
1340 | dev_dbg(dc->dev, "%s(): underflow\n", __func__); | 1336 | dev_dbg(dc->dev, "%s(): underflow\n", __func__); |
1341 | */ | 1337 | */ |
1338 | dc->stats.underflow++; | ||
1339 | } | ||
1340 | |||
1341 | if (status & (WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT)) { | ||
1342 | /* | ||
1343 | dev_dbg(dc->dev, "%s(): overflow\n", __func__); | ||
1344 | */ | ||
1345 | dc->stats.overflow++; | ||
1342 | } | 1346 | } |
1343 | 1347 | ||
1344 | return IRQ_HANDLED; | 1348 | return IRQ_HANDLED; |
@@ -1348,6 +1352,14 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data) | |||
1348 | { | 1352 | { |
1349 | struct drm_info_node *node = s->private; | 1353 | struct drm_info_node *node = s->private; |
1350 | struct tegra_dc *dc = node->info_ent->data; | 1354 | struct tegra_dc *dc = node->info_ent->data; |
1355 | int err = 0; | ||
1356 | |||
1357 | drm_modeset_lock_crtc(&dc->base, NULL); | ||
1358 | |||
1359 | if (!dc->base.state->active) { | ||
1360 | err = -EBUSY; | ||
1361 | goto unlock; | ||
1362 | } | ||
1351 | 1363 | ||
1352 | #define DUMP_REG(name) \ | 1364 | #define DUMP_REG(name) \ |
1353 | seq_printf(s, "%-40s %#05x %08x\n", #name, name, \ | 1365 | seq_printf(s, "%-40s %#05x %08x\n", #name, name, \ |
@@ -1568,11 +1580,59 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data) | |||
1568 | 1580 | ||
1569 | #undef DUMP_REG | 1581 | #undef DUMP_REG |
1570 | 1582 | ||
1583 | unlock: | ||
1584 | drm_modeset_unlock_crtc(&dc->base); | ||
1585 | return err; | ||
1586 | } | ||
1587 | |||
1588 | static int tegra_dc_show_crc(struct seq_file *s, void *data) | ||
1589 | { | ||
1590 | struct drm_info_node *node = s->private; | ||
1591 | struct tegra_dc *dc = node->info_ent->data; | ||
1592 | int err = 0; | ||
1593 | u32 value; | ||
1594 | |||
1595 | drm_modeset_lock_crtc(&dc->base, NULL); | ||
1596 | |||
1597 | if (!dc->base.state->active) { | ||
1598 | err = -EBUSY; | ||
1599 | goto unlock; | ||
1600 | } | ||
1601 | |||
1602 | value = DC_COM_CRC_CONTROL_ACTIVE_DATA | DC_COM_CRC_CONTROL_ENABLE; | ||
1603 | tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL); | ||
1604 | tegra_dc_commit(dc); | ||
1605 | |||
1606 | drm_crtc_wait_one_vblank(&dc->base); | ||
1607 | drm_crtc_wait_one_vblank(&dc->base); | ||
1608 | |||
1609 | value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM); | ||
1610 | seq_printf(s, "%08x\n", value); | ||
1611 | |||
1612 | tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL); | ||
1613 | |||
1614 | unlock: | ||
1615 | drm_modeset_unlock_crtc(&dc->base); | ||
1616 | return err; | ||
1617 | } | ||
1618 | |||
1619 | static int tegra_dc_show_stats(struct seq_file *s, void *data) | ||
1620 | { | ||
1621 | struct drm_info_node *node = s->private; | ||
1622 | struct tegra_dc *dc = node->info_ent->data; | ||
1623 | |||
1624 | seq_printf(s, "frames: %lu\n", dc->stats.frames); | ||
1625 | seq_printf(s, "vblank: %lu\n", dc->stats.vblank); | ||
1626 | seq_printf(s, "underflow: %lu\n", dc->stats.underflow); | ||
1627 | seq_printf(s, "overflow: %lu\n", dc->stats.overflow); | ||
1628 | |||
1571 | return 0; | 1629 | return 0; |
1572 | } | 1630 | } |
1573 | 1631 | ||
1574 | static struct drm_info_list debugfs_files[] = { | 1632 | static struct drm_info_list debugfs_files[] = { |
1575 | { "regs", tegra_dc_show_regs, 0, NULL }, | 1633 | { "regs", tegra_dc_show_regs, 0, NULL }, |
1634 | { "crc", tegra_dc_show_crc, 0, NULL }, | ||
1635 | { "stats", tegra_dc_show_stats, 0, NULL }, | ||
1576 | }; | 1636 | }; |
1577 | 1637 | ||
1578 | static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor) | 1638 | static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor) |
@@ -1718,7 +1778,8 @@ static int tegra_dc_init(struct host1x_client *client) | |||
1718 | tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC); | 1778 | tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC); |
1719 | } | 1779 | } |
1720 | 1780 | ||
1721 | value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT; | 1781 | value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | |
1782 | WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT; | ||
1722 | tegra_dc_writel(dc, value, DC_CMD_INT_TYPE); | 1783 | tegra_dc_writel(dc, value, DC_CMD_INT_TYPE); |
1723 | 1784 | ||
1724 | value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | | 1785 | value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | |
@@ -1734,15 +1795,19 @@ static int tegra_dc_init(struct host1x_client *client) | |||
1734 | WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1); | 1795 | WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1); |
1735 | tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER); | 1796 | tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER); |
1736 | 1797 | ||
1737 | value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; | 1798 | value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | |
1799 | WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT; | ||
1738 | tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); | 1800 | tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); |
1739 | 1801 | ||
1740 | value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; | 1802 | value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | |
1803 | WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT; | ||
1741 | tegra_dc_writel(dc, value, DC_CMD_INT_MASK); | 1804 | tegra_dc_writel(dc, value, DC_CMD_INT_MASK); |
1742 | 1805 | ||
1743 | if (dc->soc->supports_border_color) | 1806 | if (dc->soc->supports_border_color) |
1744 | tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR); | 1807 | tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR); |
1745 | 1808 | ||
1809 | tegra_dc_stats_reset(&dc->stats); | ||
1810 | |||
1746 | return 0; | 1811 | return 0; |
1747 | 1812 | ||
1748 | cleanup: | 1813 | cleanup: |
@@ -1828,8 +1893,20 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = { | |||
1828 | .has_powergate = true, | 1893 | .has_powergate = true, |
1829 | }; | 1894 | }; |
1830 | 1895 | ||
1896 | static const struct tegra_dc_soc_info tegra210_dc_soc_info = { | ||
1897 | .supports_border_color = false, | ||
1898 | .supports_interlacing = true, | ||
1899 | .supports_cursor = true, | ||
1900 | .supports_block_linear = true, | ||
1901 | .pitch_align = 64, | ||
1902 | .has_powergate = true, | ||
1903 | }; | ||
1904 | |||
1831 | static const struct of_device_id tegra_dc_of_match[] = { | 1905 | static const struct of_device_id tegra_dc_of_match[] = { |
1832 | { | 1906 | { |
1907 | .compatible = "nvidia,tegra210-dc", | ||
1908 | .data = &tegra210_dc_soc_info, | ||
1909 | }, { | ||
1833 | .compatible = "nvidia,tegra124-dc", | 1910 | .compatible = "nvidia,tegra124-dc", |
1834 | .data = &tegra124_dc_soc_info, | 1911 | .data = &tegra124_dc_soc_info, |
1835 | }, { | 1912 | }, { |
@@ -1959,6 +2036,10 @@ static int tegra_dc_probe(struct platform_device *pdev) | |||
1959 | return -ENXIO; | 2036 | return -ENXIO; |
1960 | } | 2037 | } |
1961 | 2038 | ||
2039 | dc->syncpt = host1x_syncpt_request(&pdev->dev, flags); | ||
2040 | if (!dc->syncpt) | ||
2041 | dev_warn(&pdev->dev, "failed to allocate syncpoint\n"); | ||
2042 | |||
1962 | INIT_LIST_HEAD(&dc->client.list); | 2043 | INIT_LIST_HEAD(&dc->client.list); |
1963 | dc->client.ops = &dc_client_ops; | 2044 | dc->client.ops = &dc_client_ops; |
1964 | dc->client.dev = &pdev->dev; | 2045 | dc->client.dev = &pdev->dev; |
@@ -1976,10 +2057,6 @@ static int tegra_dc_probe(struct platform_device *pdev) | |||
1976 | return err; | 2057 | return err; |
1977 | } | 2058 | } |
1978 | 2059 | ||
1979 | dc->syncpt = host1x_syncpt_request(&pdev->dev, flags); | ||
1980 | if (!dc->syncpt) | ||
1981 | dev_warn(&pdev->dev, "failed to allocate syncpoint\n"); | ||
1982 | |||
1983 | platform_set_drvdata(pdev, dc); | 2060 | platform_set_drvdata(pdev, dc); |
1984 | 2061 | ||
1985 | return 0; | 2062 | return 0; |
@@ -2018,7 +2095,6 @@ static int tegra_dc_remove(struct platform_device *pdev) | |||
2018 | struct platform_driver tegra_dc_driver = { | 2095 | struct platform_driver tegra_dc_driver = { |
2019 | .driver = { | 2096 | .driver = { |
2020 | .name = "tegra-dc", | 2097 | .name = "tegra-dc", |
2021 | .owner = THIS_MODULE, | ||
2022 | .of_match_table = tegra_dc_of_match, | 2098 | .of_match_table = tegra_dc_of_match, |
2023 | }, | 2099 | }, |
2024 | .probe = tegra_dc_probe, | 2100 | .probe = tegra_dc_probe, |
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 55792daabbb5..4a268635749b 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h | |||
@@ -86,6 +86,11 @@ | |||
86 | #define DC_CMD_REG_ACT_CONTROL 0x043 | 86 | #define DC_CMD_REG_ACT_CONTROL 0x043 |
87 | 87 | ||
88 | #define DC_COM_CRC_CONTROL 0x300 | 88 | #define DC_COM_CRC_CONTROL 0x300 |
89 | #define DC_COM_CRC_CONTROL_ALWAYS (1 << 3) | ||
90 | #define DC_COM_CRC_CONTROL_FULL_FRAME (0 << 2) | ||
91 | #define DC_COM_CRC_CONTROL_ACTIVE_DATA (1 << 2) | ||
92 | #define DC_COM_CRC_CONTROL_WAIT (1 << 1) | ||
93 | #define DC_COM_CRC_CONTROL_ENABLE (1 << 0) | ||
89 | #define DC_COM_CRC_CHECKSUM 0x301 | 94 | #define DC_COM_CRC_CHECKSUM 0x301 |
90 | #define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) | 95 | #define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) |
91 | #define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) | 96 | #define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) |
@@ -114,15 +119,17 @@ | |||
114 | #define DC_COM_CRC_CHECKSUM_LATCHED 0x329 | 119 | #define DC_COM_CRC_CHECKSUM_LATCHED 0x329 |
115 | 120 | ||
116 | #define DC_DISP_DISP_SIGNAL_OPTIONS0 0x400 | 121 | #define DC_DISP_DISP_SIGNAL_OPTIONS0 0x400 |
117 | #define H_PULSE_0_ENABLE (1 << 8) | 122 | #define H_PULSE0_ENABLE (1 << 8) |
118 | #define H_PULSE_1_ENABLE (1 << 10) | 123 | #define H_PULSE1_ENABLE (1 << 10) |
119 | #define H_PULSE_2_ENABLE (1 << 12) | 124 | #define H_PULSE2_ENABLE (1 << 12) |
120 | 125 | ||
121 | #define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401 | 126 | #define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401 |
122 | 127 | ||
123 | #define DC_DISP_DISP_WIN_OPTIONS 0x402 | 128 | #define DC_DISP_DISP_WIN_OPTIONS 0x402 |
124 | #define HDMI_ENABLE (1 << 30) | 129 | #define HDMI_ENABLE (1 << 30) |
125 | #define DSI_ENABLE (1 << 29) | 130 | #define DSI_ENABLE (1 << 29) |
131 | #define SOR1_TIMING_CYA (1 << 27) | ||
132 | #define SOR1_ENABLE (1 << 26) | ||
126 | #define SOR_ENABLE (1 << 25) | 133 | #define SOR_ENABLE (1 << 25) |
127 | #define CURSOR_ENABLE (1 << 16) | 134 | #define CURSOR_ENABLE (1 << 16) |
128 | 135 | ||
@@ -242,9 +249,20 @@ | |||
242 | #define BASE_COLOR_SIZE565 (6 << 0) | 249 | #define BASE_COLOR_SIZE565 (6 << 0) |
243 | #define BASE_COLOR_SIZE332 (7 << 0) | 250 | #define BASE_COLOR_SIZE332 (7 << 0) |
244 | #define BASE_COLOR_SIZE888 (8 << 0) | 251 | #define BASE_COLOR_SIZE888 (8 << 0) |
252 | #define DITHER_CONTROL_MASK (3 << 8) | ||
245 | #define DITHER_CONTROL_DISABLE (0 << 8) | 253 | #define DITHER_CONTROL_DISABLE (0 << 8) |
246 | #define DITHER_CONTROL_ORDERED (2 << 8) | 254 | #define DITHER_CONTROL_ORDERED (2 << 8) |
247 | #define DITHER_CONTROL_ERRDIFF (3 << 8) | 255 | #define DITHER_CONTROL_ERRDIFF (3 << 8) |
256 | #define BASE_COLOR_SIZE_MASK (0xf << 0) | ||
257 | #define BASE_COLOR_SIZE_666 (0 << 0) | ||
258 | #define BASE_COLOR_SIZE_111 (1 << 0) | ||
259 | #define BASE_COLOR_SIZE_222 (2 << 0) | ||
260 | #define BASE_COLOR_SIZE_333 (3 << 0) | ||
261 | #define BASE_COLOR_SIZE_444 (4 << 0) | ||
262 | #define BASE_COLOR_SIZE_555 (5 << 0) | ||
263 | #define BASE_COLOR_SIZE_565 (6 << 0) | ||
264 | #define BASE_COLOR_SIZE_332 (7 << 0) | ||
265 | #define BASE_COLOR_SIZE_888 (8 << 0) | ||
248 | 266 | ||
249 | #define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 | 267 | #define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 |
250 | #define SC1_H_QUALIFIER_NONE (1 << 16) | 268 | #define SC1_H_QUALIFIER_NONE (1 << 16) |
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 07b26972f487..224a7dc8e4ed 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c | |||
@@ -294,26 +294,41 @@ static int tegra_dpaux_probe(struct platform_device *pdev) | |||
294 | } | 294 | } |
295 | 295 | ||
296 | dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux"); | 296 | dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux"); |
297 | if (IS_ERR(dpaux->rst)) | 297 | if (IS_ERR(dpaux->rst)) { |
298 | dev_err(&pdev->dev, "failed to get reset control: %ld\n", | ||
299 | PTR_ERR(dpaux->rst)); | ||
298 | return PTR_ERR(dpaux->rst); | 300 | return PTR_ERR(dpaux->rst); |
301 | } | ||
299 | 302 | ||
300 | dpaux->clk = devm_clk_get(&pdev->dev, NULL); | 303 | dpaux->clk = devm_clk_get(&pdev->dev, NULL); |
301 | if (IS_ERR(dpaux->clk)) | 304 | if (IS_ERR(dpaux->clk)) { |
305 | dev_err(&pdev->dev, "failed to get module clock: %ld\n", | ||
306 | PTR_ERR(dpaux->clk)); | ||
302 | return PTR_ERR(dpaux->clk); | 307 | return PTR_ERR(dpaux->clk); |
308 | } | ||
303 | 309 | ||
304 | err = clk_prepare_enable(dpaux->clk); | 310 | err = clk_prepare_enable(dpaux->clk); |
305 | if (err < 0) | 311 | if (err < 0) { |
312 | dev_err(&pdev->dev, "failed to enable module clock: %d\n", | ||
313 | err); | ||
306 | return err; | 314 | return err; |
315 | } | ||
307 | 316 | ||
308 | reset_control_deassert(dpaux->rst); | 317 | reset_control_deassert(dpaux->rst); |
309 | 318 | ||
310 | dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent"); | 319 | dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent"); |
311 | if (IS_ERR(dpaux->clk_parent)) | 320 | if (IS_ERR(dpaux->clk_parent)) { |
321 | dev_err(&pdev->dev, "failed to get parent clock: %ld\n", | ||
322 | PTR_ERR(dpaux->clk_parent)); | ||
312 | return PTR_ERR(dpaux->clk_parent); | 323 | return PTR_ERR(dpaux->clk_parent); |
324 | } | ||
313 | 325 | ||
314 | err = clk_prepare_enable(dpaux->clk_parent); | 326 | err = clk_prepare_enable(dpaux->clk_parent); |
315 | if (err < 0) | 327 | if (err < 0) { |
328 | dev_err(&pdev->dev, "failed to enable parent clock: %d\n", | ||
329 | err); | ||
316 | return err; | 330 | return err; |
331 | } | ||
317 | 332 | ||
318 | err = clk_set_rate(dpaux->clk_parent, 270000000); | 333 | err = clk_set_rate(dpaux->clk_parent, 270000000); |
319 | if (err < 0) { | 334 | if (err < 0) { |
@@ -323,8 +338,11 @@ static int tegra_dpaux_probe(struct platform_device *pdev) | |||
323 | } | 338 | } |
324 | 339 | ||
325 | dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd"); | 340 | dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd"); |
326 | if (IS_ERR(dpaux->vdd)) | 341 | if (IS_ERR(dpaux->vdd)) { |
342 | dev_err(&pdev->dev, "failed to get VDD supply: %ld\n", | ||
343 | PTR_ERR(dpaux->vdd)); | ||
327 | return PTR_ERR(dpaux->vdd); | 344 | return PTR_ERR(dpaux->vdd); |
345 | } | ||
328 | 346 | ||
329 | err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0, | 347 | err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0, |
330 | dev_name(dpaux->dev), dpaux); | 348 | dev_name(dpaux->dev), dpaux); |
@@ -334,6 +352,8 @@ static int tegra_dpaux_probe(struct platform_device *pdev) | |||
334 | return err; | 352 | return err; |
335 | } | 353 | } |
336 | 354 | ||
355 | disable_irq(dpaux->irq); | ||
356 | |||
337 | dpaux->aux.transfer = tegra_dpaux_transfer; | 357 | dpaux->aux.transfer = tegra_dpaux_transfer; |
338 | dpaux->aux.dev = &pdev->dev; | 358 | dpaux->aux.dev = &pdev->dev; |
339 | 359 | ||
@@ -341,6 +361,24 @@ static int tegra_dpaux_probe(struct platform_device *pdev) | |||
341 | if (err < 0) | 361 | if (err < 0) |
342 | return err; | 362 | return err; |
343 | 363 | ||
364 | /* | ||
365 | * Assume that by default the DPAUX/I2C pads will be used for HDMI, | ||
366 | * so power them up and configure them in I2C mode. | ||
367 | * | ||
368 | * The DPAUX code paths reconfigure the pads in AUX mode, but there | ||
369 | * is no possibility to perform the I2C mode configuration in the | ||
370 | * HDMI path. | ||
371 | */ | ||
372 | value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE); | ||
373 | value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN; | ||
374 | tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE); | ||
375 | |||
376 | value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_PADCTL); | ||
377 | value = DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV | | ||
378 | DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV | | ||
379 | DPAUX_HYBRID_PADCTL_MODE_I2C; | ||
380 | tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL); | ||
381 | |||
344 | /* enable and clear all interrupts */ | 382 | /* enable and clear all interrupts */ |
345 | value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT | | 383 | value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT | |
346 | DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT; | 384 | DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT; |
@@ -359,6 +397,12 @@ static int tegra_dpaux_probe(struct platform_device *pdev) | |||
359 | static int tegra_dpaux_remove(struct platform_device *pdev) | 397 | static int tegra_dpaux_remove(struct platform_device *pdev) |
360 | { | 398 | { |
361 | struct tegra_dpaux *dpaux = platform_get_drvdata(pdev); | 399 | struct tegra_dpaux *dpaux = platform_get_drvdata(pdev); |
400 | u32 value; | ||
401 | |||
402 | /* make sure pads are powered down when not in use */ | ||
403 | value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE); | ||
404 | value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN; | ||
405 | tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE); | ||
362 | 406 | ||
363 | drm_dp_aux_unregister(&dpaux->aux); | 407 | drm_dp_aux_unregister(&dpaux->aux); |
364 | 408 | ||
@@ -376,6 +420,7 @@ static int tegra_dpaux_remove(struct platform_device *pdev) | |||
376 | } | 420 | } |
377 | 421 | ||
378 | static const struct of_device_id tegra_dpaux_of_match[] = { | 422 | static const struct of_device_id tegra_dpaux_of_match[] = { |
423 | { .compatible = "nvidia,tegra210-dpaux", }, | ||
379 | { .compatible = "nvidia,tegra124-dpaux", }, | 424 | { .compatible = "nvidia,tegra124-dpaux", }, |
380 | { }, | 425 | { }, |
381 | }; | 426 | }; |
@@ -425,8 +470,10 @@ int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output) | |||
425 | enum drm_connector_status status; | 470 | enum drm_connector_status status; |
426 | 471 | ||
427 | status = tegra_dpaux_detect(dpaux); | 472 | status = tegra_dpaux_detect(dpaux); |
428 | if (status == connector_status_connected) | 473 | if (status == connector_status_connected) { |
474 | enable_irq(dpaux->irq); | ||
429 | return 0; | 475 | return 0; |
476 | } | ||
430 | 477 | ||
431 | usleep_range(1000, 2000); | 478 | usleep_range(1000, 2000); |
432 | } | 479 | } |
@@ -439,6 +486,8 @@ int tegra_dpaux_detach(struct tegra_dpaux *dpaux) | |||
439 | unsigned long timeout; | 486 | unsigned long timeout; |
440 | int err; | 487 | int err; |
441 | 488 | ||
489 | disable_irq(dpaux->irq); | ||
490 | |||
442 | err = regulator_disable(dpaux->vdd); | 491 | err = regulator_disable(dpaux->vdd); |
443 | if (err < 0) | 492 | if (err < 0) |
444 | return err; | 493 | return err; |
diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h index 806e245ca787..20783d9f4728 100644 --- a/drivers/gpu/drm/tegra/dpaux.h +++ b/drivers/gpu/drm/tegra/dpaux.h | |||
@@ -57,6 +57,8 @@ | |||
57 | #define DPAUX_DP_AUX_CONFIG 0x45 | 57 | #define DPAUX_DP_AUX_CONFIG 0x45 |
58 | 58 | ||
59 | #define DPAUX_HYBRID_PADCTL 0x49 | 59 | #define DPAUX_HYBRID_PADCTL 0x49 |
60 | #define DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV (1 << 15) | ||
61 | #define DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV (1 << 14) | ||
60 | #define DPAUX_HYBRID_PADCTL_AUX_CMH(x) (((x) & 0x3) << 12) | 62 | #define DPAUX_HYBRID_PADCTL_AUX_CMH(x) (((x) & 0x3) << 12) |
61 | #define DPAUX_HYBRID_PADCTL_AUX_DRVZ(x) (((x) & 0x7) << 8) | 63 | #define DPAUX_HYBRID_PADCTL_AUX_DRVZ(x) (((x) & 0x7) << 8) |
62 | #define DPAUX_HYBRID_PADCTL_AUX_DRVI(x) (((x) & 0x3f) << 2) | 64 | #define DPAUX_HYBRID_PADCTL_AUX_DRVI(x) (((x) & 0x3f) << 2) |
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 427f50c6803c..6d88cf1fcd1c 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
@@ -171,8 +171,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
171 | if (err < 0) | 171 | if (err < 0) |
172 | goto fbdev; | 172 | goto fbdev; |
173 | 173 | ||
174 | drm_mode_config_reset(drm); | ||
175 | |||
176 | /* | 174 | /* |
177 | * We don't use the drm_irq_install() helpers provided by the DRM | 175 | * We don't use the drm_irq_install() helpers provided by the DRM |
178 | * core, so we need to set this manually in order to allow the | 176 | * core, so we need to set this manually in order to allow the |
@@ -182,11 +180,14 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
182 | 180 | ||
183 | /* syncpoints are used for full 32-bit hardware VBLANK counters */ | 181 | /* syncpoints are used for full 32-bit hardware VBLANK counters */ |
184 | drm->max_vblank_count = 0xffffffff; | 182 | drm->max_vblank_count = 0xffffffff; |
183 | drm->vblank_disable_allowed = true; | ||
185 | 184 | ||
186 | err = drm_vblank_init(drm, drm->mode_config.num_crtc); | 185 | err = drm_vblank_init(drm, drm->mode_config.num_crtc); |
187 | if (err < 0) | 186 | if (err < 0) |
188 | goto device; | 187 | goto device; |
189 | 188 | ||
189 | drm_mode_config_reset(drm); | ||
190 | |||
190 | err = tegra_drm_fb_init(drm); | 191 | err = tegra_drm_fb_init(drm); |
191 | if (err < 0) | 192 | if (err < 0) |
192 | goto vblank; | 193 | goto vblank; |
@@ -1037,9 +1038,8 @@ static int host1x_drm_resume(struct device *dev) | |||
1037 | } | 1038 | } |
1038 | #endif | 1039 | #endif |
1039 | 1040 | ||
1040 | static const struct dev_pm_ops host1x_drm_pm_ops = { | 1041 | static SIMPLE_DEV_PM_OPS(host1x_drm_pm_ops, host1x_drm_suspend, |
1041 | SET_SYSTEM_SLEEP_PM_OPS(host1x_drm_suspend, host1x_drm_resume) | 1042 | host1x_drm_resume); |
1042 | }; | ||
1043 | 1043 | ||
1044 | static const struct of_device_id host1x_drm_subdevs[] = { | 1044 | static const struct of_device_id host1x_drm_subdevs[] = { |
1045 | { .compatible = "nvidia,tegra20-dc", }, | 1045 | { .compatible = "nvidia,tegra20-dc", }, |
@@ -1056,6 +1056,12 @@ static const struct of_device_id host1x_drm_subdevs[] = { | |||
1056 | { .compatible = "nvidia,tegra124-dc", }, | 1056 | { .compatible = "nvidia,tegra124-dc", }, |
1057 | { .compatible = "nvidia,tegra124-sor", }, | 1057 | { .compatible = "nvidia,tegra124-sor", }, |
1058 | { .compatible = "nvidia,tegra124-hdmi", }, | 1058 | { .compatible = "nvidia,tegra124-hdmi", }, |
1059 | { .compatible = "nvidia,tegra124-dsi", }, | ||
1060 | { .compatible = "nvidia,tegra132-dsi", }, | ||
1061 | { .compatible = "nvidia,tegra210-dc", }, | ||
1062 | { .compatible = "nvidia,tegra210-dsi", }, | ||
1063 | { .compatible = "nvidia,tegra210-sor", }, | ||
1064 | { .compatible = "nvidia,tegra210-sor1", }, | ||
1059 | { /* sentinel */ } | 1065 | { /* sentinel */ } |
1060 | }; | 1066 | }; |
1061 | 1067 | ||
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 659b2fcc986d..ec49275ffb24 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <uapi/drm/tegra_drm.h> | 13 | #include <uapi/drm/tegra_drm.h> |
14 | #include <linux/host1x.h> | 14 | #include <linux/host1x.h> |
15 | #include <linux/of_gpio.h> | ||
15 | 16 | ||
16 | #include <drm/drmP.h> | 17 | #include <drm/drmP.h> |
17 | #include <drm/drm_crtc_helper.h> | 18 | #include <drm/drm_crtc_helper.h> |
@@ -104,6 +105,13 @@ int tegra_drm_exit(struct tegra_drm *tegra); | |||
104 | struct tegra_dc_soc_info; | 105 | struct tegra_dc_soc_info; |
105 | struct tegra_output; | 106 | struct tegra_output; |
106 | 107 | ||
108 | struct tegra_dc_stats { | ||
109 | unsigned long frames; | ||
110 | unsigned long vblank; | ||
111 | unsigned long underflow; | ||
112 | unsigned long overflow; | ||
113 | }; | ||
114 | |||
107 | struct tegra_dc { | 115 | struct tegra_dc { |
108 | struct host1x_client client; | 116 | struct host1x_client client; |
109 | struct host1x_syncpt *syncpt; | 117 | struct host1x_syncpt *syncpt; |
@@ -121,6 +129,7 @@ struct tegra_dc { | |||
121 | 129 | ||
122 | struct tegra_output *rgb; | 130 | struct tegra_output *rgb; |
123 | 131 | ||
132 | struct tegra_dc_stats stats; | ||
124 | struct list_head list; | 133 | struct list_head list; |
125 | 134 | ||
126 | struct drm_info_list *debugfs_files; | 135 | struct drm_info_list *debugfs_files; |
@@ -200,6 +209,7 @@ struct tegra_output { | |||
200 | const struct edid *edid; | 209 | const struct edid *edid; |
201 | unsigned int hpd_irq; | 210 | unsigned int hpd_irq; |
202 | int hpd_gpio; | 211 | int hpd_gpio; |
212 | enum of_gpio_flags hpd_gpio_flags; | ||
203 | 213 | ||
204 | struct drm_encoder encoder; | 214 | struct drm_encoder encoder; |
205 | struct drm_connector connector; | 215 | struct drm_connector connector; |
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index dc97c0b3681d..f0a138ef68ce 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c | |||
@@ -119,6 +119,16 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data) | |||
119 | { | 119 | { |
120 | struct drm_info_node *node = s->private; | 120 | struct drm_info_node *node = s->private; |
121 | struct tegra_dsi *dsi = node->info_ent->data; | 121 | struct tegra_dsi *dsi = node->info_ent->data; |
122 | struct drm_crtc *crtc = dsi->output.encoder.crtc; | ||
123 | struct drm_device *drm = node->minor->dev; | ||
124 | int err = 0; | ||
125 | |||
126 | drm_modeset_lock_all(drm); | ||
127 | |||
128 | if (!crtc || !crtc->state->active) { | ||
129 | err = -EBUSY; | ||
130 | goto unlock; | ||
131 | } | ||
122 | 132 | ||
123 | #define DUMP_REG(name) \ | 133 | #define DUMP_REG(name) \ |
124 | seq_printf(s, "%-32s %#05x %08x\n", #name, name, \ | 134 | seq_printf(s, "%-32s %#05x %08x\n", #name, name, \ |
@@ -208,7 +218,9 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data) | |||
208 | 218 | ||
209 | #undef DUMP_REG | 219 | #undef DUMP_REG |
210 | 220 | ||
211 | return 0; | 221 | unlock: |
222 | drm_modeset_unlock_all(drm); | ||
223 | return err; | ||
212 | } | 224 | } |
213 | 225 | ||
214 | static struct drm_info_list debugfs_files[] = { | 226 | static struct drm_info_list debugfs_files[] = { |
@@ -548,14 +560,19 @@ static void tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe, | |||
548 | 560 | ||
549 | /* horizontal sync width */ | 561 | /* horizontal sync width */ |
550 | hsw = (mode->hsync_end - mode->hsync_start) * mul / div; | 562 | hsw = (mode->hsync_end - mode->hsync_start) * mul / div; |
551 | hsw -= 10; | ||
552 | 563 | ||
553 | /* horizontal back porch */ | 564 | /* horizontal back porch */ |
554 | hbp = (mode->htotal - mode->hsync_end) * mul / div; | 565 | hbp = (mode->htotal - mode->hsync_end) * mul / div; |
555 | hbp -= 14; | 566 | |
567 | if ((dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0) | ||
568 | hbp += hsw; | ||
556 | 569 | ||
557 | /* horizontal front porch */ | 570 | /* horizontal front porch */ |
558 | hfp = (mode->hsync_start - mode->hdisplay) * mul / div; | 571 | hfp = (mode->hsync_start - mode->hdisplay) * mul / div; |
572 | |||
573 | /* subtract packet overhead */ | ||
574 | hsw -= 10; | ||
575 | hbp -= 14; | ||
559 | hfp -= 8; | 576 | hfp -= 8; |
560 | 577 | ||
561 | tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1); | 578 | tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1); |
@@ -726,11 +743,6 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi) | |||
726 | tegra_dsi_soft_reset(dsi->slave); | 743 | tegra_dsi_soft_reset(dsi->slave); |
727 | } | 744 | } |
728 | 745 | ||
729 | static int tegra_dsi_connector_dpms(struct drm_connector *connector, int mode) | ||
730 | { | ||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | static void tegra_dsi_connector_reset(struct drm_connector *connector) | 746 | static void tegra_dsi_connector_reset(struct drm_connector *connector) |
735 | { | 747 | { |
736 | struct tegra_dsi_state *state; | 748 | struct tegra_dsi_state *state; |
@@ -757,7 +769,7 @@ tegra_dsi_connector_duplicate_state(struct drm_connector *connector) | |||
757 | } | 769 | } |
758 | 770 | ||
759 | static const struct drm_connector_funcs tegra_dsi_connector_funcs = { | 771 | static const struct drm_connector_funcs tegra_dsi_connector_funcs = { |
760 | .dpms = tegra_dsi_connector_dpms, | 772 | .dpms = drm_atomic_helper_connector_dpms, |
761 | .reset = tegra_dsi_connector_reset, | 773 | .reset = tegra_dsi_connector_reset, |
762 | .detect = tegra_output_connector_detect, | 774 | .detect = tegra_output_connector_detect, |
763 | .fill_modes = drm_helper_probe_single_connector_modes, | 775 | .fill_modes = drm_helper_probe_single_connector_modes, |
@@ -783,22 +795,48 @@ static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = { | |||
783 | .destroy = tegra_output_encoder_destroy, | 795 | .destroy = tegra_output_encoder_destroy, |
784 | }; | 796 | }; |
785 | 797 | ||
786 | static void tegra_dsi_encoder_dpms(struct drm_encoder *encoder, int mode) | 798 | static void tegra_dsi_encoder_disable(struct drm_encoder *encoder) |
787 | { | 799 | { |
788 | } | 800 | struct tegra_output *output = encoder_to_output(encoder); |
801 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | ||
802 | struct tegra_dsi *dsi = to_dsi(output); | ||
803 | u32 value; | ||
804 | int err; | ||
789 | 805 | ||
790 | static void tegra_dsi_encoder_prepare(struct drm_encoder *encoder) | 806 | if (output->panel) |
791 | { | 807 | drm_panel_disable(output->panel); |
792 | } | ||
793 | 808 | ||
794 | static void tegra_dsi_encoder_commit(struct drm_encoder *encoder) | 809 | tegra_dsi_video_disable(dsi); |
795 | { | 810 | |
811 | /* | ||
812 | * The following accesses registers of the display controller, so make | ||
813 | * sure it's only executed when the output is attached to one. | ||
814 | */ | ||
815 | if (dc) { | ||
816 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
817 | value &= ~DSI_ENABLE; | ||
818 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
819 | |||
820 | tegra_dc_commit(dc); | ||
821 | } | ||
822 | |||
823 | err = tegra_dsi_wait_idle(dsi, 100); | ||
824 | if (err < 0) | ||
825 | dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err); | ||
826 | |||
827 | tegra_dsi_soft_reset(dsi); | ||
828 | |||
829 | if (output->panel) | ||
830 | drm_panel_unprepare(output->panel); | ||
831 | |||
832 | tegra_dsi_disable(dsi); | ||
833 | |||
834 | return; | ||
796 | } | 835 | } |
797 | 836 | ||
798 | static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder, | 837 | static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) |
799 | struct drm_display_mode *mode, | ||
800 | struct drm_display_mode *adjusted) | ||
801 | { | 838 | { |
839 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; | ||
802 | struct tegra_output *output = encoder_to_output(encoder); | 840 | struct tegra_output *output = encoder_to_output(encoder); |
803 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | 841 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
804 | struct tegra_dsi *dsi = to_dsi(output); | 842 | struct tegra_dsi *dsi = to_dsi(output); |
@@ -836,45 +874,6 @@ static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder, | |||
836 | return; | 874 | return; |
837 | } | 875 | } |
838 | 876 | ||
839 | static void tegra_dsi_encoder_disable(struct drm_encoder *encoder) | ||
840 | { | ||
841 | struct tegra_output *output = encoder_to_output(encoder); | ||
842 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | ||
843 | struct tegra_dsi *dsi = to_dsi(output); | ||
844 | u32 value; | ||
845 | int err; | ||
846 | |||
847 | if (output->panel) | ||
848 | drm_panel_disable(output->panel); | ||
849 | |||
850 | tegra_dsi_video_disable(dsi); | ||
851 | |||
852 | /* | ||
853 | * The following accesses registers of the display controller, so make | ||
854 | * sure it's only executed when the output is attached to one. | ||
855 | */ | ||
856 | if (dc) { | ||
857 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
858 | value &= ~DSI_ENABLE; | ||
859 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
860 | |||
861 | tegra_dc_commit(dc); | ||
862 | } | ||
863 | |||
864 | err = tegra_dsi_wait_idle(dsi, 100); | ||
865 | if (err < 0) | ||
866 | dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err); | ||
867 | |||
868 | tegra_dsi_soft_reset(dsi); | ||
869 | |||
870 | if (output->panel) | ||
871 | drm_panel_unprepare(output->panel); | ||
872 | |||
873 | tegra_dsi_disable(dsi); | ||
874 | |||
875 | return; | ||
876 | } | ||
877 | |||
878 | static int | 877 | static int |
879 | tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder, | 878 | tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder, |
880 | struct drm_crtc_state *crtc_state, | 879 | struct drm_crtc_state *crtc_state, |
@@ -957,11 +956,8 @@ tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder, | |||
957 | } | 956 | } |
958 | 957 | ||
959 | static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = { | 958 | static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = { |
960 | .dpms = tegra_dsi_encoder_dpms, | ||
961 | .prepare = tegra_dsi_encoder_prepare, | ||
962 | .commit = tegra_dsi_encoder_commit, | ||
963 | .mode_set = tegra_dsi_encoder_mode_set, | ||
964 | .disable = tegra_dsi_encoder_disable, | 959 | .disable = tegra_dsi_encoder_disable, |
960 | .enable = tegra_dsi_encoder_enable, | ||
965 | .atomic_check = tegra_dsi_encoder_atomic_check, | 961 | .atomic_check = tegra_dsi_encoder_atomic_check, |
966 | }; | 962 | }; |
967 | 963 | ||
@@ -993,6 +989,10 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) | |||
993 | DSI_PAD_OUT_CLK(0x0); | 989 | DSI_PAD_OUT_CLK(0x0); |
994 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); | 990 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); |
995 | 991 | ||
992 | value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | | ||
993 | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); | ||
994 | tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3); | ||
995 | |||
996 | return tegra_mipi_calibrate(dsi->mipi); | 996 | return tegra_mipi_calibrate(dsi->mipi); |
997 | } | 997 | } |
998 | 998 | ||
@@ -1622,6 +1622,9 @@ static int tegra_dsi_remove(struct platform_device *pdev) | |||
1622 | } | 1622 | } |
1623 | 1623 | ||
1624 | static const struct of_device_id tegra_dsi_of_match[] = { | 1624 | static const struct of_device_id tegra_dsi_of_match[] = { |
1625 | { .compatible = "nvidia,tegra210-dsi", }, | ||
1626 | { .compatible = "nvidia,tegra132-dsi", }, | ||
1627 | { .compatible = "nvidia,tegra124-dsi", }, | ||
1625 | { .compatible = "nvidia,tegra114-dsi", }, | 1628 | { .compatible = "nvidia,tegra114-dsi", }, |
1626 | { }, | 1629 | { }, |
1627 | }; | 1630 | }; |
diff --git a/drivers/gpu/drm/tegra/dsi.h b/drivers/gpu/drm/tegra/dsi.h index bad1006a5150..219263615399 100644 --- a/drivers/gpu/drm/tegra/dsi.h +++ b/drivers/gpu/drm/tegra/dsi.h | |||
@@ -113,6 +113,10 @@ | |||
113 | #define DSI_PAD_SLEW_DN(x) (((x) & 0x7) << 12) | 113 | #define DSI_PAD_SLEW_DN(x) (((x) & 0x7) << 12) |
114 | #define DSI_PAD_SLEW_UP(x) (((x) & 0x7) << 16) | 114 | #define DSI_PAD_SLEW_UP(x) (((x) & 0x7) << 16) |
115 | #define DSI_PAD_CONTROL_3 0x51 | 115 | #define DSI_PAD_CONTROL_3 0x51 |
116 | #define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12) | ||
117 | #define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8) | ||
118 | #define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4) | ||
119 | #define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0) | ||
116 | #define DSI_PAD_CONTROL_4 0x52 | 120 | #define DSI_PAD_CONTROL_4 0x52 |
117 | #define DSI_GANGED_MODE_CONTROL 0x53 | 121 | #define DSI_GANGED_MODE_CONTROL 0x53 |
118 | #define DSI_GANGED_MODE_CONTROL_ENABLE (1 << 0) | 122 | #define DSI_GANGED_MODE_CONTROL_ENABLE (1 << 0) |
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index fe4008a7ddba..52b32cbd9de6 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c | |||
@@ -772,14 +772,8 @@ static bool tegra_output_is_hdmi(struct tegra_output *output) | |||
772 | return drm_detect_hdmi_monitor(edid); | 772 | return drm_detect_hdmi_monitor(edid); |
773 | } | 773 | } |
774 | 774 | ||
775 | static int tegra_hdmi_connector_dpms(struct drm_connector *connector, | ||
776 | int mode) | ||
777 | { | ||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | static const struct drm_connector_funcs tegra_hdmi_connector_funcs = { | 775 | static const struct drm_connector_funcs tegra_hdmi_connector_funcs = { |
782 | .dpms = tegra_hdmi_connector_dpms, | 776 | .dpms = drm_atomic_helper_connector_dpms, |
783 | .reset = drm_atomic_helper_connector_reset, | 777 | .reset = drm_atomic_helper_connector_reset, |
784 | .detect = tegra_output_connector_detect, | 778 | .detect = tegra_output_connector_detect, |
785 | .fill_modes = drm_helper_probe_single_connector_modes, | 779 | .fill_modes = drm_helper_probe_single_connector_modes, |
@@ -819,22 +813,27 @@ static const struct drm_encoder_funcs tegra_hdmi_encoder_funcs = { | |||
819 | .destroy = tegra_output_encoder_destroy, | 813 | .destroy = tegra_output_encoder_destroy, |
820 | }; | 814 | }; |
821 | 815 | ||
822 | static void tegra_hdmi_encoder_dpms(struct drm_encoder *encoder, int mode) | 816 | static void tegra_hdmi_encoder_disable(struct drm_encoder *encoder) |
823 | { | 817 | { |
824 | } | 818 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
819 | u32 value; | ||
825 | 820 | ||
826 | static void tegra_hdmi_encoder_prepare(struct drm_encoder *encoder) | 821 | /* |
827 | { | 822 | * The following accesses registers of the display controller, so make |
828 | } | 823 | * sure it's only executed when the output is attached to one. |
824 | */ | ||
825 | if (dc) { | ||
826 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
827 | value &= ~HDMI_ENABLE; | ||
828 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
829 | 829 | ||
830 | static void tegra_hdmi_encoder_commit(struct drm_encoder *encoder) | 830 | tegra_dc_commit(dc); |
831 | { | 831 | } |
832 | } | 832 | } |
833 | 833 | ||
834 | static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder, | 834 | static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder) |
835 | struct drm_display_mode *mode, | ||
836 | struct drm_display_mode *adjusted) | ||
837 | { | 835 | { |
836 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; | ||
838 | unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey; | 837 | unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey; |
839 | struct tegra_output *output = encoder_to_output(encoder); | 838 | struct tegra_output *output = encoder_to_output(encoder); |
840 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | 839 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
@@ -873,13 +872,13 @@ static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder, | |||
873 | 872 | ||
874 | tegra_dc_writel(dc, VSYNC_H_POSITION(1), | 873 | tegra_dc_writel(dc, VSYNC_H_POSITION(1), |
875 | DC_DISP_DISP_TIMING_OPTIONS); | 874 | DC_DISP_DISP_TIMING_OPTIONS); |
876 | tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888, | 875 | tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE_888, |
877 | DC_DISP_DISP_COLOR_CONTROL); | 876 | DC_DISP_DISP_COLOR_CONTROL); |
878 | 877 | ||
879 | /* video_preamble uses h_pulse2 */ | 878 | /* video_preamble uses h_pulse2 */ |
880 | pulse_start = 1 + h_sync_width + h_back_porch - 10; | 879 | pulse_start = 1 + h_sync_width + h_back_porch - 10; |
881 | 880 | ||
882 | tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0); | 881 | tegra_dc_writel(dc, H_PULSE2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0); |
883 | 882 | ||
884 | value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE | | 883 | value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE | |
885 | PULSE_LAST_END_A; | 884 | PULSE_LAST_END_A; |
@@ -1036,24 +1035,6 @@ static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder, | |||
1036 | /* TODO: add HDCP support */ | 1035 | /* TODO: add HDCP support */ |
1037 | } | 1036 | } |
1038 | 1037 | ||
1039 | static void tegra_hdmi_encoder_disable(struct drm_encoder *encoder) | ||
1040 | { | ||
1041 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | ||
1042 | u32 value; | ||
1043 | |||
1044 | /* | ||
1045 | * The following accesses registers of the display controller, so make | ||
1046 | * sure it's only executed when the output is attached to one. | ||
1047 | */ | ||
1048 | if (dc) { | ||
1049 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
1050 | value &= ~HDMI_ENABLE; | ||
1051 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
1052 | |||
1053 | tegra_dc_commit(dc); | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | static int | 1038 | static int |
1058 | tegra_hdmi_encoder_atomic_check(struct drm_encoder *encoder, | 1039 | tegra_hdmi_encoder_atomic_check(struct drm_encoder *encoder, |
1059 | struct drm_crtc_state *crtc_state, | 1040 | struct drm_crtc_state *crtc_state, |
@@ -1076,11 +1057,8 @@ tegra_hdmi_encoder_atomic_check(struct drm_encoder *encoder, | |||
1076 | } | 1057 | } |
1077 | 1058 | ||
1078 | static const struct drm_encoder_helper_funcs tegra_hdmi_encoder_helper_funcs = { | 1059 | static const struct drm_encoder_helper_funcs tegra_hdmi_encoder_helper_funcs = { |
1079 | .dpms = tegra_hdmi_encoder_dpms, | ||
1080 | .prepare = tegra_hdmi_encoder_prepare, | ||
1081 | .commit = tegra_hdmi_encoder_commit, | ||
1082 | .mode_set = tegra_hdmi_encoder_mode_set, | ||
1083 | .disable = tegra_hdmi_encoder_disable, | 1060 | .disable = tegra_hdmi_encoder_disable, |
1061 | .enable = tegra_hdmi_encoder_enable, | ||
1084 | .atomic_check = tegra_hdmi_encoder_atomic_check, | 1062 | .atomic_check = tegra_hdmi_encoder_atomic_check, |
1085 | }; | 1063 | }; |
1086 | 1064 | ||
@@ -1088,11 +1066,16 @@ static int tegra_hdmi_show_regs(struct seq_file *s, void *data) | |||
1088 | { | 1066 | { |
1089 | struct drm_info_node *node = s->private; | 1067 | struct drm_info_node *node = s->private; |
1090 | struct tegra_hdmi *hdmi = node->info_ent->data; | 1068 | struct tegra_hdmi *hdmi = node->info_ent->data; |
1091 | int err; | 1069 | struct drm_crtc *crtc = hdmi->output.encoder.crtc; |
1070 | struct drm_device *drm = node->minor->dev; | ||
1071 | int err = 0; | ||
1092 | 1072 | ||
1093 | err = clk_prepare_enable(hdmi->clk); | 1073 | drm_modeset_lock_all(drm); |
1094 | if (err) | 1074 | |
1095 | return err; | 1075 | if (!crtc || !crtc->state->active) { |
1076 | err = -EBUSY; | ||
1077 | goto unlock; | ||
1078 | } | ||
1096 | 1079 | ||
1097 | #define DUMP_REG(name) \ | 1080 | #define DUMP_REG(name) \ |
1098 | seq_printf(s, "%-56s %#05x %08x\n", #name, name, \ | 1081 | seq_printf(s, "%-56s %#05x %08x\n", #name, name, \ |
@@ -1259,9 +1242,9 @@ static int tegra_hdmi_show_regs(struct seq_file *s, void *data) | |||
1259 | 1242 | ||
1260 | #undef DUMP_REG | 1243 | #undef DUMP_REG |
1261 | 1244 | ||
1262 | clk_disable_unprepare(hdmi->clk); | 1245 | unlock: |
1263 | 1246 | drm_modeset_unlock_all(drm); | |
1264 | return 0; | 1247 | return err; |
1265 | } | 1248 | } |
1266 | 1249 | ||
1267 | static struct drm_info_list debugfs_files[] = { | 1250 | static struct drm_info_list debugfs_files[] = { |
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index 37db47975d48..46664b622270 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/of_gpio.h> | ||
11 | |||
12 | #include <drm/drm_atomic_helper.h> | 10 | #include <drm/drm_atomic_helper.h> |
13 | #include <drm/drm_panel.h> | 11 | #include <drm/drm_panel.h> |
14 | #include "drm.h" | 12 | #include "drm.h" |
@@ -59,10 +57,17 @@ tegra_output_connector_detect(struct drm_connector *connector, bool force) | |||
59 | enum drm_connector_status status = connector_status_unknown; | 57 | enum drm_connector_status status = connector_status_unknown; |
60 | 58 | ||
61 | if (gpio_is_valid(output->hpd_gpio)) { | 59 | if (gpio_is_valid(output->hpd_gpio)) { |
62 | if (gpio_get_value(output->hpd_gpio) == 0) | 60 | if (output->hpd_gpio_flags & OF_GPIO_ACTIVE_LOW) { |
63 | status = connector_status_disconnected; | 61 | if (gpio_get_value(output->hpd_gpio) != 0) |
64 | else | 62 | status = connector_status_disconnected; |
65 | status = connector_status_connected; | 63 | else |
64 | status = connector_status_connected; | ||
65 | } else { | ||
66 | if (gpio_get_value(output->hpd_gpio) == 0) | ||
67 | status = connector_status_disconnected; | ||
68 | else | ||
69 | status = connector_status_connected; | ||
70 | } | ||
66 | } else { | 71 | } else { |
67 | if (!output->panel) | 72 | if (!output->panel) |
68 | status = connector_status_disconnected; | 73 | status = connector_status_disconnected; |
@@ -97,7 +102,6 @@ static irqreturn_t hpd_irq(int irq, void *data) | |||
97 | int tegra_output_probe(struct tegra_output *output) | 102 | int tegra_output_probe(struct tegra_output *output) |
98 | { | 103 | { |
99 | struct device_node *ddc, *panel; | 104 | struct device_node *ddc, *panel; |
100 | enum of_gpio_flags flags; | ||
101 | int err, size; | 105 | int err, size; |
102 | 106 | ||
103 | if (!output->of_node) | 107 | if (!output->of_node) |
@@ -128,7 +132,7 @@ int tegra_output_probe(struct tegra_output *output) | |||
128 | 132 | ||
129 | output->hpd_gpio = of_get_named_gpio_flags(output->of_node, | 133 | output->hpd_gpio = of_get_named_gpio_flags(output->of_node, |
130 | "nvidia,hpd-gpio", 0, | 134 | "nvidia,hpd-gpio", 0, |
131 | &flags); | 135 | &output->hpd_gpio_flags); |
132 | if (gpio_is_valid(output->hpd_gpio)) { | 136 | if (gpio_is_valid(output->hpd_gpio)) { |
133 | unsigned long flags; | 137 | unsigned long flags; |
134 | 138 | ||
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 9a99d213e1b1..bc9735b4ad60 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c | |||
@@ -18,7 +18,6 @@ | |||
18 | struct tegra_rgb { | 18 | struct tegra_rgb { |
19 | struct tegra_output output; | 19 | struct tegra_output output; |
20 | struct tegra_dc *dc; | 20 | struct tegra_dc *dc; |
21 | bool enabled; | ||
22 | 21 | ||
23 | struct clk *clk_parent; | 22 | struct clk *clk_parent; |
24 | struct clk *clk; | 23 | struct clk *clk; |
@@ -88,14 +87,8 @@ static void tegra_dc_write_regs(struct tegra_dc *dc, | |||
88 | tegra_dc_writel(dc, table[i].value, table[i].offset); | 87 | tegra_dc_writel(dc, table[i].value, table[i].offset); |
89 | } | 88 | } |
90 | 89 | ||
91 | static int tegra_rgb_connector_dpms(struct drm_connector *connector, | ||
92 | int mode) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static const struct drm_connector_funcs tegra_rgb_connector_funcs = { | 90 | static const struct drm_connector_funcs tegra_rgb_connector_funcs = { |
98 | .dpms = tegra_rgb_connector_dpms, | 91 | .dpms = drm_atomic_helper_connector_dpms, |
99 | .reset = drm_atomic_helper_connector_reset, | 92 | .reset = drm_atomic_helper_connector_reset, |
100 | .detect = tegra_output_connector_detect, | 93 | .detect = tegra_output_connector_detect, |
101 | .fill_modes = drm_helper_probe_single_connector_modes, | 94 | .fill_modes = drm_helper_probe_single_connector_modes, |
@@ -126,21 +119,22 @@ static const struct drm_encoder_funcs tegra_rgb_encoder_funcs = { | |||
126 | .destroy = tegra_output_encoder_destroy, | 119 | .destroy = tegra_output_encoder_destroy, |
127 | }; | 120 | }; |
128 | 121 | ||
129 | static void tegra_rgb_encoder_dpms(struct drm_encoder *encoder, int mode) | 122 | static void tegra_rgb_encoder_disable(struct drm_encoder *encoder) |
130 | { | 123 | { |
131 | } | 124 | struct tegra_output *output = encoder_to_output(encoder); |
125 | struct tegra_rgb *rgb = to_rgb(output); | ||
132 | 126 | ||
133 | static void tegra_rgb_encoder_prepare(struct drm_encoder *encoder) | 127 | if (output->panel) |
134 | { | 128 | drm_panel_disable(output->panel); |
135 | } | ||
136 | 129 | ||
137 | static void tegra_rgb_encoder_commit(struct drm_encoder *encoder) | 130 | tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable)); |
138 | { | 131 | tegra_dc_commit(rgb->dc); |
132 | |||
133 | if (output->panel) | ||
134 | drm_panel_unprepare(output->panel); | ||
139 | } | 135 | } |
140 | 136 | ||
141 | static void tegra_rgb_encoder_mode_set(struct drm_encoder *encoder, | 137 | static void tegra_rgb_encoder_enable(struct drm_encoder *encoder) |
142 | struct drm_display_mode *mode, | ||
143 | struct drm_display_mode *adjusted) | ||
144 | { | 138 | { |
145 | struct tegra_output *output = encoder_to_output(encoder); | 139 | struct tegra_output *output = encoder_to_output(encoder); |
146 | struct tegra_rgb *rgb = to_rgb(output); | 140 | struct tegra_rgb *rgb = to_rgb(output); |
@@ -175,21 +169,6 @@ static void tegra_rgb_encoder_mode_set(struct drm_encoder *encoder, | |||
175 | drm_panel_enable(output->panel); | 169 | drm_panel_enable(output->panel); |
176 | } | 170 | } |
177 | 171 | ||
178 | static void tegra_rgb_encoder_disable(struct drm_encoder *encoder) | ||
179 | { | ||
180 | struct tegra_output *output = encoder_to_output(encoder); | ||
181 | struct tegra_rgb *rgb = to_rgb(output); | ||
182 | |||
183 | if (output->panel) | ||
184 | drm_panel_disable(output->panel); | ||
185 | |||
186 | tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable)); | ||
187 | tegra_dc_commit(rgb->dc); | ||
188 | |||
189 | if (output->panel) | ||
190 | drm_panel_unprepare(output->panel); | ||
191 | } | ||
192 | |||
193 | static int | 172 | static int |
194 | tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder, | 173 | tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder, |
195 | struct drm_crtc_state *crtc_state, | 174 | struct drm_crtc_state *crtc_state, |
@@ -232,11 +211,8 @@ tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder, | |||
232 | } | 211 | } |
233 | 212 | ||
234 | static const struct drm_encoder_helper_funcs tegra_rgb_encoder_helper_funcs = { | 213 | static const struct drm_encoder_helper_funcs tegra_rgb_encoder_helper_funcs = { |
235 | .dpms = tegra_rgb_encoder_dpms, | ||
236 | .prepare = tegra_rgb_encoder_prepare, | ||
237 | .commit = tegra_rgb_encoder_commit, | ||
238 | .mode_set = tegra_rgb_encoder_mode_set, | ||
239 | .disable = tegra_rgb_encoder_disable, | 214 | .disable = tegra_rgb_encoder_disable, |
215 | .enable = tegra_rgb_encoder_enable, | ||
240 | .atomic_check = tegra_rgb_encoder_atomic_check, | 216 | .atomic_check = tegra_rgb_encoder_atomic_check, |
241 | }; | 217 | }; |
242 | 218 | ||
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index ee8ad0d4a0f2..da1715ebdd71 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c | |||
@@ -10,7 +10,9 @@ | |||
10 | #include <linux/debugfs.h> | 10 | #include <linux/debugfs.h> |
11 | #include <linux/gpio.h> | 11 | #include <linux/gpio.h> |
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/of_device.h> | ||
13 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/regulator/consumer.h> | ||
14 | #include <linux/reset.h> | 16 | #include <linux/reset.h> |
15 | 17 | ||
16 | #include <soc/tegra/pmc.h> | 18 | #include <soc/tegra/pmc.h> |
@@ -23,11 +25,146 @@ | |||
23 | #include "drm.h" | 25 | #include "drm.h" |
24 | #include "sor.h" | 26 | #include "sor.h" |
25 | 27 | ||
28 | #define SOR_REKEY 0x38 | ||
29 | |||
30 | struct tegra_sor_hdmi_settings { | ||
31 | unsigned long frequency; | ||
32 | |||
33 | u8 vcocap; | ||
34 | u8 ichpmp; | ||
35 | u8 loadadj; | ||
36 | u8 termadj; | ||
37 | u8 tx_pu; | ||
38 | u8 bg_vref; | ||
39 | |||
40 | u8 drive_current[4]; | ||
41 | u8 preemphasis[4]; | ||
42 | }; | ||
43 | |||
44 | #if 1 | ||
45 | static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = { | ||
46 | { | ||
47 | .frequency = 54000000, | ||
48 | .vcocap = 0x0, | ||
49 | .ichpmp = 0x1, | ||
50 | .loadadj = 0x3, | ||
51 | .termadj = 0x9, | ||
52 | .tx_pu = 0x10, | ||
53 | .bg_vref = 0x8, | ||
54 | .drive_current = { 0x33, 0x3a, 0x3a, 0x3a }, | ||
55 | .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, | ||
56 | }, { | ||
57 | .frequency = 75000000, | ||
58 | .vcocap = 0x3, | ||
59 | .ichpmp = 0x1, | ||
60 | .loadadj = 0x3, | ||
61 | .termadj = 0x9, | ||
62 | .tx_pu = 0x40, | ||
63 | .bg_vref = 0x8, | ||
64 | .drive_current = { 0x33, 0x3a, 0x3a, 0x3a }, | ||
65 | .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, | ||
66 | }, { | ||
67 | .frequency = 150000000, | ||
68 | .vcocap = 0x3, | ||
69 | .ichpmp = 0x1, | ||
70 | .loadadj = 0x3, | ||
71 | .termadj = 0x9, | ||
72 | .tx_pu = 0x66, | ||
73 | .bg_vref = 0x8, | ||
74 | .drive_current = { 0x33, 0x3a, 0x3a, 0x3a }, | ||
75 | .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, | ||
76 | }, { | ||
77 | .frequency = 300000000, | ||
78 | .vcocap = 0x3, | ||
79 | .ichpmp = 0x1, | ||
80 | .loadadj = 0x3, | ||
81 | .termadj = 0x9, | ||
82 | .tx_pu = 0x66, | ||
83 | .bg_vref = 0xa, | ||
84 | .drive_current = { 0x33, 0x3f, 0x3f, 0x3f }, | ||
85 | .preemphasis = { 0x00, 0x17, 0x17, 0x17 }, | ||
86 | }, { | ||
87 | .frequency = 600000000, | ||
88 | .vcocap = 0x3, | ||
89 | .ichpmp = 0x1, | ||
90 | .loadadj = 0x3, | ||
91 | .termadj = 0x9, | ||
92 | .tx_pu = 0x66, | ||
93 | .bg_vref = 0x8, | ||
94 | .drive_current = { 0x33, 0x3f, 0x3f, 0x3f }, | ||
95 | .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, | ||
96 | }, | ||
97 | }; | ||
98 | #else | ||
99 | static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = { | ||
100 | { | ||
101 | .frequency = 75000000, | ||
102 | .vcocap = 0x3, | ||
103 | .ichpmp = 0x1, | ||
104 | .loadadj = 0x3, | ||
105 | .termadj = 0x9, | ||
106 | .tx_pu = 0x40, | ||
107 | .bg_vref = 0x8, | ||
108 | .drive_current = { 0x29, 0x29, 0x29, 0x29 }, | ||
109 | .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, | ||
110 | }, { | ||
111 | .frequency = 150000000, | ||
112 | .vcocap = 0x3, | ||
113 | .ichpmp = 0x1, | ||
114 | .loadadj = 0x3, | ||
115 | .termadj = 0x9, | ||
116 | .tx_pu = 0x66, | ||
117 | .bg_vref = 0x8, | ||
118 | .drive_current = { 0x30, 0x37, 0x37, 0x37 }, | ||
119 | .preemphasis = { 0x01, 0x02, 0x02, 0x02 }, | ||
120 | }, { | ||
121 | .frequency = 300000000, | ||
122 | .vcocap = 0x3, | ||
123 | .ichpmp = 0x6, | ||
124 | .loadadj = 0x3, | ||
125 | .termadj = 0x9, | ||
126 | .tx_pu = 0x66, | ||
127 | .bg_vref = 0xf, | ||
128 | .drive_current = { 0x30, 0x37, 0x37, 0x37 }, | ||
129 | .preemphasis = { 0x10, 0x3e, 0x3e, 0x3e }, | ||
130 | }, { | ||
131 | .frequency = 600000000, | ||
132 | .vcocap = 0x3, | ||
133 | .ichpmp = 0xa, | ||
134 | .loadadj = 0x3, | ||
135 | .termadj = 0xb, | ||
136 | .tx_pu = 0x66, | ||
137 | .bg_vref = 0xe, | ||
138 | .drive_current = { 0x35, 0x3e, 0x3e, 0x3e }, | ||
139 | .preemphasis = { 0x02, 0x3f, 0x3f, 0x3f }, | ||
140 | }, | ||
141 | }; | ||
142 | #endif | ||
143 | |||
144 | struct tegra_sor_soc { | ||
145 | bool supports_edp; | ||
146 | bool supports_lvds; | ||
147 | bool supports_hdmi; | ||
148 | bool supports_dp; | ||
149 | |||
150 | const struct tegra_sor_hdmi_settings *settings; | ||
151 | unsigned int num_settings; | ||
152 | }; | ||
153 | |||
154 | struct tegra_sor; | ||
155 | |||
156 | struct tegra_sor_ops { | ||
157 | const char *name; | ||
158 | int (*probe)(struct tegra_sor *sor); | ||
159 | int (*remove)(struct tegra_sor *sor); | ||
160 | }; | ||
161 | |||
26 | struct tegra_sor { | 162 | struct tegra_sor { |
27 | struct host1x_client client; | 163 | struct host1x_client client; |
28 | struct tegra_output output; | 164 | struct tegra_output output; |
29 | struct device *dev; | 165 | struct device *dev; |
30 | 166 | ||
167 | const struct tegra_sor_soc *soc; | ||
31 | void __iomem *regs; | 168 | void __iomem *regs; |
32 | 169 | ||
33 | struct reset_control *rst; | 170 | struct reset_control *rst; |
@@ -38,12 +175,19 @@ struct tegra_sor { | |||
38 | 175 | ||
39 | struct tegra_dpaux *dpaux; | 176 | struct tegra_dpaux *dpaux; |
40 | 177 | ||
41 | struct mutex lock; | ||
42 | bool enabled; | ||
43 | |||
44 | struct drm_info_list *debugfs_files; | 178 | struct drm_info_list *debugfs_files; |
45 | struct drm_minor *minor; | 179 | struct drm_minor *minor; |
46 | struct dentry *debugfs; | 180 | struct dentry *debugfs; |
181 | |||
182 | const struct tegra_sor_ops *ops; | ||
183 | |||
184 | /* for HDMI 2.0 */ | ||
185 | struct tegra_sor_hdmi_settings *settings; | ||
186 | unsigned int num_settings; | ||
187 | |||
188 | struct regulator *avdd_io_supply; | ||
189 | struct regulator *vdd_pll_supply; | ||
190 | struct regulator *hdmi_supply; | ||
47 | }; | 191 | }; |
48 | 192 | ||
49 | struct tegra_sor_config { | 193 | struct tegra_sor_config { |
@@ -94,40 +238,40 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor, | |||
94 | SOR_LANE_DRIVE_CURRENT_LANE2(0x40) | | 238 | SOR_LANE_DRIVE_CURRENT_LANE2(0x40) | |
95 | SOR_LANE_DRIVE_CURRENT_LANE1(0x40) | | 239 | SOR_LANE_DRIVE_CURRENT_LANE1(0x40) | |
96 | SOR_LANE_DRIVE_CURRENT_LANE0(0x40); | 240 | SOR_LANE_DRIVE_CURRENT_LANE0(0x40); |
97 | tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT_0); | 241 | tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0); |
98 | 242 | ||
99 | value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) | | 243 | value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) | |
100 | SOR_LANE_PREEMPHASIS_LANE2(0x0f) | | 244 | SOR_LANE_PREEMPHASIS_LANE2(0x0f) | |
101 | SOR_LANE_PREEMPHASIS_LANE1(0x0f) | | 245 | SOR_LANE_PREEMPHASIS_LANE1(0x0f) | |
102 | SOR_LANE_PREEMPHASIS_LANE0(0x0f); | 246 | SOR_LANE_PREEMPHASIS_LANE0(0x0f); |
103 | tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS_0); | 247 | tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0); |
104 | 248 | ||
105 | value = SOR_LANE_POST_CURSOR_LANE3(0x00) | | 249 | value = SOR_LANE_POSTCURSOR_LANE3(0x00) | |
106 | SOR_LANE_POST_CURSOR_LANE2(0x00) | | 250 | SOR_LANE_POSTCURSOR_LANE2(0x00) | |
107 | SOR_LANE_POST_CURSOR_LANE1(0x00) | | 251 | SOR_LANE_POSTCURSOR_LANE1(0x00) | |
108 | SOR_LANE_POST_CURSOR_LANE0(0x00); | 252 | SOR_LANE_POSTCURSOR_LANE0(0x00); |
109 | tegra_sor_writel(sor, value, SOR_LANE_POST_CURSOR_0); | 253 | tegra_sor_writel(sor, value, SOR_LANE_POSTCURSOR0); |
110 | 254 | ||
111 | /* disable LVDS mode */ | 255 | /* disable LVDS mode */ |
112 | tegra_sor_writel(sor, 0, SOR_LVDS); | 256 | tegra_sor_writel(sor, 0, SOR_LVDS); |
113 | 257 | ||
114 | value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); | 258 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); |
115 | value |= SOR_DP_PADCTL_TX_PU_ENABLE; | 259 | value |= SOR_DP_PADCTL_TX_PU_ENABLE; |
116 | value &= ~SOR_DP_PADCTL_TX_PU_MASK; | 260 | value &= ~SOR_DP_PADCTL_TX_PU_MASK; |
117 | value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */ | 261 | value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */ |
118 | tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); | 262 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); |
119 | 263 | ||
120 | value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); | 264 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); |
121 | value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | | 265 | value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | |
122 | SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0; | 266 | SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0; |
123 | tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); | 267 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); |
124 | 268 | ||
125 | usleep_range(10, 100); | 269 | usleep_range(10, 100); |
126 | 270 | ||
127 | value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); | 271 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); |
128 | value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | | 272 | value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | |
129 | SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0); | 273 | SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0); |
130 | tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); | 274 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); |
131 | 275 | ||
132 | err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B); | 276 | err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B); |
133 | if (err < 0) | 277 | if (err < 0) |
@@ -148,11 +292,11 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor, | |||
148 | if (err < 0) | 292 | if (err < 0) |
149 | return err; | 293 | return err; |
150 | 294 | ||
151 | value = tegra_sor_readl(sor, SOR_DP_SPARE_0); | 295 | value = tegra_sor_readl(sor, SOR_DP_SPARE0); |
152 | value |= SOR_DP_SPARE_SEQ_ENABLE; | 296 | value |= SOR_DP_SPARE_SEQ_ENABLE; |
153 | value &= ~SOR_DP_SPARE_PANEL_INTERNAL; | 297 | value &= ~SOR_DP_SPARE_PANEL_INTERNAL; |
154 | value |= SOR_DP_SPARE_MACRO_SOR_CLK; | 298 | value |= SOR_DP_SPARE_MACRO_SOR_CLK; |
155 | tegra_sor_writel(sor, value, SOR_DP_SPARE_0); | 299 | tegra_sor_writel(sor, value, SOR_DP_SPARE0); |
156 | 300 | ||
157 | for (i = 0, value = 0; i < link->num_lanes; i++) { | 301 | for (i = 0, value = 0; i < link->num_lanes; i++) { |
158 | unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | | 302 | unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | |
@@ -187,18 +331,59 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor, | |||
187 | return 0; | 331 | return 0; |
188 | } | 332 | } |
189 | 333 | ||
334 | static void tegra_sor_dp_term_calibrate(struct tegra_sor *sor) | ||
335 | { | ||
336 | u32 mask = 0x08, adj = 0, value; | ||
337 | |||
338 | /* enable pad calibration logic */ | ||
339 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); | ||
340 | value &= ~SOR_DP_PADCTL_PAD_CAL_PD; | ||
341 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); | ||
342 | |||
343 | value = tegra_sor_readl(sor, SOR_PLL1); | ||
344 | value |= SOR_PLL1_TMDS_TERM; | ||
345 | tegra_sor_writel(sor, value, SOR_PLL1); | ||
346 | |||
347 | while (mask) { | ||
348 | adj |= mask; | ||
349 | |||
350 | value = tegra_sor_readl(sor, SOR_PLL1); | ||
351 | value &= ~SOR_PLL1_TMDS_TERMADJ_MASK; | ||
352 | value |= SOR_PLL1_TMDS_TERMADJ(adj); | ||
353 | tegra_sor_writel(sor, value, SOR_PLL1); | ||
354 | |||
355 | usleep_range(100, 200); | ||
356 | |||
357 | value = tegra_sor_readl(sor, SOR_PLL1); | ||
358 | if (value & SOR_PLL1_TERM_COMPOUT) | ||
359 | adj &= ~mask; | ||
360 | |||
361 | mask >>= 1; | ||
362 | } | ||
363 | |||
364 | value = tegra_sor_readl(sor, SOR_PLL1); | ||
365 | value &= ~SOR_PLL1_TMDS_TERMADJ_MASK; | ||
366 | value |= SOR_PLL1_TMDS_TERMADJ(adj); | ||
367 | tegra_sor_writel(sor, value, SOR_PLL1); | ||
368 | |||
369 | /* disable pad calibration logic */ | ||
370 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); | ||
371 | value |= SOR_DP_PADCTL_PAD_CAL_PD; | ||
372 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); | ||
373 | } | ||
374 | |||
190 | static void tegra_sor_super_update(struct tegra_sor *sor) | 375 | static void tegra_sor_super_update(struct tegra_sor *sor) |
191 | { | 376 | { |
192 | tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0); | 377 | tegra_sor_writel(sor, 0, SOR_SUPER_STATE0); |
193 | tegra_sor_writel(sor, 1, SOR_SUPER_STATE_0); | 378 | tegra_sor_writel(sor, 1, SOR_SUPER_STATE0); |
194 | tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0); | 379 | tegra_sor_writel(sor, 0, SOR_SUPER_STATE0); |
195 | } | 380 | } |
196 | 381 | ||
197 | static void tegra_sor_update(struct tegra_sor *sor) | 382 | static void tegra_sor_update(struct tegra_sor *sor) |
198 | { | 383 | { |
199 | tegra_sor_writel(sor, 0, SOR_STATE_0); | 384 | tegra_sor_writel(sor, 0, SOR_STATE0); |
200 | tegra_sor_writel(sor, 1, SOR_STATE_0); | 385 | tegra_sor_writel(sor, 1, SOR_STATE0); |
201 | tegra_sor_writel(sor, 0, SOR_STATE_0); | 386 | tegra_sor_writel(sor, 0, SOR_STATE0); |
202 | } | 387 | } |
203 | 388 | ||
204 | static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout) | 389 | static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout) |
@@ -235,16 +420,16 @@ static int tegra_sor_attach(struct tegra_sor *sor) | |||
235 | unsigned long value, timeout; | 420 | unsigned long value, timeout; |
236 | 421 | ||
237 | /* wake up in normal mode */ | 422 | /* wake up in normal mode */ |
238 | value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); | 423 | value = tegra_sor_readl(sor, SOR_SUPER_STATE1); |
239 | value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE; | 424 | value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE; |
240 | value |= SOR_SUPER_STATE_MODE_NORMAL; | 425 | value |= SOR_SUPER_STATE_MODE_NORMAL; |
241 | tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); | 426 | tegra_sor_writel(sor, value, SOR_SUPER_STATE1); |
242 | tegra_sor_super_update(sor); | 427 | tegra_sor_super_update(sor); |
243 | 428 | ||
244 | /* attach */ | 429 | /* attach */ |
245 | value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); | 430 | value = tegra_sor_readl(sor, SOR_SUPER_STATE1); |
246 | value |= SOR_SUPER_STATE_ATTACHED; | 431 | value |= SOR_SUPER_STATE_ATTACHED; |
247 | tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); | 432 | tegra_sor_writel(sor, value, SOR_SUPER_STATE1); |
248 | tegra_sor_super_update(sor); | 433 | tegra_sor_super_update(sor); |
249 | 434 | ||
250 | timeout = jiffies + msecs_to_jiffies(250); | 435 | timeout = jiffies + msecs_to_jiffies(250); |
@@ -385,7 +570,7 @@ static int tegra_sor_compute_params(struct tegra_sor *sor, | |||
385 | } | 570 | } |
386 | 571 | ||
387 | static int tegra_sor_calc_config(struct tegra_sor *sor, | 572 | static int tegra_sor_calc_config(struct tegra_sor *sor, |
388 | struct drm_display_mode *mode, | 573 | const struct drm_display_mode *mode, |
389 | struct tegra_sor_config *config, | 574 | struct tegra_sor_config *config, |
390 | struct drm_dp_link *link) | 575 | struct drm_dp_link *link) |
391 | { | 576 | { |
@@ -481,9 +666,9 @@ static int tegra_sor_detach(struct tegra_sor *sor) | |||
481 | unsigned long value, timeout; | 666 | unsigned long value, timeout; |
482 | 667 | ||
483 | /* switch to safe mode */ | 668 | /* switch to safe mode */ |
484 | value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); | 669 | value = tegra_sor_readl(sor, SOR_SUPER_STATE1); |
485 | value &= ~SOR_SUPER_STATE_MODE_NORMAL; | 670 | value &= ~SOR_SUPER_STATE_MODE_NORMAL; |
486 | tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); | 671 | tegra_sor_writel(sor, value, SOR_SUPER_STATE1); |
487 | tegra_sor_super_update(sor); | 672 | tegra_sor_super_update(sor); |
488 | 673 | ||
489 | timeout = jiffies + msecs_to_jiffies(250); | 674 | timeout = jiffies + msecs_to_jiffies(250); |
@@ -498,15 +683,15 @@ static int tegra_sor_detach(struct tegra_sor *sor) | |||
498 | return -ETIMEDOUT; | 683 | return -ETIMEDOUT; |
499 | 684 | ||
500 | /* go to sleep */ | 685 | /* go to sleep */ |
501 | value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); | 686 | value = tegra_sor_readl(sor, SOR_SUPER_STATE1); |
502 | value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK; | 687 | value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK; |
503 | tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); | 688 | tegra_sor_writel(sor, value, SOR_SUPER_STATE1); |
504 | tegra_sor_super_update(sor); | 689 | tegra_sor_super_update(sor); |
505 | 690 | ||
506 | /* detach */ | 691 | /* detach */ |
507 | value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); | 692 | value = tegra_sor_readl(sor, SOR_SUPER_STATE1); |
508 | value &= ~SOR_SUPER_STATE_ATTACHED; | 693 | value &= ~SOR_SUPER_STATE_ATTACHED; |
509 | tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); | 694 | tegra_sor_writel(sor, value, SOR_SUPER_STATE1); |
510 | tegra_sor_super_update(sor); | 695 | tegra_sor_super_update(sor); |
511 | 696 | ||
512 | timeout = jiffies + msecs_to_jiffies(250); | 697 | timeout = jiffies + msecs_to_jiffies(250); |
@@ -552,10 +737,10 @@ static int tegra_sor_power_down(struct tegra_sor *sor) | |||
552 | if (err < 0) | 737 | if (err < 0) |
553 | dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); | 738 | dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); |
554 | 739 | ||
555 | value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); | 740 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); |
556 | value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | | 741 | value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | |
557 | SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2); | 742 | SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2); |
558 | tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); | 743 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); |
559 | 744 | ||
560 | /* stop lane sequencer */ | 745 | /* stop lane sequencer */ |
561 | value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP | | 746 | value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP | |
@@ -575,39 +760,26 @@ static int tegra_sor_power_down(struct tegra_sor *sor) | |||
575 | if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0) | 760 | if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0) |
576 | return -ETIMEDOUT; | 761 | return -ETIMEDOUT; |
577 | 762 | ||
578 | value = tegra_sor_readl(sor, SOR_PLL_2); | 763 | value = tegra_sor_readl(sor, SOR_PLL2); |
579 | value |= SOR_PLL_2_PORT_POWERDOWN; | 764 | value |= SOR_PLL2_PORT_POWERDOWN; |
580 | tegra_sor_writel(sor, value, SOR_PLL_2); | 765 | tegra_sor_writel(sor, value, SOR_PLL2); |
581 | 766 | ||
582 | usleep_range(20, 100); | 767 | usleep_range(20, 100); |
583 | 768 | ||
584 | value = tegra_sor_readl(sor, SOR_PLL_0); | 769 | value = tegra_sor_readl(sor, SOR_PLL0); |
585 | value |= SOR_PLL_0_POWER_OFF; | 770 | value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR; |
586 | value |= SOR_PLL_0_VCOPD; | 771 | tegra_sor_writel(sor, value, SOR_PLL0); |
587 | tegra_sor_writel(sor, value, SOR_PLL_0); | ||
588 | 772 | ||
589 | value = tegra_sor_readl(sor, SOR_PLL_2); | 773 | value = tegra_sor_readl(sor, SOR_PLL2); |
590 | value |= SOR_PLL_2_SEQ_PLLCAPPD; | 774 | value |= SOR_PLL2_SEQ_PLLCAPPD; |
591 | value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE; | 775 | value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE; |
592 | tegra_sor_writel(sor, value, SOR_PLL_2); | 776 | tegra_sor_writel(sor, value, SOR_PLL2); |
593 | 777 | ||
594 | usleep_range(20, 100); | 778 | usleep_range(20, 100); |
595 | 779 | ||
596 | return 0; | 780 | return 0; |
597 | } | 781 | } |
598 | 782 | ||
599 | static int tegra_sor_crc_open(struct inode *inode, struct file *file) | ||
600 | { | ||
601 | file->private_data = inode->i_private; | ||
602 | |||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | static int tegra_sor_crc_release(struct inode *inode, struct file *file) | ||
607 | { | ||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static int tegra_sor_crc_wait(struct tegra_sor *sor, unsigned long timeout) | 783 | static int tegra_sor_crc_wait(struct tegra_sor *sor, unsigned long timeout) |
612 | { | 784 | { |
613 | u32 value; | 785 | u32 value; |
@@ -615,8 +787,8 @@ static int tegra_sor_crc_wait(struct tegra_sor *sor, unsigned long timeout) | |||
615 | timeout = jiffies + msecs_to_jiffies(timeout); | 787 | timeout = jiffies + msecs_to_jiffies(timeout); |
616 | 788 | ||
617 | while (time_before(jiffies, timeout)) { | 789 | while (time_before(jiffies, timeout)) { |
618 | value = tegra_sor_readl(sor, SOR_CRC_A); | 790 | value = tegra_sor_readl(sor, SOR_CRCA); |
619 | if (value & SOR_CRC_A_VALID) | 791 | if (value & SOR_CRCA_VALID) |
620 | return 0; | 792 | return 0; |
621 | 793 | ||
622 | usleep_range(100, 200); | 794 | usleep_range(100, 200); |
@@ -625,24 +797,25 @@ static int tegra_sor_crc_wait(struct tegra_sor *sor, unsigned long timeout) | |||
625 | return -ETIMEDOUT; | 797 | return -ETIMEDOUT; |
626 | } | 798 | } |
627 | 799 | ||
628 | static ssize_t tegra_sor_crc_read(struct file *file, char __user *buffer, | 800 | static int tegra_sor_show_crc(struct seq_file *s, void *data) |
629 | size_t size, loff_t *ppos) | ||
630 | { | 801 | { |
631 | struct tegra_sor *sor = file->private_data; | 802 | struct drm_info_node *node = s->private; |
632 | ssize_t num, err; | 803 | struct tegra_sor *sor = node->info_ent->data; |
633 | char buf[10]; | 804 | struct drm_crtc *crtc = sor->output.encoder.crtc; |
805 | struct drm_device *drm = node->minor->dev; | ||
806 | int err = 0; | ||
634 | u32 value; | 807 | u32 value; |
635 | 808 | ||
636 | mutex_lock(&sor->lock); | 809 | drm_modeset_lock_all(drm); |
637 | 810 | ||
638 | if (!sor->enabled) { | 811 | if (!crtc || !crtc->state->active) { |
639 | err = -EAGAIN; | 812 | err = -EBUSY; |
640 | goto unlock; | 813 | goto unlock; |
641 | } | 814 | } |
642 | 815 | ||
643 | value = tegra_sor_readl(sor, SOR_STATE_1); | 816 | value = tegra_sor_readl(sor, SOR_STATE1); |
644 | value &= ~SOR_STATE_ASY_CRC_MODE_MASK; | 817 | value &= ~SOR_STATE_ASY_CRC_MODE_MASK; |
645 | tegra_sor_writel(sor, value, SOR_STATE_1); | 818 | tegra_sor_writel(sor, value, SOR_STATE1); |
646 | 819 | ||
647 | value = tegra_sor_readl(sor, SOR_CRC_CNTRL); | 820 | value = tegra_sor_readl(sor, SOR_CRC_CNTRL); |
648 | value |= SOR_CRC_CNTRL_ENABLE; | 821 | value |= SOR_CRC_CNTRL_ENABLE; |
@@ -656,65 +829,66 @@ static ssize_t tegra_sor_crc_read(struct file *file, char __user *buffer, | |||
656 | if (err < 0) | 829 | if (err < 0) |
657 | goto unlock; | 830 | goto unlock; |
658 | 831 | ||
659 | tegra_sor_writel(sor, SOR_CRC_A_RESET, SOR_CRC_A); | 832 | tegra_sor_writel(sor, SOR_CRCA_RESET, SOR_CRCA); |
660 | value = tegra_sor_readl(sor, SOR_CRC_B); | 833 | value = tegra_sor_readl(sor, SOR_CRCB); |
661 | 834 | ||
662 | num = scnprintf(buf, sizeof(buf), "%08x\n", value); | 835 | seq_printf(s, "%08x\n", value); |
663 | |||
664 | err = simple_read_from_buffer(buffer, size, ppos, buf, num); | ||
665 | 836 | ||
666 | unlock: | 837 | unlock: |
667 | mutex_unlock(&sor->lock); | 838 | drm_modeset_unlock_all(drm); |
668 | return err; | 839 | return err; |
669 | } | 840 | } |
670 | 841 | ||
671 | static const struct file_operations tegra_sor_crc_fops = { | ||
672 | .owner = THIS_MODULE, | ||
673 | .open = tegra_sor_crc_open, | ||
674 | .read = tegra_sor_crc_read, | ||
675 | .release = tegra_sor_crc_release, | ||
676 | }; | ||
677 | |||
678 | static int tegra_sor_show_regs(struct seq_file *s, void *data) | 842 | static int tegra_sor_show_regs(struct seq_file *s, void *data) |
679 | { | 843 | { |
680 | struct drm_info_node *node = s->private; | 844 | struct drm_info_node *node = s->private; |
681 | struct tegra_sor *sor = node->info_ent->data; | 845 | struct tegra_sor *sor = node->info_ent->data; |
846 | struct drm_crtc *crtc = sor->output.encoder.crtc; | ||
847 | struct drm_device *drm = node->minor->dev; | ||
848 | int err = 0; | ||
849 | |||
850 | drm_modeset_lock_all(drm); | ||
851 | |||
852 | if (!crtc || !crtc->state->active) { | ||
853 | err = -EBUSY; | ||
854 | goto unlock; | ||
855 | } | ||
682 | 856 | ||
683 | #define DUMP_REG(name) \ | 857 | #define DUMP_REG(name) \ |
684 | seq_printf(s, "%-38s %#05x %08x\n", #name, name, \ | 858 | seq_printf(s, "%-38s %#05x %08x\n", #name, name, \ |
685 | tegra_sor_readl(sor, name)) | 859 | tegra_sor_readl(sor, name)) |
686 | 860 | ||
687 | DUMP_REG(SOR_CTXSW); | 861 | DUMP_REG(SOR_CTXSW); |
688 | DUMP_REG(SOR_SUPER_STATE_0); | 862 | DUMP_REG(SOR_SUPER_STATE0); |
689 | DUMP_REG(SOR_SUPER_STATE_1); | 863 | DUMP_REG(SOR_SUPER_STATE1); |
690 | DUMP_REG(SOR_STATE_0); | 864 | DUMP_REG(SOR_STATE0); |
691 | DUMP_REG(SOR_STATE_1); | 865 | DUMP_REG(SOR_STATE1); |
692 | DUMP_REG(SOR_HEAD_STATE_0(0)); | 866 | DUMP_REG(SOR_HEAD_STATE0(0)); |
693 | DUMP_REG(SOR_HEAD_STATE_0(1)); | 867 | DUMP_REG(SOR_HEAD_STATE0(1)); |
694 | DUMP_REG(SOR_HEAD_STATE_1(0)); | 868 | DUMP_REG(SOR_HEAD_STATE1(0)); |
695 | DUMP_REG(SOR_HEAD_STATE_1(1)); | 869 | DUMP_REG(SOR_HEAD_STATE1(1)); |
696 | DUMP_REG(SOR_HEAD_STATE_2(0)); | 870 | DUMP_REG(SOR_HEAD_STATE2(0)); |
697 | DUMP_REG(SOR_HEAD_STATE_2(1)); | 871 | DUMP_REG(SOR_HEAD_STATE2(1)); |
698 | DUMP_REG(SOR_HEAD_STATE_3(0)); | 872 | DUMP_REG(SOR_HEAD_STATE3(0)); |
699 | DUMP_REG(SOR_HEAD_STATE_3(1)); | 873 | DUMP_REG(SOR_HEAD_STATE3(1)); |
700 | DUMP_REG(SOR_HEAD_STATE_4(0)); | 874 | DUMP_REG(SOR_HEAD_STATE4(0)); |
701 | DUMP_REG(SOR_HEAD_STATE_4(1)); | 875 | DUMP_REG(SOR_HEAD_STATE4(1)); |
702 | DUMP_REG(SOR_HEAD_STATE_5(0)); | 876 | DUMP_REG(SOR_HEAD_STATE5(0)); |
703 | DUMP_REG(SOR_HEAD_STATE_5(1)); | 877 | DUMP_REG(SOR_HEAD_STATE5(1)); |
704 | DUMP_REG(SOR_CRC_CNTRL); | 878 | DUMP_REG(SOR_CRC_CNTRL); |
705 | DUMP_REG(SOR_DP_DEBUG_MVID); | 879 | DUMP_REG(SOR_DP_DEBUG_MVID); |
706 | DUMP_REG(SOR_CLK_CNTRL); | 880 | DUMP_REG(SOR_CLK_CNTRL); |
707 | DUMP_REG(SOR_CAP); | 881 | DUMP_REG(SOR_CAP); |
708 | DUMP_REG(SOR_PWR); | 882 | DUMP_REG(SOR_PWR); |
709 | DUMP_REG(SOR_TEST); | 883 | DUMP_REG(SOR_TEST); |
710 | DUMP_REG(SOR_PLL_0); | 884 | DUMP_REG(SOR_PLL0); |
711 | DUMP_REG(SOR_PLL_1); | 885 | DUMP_REG(SOR_PLL1); |
712 | DUMP_REG(SOR_PLL_2); | 886 | DUMP_REG(SOR_PLL2); |
713 | DUMP_REG(SOR_PLL_3); | 887 | DUMP_REG(SOR_PLL3); |
714 | DUMP_REG(SOR_CSTM); | 888 | DUMP_REG(SOR_CSTM); |
715 | DUMP_REG(SOR_LVDS); | 889 | DUMP_REG(SOR_LVDS); |
716 | DUMP_REG(SOR_CRC_A); | 890 | DUMP_REG(SOR_CRCA); |
717 | DUMP_REG(SOR_CRC_B); | 891 | DUMP_REG(SOR_CRCB); |
718 | DUMP_REG(SOR_BLANK); | 892 | DUMP_REG(SOR_BLANK); |
719 | DUMP_REG(SOR_SEQ_CTL); | 893 | DUMP_REG(SOR_SEQ_CTL); |
720 | DUMP_REG(SOR_LANE_SEQ_CTL); | 894 | DUMP_REG(SOR_LANE_SEQ_CTL); |
@@ -736,86 +910,89 @@ static int tegra_sor_show_regs(struct seq_file *s, void *data) | |||
736 | DUMP_REG(SOR_SEQ_INST(15)); | 910 | DUMP_REG(SOR_SEQ_INST(15)); |
737 | DUMP_REG(SOR_PWM_DIV); | 911 | DUMP_REG(SOR_PWM_DIV); |
738 | DUMP_REG(SOR_PWM_CTL); | 912 | DUMP_REG(SOR_PWM_CTL); |
739 | DUMP_REG(SOR_VCRC_A_0); | 913 | DUMP_REG(SOR_VCRC_A0); |
740 | DUMP_REG(SOR_VCRC_A_1); | 914 | DUMP_REG(SOR_VCRC_A1); |
741 | DUMP_REG(SOR_VCRC_B_0); | 915 | DUMP_REG(SOR_VCRC_B0); |
742 | DUMP_REG(SOR_VCRC_B_1); | 916 | DUMP_REG(SOR_VCRC_B1); |
743 | DUMP_REG(SOR_CCRC_A_0); | 917 | DUMP_REG(SOR_CCRC_A0); |
744 | DUMP_REG(SOR_CCRC_A_1); | 918 | DUMP_REG(SOR_CCRC_A1); |
745 | DUMP_REG(SOR_CCRC_B_0); | 919 | DUMP_REG(SOR_CCRC_B0); |
746 | DUMP_REG(SOR_CCRC_B_1); | 920 | DUMP_REG(SOR_CCRC_B1); |
747 | DUMP_REG(SOR_EDATA_A_0); | 921 | DUMP_REG(SOR_EDATA_A0); |
748 | DUMP_REG(SOR_EDATA_A_1); | 922 | DUMP_REG(SOR_EDATA_A1); |
749 | DUMP_REG(SOR_EDATA_B_0); | 923 | DUMP_REG(SOR_EDATA_B0); |
750 | DUMP_REG(SOR_EDATA_B_1); | 924 | DUMP_REG(SOR_EDATA_B1); |
751 | DUMP_REG(SOR_COUNT_A_0); | 925 | DUMP_REG(SOR_COUNT_A0); |
752 | DUMP_REG(SOR_COUNT_A_1); | 926 | DUMP_REG(SOR_COUNT_A1); |
753 | DUMP_REG(SOR_COUNT_B_0); | 927 | DUMP_REG(SOR_COUNT_B0); |
754 | DUMP_REG(SOR_COUNT_B_1); | 928 | DUMP_REG(SOR_COUNT_B1); |
755 | DUMP_REG(SOR_DEBUG_A_0); | 929 | DUMP_REG(SOR_DEBUG_A0); |
756 | DUMP_REG(SOR_DEBUG_A_1); | 930 | DUMP_REG(SOR_DEBUG_A1); |
757 | DUMP_REG(SOR_DEBUG_B_0); | 931 | DUMP_REG(SOR_DEBUG_B0); |
758 | DUMP_REG(SOR_DEBUG_B_1); | 932 | DUMP_REG(SOR_DEBUG_B1); |
759 | DUMP_REG(SOR_TRIG); | 933 | DUMP_REG(SOR_TRIG); |
760 | DUMP_REG(SOR_MSCHECK); | 934 | DUMP_REG(SOR_MSCHECK); |
761 | DUMP_REG(SOR_XBAR_CTRL); | 935 | DUMP_REG(SOR_XBAR_CTRL); |
762 | DUMP_REG(SOR_XBAR_POL); | 936 | DUMP_REG(SOR_XBAR_POL); |
763 | DUMP_REG(SOR_DP_LINKCTL_0); | 937 | DUMP_REG(SOR_DP_LINKCTL0); |
764 | DUMP_REG(SOR_DP_LINKCTL_1); | 938 | DUMP_REG(SOR_DP_LINKCTL1); |
765 | DUMP_REG(SOR_LANE_DRIVE_CURRENT_0); | 939 | DUMP_REG(SOR_LANE_DRIVE_CURRENT0); |
766 | DUMP_REG(SOR_LANE_DRIVE_CURRENT_1); | 940 | DUMP_REG(SOR_LANE_DRIVE_CURRENT1); |
767 | DUMP_REG(SOR_LANE4_DRIVE_CURRENT_0); | 941 | DUMP_REG(SOR_LANE4_DRIVE_CURRENT0); |
768 | DUMP_REG(SOR_LANE4_DRIVE_CURRENT_1); | 942 | DUMP_REG(SOR_LANE4_DRIVE_CURRENT1); |
769 | DUMP_REG(SOR_LANE_PREEMPHASIS_0); | 943 | DUMP_REG(SOR_LANE_PREEMPHASIS0); |
770 | DUMP_REG(SOR_LANE_PREEMPHASIS_1); | 944 | DUMP_REG(SOR_LANE_PREEMPHASIS1); |
771 | DUMP_REG(SOR_LANE4_PREEMPHASIS_0); | 945 | DUMP_REG(SOR_LANE4_PREEMPHASIS0); |
772 | DUMP_REG(SOR_LANE4_PREEMPHASIS_1); | 946 | DUMP_REG(SOR_LANE4_PREEMPHASIS1); |
773 | DUMP_REG(SOR_LANE_POST_CURSOR_0); | 947 | DUMP_REG(SOR_LANE_POSTCURSOR0); |
774 | DUMP_REG(SOR_LANE_POST_CURSOR_1); | 948 | DUMP_REG(SOR_LANE_POSTCURSOR1); |
775 | DUMP_REG(SOR_DP_CONFIG_0); | 949 | DUMP_REG(SOR_DP_CONFIG0); |
776 | DUMP_REG(SOR_DP_CONFIG_1); | 950 | DUMP_REG(SOR_DP_CONFIG1); |
777 | DUMP_REG(SOR_DP_MN_0); | 951 | DUMP_REG(SOR_DP_MN0); |
778 | DUMP_REG(SOR_DP_MN_1); | 952 | DUMP_REG(SOR_DP_MN1); |
779 | DUMP_REG(SOR_DP_PADCTL_0); | 953 | DUMP_REG(SOR_DP_PADCTL0); |
780 | DUMP_REG(SOR_DP_PADCTL_1); | 954 | DUMP_REG(SOR_DP_PADCTL1); |
781 | DUMP_REG(SOR_DP_DEBUG_0); | 955 | DUMP_REG(SOR_DP_DEBUG0); |
782 | DUMP_REG(SOR_DP_DEBUG_1); | 956 | DUMP_REG(SOR_DP_DEBUG1); |
783 | DUMP_REG(SOR_DP_SPARE_0); | 957 | DUMP_REG(SOR_DP_SPARE0); |
784 | DUMP_REG(SOR_DP_SPARE_1); | 958 | DUMP_REG(SOR_DP_SPARE1); |
785 | DUMP_REG(SOR_DP_AUDIO_CTRL); | 959 | DUMP_REG(SOR_DP_AUDIO_CTRL); |
786 | DUMP_REG(SOR_DP_AUDIO_HBLANK_SYMBOLS); | 960 | DUMP_REG(SOR_DP_AUDIO_HBLANK_SYMBOLS); |
787 | DUMP_REG(SOR_DP_AUDIO_VBLANK_SYMBOLS); | 961 | DUMP_REG(SOR_DP_AUDIO_VBLANK_SYMBOLS); |
788 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_HEADER); | 962 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_HEADER); |
789 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_0); | 963 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK0); |
790 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_1); | 964 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK1); |
791 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_2); | 965 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK2); |
792 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_3); | 966 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK3); |
793 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_4); | 967 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK4); |
794 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_5); | 968 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK5); |
795 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_6); | 969 | DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK6); |
796 | DUMP_REG(SOR_DP_TPG); | 970 | DUMP_REG(SOR_DP_TPG); |
797 | DUMP_REG(SOR_DP_TPG_CONFIG); | 971 | DUMP_REG(SOR_DP_TPG_CONFIG); |
798 | DUMP_REG(SOR_DP_LQ_CSTM_0); | 972 | DUMP_REG(SOR_DP_LQ_CSTM0); |
799 | DUMP_REG(SOR_DP_LQ_CSTM_1); | 973 | DUMP_REG(SOR_DP_LQ_CSTM1); |
800 | DUMP_REG(SOR_DP_LQ_CSTM_2); | 974 | DUMP_REG(SOR_DP_LQ_CSTM2); |
801 | 975 | ||
802 | #undef DUMP_REG | 976 | #undef DUMP_REG |
803 | 977 | ||
804 | return 0; | 978 | unlock: |
979 | drm_modeset_unlock_all(drm); | ||
980 | return err; | ||
805 | } | 981 | } |
806 | 982 | ||
807 | static const struct drm_info_list debugfs_files[] = { | 983 | static const struct drm_info_list debugfs_files[] = { |
984 | { "crc", tegra_sor_show_crc, 0, NULL }, | ||
808 | { "regs", tegra_sor_show_regs, 0, NULL }, | 985 | { "regs", tegra_sor_show_regs, 0, NULL }, |
809 | }; | 986 | }; |
810 | 987 | ||
811 | static int tegra_sor_debugfs_init(struct tegra_sor *sor, | 988 | static int tegra_sor_debugfs_init(struct tegra_sor *sor, |
812 | struct drm_minor *minor) | 989 | struct drm_minor *minor) |
813 | { | 990 | { |
814 | struct dentry *entry; | 991 | const char *name = sor->soc->supports_dp ? "sor1" : "sor"; |
815 | unsigned int i; | 992 | unsigned int i; |
816 | int err = 0; | 993 | int err; |
817 | 994 | ||
818 | sor->debugfs = debugfs_create_dir("sor", minor->debugfs_root); | 995 | sor->debugfs = debugfs_create_dir(name, minor->debugfs_root); |
819 | if (!sor->debugfs) | 996 | if (!sor->debugfs) |
820 | return -ENOMEM; | 997 | return -ENOMEM; |
821 | 998 | ||
@@ -835,14 +1012,9 @@ static int tegra_sor_debugfs_init(struct tegra_sor *sor, | |||
835 | if (err < 0) | 1012 | if (err < 0) |
836 | goto free; | 1013 | goto free; |
837 | 1014 | ||
838 | entry = debugfs_create_file("crc", 0644, sor->debugfs, sor, | 1015 | sor->minor = minor; |
839 | &tegra_sor_crc_fops); | ||
840 | if (!entry) { | ||
841 | err = -ENOMEM; | ||
842 | goto free; | ||
843 | } | ||
844 | 1016 | ||
845 | return err; | 1017 | return 0; |
846 | 1018 | ||
847 | free: | 1019 | free: |
848 | kfree(sor->debugfs_files); | 1020 | kfree(sor->debugfs_files); |
@@ -860,15 +1032,10 @@ static void tegra_sor_debugfs_exit(struct tegra_sor *sor) | |||
860 | sor->minor = NULL; | 1032 | sor->minor = NULL; |
861 | 1033 | ||
862 | kfree(sor->debugfs_files); | 1034 | kfree(sor->debugfs_files); |
863 | sor->debugfs = NULL; | ||
864 | |||
865 | debugfs_remove_recursive(sor->debugfs); | ||
866 | sor->debugfs_files = NULL; | 1035 | sor->debugfs_files = NULL; |
867 | } | ||
868 | 1036 | ||
869 | static int tegra_sor_connector_dpms(struct drm_connector *connector, int mode) | 1037 | debugfs_remove_recursive(sor->debugfs); |
870 | { | 1038 | sor->debugfs = NULL; |
871 | return 0; | ||
872 | } | 1039 | } |
873 | 1040 | ||
874 | static enum drm_connector_status | 1041 | static enum drm_connector_status |
@@ -880,11 +1047,11 @@ tegra_sor_connector_detect(struct drm_connector *connector, bool force) | |||
880 | if (sor->dpaux) | 1047 | if (sor->dpaux) |
881 | return tegra_dpaux_detect(sor->dpaux); | 1048 | return tegra_dpaux_detect(sor->dpaux); |
882 | 1049 | ||
883 | return connector_status_unknown; | 1050 | return tegra_output_connector_detect(connector, force); |
884 | } | 1051 | } |
885 | 1052 | ||
886 | static const struct drm_connector_funcs tegra_sor_connector_funcs = { | 1053 | static const struct drm_connector_funcs tegra_sor_connector_funcs = { |
887 | .dpms = tegra_sor_connector_dpms, | 1054 | .dpms = drm_atomic_helper_connector_dpms, |
888 | .reset = drm_atomic_helper_connector_reset, | 1055 | .reset = drm_atomic_helper_connector_reset, |
889 | .detect = tegra_sor_connector_detect, | 1056 | .detect = tegra_sor_connector_detect, |
890 | .fill_modes = drm_helper_probe_single_connector_modes, | 1057 | .fill_modes = drm_helper_probe_single_connector_modes, |
@@ -927,22 +1094,102 @@ static const struct drm_encoder_funcs tegra_sor_encoder_funcs = { | |||
927 | .destroy = tegra_output_encoder_destroy, | 1094 | .destroy = tegra_output_encoder_destroy, |
928 | }; | 1095 | }; |
929 | 1096 | ||
930 | static void tegra_sor_encoder_dpms(struct drm_encoder *encoder, int mode) | 1097 | static void tegra_sor_edp_disable(struct drm_encoder *encoder) |
931 | { | 1098 | { |
932 | } | 1099 | struct tegra_output *output = encoder_to_output(encoder); |
1100 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | ||
1101 | struct tegra_sor *sor = to_sor(output); | ||
1102 | u32 value; | ||
1103 | int err; | ||
933 | 1104 | ||
934 | static void tegra_sor_encoder_prepare(struct drm_encoder *encoder) | 1105 | if (output->panel) |
935 | { | 1106 | drm_panel_disable(output->panel); |
1107 | |||
1108 | err = tegra_sor_detach(sor); | ||
1109 | if (err < 0) | ||
1110 | dev_err(sor->dev, "failed to detach SOR: %d\n", err); | ||
1111 | |||
1112 | tegra_sor_writel(sor, 0, SOR_STATE1); | ||
1113 | tegra_sor_update(sor); | ||
1114 | |||
1115 | /* | ||
1116 | * The following accesses registers of the display controller, so make | ||
1117 | * sure it's only executed when the output is attached to one. | ||
1118 | */ | ||
1119 | if (dc) { | ||
1120 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
1121 | value &= ~SOR_ENABLE; | ||
1122 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
1123 | |||
1124 | tegra_dc_commit(dc); | ||
1125 | } | ||
1126 | |||
1127 | err = tegra_sor_power_down(sor); | ||
1128 | if (err < 0) | ||
1129 | dev_err(sor->dev, "failed to power down SOR: %d\n", err); | ||
1130 | |||
1131 | if (sor->dpaux) { | ||
1132 | err = tegra_dpaux_disable(sor->dpaux); | ||
1133 | if (err < 0) | ||
1134 | dev_err(sor->dev, "failed to disable DP: %d\n", err); | ||
1135 | } | ||
1136 | |||
1137 | err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS); | ||
1138 | if (err < 0) | ||
1139 | dev_err(sor->dev, "failed to power off I/O rail: %d\n", err); | ||
1140 | |||
1141 | if (output->panel) | ||
1142 | drm_panel_unprepare(output->panel); | ||
1143 | |||
1144 | reset_control_assert(sor->rst); | ||
1145 | clk_disable_unprepare(sor->clk); | ||
936 | } | 1146 | } |
937 | 1147 | ||
938 | static void tegra_sor_encoder_commit(struct drm_encoder *encoder) | 1148 | #if 0 |
1149 | static int calc_h_ref_to_sync(const struct drm_display_mode *mode, | ||
1150 | unsigned int *value) | ||
939 | { | 1151 | { |
1152 | unsigned int hfp, hsw, hbp, a = 0, b; | ||
1153 | |||
1154 | hfp = mode->hsync_start - mode->hdisplay; | ||
1155 | hsw = mode->hsync_end - mode->hsync_start; | ||
1156 | hbp = mode->htotal - mode->hsync_end; | ||
1157 | |||
1158 | pr_info("hfp: %u, hsw: %u, hbp: %u\n", hfp, hsw, hbp); | ||
1159 | |||
1160 | b = hfp - 1; | ||
1161 | |||
1162 | pr_info("a: %u, b: %u\n", a, b); | ||
1163 | pr_info("a + hsw + hbp = %u\n", a + hsw + hbp); | ||
1164 | |||
1165 | if (a + hsw + hbp <= 11) { | ||
1166 | a = 1 + 11 - hsw - hbp; | ||
1167 | pr_info("a: %u\n", a); | ||
1168 | } | ||
1169 | |||
1170 | if (a > b) | ||
1171 | return -EINVAL; | ||
1172 | |||
1173 | if (hsw < 1) | ||
1174 | return -EINVAL; | ||
1175 | |||
1176 | if (mode->hdisplay < 16) | ||
1177 | return -EINVAL; | ||
1178 | |||
1179 | if (value) { | ||
1180 | if (b > a && a % 2) | ||
1181 | *value = a + 1; | ||
1182 | else | ||
1183 | *value = a; | ||
1184 | } | ||
1185 | |||
1186 | return 0; | ||
940 | } | 1187 | } |
1188 | #endif | ||
941 | 1189 | ||
942 | static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | 1190 | static void tegra_sor_edp_enable(struct drm_encoder *encoder) |
943 | struct drm_display_mode *mode, | ||
944 | struct drm_display_mode *adjusted) | ||
945 | { | 1191 | { |
1192 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; | ||
946 | struct tegra_output *output = encoder_to_output(encoder); | 1193 | struct tegra_output *output = encoder_to_output(encoder); |
947 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | 1194 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
948 | unsigned int vbe, vse, hbe, hse, vbs, hbs, i; | 1195 | unsigned int vbe, vse, hbe, hse, vbs, hbs, i; |
@@ -953,14 +1200,9 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
953 | int err = 0; | 1200 | int err = 0; |
954 | u32 value; | 1201 | u32 value; |
955 | 1202 | ||
956 | mutex_lock(&sor->lock); | ||
957 | |||
958 | if (sor->enabled) | ||
959 | goto unlock; | ||
960 | |||
961 | err = clk_prepare_enable(sor->clk); | 1203 | err = clk_prepare_enable(sor->clk); |
962 | if (err < 0) | 1204 | if (err < 0) |
963 | goto unlock; | 1205 | dev_err(sor->dev, "failed to enable clock: %d\n", err); |
964 | 1206 | ||
965 | reset_control_deassert(sor->rst); | 1207 | reset_control_deassert(sor->rst); |
966 | 1208 | ||
@@ -979,7 +1221,7 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
979 | if (err < 0) { | 1221 | if (err < 0) { |
980 | dev_err(sor->dev, "failed to probe eDP link: %d\n", | 1222 | dev_err(sor->dev, "failed to probe eDP link: %d\n", |
981 | err); | 1223 | err); |
982 | goto unlock; | 1224 | return; |
983 | } | 1225 | } |
984 | } | 1226 | } |
985 | 1227 | ||
@@ -1000,40 +1242,40 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1000 | value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK; | 1242 | value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK; |
1001 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); | 1243 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); |
1002 | 1244 | ||
1003 | value = tegra_sor_readl(sor, SOR_PLL_2); | 1245 | value = tegra_sor_readl(sor, SOR_PLL2); |
1004 | value &= ~SOR_PLL_2_BANDGAP_POWERDOWN; | 1246 | value &= ~SOR_PLL2_BANDGAP_POWERDOWN; |
1005 | tegra_sor_writel(sor, value, SOR_PLL_2); | 1247 | tegra_sor_writel(sor, value, SOR_PLL2); |
1006 | usleep_range(20, 100); | 1248 | usleep_range(20, 100); |
1007 | 1249 | ||
1008 | value = tegra_sor_readl(sor, SOR_PLL_3); | 1250 | value = tegra_sor_readl(sor, SOR_PLL3); |
1009 | value |= SOR_PLL_3_PLL_VDD_MODE_V3_3; | 1251 | value |= SOR_PLL3_PLL_VDD_MODE_3V3; |
1010 | tegra_sor_writel(sor, value, SOR_PLL_3); | 1252 | tegra_sor_writel(sor, value, SOR_PLL3); |
1011 | 1253 | ||
1012 | value = SOR_PLL_0_ICHPMP(0xf) | SOR_PLL_0_VCOCAP_RST | | 1254 | value = SOR_PLL0_ICHPMP(0xf) | SOR_PLL0_VCOCAP_RST | |
1013 | SOR_PLL_0_PLLREG_LEVEL_V45 | SOR_PLL_0_RESISTOR_EXT; | 1255 | SOR_PLL0_PLLREG_LEVEL_V45 | SOR_PLL0_RESISTOR_EXT; |
1014 | tegra_sor_writel(sor, value, SOR_PLL_0); | 1256 | tegra_sor_writel(sor, value, SOR_PLL0); |
1015 | 1257 | ||
1016 | value = tegra_sor_readl(sor, SOR_PLL_2); | 1258 | value = tegra_sor_readl(sor, SOR_PLL2); |
1017 | value |= SOR_PLL_2_SEQ_PLLCAPPD; | 1259 | value |= SOR_PLL2_SEQ_PLLCAPPD; |
1018 | value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE; | 1260 | value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE; |
1019 | value |= SOR_PLL_2_LVDS_ENABLE; | 1261 | value |= SOR_PLL2_LVDS_ENABLE; |
1020 | tegra_sor_writel(sor, value, SOR_PLL_2); | 1262 | tegra_sor_writel(sor, value, SOR_PLL2); |
1021 | 1263 | ||
1022 | value = SOR_PLL_1_TERM_COMPOUT | SOR_PLL_1_TMDS_TERM; | 1264 | value = SOR_PLL1_TERM_COMPOUT | SOR_PLL1_TMDS_TERM; |
1023 | tegra_sor_writel(sor, value, SOR_PLL_1); | 1265 | tegra_sor_writel(sor, value, SOR_PLL1); |
1024 | 1266 | ||
1025 | while (true) { | 1267 | while (true) { |
1026 | value = tegra_sor_readl(sor, SOR_PLL_2); | 1268 | value = tegra_sor_readl(sor, SOR_PLL2); |
1027 | if ((value & SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE) == 0) | 1269 | if ((value & SOR_PLL2_SEQ_PLLCAPPD_ENFORCE) == 0) |
1028 | break; | 1270 | break; |
1029 | 1271 | ||
1030 | usleep_range(250, 1000); | 1272 | usleep_range(250, 1000); |
1031 | } | 1273 | } |
1032 | 1274 | ||
1033 | value = tegra_sor_readl(sor, SOR_PLL_2); | 1275 | value = tegra_sor_readl(sor, SOR_PLL2); |
1034 | value &= ~SOR_PLL_2_POWERDOWN_OVERRIDE; | 1276 | value &= ~SOR_PLL2_POWERDOWN_OVERRIDE; |
1035 | value &= ~SOR_PLL_2_PORT_POWERDOWN; | 1277 | value &= ~SOR_PLL2_PORT_POWERDOWN; |
1036 | tegra_sor_writel(sor, value, SOR_PLL_2); | 1278 | tegra_sor_writel(sor, value, SOR_PLL2); |
1037 | 1279 | ||
1038 | /* | 1280 | /* |
1039 | * power up | 1281 | * power up |
@@ -1046,51 +1288,49 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1046 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); | 1288 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); |
1047 | 1289 | ||
1048 | /* step 1 */ | 1290 | /* step 1 */ |
1049 | value = tegra_sor_readl(sor, SOR_PLL_2); | 1291 | value = tegra_sor_readl(sor, SOR_PLL2); |
1050 | value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL_2_PORT_POWERDOWN | | 1292 | value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL2_PORT_POWERDOWN | |
1051 | SOR_PLL_2_BANDGAP_POWERDOWN; | 1293 | SOR_PLL2_BANDGAP_POWERDOWN; |
1052 | tegra_sor_writel(sor, value, SOR_PLL_2); | 1294 | tegra_sor_writel(sor, value, SOR_PLL2); |
1053 | 1295 | ||
1054 | value = tegra_sor_readl(sor, SOR_PLL_0); | 1296 | value = tegra_sor_readl(sor, SOR_PLL0); |
1055 | value |= SOR_PLL_0_VCOPD | SOR_PLL_0_POWER_OFF; | 1297 | value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR; |
1056 | tegra_sor_writel(sor, value, SOR_PLL_0); | 1298 | tegra_sor_writel(sor, value, SOR_PLL0); |
1057 | 1299 | ||
1058 | value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); | 1300 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); |
1059 | value &= ~SOR_DP_PADCTL_PAD_CAL_PD; | 1301 | value &= ~SOR_DP_PADCTL_PAD_CAL_PD; |
1060 | tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); | 1302 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); |
1061 | 1303 | ||
1062 | /* step 2 */ | 1304 | /* step 2 */ |
1063 | err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS); | 1305 | err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS); |
1064 | if (err < 0) { | 1306 | if (err < 0) |
1065 | dev_err(sor->dev, "failed to power on I/O rail: %d\n", err); | 1307 | dev_err(sor->dev, "failed to power on I/O rail: %d\n", err); |
1066 | goto unlock; | ||
1067 | } | ||
1068 | 1308 | ||
1069 | usleep_range(5, 100); | 1309 | usleep_range(5, 100); |
1070 | 1310 | ||
1071 | /* step 3 */ | 1311 | /* step 3 */ |
1072 | value = tegra_sor_readl(sor, SOR_PLL_2); | 1312 | value = tegra_sor_readl(sor, SOR_PLL2); |
1073 | value &= ~SOR_PLL_2_BANDGAP_POWERDOWN; | 1313 | value &= ~SOR_PLL2_BANDGAP_POWERDOWN; |
1074 | tegra_sor_writel(sor, value, SOR_PLL_2); | 1314 | tegra_sor_writel(sor, value, SOR_PLL2); |
1075 | 1315 | ||
1076 | usleep_range(20, 100); | 1316 | usleep_range(20, 100); |
1077 | 1317 | ||
1078 | /* step 4 */ | 1318 | /* step 4 */ |
1079 | value = tegra_sor_readl(sor, SOR_PLL_0); | 1319 | value = tegra_sor_readl(sor, SOR_PLL0); |
1080 | value &= ~SOR_PLL_0_POWER_OFF; | 1320 | value &= ~SOR_PLL0_VCOPD; |
1081 | value &= ~SOR_PLL_0_VCOPD; | 1321 | value &= ~SOR_PLL0_PWR; |
1082 | tegra_sor_writel(sor, value, SOR_PLL_0); | 1322 | tegra_sor_writel(sor, value, SOR_PLL0); |
1083 | 1323 | ||
1084 | value = tegra_sor_readl(sor, SOR_PLL_2); | 1324 | value = tegra_sor_readl(sor, SOR_PLL2); |
1085 | value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE; | 1325 | value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE; |
1086 | tegra_sor_writel(sor, value, SOR_PLL_2); | 1326 | tegra_sor_writel(sor, value, SOR_PLL2); |
1087 | 1327 | ||
1088 | usleep_range(200, 1000); | 1328 | usleep_range(200, 1000); |
1089 | 1329 | ||
1090 | /* step 5 */ | 1330 | /* step 5 */ |
1091 | value = tegra_sor_readl(sor, SOR_PLL_2); | 1331 | value = tegra_sor_readl(sor, SOR_PLL2); |
1092 | value &= ~SOR_PLL_2_PORT_POWERDOWN; | 1332 | value &= ~SOR_PLL2_PORT_POWERDOWN; |
1093 | tegra_sor_writel(sor, value, SOR_PLL_2); | 1333 | tegra_sor_writel(sor, value, SOR_PLL2); |
1094 | 1334 | ||
1095 | /* switch to DP clock */ | 1335 | /* switch to DP clock */ |
1096 | err = clk_set_parent(sor->clk, sor->clk_dp); | 1336 | err = clk_set_parent(sor->clk, sor->clk_dp); |
@@ -1098,7 +1338,7 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1098 | dev_err(sor->dev, "failed to set DP parent clock: %d\n", err); | 1338 | dev_err(sor->dev, "failed to set DP parent clock: %d\n", err); |
1099 | 1339 | ||
1100 | /* power DP lanes */ | 1340 | /* power DP lanes */ |
1101 | value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); | 1341 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); |
1102 | 1342 | ||
1103 | if (link.num_lanes <= 2) | 1343 | if (link.num_lanes <= 2) |
1104 | value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2); | 1344 | value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2); |
@@ -1115,12 +1355,12 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1115 | else | 1355 | else |
1116 | value |= SOR_DP_PADCTL_PD_TXD_0; | 1356 | value |= SOR_DP_PADCTL_PD_TXD_0; |
1117 | 1357 | ||
1118 | tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); | 1358 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); |
1119 | 1359 | ||
1120 | value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0); | 1360 | value = tegra_sor_readl(sor, SOR_DP_LINKCTL0); |
1121 | value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; | 1361 | value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; |
1122 | value |= SOR_DP_LINKCTL_LANE_COUNT(link.num_lanes); | 1362 | value |= SOR_DP_LINKCTL_LANE_COUNT(link.num_lanes); |
1123 | tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0); | 1363 | tegra_sor_writel(sor, value, SOR_DP_LINKCTL0); |
1124 | 1364 | ||
1125 | /* start lane sequencer */ | 1365 | /* start lane sequencer */ |
1126 | value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | | 1366 | value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | |
@@ -1142,14 +1382,14 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1142 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); | 1382 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); |
1143 | 1383 | ||
1144 | /* set linkctl */ | 1384 | /* set linkctl */ |
1145 | value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0); | 1385 | value = tegra_sor_readl(sor, SOR_DP_LINKCTL0); |
1146 | value |= SOR_DP_LINKCTL_ENABLE; | 1386 | value |= SOR_DP_LINKCTL_ENABLE; |
1147 | 1387 | ||
1148 | value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK; | 1388 | value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK; |
1149 | value |= SOR_DP_LINKCTL_TU_SIZE(config.tu_size); | 1389 | value |= SOR_DP_LINKCTL_TU_SIZE(config.tu_size); |
1150 | 1390 | ||
1151 | value |= SOR_DP_LINKCTL_ENHANCED_FRAME; | 1391 | value |= SOR_DP_LINKCTL_ENHANCED_FRAME; |
1152 | tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0); | 1392 | tegra_sor_writel(sor, value, SOR_DP_LINKCTL0); |
1153 | 1393 | ||
1154 | for (i = 0, value = 0; i < 4; i++) { | 1394 | for (i = 0, value = 0; i < 4; i++) { |
1155 | unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | | 1395 | unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | |
@@ -1160,7 +1400,7 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1160 | 1400 | ||
1161 | tegra_sor_writel(sor, value, SOR_DP_TPG); | 1401 | tegra_sor_writel(sor, value, SOR_DP_TPG); |
1162 | 1402 | ||
1163 | value = tegra_sor_readl(sor, SOR_DP_CONFIG_0); | 1403 | value = tegra_sor_readl(sor, SOR_DP_CONFIG0); |
1164 | value &= ~SOR_DP_CONFIG_WATERMARK_MASK; | 1404 | value &= ~SOR_DP_CONFIG_WATERMARK_MASK; |
1165 | value |= SOR_DP_CONFIG_WATERMARK(config.watermark); | 1405 | value |= SOR_DP_CONFIG_WATERMARK(config.watermark); |
1166 | 1406 | ||
@@ -1177,7 +1417,7 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1177 | 1417 | ||
1178 | value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE; | 1418 | value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE; |
1179 | value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; | 1419 | value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; |
1180 | tegra_sor_writel(sor, value, SOR_DP_CONFIG_0); | 1420 | tegra_sor_writel(sor, value, SOR_DP_CONFIG0); |
1181 | 1421 | ||
1182 | value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS); | 1422 | value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS); |
1183 | value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK; | 1423 | value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK; |
@@ -1190,33 +1430,27 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1190 | tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS); | 1430 | tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS); |
1191 | 1431 | ||
1192 | /* enable pad calibration logic */ | 1432 | /* enable pad calibration logic */ |
1193 | value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); | 1433 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); |
1194 | value |= SOR_DP_PADCTL_PAD_CAL_PD; | 1434 | value |= SOR_DP_PADCTL_PAD_CAL_PD; |
1195 | tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); | 1435 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); |
1196 | 1436 | ||
1197 | if (sor->dpaux) { | 1437 | if (sor->dpaux) { |
1198 | u8 rate, lanes; | 1438 | u8 rate, lanes; |
1199 | 1439 | ||
1200 | err = drm_dp_link_probe(aux, &link); | 1440 | err = drm_dp_link_probe(aux, &link); |
1201 | if (err < 0) { | 1441 | if (err < 0) |
1202 | dev_err(sor->dev, "failed to probe eDP link: %d\n", | 1442 | dev_err(sor->dev, "failed to probe eDP link: %d\n", |
1203 | err); | 1443 | err); |
1204 | goto unlock; | ||
1205 | } | ||
1206 | 1444 | ||
1207 | err = drm_dp_link_power_up(aux, &link); | 1445 | err = drm_dp_link_power_up(aux, &link); |
1208 | if (err < 0) { | 1446 | if (err < 0) |
1209 | dev_err(sor->dev, "failed to power up eDP link: %d\n", | 1447 | dev_err(sor->dev, "failed to power up eDP link: %d\n", |
1210 | err); | 1448 | err); |
1211 | goto unlock; | ||
1212 | } | ||
1213 | 1449 | ||
1214 | err = drm_dp_link_configure(aux, &link); | 1450 | err = drm_dp_link_configure(aux, &link); |
1215 | if (err < 0) { | 1451 | if (err < 0) |
1216 | dev_err(sor->dev, "failed to configure eDP link: %d\n", | 1452 | dev_err(sor->dev, "failed to configure eDP link: %d\n", |
1217 | err); | 1453 | err); |
1218 | goto unlock; | ||
1219 | } | ||
1220 | 1454 | ||
1221 | rate = drm_dp_link_rate_to_bw_code(link.rate); | 1455 | rate = drm_dp_link_rate_to_bw_code(link.rate); |
1222 | lanes = link.num_lanes; | 1456 | lanes = link.num_lanes; |
@@ -1226,14 +1460,14 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1226 | value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate); | 1460 | value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate); |
1227 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); | 1461 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); |
1228 | 1462 | ||
1229 | value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0); | 1463 | value = tegra_sor_readl(sor, SOR_DP_LINKCTL0); |
1230 | value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; | 1464 | value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; |
1231 | value |= SOR_DP_LINKCTL_LANE_COUNT(lanes); | 1465 | value |= SOR_DP_LINKCTL_LANE_COUNT(lanes); |
1232 | 1466 | ||
1233 | if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) | 1467 | if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) |
1234 | value |= SOR_DP_LINKCTL_ENHANCED_FRAME; | 1468 | value |= SOR_DP_LINKCTL_ENHANCED_FRAME; |
1235 | 1469 | ||
1236 | tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0); | 1470 | tegra_sor_writel(sor, value, SOR_DP_LINKCTL0); |
1237 | 1471 | ||
1238 | /* disable training pattern generator */ | 1472 | /* disable training pattern generator */ |
1239 | 1473 | ||
@@ -1250,17 +1484,14 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1250 | if (err < 0) { | 1484 | if (err < 0) { |
1251 | dev_err(sor->dev, "DP fast link training failed: %d\n", | 1485 | dev_err(sor->dev, "DP fast link training failed: %d\n", |
1252 | err); | 1486 | err); |
1253 | goto unlock; | ||
1254 | } | 1487 | } |
1255 | 1488 | ||
1256 | dev_dbg(sor->dev, "fast link training succeeded\n"); | 1489 | dev_dbg(sor->dev, "fast link training succeeded\n"); |
1257 | } | 1490 | } |
1258 | 1491 | ||
1259 | err = tegra_sor_power_up(sor, 250); | 1492 | err = tegra_sor_power_up(sor, 250); |
1260 | if (err < 0) { | 1493 | if (err < 0) |
1261 | dev_err(sor->dev, "failed to power up SOR: %d\n", err); | 1494 | dev_err(sor->dev, "failed to power up SOR: %d\n", err); |
1262 | goto unlock; | ||
1263 | } | ||
1264 | 1495 | ||
1265 | /* | 1496 | /* |
1266 | * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete | 1497 | * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete |
@@ -1296,7 +1527,7 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1296 | break; | 1527 | break; |
1297 | } | 1528 | } |
1298 | 1529 | ||
1299 | tegra_sor_writel(sor, value, SOR_STATE_1); | 1530 | tegra_sor_writel(sor, value, SOR_STATE1); |
1300 | 1531 | ||
1301 | /* | 1532 | /* |
1302 | * TODO: The video timing programming below doesn't seem to match the | 1533 | * TODO: The video timing programming below doesn't seem to match the |
@@ -1304,25 +1535,27 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1304 | */ | 1535 | */ |
1305 | 1536 | ||
1306 | value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff); | 1537 | value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff); |
1307 | tegra_sor_writel(sor, value, SOR_HEAD_STATE_1(0)); | 1538 | tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe)); |
1308 | 1539 | ||
1309 | vse = mode->vsync_end - mode->vsync_start - 1; | 1540 | vse = mode->vsync_end - mode->vsync_start - 1; |
1310 | hse = mode->hsync_end - mode->hsync_start - 1; | 1541 | hse = mode->hsync_end - mode->hsync_start - 1; |
1311 | 1542 | ||
1312 | value = ((vse & 0x7fff) << 16) | (hse & 0x7fff); | 1543 | value = ((vse & 0x7fff) << 16) | (hse & 0x7fff); |
1313 | tegra_sor_writel(sor, value, SOR_HEAD_STATE_2(0)); | 1544 | tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe)); |
1314 | 1545 | ||
1315 | vbe = vse + (mode->vsync_start - mode->vdisplay); | 1546 | vbe = vse + (mode->vsync_start - mode->vdisplay); |
1316 | hbe = hse + (mode->hsync_start - mode->hdisplay); | 1547 | hbe = hse + (mode->hsync_start - mode->hdisplay); |
1317 | 1548 | ||
1318 | value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff); | 1549 | value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff); |
1319 | tegra_sor_writel(sor, value, SOR_HEAD_STATE_3(0)); | 1550 | tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe)); |
1320 | 1551 | ||
1321 | vbs = vbe + mode->vdisplay; | 1552 | vbs = vbe + mode->vdisplay; |
1322 | hbs = hbe + mode->hdisplay; | 1553 | hbs = hbe + mode->hdisplay; |
1323 | 1554 | ||
1324 | value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff); | 1555 | value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff); |
1325 | tegra_sor_writel(sor, value, SOR_HEAD_STATE_4(0)); | 1556 | tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe)); |
1557 | |||
1558 | tegra_sor_writel(sor, 0x1, SOR_HEAD_STATE5(dc->pipe)); | ||
1326 | 1559 | ||
1327 | /* CSTM (LVDS, link A/B, upper) */ | 1560 | /* CSTM (LVDS, link A/B, upper) */ |
1328 | value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B | | 1561 | value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B | |
@@ -1331,10 +1564,8 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1331 | 1564 | ||
1332 | /* PWM setup */ | 1565 | /* PWM setup */ |
1333 | err = tegra_sor_setup_pwm(sor, 250); | 1566 | err = tegra_sor_setup_pwm(sor, 250); |
1334 | if (err < 0) { | 1567 | if (err < 0) |
1335 | dev_err(sor->dev, "failed to setup PWM: %d\n", err); | 1568 | dev_err(sor->dev, "failed to setup PWM: %d\n", err); |
1336 | goto unlock; | ||
1337 | } | ||
1338 | 1569 | ||
1339 | tegra_sor_update(sor); | 1570 | tegra_sor_update(sor); |
1340 | 1571 | ||
@@ -1345,147 +1576,610 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder, | |||
1345 | tegra_dc_commit(dc); | 1576 | tegra_dc_commit(dc); |
1346 | 1577 | ||
1347 | err = tegra_sor_attach(sor); | 1578 | err = tegra_sor_attach(sor); |
1348 | if (err < 0) { | 1579 | if (err < 0) |
1349 | dev_err(sor->dev, "failed to attach SOR: %d\n", err); | 1580 | dev_err(sor->dev, "failed to attach SOR: %d\n", err); |
1350 | goto unlock; | ||
1351 | } | ||
1352 | 1581 | ||
1353 | err = tegra_sor_wakeup(sor); | 1582 | err = tegra_sor_wakeup(sor); |
1354 | if (err < 0) { | 1583 | if (err < 0) |
1355 | dev_err(sor->dev, "failed to enable DC: %d\n", err); | 1584 | dev_err(sor->dev, "failed to enable DC: %d\n", err); |
1356 | goto unlock; | ||
1357 | } | ||
1358 | 1585 | ||
1359 | if (output->panel) | 1586 | if (output->panel) |
1360 | drm_panel_enable(output->panel); | 1587 | drm_panel_enable(output->panel); |
1361 | |||
1362 | sor->enabled = true; | ||
1363 | |||
1364 | unlock: | ||
1365 | mutex_unlock(&sor->lock); | ||
1366 | } | 1588 | } |
1367 | 1589 | ||
1368 | static void tegra_sor_encoder_disable(struct drm_encoder *encoder) | 1590 | static int |
1591 | tegra_sor_encoder_atomic_check(struct drm_encoder *encoder, | ||
1592 | struct drm_crtc_state *crtc_state, | ||
1593 | struct drm_connector_state *conn_state) | ||
1369 | { | 1594 | { |
1370 | struct tegra_output *output = encoder_to_output(encoder); | 1595 | struct tegra_output *output = encoder_to_output(encoder); |
1371 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | 1596 | struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); |
1597 | unsigned long pclk = crtc_state->mode.clock * 1000; | ||
1372 | struct tegra_sor *sor = to_sor(output); | 1598 | struct tegra_sor *sor = to_sor(output); |
1373 | u32 value; | ||
1374 | int err; | 1599 | int err; |
1375 | 1600 | ||
1376 | mutex_lock(&sor->lock); | 1601 | err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent, |
1602 | pclk, 0); | ||
1603 | if (err < 0) { | ||
1604 | dev_err(output->dev, "failed to setup CRTC state: %d\n", err); | ||
1605 | return err; | ||
1606 | } | ||
1377 | 1607 | ||
1378 | if (!sor->enabled) | 1608 | return 0; |
1379 | goto unlock; | 1609 | } |
1380 | 1610 | ||
1381 | if (output->panel) | 1611 | static const struct drm_encoder_helper_funcs tegra_sor_edp_helpers = { |
1382 | drm_panel_disable(output->panel); | 1612 | .disable = tegra_sor_edp_disable, |
1613 | .enable = tegra_sor_edp_enable, | ||
1614 | .atomic_check = tegra_sor_encoder_atomic_check, | ||
1615 | }; | ||
1383 | 1616 | ||
1384 | err = tegra_sor_detach(sor); | 1617 | static inline u32 tegra_sor_hdmi_subpack(const u8 *ptr, size_t size) |
1385 | if (err < 0) { | 1618 | { |
1386 | dev_err(sor->dev, "failed to detach SOR: %d\n", err); | 1619 | u32 value = 0; |
1387 | goto unlock; | 1620 | size_t i; |
1621 | |||
1622 | for (i = size; i > 0; i--) | ||
1623 | value = (value << 8) | ptr[i - 1]; | ||
1624 | |||
1625 | return value; | ||
1626 | } | ||
1627 | |||
1628 | static void tegra_sor_hdmi_write_infopack(struct tegra_sor *sor, | ||
1629 | const void *data, size_t size) | ||
1630 | { | ||
1631 | const u8 *ptr = data; | ||
1632 | unsigned long offset; | ||
1633 | size_t i, j; | ||
1634 | u32 value; | ||
1635 | |||
1636 | switch (ptr[0]) { | ||
1637 | case HDMI_INFOFRAME_TYPE_AVI: | ||
1638 | offset = SOR_HDMI_AVI_INFOFRAME_HEADER; | ||
1639 | break; | ||
1640 | |||
1641 | case HDMI_INFOFRAME_TYPE_AUDIO: | ||
1642 | offset = SOR_HDMI_AUDIO_INFOFRAME_HEADER; | ||
1643 | break; | ||
1644 | |||
1645 | case HDMI_INFOFRAME_TYPE_VENDOR: | ||
1646 | offset = SOR_HDMI_VSI_INFOFRAME_HEADER; | ||
1647 | break; | ||
1648 | |||
1649 | default: | ||
1650 | dev_err(sor->dev, "unsupported infoframe type: %02x\n", | ||
1651 | ptr[0]); | ||
1652 | return; | ||
1388 | } | 1653 | } |
1389 | 1654 | ||
1390 | tegra_sor_writel(sor, 0, SOR_STATE_1); | 1655 | value = INFOFRAME_HEADER_TYPE(ptr[0]) | |
1391 | tegra_sor_update(sor); | 1656 | INFOFRAME_HEADER_VERSION(ptr[1]) | |
1657 | INFOFRAME_HEADER_LEN(ptr[2]); | ||
1658 | tegra_sor_writel(sor, value, offset); | ||
1659 | offset++; | ||
1392 | 1660 | ||
1393 | /* | 1661 | /* |
1394 | * The following accesses registers of the display controller, so make | 1662 | * Each subpack contains 7 bytes, divided into: |
1395 | * sure it's only executed when the output is attached to one. | 1663 | * - subpack_low: bytes 0 - 3 |
1664 | * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00) | ||
1396 | */ | 1665 | */ |
1397 | if (dc) { | 1666 | for (i = 3, j = 0; i < size; i += 7, j += 8) { |
1398 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | 1667 | size_t rem = size - i, num = min_t(size_t, rem, 4); |
1399 | value &= ~SOR_ENABLE; | ||
1400 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
1401 | 1668 | ||
1402 | tegra_dc_commit(dc); | 1669 | value = tegra_sor_hdmi_subpack(&ptr[i], num); |
1403 | } | 1670 | tegra_sor_writel(sor, value, offset++); |
1404 | 1671 | ||
1405 | err = tegra_sor_power_down(sor); | 1672 | num = min_t(size_t, rem - num, 3); |
1406 | if (err < 0) { | 1673 | |
1407 | dev_err(sor->dev, "failed to power down SOR: %d\n", err); | 1674 | value = tegra_sor_hdmi_subpack(&ptr[i + 4], num); |
1408 | goto unlock; | 1675 | tegra_sor_writel(sor, value, offset++); |
1409 | } | 1676 | } |
1677 | } | ||
1410 | 1678 | ||
1411 | if (sor->dpaux) { | 1679 | static int |
1412 | err = tegra_dpaux_disable(sor->dpaux); | 1680 | tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor, |
1413 | if (err < 0) { | 1681 | const struct drm_display_mode *mode) |
1414 | dev_err(sor->dev, "failed to disable DP: %d\n", err); | 1682 | { |
1415 | goto unlock; | 1683 | u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; |
1416 | } | 1684 | struct hdmi_avi_infoframe frame; |
1685 | u32 value; | ||
1686 | int err; | ||
1687 | |||
1688 | /* disable AVI infoframe */ | ||
1689 | value = tegra_sor_readl(sor, SOR_HDMI_AVI_INFOFRAME_CTRL); | ||
1690 | value &= ~INFOFRAME_CTRL_SINGLE; | ||
1691 | value &= ~INFOFRAME_CTRL_OTHER; | ||
1692 | value &= ~INFOFRAME_CTRL_ENABLE; | ||
1693 | tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL); | ||
1694 | |||
1695 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); | ||
1696 | if (err < 0) { | ||
1697 | dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err); | ||
1698 | return err; | ||
1417 | } | 1699 | } |
1418 | 1700 | ||
1419 | err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS); | 1701 | err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); |
1420 | if (err < 0) { | 1702 | if (err < 0) { |
1421 | dev_err(sor->dev, "failed to power off I/O rail: %d\n", err); | 1703 | dev_err(sor->dev, "failed to pack AVI infoframe: %d\n", err); |
1422 | goto unlock; | 1704 | return err; |
1423 | } | 1705 | } |
1424 | 1706 | ||
1425 | if (output->panel) | 1707 | tegra_sor_hdmi_write_infopack(sor, buffer, err); |
1426 | drm_panel_unprepare(output->panel); | ||
1427 | 1708 | ||
1428 | clk_disable_unprepare(sor->clk); | 1709 | /* enable AVI infoframe */ |
1429 | reset_control_assert(sor->rst); | 1710 | value = tegra_sor_readl(sor, SOR_HDMI_AVI_INFOFRAME_CTRL); |
1711 | value |= INFOFRAME_CTRL_CHECKSUM_ENABLE; | ||
1712 | value |= INFOFRAME_CTRL_ENABLE; | ||
1713 | tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL); | ||
1714 | |||
1715 | return 0; | ||
1716 | } | ||
1430 | 1717 | ||
1431 | sor->enabled = false; | 1718 | static void tegra_sor_hdmi_disable_audio_infoframe(struct tegra_sor *sor) |
1719 | { | ||
1720 | u32 value; | ||
1432 | 1721 | ||
1433 | unlock: | 1722 | value = tegra_sor_readl(sor, SOR_HDMI_AUDIO_INFOFRAME_CTRL); |
1434 | mutex_unlock(&sor->lock); | 1723 | value &= ~INFOFRAME_CTRL_ENABLE; |
1724 | tegra_sor_writel(sor, value, SOR_HDMI_AUDIO_INFOFRAME_CTRL); | ||
1435 | } | 1725 | } |
1436 | 1726 | ||
1437 | static int | 1727 | static struct tegra_sor_hdmi_settings * |
1438 | tegra_sor_encoder_atomic_check(struct drm_encoder *encoder, | 1728 | tegra_sor_hdmi_find_settings(struct tegra_sor *sor, unsigned long frequency) |
1439 | struct drm_crtc_state *crtc_state, | 1729 | { |
1440 | struct drm_connector_state *conn_state) | 1730 | unsigned int i; |
1731 | |||
1732 | for (i = 0; i < sor->num_settings; i++) | ||
1733 | if (frequency <= sor->settings[i].frequency) | ||
1734 | return &sor->settings[i]; | ||
1735 | |||
1736 | return NULL; | ||
1737 | } | ||
1738 | |||
1739 | static void tegra_sor_hdmi_disable(struct drm_encoder *encoder) | ||
1441 | { | 1740 | { |
1442 | struct tegra_output *output = encoder_to_output(encoder); | 1741 | struct tegra_output *output = encoder_to_output(encoder); |
1443 | struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); | 1742 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
1444 | unsigned long pclk = crtc_state->mode.clock * 1000; | ||
1445 | struct tegra_sor *sor = to_sor(output); | 1743 | struct tegra_sor *sor = to_sor(output); |
1744 | u32 value; | ||
1446 | int err; | 1745 | int err; |
1447 | 1746 | ||
1448 | err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent, | 1747 | err = tegra_sor_detach(sor); |
1449 | pclk, 0); | 1748 | if (err < 0) |
1450 | if (err < 0) { | 1749 | dev_err(sor->dev, "failed to detach SOR: %d\n", err); |
1451 | dev_err(output->dev, "failed to setup CRTC state: %d\n", err); | 1750 | |
1452 | return err; | 1751 | tegra_sor_writel(sor, 0, SOR_STATE1); |
1752 | tegra_sor_update(sor); | ||
1753 | |||
1754 | /* disable display to SOR clock */ | ||
1755 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
1756 | value &= ~SOR1_TIMING_CYA; | ||
1757 | value &= ~SOR1_ENABLE; | ||
1758 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
1759 | |||
1760 | tegra_dc_commit(dc); | ||
1761 | |||
1762 | err = tegra_sor_power_down(sor); | ||
1763 | if (err < 0) | ||
1764 | dev_err(sor->dev, "failed to power down SOR: %d\n", err); | ||
1765 | |||
1766 | err = tegra_io_rail_power_off(TEGRA_IO_RAIL_HDMI); | ||
1767 | if (err < 0) | ||
1768 | dev_err(sor->dev, "failed to power off HDMI rail: %d\n", err); | ||
1769 | |||
1770 | reset_control_assert(sor->rst); | ||
1771 | usleep_range(1000, 2000); | ||
1772 | clk_disable_unprepare(sor->clk); | ||
1773 | } | ||
1774 | |||
1775 | static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) | ||
1776 | { | ||
1777 | struct tegra_output *output = encoder_to_output(encoder); | ||
1778 | unsigned int h_ref_to_sync = 1, pulse_start, max_ac; | ||
1779 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | ||
1780 | unsigned int vbe, vse, hbe, hse, vbs, hbs, div; | ||
1781 | struct tegra_sor_hdmi_settings *settings; | ||
1782 | struct tegra_sor *sor = to_sor(output); | ||
1783 | struct drm_display_mode *mode; | ||
1784 | struct drm_display_info *info; | ||
1785 | u32 value; | ||
1786 | int err; | ||
1787 | |||
1788 | mode = &encoder->crtc->state->adjusted_mode; | ||
1789 | info = &output->connector.display_info; | ||
1790 | |||
1791 | err = clk_prepare_enable(sor->clk); | ||
1792 | if (err < 0) | ||
1793 | dev_err(sor->dev, "failed to enable clock: %d\n", err); | ||
1794 | |||
1795 | usleep_range(1000, 2000); | ||
1796 | |||
1797 | reset_control_deassert(sor->rst); | ||
1798 | |||
1799 | err = clk_set_parent(sor->clk, sor->clk_safe); | ||
1800 | if (err < 0) | ||
1801 | dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); | ||
1802 | |||
1803 | div = clk_get_rate(sor->clk) / 1000000 * 4; | ||
1804 | |||
1805 | err = tegra_io_rail_power_on(TEGRA_IO_RAIL_HDMI); | ||
1806 | if (err < 0) | ||
1807 | dev_err(sor->dev, "failed to power on HDMI rail: %d\n", err); | ||
1808 | |||
1809 | usleep_range(20, 100); | ||
1810 | |||
1811 | value = tegra_sor_readl(sor, SOR_PLL2); | ||
1812 | value &= ~SOR_PLL2_BANDGAP_POWERDOWN; | ||
1813 | tegra_sor_writel(sor, value, SOR_PLL2); | ||
1814 | |||
1815 | usleep_range(20, 100); | ||
1816 | |||
1817 | value = tegra_sor_readl(sor, SOR_PLL3); | ||
1818 | value &= ~SOR_PLL3_PLL_VDD_MODE_3V3; | ||
1819 | tegra_sor_writel(sor, value, SOR_PLL3); | ||
1820 | |||
1821 | value = tegra_sor_readl(sor, SOR_PLL0); | ||
1822 | value &= ~SOR_PLL0_VCOPD; | ||
1823 | value &= ~SOR_PLL0_PWR; | ||
1824 | tegra_sor_writel(sor, value, SOR_PLL0); | ||
1825 | |||
1826 | value = tegra_sor_readl(sor, SOR_PLL2); | ||
1827 | value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE; | ||
1828 | tegra_sor_writel(sor, value, SOR_PLL2); | ||
1829 | |||
1830 | usleep_range(200, 400); | ||
1831 | |||
1832 | value = tegra_sor_readl(sor, SOR_PLL2); | ||
1833 | value &= ~SOR_PLL2_POWERDOWN_OVERRIDE; | ||
1834 | value &= ~SOR_PLL2_PORT_POWERDOWN; | ||
1835 | tegra_sor_writel(sor, value, SOR_PLL2); | ||
1836 | |||
1837 | usleep_range(20, 100); | ||
1838 | |||
1839 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); | ||
1840 | value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | | ||
1841 | SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2; | ||
1842 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); | ||
1843 | |||
1844 | while (true) { | ||
1845 | value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); | ||
1846 | if ((value & SOR_LANE_SEQ_CTL_STATE_BUSY) == 0) | ||
1847 | break; | ||
1848 | |||
1849 | usleep_range(250, 1000); | ||
1453 | } | 1850 | } |
1454 | 1851 | ||
1455 | return 0; | 1852 | value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | |
1853 | SOR_LANE_SEQ_CTL_POWER_STATE_UP | SOR_LANE_SEQ_CTL_DELAY(5); | ||
1854 | tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL); | ||
1855 | |||
1856 | while (true) { | ||
1857 | value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); | ||
1858 | if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0) | ||
1859 | break; | ||
1860 | |||
1861 | usleep_range(250, 1000); | ||
1862 | } | ||
1863 | |||
1864 | value = tegra_sor_readl(sor, SOR_CLK_CNTRL); | ||
1865 | value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK; | ||
1866 | value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK; | ||
1867 | |||
1868 | if (mode->clock < 340000) | ||
1869 | value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70; | ||
1870 | else | ||
1871 | value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40; | ||
1872 | |||
1873 | value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK; | ||
1874 | tegra_sor_writel(sor, value, SOR_CLK_CNTRL); | ||
1875 | |||
1876 | value = tegra_sor_readl(sor, SOR_DP_SPARE0); | ||
1877 | value |= SOR_DP_SPARE_DISP_VIDEO_PREAMBLE; | ||
1878 | value &= ~SOR_DP_SPARE_PANEL_INTERNAL; | ||
1879 | value |= SOR_DP_SPARE_SEQ_ENABLE; | ||
1880 | tegra_sor_writel(sor, value, SOR_DP_SPARE0); | ||
1881 | |||
1882 | value = SOR_SEQ_CTL_PU_PC(0) | SOR_SEQ_CTL_PU_PC_ALT(0) | | ||
1883 | SOR_SEQ_CTL_PD_PC(8) | SOR_SEQ_CTL_PD_PC_ALT(8); | ||
1884 | tegra_sor_writel(sor, value, SOR_SEQ_CTL); | ||
1885 | |||
1886 | value = SOR_SEQ_INST_DRIVE_PWM_OUT_LO | SOR_SEQ_INST_HALT | | ||
1887 | SOR_SEQ_INST_WAIT_VSYNC | SOR_SEQ_INST_WAIT(1); | ||
1888 | tegra_sor_writel(sor, value, SOR_SEQ_INST(0)); | ||
1889 | tegra_sor_writel(sor, value, SOR_SEQ_INST(8)); | ||
1890 | |||
1891 | /* program the reference clock */ | ||
1892 | value = SOR_REFCLK_DIV_INT(div) | SOR_REFCLK_DIV_FRAC(div); | ||
1893 | tegra_sor_writel(sor, value, SOR_REFCLK); | ||
1894 | |||
1895 | /* XXX don't hardcode */ | ||
1896 | value = SOR_XBAR_CTRL_LINK1_XSEL(4, 4) | | ||
1897 | SOR_XBAR_CTRL_LINK1_XSEL(3, 3) | | ||
1898 | SOR_XBAR_CTRL_LINK1_XSEL(2, 2) | | ||
1899 | SOR_XBAR_CTRL_LINK1_XSEL(1, 1) | | ||
1900 | SOR_XBAR_CTRL_LINK1_XSEL(0, 0) | | ||
1901 | SOR_XBAR_CTRL_LINK0_XSEL(4, 4) | | ||
1902 | SOR_XBAR_CTRL_LINK0_XSEL(3, 3) | | ||
1903 | SOR_XBAR_CTRL_LINK0_XSEL(2, 0) | | ||
1904 | SOR_XBAR_CTRL_LINK0_XSEL(1, 1) | | ||
1905 | SOR_XBAR_CTRL_LINK0_XSEL(0, 2); | ||
1906 | tegra_sor_writel(sor, value, SOR_XBAR_CTRL); | ||
1907 | |||
1908 | tegra_sor_writel(sor, 0x00000000, SOR_XBAR_POL); | ||
1909 | |||
1910 | err = clk_set_parent(sor->clk, sor->clk_parent); | ||
1911 | if (err < 0) | ||
1912 | dev_err(sor->dev, "failed to set parent clock: %d\n", err); | ||
1913 | |||
1914 | value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe); | ||
1915 | |||
1916 | /* XXX is this the proper check? */ | ||
1917 | if (mode->clock < 75000) | ||
1918 | value |= SOR_INPUT_CONTROL_ARM_VIDEO_RANGE_LIMITED; | ||
1919 | |||
1920 | tegra_sor_writel(sor, value, SOR_INPUT_CONTROL); | ||
1921 | |||
1922 | max_ac = ((mode->htotal - mode->hdisplay) - SOR_REKEY - 18) / 32; | ||
1923 | |||
1924 | value = SOR_HDMI_CTRL_ENABLE | SOR_HDMI_CTRL_MAX_AC_PACKET(max_ac) | | ||
1925 | SOR_HDMI_CTRL_AUDIO_LAYOUT | SOR_HDMI_CTRL_REKEY(SOR_REKEY); | ||
1926 | tegra_sor_writel(sor, value, SOR_HDMI_CTRL); | ||
1927 | |||
1928 | /* H_PULSE2 setup */ | ||
1929 | pulse_start = h_ref_to_sync + (mode->hsync_end - mode->hsync_start) + | ||
1930 | (mode->htotal - mode->hsync_end) - 10; | ||
1931 | |||
1932 | value = PULSE_LAST_END_A | PULSE_QUAL_VACTIVE | | ||
1933 | PULSE_POLARITY_HIGH | PULSE_MODE_NORMAL; | ||
1934 | tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL); | ||
1935 | |||
1936 | value = PULSE_END(pulse_start + 8) | PULSE_START(pulse_start); | ||
1937 | tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A); | ||
1938 | |||
1939 | value = tegra_dc_readl(dc, DC_DISP_DISP_SIGNAL_OPTIONS0); | ||
1940 | value |= H_PULSE2_ENABLE; | ||
1941 | tegra_dc_writel(dc, value, DC_DISP_DISP_SIGNAL_OPTIONS0); | ||
1942 | |||
1943 | /* infoframe setup */ | ||
1944 | err = tegra_sor_hdmi_setup_avi_infoframe(sor, mode); | ||
1945 | if (err < 0) | ||
1946 | dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err); | ||
1947 | |||
1948 | /* XXX HDMI audio support not implemented yet */ | ||
1949 | tegra_sor_hdmi_disable_audio_infoframe(sor); | ||
1950 | |||
1951 | /* use single TMDS protocol */ | ||
1952 | value = tegra_sor_readl(sor, SOR_STATE1); | ||
1953 | value &= ~SOR_STATE_ASY_PROTOCOL_MASK; | ||
1954 | value |= SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A; | ||
1955 | tegra_sor_writel(sor, value, SOR_STATE1); | ||
1956 | |||
1957 | /* power up pad calibration */ | ||
1958 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); | ||
1959 | value &= ~SOR_DP_PADCTL_PAD_CAL_PD; | ||
1960 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); | ||
1961 | |||
1962 | /* production settings */ | ||
1963 | settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000); | ||
1964 | if (IS_ERR(settings)) { | ||
1965 | dev_err(sor->dev, "no settings for pixel clock %d Hz: %ld\n", | ||
1966 | mode->clock * 1000, PTR_ERR(settings)); | ||
1967 | return; | ||
1968 | } | ||
1969 | |||
1970 | value = tegra_sor_readl(sor, SOR_PLL0); | ||
1971 | value &= ~SOR_PLL0_ICHPMP_MASK; | ||
1972 | value &= ~SOR_PLL0_VCOCAP_MASK; | ||
1973 | value |= SOR_PLL0_ICHPMP(settings->ichpmp); | ||
1974 | value |= SOR_PLL0_VCOCAP(settings->vcocap); | ||
1975 | tegra_sor_writel(sor, value, SOR_PLL0); | ||
1976 | |||
1977 | tegra_sor_dp_term_calibrate(sor); | ||
1978 | |||
1979 | value = tegra_sor_readl(sor, SOR_PLL1); | ||
1980 | value &= ~SOR_PLL1_LOADADJ_MASK; | ||
1981 | value |= SOR_PLL1_LOADADJ(settings->loadadj); | ||
1982 | tegra_sor_writel(sor, value, SOR_PLL1); | ||
1983 | |||
1984 | value = tegra_sor_readl(sor, SOR_PLL3); | ||
1985 | value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK; | ||
1986 | value |= SOR_PLL3_BG_VREF_LEVEL(settings->bg_vref); | ||
1987 | tegra_sor_writel(sor, value, SOR_PLL3); | ||
1988 | |||
1989 | value = settings->drive_current[0] << 24 | | ||
1990 | settings->drive_current[1] << 16 | | ||
1991 | settings->drive_current[2] << 8 | | ||
1992 | settings->drive_current[3] << 0; | ||
1993 | tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0); | ||
1994 | |||
1995 | value = settings->preemphasis[0] << 24 | | ||
1996 | settings->preemphasis[1] << 16 | | ||
1997 | settings->preemphasis[2] << 8 | | ||
1998 | settings->preemphasis[3] << 0; | ||
1999 | tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0); | ||
2000 | |||
2001 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); | ||
2002 | value &= ~SOR_DP_PADCTL_TX_PU_MASK; | ||
2003 | value |= SOR_DP_PADCTL_TX_PU_ENABLE; | ||
2004 | value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu); | ||
2005 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); | ||
2006 | |||
2007 | /* power down pad calibration */ | ||
2008 | value = tegra_sor_readl(sor, SOR_DP_PADCTL0); | ||
2009 | value |= SOR_DP_PADCTL_PAD_CAL_PD; | ||
2010 | tegra_sor_writel(sor, value, SOR_DP_PADCTL0); | ||
2011 | |||
2012 | /* miscellaneous display controller settings */ | ||
2013 | value = VSYNC_H_POSITION(1); | ||
2014 | tegra_dc_writel(dc, value, DC_DISP_DISP_TIMING_OPTIONS); | ||
2015 | |||
2016 | value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL); | ||
2017 | value &= ~DITHER_CONTROL_MASK; | ||
2018 | value &= ~BASE_COLOR_SIZE_MASK; | ||
2019 | |||
2020 | switch (info->bpc) { | ||
2021 | case 6: | ||
2022 | value |= BASE_COLOR_SIZE_666; | ||
2023 | break; | ||
2024 | |||
2025 | case 8: | ||
2026 | value |= BASE_COLOR_SIZE_888; | ||
2027 | break; | ||
2028 | |||
2029 | default: | ||
2030 | WARN(1, "%u bits-per-color not supported\n", info->bpc); | ||
2031 | break; | ||
2032 | } | ||
2033 | |||
2034 | tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL); | ||
2035 | |||
2036 | err = tegra_sor_power_up(sor, 250); | ||
2037 | if (err < 0) | ||
2038 | dev_err(sor->dev, "failed to power up SOR: %d\n", err); | ||
2039 | |||
2040 | /* configure mode */ | ||
2041 | value = tegra_sor_readl(sor, SOR_STATE1); | ||
2042 | value &= ~SOR_STATE_ASY_PIXELDEPTH_MASK; | ||
2043 | value &= ~SOR_STATE_ASY_CRC_MODE_MASK; | ||
2044 | value &= ~SOR_STATE_ASY_OWNER_MASK; | ||
2045 | |||
2046 | value |= SOR_STATE_ASY_CRC_MODE_COMPLETE | | ||
2047 | SOR_STATE_ASY_OWNER(dc->pipe + 1); | ||
2048 | |||
2049 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) | ||
2050 | value &= ~SOR_STATE_ASY_HSYNCPOL; | ||
2051 | |||
2052 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
2053 | value |= SOR_STATE_ASY_HSYNCPOL; | ||
2054 | |||
2055 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) | ||
2056 | value &= ~SOR_STATE_ASY_VSYNCPOL; | ||
2057 | |||
2058 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
2059 | value |= SOR_STATE_ASY_VSYNCPOL; | ||
2060 | |||
2061 | switch (info->bpc) { | ||
2062 | case 8: | ||
2063 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; | ||
2064 | break; | ||
2065 | |||
2066 | case 6: | ||
2067 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444; | ||
2068 | break; | ||
2069 | |||
2070 | default: | ||
2071 | BUG(); | ||
2072 | break; | ||
2073 | } | ||
2074 | |||
2075 | tegra_sor_writel(sor, value, SOR_STATE1); | ||
2076 | |||
2077 | value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe)); | ||
2078 | value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK; | ||
2079 | value &= ~SOR_HEAD_STATE_DYNRANGE_MASK; | ||
2080 | tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); | ||
2081 | |||
2082 | value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe)); | ||
2083 | value &= ~SOR_HEAD_STATE_COLORSPACE_MASK; | ||
2084 | value |= SOR_HEAD_STATE_COLORSPACE_RGB; | ||
2085 | tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); | ||
2086 | |||
2087 | /* | ||
2088 | * TODO: The video timing programming below doesn't seem to match the | ||
2089 | * register definitions. | ||
2090 | */ | ||
2091 | |||
2092 | value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff); | ||
2093 | tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe)); | ||
2094 | |||
2095 | /* sync end = sync width - 1 */ | ||
2096 | vse = mode->vsync_end - mode->vsync_start - 1; | ||
2097 | hse = mode->hsync_end - mode->hsync_start - 1; | ||
2098 | |||
2099 | value = ((vse & 0x7fff) << 16) | (hse & 0x7fff); | ||
2100 | tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe)); | ||
2101 | |||
2102 | /* blank end = sync end + back porch */ | ||
2103 | vbe = vse + (mode->vtotal - mode->vsync_end); | ||
2104 | hbe = hse + (mode->htotal - mode->hsync_end); | ||
2105 | |||
2106 | value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff); | ||
2107 | tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe)); | ||
2108 | |||
2109 | /* blank start = blank end + active */ | ||
2110 | vbs = vbe + mode->vdisplay; | ||
2111 | hbs = hbe + mode->hdisplay; | ||
2112 | |||
2113 | value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff); | ||
2114 | tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe)); | ||
2115 | |||
2116 | tegra_sor_writel(sor, 0x1, SOR_HEAD_STATE5(dc->pipe)); | ||
2117 | |||
2118 | tegra_sor_update(sor); | ||
2119 | |||
2120 | err = tegra_sor_attach(sor); | ||
2121 | if (err < 0) | ||
2122 | dev_err(sor->dev, "failed to attach SOR: %d\n", err); | ||
2123 | |||
2124 | /* enable display to SOR clock and generate HDMI preamble */ | ||
2125 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
2126 | value |= SOR1_ENABLE | SOR1_TIMING_CYA; | ||
2127 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
2128 | |||
2129 | tegra_dc_commit(dc); | ||
2130 | |||
2131 | err = tegra_sor_wakeup(sor); | ||
2132 | if (err < 0) | ||
2133 | dev_err(sor->dev, "failed to wakeup SOR: %d\n", err); | ||
1456 | } | 2134 | } |
1457 | 2135 | ||
1458 | static const struct drm_encoder_helper_funcs tegra_sor_encoder_helper_funcs = { | 2136 | static const struct drm_encoder_helper_funcs tegra_sor_hdmi_helpers = { |
1459 | .dpms = tegra_sor_encoder_dpms, | 2137 | .disable = tegra_sor_hdmi_disable, |
1460 | .prepare = tegra_sor_encoder_prepare, | 2138 | .enable = tegra_sor_hdmi_enable, |
1461 | .commit = tegra_sor_encoder_commit, | ||
1462 | .mode_set = tegra_sor_encoder_mode_set, | ||
1463 | .disable = tegra_sor_encoder_disable, | ||
1464 | .atomic_check = tegra_sor_encoder_atomic_check, | 2139 | .atomic_check = tegra_sor_encoder_atomic_check, |
1465 | }; | 2140 | }; |
1466 | 2141 | ||
1467 | static int tegra_sor_init(struct host1x_client *client) | 2142 | static int tegra_sor_init(struct host1x_client *client) |
1468 | { | 2143 | { |
1469 | struct drm_device *drm = dev_get_drvdata(client->parent); | 2144 | struct drm_device *drm = dev_get_drvdata(client->parent); |
2145 | const struct drm_encoder_helper_funcs *helpers = NULL; | ||
1470 | struct tegra_sor *sor = host1x_client_to_sor(client); | 2146 | struct tegra_sor *sor = host1x_client_to_sor(client); |
2147 | int connector = DRM_MODE_CONNECTOR_Unknown; | ||
2148 | int encoder = DRM_MODE_ENCODER_NONE; | ||
1471 | int err; | 2149 | int err; |
1472 | 2150 | ||
1473 | if (!sor->dpaux) | 2151 | if (!sor->dpaux) { |
1474 | return -ENODEV; | 2152 | if (sor->soc->supports_hdmi) { |
2153 | connector = DRM_MODE_CONNECTOR_HDMIA; | ||
2154 | encoder = DRM_MODE_ENCODER_TMDS; | ||
2155 | helpers = &tegra_sor_hdmi_helpers; | ||
2156 | } else if (sor->soc->supports_lvds) { | ||
2157 | connector = DRM_MODE_CONNECTOR_LVDS; | ||
2158 | encoder = DRM_MODE_ENCODER_LVDS; | ||
2159 | } | ||
2160 | } else { | ||
2161 | if (sor->soc->supports_edp) { | ||
2162 | connector = DRM_MODE_CONNECTOR_eDP; | ||
2163 | encoder = DRM_MODE_ENCODER_TMDS; | ||
2164 | helpers = &tegra_sor_edp_helpers; | ||
2165 | } else if (sor->soc->supports_dp) { | ||
2166 | connector = DRM_MODE_CONNECTOR_DisplayPort; | ||
2167 | encoder = DRM_MODE_ENCODER_TMDS; | ||
2168 | } | ||
2169 | } | ||
1475 | 2170 | ||
1476 | sor->output.dev = sor->dev; | 2171 | sor->output.dev = sor->dev; |
1477 | 2172 | ||
1478 | drm_connector_init(drm, &sor->output.connector, | 2173 | drm_connector_init(drm, &sor->output.connector, |
1479 | &tegra_sor_connector_funcs, | 2174 | &tegra_sor_connector_funcs, |
1480 | DRM_MODE_CONNECTOR_eDP); | 2175 | connector); |
1481 | drm_connector_helper_add(&sor->output.connector, | 2176 | drm_connector_helper_add(&sor->output.connector, |
1482 | &tegra_sor_connector_helper_funcs); | 2177 | &tegra_sor_connector_helper_funcs); |
1483 | sor->output.connector.dpms = DRM_MODE_DPMS_OFF; | 2178 | sor->output.connector.dpms = DRM_MODE_DPMS_OFF; |
1484 | 2179 | ||
1485 | drm_encoder_init(drm, &sor->output.encoder, &tegra_sor_encoder_funcs, | 2180 | drm_encoder_init(drm, &sor->output.encoder, &tegra_sor_encoder_funcs, |
1486 | DRM_MODE_ENCODER_TMDS); | 2181 | encoder); |
1487 | drm_encoder_helper_add(&sor->output.encoder, | 2182 | drm_encoder_helper_add(&sor->output.encoder, helpers); |
1488 | &tegra_sor_encoder_helper_funcs); | ||
1489 | 2183 | ||
1490 | drm_mode_connector_attach_encoder(&sor->output.connector, | 2184 | drm_mode_connector_attach_encoder(&sor->output.connector, |
1491 | &sor->output.encoder); | 2185 | &sor->output.encoder); |
@@ -1578,18 +2272,130 @@ static const struct host1x_client_ops sor_client_ops = { | |||
1578 | .exit = tegra_sor_exit, | 2272 | .exit = tegra_sor_exit, |
1579 | }; | 2273 | }; |
1580 | 2274 | ||
2275 | static const struct tegra_sor_ops tegra_sor_edp_ops = { | ||
2276 | .name = "eDP", | ||
2277 | }; | ||
2278 | |||
2279 | static int tegra_sor_hdmi_probe(struct tegra_sor *sor) | ||
2280 | { | ||
2281 | int err; | ||
2282 | |||
2283 | sor->avdd_io_supply = devm_regulator_get(sor->dev, "avdd-io"); | ||
2284 | if (IS_ERR(sor->avdd_io_supply)) { | ||
2285 | dev_err(sor->dev, "cannot get AVDD I/O supply: %ld\n", | ||
2286 | PTR_ERR(sor->avdd_io_supply)); | ||
2287 | return PTR_ERR(sor->avdd_io_supply); | ||
2288 | } | ||
2289 | |||
2290 | err = regulator_enable(sor->avdd_io_supply); | ||
2291 | if (err < 0) { | ||
2292 | dev_err(sor->dev, "failed to enable AVDD I/O supply: %d\n", | ||
2293 | err); | ||
2294 | return err; | ||
2295 | } | ||
2296 | |||
2297 | sor->vdd_pll_supply = devm_regulator_get(sor->dev, "vdd-pll"); | ||
2298 | if (IS_ERR(sor->vdd_pll_supply)) { | ||
2299 | dev_err(sor->dev, "cannot get VDD PLL supply: %ld\n", | ||
2300 | PTR_ERR(sor->vdd_pll_supply)); | ||
2301 | return PTR_ERR(sor->vdd_pll_supply); | ||
2302 | } | ||
2303 | |||
2304 | err = regulator_enable(sor->vdd_pll_supply); | ||
2305 | if (err < 0) { | ||
2306 | dev_err(sor->dev, "failed to enable VDD PLL supply: %d\n", | ||
2307 | err); | ||
2308 | return err; | ||
2309 | } | ||
2310 | |||
2311 | sor->hdmi_supply = devm_regulator_get(sor->dev, "hdmi"); | ||
2312 | if (IS_ERR(sor->hdmi_supply)) { | ||
2313 | dev_err(sor->dev, "cannot get HDMI supply: %ld\n", | ||
2314 | PTR_ERR(sor->hdmi_supply)); | ||
2315 | return PTR_ERR(sor->hdmi_supply); | ||
2316 | } | ||
2317 | |||
2318 | err = regulator_enable(sor->hdmi_supply); | ||
2319 | if (err < 0) { | ||
2320 | dev_err(sor->dev, "failed to enable HDMI supply: %d\n", err); | ||
2321 | return err; | ||
2322 | } | ||
2323 | |||
2324 | return 0; | ||
2325 | } | ||
2326 | |||
2327 | static int tegra_sor_hdmi_remove(struct tegra_sor *sor) | ||
2328 | { | ||
2329 | regulator_disable(sor->hdmi_supply); | ||
2330 | regulator_disable(sor->vdd_pll_supply); | ||
2331 | regulator_disable(sor->avdd_io_supply); | ||
2332 | |||
2333 | return 0; | ||
2334 | } | ||
2335 | |||
2336 | static const struct tegra_sor_ops tegra_sor_hdmi_ops = { | ||
2337 | .name = "HDMI", | ||
2338 | .probe = tegra_sor_hdmi_probe, | ||
2339 | .remove = tegra_sor_hdmi_remove, | ||
2340 | }; | ||
2341 | |||
2342 | static const struct tegra_sor_soc tegra124_sor = { | ||
2343 | .supports_edp = true, | ||
2344 | .supports_lvds = true, | ||
2345 | .supports_hdmi = false, | ||
2346 | .supports_dp = false, | ||
2347 | }; | ||
2348 | |||
2349 | static const struct tegra_sor_soc tegra210_sor = { | ||
2350 | .supports_edp = true, | ||
2351 | .supports_lvds = false, | ||
2352 | .supports_hdmi = false, | ||
2353 | .supports_dp = false, | ||
2354 | }; | ||
2355 | |||
2356 | static const struct tegra_sor_soc tegra210_sor1 = { | ||
2357 | .supports_edp = false, | ||
2358 | .supports_lvds = false, | ||
2359 | .supports_hdmi = true, | ||
2360 | .supports_dp = true, | ||
2361 | |||
2362 | .num_settings = ARRAY_SIZE(tegra210_sor_hdmi_defaults), | ||
2363 | .settings = tegra210_sor_hdmi_defaults, | ||
2364 | }; | ||
2365 | |||
2366 | static const struct of_device_id tegra_sor_of_match[] = { | ||
2367 | { .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 }, | ||
2368 | { .compatible = "nvidia,tegra210-sor", .data = &tegra210_sor }, | ||
2369 | { .compatible = "nvidia,tegra124-sor", .data = &tegra124_sor }, | ||
2370 | { }, | ||
2371 | }; | ||
2372 | MODULE_DEVICE_TABLE(of, tegra_sor_of_match); | ||
2373 | |||
1581 | static int tegra_sor_probe(struct platform_device *pdev) | 2374 | static int tegra_sor_probe(struct platform_device *pdev) |
1582 | { | 2375 | { |
2376 | const struct of_device_id *match; | ||
1583 | struct device_node *np; | 2377 | struct device_node *np; |
1584 | struct tegra_sor *sor; | 2378 | struct tegra_sor *sor; |
1585 | struct resource *regs; | 2379 | struct resource *regs; |
1586 | int err; | 2380 | int err; |
1587 | 2381 | ||
2382 | match = of_match_device(tegra_sor_of_match, &pdev->dev); | ||
2383 | |||
1588 | sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL); | 2384 | sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL); |
1589 | if (!sor) | 2385 | if (!sor) |
1590 | return -ENOMEM; | 2386 | return -ENOMEM; |
1591 | 2387 | ||
1592 | sor->output.dev = sor->dev = &pdev->dev; | 2388 | sor->output.dev = sor->dev = &pdev->dev; |
2389 | sor->soc = match->data; | ||
2390 | |||
2391 | sor->settings = devm_kmemdup(&pdev->dev, sor->soc->settings, | ||
2392 | sor->soc->num_settings * | ||
2393 | sizeof(*sor->settings), | ||
2394 | GFP_KERNEL); | ||
2395 | if (!sor->settings) | ||
2396 | return -ENOMEM; | ||
2397 | |||
2398 | sor->num_settings = sor->soc->num_settings; | ||
1593 | 2399 | ||
1594 | np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0); | 2400 | np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0); |
1595 | if (np) { | 2401 | if (np) { |
@@ -1600,51 +2406,106 @@ static int tegra_sor_probe(struct platform_device *pdev) | |||
1600 | return -EPROBE_DEFER; | 2406 | return -EPROBE_DEFER; |
1601 | } | 2407 | } |
1602 | 2408 | ||
2409 | if (!sor->dpaux) { | ||
2410 | if (sor->soc->supports_hdmi) { | ||
2411 | sor->ops = &tegra_sor_hdmi_ops; | ||
2412 | } else if (sor->soc->supports_lvds) { | ||
2413 | dev_err(&pdev->dev, "LVDS not supported yet\n"); | ||
2414 | return -ENODEV; | ||
2415 | } else { | ||
2416 | dev_err(&pdev->dev, "unknown (non-DP) support\n"); | ||
2417 | return -ENODEV; | ||
2418 | } | ||
2419 | } else { | ||
2420 | if (sor->soc->supports_edp) { | ||
2421 | sor->ops = &tegra_sor_edp_ops; | ||
2422 | } else if (sor->soc->supports_dp) { | ||
2423 | dev_err(&pdev->dev, "DisplayPort not supported yet\n"); | ||
2424 | return -ENODEV; | ||
2425 | } else { | ||
2426 | dev_err(&pdev->dev, "unknown (DP) support\n"); | ||
2427 | return -ENODEV; | ||
2428 | } | ||
2429 | } | ||
2430 | |||
1603 | err = tegra_output_probe(&sor->output); | 2431 | err = tegra_output_probe(&sor->output); |
1604 | if (err < 0) | 2432 | if (err < 0) { |
2433 | dev_err(&pdev->dev, "failed to probe output: %d\n", err); | ||
1605 | return err; | 2434 | return err; |
2435 | } | ||
2436 | |||
2437 | if (sor->ops && sor->ops->probe) { | ||
2438 | err = sor->ops->probe(sor); | ||
2439 | if (err < 0) { | ||
2440 | dev_err(&pdev->dev, "failed to probe %s: %d\n", | ||
2441 | sor->ops->name, err); | ||
2442 | goto output; | ||
2443 | } | ||
2444 | } | ||
1606 | 2445 | ||
1607 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2446 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1608 | sor->regs = devm_ioremap_resource(&pdev->dev, regs); | 2447 | sor->regs = devm_ioremap_resource(&pdev->dev, regs); |
1609 | if (IS_ERR(sor->regs)) | 2448 | if (IS_ERR(sor->regs)) { |
1610 | return PTR_ERR(sor->regs); | 2449 | err = PTR_ERR(sor->regs); |
2450 | goto remove; | ||
2451 | } | ||
1611 | 2452 | ||
1612 | sor->rst = devm_reset_control_get(&pdev->dev, "sor"); | 2453 | sor->rst = devm_reset_control_get(&pdev->dev, "sor"); |
1613 | if (IS_ERR(sor->rst)) | 2454 | if (IS_ERR(sor->rst)) { |
1614 | return PTR_ERR(sor->rst); | 2455 | err = PTR_ERR(sor->rst); |
2456 | dev_err(&pdev->dev, "failed to get reset control: %d\n", err); | ||
2457 | goto remove; | ||
2458 | } | ||
1615 | 2459 | ||
1616 | sor->clk = devm_clk_get(&pdev->dev, NULL); | 2460 | sor->clk = devm_clk_get(&pdev->dev, NULL); |
1617 | if (IS_ERR(sor->clk)) | 2461 | if (IS_ERR(sor->clk)) { |
1618 | return PTR_ERR(sor->clk); | 2462 | err = PTR_ERR(sor->clk); |
2463 | dev_err(&pdev->dev, "failed to get module clock: %d\n", err); | ||
2464 | goto remove; | ||
2465 | } | ||
1619 | 2466 | ||
1620 | sor->clk_parent = devm_clk_get(&pdev->dev, "parent"); | 2467 | sor->clk_parent = devm_clk_get(&pdev->dev, "parent"); |
1621 | if (IS_ERR(sor->clk_parent)) | 2468 | if (IS_ERR(sor->clk_parent)) { |
1622 | return PTR_ERR(sor->clk_parent); | 2469 | err = PTR_ERR(sor->clk_parent); |
2470 | dev_err(&pdev->dev, "failed to get parent clock: %d\n", err); | ||
2471 | goto remove; | ||
2472 | } | ||
1623 | 2473 | ||
1624 | sor->clk_safe = devm_clk_get(&pdev->dev, "safe"); | 2474 | sor->clk_safe = devm_clk_get(&pdev->dev, "safe"); |
1625 | if (IS_ERR(sor->clk_safe)) | 2475 | if (IS_ERR(sor->clk_safe)) { |
1626 | return PTR_ERR(sor->clk_safe); | 2476 | err = PTR_ERR(sor->clk_safe); |
2477 | dev_err(&pdev->dev, "failed to get safe clock: %d\n", err); | ||
2478 | goto remove; | ||
2479 | } | ||
1627 | 2480 | ||
1628 | sor->clk_dp = devm_clk_get(&pdev->dev, "dp"); | 2481 | sor->clk_dp = devm_clk_get(&pdev->dev, "dp"); |
1629 | if (IS_ERR(sor->clk_dp)) | 2482 | if (IS_ERR(sor->clk_dp)) { |
1630 | return PTR_ERR(sor->clk_dp); | 2483 | err = PTR_ERR(sor->clk_dp); |
2484 | dev_err(&pdev->dev, "failed to get DP clock: %d\n", err); | ||
2485 | goto remove; | ||
2486 | } | ||
1631 | 2487 | ||
1632 | INIT_LIST_HEAD(&sor->client.list); | 2488 | INIT_LIST_HEAD(&sor->client.list); |
1633 | sor->client.ops = &sor_client_ops; | 2489 | sor->client.ops = &sor_client_ops; |
1634 | sor->client.dev = &pdev->dev; | 2490 | sor->client.dev = &pdev->dev; |
1635 | 2491 | ||
1636 | mutex_init(&sor->lock); | ||
1637 | |||
1638 | err = host1x_client_register(&sor->client); | 2492 | err = host1x_client_register(&sor->client); |
1639 | if (err < 0) { | 2493 | if (err < 0) { |
1640 | dev_err(&pdev->dev, "failed to register host1x client: %d\n", | 2494 | dev_err(&pdev->dev, "failed to register host1x client: %d\n", |
1641 | err); | 2495 | err); |
1642 | return err; | 2496 | goto remove; |
1643 | } | 2497 | } |
1644 | 2498 | ||
1645 | platform_set_drvdata(pdev, sor); | 2499 | platform_set_drvdata(pdev, sor); |
1646 | 2500 | ||
1647 | return 0; | 2501 | return 0; |
2502 | |||
2503 | remove: | ||
2504 | if (sor->ops && sor->ops->remove) | ||
2505 | sor->ops->remove(sor); | ||
2506 | output: | ||
2507 | tegra_output_remove(&sor->output); | ||
2508 | return err; | ||
1648 | } | 2509 | } |
1649 | 2510 | ||
1650 | static int tegra_sor_remove(struct platform_device *pdev) | 2511 | static int tegra_sor_remove(struct platform_device *pdev) |
@@ -1659,17 +2520,17 @@ static int tegra_sor_remove(struct platform_device *pdev) | |||
1659 | return err; | 2520 | return err; |
1660 | } | 2521 | } |
1661 | 2522 | ||
2523 | if (sor->ops && sor->ops->remove) { | ||
2524 | err = sor->ops->remove(sor); | ||
2525 | if (err < 0) | ||
2526 | dev_err(&pdev->dev, "failed to remove SOR: %d\n", err); | ||
2527 | } | ||
2528 | |||
1662 | tegra_output_remove(&sor->output); | 2529 | tegra_output_remove(&sor->output); |
1663 | 2530 | ||
1664 | return 0; | 2531 | return 0; |
1665 | } | 2532 | } |
1666 | 2533 | ||
1667 | static const struct of_device_id tegra_sor_of_match[] = { | ||
1668 | { .compatible = "nvidia,tegra124-sor", }, | ||
1669 | { }, | ||
1670 | }; | ||
1671 | MODULE_DEVICE_TABLE(of, tegra_sor_of_match); | ||
1672 | |||
1673 | struct platform_driver tegra_sor_driver = { | 2534 | struct platform_driver tegra_sor_driver = { |
1674 | .driver = { | 2535 | .driver = { |
1675 | .name = "tegra-sor", | 2536 | .name = "tegra-sor", |
diff --git a/drivers/gpu/drm/tegra/sor.h b/drivers/gpu/drm/tegra/sor.h index a5f8853fedb5..2d31d027e3f6 100644 --- a/drivers/gpu/drm/tegra/sor.h +++ b/drivers/gpu/drm/tegra/sor.h | |||
@@ -11,9 +11,9 @@ | |||
11 | 11 | ||
12 | #define SOR_CTXSW 0x00 | 12 | #define SOR_CTXSW 0x00 |
13 | 13 | ||
14 | #define SOR_SUPER_STATE_0 0x01 | 14 | #define SOR_SUPER_STATE0 0x01 |
15 | 15 | ||
16 | #define SOR_SUPER_STATE_1 0x02 | 16 | #define SOR_SUPER_STATE1 0x02 |
17 | #define SOR_SUPER_STATE_ATTACHED (1 << 3) | 17 | #define SOR_SUPER_STATE_ATTACHED (1 << 3) |
18 | #define SOR_SUPER_STATE_MODE_NORMAL (1 << 2) | 18 | #define SOR_SUPER_STATE_MODE_NORMAL (1 << 2) |
19 | #define SOR_SUPER_STATE_HEAD_MODE_MASK (3 << 0) | 19 | #define SOR_SUPER_STATE_HEAD_MODE_MASK (3 << 0) |
@@ -21,9 +21,9 @@ | |||
21 | #define SOR_SUPER_STATE_HEAD_MODE_SNOOZE (1 << 0) | 21 | #define SOR_SUPER_STATE_HEAD_MODE_SNOOZE (1 << 0) |
22 | #define SOR_SUPER_STATE_HEAD_MODE_SLEEP (0 << 0) | 22 | #define SOR_SUPER_STATE_HEAD_MODE_SLEEP (0 << 0) |
23 | 23 | ||
24 | #define SOR_STATE_0 0x03 | 24 | #define SOR_STATE0 0x03 |
25 | 25 | ||
26 | #define SOR_STATE_1 0x04 | 26 | #define SOR_STATE1 0x04 |
27 | #define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17) | 27 | #define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17) |
28 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17) | 28 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17) |
29 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17) | 29 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17) |
@@ -33,19 +33,27 @@ | |||
33 | #define SOR_STATE_ASY_PROTOCOL_CUSTOM (0xf << 8) | 33 | #define SOR_STATE_ASY_PROTOCOL_CUSTOM (0xf << 8) |
34 | #define SOR_STATE_ASY_PROTOCOL_DP_A (0x8 << 8) | 34 | #define SOR_STATE_ASY_PROTOCOL_DP_A (0x8 << 8) |
35 | #define SOR_STATE_ASY_PROTOCOL_DP_B (0x9 << 8) | 35 | #define SOR_STATE_ASY_PROTOCOL_DP_B (0x9 << 8) |
36 | #define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (0x1 << 8) | ||
36 | #define SOR_STATE_ASY_PROTOCOL_LVDS (0x0 << 8) | 37 | #define SOR_STATE_ASY_PROTOCOL_LVDS (0x0 << 8) |
37 | #define SOR_STATE_ASY_CRC_MODE_MASK (0x3 << 6) | 38 | #define SOR_STATE_ASY_CRC_MODE_MASK (0x3 << 6) |
38 | #define SOR_STATE_ASY_CRC_MODE_NON_ACTIVE (0x2 << 6) | 39 | #define SOR_STATE_ASY_CRC_MODE_NON_ACTIVE (0x2 << 6) |
39 | #define SOR_STATE_ASY_CRC_MODE_COMPLETE (0x1 << 6) | 40 | #define SOR_STATE_ASY_CRC_MODE_COMPLETE (0x1 << 6) |
40 | #define SOR_STATE_ASY_CRC_MODE_ACTIVE (0x0 << 6) | 41 | #define SOR_STATE_ASY_CRC_MODE_ACTIVE (0x0 << 6) |
42 | #define SOR_STATE_ASY_OWNER_MASK 0xf | ||
41 | #define SOR_STATE_ASY_OWNER(x) (((x) & 0xf) << 0) | 43 | #define SOR_STATE_ASY_OWNER(x) (((x) & 0xf) << 0) |
42 | 44 | ||
43 | #define SOR_HEAD_STATE_0(x) (0x05 + (x)) | 45 | #define SOR_HEAD_STATE0(x) (0x05 + (x)) |
44 | #define SOR_HEAD_STATE_1(x) (0x07 + (x)) | 46 | #define SOR_HEAD_STATE_RANGECOMPRESS_MASK (0x1 << 3) |
45 | #define SOR_HEAD_STATE_2(x) (0x09 + (x)) | 47 | #define SOR_HEAD_STATE_DYNRANGE_MASK (0x1 << 2) |
46 | #define SOR_HEAD_STATE_3(x) (0x0b + (x)) | 48 | #define SOR_HEAD_STATE_DYNRANGE_VESA (0 << 2) |
47 | #define SOR_HEAD_STATE_4(x) (0x0d + (x)) | 49 | #define SOR_HEAD_STATE_DYNRANGE_CEA (1 << 2) |
48 | #define SOR_HEAD_STATE_5(x) (0x0f + (x)) | 50 | #define SOR_HEAD_STATE_COLORSPACE_MASK (0x3 << 0) |
51 | #define SOR_HEAD_STATE_COLORSPACE_RGB (0 << 0) | ||
52 | #define SOR_HEAD_STATE1(x) (0x07 + (x)) | ||
53 | #define SOR_HEAD_STATE2(x) (0x09 + (x)) | ||
54 | #define SOR_HEAD_STATE3(x) (0x0b + (x)) | ||
55 | #define SOR_HEAD_STATE4(x) (0x0d + (x)) | ||
56 | #define SOR_HEAD_STATE5(x) (0x0f + (x)) | ||
49 | #define SOR_CRC_CNTRL 0x11 | 57 | #define SOR_CRC_CNTRL 0x11 |
50 | #define SOR_CRC_CNTRL_ENABLE (1 << 0) | 58 | #define SOR_CRC_CNTRL_ENABLE (1 << 0) |
51 | #define SOR_DP_DEBUG_MVID 0x12 | 59 | #define SOR_DP_DEBUG_MVID 0x12 |
@@ -75,62 +83,101 @@ | |||
75 | #define SOR_TEST_HEAD_MODE_MASK (3 << 8) | 83 | #define SOR_TEST_HEAD_MODE_MASK (3 << 8) |
76 | #define SOR_TEST_HEAD_MODE_AWAKE (2 << 8) | 84 | #define SOR_TEST_HEAD_MODE_AWAKE (2 << 8) |
77 | 85 | ||
78 | #define SOR_PLL_0 0x17 | 86 | #define SOR_PLL0 0x17 |
79 | #define SOR_PLL_0_ICHPMP_MASK (0xf << 24) | 87 | #define SOR_PLL0_ICHPMP_MASK (0xf << 24) |
80 | #define SOR_PLL_0_ICHPMP(x) (((x) & 0xf) << 24) | 88 | #define SOR_PLL0_ICHPMP(x) (((x) & 0xf) << 24) |
81 | #define SOR_PLL_0_VCOCAP_MASK (0xf << 8) | 89 | #define SOR_PLL0_VCOCAP_MASK (0xf << 8) |
82 | #define SOR_PLL_0_VCOCAP(x) (((x) & 0xf) << 8) | 90 | #define SOR_PLL0_VCOCAP(x) (((x) & 0xf) << 8) |
83 | #define SOR_PLL_0_VCOCAP_RST SOR_PLL_0_VCOCAP(3) | 91 | #define SOR_PLL0_VCOCAP_RST SOR_PLL0_VCOCAP(3) |
84 | #define SOR_PLL_0_PLLREG_MASK (0x3 << 6) | 92 | #define SOR_PLL0_PLLREG_MASK (0x3 << 6) |
85 | #define SOR_PLL_0_PLLREG_LEVEL(x) (((x) & 0x3) << 6) | 93 | #define SOR_PLL0_PLLREG_LEVEL(x) (((x) & 0x3) << 6) |
86 | #define SOR_PLL_0_PLLREG_LEVEL_V25 SOR_PLL_0_PLLREG_LEVEL(0) | 94 | #define SOR_PLL0_PLLREG_LEVEL_V25 SOR_PLL0_PLLREG_LEVEL(0) |
87 | #define SOR_PLL_0_PLLREG_LEVEL_V15 SOR_PLL_0_PLLREG_LEVEL(1) | 95 | #define SOR_PLL0_PLLREG_LEVEL_V15 SOR_PLL0_PLLREG_LEVEL(1) |
88 | #define SOR_PLL_0_PLLREG_LEVEL_V35 SOR_PLL_0_PLLREG_LEVEL(2) | 96 | #define SOR_PLL0_PLLREG_LEVEL_V35 SOR_PLL0_PLLREG_LEVEL(2) |
89 | #define SOR_PLL_0_PLLREG_LEVEL_V45 SOR_PLL_0_PLLREG_LEVEL(3) | 97 | #define SOR_PLL0_PLLREG_LEVEL_V45 SOR_PLL0_PLLREG_LEVEL(3) |
90 | #define SOR_PLL_0_PULLDOWN (1 << 5) | 98 | #define SOR_PLL0_PULLDOWN (1 << 5) |
91 | #define SOR_PLL_0_RESISTOR_EXT (1 << 4) | 99 | #define SOR_PLL0_RESISTOR_EXT (1 << 4) |
92 | #define SOR_PLL_0_VCOPD (1 << 2) | 100 | #define SOR_PLL0_VCOPD (1 << 2) |
93 | #define SOR_PLL_0_POWER_OFF (1 << 0) | 101 | #define SOR_PLL0_PWR (1 << 0) |
94 | 102 | ||
95 | #define SOR_PLL_1 0x18 | 103 | #define SOR_PLL1 0x18 |
96 | /* XXX: read-only bit? */ | 104 | /* XXX: read-only bit? */ |
97 | #define SOR_PLL_1_TERM_COMPOUT (1 << 15) | 105 | #define SOR_PLL1_LOADADJ_MASK (0xf << 20) |
98 | #define SOR_PLL_1_TMDS_TERM (1 << 8) | 106 | #define SOR_PLL1_LOADADJ(x) (((x) & 0xf) << 20) |
99 | 107 | #define SOR_PLL1_TERM_COMPOUT (1 << 15) | |
100 | #define SOR_PLL_2 0x19 | 108 | #define SOR_PLL1_TMDS_TERMADJ_MASK (0xf << 9) |
101 | #define SOR_PLL_2_LVDS_ENABLE (1 << 25) | 109 | #define SOR_PLL1_TMDS_TERMADJ(x) (((x) & 0xf) << 9) |
102 | #define SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE (1 << 24) | 110 | #define SOR_PLL1_TMDS_TERM (1 << 8) |
103 | #define SOR_PLL_2_PORT_POWERDOWN (1 << 23) | 111 | |
104 | #define SOR_PLL_2_BANDGAP_POWERDOWN (1 << 22) | 112 | #define SOR_PLL2 0x19 |
105 | #define SOR_PLL_2_POWERDOWN_OVERRIDE (1 << 18) | 113 | #define SOR_PLL2_LVDS_ENABLE (1 << 25) |
106 | #define SOR_PLL_2_SEQ_PLLCAPPD (1 << 17) | 114 | #define SOR_PLL2_SEQ_PLLCAPPD_ENFORCE (1 << 24) |
107 | 115 | #define SOR_PLL2_PORT_POWERDOWN (1 << 23) | |
108 | #define SOR_PLL_3 0x1a | 116 | #define SOR_PLL2_BANDGAP_POWERDOWN (1 << 22) |
109 | #define SOR_PLL_3_PLL_VDD_MODE_V1_8 (0 << 13) | 117 | #define SOR_PLL2_POWERDOWN_OVERRIDE (1 << 18) |
110 | #define SOR_PLL_3_PLL_VDD_MODE_V3_3 (1 << 13) | 118 | #define SOR_PLL2_SEQ_PLLCAPPD (1 << 17) |
119 | #define SOR_PLL2_SEQ_PLL_PULLDOWN (1 << 16) | ||
120 | |||
121 | #define SOR_PLL3 0x1a | ||
122 | #define SOR_PLL3_BG_VREF_LEVEL_MASK (0xf << 24) | ||
123 | #define SOR_PLL3_BG_VREF_LEVEL(x) (((x) & 0xf) << 24) | ||
124 | #define SOR_PLL3_PLL_VDD_MODE_1V8 (0 << 13) | ||
125 | #define SOR_PLL3_PLL_VDD_MODE_3V3 (1 << 13) | ||
111 | 126 | ||
112 | #define SOR_CSTM 0x1b | 127 | #define SOR_CSTM 0x1b |
128 | #define SOR_CSTM_ROTCLK_MASK (0xf << 24) | ||
129 | #define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24) | ||
113 | #define SOR_CSTM_LVDS (1 << 16) | 130 | #define SOR_CSTM_LVDS (1 << 16) |
114 | #define SOR_CSTM_LINK_ACT_B (1 << 15) | 131 | #define SOR_CSTM_LINK_ACT_B (1 << 15) |
115 | #define SOR_CSTM_LINK_ACT_A (1 << 14) | 132 | #define SOR_CSTM_LINK_ACT_A (1 << 14) |
116 | #define SOR_CSTM_UPPER (1 << 11) | 133 | #define SOR_CSTM_UPPER (1 << 11) |
117 | 134 | ||
118 | #define SOR_LVDS 0x1c | 135 | #define SOR_LVDS 0x1c |
119 | #define SOR_CRC_A 0x1d | 136 | #define SOR_CRCA 0x1d |
120 | #define SOR_CRC_A_VALID (1 << 0) | 137 | #define SOR_CRCA_VALID (1 << 0) |
121 | #define SOR_CRC_A_RESET (1 << 0) | 138 | #define SOR_CRCA_RESET (1 << 0) |
122 | #define SOR_CRC_B 0x1e | 139 | #define SOR_CRCB 0x1e |
123 | #define SOR_BLANK 0x1f | 140 | #define SOR_BLANK 0x1f |
124 | #define SOR_SEQ_CTL 0x20 | 141 | #define SOR_SEQ_CTL 0x20 |
142 | #define SOR_SEQ_CTL_PD_PC_ALT(x) (((x) & 0xf) << 12) | ||
143 | #define SOR_SEQ_CTL_PD_PC(x) (((x) & 0xf) << 8) | ||
144 | #define SOR_SEQ_CTL_PU_PC_ALT(x) (((x) & 0xf) << 4) | ||
145 | #define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) << 0) | ||
125 | 146 | ||
126 | #define SOR_LANE_SEQ_CTL 0x21 | 147 | #define SOR_LANE_SEQ_CTL 0x21 |
127 | #define SOR_LANE_SEQ_CTL_TRIGGER (1 << 31) | 148 | #define SOR_LANE_SEQ_CTL_TRIGGER (1 << 31) |
149 | #define SOR_LANE_SEQ_CTL_STATE_BUSY (1 << 28) | ||
128 | #define SOR_LANE_SEQ_CTL_SEQUENCE_UP (0 << 20) | 150 | #define SOR_LANE_SEQ_CTL_SEQUENCE_UP (0 << 20) |
129 | #define SOR_LANE_SEQ_CTL_SEQUENCE_DOWN (1 << 20) | 151 | #define SOR_LANE_SEQ_CTL_SEQUENCE_DOWN (1 << 20) |
130 | #define SOR_LANE_SEQ_CTL_POWER_STATE_UP (0 << 16) | 152 | #define SOR_LANE_SEQ_CTL_POWER_STATE_UP (0 << 16) |
131 | #define SOR_LANE_SEQ_CTL_POWER_STATE_DOWN (1 << 16) | 153 | #define SOR_LANE_SEQ_CTL_POWER_STATE_DOWN (1 << 16) |
154 | #define SOR_LANE_SEQ_CTL_DELAY(x) (((x) & 0xf) << 12) | ||
132 | 155 | ||
133 | #define SOR_SEQ_INST(x) (0x22 + (x)) | 156 | #define SOR_SEQ_INST(x) (0x22 + (x)) |
157 | #define SOR_SEQ_INST_PLL_PULLDOWN (1 << 31) | ||
158 | #define SOR_SEQ_INST_POWERDOWN_MACRO (1 << 30) | ||
159 | #define SOR_SEQ_INST_ASSERT_PLL_RESET (1 << 29) | ||
160 | #define SOR_SEQ_INST_BLANK_V (1 << 28) | ||
161 | #define SOR_SEQ_INST_BLANK_H (1 << 27) | ||
162 | #define SOR_SEQ_INST_BLANK_DE (1 << 26) | ||
163 | #define SOR_SEQ_INST_BLACK_DATA (1 << 25) | ||
164 | #define SOR_SEQ_INST_TRISTATE_IOS (1 << 24) | ||
165 | #define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23) | ||
166 | #define SOR_SEQ_INST_PIN_B_LOW (0 << 22) | ||
167 | #define SOR_SEQ_INST_PIN_B_HIGH (1 << 22) | ||
168 | #define SOR_SEQ_INST_PIN_A_LOW (0 << 21) | ||
169 | #define SOR_SEQ_INST_PIN_A_HIGH (1 << 21) | ||
170 | #define SOR_SEQ_INST_SEQUENCE_UP (0 << 19) | ||
171 | #define SOR_SEQ_INST_SEQUENCE_DOWN (1 << 19) | ||
172 | #define SOR_SEQ_INST_LANE_SEQ_STOP (0 << 18) | ||
173 | #define SOR_SEQ_INST_LANE_SEQ_RUN (1 << 18) | ||
174 | #define SOR_SEQ_INST_PORT_POWERDOWN (1 << 17) | ||
175 | #define SOR_SEQ_INST_PLL_POWERDOWN (1 << 16) | ||
176 | #define SOR_SEQ_INST_HALT (1 << 15) | ||
177 | #define SOR_SEQ_INST_WAIT_US (0 << 12) | ||
178 | #define SOR_SEQ_INST_WAIT_MS (1 << 12) | ||
179 | #define SOR_SEQ_INST_WAIT_VSYNC (2 << 12) | ||
180 | #define SOR_SEQ_INST_WAIT(x) (((x) & 0x3ff) << 0) | ||
134 | 181 | ||
135 | #define SOR_PWM_DIV 0x32 | 182 | #define SOR_PWM_DIV 0x32 |
136 | #define SOR_PWM_DIV_MASK 0xffffff | 183 | #define SOR_PWM_DIV_MASK 0xffffff |
@@ -140,32 +187,36 @@ | |||
140 | #define SOR_PWM_CTL_CLK_SEL (1 << 30) | 187 | #define SOR_PWM_CTL_CLK_SEL (1 << 30) |
141 | #define SOR_PWM_CTL_DUTY_CYCLE_MASK 0xffffff | 188 | #define SOR_PWM_CTL_DUTY_CYCLE_MASK 0xffffff |
142 | 189 | ||
143 | #define SOR_VCRC_A_0 0x34 | 190 | #define SOR_VCRC_A0 0x34 |
144 | #define SOR_VCRC_A_1 0x35 | 191 | #define SOR_VCRC_A1 0x35 |
145 | #define SOR_VCRC_B_0 0x36 | 192 | #define SOR_VCRC_B0 0x36 |
146 | #define SOR_VCRC_B_1 0x37 | 193 | #define SOR_VCRC_B1 0x37 |
147 | #define SOR_CCRC_A_0 0x38 | 194 | #define SOR_CCRC_A0 0x38 |
148 | #define SOR_CCRC_A_1 0x39 | 195 | #define SOR_CCRC_A1 0x39 |
149 | #define SOR_CCRC_B_0 0x3a | 196 | #define SOR_CCRC_B0 0x3a |
150 | #define SOR_CCRC_B_1 0x3b | 197 | #define SOR_CCRC_B1 0x3b |
151 | #define SOR_EDATA_A_0 0x3c | 198 | #define SOR_EDATA_A0 0x3c |
152 | #define SOR_EDATA_A_1 0x3d | 199 | #define SOR_EDATA_A1 0x3d |
153 | #define SOR_EDATA_B_0 0x3e | 200 | #define SOR_EDATA_B0 0x3e |
154 | #define SOR_EDATA_B_1 0x3f | 201 | #define SOR_EDATA_B1 0x3f |
155 | #define SOR_COUNT_A_0 0x40 | 202 | #define SOR_COUNT_A0 0x40 |
156 | #define SOR_COUNT_A_1 0x41 | 203 | #define SOR_COUNT_A1 0x41 |
157 | #define SOR_COUNT_B_0 0x42 | 204 | #define SOR_COUNT_B0 0x42 |
158 | #define SOR_COUNT_B_1 0x43 | 205 | #define SOR_COUNT_B1 0x43 |
159 | #define SOR_DEBUG_A_0 0x44 | 206 | #define SOR_DEBUG_A0 0x44 |
160 | #define SOR_DEBUG_A_1 0x45 | 207 | #define SOR_DEBUG_A1 0x45 |
161 | #define SOR_DEBUG_B_0 0x46 | 208 | #define SOR_DEBUG_B0 0x46 |
162 | #define SOR_DEBUG_B_1 0x47 | 209 | #define SOR_DEBUG_B1 0x47 |
163 | #define SOR_TRIG 0x48 | 210 | #define SOR_TRIG 0x48 |
164 | #define SOR_MSCHECK 0x49 | 211 | #define SOR_MSCHECK 0x49 |
165 | #define SOR_XBAR_CTRL 0x4a | 212 | #define SOR_XBAR_CTRL 0x4a |
213 | #define SOR_XBAR_CTRL_LINK1_XSEL(channel, value) ((((value) & 0x7) << ((channel) * 3)) << 17) | ||
214 | #define SOR_XBAR_CTRL_LINK0_XSEL(channel, value) ((((value) & 0x7) << ((channel) * 3)) << 2) | ||
215 | #define SOR_XBAR_CTRL_LINK_SWAP (1 << 1) | ||
216 | #define SOR_XBAR_CTRL_BYPASS (1 << 0) | ||
166 | #define SOR_XBAR_POL 0x4b | 217 | #define SOR_XBAR_POL 0x4b |
167 | 218 | ||
168 | #define SOR_DP_LINKCTL_0 0x4c | 219 | #define SOR_DP_LINKCTL0 0x4c |
169 | #define SOR_DP_LINKCTL_LANE_COUNT_MASK (0x1f << 16) | 220 | #define SOR_DP_LINKCTL_LANE_COUNT_MASK (0x1f << 16) |
170 | #define SOR_DP_LINKCTL_LANE_COUNT(x) (((1 << (x)) - 1) << 16) | 221 | #define SOR_DP_LINKCTL_LANE_COUNT(x) (((1 << (x)) - 1) << 16) |
171 | #define SOR_DP_LINKCTL_ENHANCED_FRAME (1 << 14) | 222 | #define SOR_DP_LINKCTL_ENHANCED_FRAME (1 << 14) |
@@ -173,34 +224,34 @@ | |||
173 | #define SOR_DP_LINKCTL_TU_SIZE(x) (((x) & 0x7f) << 2) | 224 | #define SOR_DP_LINKCTL_TU_SIZE(x) (((x) & 0x7f) << 2) |
174 | #define SOR_DP_LINKCTL_ENABLE (1 << 0) | 225 | #define SOR_DP_LINKCTL_ENABLE (1 << 0) |
175 | 226 | ||
176 | #define SOR_DP_LINKCTL_1 0x4d | 227 | #define SOR_DP_LINKCTL1 0x4d |
177 | 228 | ||
178 | #define SOR_LANE_DRIVE_CURRENT_0 0x4e | 229 | #define SOR_LANE_DRIVE_CURRENT0 0x4e |
179 | #define SOR_LANE_DRIVE_CURRENT_1 0x4f | 230 | #define SOR_LANE_DRIVE_CURRENT1 0x4f |
180 | #define SOR_LANE4_DRIVE_CURRENT_0 0x50 | 231 | #define SOR_LANE4_DRIVE_CURRENT0 0x50 |
181 | #define SOR_LANE4_DRIVE_CURRENT_1 0x51 | 232 | #define SOR_LANE4_DRIVE_CURRENT1 0x51 |
182 | #define SOR_LANE_DRIVE_CURRENT_LANE3(x) (((x) & 0xff) << 24) | 233 | #define SOR_LANE_DRIVE_CURRENT_LANE3(x) (((x) & 0xff) << 24) |
183 | #define SOR_LANE_DRIVE_CURRENT_LANE2(x) (((x) & 0xff) << 16) | 234 | #define SOR_LANE_DRIVE_CURRENT_LANE2(x) (((x) & 0xff) << 16) |
184 | #define SOR_LANE_DRIVE_CURRENT_LANE1(x) (((x) & 0xff) << 8) | 235 | #define SOR_LANE_DRIVE_CURRENT_LANE1(x) (((x) & 0xff) << 8) |
185 | #define SOR_LANE_DRIVE_CURRENT_LANE0(x) (((x) & 0xff) << 0) | 236 | #define SOR_LANE_DRIVE_CURRENT_LANE0(x) (((x) & 0xff) << 0) |
186 | 237 | ||
187 | #define SOR_LANE_PREEMPHASIS_0 0x52 | 238 | #define SOR_LANE_PREEMPHASIS0 0x52 |
188 | #define SOR_LANE_PREEMPHASIS_1 0x53 | 239 | #define SOR_LANE_PREEMPHASIS1 0x53 |
189 | #define SOR_LANE4_PREEMPHASIS_0 0x54 | 240 | #define SOR_LANE4_PREEMPHASIS0 0x54 |
190 | #define SOR_LANE4_PREEMPHASIS_1 0x55 | 241 | #define SOR_LANE4_PREEMPHASIS1 0x55 |
191 | #define SOR_LANE_PREEMPHASIS_LANE3(x) (((x) & 0xff) << 24) | 242 | #define SOR_LANE_PREEMPHASIS_LANE3(x) (((x) & 0xff) << 24) |
192 | #define SOR_LANE_PREEMPHASIS_LANE2(x) (((x) & 0xff) << 16) | 243 | #define SOR_LANE_PREEMPHASIS_LANE2(x) (((x) & 0xff) << 16) |
193 | #define SOR_LANE_PREEMPHASIS_LANE1(x) (((x) & 0xff) << 8) | 244 | #define SOR_LANE_PREEMPHASIS_LANE1(x) (((x) & 0xff) << 8) |
194 | #define SOR_LANE_PREEMPHASIS_LANE0(x) (((x) & 0xff) << 0) | 245 | #define SOR_LANE_PREEMPHASIS_LANE0(x) (((x) & 0xff) << 0) |
195 | 246 | ||
196 | #define SOR_LANE_POST_CURSOR_0 0x56 | 247 | #define SOR_LANE_POSTCURSOR0 0x56 |
197 | #define SOR_LANE_POST_CURSOR_1 0x57 | 248 | #define SOR_LANE_POSTCURSOR1 0x57 |
198 | #define SOR_LANE_POST_CURSOR_LANE3(x) (((x) & 0xff) << 24) | 249 | #define SOR_LANE_POSTCURSOR_LANE3(x) (((x) & 0xff) << 24) |
199 | #define SOR_LANE_POST_CURSOR_LANE2(x) (((x) & 0xff) << 16) | 250 | #define SOR_LANE_POSTCURSOR_LANE2(x) (((x) & 0xff) << 16) |
200 | #define SOR_LANE_POST_CURSOR_LANE1(x) (((x) & 0xff) << 8) | 251 | #define SOR_LANE_POSTCURSOR_LANE1(x) (((x) & 0xff) << 8) |
201 | #define SOR_LANE_POST_CURSOR_LANE0(x) (((x) & 0xff) << 0) | 252 | #define SOR_LANE_POSTCURSOR_LANE0(x) (((x) & 0xff) << 0) |
202 | 253 | ||
203 | #define SOR_DP_CONFIG_0 0x58 | 254 | #define SOR_DP_CONFIG0 0x58 |
204 | #define SOR_DP_CONFIG_DISPARITY_NEGATIVE (1 << 31) | 255 | #define SOR_DP_CONFIG_DISPARITY_NEGATIVE (1 << 31) |
205 | #define SOR_DP_CONFIG_ACTIVE_SYM_ENABLE (1 << 26) | 256 | #define SOR_DP_CONFIG_ACTIVE_SYM_ENABLE (1 << 26) |
206 | #define SOR_DP_CONFIG_ACTIVE_SYM_POLARITY (1 << 24) | 257 | #define SOR_DP_CONFIG_ACTIVE_SYM_POLARITY (1 << 24) |
@@ -211,11 +262,11 @@ | |||
211 | #define SOR_DP_CONFIG_WATERMARK_MASK (0x3f << 0) | 262 | #define SOR_DP_CONFIG_WATERMARK_MASK (0x3f << 0) |
212 | #define SOR_DP_CONFIG_WATERMARK(x) (((x) & 0x3f) << 0) | 263 | #define SOR_DP_CONFIG_WATERMARK(x) (((x) & 0x3f) << 0) |
213 | 264 | ||
214 | #define SOR_DP_CONFIG_1 0x59 | 265 | #define SOR_DP_CONFIG1 0x59 |
215 | #define SOR_DP_MN_0 0x5a | 266 | #define SOR_DP_MN0 0x5a |
216 | #define SOR_DP_MN_1 0x5b | 267 | #define SOR_DP_MN1 0x5b |
217 | 268 | ||
218 | #define SOR_DP_PADCTL_0 0x5c | 269 | #define SOR_DP_PADCTL0 0x5c |
219 | #define SOR_DP_PADCTL_PAD_CAL_PD (1 << 23) | 270 | #define SOR_DP_PADCTL_PAD_CAL_PD (1 << 23) |
220 | #define SOR_DP_PADCTL_TX_PU_ENABLE (1 << 22) | 271 | #define SOR_DP_PADCTL_TX_PU_ENABLE (1 << 22) |
221 | #define SOR_DP_PADCTL_TX_PU_MASK (0xff << 8) | 272 | #define SOR_DP_PADCTL_TX_PU_MASK (0xff << 8) |
@@ -229,17 +280,18 @@ | |||
229 | #define SOR_DP_PADCTL_PD_TXD_1 (1 << 1) | 280 | #define SOR_DP_PADCTL_PD_TXD_1 (1 << 1) |
230 | #define SOR_DP_PADCTL_PD_TXD_2 (1 << 0) | 281 | #define SOR_DP_PADCTL_PD_TXD_2 (1 << 0) |
231 | 282 | ||
232 | #define SOR_DP_PADCTL_1 0x5d | 283 | #define SOR_DP_PADCTL1 0x5d |
233 | 284 | ||
234 | #define SOR_DP_DEBUG_0 0x5e | 285 | #define SOR_DP_DEBUG0 0x5e |
235 | #define SOR_DP_DEBUG_1 0x5f | 286 | #define SOR_DP_DEBUG1 0x5f |
236 | 287 | ||
237 | #define SOR_DP_SPARE_0 0x60 | 288 | #define SOR_DP_SPARE0 0x60 |
238 | #define SOR_DP_SPARE_MACRO_SOR_CLK (1 << 2) | 289 | #define SOR_DP_SPARE_DISP_VIDEO_PREAMBLE (1 << 3) |
239 | #define SOR_DP_SPARE_PANEL_INTERNAL (1 << 1) | 290 | #define SOR_DP_SPARE_MACRO_SOR_CLK (1 << 2) |
240 | #define SOR_DP_SPARE_SEQ_ENABLE (1 << 0) | 291 | #define SOR_DP_SPARE_PANEL_INTERNAL (1 << 1) |
292 | #define SOR_DP_SPARE_SEQ_ENABLE (1 << 0) | ||
241 | 293 | ||
242 | #define SOR_DP_SPARE_1 0x61 | 294 | #define SOR_DP_SPARE1 0x61 |
243 | #define SOR_DP_AUDIO_CTRL 0x62 | 295 | #define SOR_DP_AUDIO_CTRL 0x62 |
244 | 296 | ||
245 | #define SOR_DP_AUDIO_HBLANK_SYMBOLS 0x63 | 297 | #define SOR_DP_AUDIO_HBLANK_SYMBOLS 0x63 |
@@ -249,13 +301,13 @@ | |||
249 | #define SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK (0x1fffff << 0) | 301 | #define SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK (0x1fffff << 0) |
250 | 302 | ||
251 | #define SOR_DP_GENERIC_INFOFRAME_HEADER 0x65 | 303 | #define SOR_DP_GENERIC_INFOFRAME_HEADER 0x65 |
252 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_0 0x66 | 304 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK0 0x66 |
253 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_1 0x67 | 305 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK1 0x67 |
254 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_2 0x68 | 306 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK2 0x68 |
255 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_3 0x69 | 307 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK3 0x69 |
256 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_4 0x6a | 308 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK4 0x6a |
257 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_5 0x6b | 309 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK5 0x6b |
258 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_6 0x6c | 310 | #define SOR_DP_GENERIC_INFOFRAME_SUBPACK6 0x6c |
259 | 311 | ||
260 | #define SOR_DP_TPG 0x6d | 312 | #define SOR_DP_TPG 0x6d |
261 | #define SOR_DP_TPG_CHANNEL_CODING (1 << 6) | 313 | #define SOR_DP_TPG_CHANNEL_CODING (1 << 6) |
@@ -275,8 +327,44 @@ | |||
275 | #define SOR_DP_TPG_PATTERN_NONE (0x0 << 0) | 327 | #define SOR_DP_TPG_PATTERN_NONE (0x0 << 0) |
276 | 328 | ||
277 | #define SOR_DP_TPG_CONFIG 0x6e | 329 | #define SOR_DP_TPG_CONFIG 0x6e |
278 | #define SOR_DP_LQ_CSTM_0 0x6f | 330 | #define SOR_DP_LQ_CSTM0 0x6f |
279 | #define SOR_DP_LQ_CSTM_1 0x70 | 331 | #define SOR_DP_LQ_CSTM1 0x70 |
280 | #define SOR_DP_LQ_CSTM_2 0x71 | 332 | #define SOR_DP_LQ_CSTM2 0x71 |
333 | |||
334 | #define SOR_HDMI_AUDIO_INFOFRAME_CTRL 0x9a | ||
335 | #define SOR_HDMI_AUDIO_INFOFRAME_STATUS 0x9b | ||
336 | #define SOR_HDMI_AUDIO_INFOFRAME_HEADER 0x9c | ||
337 | |||
338 | #define SOR_HDMI_AVI_INFOFRAME_CTRL 0x9f | ||
339 | #define INFOFRAME_CTRL_CHECKSUM_ENABLE (1 << 9) | ||
340 | #define INFOFRAME_CTRL_SINGLE (1 << 8) | ||
341 | #define INFOFRAME_CTRL_OTHER (1 << 4) | ||
342 | #define INFOFRAME_CTRL_ENABLE (1 << 0) | ||
343 | |||
344 | #define SOR_HDMI_AVI_INFOFRAME_STATUS 0xa0 | ||
345 | #define INFOFRAME_STATUS_DONE (1 << 0) | ||
346 | |||
347 | #define SOR_HDMI_AVI_INFOFRAME_HEADER 0xa1 | ||
348 | #define INFOFRAME_HEADER_LEN(x) (((x) & 0xff) << 16) | ||
349 | #define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8) | ||
350 | #define INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0) | ||
351 | |||
352 | #define SOR_HDMI_CTRL 0xc0 | ||
353 | #define SOR_HDMI_CTRL_ENABLE (1 << 30) | ||
354 | #define SOR_HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16) | ||
355 | #define SOR_HDMI_CTRL_AUDIO_LAYOUT (1 << 10) | ||
356 | #define SOR_HDMI_CTRL_REKEY(x) (((x) & 0x7f) << 0) | ||
357 | |||
358 | #define SOR_REFCLK 0xe6 | ||
359 | #define SOR_REFCLK_DIV_INT(x) ((((x) >> 2) & 0xff) << 8) | ||
360 | #define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x3) << 6) | ||
361 | |||
362 | #define SOR_INPUT_CONTROL 0xe8 | ||
363 | #define SOR_INPUT_CONTROL_ARM_VIDEO_RANGE_LIMITED (1 << 1) | ||
364 | #define SOR_INPUT_CONTROL_HDMI_SRC_SELECT(x) (((x) & 0x1) << 0) | ||
365 | |||
366 | #define SOR_HDMI_VSI_INFOFRAME_CTRL 0x123 | ||
367 | #define SOR_HDMI_VSI_INFOFRAME_STATUS 0x124 | ||
368 | #define SOR_HDMI_VSI_INFOFRAME_HEADER 0x125 | ||
281 | 369 | ||
282 | #endif | 370 | #endif |
diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c index fbc6ee6ca337..52a6fd224127 100644 --- a/drivers/gpu/host1x/mipi.c +++ b/drivers/gpu/host1x/mipi.c | |||
@@ -31,6 +31,9 @@ | |||
31 | #include "dev.h" | 31 | #include "dev.h" |
32 | 32 | ||
33 | #define MIPI_CAL_CTRL 0x00 | 33 | #define MIPI_CAL_CTRL 0x00 |
34 | #define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26) | ||
35 | #define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24) | ||
36 | #define MIPI_CAL_CTRL_CLKEN_OVR (1 << 4) | ||
34 | #define MIPI_CAL_CTRL_START (1 << 0) | 37 | #define MIPI_CAL_CTRL_START (1 << 0) |
35 | 38 | ||
36 | #define MIPI_CAL_AUTOCAL_CTRL 0x01 | 39 | #define MIPI_CAL_AUTOCAL_CTRL 0x01 |
@@ -44,15 +47,18 @@ | |||
44 | #define MIPI_CAL_CONFIG_CSIC 0x07 | 47 | #define MIPI_CAL_CONFIG_CSIC 0x07 |
45 | #define MIPI_CAL_CONFIG_CSID 0x08 | 48 | #define MIPI_CAL_CONFIG_CSID 0x08 |
46 | #define MIPI_CAL_CONFIG_CSIE 0x09 | 49 | #define MIPI_CAL_CONFIG_CSIE 0x09 |
50 | #define MIPI_CAL_CONFIG_CSIF 0x0a | ||
47 | #define MIPI_CAL_CONFIG_DSIA 0x0e | 51 | #define MIPI_CAL_CONFIG_DSIA 0x0e |
48 | #define MIPI_CAL_CONFIG_DSIB 0x0f | 52 | #define MIPI_CAL_CONFIG_DSIB 0x0f |
49 | #define MIPI_CAL_CONFIG_DSIC 0x10 | 53 | #define MIPI_CAL_CONFIG_DSIC 0x10 |
50 | #define MIPI_CAL_CONFIG_DSID 0x11 | 54 | #define MIPI_CAL_CONFIG_DSID 0x11 |
51 | 55 | ||
52 | #define MIPI_CAL_CONFIG_DSIAB_CLK 0x19 | 56 | #define MIPI_CAL_CONFIG_DSIA_CLK 0x19 |
53 | #define MIPI_CAL_CONFIG_DSICD_CLK 0x1a | 57 | #define MIPI_CAL_CONFIG_DSIB_CLK 0x1a |
54 | #define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b | 58 | #define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b |
59 | #define MIPI_CAL_CONFIG_DSIC_CLK 0x1c | ||
55 | #define MIPI_CAL_CONFIG_CSICD_CLK 0x1c | 60 | #define MIPI_CAL_CONFIG_CSICD_CLK 0x1c |
61 | #define MIPI_CAL_CONFIG_DSID_CLK 0x1d | ||
56 | #define MIPI_CAL_CONFIG_CSIE_CLK 0x1d | 62 | #define MIPI_CAL_CONFIG_CSIE_CLK 0x1d |
57 | 63 | ||
58 | /* for data and clock lanes */ | 64 | /* for data and clock lanes */ |
@@ -73,8 +79,11 @@ | |||
73 | 79 | ||
74 | #define MIPI_CAL_BIAS_PAD_CFG1 0x17 | 80 | #define MIPI_CAL_BIAS_PAD_CFG1 0x17 |
75 | #define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16) | 81 | #define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16) |
82 | #define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8) | ||
76 | 83 | ||
77 | #define MIPI_CAL_BIAS_PAD_CFG2 0x18 | 84 | #define MIPI_CAL_BIAS_PAD_CFG2 0x18 |
85 | #define MIPI_CAL_BIAS_PAD_VCLAMP(x) (((x) & 0x7) << 16) | ||
86 | #define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4) | ||
78 | #define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1) | 87 | #define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1) |
79 | 88 | ||
80 | struct tegra_mipi_pad { | 89 | struct tegra_mipi_pad { |
@@ -86,13 +95,35 @@ struct tegra_mipi_soc { | |||
86 | bool has_clk_lane; | 95 | bool has_clk_lane; |
87 | const struct tegra_mipi_pad *pads; | 96 | const struct tegra_mipi_pad *pads; |
88 | unsigned int num_pads; | 97 | unsigned int num_pads; |
98 | |||
99 | bool clock_enable_override; | ||
100 | bool needs_vclamp_ref; | ||
101 | |||
102 | /* bias pad configuration settings */ | ||
103 | u8 pad_drive_down_ref; | ||
104 | u8 pad_drive_up_ref; | ||
105 | |||
106 | u8 pad_vclamp_level; | ||
107 | u8 pad_vauxp_level; | ||
108 | |||
109 | /* calibration settings for data lanes */ | ||
110 | u8 hspdos; | ||
111 | u8 hspuos; | ||
112 | u8 termos; | ||
113 | |||
114 | /* calibration settings for clock lanes */ | ||
115 | u8 hsclkpdos; | ||
116 | u8 hsclkpuos; | ||
89 | }; | 117 | }; |
90 | 118 | ||
91 | struct tegra_mipi { | 119 | struct tegra_mipi { |
92 | const struct tegra_mipi_soc *soc; | 120 | const struct tegra_mipi_soc *soc; |
121 | struct device *dev; | ||
93 | void __iomem *regs; | 122 | void __iomem *regs; |
94 | struct mutex lock; | 123 | struct mutex lock; |
95 | struct clk *clk; | 124 | struct clk *clk; |
125 | |||
126 | unsigned long usage_count; | ||
96 | }; | 127 | }; |
97 | 128 | ||
98 | struct tegra_mipi_device { | 129 | struct tegra_mipi_device { |
@@ -114,6 +145,67 @@ static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value, | |||
114 | writel(value, mipi->regs + (offset << 2)); | 145 | writel(value, mipi->regs + (offset << 2)); |
115 | } | 146 | } |
116 | 147 | ||
148 | static int tegra_mipi_power_up(struct tegra_mipi *mipi) | ||
149 | { | ||
150 | u32 value; | ||
151 | int err; | ||
152 | |||
153 | err = clk_enable(mipi->clk); | ||
154 | if (err < 0) | ||
155 | return err; | ||
156 | |||
157 | value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0); | ||
158 | value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP; | ||
159 | |||
160 | if (mipi->soc->needs_vclamp_ref) | ||
161 | value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF; | ||
162 | |||
163 | tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0); | ||
164 | |||
165 | value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2); | ||
166 | value &= ~MIPI_CAL_BIAS_PAD_PDVREG; | ||
167 | tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2); | ||
168 | |||
169 | clk_disable(mipi->clk); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int tegra_mipi_power_down(struct tegra_mipi *mipi) | ||
175 | { | ||
176 | u32 value; | ||
177 | int err; | ||
178 | |||
179 | err = clk_enable(mipi->clk); | ||
180 | if (err < 0) | ||
181 | return err; | ||
182 | |||
183 | /* | ||
184 | * The MIPI_CAL_BIAS_PAD_PDVREG controls a voltage regulator that | ||
185 | * supplies the DSI pads. This must be kept enabled until none of the | ||
186 | * DSI lanes are used anymore. | ||
187 | */ | ||
188 | value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2); | ||
189 | value |= MIPI_CAL_BIAS_PAD_PDVREG; | ||
190 | tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2); | ||
191 | |||
192 | /* | ||
193 | * MIPI_CAL_BIAS_PAD_PDVCLAMP and MIPI_CAL_BIAS_PAD_E_VCLAMP_REF | ||
194 | * control a regulator that supplies current to the pre-driver logic. | ||
195 | * Powering down this regulator causes DSI to fail, so it must remain | ||
196 | * powered on until none of the DSI lanes are used anymore. | ||
197 | */ | ||
198 | value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0); | ||
199 | |||
200 | if (mipi->soc->needs_vclamp_ref) | ||
201 | value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF; | ||
202 | |||
203 | value |= MIPI_CAL_BIAS_PAD_PDVCLAMP; | ||
204 | tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
117 | struct tegra_mipi_device *tegra_mipi_request(struct device *device) | 209 | struct tegra_mipi_device *tegra_mipi_request(struct device *device) |
118 | { | 210 | { |
119 | struct device_node *np = device->of_node; | 211 | struct device_node *np = device->of_node; |
@@ -150,6 +242,20 @@ struct tegra_mipi_device *tegra_mipi_request(struct device *device) | |||
150 | dev->pads = args.args[0]; | 242 | dev->pads = args.args[0]; |
151 | dev->device = device; | 243 | dev->device = device; |
152 | 244 | ||
245 | mutex_lock(&dev->mipi->lock); | ||
246 | |||
247 | if (dev->mipi->usage_count++ == 0) { | ||
248 | err = tegra_mipi_power_up(dev->mipi); | ||
249 | if (err < 0) { | ||
250 | dev_err(dev->mipi->dev, | ||
251 | "failed to power up MIPI bricks: %d\n", | ||
252 | err); | ||
253 | return ERR_PTR(err); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | mutex_unlock(&dev->mipi->lock); | ||
258 | |||
153 | return dev; | 259 | return dev; |
154 | 260 | ||
155 | put: | 261 | put: |
@@ -164,6 +270,25 @@ EXPORT_SYMBOL(tegra_mipi_request); | |||
164 | 270 | ||
165 | void tegra_mipi_free(struct tegra_mipi_device *device) | 271 | void tegra_mipi_free(struct tegra_mipi_device *device) |
166 | { | 272 | { |
273 | int err; | ||
274 | |||
275 | mutex_lock(&device->mipi->lock); | ||
276 | |||
277 | if (--device->mipi->usage_count == 0) { | ||
278 | err = tegra_mipi_power_down(device->mipi); | ||
279 | if (err < 0) { | ||
280 | /* | ||
281 | * Not much that can be done here, so an error message | ||
282 | * will have to do. | ||
283 | */ | ||
284 | dev_err(device->mipi->dev, | ||
285 | "failed to power down MIPI bricks: %d\n", | ||
286 | err); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | mutex_unlock(&device->mipi->lock); | ||
291 | |||
167 | platform_device_put(device->pdev); | 292 | platform_device_put(device->pdev); |
168 | kfree(device); | 293 | kfree(device); |
169 | } | 294 | } |
@@ -199,16 +324,15 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device) | |||
199 | 324 | ||
200 | mutex_lock(&device->mipi->lock); | 325 | mutex_lock(&device->mipi->lock); |
201 | 326 | ||
202 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG0); | 327 | value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) | |
203 | value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP; | 328 | MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref); |
204 | value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF; | 329 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG1); |
205 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0); | ||
206 | |||
207 | tegra_mipi_writel(device->mipi, MIPI_CAL_BIAS_PAD_DRV_DN_REF(2), | ||
208 | MIPI_CAL_BIAS_PAD_CFG1); | ||
209 | 330 | ||
210 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2); | 331 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2); |
211 | value &= ~MIPI_CAL_BIAS_PAD_PDVREG; | 332 | value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); |
333 | value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); | ||
334 | value |= MIPI_CAL_BIAS_PAD_VCLAMP(soc->pad_vclamp_level); | ||
335 | value |= MIPI_CAL_BIAS_PAD_VAUXP(soc->pad_vauxp_level); | ||
212 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2); | 336 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2); |
213 | 337 | ||
214 | for (i = 0; i < soc->num_pads; i++) { | 338 | for (i = 0; i < soc->num_pads; i++) { |
@@ -216,21 +340,38 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device) | |||
216 | 340 | ||
217 | if (device->pads & BIT(i)) { | 341 | if (device->pads & BIT(i)) { |
218 | data = MIPI_CAL_CONFIG_SELECT | | 342 | data = MIPI_CAL_CONFIG_SELECT | |
219 | MIPI_CAL_CONFIG_HSPDOS(0) | | 343 | MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) | |
220 | MIPI_CAL_CONFIG_HSPUOS(4) | | 344 | MIPI_CAL_CONFIG_HSPUOS(soc->hspuos) | |
221 | MIPI_CAL_CONFIG_TERMOS(5); | 345 | MIPI_CAL_CONFIG_TERMOS(soc->termos); |
222 | clk = MIPI_CAL_CONFIG_SELECT | | 346 | clk = MIPI_CAL_CONFIG_SELECT | |
223 | MIPI_CAL_CONFIG_HSCLKPDOSD(0) | | 347 | MIPI_CAL_CONFIG_HSCLKPDOSD(soc->hsclkpdos) | |
224 | MIPI_CAL_CONFIG_HSCLKPUOSD(4); | 348 | MIPI_CAL_CONFIG_HSCLKPUOSD(soc->hsclkpuos); |
225 | } | 349 | } |
226 | 350 | ||
227 | tegra_mipi_writel(device->mipi, data, soc->pads[i].data); | 351 | tegra_mipi_writel(device->mipi, data, soc->pads[i].data); |
228 | 352 | ||
229 | if (soc->has_clk_lane) | 353 | if (soc->has_clk_lane && soc->pads[i].clk != 0) |
230 | tegra_mipi_writel(device->mipi, clk, soc->pads[i].clk); | 354 | tegra_mipi_writel(device->mipi, clk, soc->pads[i].clk); |
231 | } | 355 | } |
232 | 356 | ||
233 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL); | 357 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL); |
358 | value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf); | ||
359 | value &= ~MIPI_CAL_CTRL_PRESCALE(0x3); | ||
360 | value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa); | ||
361 | value |= MIPI_CAL_CTRL_PRESCALE(0x2); | ||
362 | |||
363 | if (!soc->clock_enable_override) | ||
364 | value &= ~MIPI_CAL_CTRL_CLKEN_OVR; | ||
365 | else | ||
366 | value |= MIPI_CAL_CTRL_CLKEN_OVR; | ||
367 | |||
368 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL); | ||
369 | |||
370 | /* clear any pending status bits */ | ||
371 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_STATUS); | ||
372 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_STATUS); | ||
373 | |||
374 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL); | ||
234 | value |= MIPI_CAL_CTRL_START; | 375 | value |= MIPI_CAL_CTRL_START; |
235 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL); | 376 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL); |
236 | 377 | ||
@@ -259,6 +400,17 @@ static const struct tegra_mipi_soc tegra114_mipi_soc = { | |||
259 | .has_clk_lane = false, | 400 | .has_clk_lane = false, |
260 | .pads = tegra114_mipi_pads, | 401 | .pads = tegra114_mipi_pads, |
261 | .num_pads = ARRAY_SIZE(tegra114_mipi_pads), | 402 | .num_pads = ARRAY_SIZE(tegra114_mipi_pads), |
403 | .clock_enable_override = true, | ||
404 | .needs_vclamp_ref = true, | ||
405 | .pad_drive_down_ref = 0x2, | ||
406 | .pad_drive_up_ref = 0x0, | ||
407 | .pad_vclamp_level = 0x0, | ||
408 | .pad_vauxp_level = 0x0, | ||
409 | .hspdos = 0x0, | ||
410 | .hspuos = 0x4, | ||
411 | .termos = 0x5, | ||
412 | .hsclkpdos = 0x0, | ||
413 | .hsclkpuos = 0x4, | ||
262 | }; | 414 | }; |
263 | 415 | ||
264 | static const struct tegra_mipi_pad tegra124_mipi_pads[] = { | 416 | static const struct tegra_mipi_pad tegra124_mipi_pads[] = { |
@@ -266,20 +418,80 @@ static const struct tegra_mipi_pad tegra124_mipi_pads[] = { | |||
266 | { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK }, | 418 | { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK }, |
267 | { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, | 419 | { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, |
268 | { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, | 420 | { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, |
269 | { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK }, | 421 | { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK }, |
270 | { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIAB_CLK }, | 422 | { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK }, |
271 | { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIAB_CLK }, | 423 | { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK }, |
272 | }; | 424 | }; |
273 | 425 | ||
274 | static const struct tegra_mipi_soc tegra124_mipi_soc = { | 426 | static const struct tegra_mipi_soc tegra124_mipi_soc = { |
275 | .has_clk_lane = true, | 427 | .has_clk_lane = true, |
276 | .pads = tegra124_mipi_pads, | 428 | .pads = tegra124_mipi_pads, |
277 | .num_pads = ARRAY_SIZE(tegra124_mipi_pads), | 429 | .num_pads = ARRAY_SIZE(tegra124_mipi_pads), |
430 | .clock_enable_override = true, | ||
431 | .needs_vclamp_ref = true, | ||
432 | .pad_drive_down_ref = 0x2, | ||
433 | .pad_drive_up_ref = 0x0, | ||
434 | .pad_vclamp_level = 0x0, | ||
435 | .pad_vauxp_level = 0x0, | ||
436 | .hspdos = 0x0, | ||
437 | .hspuos = 0x0, | ||
438 | .termos = 0x0, | ||
439 | .hsclkpdos = 0x1, | ||
440 | .hsclkpuos = 0x2, | ||
441 | }; | ||
442 | |||
443 | static const struct tegra_mipi_soc tegra132_mipi_soc = { | ||
444 | .has_clk_lane = true, | ||
445 | .pads = tegra124_mipi_pads, | ||
446 | .num_pads = ARRAY_SIZE(tegra124_mipi_pads), | ||
447 | .clock_enable_override = false, | ||
448 | .needs_vclamp_ref = false, | ||
449 | .pad_drive_down_ref = 0x0, | ||
450 | .pad_drive_up_ref = 0x3, | ||
451 | .pad_vclamp_level = 0x0, | ||
452 | .pad_vauxp_level = 0x0, | ||
453 | .hspdos = 0x0, | ||
454 | .hspuos = 0x0, | ||
455 | .termos = 0x0, | ||
456 | .hsclkpdos = 0x3, | ||
457 | .hsclkpuos = 0x2, | ||
458 | }; | ||
459 | |||
460 | static const struct tegra_mipi_pad tegra210_mipi_pads[] = { | ||
461 | { .data = MIPI_CAL_CONFIG_CSIA, .clk = 0 }, | ||
462 | { .data = MIPI_CAL_CONFIG_CSIB, .clk = 0 }, | ||
463 | { .data = MIPI_CAL_CONFIG_CSIC, .clk = 0 }, | ||
464 | { .data = MIPI_CAL_CONFIG_CSID, .clk = 0 }, | ||
465 | { .data = MIPI_CAL_CONFIG_CSIE, .clk = 0 }, | ||
466 | { .data = MIPI_CAL_CONFIG_CSIF, .clk = 0 }, | ||
467 | { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK }, | ||
468 | { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK }, | ||
469 | { .data = MIPI_CAL_CONFIG_DSIC, .clk = MIPI_CAL_CONFIG_DSIC_CLK }, | ||
470 | { .data = MIPI_CAL_CONFIG_DSID, .clk = MIPI_CAL_CONFIG_DSID_CLK }, | ||
471 | }; | ||
472 | |||
473 | static const struct tegra_mipi_soc tegra210_mipi_soc = { | ||
474 | .has_clk_lane = true, | ||
475 | .pads = tegra210_mipi_pads, | ||
476 | .num_pads = ARRAY_SIZE(tegra210_mipi_pads), | ||
477 | .clock_enable_override = true, | ||
478 | .needs_vclamp_ref = false, | ||
479 | .pad_drive_down_ref = 0x0, | ||
480 | .pad_drive_up_ref = 0x3, | ||
481 | .pad_vclamp_level = 0x1, | ||
482 | .pad_vauxp_level = 0x1, | ||
483 | .hspdos = 0x0, | ||
484 | .hspuos = 0x2, | ||
485 | .termos = 0x0, | ||
486 | .hsclkpdos = 0x0, | ||
487 | .hsclkpuos = 0x2, | ||
278 | }; | 488 | }; |
279 | 489 | ||
280 | static struct of_device_id tegra_mipi_of_match[] = { | 490 | static const struct of_device_id tegra_mipi_of_match[] = { |
281 | { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc }, | 491 | { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc }, |
282 | { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc }, | 492 | { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc }, |
493 | { .compatible = "nvidia,tegra132-mipi", .data = &tegra132_mipi_soc }, | ||
494 | { .compatible = "nvidia,tegra210-mipi", .data = &tegra210_mipi_soc }, | ||
283 | { }, | 495 | { }, |
284 | }; | 496 | }; |
285 | 497 | ||
@@ -299,6 +511,7 @@ static int tegra_mipi_probe(struct platform_device *pdev) | |||
299 | return -ENOMEM; | 511 | return -ENOMEM; |
300 | 512 | ||
301 | mipi->soc = match->data; | 513 | mipi->soc = match->data; |
514 | mipi->dev = &pdev->dev; | ||
302 | 515 | ||
303 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 516 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
304 | mipi->regs = devm_ioremap_resource(&pdev->dev, res); | 517 | mipi->regs = devm_ioremap_resource(&pdev->dev, res); |