Skip to content

Commit c932ced

Browse files
Aradhya Bhatiamartinezjavier
authored andcommitted
drm/tidss: Update encoder/bridge chain connect model
With the new encoder/bridge chain model, the display controller driver is required to create a drm_connector entity instead of asking the bridge to do so during drm_bridge_attach. Moreover, the controller driver should create a drm_bridge entity to negotiate bus formats and a 'simple' drm_encoder entity to expose it to userspace. Update the encoder/bridge initialization sequence in tidss as per the new model. Signed-off-by: Aradhya Bhatia <[email protected]> Reviewed-by: Tomi Valkeinen <[email protected]> Signed-off-by: Javier Martinez Canillas <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent b1c08ff commit c932ced

File tree

3 files changed

+94
-63
lines changed

3 files changed

+94
-63
lines changed

drivers/gpu/drm/tidss/tidss_encoder.c

Lines changed: 87 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,91 +6,125 @@
66

77
#include <linux/export.h>
88

9+
#include <drm/drm_atomic_helper.h>
10+
#include <drm/drm_bridge.h>
11+
#include <drm/drm_bridge_connector.h>
912
#include <drm/drm_crtc.h>
1013
#include <drm/drm_modeset_helper_vtables.h>
1114
#include <drm/drm_panel.h>
1215
#include <drm/drm_of.h>
16+
#include <drm/drm_simple_kms_helper.h>
1317

1418
#include "tidss_crtc.h"
1519
#include "tidss_drv.h"
1620
#include "tidss_encoder.h"
1721

18-
static int tidss_encoder_atomic_check(struct drm_encoder *encoder,
19-
struct drm_crtc_state *crtc_state,
20-
struct drm_connector_state *conn_state)
22+
struct tidss_encoder {
23+
struct drm_bridge bridge;
24+
struct drm_encoder encoder;
25+
struct drm_connector *connector;
26+
struct drm_bridge *next_bridge;
27+
struct tidss_device *tidss;
28+
};
29+
30+
static inline struct tidss_encoder
31+
*bridge_to_tidss_encoder(struct drm_bridge *b)
32+
{
33+
return container_of(b, struct tidss_encoder, bridge);
34+
}
35+
36+
static int tidss_bridge_attach(struct drm_bridge *bridge,
37+
enum drm_bridge_attach_flags flags)
38+
{
39+
struct tidss_encoder *t_enc = bridge_to_tidss_encoder(bridge);
40+
41+
return drm_bridge_attach(bridge->encoder, t_enc->next_bridge,
42+
bridge, flags);
43+
}
44+
45+
static int tidss_bridge_atomic_check(struct drm_bridge *bridge,
46+
struct drm_bridge_state *bridge_state,
47+
struct drm_crtc_state *crtc_state,
48+
struct drm_connector_state *conn_state)
2149
{
22-
struct drm_device *ddev = encoder->dev;
50+
struct tidss_encoder *t_enc = bridge_to_tidss_encoder(bridge);
51+
struct tidss_device *tidss = t_enc->tidss;
2352
struct tidss_crtc_state *tcrtc_state = to_tidss_crtc_state(crtc_state);
2453
struct drm_display_info *di = &conn_state->connector->display_info;
25-
struct drm_bridge *bridge;
26-
bool bus_flags_set = false;
27-
28-
dev_dbg(ddev->dev, "%s\n", __func__);
29-
30-
/*
31-
* Take the bus_flags from the first bridge that defines
32-
* bridge timings, or from the connector's display_info if no
33-
* bridge defines the timings.
34-
*/
35-
drm_for_each_bridge_in_chain(encoder, bridge) {
36-
if (!bridge->timings)
37-
continue;
38-
39-
tcrtc_state->bus_flags = bridge->timings->input_bus_flags;
40-
bus_flags_set = true;
41-
break;
42-
}
54+
struct drm_bridge_state *next_bridge_state = NULL;
55+
56+
if (t_enc->next_bridge)
57+
next_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
58+
t_enc->next_bridge);
4359

44-
if (!di->bus_formats || di->num_bus_formats == 0) {
45-
dev_err(ddev->dev, "%s: No bus_formats in connected display\n",
60+
if (next_bridge_state) {
61+
tcrtc_state->bus_flags = next_bridge_state->input_bus_cfg.flags;
62+
tcrtc_state->bus_format = next_bridge_state->input_bus_cfg.format;
63+
} else if (di->num_bus_formats) {
64+
tcrtc_state->bus_format = di->bus_formats[0];
65+
tcrtc_state->bus_flags = di->bus_flags;
66+
} else {
67+
dev_err(tidss->dev, "%s: No bus_formats in connected display\n",
4668
__func__);
4769
return -EINVAL;
4870
}
4971

50-
// XXX any cleaner way to set bus format and flags?
51-
tcrtc_state->bus_format = di->bus_formats[0];
52-
if (!bus_flags_set)
53-
tcrtc_state->bus_flags = di->bus_flags;
54-
5572
return 0;
5673
}
5774

58-
static void tidss_encoder_destroy(struct drm_encoder *encoder)
59-
{
60-
drm_encoder_cleanup(encoder);
61-
kfree(encoder);
62-
}
63-
64-
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
65-
.atomic_check = tidss_encoder_atomic_check,
66-
};
67-
68-
static const struct drm_encoder_funcs encoder_funcs = {
69-
.destroy = tidss_encoder_destroy,
75+
static const struct drm_bridge_funcs tidss_bridge_funcs = {
76+
.attach = tidss_bridge_attach,
77+
.atomic_check = tidss_bridge_atomic_check,
78+
.atomic_reset = drm_atomic_helper_bridge_reset,
79+
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
80+
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
7081
};
7182

72-
struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
73-
u32 encoder_type, u32 possible_crtcs)
83+
int tidss_encoder_create(struct tidss_device *tidss,
84+
struct drm_bridge *next_bridge,
85+
u32 encoder_type, u32 possible_crtcs)
7486
{
87+
struct tidss_encoder *t_enc;
7588
struct drm_encoder *enc;
89+
struct drm_connector *connector;
7690
int ret;
7791

78-
enc = kzalloc(sizeof(*enc), GFP_KERNEL);
79-
if (!enc)
80-
return ERR_PTR(-ENOMEM);
92+
t_enc = drmm_simple_encoder_alloc(&tidss->ddev, struct tidss_encoder,
93+
encoder, encoder_type);
94+
if (IS_ERR(t_enc))
95+
return PTR_ERR(t_enc);
96+
97+
t_enc->tidss = tidss;
98+
t_enc->next_bridge = next_bridge;
99+
t_enc->bridge.funcs = &tidss_bridge_funcs;
81100

101+
enc = &t_enc->encoder;
82102
enc->possible_crtcs = possible_crtcs;
83103

84-
ret = drm_encoder_init(&tidss->ddev, enc, &encoder_funcs,
85-
encoder_type, NULL);
86-
if (ret < 0) {
87-
kfree(enc);
88-
return ERR_PTR(ret);
104+
/* Attaching first bridge to the encoder */
105+
ret = drm_bridge_attach(enc, &t_enc->bridge, NULL,
106+
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
107+
if (ret) {
108+
dev_err(tidss->dev, "bridge attach failed: %d\n", ret);
109+
return ret;
110+
}
111+
112+
/* Initializing the connector at the end of bridge-chain */
113+
connector = drm_bridge_connector_init(&tidss->ddev, enc);
114+
if (IS_ERR(connector)) {
115+
dev_err(tidss->dev, "bridge_connector create failed\n");
116+
return PTR_ERR(connector);
117+
}
118+
119+
ret = drm_connector_attach_encoder(connector, enc);
120+
if (ret) {
121+
dev_err(tidss->dev, "attaching encoder to connector failed\n");
122+
return ret;
89123
}
90124

91-
drm_encoder_helper_add(enc, &encoder_helper_funcs);
125+
t_enc->connector = connector;
92126

93127
dev_dbg(tidss->dev, "Encoder create done\n");
94128

95-
return enc;
129+
return ret;
96130
}

drivers/gpu/drm/tidss/tidss_encoder.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
struct tidss_device;
1313

14-
struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
15-
u32 encoder_type, u32 possible_crtcs);
14+
int tidss_encoder_create(struct tidss_device *tidss,
15+
struct drm_bridge *next_bridge,
16+
u32 encoder_type, u32 possible_crtcs);
1617

1718
#endif

drivers/gpu/drm/tidss/tidss_kms.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
193193
for (i = 0; i < num_pipes; ++i) {
194194
struct tidss_plane *tplane;
195195
struct tidss_crtc *tcrtc;
196-
struct drm_encoder *enc;
197196
u32 hw_plane_id = feat->vid_order[tidss->num_planes];
198197
int ret;
199198

@@ -216,16 +215,13 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
216215

217216
tidss->crtcs[tidss->num_crtcs++] = &tcrtc->crtc;
218217

219-
enc = tidss_encoder_create(tidss, pipes[i].enc_type,
218+
ret = tidss_encoder_create(tidss, pipes[i].bridge,
219+
pipes[i].enc_type,
220220
1 << tcrtc->crtc.index);
221-
if (IS_ERR(enc)) {
221+
if (ret) {
222222
dev_err(tidss->dev, "encoder create failed\n");
223-
return PTR_ERR(enc);
224-
}
225-
226-
ret = drm_bridge_attach(enc, pipes[i].bridge, NULL, 0);
227-
if (ret)
228223
return ret;
224+
}
229225
}
230226

231227
/* create overlay planes of the leftover planes */

0 commit comments

Comments
 (0)