diff options
-rw-r--r-- | drivers/gpu/drm/i2c/adv7511.c | 101 |
1 files changed, 53 insertions, 48 deletions
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index 828b60185016..b728523e194f 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c | |||
@@ -27,7 +27,7 @@ struct adv7511 { | |||
27 | struct regmap *regmap; | 27 | struct regmap *regmap; |
28 | struct regmap *packet_memory_regmap; | 28 | struct regmap *packet_memory_regmap; |
29 | enum drm_connector_status status; | 29 | enum drm_connector_status status; |
30 | int dpms_mode; | 30 | bool powered; |
31 | 31 | ||
32 | unsigned int f_tmds; | 32 | unsigned int f_tmds; |
33 | 33 | ||
@@ -358,6 +358,48 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, | |||
358 | adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB; | 358 | adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB; |
359 | } | 359 | } |
360 | 360 | ||
361 | static void adv7511_power_on(struct adv7511 *adv7511) | ||
362 | { | ||
363 | adv7511->current_edid_segment = -1; | ||
364 | |||
365 | regmap_write(adv7511->regmap, ADV7511_REG_INT(0), | ||
366 | ADV7511_INT0_EDID_READY); | ||
367 | regmap_write(adv7511->regmap, ADV7511_REG_INT(1), | ||
368 | ADV7511_INT1_DDC_ERROR); | ||
369 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | ||
370 | ADV7511_POWER_POWER_DOWN, 0); | ||
371 | |||
372 | /* | ||
373 | * Per spec it is allowed to pulse the HDP signal to indicate that the | ||
374 | * EDID information has changed. Some monitors do this when they wakeup | ||
375 | * from standby or are enabled. When the HDP goes low the adv7511 is | ||
376 | * reset and the outputs are disabled which might cause the monitor to | ||
377 | * go to standby again. To avoid this we ignore the HDP pin for the | ||
378 | * first few seconds after enabling the output. | ||
379 | */ | ||
380 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2, | ||
381 | ADV7511_REG_POWER2_HDP_SRC_MASK, | ||
382 | ADV7511_REG_POWER2_HDP_SRC_NONE); | ||
383 | |||
384 | /* | ||
385 | * Most of the registers are reset during power down or when HPD is low. | ||
386 | */ | ||
387 | regcache_sync(adv7511->regmap); | ||
388 | |||
389 | adv7511->powered = true; | ||
390 | } | ||
391 | |||
392 | static void adv7511_power_off(struct adv7511 *adv7511) | ||
393 | { | ||
394 | /* TODO: setup additional power down modes */ | ||
395 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | ||
396 | ADV7511_POWER_POWER_DOWN, | ||
397 | ADV7511_POWER_POWER_DOWN); | ||
398 | regcache_mark_dirty(adv7511->regmap); | ||
399 | |||
400 | adv7511->powered = false; | ||
401 | } | ||
402 | |||
361 | /* ----------------------------------------------------------------------------- | 403 | /* ----------------------------------------------------------------------------- |
362 | * Interrupt and hotplug detection | 404 | * Interrupt and hotplug detection |
363 | */ | 405 | */ |
@@ -524,7 +566,7 @@ static int adv7511_get_modes(struct drm_encoder *encoder, | |||
524 | unsigned int count; | 566 | unsigned int count; |
525 | 567 | ||
526 | /* Reading the EDID only works if the device is powered */ | 568 | /* Reading the EDID only works if the device is powered */ |
527 | if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) { | 569 | if (!adv7511->powered) { |
528 | regmap_write(adv7511->regmap, ADV7511_REG_INT(0), | 570 | regmap_write(adv7511->regmap, ADV7511_REG_INT(0), |
529 | ADV7511_INT0_EDID_READY); | 571 | ADV7511_INT0_EDID_READY); |
530 | regmap_write(adv7511->regmap, ADV7511_REG_INT(1), | 572 | regmap_write(adv7511->regmap, ADV7511_REG_INT(1), |
@@ -536,7 +578,7 @@ static int adv7511_get_modes(struct drm_encoder *encoder, | |||
536 | 578 | ||
537 | edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511); | 579 | edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511); |
538 | 580 | ||
539 | if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) | 581 | if (!adv7511->powered) |
540 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | 582 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, |
541 | ADV7511_POWER_POWER_DOWN, | 583 | ADV7511_POWER_POWER_DOWN, |
542 | ADV7511_POWER_POWER_DOWN); | 584 | ADV7511_POWER_POWER_DOWN); |
@@ -558,43 +600,10 @@ static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
558 | { | 600 | { |
559 | struct adv7511 *adv7511 = encoder_to_adv7511(encoder); | 601 | struct adv7511 *adv7511 = encoder_to_adv7511(encoder); |
560 | 602 | ||
561 | switch (mode) { | 603 | if (mode == DRM_MODE_DPMS_ON) |
562 | case DRM_MODE_DPMS_ON: | 604 | adv7511_power_on(adv7511); |
563 | adv7511->current_edid_segment = -1; | 605 | else |
564 | 606 | adv7511_power_off(adv7511); | |
565 | regmap_write(adv7511->regmap, ADV7511_REG_INT(0), | ||
566 | ADV7511_INT0_EDID_READY); | ||
567 | regmap_write(adv7511->regmap, ADV7511_REG_INT(1), | ||
568 | ADV7511_INT1_DDC_ERROR); | ||
569 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | ||
570 | ADV7511_POWER_POWER_DOWN, 0); | ||
571 | /* | ||
572 | * Per spec it is allowed to pulse the HDP signal to indicate | ||
573 | * that the EDID information has changed. Some monitors do this | ||
574 | * when they wakeup from standby or are enabled. When the HDP | ||
575 | * goes low the adv7511 is reset and the outputs are disabled | ||
576 | * which might cause the monitor to go to standby again. To | ||
577 | * avoid this we ignore the HDP pin for the first few seconds | ||
578 | * after enabling the output. | ||
579 | */ | ||
580 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2, | ||
581 | ADV7511_REG_POWER2_HDP_SRC_MASK, | ||
582 | ADV7511_REG_POWER2_HDP_SRC_NONE); | ||
583 | /* Most of the registers are reset during power down or | ||
584 | * when HPD is low | ||
585 | */ | ||
586 | regcache_sync(adv7511->regmap); | ||
587 | break; | ||
588 | default: | ||
589 | /* TODO: setup additional power down modes */ | ||
590 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | ||
591 | ADV7511_POWER_POWER_DOWN, | ||
592 | ADV7511_POWER_POWER_DOWN); | ||
593 | regcache_mark_dirty(adv7511->regmap); | ||
594 | break; | ||
595 | } | ||
596 | |||
597 | adv7511->dpms_mode = mode; | ||
598 | } | 607 | } |
599 | 608 | ||
600 | static enum drm_connector_status | 609 | static enum drm_connector_status |
@@ -622,10 +631,9 @@ adv7511_encoder_detect(struct drm_encoder *encoder, | |||
622 | * there is a pending HPD interrupt and the cable is connected there was | 631 | * there is a pending HPD interrupt and the cable is connected there was |
623 | * at least one transition from disconnected to connected and the chip | 632 | * at least one transition from disconnected to connected and the chip |
624 | * has to be reinitialized. */ | 633 | * has to be reinitialized. */ |
625 | if (status == connector_status_connected && hpd && | 634 | if (status == connector_status_connected && hpd && adv7511->powered) { |
626 | adv7511->dpms_mode == DRM_MODE_DPMS_ON) { | ||
627 | regcache_mark_dirty(adv7511->regmap); | 635 | regcache_mark_dirty(adv7511->regmap); |
628 | adv7511_encoder_dpms(encoder, adv7511->dpms_mode); | 636 | adv7511_power_on(adv7511); |
629 | adv7511_get_modes(encoder, connector); | 637 | adv7511_get_modes(encoder, connector); |
630 | if (adv7511->status == connector_status_connected) | 638 | if (adv7511->status == connector_status_connected) |
631 | status = connector_status_disconnected; | 639 | status = connector_status_disconnected; |
@@ -860,7 +868,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | |||
860 | if (!adv7511) | 868 | if (!adv7511) |
861 | return -ENOMEM; | 869 | return -ENOMEM; |
862 | 870 | ||
863 | adv7511->dpms_mode = DRM_MODE_DPMS_OFF; | 871 | adv7511->powered = false; |
864 | adv7511->status = connector_status_disconnected; | 872 | adv7511->status = connector_status_disconnected; |
865 | 873 | ||
866 | ret = adv7511_parse_dt(dev->of_node, &link_config); | 874 | ret = adv7511_parse_dt(dev->of_node, &link_config); |
@@ -920,10 +928,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | |||
920 | regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, | 928 | regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, |
921 | ADV7511_CEC_CTRL_POWER_DOWN); | 929 | ADV7511_CEC_CTRL_POWER_DOWN); |
922 | 930 | ||
923 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | 931 | adv7511_power_off(adv7511); |
924 | ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN); | ||
925 | |||
926 | adv7511->current_edid_segment = -1; | ||
927 | 932 | ||
928 | i2c_set_clientdata(i2c, adv7511); | 933 | i2c_set_clientdata(i2c, adv7511); |
929 | 934 | ||