aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vc4/vc4_hdmi.c
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2017-04-11 12:39:25 -0400
committerEric Anholt <eric@anholt.net>2017-04-18 15:27:32 -0400
commit4f6e3d66ac522dec9733d433ad00e8e77747c372 (patch)
treee89c1b87a96b8c56355a472ddf321da3c600f355 /drivers/gpu/drm/vc4/vc4_hdmi.c
parent75cccac4028cede6d064699abae903c9e338004f (diff)
drm/vc4: Add runtime PM support to the HDMI encoder driver
The HDMI driver is currently enabling all clocks at probe time and keeps the power-domain connected to the HDMI encoder enabled. Move all activation code to vc4_hdmi_encoder_enable() and make sure the clks and power domain are released when the HDMI encoder is not used by adding deactivation steps in vc4_hdmi_encoder_disable(). Note that the sequencing imposed by the IP requires that we move vc4_hdmi_encoder_mode_set() code into vc4_hdmi_encoder_enable(). Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Signed-off-by: Eric Anholt <eric@anholt.net> Reviewed-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_hdmi.c')
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c174
1 files changed, 92 insertions, 82 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index e9cbe269710b..3c2723f6345c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -51,6 +51,7 @@
51#include "linux/of_address.h" 51#include "linux/of_address.h"
52#include "linux/of_gpio.h" 52#include "linux/of_gpio.h"
53#include "linux/of_platform.h" 53#include "linux/of_platform.h"
54#include "linux/pm_runtime.h"
54#include "linux/rational.h" 55#include "linux/rational.h"
55#include "sound/dmaengine_pcm.h" 56#include "sound/dmaengine_pcm.h"
56#include "sound/pcm_drm_eld.h" 57#include "sound/pcm_drm_eld.h"
@@ -449,13 +450,38 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
449 vc4_hdmi_set_spd_infoframe(encoder); 450 vc4_hdmi_set_spd_infoframe(encoder);
450} 451}
451 452
452static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, 453static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
453 struct drm_display_mode *unadjusted_mode, 454{
454 struct drm_display_mode *mode) 455 struct drm_device *dev = encoder->dev;
456 struct vc4_dev *vc4 = to_vc4_dev(dev);
457 struct vc4_hdmi *hdmi = vc4->hdmi;
458 int ret;
459
460 HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
461
462 HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
463 HD_WRITE(VC4_HD_VID_CTL,
464 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
465
466 HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
467 udelay(1);
468 HD_WRITE(VC4_HD_M_CTL, 0);
469
470 clk_disable_unprepare(hdmi->hsm_clock);
471 clk_disable_unprepare(hdmi->pixel_clock);
472
473 ret = pm_runtime_put(&hdmi->pdev->dev);
474 if (ret < 0)
475 DRM_ERROR("Failed to release power domain: %d\n", ret);
476}
477
478static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
455{ 479{
480 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
456 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); 481 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
457 struct drm_device *dev = encoder->dev; 482 struct drm_device *dev = encoder->dev;
458 struct vc4_dev *vc4 = to_vc4_dev(dev); 483 struct vc4_dev *vc4 = to_vc4_dev(dev);
484 struct vc4_hdmi *hdmi = vc4->hdmi;
459 bool debug_dump_regs = false; 485 bool debug_dump_regs = false;
460 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; 486 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
461 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; 487 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
@@ -475,6 +501,64 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
475 interlaced, 501 interlaced,
476 VC4_HDMI_VERTB_VBP)); 502 VC4_HDMI_VERTB_VBP));
477 u32 csc_ctl; 503 u32 csc_ctl;
504 int ret;
505
506 ret = pm_runtime_get_sync(&hdmi->pdev->dev);
507 if (ret < 0) {
508 DRM_ERROR("Failed to retain power domain: %d\n", ret);
509 return;
510 }
511
512 /* This is the rate that is set by the firmware. The number
513 * needs to be a bit higher than the pixel clock rate
514 * (generally 148.5Mhz).
515 */
516 ret = clk_set_rate(hdmi->hsm_clock, 163682864);
517 if (ret) {
518 DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
519 return;
520 }
521
522 ret = clk_set_rate(hdmi->pixel_clock,
523 mode->clock * 1000 *
524 ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
525 if (ret) {
526 DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
527 return;
528 }
529
530 ret = clk_prepare_enable(hdmi->pixel_clock);
531 if (ret) {
532 DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
533 return;
534 }
535
536 ret = clk_prepare_enable(hdmi->hsm_clock);
537 if (ret) {
538 DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
539 ret);
540 clk_disable_unprepare(hdmi->pixel_clock);
541 return;
542 }
543
544 HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
545 udelay(1);
546 HD_WRITE(VC4_HD_M_CTL, 0);
547
548 HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
549
550 HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
551 VC4_HDMI_SW_RESET_HDMI |
552 VC4_HDMI_SW_RESET_FORMAT_DETECT);
553
554 HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
555
556 /* PHY should be in reset, like
557 * vc4_hdmi_encoder_disable() does.
558 */
559 HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
560
561 HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
478 562
479 if (debug_dump_regs) { 563 if (debug_dump_regs) {
480 DRM_INFO("HDMI regs before:\n"); 564 DRM_INFO("HDMI regs before:\n");
@@ -483,9 +567,6 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
483 567
484 HD_WRITE(VC4_HD_VID_CTL, 0); 568 HD_WRITE(VC4_HD_VID_CTL, 0);
485 569
486 clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000 *
487 ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
488
489 HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, 570 HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
490 HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | 571 HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
491 VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT | 572 VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
@@ -559,28 +640,6 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
559 DRM_INFO("HDMI regs after:\n"); 640 DRM_INFO("HDMI regs after:\n");
560 vc4_hdmi_dump_regs(dev); 641 vc4_hdmi_dump_regs(dev);
561 } 642 }
562}
563
564static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
565{
566 struct drm_device *dev = encoder->dev;
567 struct vc4_dev *vc4 = to_vc4_dev(dev);
568
569 HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
570
571 HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
572 HD_WRITE(VC4_HD_VID_CTL,
573 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
574}
575
576static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
577{
578 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
579 struct drm_device *dev = encoder->dev;
580 struct vc4_dev *vc4 = to_vc4_dev(dev);
581 int ret;
582
583 HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
584 643
585 HD_WRITE(VC4_HD_VID_CTL, 644 HD_WRITE(VC4_HD_VID_CTL,
586 HD_READ(VC4_HD_VID_CTL) | 645 HD_READ(VC4_HD_VID_CTL) |
@@ -646,7 +705,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
646} 705}
647 706
648static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { 707static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
649 .mode_set = vc4_hdmi_encoder_mode_set,
650 .disable = vc4_hdmi_encoder_disable, 708 .disable = vc4_hdmi_encoder_disable,
651 .enable = vc4_hdmi_encoder_enable, 709 .enable = vc4_hdmi_encoder_enable,
652}; 710};
@@ -1147,33 +1205,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
1147 return -EPROBE_DEFER; 1205 return -EPROBE_DEFER;
1148 } 1206 }
1149 1207
1150 /* Enable the clocks at startup. We can't quite recover from
1151 * turning off the pixel clock during disable/enables yet, so
1152 * it's always running.
1153 */
1154 ret = clk_prepare_enable(hdmi->pixel_clock);
1155 if (ret) {
1156 DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
1157 goto err_put_i2c;
1158 }
1159
1160 /* This is the rate that is set by the firmware. The number
1161 * needs to be a bit higher than the pixel clock rate
1162 * (generally 148.5Mhz).
1163 */
1164 ret = clk_set_rate(hdmi->hsm_clock, 163682864);
1165 if (ret) {
1166 DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
1167 goto err_unprepare_pix;
1168 }
1169
1170 ret = clk_prepare_enable(hdmi->hsm_clock);
1171 if (ret) {
1172 DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
1173 ret);
1174 goto err_unprepare_pix;
1175 }
1176
1177 /* Only use the GPIO HPD pin if present in the DT, otherwise 1208 /* Only use the GPIO HPD pin if present in the DT, otherwise
1178 * we'll use the HDMI core's register. 1209 * we'll use the HDMI core's register.
1179 */ 1210 */
@@ -1185,7 +1216,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
1185 &hpd_gpio_flags); 1216 &hpd_gpio_flags);
1186 if (hdmi->hpd_gpio < 0) { 1217 if (hdmi->hpd_gpio < 0) {
1187 ret = hdmi->hpd_gpio; 1218 ret = hdmi->hpd_gpio;
1188 goto err_unprepare_hsm; 1219 goto err_put_i2c;
1189 } 1220 }
1190 1221
1191 hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; 1222 hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
@@ -1193,25 +1224,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
1193 1224
1194 vc4->hdmi = hdmi; 1225 vc4->hdmi = hdmi;
1195 1226
1196 /* HDMI core must be enabled. */ 1227 pm_runtime_enable(dev);
1197 if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
1198 HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
1199 udelay(1);
1200 HD_WRITE(VC4_HD_M_CTL, 0);
1201
1202 HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
1203
1204 HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
1205 VC4_HDMI_SW_RESET_HDMI |
1206 VC4_HDMI_SW_RESET_FORMAT_DETECT);
1207
1208 HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
1209
1210 /* PHY should be in reset, like
1211 * vc4_hdmi_encoder_disable() does.
1212 */
1213 HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
1214 }
1215 1228
1216 drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs, 1229 drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs,
1217 DRM_MODE_ENCODER_TMDS, NULL); 1230 DRM_MODE_ENCODER_TMDS, NULL);
@@ -1231,10 +1244,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
1231 1244
1232err_destroy_encoder: 1245err_destroy_encoder:
1233 vc4_hdmi_encoder_destroy(hdmi->encoder); 1246 vc4_hdmi_encoder_destroy(hdmi->encoder);
1234err_unprepare_hsm: 1247 pm_runtime_disable(dev);
1235 clk_disable_unprepare(hdmi->hsm_clock);
1236err_unprepare_pix:
1237 clk_disable_unprepare(hdmi->pixel_clock);
1238err_put_i2c: 1248err_put_i2c:
1239 put_device(&hdmi->ddc->dev); 1249 put_device(&hdmi->ddc->dev);
1240 1250
@@ -1253,8 +1263,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
1253 vc4_hdmi_connector_destroy(hdmi->connector); 1263 vc4_hdmi_connector_destroy(hdmi->connector);
1254 vc4_hdmi_encoder_destroy(hdmi->encoder); 1264 vc4_hdmi_encoder_destroy(hdmi->encoder);
1255 1265
1256 clk_disable_unprepare(hdmi->pixel_clock); 1266 pm_runtime_disable(dev);
1257 clk_disable_unprepare(hdmi->hsm_clock); 1267
1258 put_device(&hdmi->ddc->dev); 1268 put_device(&hdmi->ddc->dev);
1259 1269
1260 vc4->hdmi = NULL; 1270 vc4->hdmi = NULL;