Skip to content

Commit 1f0f015

Browse files
sandy-huangmmind
authored andcommitted
drm/rockchip: Add support for Rockchip Soc RGB output interface
Some Rockchip CRTCs, like rv1108 and px30, can directly output parallel and serial RGB data to panel or conversion chip. So add a feature-bit for vops to mark the ability for these direct outputs and add an internal encoder in that case, that can attach to bridge chipsor panels. Changes in v7: 1. forget to delete rockchip_rgb_driver and delete it. Changes in v6: 1. Update according to Heiko Stuebner' implemention, rgb output is part of vop's feature, should not register as a independent driver. Changes in v5: 1. add SPDX-License-Identifier tag Changes in v4: 1. add support px30; Changes in v3: 1. update for rgb-mode move to panel node. Changes in v2: 1. add error log when probe failed; 2. update name_to_output_mode() according to sean's suggest; 3. Fix uninitialized use of ret. Signed-off-by: Sandy Huang <hjc@rock-chips.com> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Heiko Stuebner <heiko@sntech.de> Link: https://patchwork.freedesktop.org/patch/msgid/20180830211207.10480-3-heiko@sntech.de
1 parent 3880f62 commit 1f0f015

File tree

6 files changed

+222
-0
lines changed

6 files changed

+222
-0
lines changed

drivers/gpu/drm/rockchip/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ config DRM_ROCKCHIP
88
select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
99
select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
1010
select DRM_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
11+
select DRM_RGB if ROCKCHIP_RGB
1112
select SND_SOC_HDMI_CODEC if ROCKCHIP_CDN_DP && SND_SOC
1213
help
1314
Choose this option if you have a Rockchip soc chipset.
@@ -66,4 +67,14 @@ config ROCKCHIP_LVDS
6667
Rockchip rk3288 SoC has LVDS TX Controller can be used, and it
6768
support LVDS, rgb, dual LVDS output mode. say Y to enable its
6869
driver.
70+
71+
config ROCKCHIP_RGB
72+
bool "Rockchip RGB support"
73+
depends on DRM_ROCKCHIP
74+
depends on PINCTRL
75+
help
76+
Choose this option to enable support for Rockchip RGB output.
77+
Some Rockchip CRTCs, like rv1108, can directly output parallel
78+
and serial RGB format to panel or connect to a conversion chip.
79+
say Y to enable its driver.
6980
endif

drivers/gpu/drm/rockchip/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
1414
rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
1515
rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
1616
rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o
17+
rockchipdrm-$(CONFIG_ROCKCHIP_RGB) += rockchip_rgb.o
1718

1819
obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o

drivers/gpu/drm/rockchip/rockchip_drm_vop.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "rockchip_drm_fb.h"
4343
#include "rockchip_drm_psr.h"
4444
#include "rockchip_drm_vop.h"
45+
#include "rockchip_rgb.h"
4546

4647
#define VOP_WIN_SET(x, win, name, v) \
4748
vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name)
@@ -93,6 +94,7 @@ struct vop_win {
9394
struct vop *vop;
9495
};
9596

97+
struct rockchip_rgb;
9698
struct vop {
9799
struct drm_crtc crtc;
98100
struct device *dev;
@@ -136,6 +138,9 @@ struct vop {
136138
/* vop dclk reset */
137139
struct reset_control *dclk_rst;
138140

141+
/* optional internal rgb encoder */
142+
struct rockchip_rgb *rgb;
143+
139144
struct vop_win win[];
140145
};
141146

@@ -1638,6 +1643,14 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
16381643
if (ret)
16391644
goto err_disable_pm_runtime;
16401645

1646+
if (vop->data->feature & VOP_FEATURE_INTERNAL_RGB) {
1647+
vop->rgb = rockchip_rgb_init(dev, &vop->crtc, vop->drm_dev);
1648+
if (IS_ERR(vop->rgb)) {
1649+
ret = PTR_ERR(vop->rgb);
1650+
goto err_disable_pm_runtime;
1651+
}
1652+
}
1653+
16411654
return 0;
16421655

16431656
err_disable_pm_runtime:
@@ -1650,6 +1663,9 @@ static void vop_unbind(struct device *dev, struct device *master, void *data)
16501663
{
16511664
struct vop *vop = dev_get_drvdata(dev);
16521665

1666+
if (vop->rgb)
1667+
rockchip_rgb_fini(vop->rgb);
1668+
16531669
pm_runtime_disable(dev);
16541670
vop_destroy_crtc(vop);
16551671

drivers/gpu/drm/rockchip/rockchip_drm_vop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ struct vop_data {
162162
unsigned int win_size;
163163

164164
#define VOP_FEATURE_OUTPUT_RGB10 BIT(0)
165+
#define VOP_FEATURE_INTERNAL_RGB BIT(1)
165166
u64 feature;
166167
};
167168

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4+
* Author:
5+
* Sandy Huang <hjc@rock-chips.com>
6+
*
7+
* This software is licensed under the terms of the GNU General Public
8+
* License version 2, as published by the Free Software Foundation, and
9+
* may be copied, distributed, and modified under those terms.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*/
16+
17+
#include <drm/drmP.h>
18+
#include <drm/drm_atomic_helper.h>
19+
#include <drm/drm_crtc_helper.h>
20+
#include <drm/drm_dp_helper.h>
21+
#include <drm/drm_panel.h>
22+
#include <drm/drm_of.h>
23+
24+
#include <linux/component.h>
25+
#include <linux/of_graph.h>
26+
27+
#include "rockchip_drm_drv.h"
28+
#include "rockchip_drm_vop.h"
29+
30+
#define encoder_to_rgb(c) container_of(c, struct rockchip_rgb, encoder)
31+
32+
struct rockchip_rgb {
33+
struct device *dev;
34+
struct drm_device *drm_dev;
35+
struct drm_bridge *bridge;
36+
struct drm_encoder encoder;
37+
int output_mode;
38+
};
39+
40+
static int
41+
rockchip_rgb_encoder_atomic_check(struct drm_encoder *encoder,
42+
struct drm_crtc_state *crtc_state,
43+
struct drm_connector_state *conn_state)
44+
{
45+
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
46+
struct drm_connector *connector = conn_state->connector;
47+
struct drm_display_info *info = &connector->display_info;
48+
u32 bus_format;
49+
50+
if (info->num_bus_formats)
51+
bus_format = info->bus_formats[0];
52+
else
53+
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
54+
55+
switch (bus_format) {
56+
case MEDIA_BUS_FMT_RGB666_1X18:
57+
s->output_mode = ROCKCHIP_OUT_MODE_P666;
58+
break;
59+
case MEDIA_BUS_FMT_RGB565_1X16:
60+
s->output_mode = ROCKCHIP_OUT_MODE_P565;
61+
break;
62+
case MEDIA_BUS_FMT_RGB888_1X24:
63+
case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
64+
default:
65+
s->output_mode = ROCKCHIP_OUT_MODE_P888;
66+
break;
67+
}
68+
69+
s->output_type = DRM_MODE_CONNECTOR_LVDS;
70+
71+
return 0;
72+
}
73+
74+
static const
75+
struct drm_encoder_helper_funcs rockchip_rgb_encoder_helper_funcs = {
76+
.atomic_check = rockchip_rgb_encoder_atomic_check,
77+
};
78+
79+
static const struct drm_encoder_funcs rockchip_rgb_encoder_funcs = {
80+
.destroy = drm_encoder_cleanup,
81+
};
82+
83+
struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
84+
struct drm_crtc *crtc,
85+
struct drm_device *drm_dev)
86+
{
87+
struct rockchip_rgb *rgb;
88+
struct drm_encoder *encoder;
89+
struct device_node *port, *endpoint;
90+
u32 endpoint_id;
91+
int ret = 0, child_count = 0;
92+
struct drm_panel *panel;
93+
struct drm_bridge *bridge;
94+
95+
rgb = devm_kzalloc(dev, sizeof(*rgb), GFP_KERNEL);
96+
if (!rgb)
97+
return ERR_PTR(-ENOMEM);
98+
99+
rgb->dev = dev;
100+
rgb->drm_dev = drm_dev;
101+
102+
port = of_graph_get_port_by_id(dev->of_node, 0);
103+
if (!port)
104+
return ERR_PTR(-EINVAL);
105+
106+
for_each_child_of_node(port, endpoint) {
107+
if (of_property_read_u32(endpoint, "reg", &endpoint_id))
108+
endpoint_id = 0;
109+
110+
if (rockchip_drm_endpoint_is_subdriver(endpoint) > 0)
111+
continue;
112+
113+
child_count++;
114+
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id,
115+
&panel, &bridge);
116+
if (!ret)
117+
break;
118+
}
119+
120+
of_node_put(port);
121+
122+
/* if the rgb output is not connected to anything, just return */
123+
if (!child_count)
124+
return NULL;
125+
126+
if (ret < 0) {
127+
if (ret != -EPROBE_DEFER)
128+
DRM_DEV_ERROR(dev, "failed to find panel or bridge %d\n", ret);
129+
return ERR_PTR(ret);
130+
}
131+
132+
encoder = &rgb->encoder;
133+
encoder->possible_crtcs = drm_crtc_mask(crtc);
134+
135+
ret = drm_encoder_init(drm_dev, encoder, &rockchip_rgb_encoder_funcs,
136+
DRM_MODE_ENCODER_NONE, NULL);
137+
if (ret < 0) {
138+
DRM_DEV_ERROR(drm_dev->dev,
139+
"failed to initialize encoder: %d\n", ret);
140+
return ERR_PTR(ret);
141+
}
142+
143+
drm_encoder_helper_add(encoder, &rockchip_rgb_encoder_helper_funcs);
144+
145+
if (panel) {
146+
bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_LVDS);
147+
if (IS_ERR(bridge))
148+
return ERR_CAST(bridge);
149+
}
150+
151+
rgb->bridge = bridge;
152+
153+
ret = drm_bridge_attach(encoder, rgb->bridge, NULL);
154+
if (ret) {
155+
DRM_DEV_ERROR(drm_dev->dev,
156+
"failed to attach bridge: %d\n", ret);
157+
goto err_free_encoder;
158+
}
159+
160+
return rgb;
161+
162+
err_free_encoder:
163+
drm_encoder_cleanup(encoder);
164+
return ERR_PTR(ret);
165+
}
166+
EXPORT_SYMBOL_GPL(rockchip_rgb_init);
167+
168+
void rockchip_rgb_fini(struct rockchip_rgb *rgb)
169+
{
170+
drm_panel_bridge_remove(rgb->bridge);
171+
drm_encoder_cleanup(&rgb->encoder);
172+
}
173+
EXPORT_SYMBOL_GPL(rockchip_rgb_fini);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4+
* Author:
5+
* Sandy Huang <hjc@rock-chips.com>
6+
*
7+
* This software is licensed under the terms of the GNU General Public
8+
* License version 2, as published by the Free Software Foundation, and
9+
* may be copied, distributed, and modified under those terms.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*/
16+
17+
struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
18+
struct drm_crtc *crtc,
19+
struct drm_device *drm_dev);
20+
void rockchip_rgb_fini(struct rockchip_rgb *rgb);

0 commit comments

Comments
 (0)