diff options
| -rw-r--r-- | drivers/gpu/drm/i2c/adv7511.c | 197 |
1 files changed, 102 insertions, 95 deletions
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index 61aa824d45d2..b728523e194f 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c | |||
| @@ -27,12 +27,13 @@ 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 | ||
| 34 | unsigned int current_edid_segment; | 34 | unsigned int current_edid_segment; |
| 35 | uint8_t edid_buf[256]; | 35 | uint8_t edid_buf[256]; |
| 36 | bool edid_read; | ||
| 36 | 37 | ||
| 37 | wait_queue_head_t wq; | 38 | wait_queue_head_t wq; |
| 38 | struct drm_encoder *encoder; | 39 | struct drm_encoder *encoder; |
| @@ -357,6 +358,48 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, | |||
| 357 | adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB; | 358 | adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB; |
| 358 | } | 359 | } |
| 359 | 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 | |||
| 360 | /* ----------------------------------------------------------------------------- | 403 | /* ----------------------------------------------------------------------------- |
| 361 | * Interrupt and hotplug detection | 404 | * Interrupt and hotplug detection |
| 362 | */ | 405 | */ |
| @@ -379,69 +422,71 @@ static bool adv7511_hpd(struct adv7511 *adv7511) | |||
| 379 | return false; | 422 | return false; |
| 380 | } | 423 | } |
| 381 | 424 | ||
| 382 | static irqreturn_t adv7511_irq_handler(int irq, void *devid) | 425 | static int adv7511_irq_process(struct adv7511 *adv7511) |
| 383 | { | ||
| 384 | struct adv7511 *adv7511 = devid; | ||
| 385 | |||
| 386 | if (adv7511_hpd(adv7511)) | ||
| 387 | drm_helper_hpd_irq_event(adv7511->encoder->dev); | ||
| 388 | |||
| 389 | wake_up_all(&adv7511->wq); | ||
| 390 | |||
| 391 | return IRQ_HANDLED; | ||
| 392 | } | ||
| 393 | |||
| 394 | static unsigned int adv7511_is_interrupt_pending(struct adv7511 *adv7511, | ||
| 395 | unsigned int irq) | ||
| 396 | { | 426 | { |
| 397 | unsigned int irq0, irq1; | 427 | unsigned int irq0, irq1; |
| 398 | unsigned int pending; | ||
| 399 | int ret; | 428 | int ret; |
| 400 | 429 | ||
| 401 | ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0); | 430 | ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0); |
| 402 | if (ret < 0) | 431 | if (ret < 0) |
| 403 | return 0; | 432 | return ret; |
| 433 | |||
| 404 | ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1); | 434 | ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1); |
| 405 | if (ret < 0) | 435 | if (ret < 0) |
| 406 | return 0; | 436 | return ret; |
| 407 | 437 | ||
| 408 | pending = (irq1 << 8) | irq0; | 438 | regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0); |
| 439 | regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1); | ||
| 409 | 440 | ||
| 410 | return pending & irq; | 441 | if (irq0 & ADV7511_INT0_HDP) |
| 442 | drm_helper_hpd_irq_event(adv7511->encoder->dev); | ||
| 443 | |||
| 444 | if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) { | ||
| 445 | adv7511->edid_read = true; | ||
| 446 | |||
| 447 | if (adv7511->i2c_main->irq) | ||
| 448 | wake_up_all(&adv7511->wq); | ||
| 449 | } | ||
| 450 | |||
| 451 | return 0; | ||
| 411 | } | 452 | } |
| 412 | 453 | ||
| 413 | static int adv7511_wait_for_interrupt(struct adv7511 *adv7511, int irq, | 454 | static irqreturn_t adv7511_irq_handler(int irq, void *devid) |
| 414 | int timeout) | 455 | { |
| 456 | struct adv7511 *adv7511 = devid; | ||
| 457 | int ret; | ||
| 458 | |||
| 459 | ret = adv7511_irq_process(adv7511); | ||
| 460 | return ret < 0 ? IRQ_NONE : IRQ_HANDLED; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* ----------------------------------------------------------------------------- | ||
| 464 | * EDID retrieval | ||
| 465 | */ | ||
| 466 | |||
| 467 | static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) | ||
| 415 | { | 468 | { |
| 416 | unsigned int pending; | ||
| 417 | int ret; | 469 | int ret; |
| 418 | 470 | ||
| 419 | if (adv7511->i2c_main->irq) { | 471 | if (adv7511->i2c_main->irq) { |
| 420 | ret = wait_event_interruptible_timeout(adv7511->wq, | 472 | ret = wait_event_interruptible_timeout(adv7511->wq, |
| 421 | adv7511_is_interrupt_pending(adv7511, irq), | 473 | adv7511->edid_read, msecs_to_jiffies(timeout)); |
| 422 | msecs_to_jiffies(timeout)); | ||
| 423 | if (ret <= 0) | ||
| 424 | return 0; | ||
| 425 | pending = adv7511_is_interrupt_pending(adv7511, irq); | ||
| 426 | } else { | 474 | } else { |
| 427 | if (timeout < 25) | 475 | for (; timeout > 0; timeout -= 25) { |
| 428 | timeout = 25; | 476 | ret = adv7511_irq_process(adv7511); |
| 429 | do { | 477 | if (ret < 0) |
| 430 | pending = adv7511_is_interrupt_pending(adv7511, irq); | ||
| 431 | if (pending) | ||
| 432 | break; | 478 | break; |
| 479 | |||
| 480 | if (adv7511->edid_read) | ||
| 481 | break; | ||
| 482 | |||
| 433 | msleep(25); | 483 | msleep(25); |
| 434 | timeout -= 25; | 484 | } |
| 435 | } while (timeout >= 25); | ||
| 436 | } | 485 | } |
| 437 | 486 | ||
| 438 | return pending; | 487 | return adv7511->edid_read ? 0 : -EIO; |
| 439 | } | 488 | } |
| 440 | 489 | ||
| 441 | /* ----------------------------------------------------------------------------- | ||
| 442 | * EDID retrieval | ||
| 443 | */ | ||
| 444 | |||
| 445 | static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, | 490 | static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, |
| 446 | size_t len) | 491 | size_t len) |
| 447 | { | 492 | { |
| @@ -463,19 +508,14 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, | |||
| 463 | return ret; | 508 | return ret; |
| 464 | 509 | ||
| 465 | if (status != 2) { | 510 | if (status != 2) { |
| 511 | adv7511->edid_read = false; | ||
| 466 | regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT, | 512 | regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT, |
| 467 | block); | 513 | block); |
| 468 | ret = adv7511_wait_for_interrupt(adv7511, | 514 | ret = adv7511_wait_for_edid(adv7511, 200); |
| 469 | ADV7511_INT0_EDID_READY | | 515 | if (ret < 0) |
| 470 | ADV7511_INT1_DDC_ERROR, 200); | 516 | return ret; |
| 471 | |||
| 472 | if (!(ret & ADV7511_INT0_EDID_READY)) | ||
| 473 | return -EIO; | ||
| 474 | } | 517 | } |
| 475 | 518 | ||
| 476 | regmap_write(adv7511->regmap, ADV7511_REG_INT(0), | ||
| 477 | ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR); | ||
| 478 | |||
| 479 | /* Break this apart, hopefully more I2C controllers will | 519 | /* Break this apart, hopefully more I2C controllers will |
| 480 | * support 64 byte transfers than 256 byte transfers | 520 | * support 64 byte transfers than 256 byte transfers |
| 481 | */ | 521 | */ |
| @@ -526,9 +566,11 @@ static int adv7511_get_modes(struct drm_encoder *encoder, | |||
| 526 | unsigned int count; | 566 | unsigned int count; |
| 527 | 567 | ||
| 528 | /* Reading the EDID only works if the device is powered */ | 568 | /* Reading the EDID only works if the device is powered */ |
| 529 | if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) { | 569 | if (!adv7511->powered) { |
| 530 | regmap_write(adv7511->regmap, ADV7511_REG_INT(0), | 570 | regmap_write(adv7511->regmap, ADV7511_REG_INT(0), |
| 531 | ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR); | 571 | ADV7511_INT0_EDID_READY); |
| 572 | regmap_write(adv7511->regmap, ADV7511_REG_INT(1), | ||
| 573 | ADV7511_INT1_DDC_ERROR); | ||
| 532 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | 574 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, |
| 533 | ADV7511_POWER_POWER_DOWN, 0); | 575 | ADV7511_POWER_POWER_DOWN, 0); |
| 534 | adv7511->current_edid_segment = -1; | 576 | adv7511->current_edid_segment = -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,41 +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 | ADV7511_INT1_DDC_ERROR); | ||
| 567 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | ||
| 568 | ADV7511_POWER_POWER_DOWN, 0); | ||
| 569 | /* | ||
| 570 | * Per spec it is allowed to pulse the HDP signal to indicate | ||
| 571 | * that the EDID information has changed. Some monitors do this | ||
| 572 | * when they wakeup from standby or are enabled. When the HDP | ||
| 573 | * goes low the adv7511 is reset and the outputs are disabled | ||
| 574 | * which might cause the monitor to go to standby again. To | ||
| 575 | * avoid this we ignore the HDP pin for the first few seconds | ||
| 576 | * after enabling the output. | ||
| 577 | */ | ||
| 578 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2, | ||
| 579 | ADV7511_REG_POWER2_HDP_SRC_MASK, | ||
| 580 | ADV7511_REG_POWER2_HDP_SRC_NONE); | ||
| 581 | /* Most of the registers are reset during power down or | ||
| 582 | * when HPD is low | ||
| 583 | */ | ||
| 584 | regcache_sync(adv7511->regmap); | ||
| 585 | break; | ||
| 586 | default: | ||
| 587 | /* TODO: setup additional power down modes */ | ||
| 588 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | ||
| 589 | ADV7511_POWER_POWER_DOWN, | ||
| 590 | ADV7511_POWER_POWER_DOWN); | ||
| 591 | regcache_mark_dirty(adv7511->regmap); | ||
| 592 | break; | ||
| 593 | } | ||
| 594 | |||
| 595 | adv7511->dpms_mode = mode; | ||
| 596 | } | 607 | } |
| 597 | 608 | ||
| 598 | static enum drm_connector_status | 609 | static enum drm_connector_status |
| @@ -620,10 +631,9 @@ adv7511_encoder_detect(struct drm_encoder *encoder, | |||
| 620 | * 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 |
| 621 | * at least one transition from disconnected to connected and the chip | 632 | * at least one transition from disconnected to connected and the chip |
| 622 | * has to be reinitialized. */ | 633 | * has to be reinitialized. */ |
| 623 | if (status == connector_status_connected && hpd && | 634 | if (status == connector_status_connected && hpd && adv7511->powered) { |
| 624 | adv7511->dpms_mode == DRM_MODE_DPMS_ON) { | ||
| 625 | regcache_mark_dirty(adv7511->regmap); | 635 | regcache_mark_dirty(adv7511->regmap); |
| 626 | adv7511_encoder_dpms(encoder, adv7511->dpms_mode); | 636 | adv7511_power_on(adv7511); |
| 627 | adv7511_get_modes(encoder, connector); | 637 | adv7511_get_modes(encoder, connector); |
| 628 | if (adv7511->status == connector_status_connected) | 638 | if (adv7511->status == connector_status_connected) |
| 629 | status = connector_status_disconnected; | 639 | status = connector_status_disconnected; |
| @@ -858,7 +868,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | |||
| 858 | if (!adv7511) | 868 | if (!adv7511) |
| 859 | return -ENOMEM; | 869 | return -ENOMEM; |
| 860 | 870 | ||
| 861 | adv7511->dpms_mode = DRM_MODE_DPMS_OFF; | 871 | adv7511->powered = false; |
| 862 | adv7511->status = connector_status_disconnected; | 872 | adv7511->status = connector_status_disconnected; |
| 863 | 873 | ||
| 864 | ret = adv7511_parse_dt(dev->of_node, &link_config); | 874 | ret = adv7511_parse_dt(dev->of_node, &link_config); |
| @@ -918,10 +928,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | |||
| 918 | regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, | 928 | regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, |
| 919 | ADV7511_CEC_CTRL_POWER_DOWN); | 929 | ADV7511_CEC_CTRL_POWER_DOWN); |
| 920 | 930 | ||
| 921 | regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, | 931 | adv7511_power_off(adv7511); |
| 922 | ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN); | ||
| 923 | |||
| 924 | adv7511->current_edid_segment = -1; | ||
| 925 | 932 | ||
| 926 | i2c_set_clientdata(i2c, adv7511); | 933 | i2c_set_clientdata(i2c, adv7511); |
| 927 | 934 | ||
