1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * RZ/G2L Display Unit Encoder
4 *
5 * Copyright (C) 2023 Renesas Electronics Corporation
6 *
7 * Based on rcar_du_encoder.c
8 */
9
10#include <linux/export.h>
11#include <linux/of.h>
12
13#include <drm/drm_bridge.h>
14#include <drm/drm_bridge_connector.h>
15#include <drm/drm_panel.h>
16
17#include "rzg2l_du_drv.h"
18#include "rzg2l_du_encoder.h"
19
20/* -----------------------------------------------------------------------------
21 * Encoder
22 */
23
24static const struct drm_encoder_funcs rzg2l_du_encoder_funcs = {
25};
26
27int rzg2l_du_encoder_init(struct rzg2l_du_device  *rcdu,
28			  enum rzg2l_du_output output,
29			  struct device_node *enc_node)
30{
31	struct rzg2l_du_encoder *renc;
32	struct drm_connector *connector;
33	struct drm_bridge *bridge;
34	int ret;
35
36	/* Locate the DRM bridge from the DT node. */
37	bridge = of_drm_find_bridge(enc_node);
38	if (!bridge)
39		return -EPROBE_DEFER;
40
41	dev_dbg(rcdu->dev, "initializing encoder %pOF for output %s\n",
42		enc_node, rzg2l_du_output_name(output));
43
44	renc = drmm_encoder_alloc(&rcdu->ddev, struct rzg2l_du_encoder, base,
45				  &rzg2l_du_encoder_funcs, DRM_MODE_ENCODER_NONE,
46				  NULL);
47	if (IS_ERR(renc))
48		return PTR_ERR(renc);
49
50	renc->output = output;
51
52	/* Attach the bridge to the encoder. */
53	ret = drm_bridge_attach(&renc->base, bridge, NULL,
54				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
55	if (ret) {
56		dev_err(rcdu->dev,
57			"failed to attach bridge %pOF for output %s (%d)\n",
58			bridge->of_node, rzg2l_du_output_name(output), ret);
59		return ret;
60	}
61
62	/* Create the connector for the chain of bridges. */
63	connector = drm_bridge_connector_init(&rcdu->ddev, &renc->base);
64	if (IS_ERR(connector)) {
65		dev_err(rcdu->dev,
66			"failed to created connector for output %s (%ld)\n",
67			rzg2l_du_output_name(output), PTR_ERR(connector));
68		return PTR_ERR(connector);
69	}
70
71	return drm_connector_attach_encoder(connector, &renc->base);
72}
73