Skip to content

Commit ce6cb55

Browse files
atseanpauldaeinki
authored andcommitted
drm/exynos: Implement drm_connector directly in vidi driver
This patch implements drm_connector directly in the vidi driver, this will allow us to move away from the exynos_drm_connector layer. Signed-off-by: Sean Paul <[email protected]> Signed-off-by: Inki Dae <[email protected]>
1 parent caa5d1e commit ce6cb55

File tree

1 file changed

+108
-54
lines changed

1 file changed

+108
-54
lines changed

drivers/gpu/drm/exynos/exynos_drm_vidi.c

Lines changed: 108 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#define WINDOWS_NR 3
3030

3131
#define get_vidi_mgr(dev) platform_get_drvdata(to_platform_device(dev))
32+
#define ctx_from_connector(c) container_of(c, struct vidi_context, \
33+
connector)
3234

3335
struct vidi_win_data {
3436
unsigned int offset_x;
@@ -47,6 +49,8 @@ struct vidi_win_data {
4749
struct vidi_context {
4850
struct drm_device *drm_dev;
4951
struct drm_crtc *crtc;
52+
struct drm_encoder *encoder;
53+
struct drm_connector connector;
5054
struct vidi_win_data win_data[WINDOWS_NR];
5155
struct edid *raw_edid;
5256
unsigned int clkdiv;
@@ -86,60 +90,6 @@ static const char fake_edid_info[] = {
8690
0x00, 0x00, 0x00, 0x06
8791
};
8892

89-
static bool vidi_display_is_connected(struct exynos_drm_display *display)
90-
{
91-
struct vidi_context *ctx = display->ctx;
92-
93-
/*
94-
* connection request would come from user side
95-
* to do hotplug through specific ioctl.
96-
*/
97-
return ctx->connected ? true : false;
98-
}
99-
100-
static struct edid *vidi_get_edid(struct exynos_drm_display *display,
101-
struct drm_connector *connector)
102-
{
103-
struct vidi_context *ctx = display->ctx;
104-
struct edid *edid;
105-
106-
/*
107-
* the edid data comes from user side and it would be set
108-
* to ctx->raw_edid through specific ioctl.
109-
*/
110-
if (!ctx->raw_edid) {
111-
DRM_DEBUG_KMS("raw_edid is null.\n");
112-
return ERR_PTR(-EFAULT);
113-
}
114-
115-
edid = drm_edid_duplicate(ctx->raw_edid);
116-
if (!edid) {
117-
DRM_DEBUG_KMS("failed to allocate edid\n");
118-
return ERR_PTR(-ENOMEM);
119-
}
120-
121-
return edid;
122-
}
123-
124-
static int vidi_check_mode(struct exynos_drm_display *display,
125-
struct drm_display_mode *mode)
126-
{
127-
/* TODO. */
128-
129-
return 0;
130-
}
131-
132-
static struct exynos_drm_display_ops vidi_display_ops = {
133-
.is_connected = vidi_display_is_connected,
134-
.get_edid = vidi_get_edid,
135-
.check_mode = vidi_check_mode,
136-
};
137-
138-
static struct exynos_drm_display vidi_display = {
139-
.type = EXYNOS_DISPLAY_TYPE_VIDI,
140-
.ops = &vidi_display_ops,
141-
};
142-
14393
static void vidi_apply(struct exynos_drm_manager *mgr)
14494
{
14595
struct vidi_context *ctx = mgr->ctx;
@@ -532,6 +482,110 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
532482
return 0;
533483
}
534484

485+
static enum drm_connector_status vidi_detect(struct drm_connector *connector,
486+
bool force)
487+
{
488+
struct vidi_context *ctx = ctx_from_connector(connector);
489+
490+
/*
491+
* connection request would come from user side
492+
* to do hotplug through specific ioctl.
493+
*/
494+
return ctx->connected ? connector_status_connected :
495+
connector_status_disconnected;
496+
}
497+
498+
static void vidi_connector_destroy(struct drm_connector *connector)
499+
{
500+
}
501+
502+
static struct drm_connector_funcs vidi_connector_funcs = {
503+
.dpms = drm_helper_connector_dpms,
504+
.fill_modes = drm_helper_probe_single_connector_modes,
505+
.detect = vidi_detect,
506+
.destroy = vidi_connector_destroy,
507+
};
508+
509+
static int vidi_get_modes(struct drm_connector *connector)
510+
{
511+
struct vidi_context *ctx = ctx_from_connector(connector);
512+
struct edid *edid;
513+
int edid_len;
514+
515+
/*
516+
* the edid data comes from user side and it would be set
517+
* to ctx->raw_edid through specific ioctl.
518+
*/
519+
if (!ctx->raw_edid) {
520+
DRM_DEBUG_KMS("raw_edid is null.\n");
521+
return -EFAULT;
522+
}
523+
524+
edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
525+
edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
526+
if (!edid) {
527+
DRM_DEBUG_KMS("failed to allocate edid\n");
528+
return -ENOMEM;
529+
}
530+
531+
drm_mode_connector_update_edid_property(connector, edid);
532+
533+
return drm_add_edid_modes(connector, edid);
534+
}
535+
536+
static int vidi_mode_valid(struct drm_connector *connector,
537+
struct drm_display_mode *mode)
538+
{
539+
return MODE_OK;
540+
}
541+
542+
static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector)
543+
{
544+
struct vidi_context *ctx = ctx_from_connector(connector);
545+
546+
return ctx->encoder;
547+
}
548+
549+
static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
550+
.get_modes = vidi_get_modes,
551+
.mode_valid = vidi_mode_valid,
552+
.best_encoder = vidi_best_encoder,
553+
};
554+
555+
static int vidi_create_connector(struct exynos_drm_display *display,
556+
struct drm_encoder *encoder)
557+
{
558+
struct vidi_context *ctx = display->ctx;
559+
struct drm_connector *connector = &ctx->connector;
560+
int ret;
561+
562+
ctx->encoder = encoder;
563+
connector->polled = DRM_CONNECTOR_POLL_HPD;
564+
565+
ret = drm_connector_init(ctx->drm_dev, connector,
566+
&vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
567+
if (ret) {
568+
DRM_ERROR("Failed to initialize connector with drm\n");
569+
return ret;
570+
}
571+
572+
drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
573+
drm_sysfs_connector_add(connector);
574+
drm_mode_connector_attach_encoder(connector, encoder);
575+
576+
return 0;
577+
}
578+
579+
580+
static struct exynos_drm_display_ops vidi_display_ops = {
581+
.create_connector = vidi_create_connector,
582+
};
583+
584+
static struct exynos_drm_display vidi_display = {
585+
.type = EXYNOS_DISPLAY_TYPE_VIDI,
586+
.ops = &vidi_display_ops,
587+
};
588+
535589
static int vidi_probe(struct platform_device *pdev)
536590
{
537591
struct device *dev = &pdev->dev;

0 commit comments

Comments
 (0)