armada_slave.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Copyright (C) 2012 Russell King
  3. * Rewritten from the dovefb driver, and Armada510 manuals.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <drm/drmP.h>
  10. #include <drm/drm_crtc_helper.h>
  11. #include <drm/drm_edid.h>
  12. #include <drm/drm_encoder_slave.h>
  13. #include "armada_drm.h"
  14. #include "armada_output.h"
  15. #include "armada_slave.h"
  16. static int armada_drm_slave_get_modes(struct drm_connector *conn)
  17. {
  18. struct drm_encoder *enc = armada_drm_connector_encoder(conn);
  19. int count = 0;
  20. if (enc) {
  21. struct drm_encoder_slave *slave = to_encoder_slave(enc);
  22. count = slave->slave_funcs->get_modes(enc, conn);
  23. }
  24. return count;
  25. }
  26. static void armada_drm_slave_destroy(struct drm_encoder *enc)
  27. {
  28. struct drm_encoder_slave *slave = to_encoder_slave(enc);
  29. struct i2c_client *client = drm_i2c_encoder_get_client(enc);
  30. if (slave->slave_funcs)
  31. slave->slave_funcs->destroy(enc);
  32. if (client)
  33. i2c_put_adapter(client->adapter);
  34. drm_encoder_cleanup(&slave->base);
  35. kfree(slave);
  36. }
  37. static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = {
  38. .destroy = armada_drm_slave_destroy,
  39. };
  40. static const struct drm_connector_helper_funcs armada_drm_slave_helper_funcs = {
  41. .get_modes = armada_drm_slave_get_modes,
  42. .mode_valid = armada_drm_slave_encoder_mode_valid,
  43. .best_encoder = armada_drm_connector_encoder,
  44. };
  45. static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = {
  46. .dpms = drm_i2c_encoder_dpms,
  47. .save = drm_i2c_encoder_save,
  48. .restore = drm_i2c_encoder_restore,
  49. .mode_fixup = drm_i2c_encoder_mode_fixup,
  50. .prepare = drm_i2c_encoder_prepare,
  51. .commit = drm_i2c_encoder_commit,
  52. .mode_set = drm_i2c_encoder_mode_set,
  53. .detect = drm_i2c_encoder_detect,
  54. };
  55. static int
  56. armada_drm_conn_slave_create(struct drm_connector *conn, const void *data)
  57. {
  58. const struct armada_drm_slave_config *config = data;
  59. struct drm_encoder_slave *slave;
  60. struct i2c_adapter *adap;
  61. int ret;
  62. conn->interlace_allowed = config->interlace_allowed;
  63. conn->doublescan_allowed = config->doublescan_allowed;
  64. conn->polled = config->polled;
  65. drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs);
  66. slave = kzalloc(sizeof(*slave), GFP_KERNEL);
  67. if (!slave)
  68. return -ENOMEM;
  69. slave->base.possible_crtcs = config->crtcs;
  70. adap = i2c_get_adapter(config->i2c_adapter_id);
  71. if (!adap) {
  72. kfree(slave);
  73. return -EPROBE_DEFER;
  74. }
  75. ret = drm_encoder_init(conn->dev, &slave->base,
  76. &armada_drm_slave_encoder_funcs,
  77. DRM_MODE_ENCODER_TMDS);
  78. if (ret) {
  79. DRM_ERROR("unable to init encoder\n");
  80. i2c_put_adapter(adap);
  81. kfree(slave);
  82. return ret;
  83. }
  84. ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info);
  85. i2c_put_adapter(adap);
  86. if (ret) {
  87. DRM_ERROR("unable to init encoder slave\n");
  88. armada_drm_slave_destroy(&slave->base);
  89. return ret;
  90. }
  91. drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers);
  92. ret = slave->slave_funcs->create_resources(&slave->base, conn);
  93. if (ret) {
  94. armada_drm_slave_destroy(&slave->base);
  95. return ret;
  96. }
  97. ret = drm_mode_connector_attach_encoder(conn, &slave->base);
  98. if (ret) {
  99. armada_drm_slave_destroy(&slave->base);
  100. return ret;
  101. }
  102. conn->encoder = &slave->base;
  103. return ret;
  104. }
  105. static const struct armada_output_type armada_drm_conn_slave = {
  106. .connector_type = DRM_MODE_CONNECTOR_HDMIA,
  107. .create = armada_drm_conn_slave_create,
  108. .set_property = armada_drm_slave_encoder_set_property,
  109. };
  110. int armada_drm_connector_slave_create(struct drm_device *dev,
  111. const struct armada_drm_slave_config *config)
  112. {
  113. return armada_output_create(dev, &armada_drm_conn_slave, config);
  114. }