PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / gpu / drm / armada / armada_slave.c
blob00d0facb42f3e3cf5f3ff9125e574033b38cd9c8
1 /*
2 * Copyright (C) 2012 Russell King
3 * Rewritten from the dovefb driver, and Armada510 manuals.
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"
17 static int armada_drm_slave_get_modes(struct drm_connector *conn)
19 struct drm_encoder *enc = armada_drm_connector_encoder(conn);
20 int count = 0;
22 if (enc) {
23 struct drm_encoder_slave *slave = to_encoder_slave(enc);
25 count = slave->slave_funcs->get_modes(enc, conn);
28 return count;
31 static void armada_drm_slave_destroy(struct drm_encoder *enc)
33 struct drm_encoder_slave *slave = to_encoder_slave(enc);
34 struct i2c_client *client = drm_i2c_encoder_get_client(enc);
36 if (slave->slave_funcs)
37 slave->slave_funcs->destroy(enc);
38 if (client)
39 i2c_put_adapter(client->adapter);
41 drm_encoder_cleanup(&slave->base);
42 kfree(slave);
45 static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = {
46 .destroy = armada_drm_slave_destroy,
49 static const struct drm_connector_helper_funcs armada_drm_slave_helper_funcs = {
50 .get_modes = armada_drm_slave_get_modes,
51 .mode_valid = armada_drm_slave_encoder_mode_valid,
52 .best_encoder = armada_drm_connector_encoder,
55 static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = {
56 .dpms = drm_i2c_encoder_dpms,
57 .save = drm_i2c_encoder_save,
58 .restore = drm_i2c_encoder_restore,
59 .mode_fixup = drm_i2c_encoder_mode_fixup,
60 .prepare = drm_i2c_encoder_prepare,
61 .commit = drm_i2c_encoder_commit,
62 .mode_set = drm_i2c_encoder_mode_set,
63 .detect = drm_i2c_encoder_detect,
66 static int
67 armada_drm_conn_slave_create(struct drm_connector *conn, const void *data)
69 const struct armada_drm_slave_config *config = data;
70 struct drm_encoder_slave *slave;
71 struct i2c_adapter *adap;
72 int ret;
74 conn->interlace_allowed = config->interlace_allowed;
75 conn->doublescan_allowed = config->doublescan_allowed;
76 conn->polled = config->polled;
78 drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs);
80 slave = kzalloc(sizeof(*slave), GFP_KERNEL);
81 if (!slave)
82 return -ENOMEM;
84 slave->base.possible_crtcs = config->crtcs;
86 adap = i2c_get_adapter(config->i2c_adapter_id);
87 if (!adap) {
88 kfree(slave);
89 return -EPROBE_DEFER;
92 ret = drm_encoder_init(conn->dev, &slave->base,
93 &armada_drm_slave_encoder_funcs,
94 DRM_MODE_ENCODER_TMDS);
95 if (ret) {
96 DRM_ERROR("unable to init encoder\n");
97 i2c_put_adapter(adap);
98 kfree(slave);
99 return ret;
102 ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info);
103 i2c_put_adapter(adap);
104 if (ret) {
105 DRM_ERROR("unable to init encoder slave\n");
106 armada_drm_slave_destroy(&slave->base);
107 return ret;
110 drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers);
112 ret = slave->slave_funcs->create_resources(&slave->base, conn);
113 if (ret) {
114 armada_drm_slave_destroy(&slave->base);
115 return ret;
118 ret = drm_mode_connector_attach_encoder(conn, &slave->base);
119 if (ret) {
120 armada_drm_slave_destroy(&slave->base);
121 return ret;
124 conn->encoder = &slave->base;
126 return ret;
129 static const struct armada_output_type armada_drm_conn_slave = {
130 .connector_type = DRM_MODE_CONNECTOR_HDMIA,
131 .create = armada_drm_conn_slave_create,
132 .set_property = armada_drm_slave_encoder_set_property,
135 int armada_drm_connector_slave_create(struct drm_device *dev,
136 const struct armada_drm_slave_config *config)
138 return armada_output_create(dev, &armada_drm_conn_slave, config);