aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandy Huang <hjc@rock-chips.com>2018-08-30 17:12:06 -0400
committerHeiko Stuebner <heiko@sntech.de>2018-09-05 06:24:36 -0400
commit1f0f015151727872be866b6a5b64e07f9e7a3071 (patch)
tree6cc69de3ca1b4ab35d6c159726ca1a5f5d65a16c
parent3880f62e476df5fb6fe4ac3ebd2442a9ce306c6b (diff)
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
-rw-r--r--drivers/gpu/drm/rockchip/Kconfig11
-rw-r--r--drivers/gpu/drm/rockchip/Makefile1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c16
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.h1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_rgb.c173
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_rgb.h20
6 files changed, 222 insertions, 0 deletions
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 0534dc1ca32a..26438d45732b 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -8,6 +8,7 @@ config DRM_ROCKCHIP
8 select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP 8 select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
9 select DRM_DW_HDMI if ROCKCHIP_DW_HDMI 9 select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
10 select DRM_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI 10 select DRM_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
11 select DRM_RGB if ROCKCHIP_RGB
11 select SND_SOC_HDMI_CODEC if ROCKCHIP_CDN_DP && SND_SOC 12 select SND_SOC_HDMI_CODEC if ROCKCHIP_CDN_DP && SND_SOC
12 help 13 help
13 Choose this option if you have a Rockchip soc chipset. 14 Choose this option if you have a Rockchip soc chipset.
@@ -66,4 +67,14 @@ config ROCKCHIP_LVDS
66 Rockchip rk3288 SoC has LVDS TX Controller can be used, and it 67 Rockchip rk3288 SoC has LVDS TX Controller can be used, and it
67 support LVDS, rgb, dual LVDS output mode. say Y to enable its 68 support LVDS, rgb, dual LVDS output mode. say Y to enable its
68 driver. 69 driver.
70
71config 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.
69endif 80endif
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index a314e2109e76..868263ff0302 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -14,5 +14,6 @@ rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
14rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o 14rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
15rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o 15rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
16rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o 16rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o
17rockchipdrm-$(CONFIG_ROCKCHIP_RGB) += rockchip_rgb.o
17 18
18obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o 19obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 17f9ed688841..0c35a88e33dd 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -42,6 +42,7 @@
42#include "rockchip_drm_fb.h" 42#include "rockchip_drm_fb.h"
43#include "rockchip_drm_psr.h" 43#include "rockchip_drm_psr.h"
44#include "rockchip_drm_vop.h" 44#include "rockchip_drm_vop.h"
45#include "rockchip_rgb.h"
45 46
46#define VOP_WIN_SET(x, win, name, v) \ 47#define VOP_WIN_SET(x, win, name, v) \
47 vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name) 48 vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name)
@@ -93,6 +94,7 @@ struct vop_win {
93 struct vop *vop; 94 struct vop *vop;
94}; 95};
95 96
97struct rockchip_rgb;
96struct vop { 98struct vop {
97 struct drm_crtc crtc; 99 struct drm_crtc crtc;
98 struct device *dev; 100 struct device *dev;
@@ -136,6 +138,9 @@ struct vop {
136 /* vop dclk reset */ 138 /* vop dclk reset */
137 struct reset_control *dclk_rst; 139 struct reset_control *dclk_rst;
138 140
141 /* optional internal rgb encoder */
142 struct rockchip_rgb *rgb;
143
139 struct vop_win win[]; 144 struct vop_win win[];
140}; 145};
141 146
@@ -1638,6 +1643,14 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
1638 if (ret) 1643 if (ret)
1639 goto err_disable_pm_runtime; 1644 goto err_disable_pm_runtime;
1640 1645
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
1641 return 0; 1654 return 0;
1642 1655
1643err_disable_pm_runtime: 1656err_disable_pm_runtime:
@@ -1650,6 +1663,9 @@ static void vop_unbind(struct device *dev, struct device *master, void *data)
1650{ 1663{
1651 struct vop *vop = dev_get_drvdata(dev); 1664 struct vop *vop = dev_get_drvdata(dev);
1652 1665
1666 if (vop->rgb)
1667 rockchip_rgb_fini(vop->rgb);
1668
1653 pm_runtime_disable(dev); 1669 pm_runtime_disable(dev);
1654 vop_destroy_crtc(vop); 1670 vop_destroy_crtc(vop);
1655 1671
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index fcb91041a666..fd5765dfd637 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -162,6 +162,7 @@ struct vop_data {
162 unsigned int win_size; 162 unsigned int win_size;
163 163
164#define VOP_FEATURE_OUTPUT_RGB10 BIT(0) 164#define VOP_FEATURE_OUTPUT_RGB10 BIT(0)
165#define VOP_FEATURE_INTERNAL_RGB BIT(1)
165 u64 feature; 166 u64 feature;
166}; 167};
167 168
diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c
new file mode 100644
index 000000000000..96ac1458a59c
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c
@@ -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
32struct 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
40static int
41rockchip_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
74static const
75struct drm_encoder_helper_funcs rockchip_rgb_encoder_helper_funcs = {
76 .atomic_check = rockchip_rgb_encoder_atomic_check,
77};
78
79static const struct drm_encoder_funcs rockchip_rgb_encoder_funcs = {
80 .destroy = drm_encoder_cleanup,
81};
82
83struct 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
162err_free_encoder:
163 drm_encoder_cleanup(encoder);
164 return ERR_PTR(ret);
165}
166EXPORT_SYMBOL_GPL(rockchip_rgb_init);
167
168void rockchip_rgb_fini(struct rockchip_rgb *rgb)
169{
170 drm_panel_bridge_remove(rgb->bridge);
171 drm_encoder_cleanup(&rgb->encoder);
172}
173EXPORT_SYMBOL_GPL(rockchip_rgb_fini);
diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.h b/drivers/gpu/drm/rockchip/rockchip_rgb.h
new file mode 100644
index 000000000000..c712a673d1e3
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_rgb.h
@@ -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
17struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
18 struct drm_crtc *crtc,
19 struct drm_device *drm_dev);
20void rockchip_rgb_fini(struct rockchip_rgb *rgb);