2 * Copyright (C) 2012 Russell King
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <drm/drm_crtc_helper.h>
10 #include <drm/drm_edid.h>
11 #include <drm/drm_encoder_slave.h>
12 #include "armada_output.h"
13 #include "armada_drm.h"
15 struct armada_connector
{
16 struct drm_connector conn
;
17 const struct armada_output_type
*type
;
20 #define drm_to_armada_conn(c) container_of(c, struct armada_connector, conn)
22 struct drm_encoder
*armada_drm_connector_encoder(struct drm_connector
*conn
)
24 struct drm_encoder
*enc
= conn
->encoder
;
26 return enc
? enc
: drm_encoder_find(conn
->dev
, conn
->encoder_ids
[0]);
29 static enum drm_connector_status
armada_drm_connector_detect(
30 struct drm_connector
*conn
, bool force
)
32 struct armada_connector
*dconn
= drm_to_armada_conn(conn
);
33 enum drm_connector_status status
= connector_status_disconnected
;
35 if (dconn
->type
->detect
) {
36 status
= dconn
->type
->detect(conn
, force
);
38 struct drm_encoder
*enc
= armada_drm_connector_encoder(conn
);
41 status
= encoder_helper_funcs(enc
)->detect(enc
, conn
);
47 static void armada_drm_connector_destroy(struct drm_connector
*conn
)
49 struct armada_connector
*dconn
= drm_to_armada_conn(conn
);
51 drm_connector_unregister(conn
);
52 drm_connector_cleanup(conn
);
56 static int armada_drm_connector_set_property(struct drm_connector
*conn
,
57 struct drm_property
*property
, uint64_t value
)
59 struct armada_connector
*dconn
= drm_to_armada_conn(conn
);
61 if (!dconn
->type
->set_property
)
64 return dconn
->type
->set_property(conn
, property
, value
);
67 static const struct drm_connector_funcs armada_drm_conn_funcs
= {
68 .dpms
= drm_helper_connector_dpms
,
69 .fill_modes
= drm_helper_probe_single_connector_modes
,
70 .detect
= armada_drm_connector_detect
,
71 .destroy
= armada_drm_connector_destroy
,
72 .set_property
= armada_drm_connector_set_property
,
75 /* Shouldn't this be a generic helper function? */
76 int armada_drm_slave_encoder_mode_valid(struct drm_connector
*conn
,
77 struct drm_display_mode
*mode
)
79 struct drm_encoder
*encoder
= armada_drm_connector_encoder(conn
);
83 struct drm_encoder_slave
*slave
= to_encoder_slave(encoder
);
85 valid
= slave
->slave_funcs
->mode_valid(encoder
, mode
);
90 int armada_drm_slave_encoder_set_property(struct drm_connector
*conn
,
91 struct drm_property
*property
, uint64_t value
)
93 struct drm_encoder
*encoder
= armada_drm_connector_encoder(conn
);
97 struct drm_encoder_slave
*slave
= to_encoder_slave(encoder
);
99 rc
= slave
->slave_funcs
->set_property(encoder
, conn
, property
,
105 int armada_output_create(struct drm_device
*dev
,
106 const struct armada_output_type
*type
, const void *data
)
108 struct armada_connector
*dconn
;
111 dconn
= kzalloc(sizeof(*dconn
), GFP_KERNEL
);
117 ret
= drm_connector_init(dev
, &dconn
->conn
, &armada_drm_conn_funcs
,
118 type
->connector_type
);
120 DRM_ERROR("unable to init connector\n");
121 goto err_destroy_dconn
;
124 ret
= type
->create(&dconn
->conn
, data
);
128 ret
= drm_connector_register(&dconn
->conn
);
135 if (dconn
->conn
.encoder
)
136 dconn
->conn
.encoder
->funcs
->destroy(dconn
->conn
.encoder
);
138 drm_connector_cleanup(&dconn
->conn
);