xref: /linux/drivers/gpu/drm/tilcdc/tilcdc_encoder.c (revision cb18dbb74f46bd0aa612aaae144dd191c548739c)
1*cb18dbb7SKory Maincent (TI.com) // SPDX-License-Identifier: GPL-2.0-only
2*cb18dbb7SKory Maincent (TI.com) /*
3*cb18dbb7SKory Maincent (TI.com)  * Copyright (C) 2015 Texas Instruments
4*cb18dbb7SKory Maincent (TI.com)  * Author: Jyri Sarha <jsarha@ti.com>
5*cb18dbb7SKory Maincent (TI.com)  */
6*cb18dbb7SKory Maincent (TI.com) 
7*cb18dbb7SKory Maincent (TI.com) #include <linux/of_graph.h>
8*cb18dbb7SKory Maincent (TI.com) 
9*cb18dbb7SKory Maincent (TI.com) #include <drm/drm_atomic_helper.h>
10*cb18dbb7SKory Maincent (TI.com) #include <drm/drm_bridge.h>
11*cb18dbb7SKory Maincent (TI.com) #include <drm/drm_of.h>
12*cb18dbb7SKory Maincent (TI.com) #include <drm/drm_simple_kms_helper.h>
13*cb18dbb7SKory Maincent (TI.com) 
14*cb18dbb7SKory Maincent (TI.com) #include "tilcdc_drv.h"
15*cb18dbb7SKory Maincent (TI.com) #include "tilcdc_encoder.h"
16*cb18dbb7SKory Maincent (TI.com) 
17*cb18dbb7SKory Maincent (TI.com) static
18*cb18dbb7SKory Maincent (TI.com) struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev,
19*cb18dbb7SKory Maincent (TI.com) 						    struct drm_encoder *encoder)
20*cb18dbb7SKory Maincent (TI.com) {
21*cb18dbb7SKory Maincent (TI.com) 	struct drm_connector *connector;
22*cb18dbb7SKory Maincent (TI.com) 
23*cb18dbb7SKory Maincent (TI.com) 	list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
24*cb18dbb7SKory Maincent (TI.com) 		if (drm_connector_has_possible_encoder(connector, encoder))
25*cb18dbb7SKory Maincent (TI.com) 			return connector;
26*cb18dbb7SKory Maincent (TI.com) 	}
27*cb18dbb7SKory Maincent (TI.com) 
28*cb18dbb7SKory Maincent (TI.com) 	dev_err(ddev->dev, "No connector found for %s encoder (id %d)\n",
29*cb18dbb7SKory Maincent (TI.com) 		encoder->name, encoder->base.id);
30*cb18dbb7SKory Maincent (TI.com) 
31*cb18dbb7SKory Maincent (TI.com) 	return NULL;
32*cb18dbb7SKory Maincent (TI.com) }
33*cb18dbb7SKory Maincent (TI.com) 
34*cb18dbb7SKory Maincent (TI.com) static
35*cb18dbb7SKory Maincent (TI.com) int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
36*cb18dbb7SKory Maincent (TI.com) {
37*cb18dbb7SKory Maincent (TI.com) 	struct tilcdc_drm_private *priv = ddev->dev_private;
38*cb18dbb7SKory Maincent (TI.com) 	int ret;
39*cb18dbb7SKory Maincent (TI.com) 
40*cb18dbb7SKory Maincent (TI.com) 	priv->encoder->possible_crtcs = BIT(0);
41*cb18dbb7SKory Maincent (TI.com) 
42*cb18dbb7SKory Maincent (TI.com) 	ret = drm_bridge_attach(priv->encoder, bridge, NULL, 0);
43*cb18dbb7SKory Maincent (TI.com) 	if (ret)
44*cb18dbb7SKory Maincent (TI.com) 		return ret;
45*cb18dbb7SKory Maincent (TI.com) 
46*cb18dbb7SKory Maincent (TI.com) 	priv->connector = tilcdc_encoder_find_connector(ddev, priv->encoder);
47*cb18dbb7SKory Maincent (TI.com) 	if (!priv->connector)
48*cb18dbb7SKory Maincent (TI.com) 		return -ENODEV;
49*cb18dbb7SKory Maincent (TI.com) 
50*cb18dbb7SKory Maincent (TI.com) 	return 0;
51*cb18dbb7SKory Maincent (TI.com) }
52*cb18dbb7SKory Maincent (TI.com) 
53*cb18dbb7SKory Maincent (TI.com) int tilcdc_encoder_create(struct drm_device *ddev)
54*cb18dbb7SKory Maincent (TI.com) {
55*cb18dbb7SKory Maincent (TI.com) 	struct tilcdc_drm_private *priv = ddev->dev_private;
56*cb18dbb7SKory Maincent (TI.com) 	struct drm_bridge *bridge;
57*cb18dbb7SKory Maincent (TI.com) 	struct drm_panel *panel;
58*cb18dbb7SKory Maincent (TI.com) 	int ret;
59*cb18dbb7SKory Maincent (TI.com) 
60*cb18dbb7SKory Maincent (TI.com) 	ret = drm_of_find_panel_or_bridge(ddev->dev->of_node, 0, 0,
61*cb18dbb7SKory Maincent (TI.com) 					  &panel, &bridge);
62*cb18dbb7SKory Maincent (TI.com) 	if (ret == -ENODEV)
63*cb18dbb7SKory Maincent (TI.com) 		return 0;
64*cb18dbb7SKory Maincent (TI.com) 	else if (ret)
65*cb18dbb7SKory Maincent (TI.com) 		return ret;
66*cb18dbb7SKory Maincent (TI.com) 
67*cb18dbb7SKory Maincent (TI.com) 	priv->encoder = devm_kzalloc(ddev->dev, sizeof(*priv->encoder), GFP_KERNEL);
68*cb18dbb7SKory Maincent (TI.com) 	if (!priv->encoder)
69*cb18dbb7SKory Maincent (TI.com) 		return -ENOMEM;
70*cb18dbb7SKory Maincent (TI.com) 
71*cb18dbb7SKory Maincent (TI.com) 	ret = drm_simple_encoder_init(ddev, priv->encoder,
72*cb18dbb7SKory Maincent (TI.com) 				      DRM_MODE_ENCODER_NONE);
73*cb18dbb7SKory Maincent (TI.com) 	if (ret) {
74*cb18dbb7SKory Maincent (TI.com) 		dev_err(ddev->dev, "drm_encoder_init() failed %d\n", ret);
75*cb18dbb7SKory Maincent (TI.com) 		return ret;
76*cb18dbb7SKory Maincent (TI.com) 	}
77*cb18dbb7SKory Maincent (TI.com) 
78*cb18dbb7SKory Maincent (TI.com) 	if (panel) {
79*cb18dbb7SKory Maincent (TI.com) 		bridge = devm_drm_panel_bridge_add_typed(ddev->dev, panel,
80*cb18dbb7SKory Maincent (TI.com) 							 DRM_MODE_CONNECTOR_DPI);
81*cb18dbb7SKory Maincent (TI.com) 		if (IS_ERR(bridge)) {
82*cb18dbb7SKory Maincent (TI.com) 			ret = PTR_ERR(bridge);
83*cb18dbb7SKory Maincent (TI.com) 			goto err_encoder_cleanup;
84*cb18dbb7SKory Maincent (TI.com) 		}
85*cb18dbb7SKory Maincent (TI.com) 	}
86*cb18dbb7SKory Maincent (TI.com) 
87*cb18dbb7SKory Maincent (TI.com) 	ret = tilcdc_attach_bridge(ddev, bridge);
88*cb18dbb7SKory Maincent (TI.com) 	if (ret)
89*cb18dbb7SKory Maincent (TI.com) 		goto err_encoder_cleanup;
90*cb18dbb7SKory Maincent (TI.com) 
91*cb18dbb7SKory Maincent (TI.com) 	return 0;
92*cb18dbb7SKory Maincent (TI.com) 
93*cb18dbb7SKory Maincent (TI.com) err_encoder_cleanup:
94*cb18dbb7SKory Maincent (TI.com) 	drm_encoder_cleanup(priv->encoder);
95*cb18dbb7SKory Maincent (TI.com) 	return ret;
96*cb18dbb7SKory Maincent (TI.com) }
97