123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- /*
- * Copyright (C) 2012 Russell King
- * Rewritten from the dovefb driver, and Armada510 manuals.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
- #include <drm/drmP.h>
- #include <drm/drm_crtc_helper.h>
- #include <drm/drm_edid.h>
- #include <drm/drm_encoder_slave.h>
- #include "armada_drm.h"
- #include "armada_output.h"
- #include "armada_slave.h"
- static int armada_drm_slave_get_modes(struct drm_connector *conn)
- {
- struct drm_encoder *enc = armada_drm_connector_encoder(conn);
- int count = 0;
- if (enc) {
- struct drm_encoder_slave *slave = to_encoder_slave(enc);
- count = slave->slave_funcs->get_modes(enc, conn);
- }
- return count;
- }
- static void armada_drm_slave_destroy(struct drm_encoder *enc)
- {
- struct drm_encoder_slave *slave = to_encoder_slave(enc);
- struct i2c_client *client = drm_i2c_encoder_get_client(enc);
- if (slave->slave_funcs)
- slave->slave_funcs->destroy(enc);
- if (client)
- i2c_put_adapter(client->adapter);
- drm_encoder_cleanup(&slave->base);
- kfree(slave);
- }
- static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = {
- .destroy = armada_drm_slave_destroy,
- };
- static const struct drm_connector_helper_funcs armada_drm_slave_helper_funcs = {
- .get_modes = armada_drm_slave_get_modes,
- .mode_valid = armada_drm_slave_encoder_mode_valid,
- .best_encoder = armada_drm_connector_encoder,
- };
- static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = {
- .dpms = drm_i2c_encoder_dpms,
- .save = drm_i2c_encoder_save,
- .restore = drm_i2c_encoder_restore,
- .mode_fixup = drm_i2c_encoder_mode_fixup,
- .prepare = drm_i2c_encoder_prepare,
- .commit = drm_i2c_encoder_commit,
- .mode_set = drm_i2c_encoder_mode_set,
- .detect = drm_i2c_encoder_detect,
- };
- static int
- armada_drm_conn_slave_create(struct drm_connector *conn, const void *data)
- {
- const struct armada_drm_slave_config *config = data;
- struct drm_encoder_slave *slave;
- struct i2c_adapter *adap;
- int ret;
- conn->interlace_allowed = config->interlace_allowed;
- conn->doublescan_allowed = config->doublescan_allowed;
- conn->polled = config->polled;
- drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs);
- slave = kzalloc(sizeof(*slave), GFP_KERNEL);
- if (!slave)
- return -ENOMEM;
- slave->base.possible_crtcs = config->crtcs;
- adap = i2c_get_adapter(config->i2c_adapter_id);
- if (!adap) {
- kfree(slave);
- return -EPROBE_DEFER;
- }
- ret = drm_encoder_init(conn->dev, &slave->base,
- &armada_drm_slave_encoder_funcs,
- DRM_MODE_ENCODER_TMDS);
- if (ret) {
- DRM_ERROR("unable to init encoder\n");
- i2c_put_adapter(adap);
- kfree(slave);
- return ret;
- }
- ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info);
- i2c_put_adapter(adap);
- if (ret) {
- DRM_ERROR("unable to init encoder slave\n");
- armada_drm_slave_destroy(&slave->base);
- return ret;
- }
- drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers);
- ret = slave->slave_funcs->create_resources(&slave->base, conn);
- if (ret) {
- armada_drm_slave_destroy(&slave->base);
- return ret;
- }
- ret = drm_mode_connector_attach_encoder(conn, &slave->base);
- if (ret) {
- armada_drm_slave_destroy(&slave->base);
- return ret;
- }
- conn->encoder = &slave->base;
- return ret;
- }
- static const struct armada_output_type armada_drm_conn_slave = {
- .connector_type = DRM_MODE_CONNECTOR_HDMIA,
- .create = armada_drm_conn_slave_create,
- .set_property = armada_drm_slave_encoder_set_property,
- };
- int armada_drm_connector_slave_create(struct drm_device *dev,
- const struct armada_drm_slave_config *config)
- {
- return armada_output_create(dev, &armada_drm_conn_slave, config);
- }
|