.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd |
---|
3 | 4 | * Author:Mark Yao <mark.yao@rock-chips.com> |
---|
4 | 5 | * |
---|
5 | 6 | * based on exynos_drm_drv.c |
---|
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 | 7 | */ |
---|
16 | 8 | |
---|
17 | | -#include <drm/drmP.h> |
---|
18 | | -#include <drm/drm_atomic.h> |
---|
19 | | -#include <drm/drm_crtc_helper.h> |
---|
20 | | -#include <drm/drm_fb_helper.h> |
---|
21 | | -#include <drm/drm_gem_cma_helper.h> |
---|
22 | | -#include <drm/drm_of.h> |
---|
23 | | -#include <linux/devfreq.h> |
---|
24 | | -#include <linux/dma-buf.h> |
---|
| 9 | +#include <linux/dma-buf-cache.h> |
---|
25 | 10 | #include <linux/dma-mapping.h> |
---|
26 | 11 | #include <linux/dma-iommu.h> |
---|
27 | 12 | #include <linux/genalloc.h> |
---|
28 | 13 | #include <linux/pm_runtime.h> |
---|
29 | | -#include <linux/memblock.h> |
---|
30 | 14 | #include <linux/module.h> |
---|
31 | 15 | #include <linux/of_address.h> |
---|
32 | 16 | #include <linux/of_graph.h> |
---|
| 17 | +#include <linux/of_platform.h> |
---|
33 | 18 | #include <linux/clk.h> |
---|
34 | | -#include <linux/clk-provider.h> |
---|
35 | 19 | #include <linux/component.h> |
---|
36 | 20 | #include <linux/console.h> |
---|
37 | 21 | #include <linux/iommu.h> |
---|
38 | 22 | #include <linux/of_reserved_mem.h> |
---|
39 | 23 | |
---|
| 24 | +#include <drm/drm_debugfs.h> |
---|
| 25 | +#include <drm/drm_drv.h> |
---|
| 26 | +#include <drm/drm_displayid.h> |
---|
| 27 | +#include <drm/drm_fb_helper.h> |
---|
| 28 | +#include <drm/drm_gem_cma_helper.h> |
---|
| 29 | +#include <drm/drm_of.h> |
---|
| 30 | +#include <drm/drm_probe_helper.h> |
---|
| 31 | +#include <drm/drm_vblank.h> |
---|
| 32 | + |
---|
40 | 33 | #include "rockchip_drm_drv.h" |
---|
41 | 34 | #include "rockchip_drm_fb.h" |
---|
42 | 35 | #include "rockchip_drm_fbdev.h" |
---|
43 | 36 | #include "rockchip_drm_gem.h" |
---|
| 37 | +#include "rockchip_drm_logo.h" |
---|
44 | 38 | |
---|
45 | | -#include "../drm_internal.h" |
---|
| 39 | +#include "../drm_crtc_internal.h" |
---|
46 | 40 | |
---|
47 | 41 | #define DRIVER_NAME "rockchip" |
---|
48 | 42 | #define DRIVER_DESC "RockChip Soc DRM" |
---|
49 | 43 | #define DRIVER_DATE "20140818" |
---|
50 | | -#define DRIVER_MAJOR 2 |
---|
| 44 | +#define DRIVER_MAJOR 3 |
---|
51 | 45 | #define DRIVER_MINOR 0 |
---|
52 | | -#define DRIVER_PATCH 0 |
---|
53 | | - |
---|
54 | | -/*********************************************************************** |
---|
55 | | - * Rockchip DRM driver version |
---|
56 | | - * |
---|
57 | | - * v2.0.0 : add basic version for linux 4.19 rockchip drm driver(hjc) |
---|
58 | | - * |
---|
59 | | - **********************************************************************/ |
---|
60 | 46 | |
---|
61 | 47 | #if IS_ENABLED(CONFIG_DRM_ROCKCHIP_VVOP) |
---|
62 | 48 | static bool is_support_iommu = false; |
---|
.. | .. |
---|
64 | 50 | static bool is_support_iommu = true; |
---|
65 | 51 | #endif |
---|
66 | 52 | static bool iommu_reserve_map; |
---|
| 53 | + |
---|
67 | 54 | static struct drm_driver rockchip_drm_driver; |
---|
68 | 55 | |
---|
69 | | -struct rockchip_drm_mode_set { |
---|
70 | | - struct list_head head; |
---|
71 | | - struct drm_framebuffer *fb; |
---|
72 | | - struct drm_connector *connector; |
---|
73 | | - struct drm_crtc *crtc; |
---|
74 | | - struct drm_display_mode *mode; |
---|
75 | | - int clock; |
---|
76 | | - int hdisplay; |
---|
77 | | - int vdisplay; |
---|
78 | | - int vrefresh; |
---|
79 | | - int flags; |
---|
80 | | - int picture_aspect_ratio; |
---|
81 | | - int crtc_hsync_end; |
---|
82 | | - int crtc_vsync_end; |
---|
| 56 | +static unsigned int drm_debug; |
---|
| 57 | +module_param_named(debug, drm_debug, int, 0600); |
---|
83 | 58 | |
---|
84 | | - int left_margin; |
---|
85 | | - int right_margin; |
---|
86 | | - int top_margin; |
---|
87 | | - int bottom_margin; |
---|
| 59 | +static inline bool rockchip_drm_debug_enabled(enum rockchip_drm_debug_category category) |
---|
| 60 | +{ |
---|
| 61 | + return unlikely(drm_debug & category); |
---|
| 62 | +} |
---|
88 | 63 | |
---|
89 | | - unsigned int brightness; |
---|
90 | | - unsigned int contrast; |
---|
91 | | - unsigned int saturation; |
---|
92 | | - unsigned int hue; |
---|
| 64 | +__printf(3, 4) |
---|
| 65 | +void rockchip_drm_dbg(const struct device *dev, enum rockchip_drm_debug_category category, |
---|
| 66 | + const char *format, ...) |
---|
| 67 | +{ |
---|
| 68 | + struct va_format vaf; |
---|
| 69 | + va_list args; |
---|
93 | 70 | |
---|
94 | | - bool mode_changed; |
---|
95 | | - bool force_output; |
---|
96 | | - int ratio; |
---|
97 | | -}; |
---|
| 71 | + if (!rockchip_drm_debug_enabled(category)) |
---|
| 72 | + return; |
---|
| 73 | + |
---|
| 74 | + va_start(args, format); |
---|
| 75 | + vaf.fmt = format; |
---|
| 76 | + vaf.va = &args; |
---|
| 77 | + |
---|
| 78 | + if (dev) |
---|
| 79 | + dev_printk(KERN_DEBUG, dev, "%pV", &vaf); |
---|
| 80 | + else |
---|
| 81 | + printk(KERN_DEBUG "%pV", &vaf); |
---|
| 82 | + |
---|
| 83 | + va_end(args); |
---|
| 84 | +} |
---|
| 85 | + |
---|
| 86 | +/** |
---|
| 87 | + * rockchip_drm_wait_vact_end |
---|
| 88 | + * @crtc: CRTC to enable line flag |
---|
| 89 | + * @mstimeout: millisecond for timeout |
---|
| 90 | + * |
---|
| 91 | + * Wait for vact_end line flag irq or timeout. |
---|
| 92 | + * |
---|
| 93 | + * Returns: |
---|
| 94 | + * Zero on success, negative errno on failure. |
---|
| 95 | + */ |
---|
| 96 | +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout) |
---|
| 97 | +{ |
---|
| 98 | + struct rockchip_drm_private *priv; |
---|
| 99 | + int pipe, ret = 0; |
---|
| 100 | + |
---|
| 101 | + if (!crtc) |
---|
| 102 | + return -ENODEV; |
---|
| 103 | + |
---|
| 104 | + if (mstimeout <= 0) |
---|
| 105 | + return -EINVAL; |
---|
| 106 | + |
---|
| 107 | + priv = crtc->dev->dev_private; |
---|
| 108 | + pipe = drm_crtc_index(crtc); |
---|
| 109 | + |
---|
| 110 | + if (priv->crtc_funcs[pipe] && priv->crtc_funcs[pipe]->wait_vact_end) |
---|
| 111 | + ret = priv->crtc_funcs[pipe]->wait_vact_end(crtc, mstimeout); |
---|
| 112 | + |
---|
| 113 | + return ret; |
---|
| 114 | +} |
---|
| 115 | +EXPORT_SYMBOL(rockchip_drm_wait_vact_end); |
---|
| 116 | + |
---|
| 117 | +void drm_mode_convert_to_split_mode(struct drm_display_mode *mode) |
---|
| 118 | +{ |
---|
| 119 | + u16 hactive, hfp, hsync, hbp; |
---|
| 120 | + |
---|
| 121 | + hactive = mode->hdisplay; |
---|
| 122 | + hfp = mode->hsync_start - mode->hdisplay; |
---|
| 123 | + hsync = mode->hsync_end - mode->hsync_start; |
---|
| 124 | + hbp = mode->htotal - mode->hsync_end; |
---|
| 125 | + |
---|
| 126 | + mode->clock *= 2; |
---|
| 127 | + mode->crtc_clock *= 2; |
---|
| 128 | + mode->hdisplay = hactive * 2; |
---|
| 129 | + mode->hsync_start = mode->hdisplay + hfp * 2; |
---|
| 130 | + mode->hsync_end = mode->hsync_start + hsync * 2; |
---|
| 131 | + mode->htotal = mode->hsync_end + hbp * 2; |
---|
| 132 | + drm_mode_set_name(mode); |
---|
| 133 | +} |
---|
| 134 | +EXPORT_SYMBOL(drm_mode_convert_to_split_mode); |
---|
| 135 | + |
---|
| 136 | +void drm_mode_convert_to_origin_mode(struct drm_display_mode *mode) |
---|
| 137 | +{ |
---|
| 138 | + u16 hactive, hfp, hsync, hbp; |
---|
| 139 | + |
---|
| 140 | + hactive = mode->hdisplay; |
---|
| 141 | + hfp = mode->hsync_start - mode->hdisplay; |
---|
| 142 | + hsync = mode->hsync_end - mode->hsync_start; |
---|
| 143 | + hbp = mode->htotal - mode->hsync_end; |
---|
| 144 | + |
---|
| 145 | + mode->clock /= 2; |
---|
| 146 | + mode->crtc_clock /= 2; |
---|
| 147 | + mode->hdisplay = hactive / 2; |
---|
| 148 | + mode->hsync_start = mode->hdisplay + hfp / 2; |
---|
| 149 | + mode->hsync_end = mode->hsync_start + hsync / 2; |
---|
| 150 | + mode->htotal = mode->hsync_end + hbp / 2; |
---|
| 151 | +} |
---|
| 152 | +EXPORT_SYMBOL(drm_mode_convert_to_origin_mode); |
---|
| 153 | + |
---|
| 154 | +/** |
---|
| 155 | + * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector |
---|
| 156 | + * @connector: connector to report the event on |
---|
| 157 | + * |
---|
| 158 | + * On some hardware a hotplug event notification may come from outside the display |
---|
| 159 | + * driver / device. An example of this is some USB Type-C setups where the hardware |
---|
| 160 | + * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD |
---|
| 161 | + * status bit to the GPU's DP HPD pin. |
---|
| 162 | + * |
---|
| 163 | + * This function can be used to report these out-of-band events after obtaining |
---|
| 164 | + * a drm_connector reference through calling drm_connector_find_by_fwnode(). |
---|
| 165 | + */ |
---|
| 166 | +void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode) |
---|
| 167 | +{ |
---|
| 168 | + struct rockchip_drm_sub_dev *sub_dev; |
---|
| 169 | + |
---|
| 170 | + if (!connector_fwnode || !connector_fwnode->dev) |
---|
| 171 | + return; |
---|
| 172 | + |
---|
| 173 | + sub_dev = rockchip_drm_get_sub_dev(dev_of_node(connector_fwnode->dev)); |
---|
| 174 | + |
---|
| 175 | + if (sub_dev && sub_dev->connector && sub_dev->oob_hotplug_event) |
---|
| 176 | + sub_dev->oob_hotplug_event(sub_dev->connector); |
---|
| 177 | +} |
---|
| 178 | +EXPORT_SYMBOL(drm_connector_oob_hotplug_event); |
---|
| 179 | + |
---|
| 180 | +uint32_t rockchip_drm_get_bpp(const struct drm_format_info *info) |
---|
| 181 | +{ |
---|
| 182 | + /* use whatever a driver has set */ |
---|
| 183 | + if (info->cpp[0]) |
---|
| 184 | + return info->cpp[0] * 8; |
---|
| 185 | + |
---|
| 186 | + switch (info->format) { |
---|
| 187 | + case DRM_FORMAT_YUV420_8BIT: |
---|
| 188 | + return 12; |
---|
| 189 | + case DRM_FORMAT_YUV420_10BIT: |
---|
| 190 | + return 15; |
---|
| 191 | + case DRM_FORMAT_VUY101010: |
---|
| 192 | + return 30; |
---|
| 193 | + default: |
---|
| 194 | + break; |
---|
| 195 | + } |
---|
| 196 | + |
---|
| 197 | + /* all attempts failed */ |
---|
| 198 | + return 0; |
---|
| 199 | +} |
---|
| 200 | +EXPORT_SYMBOL(rockchip_drm_get_bpp); |
---|
| 201 | + |
---|
| 202 | +uint32_t rockchip_drm_get_cycles_per_pixel(uint32_t bus_format) |
---|
| 203 | +{ |
---|
| 204 | + switch (bus_format) { |
---|
| 205 | + case MEDIA_BUS_FMT_RGB565_1X16: |
---|
| 206 | + case MEDIA_BUS_FMT_RGB666_1X18: |
---|
| 207 | + case MEDIA_BUS_FMT_RGB888_1X24: |
---|
| 208 | + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: |
---|
| 209 | + return 1; |
---|
| 210 | + case MEDIA_BUS_FMT_RGB565_2X8_LE: |
---|
| 211 | + case MEDIA_BUS_FMT_BGR565_2X8_LE: |
---|
| 212 | + return 2; |
---|
| 213 | + case MEDIA_BUS_FMT_RGB666_3X6: |
---|
| 214 | + case MEDIA_BUS_FMT_RGB888_3X8: |
---|
| 215 | + case MEDIA_BUS_FMT_BGR888_3X8: |
---|
| 216 | + return 3; |
---|
| 217 | + case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: |
---|
| 218 | + case MEDIA_BUS_FMT_BGR888_DUMMY_4X8: |
---|
| 219 | + return 4; |
---|
| 220 | + default: |
---|
| 221 | + return 1; |
---|
| 222 | + } |
---|
| 223 | +} |
---|
| 224 | +EXPORT_SYMBOL(rockchip_drm_get_cycles_per_pixel); |
---|
| 225 | + |
---|
| 226 | +/** |
---|
| 227 | + * rockchip_drm_of_find_possible_crtcs - find the possible CRTCs for an active |
---|
| 228 | + * encoder port |
---|
| 229 | + * @dev: DRM device |
---|
| 230 | + * @port: encoder port to scan for endpoints |
---|
| 231 | + * |
---|
| 232 | + * Scan all active endpoints attached to a port, locate their attached CRTCs, |
---|
| 233 | + * and generate the DRM mask of CRTCs which may be attached to this |
---|
| 234 | + * encoder. |
---|
| 235 | + * |
---|
| 236 | + * See Documentation/devicetree/bindings/graph.txt for the bindings. |
---|
| 237 | + */ |
---|
| 238 | +uint32_t rockchip_drm_of_find_possible_crtcs(struct drm_device *dev, |
---|
| 239 | + struct device_node *port) |
---|
| 240 | +{ |
---|
| 241 | + struct device_node *remote_port, *ep; |
---|
| 242 | + uint32_t possible_crtcs = 0; |
---|
| 243 | + |
---|
| 244 | + for_each_endpoint_of_node(port, ep) { |
---|
| 245 | + if (!of_device_is_available(ep)) |
---|
| 246 | + continue; |
---|
| 247 | + |
---|
| 248 | + remote_port = of_graph_get_remote_port(ep); |
---|
| 249 | + if (!remote_port) { |
---|
| 250 | + of_node_put(ep); |
---|
| 251 | + continue; |
---|
| 252 | + } |
---|
| 253 | + |
---|
| 254 | + possible_crtcs |= drm_of_crtc_port_mask(dev, remote_port); |
---|
| 255 | + |
---|
| 256 | + of_node_put(remote_port); |
---|
| 257 | + } |
---|
| 258 | + |
---|
| 259 | + return possible_crtcs; |
---|
| 260 | +} |
---|
| 261 | +EXPORT_SYMBOL(rockchip_drm_of_find_possible_crtcs); |
---|
98 | 262 | |
---|
99 | 263 | static DEFINE_MUTEX(rockchip_drm_sub_dev_lock); |
---|
100 | 264 | static LIST_HEAD(rockchip_drm_sub_dev_list); |
---|
| 265 | + |
---|
| 266 | +void rockchip_connector_update_vfp_for_vrr(struct drm_crtc *crtc, struct drm_display_mode *mode, |
---|
| 267 | + int vfp) |
---|
| 268 | +{ |
---|
| 269 | + struct rockchip_drm_sub_dev *sub_dev; |
---|
| 270 | + |
---|
| 271 | + mutex_lock(&rockchip_drm_sub_dev_lock); |
---|
| 272 | + list_for_each_entry(sub_dev, &rockchip_drm_sub_dev_list, list) { |
---|
| 273 | + if (sub_dev->connector->state->crtc == crtc) { |
---|
| 274 | + if (sub_dev->update_vfp_for_vrr) |
---|
| 275 | + sub_dev->update_vfp_for_vrr(sub_dev->connector, mode, vfp); |
---|
| 276 | + } |
---|
| 277 | + } |
---|
| 278 | + mutex_unlock(&rockchip_drm_sub_dev_lock); |
---|
| 279 | +} |
---|
| 280 | +EXPORT_SYMBOL(rockchip_connector_update_vfp_for_vrr); |
---|
101 | 281 | |
---|
102 | 282 | void rockchip_drm_register_sub_dev(struct rockchip_drm_sub_dev *sub_dev) |
---|
103 | 283 | { |
---|
.. | .. |
---|
151 | 331 | } |
---|
152 | 332 | EXPORT_SYMBOL(rockchip_drm_get_sub_dev_type); |
---|
153 | 333 | |
---|
| 334 | +u32 rockchip_drm_get_scan_line_time_ns(void) |
---|
| 335 | +{ |
---|
| 336 | + struct rockchip_drm_sub_dev *sub_dev = NULL; |
---|
| 337 | + struct drm_display_mode *mode; |
---|
| 338 | + int linedur_ns = 0; |
---|
| 339 | + |
---|
| 340 | + mutex_lock(&rockchip_drm_sub_dev_lock); |
---|
| 341 | + list_for_each_entry(sub_dev, &rockchip_drm_sub_dev_list, list) { |
---|
| 342 | + if (sub_dev->connector->encoder && sub_dev->connector->state->crtc) { |
---|
| 343 | + mode = &sub_dev->connector->state->crtc->state->adjusted_mode; |
---|
| 344 | + linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, mode->crtc_clock); |
---|
| 345 | + break; |
---|
| 346 | + } |
---|
| 347 | + } |
---|
| 348 | + mutex_unlock(&rockchip_drm_sub_dev_lock); |
---|
| 349 | + |
---|
| 350 | + return linedur_ns; |
---|
| 351 | +} |
---|
| 352 | +EXPORT_SYMBOL(rockchip_drm_get_scan_line_time_ns); |
---|
| 353 | + |
---|
154 | 354 | void rockchip_drm_te_handle(struct drm_crtc *crtc) |
---|
155 | 355 | { |
---|
156 | 356 | struct rockchip_drm_private *priv = crtc->dev->dev_private; |
---|
.. | .. |
---|
166 | 366 | { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390, |
---|
167 | 367 | 1430, 1650, 0, 720, 725, 730, 750, 0, |
---|
168 | 368 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), |
---|
169 | | - .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
---|
| 369 | + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
---|
170 | 370 | /* 16 - 1920x1080@60Hz 16:9 */ |
---|
171 | 371 | { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008, |
---|
172 | 372 | 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, |
---|
173 | 373 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), |
---|
174 | | - .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
---|
| 374 | + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
---|
175 | 375 | /* 31 - 1920x1080@50Hz 16:9 */ |
---|
176 | 376 | { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448, |
---|
177 | 377 | 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, |
---|
178 | 378 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), |
---|
179 | | - .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
---|
| 379 | + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
---|
180 | 380 | /* 19 - 1280x720@50Hz 16:9 */ |
---|
181 | 381 | { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720, |
---|
182 | 382 | 1760, 1980, 0, 720, 725, 730, 750, 0, |
---|
183 | 383 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), |
---|
184 | | - .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
---|
| 384 | + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
---|
185 | 385 | /* 0x10 - 1024x768@60Hz */ |
---|
186 | 386 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, |
---|
187 | 387 | 1184, 1344, 0, 768, 771, 777, 806, 0, |
---|
.. | .. |
---|
190 | 390 | { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732, |
---|
191 | 391 | 796, 864, 0, 576, 581, 586, 625, 0, |
---|
192 | 392 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), |
---|
193 | | - .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, |
---|
| 393 | + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, |
---|
194 | 394 | /* 2 - 720x480@60Hz 4:3 */ |
---|
195 | 395 | { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736, |
---|
196 | 396 | 798, 858, 0, 480, 489, 495, 525, 0, |
---|
197 | 397 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), |
---|
198 | | - .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, |
---|
| 398 | + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, |
---|
199 | 399 | }; |
---|
200 | 400 | |
---|
201 | 401 | int rockchip_drm_add_modes_noedid(struct drm_connector *connector) |
---|
.. | .. |
---|
224 | 424 | } |
---|
225 | 425 | EXPORT_SYMBOL(rockchip_drm_add_modes_noedid); |
---|
226 | 426 | |
---|
227 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
228 | | -struct drm_prime_callback_data { |
---|
229 | | - struct drm_gem_object *obj; |
---|
230 | | - struct sg_table *sgt; |
---|
| 427 | +static const struct rockchip_drm_width_dclk { |
---|
| 428 | + int width; |
---|
| 429 | + u32 dclk_khz; |
---|
| 430 | +} rockchip_drm_dclk[] = { |
---|
| 431 | + {1920, 148500}, |
---|
| 432 | + {2048, 200000}, |
---|
| 433 | + {2560, 280000}, |
---|
| 434 | + {3840, 594000}, |
---|
| 435 | + {4096, 594000}, |
---|
| 436 | + {7680, 2376000}, |
---|
231 | 437 | }; |
---|
232 | | -#endif |
---|
233 | 438 | |
---|
234 | | -#ifndef MODULE |
---|
235 | | -static struct drm_crtc *find_crtc_by_node(struct drm_device *drm_dev, struct device_node *node) |
---|
| 439 | +u32 rockchip_drm_get_dclk_by_width(int width) |
---|
236 | 440 | { |
---|
237 | | - struct device_node *np_crtc; |
---|
238 | | - struct drm_crtc *crtc; |
---|
| 441 | + int i = 0; |
---|
| 442 | + u32 dclk_khz; |
---|
239 | 443 | |
---|
240 | | - np_crtc = of_get_parent(node); |
---|
241 | | - if (!np_crtc || !of_device_is_available(np_crtc)) |
---|
| 444 | + for (i = 0; i < ARRAY_SIZE(rockchip_drm_dclk); i++) { |
---|
| 445 | + if (width == rockchip_drm_dclk[i].width) { |
---|
| 446 | + dclk_khz = rockchip_drm_dclk[i].dclk_khz; |
---|
| 447 | + break; |
---|
| 448 | + } |
---|
| 449 | + } |
---|
| 450 | + |
---|
| 451 | + if (i == ARRAY_SIZE(rockchip_drm_dclk)) { |
---|
| 452 | + DRM_ERROR("Can't not find %d width solution and use 148500 khz as max dclk\n", width); |
---|
| 453 | + |
---|
| 454 | + dclk_khz = 148500; |
---|
| 455 | + } |
---|
| 456 | + |
---|
| 457 | + return dclk_khz; |
---|
| 458 | +} |
---|
| 459 | +EXPORT_SYMBOL(rockchip_drm_get_dclk_by_width); |
---|
| 460 | + |
---|
| 461 | +static int |
---|
| 462 | +cea_db_tag(const u8 *db) |
---|
| 463 | +{ |
---|
| 464 | + return db[0] >> 5; |
---|
| 465 | +} |
---|
| 466 | + |
---|
| 467 | +static int |
---|
| 468 | +cea_db_payload_len(const u8 *db) |
---|
| 469 | +{ |
---|
| 470 | + return db[0] & 0x1f; |
---|
| 471 | +} |
---|
| 472 | + |
---|
| 473 | +#define for_each_cea_db(cea, i, start, end) \ |
---|
| 474 | + for ((i) = (start); \ |
---|
| 475 | + (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); \ |
---|
| 476 | + (i) += cea_db_payload_len(&(cea)[(i)]) + 1) |
---|
| 477 | + |
---|
| 478 | +#define HDMI_NEXT_HDR_VSDB_OUI 0xd04601 |
---|
| 479 | + |
---|
| 480 | +static bool cea_db_is_hdmi_next_hdr_block(const u8 *db) |
---|
| 481 | +{ |
---|
| 482 | + unsigned int oui; |
---|
| 483 | + |
---|
| 484 | + if (cea_db_tag(db) != 0x07) |
---|
| 485 | + return false; |
---|
| 486 | + |
---|
| 487 | + if (cea_db_payload_len(db) < 11) |
---|
| 488 | + return false; |
---|
| 489 | + |
---|
| 490 | + oui = db[3] << 16 | db[2] << 8 | db[1]; |
---|
| 491 | + |
---|
| 492 | + return oui == HDMI_NEXT_HDR_VSDB_OUI; |
---|
| 493 | +} |
---|
| 494 | + |
---|
| 495 | +static bool cea_db_is_hdmi_forum_vsdb(const u8 *db) |
---|
| 496 | +{ |
---|
| 497 | + unsigned int oui; |
---|
| 498 | + |
---|
| 499 | + if (cea_db_tag(db) != 0x03) |
---|
| 500 | + return false; |
---|
| 501 | + |
---|
| 502 | + if (cea_db_payload_len(db) < 7) |
---|
| 503 | + return false; |
---|
| 504 | + |
---|
| 505 | + oui = db[3] << 16 | db[2] << 8 | db[1]; |
---|
| 506 | + |
---|
| 507 | + return oui == HDMI_FORUM_IEEE_OUI; |
---|
| 508 | +} |
---|
| 509 | + |
---|
| 510 | +static int |
---|
| 511 | +cea_db_offsets(const u8 *cea, int *start, int *end) |
---|
| 512 | +{ |
---|
| 513 | + /* DisplayID CTA extension blocks and top-level CEA EDID |
---|
| 514 | + * block header definitions differ in the following bytes: |
---|
| 515 | + * 1) Byte 2 of the header specifies length differently, |
---|
| 516 | + * 2) Byte 3 is only present in the CEA top level block. |
---|
| 517 | + * |
---|
| 518 | + * The different definitions for byte 2 follow. |
---|
| 519 | + * |
---|
| 520 | + * DisplayID CTA extension block defines byte 2 as: |
---|
| 521 | + * Number of payload bytes |
---|
| 522 | + * |
---|
| 523 | + * CEA EDID block defines byte 2 as: |
---|
| 524 | + * Byte number (decimal) within this block where the 18-byte |
---|
| 525 | + * DTDs begin. If no non-DTD data is present in this extension |
---|
| 526 | + * block, the value should be set to 04h (the byte after next). |
---|
| 527 | + * If set to 00h, there are no DTDs present in this block and |
---|
| 528 | + * no non-DTD data. |
---|
| 529 | + */ |
---|
| 530 | + if (cea[0] == 0x81) { |
---|
| 531 | + /* |
---|
| 532 | + * for_each_displayid_db() has already verified |
---|
| 533 | + * that these stay within expected bounds. |
---|
| 534 | + */ |
---|
| 535 | + *start = 3; |
---|
| 536 | + *end = *start + cea[2]; |
---|
| 537 | + } else if (cea[0] == 0x02) { |
---|
| 538 | + /* Data block offset in CEA extension block */ |
---|
| 539 | + *start = 4; |
---|
| 540 | + *end = cea[2]; |
---|
| 541 | + if (*end == 0) |
---|
| 542 | + *end = 127; |
---|
| 543 | + if (*end < 4 || *end > 127) |
---|
| 544 | + return -ERANGE; |
---|
| 545 | + } else { |
---|
| 546 | + return -EOPNOTSUPP; |
---|
| 547 | + } |
---|
| 548 | + |
---|
| 549 | + return 0; |
---|
| 550 | +} |
---|
| 551 | + |
---|
| 552 | +static u8 *find_edid_extension(const struct edid *edid, |
---|
| 553 | + int ext_id, int *ext_index) |
---|
| 554 | +{ |
---|
| 555 | + u8 *edid_ext = NULL; |
---|
| 556 | + int i; |
---|
| 557 | + |
---|
| 558 | + /* No EDID or EDID extensions */ |
---|
| 559 | + if (edid == NULL || edid->extensions == 0) |
---|
242 | 560 | return NULL; |
---|
243 | 561 | |
---|
244 | | - drm_for_each_crtc(crtc, drm_dev) { |
---|
245 | | - if (crtc->port == np_crtc) |
---|
246 | | - return crtc; |
---|
| 562 | + /* Find CEA extension */ |
---|
| 563 | + for (i = *ext_index; i < edid->extensions; i++) { |
---|
| 564 | + edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1); |
---|
| 565 | + if (edid_ext[0] == ext_id) |
---|
| 566 | + break; |
---|
| 567 | + } |
---|
| 568 | + |
---|
| 569 | + if (i >= edid->extensions) |
---|
| 570 | + return NULL; |
---|
| 571 | + |
---|
| 572 | + *ext_index = i + 1; |
---|
| 573 | + |
---|
| 574 | + return edid_ext; |
---|
| 575 | +} |
---|
| 576 | + |
---|
| 577 | +static int validate_displayid(u8 *displayid, int length, int idx) |
---|
| 578 | +{ |
---|
| 579 | + int i, dispid_length; |
---|
| 580 | + u8 csum = 0; |
---|
| 581 | + struct displayid_hdr *base; |
---|
| 582 | + |
---|
| 583 | + base = (struct displayid_hdr *)&displayid[idx]; |
---|
| 584 | + |
---|
| 585 | + DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n", |
---|
| 586 | + base->rev, base->bytes, base->prod_id, base->ext_count); |
---|
| 587 | + |
---|
| 588 | + /* +1 for DispID checksum */ |
---|
| 589 | + dispid_length = sizeof(*base) + base->bytes + 1; |
---|
| 590 | + if (dispid_length > length - idx) |
---|
| 591 | + return -EINVAL; |
---|
| 592 | + |
---|
| 593 | + for (i = 0; i < dispid_length; i++) |
---|
| 594 | + csum += displayid[idx + i]; |
---|
| 595 | + if (csum) { |
---|
| 596 | + DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum); |
---|
| 597 | + return -EINVAL; |
---|
| 598 | + } |
---|
| 599 | + |
---|
| 600 | + return 0; |
---|
| 601 | +} |
---|
| 602 | + |
---|
| 603 | +static u8 *find_displayid_extension(const struct edid *edid, |
---|
| 604 | + int *length, int *idx, |
---|
| 605 | + int *ext_index) |
---|
| 606 | +{ |
---|
| 607 | + u8 *displayid = find_edid_extension(edid, 0x70, ext_index); |
---|
| 608 | + struct displayid_hdr *base; |
---|
| 609 | + int ret; |
---|
| 610 | + |
---|
| 611 | + if (!displayid) |
---|
| 612 | + return NULL; |
---|
| 613 | + |
---|
| 614 | + /* EDID extensions block checksum isn't for us */ |
---|
| 615 | + *length = EDID_LENGTH - 1; |
---|
| 616 | + *idx = 1; |
---|
| 617 | + |
---|
| 618 | + ret = validate_displayid(displayid, *length, *idx); |
---|
| 619 | + if (ret) |
---|
| 620 | + return NULL; |
---|
| 621 | + |
---|
| 622 | + base = (struct displayid_hdr *)&displayid[*idx]; |
---|
| 623 | + *length = *idx + sizeof(*base) + base->bytes; |
---|
| 624 | + |
---|
| 625 | + return displayid; |
---|
| 626 | +} |
---|
| 627 | + |
---|
| 628 | +static u8 *find_cea_extension(const struct edid *edid) |
---|
| 629 | +{ |
---|
| 630 | + int length, idx; |
---|
| 631 | + struct displayid_block *block; |
---|
| 632 | + u8 *cea; |
---|
| 633 | + u8 *displayid; |
---|
| 634 | + int ext_index; |
---|
| 635 | + |
---|
| 636 | + /* Look for a top level CEA extension block */ |
---|
| 637 | + /* FIXME: make callers iterate through multiple CEA ext blocks? */ |
---|
| 638 | + ext_index = 0; |
---|
| 639 | + cea = find_edid_extension(edid, 0x02, &ext_index); |
---|
| 640 | + if (cea) |
---|
| 641 | + return cea; |
---|
| 642 | + |
---|
| 643 | + /* CEA blocks can also be found embedded in a DisplayID block */ |
---|
| 644 | + ext_index = 0; |
---|
| 645 | + for (;;) { |
---|
| 646 | + displayid = find_displayid_extension(edid, &length, &idx, |
---|
| 647 | + &ext_index); |
---|
| 648 | + if (!displayid) |
---|
| 649 | + return NULL; |
---|
| 650 | + |
---|
| 651 | + idx += sizeof(struct displayid_hdr); |
---|
| 652 | + for_each_displayid_db(displayid, block, idx, length) { |
---|
| 653 | + if (block->tag == 0x81) |
---|
| 654 | + return (u8 *)block; |
---|
| 655 | + } |
---|
247 | 656 | } |
---|
248 | 657 | |
---|
249 | 658 | return NULL; |
---|
250 | 659 | } |
---|
251 | 660 | |
---|
252 | | -static struct drm_connector *find_connector_by_node(struct drm_device *drm_dev, |
---|
253 | | - struct device_node *node) |
---|
| 661 | +#define EDID_CEA_YCRCB422 (1 << 4) |
---|
| 662 | + |
---|
| 663 | +int rockchip_drm_get_yuv422_format(struct drm_connector *connector, |
---|
| 664 | + struct edid *edid) |
---|
254 | 665 | { |
---|
255 | | - struct device_node *np_connector; |
---|
256 | | - struct rockchip_drm_sub_dev *sub_dev; |
---|
| 666 | + struct drm_display_info *info; |
---|
| 667 | + const u8 *edid_ext; |
---|
257 | 668 | |
---|
258 | | - np_connector = of_graph_get_remote_port_parent(node); |
---|
259 | | - if (!np_connector || !of_device_is_available(np_connector)) |
---|
260 | | - return NULL; |
---|
| 669 | + if (!connector || !edid) |
---|
| 670 | + return -EINVAL; |
---|
261 | 671 | |
---|
262 | | - sub_dev = rockchip_drm_get_sub_dev(np_connector); |
---|
263 | | - if (!sub_dev) |
---|
264 | | - return NULL; |
---|
| 672 | + info = &connector->display_info; |
---|
265 | 673 | |
---|
266 | | - return sub_dev->connector; |
---|
267 | | -} |
---|
| 674 | + edid_ext = find_cea_extension(edid); |
---|
| 675 | + if (!edid_ext) |
---|
| 676 | + return -EINVAL; |
---|
268 | 677 | |
---|
269 | | -static struct drm_connector *find_connector_by_bridge(struct drm_device *drm_dev, |
---|
270 | | - struct device_node *node) |
---|
271 | | -{ |
---|
272 | | - struct device_node *np_encoder, *np_connector = NULL; |
---|
273 | | - struct drm_connector *connector = NULL; |
---|
274 | | - struct device_node *port, *endpoint; |
---|
275 | | - struct rockchip_drm_sub_dev *sub_dev; |
---|
276 | | - |
---|
277 | | - np_encoder = of_graph_get_remote_port_parent(node); |
---|
278 | | - if (!np_encoder || !of_device_is_available(np_encoder)) |
---|
279 | | - goto err_put_encoder; |
---|
280 | | - |
---|
281 | | - port = of_graph_get_port_by_id(np_encoder, 1); |
---|
282 | | - if (!port) { |
---|
283 | | - dev_err(drm_dev->dev, "can't found port point!\n"); |
---|
284 | | - goto err_put_encoder; |
---|
285 | | - } |
---|
286 | | - |
---|
287 | | - for_each_child_of_node(port, endpoint) { |
---|
288 | | - np_connector = of_graph_get_remote_port_parent(endpoint); |
---|
289 | | - if (!np_connector) { |
---|
290 | | - dev_err(drm_dev->dev, |
---|
291 | | - "can't found connector node, please init!\n"); |
---|
292 | | - goto err_put_port; |
---|
293 | | - } |
---|
294 | | - if (!of_device_is_available(np_connector)) { |
---|
295 | | - of_node_put(np_connector); |
---|
296 | | - np_connector = NULL; |
---|
297 | | - continue; |
---|
298 | | - } else { |
---|
299 | | - break; |
---|
300 | | - } |
---|
301 | | - } |
---|
302 | | - if (!np_connector) { |
---|
303 | | - dev_err(drm_dev->dev, "can't found available connector node!\n"); |
---|
304 | | - goto err_put_port; |
---|
305 | | - } |
---|
306 | | - |
---|
307 | | - sub_dev = rockchip_drm_get_sub_dev(np_connector); |
---|
308 | | - if (!sub_dev) |
---|
309 | | - goto err_put_port; |
---|
310 | | - connector = sub_dev->connector; |
---|
311 | | - |
---|
312 | | - of_node_put(np_connector); |
---|
313 | | -err_put_port: |
---|
314 | | - of_node_put(port); |
---|
315 | | -err_put_encoder: |
---|
316 | | - of_node_put(np_encoder); |
---|
317 | | - |
---|
318 | | - return connector; |
---|
319 | | -} |
---|
320 | | - |
---|
321 | | -void rockchip_free_loader_memory(struct drm_device *drm) |
---|
322 | | -{ |
---|
323 | | - struct rockchip_drm_private *private = drm->dev_private; |
---|
324 | | - struct rockchip_logo *logo; |
---|
325 | | - void *start, *end; |
---|
326 | | - |
---|
327 | | - if (!private || !private->logo || --private->logo->count) |
---|
328 | | - return; |
---|
329 | | - |
---|
330 | | - logo = private->logo; |
---|
331 | | - start = phys_to_virt(logo->dma_addr); |
---|
332 | | - end = phys_to_virt(logo->dma_addr + logo->size); |
---|
333 | | - |
---|
334 | | - if (private->domain) { |
---|
335 | | - u32 pg_size = 1UL << __ffs(private->domain->pgsize_bitmap); |
---|
336 | | - |
---|
337 | | - iommu_unmap(private->domain, logo->dma_addr, ALIGN(logo->size, pg_size)); |
---|
338 | | - } |
---|
339 | | - |
---|
340 | | - memblock_free(logo->start, logo->size); |
---|
341 | | - free_reserved_area(start, end, -1, "drm_logo"); |
---|
342 | | - kfree(logo); |
---|
343 | | - private->logo = NULL; |
---|
344 | | - private->loader_protect = false; |
---|
345 | | -} |
---|
346 | | - |
---|
347 | | -static int init_loader_memory(struct drm_device *drm_dev) |
---|
348 | | -{ |
---|
349 | | - struct rockchip_drm_private *private = drm_dev->dev_private; |
---|
350 | | - struct rockchip_logo *logo; |
---|
351 | | - struct device_node *np = drm_dev->dev->of_node; |
---|
352 | | - struct device_node *node; |
---|
353 | | - phys_addr_t start, size; |
---|
354 | | - u32 pg_size = PAGE_SIZE; |
---|
355 | | - struct resource res; |
---|
356 | | - int ret, idx; |
---|
357 | | - |
---|
358 | | - idx = of_property_match_string(np, "memory-region-names", "drm-logo"); |
---|
359 | | - if (idx >= 0) |
---|
360 | | - node = of_parse_phandle(np, "memory-region", idx); |
---|
361 | | - else |
---|
362 | | - node = of_parse_phandle(np, "logo-memory-region", 0); |
---|
363 | | - if (!node) |
---|
364 | | - return -ENOMEM; |
---|
365 | | - |
---|
366 | | - ret = of_address_to_resource(node, 0, &res); |
---|
367 | | - if (ret) |
---|
368 | | - return ret; |
---|
369 | | - if (private->domain) |
---|
370 | | - pg_size = 1UL << __ffs(private->domain->pgsize_bitmap); |
---|
371 | | - start = ALIGN_DOWN(res.start, pg_size); |
---|
372 | | - size = resource_size(&res); |
---|
373 | | - if (!size) |
---|
374 | | - return -ENOMEM; |
---|
375 | | - |
---|
376 | | - logo = kmalloc(sizeof(*logo), GFP_KERNEL); |
---|
377 | | - if (!logo) |
---|
378 | | - return -ENOMEM; |
---|
379 | | - |
---|
380 | | - logo->kvaddr = phys_to_virt(start); |
---|
381 | | - |
---|
382 | | - if (private->domain) { |
---|
383 | | - ret = iommu_map(private->domain, start, start, ALIGN(size, pg_size), |
---|
384 | | - IOMMU_WRITE | IOMMU_READ); |
---|
385 | | - if (ret) { |
---|
386 | | - dev_err(drm_dev->dev, "failed to create 1v1 mapping\n"); |
---|
387 | | - goto err_free_logo; |
---|
388 | | - } |
---|
389 | | - } |
---|
390 | | - |
---|
391 | | - logo->dma_addr = start; |
---|
392 | | - logo->size = size; |
---|
393 | | - logo->count = 1; |
---|
394 | | - private->logo = logo; |
---|
395 | | - |
---|
396 | | - idx = of_property_match_string(np, "memory-region-names", "drm-cubic-lut"); |
---|
397 | | - if (idx < 0) |
---|
398 | | - return 0; |
---|
399 | | - |
---|
400 | | - node = of_parse_phandle(np, "memory-region", idx); |
---|
401 | | - if (!node) |
---|
402 | | - return -ENOMEM; |
---|
403 | | - |
---|
404 | | - ret = of_address_to_resource(node, 0, &res); |
---|
405 | | - if (ret) |
---|
406 | | - return ret; |
---|
407 | | - start = ALIGN_DOWN(res.start, pg_size); |
---|
408 | | - size = resource_size(&res); |
---|
409 | | - if (!size) |
---|
410 | | - return 0; |
---|
411 | | - |
---|
412 | | - private->cubic_lut_kvaddr = phys_to_virt(start); |
---|
413 | | - if (private->domain) { |
---|
414 | | - ret = iommu_map(private->domain, start, start, ALIGN(size, pg_size), |
---|
415 | | - IOMMU_WRITE | IOMMU_READ); |
---|
416 | | - if (ret) { |
---|
417 | | - dev_err(drm_dev->dev, "failed to create 1v1 mapping for cubic lut\n"); |
---|
418 | | - goto err_free_logo; |
---|
419 | | - } |
---|
420 | | - } |
---|
421 | | - private->cubic_lut_dma_addr = start; |
---|
| 678 | + if (edid_ext[3] & EDID_CEA_YCRCB422) |
---|
| 679 | + info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; |
---|
422 | 680 | |
---|
423 | 681 | return 0; |
---|
424 | | - |
---|
425 | | -err_free_logo: |
---|
426 | | - kfree(logo); |
---|
427 | | - |
---|
428 | | - return ret; |
---|
429 | 682 | } |
---|
| 683 | +EXPORT_SYMBOL(rockchip_drm_get_yuv422_format); |
---|
430 | 684 | |
---|
431 | | -static struct drm_framebuffer * |
---|
432 | | -get_framebuffer_by_node(struct drm_device *drm_dev, struct device_node *node) |
---|
| 685 | +static |
---|
| 686 | +void get_max_frl_rate(int max_frl_rate, u8 *max_lanes, u8 *max_rate_per_lane) |
---|
433 | 687 | { |
---|
434 | | - struct rockchip_drm_private *private = drm_dev->dev_private; |
---|
435 | | - struct drm_mode_fb_cmd2 mode_cmd = { 0 }; |
---|
436 | | - u32 val; |
---|
437 | | - int bpp; |
---|
438 | | - |
---|
439 | | - if (WARN_ON(!private->logo)) |
---|
440 | | - return NULL; |
---|
441 | | - |
---|
442 | | - if (of_property_read_u32(node, "logo,offset", &val)) { |
---|
443 | | - pr_err("%s: failed to get logo,offset\n", __func__); |
---|
444 | | - return NULL; |
---|
445 | | - } |
---|
446 | | - mode_cmd.offsets[0] = val; |
---|
447 | | - |
---|
448 | | - if (of_property_read_u32(node, "logo,width", &val)) { |
---|
449 | | - pr_err("%s: failed to get logo,width\n", __func__); |
---|
450 | | - return NULL; |
---|
451 | | - } |
---|
452 | | - mode_cmd.width = val; |
---|
453 | | - |
---|
454 | | - if (of_property_read_u32(node, "logo,height", &val)) { |
---|
455 | | - pr_err("%s: failed to get logo,height\n", __func__); |
---|
456 | | - return NULL; |
---|
457 | | - } |
---|
458 | | - mode_cmd.height = val; |
---|
459 | | - |
---|
460 | | - if (of_property_read_u32(node, "logo,bpp", &val)) { |
---|
461 | | - pr_err("%s: failed to get logo,bpp\n", __func__); |
---|
462 | | - return NULL; |
---|
463 | | - } |
---|
464 | | - bpp = val; |
---|
465 | | - |
---|
466 | | - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * bpp, 32) / 8; |
---|
467 | | - |
---|
468 | | - switch (bpp) { |
---|
469 | | - case 16: |
---|
470 | | - mode_cmd.pixel_format = DRM_FORMAT_RGB565; |
---|
| 688 | + switch (max_frl_rate) { |
---|
| 689 | + case 1: |
---|
| 690 | + *max_lanes = 3; |
---|
| 691 | + *max_rate_per_lane = 3; |
---|
471 | 692 | break; |
---|
472 | | - case 24: |
---|
473 | | - mode_cmd.pixel_format = DRM_FORMAT_RGB888; |
---|
| 693 | + case 2: |
---|
| 694 | + *max_lanes = 3; |
---|
| 695 | + *max_rate_per_lane = 6; |
---|
474 | 696 | break; |
---|
475 | | - case 32: |
---|
476 | | - mode_cmd.pixel_format = DRM_FORMAT_XRGB8888; |
---|
| 697 | + case 3: |
---|
| 698 | + *max_lanes = 4; |
---|
| 699 | + *max_rate_per_lane = 6; |
---|
477 | 700 | break; |
---|
| 701 | + case 4: |
---|
| 702 | + *max_lanes = 4; |
---|
| 703 | + *max_rate_per_lane = 8; |
---|
| 704 | + break; |
---|
| 705 | + case 5: |
---|
| 706 | + *max_lanes = 4; |
---|
| 707 | + *max_rate_per_lane = 10; |
---|
| 708 | + break; |
---|
| 709 | + case 6: |
---|
| 710 | + *max_lanes = 4; |
---|
| 711 | + *max_rate_per_lane = 12; |
---|
| 712 | + break; |
---|
| 713 | + case 0: |
---|
478 | 714 | default: |
---|
479 | | - pr_err("%s: unsupported to logo bpp %d\n", __func__, bpp); |
---|
480 | | - return NULL; |
---|
| 715 | + *max_lanes = 0; |
---|
| 716 | + *max_rate_per_lane = 0; |
---|
481 | 717 | } |
---|
482 | | - |
---|
483 | | - return rockchip_fb_alloc(drm_dev, &mode_cmd, NULL, private->logo, 1); |
---|
484 | 718 | } |
---|
485 | 719 | |
---|
486 | | -static struct rockchip_drm_mode_set * |
---|
487 | | -of_parse_display_resource(struct drm_device *drm_dev, struct device_node *route) |
---|
| 720 | +#define EDID_DSC_10BPC (1 << 0) |
---|
| 721 | +#define EDID_DSC_12BPC (1 << 1) |
---|
| 722 | +#define EDID_DSC_16BPC (1 << 2) |
---|
| 723 | +#define EDID_DSC_ALL_BPP (1 << 3) |
---|
| 724 | +#define EDID_DSC_NATIVE_420 (1 << 6) |
---|
| 725 | +#define EDID_DSC_1P2 (1 << 7) |
---|
| 726 | +#define EDID_DSC_MAX_FRL_RATE_MASK 0xf0 |
---|
| 727 | +#define EDID_DSC_MAX_SLICES 0xf |
---|
| 728 | +#define EDID_DSC_TOTAL_CHUNK_KBYTES 0x3f |
---|
| 729 | +#define EDID_MAX_FRL_RATE_MASK 0xf0 |
---|
| 730 | + |
---|
| 731 | +static |
---|
| 732 | +void parse_edid_forum_vsdb(struct rockchip_drm_dsc_cap *dsc_cap, |
---|
| 733 | + u8 *max_frl_rate_per_lane, u8 *max_lanes, u8 *add_func, |
---|
| 734 | + const u8 *hf_vsdb) |
---|
488 | 735 | { |
---|
489 | | - struct rockchip_drm_private *private = drm_dev->dev_private; |
---|
490 | | - struct rockchip_drm_mode_set *set; |
---|
491 | | - struct device_node *connect; |
---|
492 | | - struct drm_framebuffer *fb; |
---|
493 | | - struct drm_connector *connector; |
---|
494 | | - struct drm_crtc *crtc; |
---|
495 | | - const char *string; |
---|
496 | | - u32 val; |
---|
| 736 | + u8 max_frl_rate; |
---|
| 737 | + u8 dsc_max_frl_rate; |
---|
| 738 | + u8 dsc_max_slices; |
---|
497 | 739 | |
---|
498 | | - connect = of_parse_phandle(route, "connect", 0); |
---|
499 | | - if (!connect) |
---|
500 | | - return NULL; |
---|
501 | | - |
---|
502 | | - fb = get_framebuffer_by_node(drm_dev, route); |
---|
503 | | - if (IS_ERR_OR_NULL(fb)) |
---|
504 | | - return NULL; |
---|
505 | | - |
---|
506 | | - crtc = find_crtc_by_node(drm_dev, connect); |
---|
507 | | - connector = find_connector_by_node(drm_dev, connect); |
---|
508 | | - if (!connector) |
---|
509 | | - connector = find_connector_by_bridge(drm_dev, connect); |
---|
510 | | - if (!crtc || !connector) { |
---|
511 | | - dev_warn(drm_dev->dev, |
---|
512 | | - "No available crtc or connector for display"); |
---|
513 | | - drm_framebuffer_put(fb); |
---|
514 | | - return NULL; |
---|
515 | | - } |
---|
516 | | - |
---|
517 | | - set = kzalloc(sizeof(*set), GFP_KERNEL); |
---|
518 | | - if (!set) |
---|
519 | | - return NULL; |
---|
520 | | - |
---|
521 | | - if (!of_property_read_u32(route, "video,clock", &val)) |
---|
522 | | - set->clock = val; |
---|
523 | | - |
---|
524 | | - if (!of_property_read_u32(route, "video,hdisplay", &val)) |
---|
525 | | - set->hdisplay = val; |
---|
526 | | - |
---|
527 | | - if (!of_property_read_u32(route, "video,vdisplay", &val)) |
---|
528 | | - set->vdisplay = val; |
---|
529 | | - |
---|
530 | | - if (!of_property_read_u32(route, "video,crtc_hsync_end", &val)) |
---|
531 | | - set->crtc_hsync_end = val; |
---|
532 | | - |
---|
533 | | - if (!of_property_read_u32(route, "video,crtc_vsync_end", &val)) |
---|
534 | | - set->crtc_vsync_end = val; |
---|
535 | | - |
---|
536 | | - if (!of_property_read_u32(route, "video,vrefresh", &val)) |
---|
537 | | - set->vrefresh = val; |
---|
538 | | - |
---|
539 | | - if (!of_property_read_u32(route, "video,flags", &val)) |
---|
540 | | - set->flags = val; |
---|
541 | | - |
---|
542 | | - if (!of_property_read_u32(route, "video,aspect_ratio", &val)) |
---|
543 | | - set->picture_aspect_ratio = val; |
---|
544 | | - |
---|
545 | | - if (!of_property_read_u32(route, "overscan,left_margin", &val)) |
---|
546 | | - set->left_margin = val; |
---|
547 | | - |
---|
548 | | - if (!of_property_read_u32(route, "overscan,right_margin", &val)) |
---|
549 | | - set->right_margin = val; |
---|
550 | | - |
---|
551 | | - if (!of_property_read_u32(route, "overscan,top_margin", &val)) |
---|
552 | | - set->top_margin = val; |
---|
553 | | - |
---|
554 | | - if (!of_property_read_u32(route, "overscan,bottom_margin", &val)) |
---|
555 | | - set->bottom_margin = val; |
---|
556 | | - |
---|
557 | | - if (!of_property_read_u32(route, "bcsh,brightness", &val)) |
---|
558 | | - set->brightness = val; |
---|
559 | | - else |
---|
560 | | - set->brightness = 50; |
---|
561 | | - |
---|
562 | | - if (!of_property_read_u32(route, "bcsh,contrast", &val)) |
---|
563 | | - set->contrast = val; |
---|
564 | | - else |
---|
565 | | - set->contrast = 50; |
---|
566 | | - |
---|
567 | | - if (!of_property_read_u32(route, "bcsh,saturation", &val)) |
---|
568 | | - set->saturation = val; |
---|
569 | | - else |
---|
570 | | - set->saturation = 50; |
---|
571 | | - |
---|
572 | | - if (!of_property_read_u32(route, "bcsh,hue", &val)) |
---|
573 | | - set->hue = val; |
---|
574 | | - else |
---|
575 | | - set->hue = 50; |
---|
576 | | - |
---|
577 | | - set->force_output = of_property_read_bool(route, "force-output"); |
---|
578 | | - |
---|
579 | | - if (!of_property_read_u32(route, "cubic_lut,offset", &val)) { |
---|
580 | | - private->cubic_lut[crtc->index].enable = true; |
---|
581 | | - private->cubic_lut[crtc->index].offset = val; |
---|
582 | | - } |
---|
583 | | - |
---|
584 | | - set->ratio = 1; |
---|
585 | | - if (!of_property_read_string(route, "logo,mode", &string) && |
---|
586 | | - !strcmp(string, "fullscreen")) |
---|
587 | | - set->ratio = 0; |
---|
588 | | - |
---|
589 | | - set->fb = fb; |
---|
590 | | - set->crtc = crtc; |
---|
591 | | - set->connector = connector; |
---|
592 | | - |
---|
593 | | - return set; |
---|
594 | | -} |
---|
595 | | - |
---|
596 | | -static int rockchip_drm_fill_connector_modes(struct drm_connector *connector, |
---|
597 | | - uint32_t maxX, uint32_t maxY, |
---|
598 | | - bool force_output) |
---|
599 | | -{ |
---|
600 | | - struct drm_device *dev = connector->dev; |
---|
601 | | - struct drm_display_mode *mode; |
---|
602 | | - const struct drm_connector_helper_funcs *connector_funcs = |
---|
603 | | - connector->helper_private; |
---|
604 | | - int count = 0; |
---|
605 | | - bool verbose_prune = true; |
---|
606 | | - enum drm_connector_status old_status; |
---|
607 | | - |
---|
608 | | - WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
---|
609 | | - |
---|
610 | | - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, |
---|
611 | | - connector->name); |
---|
612 | | - /* set all modes to the unverified state */ |
---|
613 | | - list_for_each_entry(mode, &connector->modes, head) |
---|
614 | | - mode->status = MODE_STALE; |
---|
615 | | - |
---|
616 | | - if (force_output) |
---|
617 | | - connector->force = DRM_FORCE_ON; |
---|
618 | | - if (connector->force) { |
---|
619 | | - if (connector->force == DRM_FORCE_ON || |
---|
620 | | - connector->force == DRM_FORCE_ON_DIGITAL) |
---|
621 | | - connector->status = connector_status_connected; |
---|
622 | | - else |
---|
623 | | - connector->status = connector_status_disconnected; |
---|
624 | | - if (connector->funcs->force) |
---|
625 | | - connector->funcs->force(connector); |
---|
626 | | - } else { |
---|
627 | | - old_status = connector->status; |
---|
628 | | - |
---|
629 | | - if (connector->funcs->detect) |
---|
630 | | - connector->status = connector->funcs->detect(connector, true); |
---|
631 | | - else |
---|
632 | | - connector->status = connector_status_connected; |
---|
633 | | - /* |
---|
634 | | - * Normally either the driver's hpd code or the poll loop should |
---|
635 | | - * pick up any changes and fire the hotplug event. But if |
---|
636 | | - * userspace sneaks in a probe, we might miss a change. Hence |
---|
637 | | - * check here, and if anything changed start the hotplug code. |
---|
638 | | - */ |
---|
639 | | - if (old_status != connector->status) { |
---|
640 | | - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", |
---|
641 | | - connector->base.id, |
---|
642 | | - connector->name, |
---|
643 | | - old_status, connector->status); |
---|
644 | | - |
---|
645 | | - /* |
---|
646 | | - * The hotplug event code might call into the fb |
---|
647 | | - * helpers, and so expects that we do not hold any |
---|
648 | | - * locks. Fire up the poll struct instead, it will |
---|
649 | | - * disable itself again. |
---|
650 | | - */ |
---|
651 | | - dev->mode_config.delayed_event = true; |
---|
652 | | - if (dev->mode_config.poll_enabled) |
---|
653 | | - schedule_delayed_work(&dev->mode_config.output_poll_work, |
---|
654 | | - 0); |
---|
655 | | - } |
---|
656 | | - } |
---|
657 | | - |
---|
658 | | - /* Re-enable polling in case the global poll config changed. */ |
---|
659 | | - if (!dev->mode_config.poll_running) |
---|
660 | | - drm_kms_helper_poll_enable(dev); |
---|
661 | | - |
---|
662 | | - dev->mode_config.poll_running = true; |
---|
663 | | - |
---|
664 | | - if (connector->status == connector_status_disconnected) { |
---|
665 | | - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", |
---|
666 | | - connector->base.id, connector->name); |
---|
667 | | - drm_connector_update_edid_property(connector, NULL); |
---|
668 | | - verbose_prune = false; |
---|
669 | | - goto prune; |
---|
670 | | - } |
---|
671 | | - |
---|
672 | | - count = (*connector_funcs->get_modes)(connector); |
---|
673 | | - |
---|
674 | | - if (count == 0 && connector->status == connector_status_connected) |
---|
675 | | - count = drm_add_modes_noedid(connector, 1024, 768); |
---|
676 | | - if (force_output) |
---|
677 | | - count += rockchip_drm_add_modes_noedid(connector); |
---|
678 | | - if (count == 0) |
---|
679 | | - goto prune; |
---|
680 | | - |
---|
681 | | - drm_connector_list_update(connector); |
---|
682 | | - |
---|
683 | | - list_for_each_entry(mode, &connector->modes, head) { |
---|
684 | | - if (mode->status == MODE_OK) |
---|
685 | | - mode->status = drm_mode_validate_driver(dev, mode); |
---|
686 | | - |
---|
687 | | - if (mode->status == MODE_OK) |
---|
688 | | - mode->status = drm_mode_validate_size(mode, maxX, maxY); |
---|
689 | | - |
---|
690 | | - /** |
---|
691 | | - * if (mode->status == MODE_OK) |
---|
692 | | - * mode->status = drm_mode_validate_flag(mode, mode_flags); |
---|
693 | | - */ |
---|
694 | | - if (mode->status == MODE_OK && connector_funcs->mode_valid) |
---|
695 | | - mode->status = connector_funcs->mode_valid(connector, |
---|
696 | | - mode); |
---|
697 | | - if (mode->status == MODE_OK) |
---|
698 | | - mode->status = drm_mode_validate_ycbcr420(mode, |
---|
699 | | - connector); |
---|
700 | | - } |
---|
701 | | - |
---|
702 | | -prune: |
---|
703 | | - drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); |
---|
704 | | - |
---|
705 | | - if (list_empty(&connector->modes)) |
---|
706 | | - return 0; |
---|
707 | | - |
---|
708 | | - list_for_each_entry(mode, &connector->modes, head) |
---|
709 | | - mode->vrefresh = drm_mode_vrefresh(mode); |
---|
710 | | - |
---|
711 | | - drm_mode_sort(&connector->modes); |
---|
712 | | - |
---|
713 | | - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, |
---|
714 | | - connector->name); |
---|
715 | | - list_for_each_entry(mode, &connector->modes, head) { |
---|
716 | | - drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
---|
717 | | - drm_mode_debug_printmodeline(mode); |
---|
718 | | - } |
---|
719 | | - |
---|
720 | | - return count; |
---|
721 | | -} |
---|
722 | | - |
---|
723 | | -static int setup_initial_state(struct drm_device *drm_dev, |
---|
724 | | - struct drm_atomic_state *state, |
---|
725 | | - struct rockchip_drm_mode_set *set) |
---|
726 | | -{ |
---|
727 | | - struct rockchip_drm_private *priv = drm_dev->dev_private; |
---|
728 | | - struct drm_connector *connector = set->connector; |
---|
729 | | - struct drm_crtc *crtc = set->crtc; |
---|
730 | | - struct drm_crtc_state *crtc_state; |
---|
731 | | - struct drm_connector_state *conn_state; |
---|
732 | | - struct drm_plane_state *primary_state; |
---|
733 | | - struct drm_display_mode *mode = NULL; |
---|
734 | | - const struct drm_connector_helper_funcs *funcs; |
---|
735 | | - const struct drm_encoder_helper_funcs *encoder_funcs; |
---|
736 | | - int pipe = drm_crtc_index(crtc); |
---|
737 | | - bool is_crtc_enabled = true; |
---|
738 | | - int hdisplay, vdisplay; |
---|
739 | | - int fb_width, fb_height; |
---|
740 | | - int found = 0, match = 0; |
---|
741 | | - int num_modes; |
---|
742 | | - int ret = 0; |
---|
743 | | - struct rockchip_crtc_state *s = NULL; |
---|
744 | | - |
---|
745 | | - if (!set->hdisplay || !set->vdisplay || !set->vrefresh) |
---|
746 | | - is_crtc_enabled = false; |
---|
747 | | - |
---|
748 | | - conn_state = drm_atomic_get_connector_state(state, connector); |
---|
749 | | - if (IS_ERR(conn_state)) |
---|
750 | | - return PTR_ERR(conn_state); |
---|
751 | | - |
---|
752 | | - funcs = connector->helper_private; |
---|
753 | | - |
---|
754 | | - if (funcs->best_encoder) |
---|
755 | | - conn_state->best_encoder = funcs->best_encoder(connector); |
---|
756 | | - else |
---|
757 | | - conn_state->best_encoder = drm_atomic_helper_best_encoder(connector); |
---|
758 | | - |
---|
759 | | - if (funcs->loader_protect) |
---|
760 | | - funcs->loader_protect(connector, true); |
---|
761 | | - connector->loader_protect = true; |
---|
762 | | - encoder_funcs = conn_state->best_encoder->helper_private; |
---|
763 | | - if (encoder_funcs->loader_protect) |
---|
764 | | - encoder_funcs->loader_protect(conn_state->best_encoder, true); |
---|
765 | | - conn_state->best_encoder->loader_protect = true; |
---|
766 | | - num_modes = rockchip_drm_fill_connector_modes(connector, 4096, 4096, set->force_output); |
---|
767 | | - if (!num_modes) { |
---|
768 | | - dev_err(drm_dev->dev, "connector[%s] can't found any modes\n", |
---|
769 | | - connector->name); |
---|
770 | | - ret = -EINVAL; |
---|
771 | | - goto error_conn; |
---|
772 | | - } |
---|
773 | | - |
---|
774 | | - list_for_each_entry(mode, &connector->modes, head) { |
---|
775 | | - if (mode->clock == set->clock && |
---|
776 | | - mode->hdisplay == set->hdisplay && |
---|
777 | | - mode->vdisplay == set->vdisplay && |
---|
778 | | - mode->crtc_hsync_end == set->crtc_hsync_end && |
---|
779 | | - mode->crtc_vsync_end == set->crtc_vsync_end && |
---|
780 | | - drm_mode_vrefresh(mode) == set->vrefresh && |
---|
781 | | - /* we just need to focus on DRM_MODE_FLAG_ALL flag, so here |
---|
782 | | - * we compare mode->flags with set->flags & DRM_MODE_FLAG_ALL. |
---|
783 | | - */ |
---|
784 | | - mode->flags == (set->flags & DRM_MODE_FLAG_ALL) && |
---|
785 | | - mode->picture_aspect_ratio == set->picture_aspect_ratio) { |
---|
786 | | - found = 1; |
---|
787 | | - match = 1; |
---|
788 | | - break; |
---|
789 | | - } |
---|
790 | | - } |
---|
791 | | - |
---|
792 | | - if (!found) { |
---|
793 | | - ret = -EINVAL; |
---|
794 | | - connector->status = connector_status_disconnected; |
---|
795 | | - goto error_conn; |
---|
796 | | - } |
---|
797 | | - |
---|
798 | | - conn_state->tv.brightness = set->brightness; |
---|
799 | | - conn_state->tv.contrast = set->contrast; |
---|
800 | | - conn_state->tv.saturation = set->saturation; |
---|
801 | | - conn_state->tv.hue = set->hue; |
---|
802 | | - set->mode = mode; |
---|
803 | | - crtc_state = drm_atomic_get_crtc_state(state, crtc); |
---|
804 | | - if (IS_ERR(crtc_state)) { |
---|
805 | | - ret = PTR_ERR(crtc_state); |
---|
806 | | - goto error_conn; |
---|
807 | | - } |
---|
808 | | - |
---|
809 | | - drm_mode_copy(&crtc_state->adjusted_mode, mode); |
---|
810 | | - if (!match || !is_crtc_enabled) { |
---|
811 | | - set->mode_changed = true; |
---|
812 | | - } else { |
---|
813 | | - ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); |
---|
814 | | - if (ret) |
---|
815 | | - goto error_conn; |
---|
816 | | - |
---|
817 | | - mode->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE; |
---|
818 | | - ret = drm_atomic_set_mode_for_crtc(crtc_state, mode); |
---|
819 | | - if (ret) |
---|
820 | | - goto error_conn; |
---|
821 | | - |
---|
822 | | - crtc_state->active = true; |
---|
823 | | - |
---|
824 | | - if (priv->crtc_funcs[pipe] && |
---|
825 | | - priv->crtc_funcs[pipe]->loader_protect) |
---|
826 | | - priv->crtc_funcs[pipe]->loader_protect(crtc, true); |
---|
827 | | - } |
---|
828 | | - |
---|
829 | | - if (!set->fb) { |
---|
830 | | - ret = 0; |
---|
831 | | - goto error_crtc; |
---|
832 | | - } |
---|
833 | | - primary_state = drm_atomic_get_plane_state(state, crtc->primary); |
---|
834 | | - if (IS_ERR(primary_state)) { |
---|
835 | | - ret = PTR_ERR(primary_state); |
---|
836 | | - goto error_crtc; |
---|
837 | | - } |
---|
838 | | - |
---|
839 | | - hdisplay = mode->hdisplay; |
---|
840 | | - vdisplay = mode->vdisplay; |
---|
841 | | - fb_width = set->fb->width; |
---|
842 | | - fb_height = set->fb->height; |
---|
843 | | - |
---|
844 | | - primary_state->crtc = crtc; |
---|
845 | | - primary_state->src_x = 0; |
---|
846 | | - primary_state->src_y = 0; |
---|
847 | | - primary_state->src_w = fb_width << 16; |
---|
848 | | - primary_state->src_h = fb_height << 16; |
---|
849 | | - if (set->ratio) { |
---|
850 | | - if (set->fb->width >= hdisplay) { |
---|
851 | | - primary_state->crtc_x = 0; |
---|
852 | | - primary_state->crtc_w = hdisplay; |
---|
853 | | - } else { |
---|
854 | | - primary_state->crtc_x = (hdisplay - fb_width) / 2; |
---|
855 | | - primary_state->crtc_w = set->fb->width; |
---|
856 | | - } |
---|
857 | | - |
---|
858 | | - if (set->fb->height >= vdisplay) { |
---|
859 | | - primary_state->crtc_y = 0; |
---|
860 | | - primary_state->crtc_h = vdisplay; |
---|
861 | | - } else { |
---|
862 | | - primary_state->crtc_y = (vdisplay - fb_height) / 2; |
---|
863 | | - primary_state->crtc_h = fb_height; |
---|
864 | | - } |
---|
865 | | - } else { |
---|
866 | | - primary_state->crtc_x = 0; |
---|
867 | | - primary_state->crtc_y = 0; |
---|
868 | | - primary_state->crtc_w = hdisplay; |
---|
869 | | - primary_state->crtc_h = vdisplay; |
---|
870 | | - } |
---|
871 | | - s = to_rockchip_crtc_state(crtc->state); |
---|
872 | | - s->output_type = connector->connector_type; |
---|
873 | | - |
---|
874 | | - return 0; |
---|
875 | | - |
---|
876 | | -error_crtc: |
---|
877 | | - if (priv->crtc_funcs[pipe] && priv->crtc_funcs[pipe]->loader_protect) |
---|
878 | | - priv->crtc_funcs[pipe]->loader_protect(crtc, false); |
---|
879 | | -error_conn: |
---|
880 | | - if (funcs->loader_protect) |
---|
881 | | - funcs->loader_protect(connector, false); |
---|
882 | | - connector->loader_protect = false; |
---|
883 | | - if (encoder_funcs->loader_protect) |
---|
884 | | - encoder_funcs->loader_protect(conn_state->best_encoder, false); |
---|
885 | | - conn_state->best_encoder->loader_protect = false; |
---|
886 | | - |
---|
887 | | - return ret; |
---|
888 | | -} |
---|
889 | | - |
---|
890 | | -static int update_state(struct drm_device *drm_dev, |
---|
891 | | - struct drm_atomic_state *state, |
---|
892 | | - struct rockchip_drm_mode_set *set, |
---|
893 | | - unsigned int *plane_mask) |
---|
894 | | -{ |
---|
895 | | - struct drm_crtc *crtc = set->crtc; |
---|
896 | | - struct drm_connector *connector = set->connector; |
---|
897 | | - struct drm_display_mode *mode = set->mode; |
---|
898 | | - struct drm_plane_state *primary_state; |
---|
899 | | - struct drm_crtc_state *crtc_state; |
---|
900 | | - struct drm_connector_state *conn_state; |
---|
901 | | - int ret; |
---|
902 | | - struct rockchip_crtc_state *s; |
---|
903 | | - |
---|
904 | | - crtc_state = drm_atomic_get_crtc_state(state, crtc); |
---|
905 | | - if (IS_ERR(crtc_state)) |
---|
906 | | - return PTR_ERR(crtc_state); |
---|
907 | | - conn_state = drm_atomic_get_connector_state(state, connector); |
---|
908 | | - if (IS_ERR(conn_state)) |
---|
909 | | - return PTR_ERR(conn_state); |
---|
910 | | - s = to_rockchip_crtc_state(crtc_state); |
---|
911 | | - s->left_margin = set->left_margin; |
---|
912 | | - s->right_margin = set->right_margin; |
---|
913 | | - s->top_margin = set->top_margin; |
---|
914 | | - s->bottom_margin = set->bottom_margin; |
---|
915 | | - |
---|
916 | | - if (set->mode_changed) { |
---|
917 | | - ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); |
---|
918 | | - if (ret) |
---|
919 | | - return ret; |
---|
920 | | - |
---|
921 | | - ret = drm_atomic_set_mode_for_crtc(crtc_state, mode); |
---|
922 | | - if (ret) |
---|
923 | | - return ret; |
---|
924 | | - |
---|
925 | | - crtc_state->active = true; |
---|
926 | | - } else { |
---|
927 | | - const struct drm_encoder_helper_funcs *encoder_helper_funcs; |
---|
928 | | - const struct drm_connector_helper_funcs *connector_helper_funcs; |
---|
929 | | - struct drm_encoder *encoder; |
---|
930 | | - |
---|
931 | | - connector_helper_funcs = connector->helper_private; |
---|
932 | | - if (!connector_helper_funcs) |
---|
933 | | - return -ENXIO; |
---|
934 | | - if (connector_helper_funcs->best_encoder) |
---|
935 | | - encoder = connector_helper_funcs->best_encoder(connector); |
---|
936 | | - else |
---|
937 | | - encoder = drm_atomic_helper_best_encoder(connector); |
---|
938 | | - if (!encoder) |
---|
939 | | - return -ENXIO; |
---|
940 | | - encoder_helper_funcs = encoder->helper_private; |
---|
941 | | - if (!encoder_helper_funcs->atomic_check) |
---|
942 | | - return -ENXIO; |
---|
943 | | - ret = encoder_helper_funcs->atomic_check(encoder, crtc->state, |
---|
944 | | - conn_state); |
---|
945 | | - if (ret) |
---|
946 | | - return ret; |
---|
947 | | - |
---|
948 | | - if (encoder_helper_funcs->atomic_mode_set) |
---|
949 | | - encoder_helper_funcs->atomic_mode_set(encoder, |
---|
950 | | - crtc_state, |
---|
951 | | - conn_state); |
---|
952 | | - else if (encoder_helper_funcs->mode_set) |
---|
953 | | - encoder_helper_funcs->mode_set(encoder, mode, mode); |
---|
954 | | - } |
---|
955 | | - |
---|
956 | | - primary_state = drm_atomic_get_plane_state(state, crtc->primary); |
---|
957 | | - if (IS_ERR(primary_state)) |
---|
958 | | - return PTR_ERR(primary_state); |
---|
959 | | - |
---|
960 | | - crtc_state->plane_mask = 1 << drm_plane_index(crtc->primary); |
---|
961 | | - *plane_mask |= crtc_state->plane_mask; |
---|
962 | | - |
---|
963 | | - drm_atomic_set_fb_for_plane(primary_state, set->fb); |
---|
964 | | - drm_framebuffer_put(set->fb); |
---|
965 | | - ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); |
---|
966 | | - |
---|
967 | | - return ret; |
---|
968 | | -} |
---|
969 | | - |
---|
970 | | -static void show_loader_logo(struct drm_device *drm_dev) |
---|
971 | | -{ |
---|
972 | | - struct drm_atomic_state *state, *old_state; |
---|
973 | | - struct device_node *np = drm_dev->dev->of_node; |
---|
974 | | - struct drm_mode_config *mode_config = &drm_dev->mode_config; |
---|
975 | | - struct rockchip_drm_private *private = drm_dev->dev_private; |
---|
976 | | - struct device_node *root, *route; |
---|
977 | | - struct rockchip_drm_mode_set *set, *tmp, *unset; |
---|
978 | | - struct list_head mode_set_list; |
---|
979 | | - struct list_head mode_unset_list; |
---|
980 | | - unsigned int plane_mask = 0; |
---|
981 | | - int ret, i; |
---|
982 | | - |
---|
983 | | - root = of_get_child_by_name(np, "route"); |
---|
984 | | - if (!root) { |
---|
985 | | - dev_warn(drm_dev->dev, "failed to parse display resources\n"); |
---|
| 740 | + if (!hf_vsdb[7]) |
---|
986 | 741 | return; |
---|
987 | | - } |
---|
988 | 742 | |
---|
989 | | - if (init_loader_memory(drm_dev)) { |
---|
990 | | - dev_warn(drm_dev->dev, "failed to parse loader memory\n"); |
---|
| 743 | + DRM_DEBUG_KMS("hdmi_21 sink detected. parsing edid\n"); |
---|
| 744 | + max_frl_rate = (hf_vsdb[7] & EDID_MAX_FRL_RATE_MASK) >> 4; |
---|
| 745 | + get_max_frl_rate(max_frl_rate, max_lanes, |
---|
| 746 | + max_frl_rate_per_lane); |
---|
| 747 | + |
---|
| 748 | + *add_func = hf_vsdb[8]; |
---|
| 749 | + |
---|
| 750 | + if (cea_db_payload_len(hf_vsdb) < 13) |
---|
991 | 751 | return; |
---|
| 752 | + |
---|
| 753 | + dsc_cap->v_1p2 = hf_vsdb[11] & EDID_DSC_1P2; |
---|
| 754 | + |
---|
| 755 | + if (!dsc_cap->v_1p2) |
---|
| 756 | + return; |
---|
| 757 | + |
---|
| 758 | + dsc_cap->native_420 = hf_vsdb[11] & EDID_DSC_NATIVE_420; |
---|
| 759 | + dsc_cap->all_bpp = hf_vsdb[11] & EDID_DSC_ALL_BPP; |
---|
| 760 | + |
---|
| 761 | + if (hf_vsdb[11] & EDID_DSC_16BPC) |
---|
| 762 | + dsc_cap->bpc_supported = 16; |
---|
| 763 | + else if (hf_vsdb[11] & EDID_DSC_12BPC) |
---|
| 764 | + dsc_cap->bpc_supported = 12; |
---|
| 765 | + else if (hf_vsdb[11] & EDID_DSC_10BPC) |
---|
| 766 | + dsc_cap->bpc_supported = 10; |
---|
| 767 | + else |
---|
| 768 | + dsc_cap->bpc_supported = 0; |
---|
| 769 | + |
---|
| 770 | + dsc_max_frl_rate = (hf_vsdb[12] & EDID_DSC_MAX_FRL_RATE_MASK) >> 4; |
---|
| 771 | + get_max_frl_rate(dsc_max_frl_rate, &dsc_cap->max_lanes, |
---|
| 772 | + &dsc_cap->max_frl_rate_per_lane); |
---|
| 773 | + dsc_cap->total_chunk_kbytes = hf_vsdb[13] & EDID_DSC_TOTAL_CHUNK_KBYTES; |
---|
| 774 | + |
---|
| 775 | + dsc_max_slices = hf_vsdb[12] & EDID_DSC_MAX_SLICES; |
---|
| 776 | + switch (dsc_max_slices) { |
---|
| 777 | + case 1: |
---|
| 778 | + dsc_cap->max_slices = 1; |
---|
| 779 | + dsc_cap->clk_per_slice = 340; |
---|
| 780 | + break; |
---|
| 781 | + case 2: |
---|
| 782 | + dsc_cap->max_slices = 2; |
---|
| 783 | + dsc_cap->clk_per_slice = 340; |
---|
| 784 | + break; |
---|
| 785 | + case 3: |
---|
| 786 | + dsc_cap->max_slices = 4; |
---|
| 787 | + dsc_cap->clk_per_slice = 340; |
---|
| 788 | + break; |
---|
| 789 | + case 4: |
---|
| 790 | + dsc_cap->max_slices = 8; |
---|
| 791 | + dsc_cap->clk_per_slice = 340; |
---|
| 792 | + break; |
---|
| 793 | + case 5: |
---|
| 794 | + dsc_cap->max_slices = 8; |
---|
| 795 | + dsc_cap->clk_per_slice = 400; |
---|
| 796 | + break; |
---|
| 797 | + case 6: |
---|
| 798 | + dsc_cap->max_slices = 12; |
---|
| 799 | + dsc_cap->clk_per_slice = 400; |
---|
| 800 | + break; |
---|
| 801 | + case 7: |
---|
| 802 | + dsc_cap->max_slices = 16; |
---|
| 803 | + dsc_cap->clk_per_slice = 400; |
---|
| 804 | + break; |
---|
| 805 | + case 0: |
---|
| 806 | + default: |
---|
| 807 | + dsc_cap->max_slices = 0; |
---|
| 808 | + dsc_cap->clk_per_slice = 0; |
---|
992 | 809 | } |
---|
993 | | - |
---|
994 | | - INIT_LIST_HEAD(&mode_set_list); |
---|
995 | | - INIT_LIST_HEAD(&mode_unset_list); |
---|
996 | | - drm_modeset_lock_all(drm_dev); |
---|
997 | | - state = drm_atomic_state_alloc(drm_dev); |
---|
998 | | - if (!state) { |
---|
999 | | - dev_err(drm_dev->dev, "failed to alloc atomic state\n"); |
---|
1000 | | - ret = -ENOMEM; |
---|
1001 | | - goto err_unlock; |
---|
1002 | | - } |
---|
1003 | | - |
---|
1004 | | - state->acquire_ctx = mode_config->acquire_ctx; |
---|
1005 | | - |
---|
1006 | | - for_each_child_of_node(root, route) { |
---|
1007 | | - if (!of_device_is_available(route)) |
---|
1008 | | - continue; |
---|
1009 | | - |
---|
1010 | | - set = of_parse_display_resource(drm_dev, route); |
---|
1011 | | - if (!set) |
---|
1012 | | - continue; |
---|
1013 | | - |
---|
1014 | | - if (setup_initial_state(drm_dev, state, set)) { |
---|
1015 | | - drm_framebuffer_put(set->fb); |
---|
1016 | | - INIT_LIST_HEAD(&set->head); |
---|
1017 | | - list_add_tail(&set->head, &mode_unset_list); |
---|
1018 | | - continue; |
---|
1019 | | - } |
---|
1020 | | - INIT_LIST_HEAD(&set->head); |
---|
1021 | | - list_add_tail(&set->head, &mode_set_list); |
---|
1022 | | - } |
---|
1023 | | - |
---|
1024 | | - /* |
---|
1025 | | - * the mode_unset_list store the unconnected route, if route's crtc |
---|
1026 | | - * isn't used, we should close it. |
---|
1027 | | - */ |
---|
1028 | | - list_for_each_entry_safe(unset, tmp, &mode_unset_list, head) { |
---|
1029 | | - struct rockchip_drm_mode_set *tmp_set; |
---|
1030 | | - int find_used_crtc = 0; |
---|
1031 | | - |
---|
1032 | | - list_for_each_entry_safe(set, tmp_set, &mode_set_list, head) { |
---|
1033 | | - if (set->crtc == unset->crtc) { |
---|
1034 | | - find_used_crtc = 1; |
---|
1035 | | - continue; |
---|
1036 | | - } |
---|
1037 | | - } |
---|
1038 | | - |
---|
1039 | | - if (!find_used_crtc) { |
---|
1040 | | - struct drm_crtc *crtc = unset->crtc; |
---|
1041 | | - int pipe = drm_crtc_index(crtc); |
---|
1042 | | - struct rockchip_drm_private *priv = |
---|
1043 | | - drm_dev->dev_private; |
---|
1044 | | - |
---|
1045 | | - if (unset->hdisplay && unset->vdisplay) { |
---|
1046 | | - if (priv->crtc_funcs[pipe] && |
---|
1047 | | - priv->crtc_funcs[pipe]->loader_protect) |
---|
1048 | | - priv->crtc_funcs[pipe]->loader_protect(crtc, true); |
---|
1049 | | - priv->crtc_funcs[pipe]->crtc_close(crtc); |
---|
1050 | | - if (priv->crtc_funcs[pipe] && |
---|
1051 | | - priv->crtc_funcs[pipe]->loader_protect) |
---|
1052 | | - priv->crtc_funcs[pipe]->loader_protect(crtc, false); |
---|
1053 | | - } |
---|
1054 | | - } |
---|
1055 | | - |
---|
1056 | | - list_del(&unset->head); |
---|
1057 | | - kfree(unset); |
---|
1058 | | - } |
---|
1059 | | - |
---|
1060 | | - if (list_empty(&mode_set_list)) { |
---|
1061 | | - dev_warn(drm_dev->dev, "can't not find any loader display\n"); |
---|
1062 | | - ret = -ENXIO; |
---|
1063 | | - goto err_free_state; |
---|
1064 | | - } |
---|
1065 | | - |
---|
1066 | | - /* |
---|
1067 | | - * The state save initial devices status, swap the state into |
---|
1068 | | - * drm devices as old state, so if new state come, can compare |
---|
1069 | | - * with this state to judge which status need to update. |
---|
1070 | | - */ |
---|
1071 | | - WARN_ON(drm_atomic_helper_swap_state(state, false)); |
---|
1072 | | - drm_atomic_state_put(state); |
---|
1073 | | - old_state = drm_atomic_helper_duplicate_state(drm_dev, |
---|
1074 | | - mode_config->acquire_ctx); |
---|
1075 | | - if (IS_ERR(old_state)) { |
---|
1076 | | - dev_err(drm_dev->dev, "failed to duplicate atomic state\n"); |
---|
1077 | | - ret = PTR_ERR_OR_ZERO(old_state); |
---|
1078 | | - goto err_free_state; |
---|
1079 | | - } |
---|
1080 | | - |
---|
1081 | | - state = drm_atomic_helper_duplicate_state(drm_dev, |
---|
1082 | | - mode_config->acquire_ctx); |
---|
1083 | | - if (IS_ERR(state)) { |
---|
1084 | | - dev_err(drm_dev->dev, "failed to duplicate atomic state\n"); |
---|
1085 | | - ret = PTR_ERR_OR_ZERO(state); |
---|
1086 | | - goto err_free_old_state; |
---|
1087 | | - } |
---|
1088 | | - state->acquire_ctx = mode_config->acquire_ctx; |
---|
1089 | | - list_for_each_entry(set, &mode_set_list, head) |
---|
1090 | | - /* |
---|
1091 | | - * We don't want to see any fail on update_state. |
---|
1092 | | - */ |
---|
1093 | | - WARN_ON(update_state(drm_dev, state, set, &plane_mask)); |
---|
1094 | | - |
---|
1095 | | - for (i = 0; i < state->num_connector; i++) { |
---|
1096 | | - if (state->connectors[i].new_state->connector->status != |
---|
1097 | | - connector_status_connected) |
---|
1098 | | - state->connectors[i].new_state->best_encoder = NULL; |
---|
1099 | | - } |
---|
1100 | | - |
---|
1101 | | - ret = drm_atomic_commit(state); |
---|
1102 | | - /** |
---|
1103 | | - * todo |
---|
1104 | | - * drm_atomic_clean_old_fb(drm_dev, plane_mask, ret); |
---|
1105 | | - */ |
---|
1106 | | - |
---|
1107 | | - list_for_each_entry_safe(set, tmp, &mode_set_list, head) { |
---|
1108 | | - if (set->force_output) |
---|
1109 | | - set->connector->force = DRM_FORCE_UNSPECIFIED; |
---|
1110 | | - list_del(&set->head); |
---|
1111 | | - kfree(set); |
---|
1112 | | - } |
---|
1113 | | - |
---|
1114 | | - /* |
---|
1115 | | - * Is possible get deadlock here? |
---|
1116 | | - */ |
---|
1117 | | - WARN_ON(ret == -EDEADLK); |
---|
1118 | | - |
---|
1119 | | - if (ret) { |
---|
1120 | | - /* |
---|
1121 | | - * restore display status if atomic commit failed. |
---|
1122 | | - */ |
---|
1123 | | - WARN_ON(drm_atomic_helper_swap_state(old_state, false)); |
---|
1124 | | - goto err_free_state; |
---|
1125 | | - } |
---|
1126 | | - |
---|
1127 | | - rockchip_free_loader_memory(drm_dev); |
---|
1128 | | - drm_atomic_state_put(old_state); |
---|
1129 | | - drm_atomic_state_put(state); |
---|
1130 | | - |
---|
1131 | | - private->loader_protect = true; |
---|
1132 | | - drm_modeset_unlock_all(drm_dev); |
---|
1133 | | - return; |
---|
1134 | | -err_free_old_state: |
---|
1135 | | - drm_atomic_state_put(old_state); |
---|
1136 | | -err_free_state: |
---|
1137 | | - drm_atomic_state_put(state); |
---|
1138 | | -err_unlock: |
---|
1139 | | - drm_modeset_unlock_all(drm_dev); |
---|
1140 | | - if (ret) |
---|
1141 | | - dev_err(drm_dev->dev, "failed to show loader logo\n"); |
---|
1142 | 810 | } |
---|
1143 | 811 | |
---|
1144 | | -static const char *const loader_protect_clocks[] __initconst = { |
---|
1145 | | - "hclk_vio", |
---|
1146 | | - "hclk_vop", |
---|
1147 | | - "hclk_vopb", |
---|
1148 | | - "hclk_vopl", |
---|
1149 | | - "aclk_vio", |
---|
1150 | | - "aclk_vio0", |
---|
1151 | | - "aclk_vio1", |
---|
1152 | | - "aclk_vop", |
---|
1153 | | - "aclk_vopb", |
---|
1154 | | - "aclk_vopl", |
---|
1155 | | - "aclk_vo_pre", |
---|
1156 | | - "aclk_vio_pre", |
---|
1157 | | - "dclk_vop", |
---|
1158 | | - "dclk_vop0", |
---|
1159 | | - "dclk_vop1", |
---|
1160 | | - "dclk_vopb", |
---|
1161 | | - "dclk_vopl", |
---|
| 812 | +enum { |
---|
| 813 | + VER_26_BYTE_V0, |
---|
| 814 | + VER_15_BYTE_V1, |
---|
| 815 | + VER_12_BYTE_V1, |
---|
| 816 | + VER_12_BYTE_V2, |
---|
1162 | 817 | }; |
---|
1163 | 818 | |
---|
1164 | | -static struct clk **loader_clocks __initdata; |
---|
1165 | | -static int __init rockchip_clocks_loader_protect(void) |
---|
| 819 | +static int check_next_hdr_version(const u8 *next_hdr_db) |
---|
1166 | 820 | { |
---|
1167 | | - int nclocks = ARRAY_SIZE(loader_protect_clocks); |
---|
1168 | | - struct clk *clk; |
---|
1169 | | - int i; |
---|
| 821 | + u16 ver; |
---|
1170 | 822 | |
---|
1171 | | - loader_clocks = kcalloc(nclocks, sizeof(void *), GFP_KERNEL); |
---|
1172 | | - if (!loader_clocks) |
---|
1173 | | - return -ENOMEM; |
---|
| 823 | + ver = (next_hdr_db[5] & 0xf0) << 8 | next_hdr_db[0]; |
---|
1174 | 824 | |
---|
1175 | | - for (i = 0; i < nclocks; i++) { |
---|
1176 | | - clk = __clk_lookup(loader_protect_clocks[i]); |
---|
1177 | | - |
---|
1178 | | - if (clk) { |
---|
1179 | | - loader_clocks[i] = clk; |
---|
1180 | | - clk_prepare_enable(clk); |
---|
1181 | | - } |
---|
| 825 | + switch (ver) { |
---|
| 826 | + case 0x00f9: |
---|
| 827 | + return VER_26_BYTE_V0; |
---|
| 828 | + case 0x20ee: |
---|
| 829 | + return VER_15_BYTE_V1; |
---|
| 830 | + case 0x20eb: |
---|
| 831 | + return VER_12_BYTE_V1; |
---|
| 832 | + case 0x40eb: |
---|
| 833 | + return VER_12_BYTE_V2; |
---|
| 834 | + default: |
---|
| 835 | + return -ENOENT; |
---|
1182 | 836 | } |
---|
1183 | | - |
---|
1184 | | - return 0; |
---|
1185 | 837 | } |
---|
1186 | | -arch_initcall_sync(rockchip_clocks_loader_protect); |
---|
1187 | 838 | |
---|
1188 | | -static int __init rockchip_clocks_loader_unprotect(void) |
---|
| 839 | +static void parse_ver_26_v0_data(struct ver_26_v0 *hdr, const u8 *data) |
---|
1189 | 840 | { |
---|
1190 | | - int i; |
---|
| 841 | + hdr->yuv422_12bit = data[5] & BIT(0); |
---|
| 842 | + hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1; |
---|
| 843 | + hdr->global_dimming = (data[5] & BIT(2)) >> 2; |
---|
1191 | 844 | |
---|
1192 | | - if (!loader_clocks) |
---|
1193 | | - return -ENODEV; |
---|
| 845 | + hdr->dm_major_ver = (data[21] & 0xf0) >> 4; |
---|
| 846 | + hdr->dm_minor_ver = data[21] & 0xf; |
---|
1194 | 847 | |
---|
1195 | | - for (i = 0; i < ARRAY_SIZE(loader_protect_clocks); i++) { |
---|
1196 | | - struct clk *clk = loader_clocks[i]; |
---|
| 848 | + hdr->t_min_pq = (data[19] << 4) | ((data[18] & 0xf0) >> 4); |
---|
| 849 | + hdr->t_max_pq = (data[20] << 4) | (data[18] & 0xf); |
---|
1197 | 850 | |
---|
1198 | | - if (clk) |
---|
1199 | | - clk_disable_unprepare(clk); |
---|
| 851 | + hdr->rx = (data[7] << 4) | ((data[6] & 0xf0) >> 4); |
---|
| 852 | + hdr->ry = (data[8] << 4) | (data[6] & 0xf); |
---|
| 853 | + hdr->gx = (data[10] << 4) | ((data[9] & 0xf0) >> 4); |
---|
| 854 | + hdr->gy = (data[11] << 4) | (data[9] & 0xf); |
---|
| 855 | + hdr->bx = (data[13] << 4) | ((data[12] & 0xf0) >> 4); |
---|
| 856 | + hdr->by = (data[14] << 4) | (data[12] & 0xf); |
---|
| 857 | + hdr->wx = (data[16] << 4) | ((data[15] & 0xf0) >> 4); |
---|
| 858 | + hdr->wy = (data[17] << 4) | (data[15] & 0xf); |
---|
| 859 | +} |
---|
| 860 | + |
---|
| 861 | +static void parse_ver_15_v1_data(struct ver_15_v1 *hdr, const u8 *data) |
---|
| 862 | +{ |
---|
| 863 | + hdr->yuv422_12bit = data[5] & BIT(0); |
---|
| 864 | + hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1; |
---|
| 865 | + hdr->global_dimming = data[6] & BIT(0); |
---|
| 866 | + |
---|
| 867 | + hdr->dm_version = (data[5] & 0x1c) >> 2; |
---|
| 868 | + |
---|
| 869 | + hdr->colorimetry = data[7] & BIT(0); |
---|
| 870 | + |
---|
| 871 | + hdr->t_max_lum = (data[6] & 0xfe) >> 1; |
---|
| 872 | + hdr->t_min_lum = (data[7] & 0xfe) >> 1; |
---|
| 873 | + |
---|
| 874 | + hdr->rx = data[9]; |
---|
| 875 | + hdr->ry = data[10]; |
---|
| 876 | + hdr->gx = data[11]; |
---|
| 877 | + hdr->gy = data[12]; |
---|
| 878 | + hdr->bx = data[13]; |
---|
| 879 | + hdr->by = data[14]; |
---|
| 880 | +} |
---|
| 881 | + |
---|
| 882 | +static void parse_ver_12_v1_data(struct ver_12_v1 *hdr, const u8 *data) |
---|
| 883 | +{ |
---|
| 884 | + hdr->yuv422_12bit = data[5] & BIT(0); |
---|
| 885 | + hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1; |
---|
| 886 | + hdr->global_dimming = data[6] & BIT(0); |
---|
| 887 | + |
---|
| 888 | + hdr->dm_version = (data[5] & 0x1c) >> 2; |
---|
| 889 | + |
---|
| 890 | + hdr->colorimetry = data[7] & BIT(0); |
---|
| 891 | + |
---|
| 892 | + hdr->t_max_lum = (data[6] & 0xfe) >> 1; |
---|
| 893 | + hdr->t_min_lum = (data[7] & 0xfe) >> 1; |
---|
| 894 | + |
---|
| 895 | + hdr->low_latency = data[8] & 0x3; |
---|
| 896 | + |
---|
| 897 | + hdr->unique_rx = (data[11] & 0xf8) >> 3; |
---|
| 898 | + hdr->unique_ry = (data[11] & 0x7) << 2 | (data[10] & BIT(0)) << 1 | |
---|
| 899 | + (data[9] & BIT(0)); |
---|
| 900 | + hdr->unique_gx = (data[9] & 0xfe) >> 1; |
---|
| 901 | + hdr->unique_gy = (data[10] & 0xfe) >> 1; |
---|
| 902 | + hdr->unique_bx = (data[8] & 0xe0) >> 5; |
---|
| 903 | + hdr->unique_by = (data[8] & 0x1c) >> 2; |
---|
| 904 | +} |
---|
| 905 | + |
---|
| 906 | +static void parse_ver_12_v2_data(struct ver_12_v2 *hdr, const u8 *data) |
---|
| 907 | +{ |
---|
| 908 | + hdr->yuv422_12bit = data[5] & BIT(0); |
---|
| 909 | + hdr->backlt_ctrl = (data[5] & BIT(1)) >> 1; |
---|
| 910 | + hdr->global_dimming = (data[6] & BIT(2)) >> 2; |
---|
| 911 | + |
---|
| 912 | + hdr->dm_version = (data[5] & 0x1c) >> 2; |
---|
| 913 | + hdr->backlt_min_luma = data[6] & 0x3; |
---|
| 914 | + hdr->interface = data[7] & 0x3; |
---|
| 915 | + hdr->yuv444_10b_12b = (data[8] & BIT(0)) << 1 | (data[9] & BIT(0)); |
---|
| 916 | + |
---|
| 917 | + hdr->t_min_pq_v2 = (data[6] & 0xf8) >> 3; |
---|
| 918 | + hdr->t_max_pq_v2 = (data[7] & 0xf8) >> 3; |
---|
| 919 | + |
---|
| 920 | + hdr->unique_rx = (data[10] & 0xf8) >> 3; |
---|
| 921 | + hdr->unique_ry = (data[11] & 0xf8) >> 3; |
---|
| 922 | + hdr->unique_gx = (data[8] & 0xfe) >> 1; |
---|
| 923 | + hdr->unique_gy = (data[9] & 0xfe) >> 1; |
---|
| 924 | + hdr->unique_bx = data[10] & 0x7; |
---|
| 925 | + hdr->unique_by = data[11] & 0x7; |
---|
| 926 | +} |
---|
| 927 | + |
---|
| 928 | +static |
---|
| 929 | +void parse_next_hdr_block(struct next_hdr_sink_data *sink_data, |
---|
| 930 | + const u8 *next_hdr_db) |
---|
| 931 | +{ |
---|
| 932 | + int version; |
---|
| 933 | + |
---|
| 934 | + version = check_next_hdr_version(next_hdr_db); |
---|
| 935 | + if (version < 0) |
---|
| 936 | + return; |
---|
| 937 | + |
---|
| 938 | + sink_data->version = version; |
---|
| 939 | + |
---|
| 940 | + switch (version) { |
---|
| 941 | + case VER_26_BYTE_V0: |
---|
| 942 | + parse_ver_26_v0_data(&sink_data->ver_26_v0, next_hdr_db); |
---|
| 943 | + break; |
---|
| 944 | + case VER_15_BYTE_V1: |
---|
| 945 | + parse_ver_15_v1_data(&sink_data->ver_15_v1, next_hdr_db); |
---|
| 946 | + break; |
---|
| 947 | + case VER_12_BYTE_V1: |
---|
| 948 | + parse_ver_12_v1_data(&sink_data->ver_12_v1, next_hdr_db); |
---|
| 949 | + break; |
---|
| 950 | + case VER_12_BYTE_V2: |
---|
| 951 | + parse_ver_12_v2_data(&sink_data->ver_12_v2, next_hdr_db); |
---|
| 952 | + break; |
---|
| 953 | + default: |
---|
| 954 | + break; |
---|
1200 | 955 | } |
---|
1201 | | - kfree(loader_clocks); |
---|
1202 | | - |
---|
1203 | | - return 0; |
---|
1204 | 956 | } |
---|
1205 | | -late_initcall_sync(rockchip_clocks_loader_unprotect); |
---|
1206 | | -#endif |
---|
1207 | 957 | |
---|
1208 | | -int rockchip_drm_crtc_send_mcu_cmd(struct drm_device *drm_dev, |
---|
1209 | | - struct device_node *np_crtc, |
---|
1210 | | - u32 type, u32 value) |
---|
| 958 | +int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, |
---|
| 959 | + u8 *max_frl_rate_per_lane, u8 *max_lanes, u8 *add_func, |
---|
| 960 | + const struct edid *edid) |
---|
1211 | 961 | { |
---|
1212 | | - struct drm_crtc *crtc; |
---|
1213 | | - int pipe = 0; |
---|
1214 | | - struct rockchip_drm_private *priv; |
---|
| 962 | + const u8 *edid_ext; |
---|
| 963 | + int i, start, end; |
---|
1215 | 964 | |
---|
1216 | | - if (!np_crtc || !of_device_is_available(np_crtc)) |
---|
| 965 | + if (!dsc_cap || !max_frl_rate_per_lane || !max_lanes || !edid || !add_func) |
---|
1217 | 966 | return -EINVAL; |
---|
1218 | 967 | |
---|
1219 | | - drm_for_each_crtc(crtc, drm_dev) { |
---|
1220 | | - if (of_get_parent(crtc->port) == np_crtc) |
---|
1221 | | - break; |
---|
1222 | | - } |
---|
1223 | | - |
---|
1224 | | - pipe = drm_crtc_index(crtc); |
---|
1225 | | - if (pipe >= ROCKCHIP_MAX_CRTC) |
---|
| 968 | + edid_ext = find_cea_extension(edid); |
---|
| 969 | + if (!edid_ext) |
---|
1226 | 970 | return -EINVAL; |
---|
1227 | | - priv = crtc->dev->dev_private; |
---|
1228 | | - if (priv->crtc_funcs[pipe]->crtc_send_mcu_cmd) |
---|
1229 | | - priv->crtc_funcs[pipe]->crtc_send_mcu_cmd(crtc, type, value); |
---|
| 971 | + |
---|
| 972 | + if (cea_db_offsets(edid_ext, &start, &end)) |
---|
| 973 | + return -EINVAL; |
---|
| 974 | + |
---|
| 975 | + for_each_cea_db(edid_ext, i, start, end) { |
---|
| 976 | + const u8 *db = &edid_ext[i]; |
---|
| 977 | + |
---|
| 978 | + if (cea_db_is_hdmi_forum_vsdb(db)) |
---|
| 979 | + parse_edid_forum_vsdb(dsc_cap, max_frl_rate_per_lane, |
---|
| 980 | + max_lanes, add_func, db); |
---|
| 981 | + } |
---|
1230 | 982 | |
---|
1231 | 983 | return 0; |
---|
1232 | 984 | } |
---|
1233 | | -EXPORT_SYMBOL(rockchip_drm_crtc_send_mcu_cmd); |
---|
| 985 | +EXPORT_SYMBOL(rockchip_drm_parse_cea_ext); |
---|
| 986 | + |
---|
| 987 | +int rockchip_drm_parse_next_hdr(struct next_hdr_sink_data *sink_data, |
---|
| 988 | + const struct edid *edid) |
---|
| 989 | +{ |
---|
| 990 | + const u8 *edid_ext; |
---|
| 991 | + int i, start, end; |
---|
| 992 | + |
---|
| 993 | + if (!sink_data || !edid) |
---|
| 994 | + return -EINVAL; |
---|
| 995 | + |
---|
| 996 | + memset(sink_data, 0, sizeof(struct next_hdr_sink_data)); |
---|
| 997 | + |
---|
| 998 | + edid_ext = find_cea_extension(edid); |
---|
| 999 | + if (!edid_ext) |
---|
| 1000 | + return -EINVAL; |
---|
| 1001 | + |
---|
| 1002 | + if (cea_db_offsets(edid_ext, &start, &end)) |
---|
| 1003 | + return -EINVAL; |
---|
| 1004 | + |
---|
| 1005 | + for_each_cea_db(edid_ext, i, start, end) { |
---|
| 1006 | + const u8 *db = &edid_ext[i]; |
---|
| 1007 | + |
---|
| 1008 | + if (cea_db_is_hdmi_next_hdr_block(db)) |
---|
| 1009 | + parse_next_hdr_block(sink_data, db); |
---|
| 1010 | + } |
---|
| 1011 | + |
---|
| 1012 | + return 0; |
---|
| 1013 | +} |
---|
| 1014 | +EXPORT_SYMBOL(rockchip_drm_parse_next_hdr); |
---|
| 1015 | + |
---|
| 1016 | +#define COLORIMETRY_DATA_BLOCK 0x5 |
---|
| 1017 | +#define USE_EXTENDED_TAG 0x07 |
---|
| 1018 | + |
---|
| 1019 | +static bool cea_db_is_hdmi_colorimetry_data_block(const u8 *db) |
---|
| 1020 | +{ |
---|
| 1021 | + if (cea_db_tag(db) != USE_EXTENDED_TAG) |
---|
| 1022 | + return false; |
---|
| 1023 | + |
---|
| 1024 | + if (db[1] != COLORIMETRY_DATA_BLOCK) |
---|
| 1025 | + return false; |
---|
| 1026 | + |
---|
| 1027 | + return true; |
---|
| 1028 | +} |
---|
| 1029 | + |
---|
| 1030 | +int |
---|
| 1031 | +rockchip_drm_parse_colorimetry_data_block(u8 *colorimetry, const struct edid *edid) |
---|
| 1032 | +{ |
---|
| 1033 | + const u8 *edid_ext; |
---|
| 1034 | + int i, start, end; |
---|
| 1035 | + |
---|
| 1036 | + if (!colorimetry || !edid) |
---|
| 1037 | + return -EINVAL; |
---|
| 1038 | + |
---|
| 1039 | + *colorimetry = 0; |
---|
| 1040 | + |
---|
| 1041 | + edid_ext = find_cea_extension(edid); |
---|
| 1042 | + if (!edid_ext) |
---|
| 1043 | + return -EINVAL; |
---|
| 1044 | + |
---|
| 1045 | + if (cea_db_offsets(edid_ext, &start, &end)) |
---|
| 1046 | + return -EINVAL; |
---|
| 1047 | + |
---|
| 1048 | + for_each_cea_db(edid_ext, i, start, end) { |
---|
| 1049 | + const u8 *db = &edid_ext[i]; |
---|
| 1050 | + |
---|
| 1051 | + if (cea_db_is_hdmi_colorimetry_data_block(db)) |
---|
| 1052 | + /* As per CEA 861-G spec */ |
---|
| 1053 | + *colorimetry = ((db[3] & (0x1 << 7)) << 1) | db[2]; |
---|
| 1054 | + } |
---|
| 1055 | + |
---|
| 1056 | + return 0; |
---|
| 1057 | +} |
---|
| 1058 | +EXPORT_SYMBOL(rockchip_drm_parse_colorimetry_data_block); |
---|
1234 | 1059 | |
---|
1235 | 1060 | /* |
---|
1236 | 1061 | * Attach a (component) device to the shared drm dma mapping from master drm |
---|
.. | .. |
---|
1265 | 1090 | return; |
---|
1266 | 1091 | |
---|
1267 | 1092 | iommu_detach_device(domain, dev); |
---|
| 1093 | +} |
---|
| 1094 | + |
---|
| 1095 | +void rockchip_drm_crtc_standby(struct drm_crtc *crtc, bool standby) |
---|
| 1096 | +{ |
---|
| 1097 | + struct rockchip_drm_private *priv = crtc->dev->dev_private; |
---|
| 1098 | + int pipe = drm_crtc_index(crtc); |
---|
| 1099 | + |
---|
| 1100 | + if (pipe < ROCKCHIP_MAX_CRTC && |
---|
| 1101 | + priv->crtc_funcs[pipe] && |
---|
| 1102 | + priv->crtc_funcs[pipe]->crtc_standby) |
---|
| 1103 | + priv->crtc_funcs[pipe]->crtc_standby(crtc, standby); |
---|
1268 | 1104 | } |
---|
1269 | 1105 | |
---|
1270 | 1106 | int rockchip_register_crtc_funcs(struct drm_crtc *crtc, |
---|
.. | .. |
---|
1383 | 1219 | struct drm_minor *minor = node->minor; |
---|
1384 | 1220 | struct drm_device *drm_dev = minor->dev; |
---|
1385 | 1221 | struct rockchip_drm_private *priv = drm_dev->dev_private; |
---|
1386 | | - |
---|
1387 | 1222 | struct drm_printer p = drm_seq_file_printer(s); |
---|
1388 | 1223 | |
---|
1389 | 1224 | if (!priv->domain) |
---|
1390 | 1225 | return 0; |
---|
1391 | | - |
---|
1392 | 1226 | mutex_lock(&priv->mm_lock); |
---|
1393 | | - |
---|
1394 | 1227 | drm_mm_print(&priv->mm, &p); |
---|
1395 | | - |
---|
1396 | 1228 | mutex_unlock(&priv->mm_lock); |
---|
1397 | 1229 | |
---|
1398 | 1230 | return 0; |
---|
.. | .. |
---|
1462 | 1294 | { "mm_dump", rockchip_drm_mm_dump, 0, NULL }, |
---|
1463 | 1295 | }; |
---|
1464 | 1296 | |
---|
1465 | | -static int rockchip_drm_debugfs_init(struct drm_minor *minor) |
---|
| 1297 | +static void rockchip_drm_debugfs_init(struct drm_minor *minor) |
---|
1466 | 1298 | { |
---|
1467 | 1299 | struct drm_device *dev = minor->dev; |
---|
1468 | 1300 | struct rockchip_drm_private *priv = dev->dev_private; |
---|
1469 | 1301 | struct drm_crtc *crtc; |
---|
1470 | | - int ret; |
---|
1471 | 1302 | |
---|
1472 | | - ret = drm_debugfs_create_files(rockchip_debugfs_files, |
---|
1473 | | - ARRAY_SIZE(rockchip_debugfs_files), |
---|
1474 | | - minor->debugfs_root, |
---|
1475 | | - minor); |
---|
1476 | | - if (ret) { |
---|
1477 | | - dev_err(dev->dev, "could not install rockchip_debugfs_list\n"); |
---|
1478 | | - return ret; |
---|
1479 | | - } |
---|
| 1303 | + drm_debugfs_create_files(rockchip_debugfs_files, |
---|
| 1304 | + ARRAY_SIZE(rockchip_debugfs_files), |
---|
| 1305 | + minor->debugfs_root, minor); |
---|
1480 | 1306 | |
---|
1481 | 1307 | drm_for_each_crtc(crtc, dev) { |
---|
1482 | 1308 | int pipe = drm_crtc_index(crtc); |
---|
.. | .. |
---|
1485 | 1311 | priv->crtc_funcs[pipe]->debugfs_init) |
---|
1486 | 1312 | priv->crtc_funcs[pipe]->debugfs_init(minor, crtc); |
---|
1487 | 1313 | } |
---|
1488 | | - |
---|
1489 | | - return 0; |
---|
1490 | 1314 | } |
---|
1491 | 1315 | #endif |
---|
| 1316 | + |
---|
| 1317 | +static const struct drm_prop_enum_list split_area[] = { |
---|
| 1318 | + { ROCKCHIP_DRM_SPLIT_UNSET, "UNSET" }, |
---|
| 1319 | + { ROCKCHIP_DRM_SPLIT_LEFT_SIDE, "LEFT" }, |
---|
| 1320 | + { ROCKCHIP_DRM_SPLIT_RIGHT_SIDE, "RIGHT" }, |
---|
| 1321 | +}; |
---|
1492 | 1322 | |
---|
1493 | 1323 | static int rockchip_drm_create_properties(struct drm_device *dev) |
---|
1494 | 1324 | { |
---|
.. | .. |
---|
1508 | 1338 | private->color_space_prop = prop; |
---|
1509 | 1339 | |
---|
1510 | 1340 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
---|
1511 | | - "GLOBAL_ALPHA", 0, 255); |
---|
1512 | | - if (!prop) |
---|
1513 | | - return -ENOMEM; |
---|
1514 | | - private->global_alpha_prop = prop; |
---|
1515 | | - |
---|
1516 | | - prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
---|
1517 | | - "BLEND_MODE", 0, 1); |
---|
1518 | | - if (!prop) |
---|
1519 | | - return -ENOMEM; |
---|
1520 | | - private->blend_mode_prop = prop; |
---|
1521 | | - |
---|
1522 | | - prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
---|
1523 | | - "ALPHA_SCALE", 0, 1); |
---|
1524 | | - if (!prop) |
---|
1525 | | - return -ENOMEM; |
---|
1526 | | - private->alpha_scale_prop = prop; |
---|
1527 | | - |
---|
1528 | | - prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
---|
1529 | 1341 | "ASYNC_COMMIT", 0, 1); |
---|
1530 | 1342 | if (!prop) |
---|
1531 | 1343 | return -ENOMEM; |
---|
.. | .. |
---|
1537 | 1349 | return -ENOMEM; |
---|
1538 | 1350 | private->share_id_prop = prop; |
---|
1539 | 1351 | |
---|
1540 | | - prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
---|
| 1352 | + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_IMMUTABLE, |
---|
1541 | 1353 | "CONNECTOR_ID", 0, 0xf); |
---|
1542 | 1354 | if (!prop) |
---|
1543 | 1355 | return -ENOMEM; |
---|
1544 | 1356 | private->connector_id_prop = prop; |
---|
1545 | 1357 | |
---|
| 1358 | + prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "SPLIT_AREA", |
---|
| 1359 | + split_area, |
---|
| 1360 | + ARRAY_SIZE(split_area)); |
---|
| 1361 | + private->split_area_prop = prop; |
---|
| 1362 | + |
---|
| 1363 | + prop = drm_property_create_object(dev, |
---|
| 1364 | + DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_IMMUTABLE, |
---|
| 1365 | + "SOC_ID", DRM_MODE_OBJECT_CRTC); |
---|
| 1366 | + private->soc_id_prop = prop; |
---|
| 1367 | + |
---|
| 1368 | + prop = drm_property_create_object(dev, |
---|
| 1369 | + DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_IMMUTABLE, |
---|
| 1370 | + "PORT_ID", DRM_MODE_OBJECT_CRTC); |
---|
| 1371 | + private->port_id_prop = prop; |
---|
| 1372 | + |
---|
| 1373 | + private->aclk_prop = drm_property_create_range(dev, 0, "ACLK", 0, UINT_MAX); |
---|
| 1374 | + private->bg_prop = drm_property_create_range(dev, 0, "BACKGROUND", 0, UINT_MAX); |
---|
| 1375 | + private->line_flag_prop = drm_property_create_range(dev, 0, "LINE_FLAG1", 0, UINT_MAX); |
---|
| 1376 | + private->cubic_lut_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CUBIC_LUT", 0); |
---|
| 1377 | + private->cubic_lut_size_prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, |
---|
| 1378 | + "CUBIC_LUT_SIZE", 0, UINT_MAX); |
---|
| 1379 | + |
---|
1546 | 1380 | return drm_mode_create_tv_properties(dev, 0, NULL); |
---|
1547 | | -} |
---|
1548 | | - |
---|
1549 | | -static int rockchip_gem_pool_init(struct drm_device *drm) |
---|
1550 | | -{ |
---|
1551 | | - struct rockchip_drm_private *private = drm->dev_private; |
---|
1552 | | - struct device_node *np = drm->dev->of_node; |
---|
1553 | | - struct device_node *node; |
---|
1554 | | - phys_addr_t start, size; |
---|
1555 | | - struct resource res; |
---|
1556 | | - int ret; |
---|
1557 | | - |
---|
1558 | | - node = of_parse_phandle(np, "secure-memory-region", 0); |
---|
1559 | | - if (!node) |
---|
1560 | | - return -ENXIO; |
---|
1561 | | - |
---|
1562 | | - ret = of_address_to_resource(node, 0, &res); |
---|
1563 | | - if (ret) |
---|
1564 | | - return ret; |
---|
1565 | | - start = res.start; |
---|
1566 | | - size = resource_size(&res); |
---|
1567 | | - if (!size) |
---|
1568 | | - return -ENOMEM; |
---|
1569 | | - |
---|
1570 | | - private->secure_buffer_pool = gen_pool_create(PAGE_SHIFT, -1); |
---|
1571 | | - if (!private->secure_buffer_pool) |
---|
1572 | | - return -ENOMEM; |
---|
1573 | | - |
---|
1574 | | - gen_pool_add(private->secure_buffer_pool, start, size, -1); |
---|
1575 | | - |
---|
1576 | | - return 0; |
---|
1577 | | -} |
---|
1578 | | - |
---|
1579 | | -static void rockchip_gem_pool_destroy(struct drm_device *drm) |
---|
1580 | | -{ |
---|
1581 | | - struct rockchip_drm_private *private = drm->dev_private; |
---|
1582 | | - |
---|
1583 | | - if (!private->secure_buffer_pool) |
---|
1584 | | - return; |
---|
1585 | | - |
---|
1586 | | - gen_pool_destroy(private->secure_buffer_pool); |
---|
1587 | 1381 | } |
---|
1588 | 1382 | |
---|
1589 | 1383 | static void rockchip_attach_connector_property(struct drm_device *drm) |
---|
.. | .. |
---|
1655 | 1449 | drm_modeset_unlock_all(drm); |
---|
1656 | 1450 | } |
---|
1657 | 1451 | |
---|
1658 | | -static bool is_support_hotplug(uint32_t output_type) |
---|
| 1452 | +static int rockchip_gem_pool_init(struct drm_device *drm) |
---|
1659 | 1453 | { |
---|
1660 | | - switch (output_type) { |
---|
1661 | | - case DRM_MODE_CONNECTOR_DVII: |
---|
1662 | | - case DRM_MODE_CONNECTOR_DVID: |
---|
1663 | | - case DRM_MODE_CONNECTOR_DVIA: |
---|
1664 | | - case DRM_MODE_CONNECTOR_DisplayPort: |
---|
1665 | | - case DRM_MODE_CONNECTOR_HDMIA: |
---|
1666 | | - case DRM_MODE_CONNECTOR_HDMIB: |
---|
1667 | | - case DRM_MODE_CONNECTOR_TV: |
---|
1668 | | - return true; |
---|
1669 | | - default: |
---|
1670 | | - return false; |
---|
1671 | | - } |
---|
| 1454 | + struct rockchip_drm_private *private = drm->dev_private; |
---|
| 1455 | + struct device_node *np = drm->dev->of_node; |
---|
| 1456 | + struct device_node *node; |
---|
| 1457 | + phys_addr_t start, size; |
---|
| 1458 | + struct resource res; |
---|
| 1459 | + int ret; |
---|
| 1460 | + |
---|
| 1461 | + node = of_parse_phandle(np, "secure-memory-region", 0); |
---|
| 1462 | + if (!node) |
---|
| 1463 | + return -ENXIO; |
---|
| 1464 | + |
---|
| 1465 | + ret = of_address_to_resource(node, 0, &res); |
---|
| 1466 | + if (ret) |
---|
| 1467 | + return ret; |
---|
| 1468 | + start = res.start; |
---|
| 1469 | + size = resource_size(&res); |
---|
| 1470 | + if (!size) |
---|
| 1471 | + return -ENOMEM; |
---|
| 1472 | + |
---|
| 1473 | + private->secure_buffer_pool = gen_pool_create(PAGE_SHIFT, -1); |
---|
| 1474 | + if (!private->secure_buffer_pool) |
---|
| 1475 | + return -ENOMEM; |
---|
| 1476 | + |
---|
| 1477 | + gen_pool_add(private->secure_buffer_pool, start, size, -1); |
---|
| 1478 | + |
---|
| 1479 | + return 0; |
---|
| 1480 | +} |
---|
| 1481 | + |
---|
| 1482 | +static void rockchip_gem_pool_destroy(struct drm_device *drm) |
---|
| 1483 | +{ |
---|
| 1484 | + struct rockchip_drm_private *private = drm->dev_private; |
---|
| 1485 | + |
---|
| 1486 | + if (!private->secure_buffer_pool) |
---|
| 1487 | + return; |
---|
| 1488 | + |
---|
| 1489 | + gen_pool_destroy(private->secure_buffer_pool); |
---|
1672 | 1490 | } |
---|
1673 | 1491 | |
---|
1674 | 1492 | static int rockchip_drm_bind(struct device *dev) |
---|
.. | .. |
---|
1676 | 1494 | struct drm_device *drm_dev; |
---|
1677 | 1495 | struct rockchip_drm_private *private; |
---|
1678 | 1496 | int ret; |
---|
1679 | | - struct device_node *np = dev->of_node; |
---|
1680 | | - struct device_node *parent_np; |
---|
1681 | | - struct drm_crtc *crtc; |
---|
1682 | 1497 | |
---|
1683 | 1498 | drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev); |
---|
1684 | 1499 | if (IS_ERR(drm_dev)) |
---|
.. | .. |
---|
1692 | 1507 | goto err_free; |
---|
1693 | 1508 | } |
---|
1694 | 1509 | |
---|
1695 | | - mutex_init(&private->commit_lock); |
---|
1696 | 1510 | mutex_init(&private->ovl_lock); |
---|
1697 | | - INIT_WORK(&private->commit_work, rockchip_drm_atomic_work); |
---|
| 1511 | + |
---|
1698 | 1512 | drm_dev->dev_private = private; |
---|
1699 | 1513 | |
---|
1700 | | - private->dmc_support = false; |
---|
1701 | | - private->devfreq = devfreq_get_devfreq_by_phandle(dev, 0); |
---|
1702 | | - if (IS_ERR(private->devfreq)) { |
---|
1703 | | - if (PTR_ERR(private->devfreq) == -EPROBE_DEFER) { |
---|
1704 | | - parent_np = of_parse_phandle(np, "devfreq", 0); |
---|
1705 | | - if (parent_np && |
---|
1706 | | - of_device_is_available(parent_np)) { |
---|
1707 | | - private->dmc_support = true; |
---|
1708 | | - dev_warn(dev, "defer getting devfreq\n"); |
---|
1709 | | - } else { |
---|
1710 | | - dev_info(dev, "dmc is disabled\n"); |
---|
1711 | | - } |
---|
1712 | | - } else { |
---|
1713 | | - dev_info(dev, "devfreq is not set\n"); |
---|
1714 | | - } |
---|
1715 | | - private->devfreq = NULL; |
---|
1716 | | - } else { |
---|
1717 | | - private->dmc_support = true; |
---|
1718 | | - dev_info(dev, "devfreq is ready\n"); |
---|
1719 | | - } |
---|
1720 | | - private->hdmi_pll.pll = devm_clk_get(dev, "hdmi-tmds-pll"); |
---|
1721 | | - if (PTR_ERR(private->hdmi_pll.pll) == -ENOENT) { |
---|
1722 | | - private->hdmi_pll.pll = NULL; |
---|
1723 | | - } else if (PTR_ERR(private->hdmi_pll.pll) == -EPROBE_DEFER) { |
---|
| 1514 | + INIT_LIST_HEAD(&private->psr_list); |
---|
| 1515 | + mutex_init(&private->psr_list_lock); |
---|
| 1516 | + mutex_init(&private->commit_lock); |
---|
| 1517 | + |
---|
| 1518 | + private->hdmi_pll.pll = devm_clk_get_optional(dev, "hdmi-tmds-pll"); |
---|
| 1519 | + if (PTR_ERR(private->hdmi_pll.pll) == -EPROBE_DEFER) { |
---|
1724 | 1520 | ret = -EPROBE_DEFER; |
---|
1725 | 1521 | goto err_free; |
---|
1726 | 1522 | } else if (IS_ERR(private->hdmi_pll.pll)) { |
---|
.. | .. |
---|
1728 | 1524 | ret = PTR_ERR(private->hdmi_pll.pll); |
---|
1729 | 1525 | goto err_free; |
---|
1730 | 1526 | } |
---|
1731 | | - private->default_pll.pll = devm_clk_get(dev, "default-vop-pll"); |
---|
1732 | | - if (PTR_ERR(private->default_pll.pll) == -ENOENT) { |
---|
1733 | | - private->default_pll.pll = NULL; |
---|
1734 | | - } else if (PTR_ERR(private->default_pll.pll) == -EPROBE_DEFER) { |
---|
| 1527 | + private->default_pll.pll = devm_clk_get_optional(dev, "default-vop-pll"); |
---|
| 1528 | + if (PTR_ERR(private->default_pll.pll) == -EPROBE_DEFER) { |
---|
1735 | 1529 | ret = -EPROBE_DEFER; |
---|
1736 | 1530 | goto err_free; |
---|
1737 | 1531 | } else if (IS_ERR(private->default_pll.pll)) { |
---|
.. | .. |
---|
1740 | 1534 | goto err_free; |
---|
1741 | 1535 | } |
---|
1742 | 1536 | |
---|
1743 | | - INIT_LIST_HEAD(&private->psr_list); |
---|
1744 | | - mutex_init(&private->psr_list_lock); |
---|
1745 | | - |
---|
1746 | | - ret = rockchip_drm_init_iommu(drm_dev); |
---|
| 1537 | + ret = drmm_mode_config_init(drm_dev); |
---|
1747 | 1538 | if (ret) |
---|
1748 | 1539 | goto err_free; |
---|
1749 | | - |
---|
1750 | | - drm_mode_config_init(drm_dev); |
---|
1751 | 1540 | |
---|
1752 | 1541 | rockchip_drm_mode_config_init(drm_dev); |
---|
1753 | 1542 | rockchip_drm_create_properties(drm_dev); |
---|
.. | .. |
---|
1773 | 1562 | /* init kms poll for handling hpd */ |
---|
1774 | 1563 | drm_kms_helper_poll_init(drm_dev); |
---|
1775 | 1564 | |
---|
1776 | | - private->page_pools = dmabuf_page_pool_create(GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP, 0); |
---|
| 1565 | + ret = rockchip_drm_init_iommu(drm_dev); |
---|
| 1566 | + if (ret) |
---|
| 1567 | + goto err_unbind_all; |
---|
1777 | 1568 | |
---|
1778 | 1569 | rockchip_gem_pool_init(drm_dev); |
---|
1779 | | -#ifndef MODULE |
---|
1780 | | - show_loader_logo(drm_dev); |
---|
1781 | | -#endif |
---|
1782 | 1570 | ret = of_reserved_mem_device_init(drm_dev->dev); |
---|
1783 | 1571 | if (ret) |
---|
1784 | 1572 | DRM_DEBUG_KMS("No reserved memory region assign to drm\n"); |
---|
1785 | 1573 | |
---|
| 1574 | + rockchip_drm_show_logo(drm_dev); |
---|
| 1575 | + |
---|
1786 | 1576 | ret = rockchip_drm_fbdev_init(drm_dev); |
---|
1787 | 1577 | if (ret) |
---|
1788 | | - goto err_kms_helper_poll_fini; |
---|
1789 | | - |
---|
1790 | | - if (private->fbdev_helper && private->fbdev_helper->fb) { |
---|
1791 | | - drm_for_each_crtc(crtc, drm_dev) { |
---|
1792 | | - struct rockchip_crtc_state *s = NULL; |
---|
1793 | | - |
---|
1794 | | - s = to_rockchip_crtc_state(crtc->state); |
---|
1795 | | - if (is_support_hotplug(s->output_type)) |
---|
1796 | | - drm_framebuffer_get(private->fbdev_helper->fb); |
---|
1797 | | - } |
---|
1798 | | - } |
---|
| 1578 | + goto err_iommu_cleanup; |
---|
1799 | 1579 | |
---|
1800 | 1580 | drm_dev->mode_config.allow_fb_modifiers = true; |
---|
1801 | 1581 | |
---|
1802 | 1582 | ret = drm_dev_register(drm_dev, 0); |
---|
1803 | 1583 | if (ret) |
---|
1804 | | - goto err_fbdev_fini; |
---|
| 1584 | + goto err_kms_helper_poll_fini; |
---|
1805 | 1585 | |
---|
1806 | 1586 | return 0; |
---|
1807 | | -err_fbdev_fini: |
---|
1808 | | - rockchip_drm_fbdev_fini(drm_dev); |
---|
1809 | 1587 | err_kms_helper_poll_fini: |
---|
1810 | 1588 | rockchip_gem_pool_destroy(drm_dev); |
---|
1811 | 1589 | drm_kms_helper_poll_fini(drm_dev); |
---|
| 1590 | + rockchip_drm_fbdev_fini(drm_dev); |
---|
| 1591 | +err_iommu_cleanup: |
---|
| 1592 | + rockchip_iommu_cleanup(drm_dev); |
---|
1812 | 1593 | err_unbind_all: |
---|
1813 | | - dmabuf_page_pool_destroy(private->page_pools); |
---|
1814 | 1594 | component_unbind_all(dev, drm_dev); |
---|
1815 | 1595 | err_mode_config_cleanup: |
---|
1816 | 1596 | drm_mode_config_cleanup(drm_dev); |
---|
1817 | | - rockchip_iommu_cleanup(drm_dev); |
---|
1818 | 1597 | err_free: |
---|
1819 | 1598 | drm_dev->dev_private = NULL; |
---|
1820 | 1599 | dev_set_drvdata(dev, NULL); |
---|
.. | .. |
---|
1971 | 1750 | return rockchip_gem_prime_end_cpu_access(obj, dir); |
---|
1972 | 1751 | } |
---|
1973 | 1752 | |
---|
1974 | | -static int rockchip_drm_gem_begin_cpu_access_partial( |
---|
1975 | | - struct dma_buf *dma_buf, |
---|
1976 | | - enum dma_data_direction dir, |
---|
1977 | | - unsigned int offset, unsigned int len) |
---|
1978 | | -{ |
---|
1979 | | - struct drm_gem_object *obj = dma_buf->priv; |
---|
1980 | | - |
---|
1981 | | - return rockchip_gem_prime_begin_cpu_access_partial(obj, dir, offset, len); |
---|
1982 | | -} |
---|
1983 | | - |
---|
1984 | | -static int rockchip_drm_gem_end_cpu_access_partial( |
---|
1985 | | - struct dma_buf *dma_buf, |
---|
1986 | | - enum dma_data_direction dir, |
---|
1987 | | - unsigned int offset, unsigned int len) |
---|
1988 | | -{ |
---|
1989 | | - struct drm_gem_object *obj = dma_buf->priv; |
---|
1990 | | - |
---|
1991 | | - return rockchip_gem_prime_end_cpu_access_partial(obj, dir, offset, len); |
---|
1992 | | -} |
---|
1993 | | - |
---|
1994 | 1753 | static const struct dma_buf_ops rockchip_drm_gem_prime_dmabuf_ops = { |
---|
| 1754 | + .cache_sgt_mapping = true, |
---|
1995 | 1755 | .attach = drm_gem_map_attach, |
---|
1996 | 1756 | .detach = drm_gem_map_detach, |
---|
1997 | 1757 | .map_dma_buf = drm_gem_map_dma_buf, |
---|
1998 | 1758 | .unmap_dma_buf = drm_gem_unmap_dma_buf, |
---|
1999 | 1759 | .release = drm_gem_dmabuf_release, |
---|
2000 | | - .map = drm_gem_dmabuf_kmap, |
---|
2001 | | - .unmap = drm_gem_dmabuf_kunmap, |
---|
2002 | 1760 | .mmap = drm_gem_dmabuf_mmap, |
---|
2003 | 1761 | .vmap = drm_gem_dmabuf_vmap, |
---|
2004 | 1762 | .vunmap = drm_gem_dmabuf_vunmap, |
---|
| 1763 | + .get_uuid = drm_gem_dmabuf_get_uuid, |
---|
2005 | 1764 | .begin_cpu_access = rockchip_drm_gem_dmabuf_begin_cpu_access, |
---|
2006 | 1765 | .end_cpu_access = rockchip_drm_gem_dmabuf_end_cpu_access, |
---|
2007 | | - .begin_cpu_access_partial = rockchip_drm_gem_begin_cpu_access_partial, |
---|
2008 | | - .end_cpu_access_partial = rockchip_drm_gem_end_cpu_access_partial, |
---|
2009 | 1766 | }; |
---|
2010 | | - |
---|
2011 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
2012 | | -static void drm_gem_prime_dmabuf_release_callback(void *data) |
---|
2013 | | -{ |
---|
2014 | | - struct drm_prime_callback_data *cb_data = data; |
---|
2015 | | - |
---|
2016 | | - if (cb_data && cb_data->obj && cb_data->obj->import_attach) { |
---|
2017 | | - struct dma_buf_attachment *attach = cb_data->obj->import_attach; |
---|
2018 | | - struct sg_table *sgt = cb_data->sgt; |
---|
2019 | | - |
---|
2020 | | - if (sgt) |
---|
2021 | | - dma_buf_unmap_attachment(attach, sgt, |
---|
2022 | | - DMA_BIDIRECTIONAL); |
---|
2023 | | - dma_buf_detach(attach->dmabuf, attach); |
---|
2024 | | - drm_gem_object_put_unlocked(cb_data->obj); |
---|
2025 | | - kfree(cb_data); |
---|
2026 | | - } |
---|
2027 | | -} |
---|
2028 | | -#endif |
---|
2029 | 1767 | |
---|
2030 | 1768 | static struct drm_gem_object *rockchip_drm_gem_prime_import_dev(struct drm_device *dev, |
---|
2031 | 1769 | struct dma_buf *dma_buf, |
---|
.. | .. |
---|
2034 | 1772 | struct dma_buf_attachment *attach; |
---|
2035 | 1773 | struct sg_table *sgt; |
---|
2036 | 1774 | struct drm_gem_object *obj; |
---|
2037 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
2038 | | - struct drm_prime_callback_data *cb_data = NULL; |
---|
2039 | | -#endif |
---|
2040 | 1775 | int ret; |
---|
2041 | 1776 | |
---|
2042 | 1777 | if (dma_buf->ops == &rockchip_drm_gem_prime_dmabuf_ops) { |
---|
.. | .. |
---|
2051 | 1786 | } |
---|
2052 | 1787 | } |
---|
2053 | 1788 | |
---|
2054 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
2055 | | - cb_data = dma_buf_get_release_callback_data(dma_buf, |
---|
2056 | | - drm_gem_prime_dmabuf_release_callback); |
---|
2057 | | - if (cb_data && cb_data->obj && cb_data->obj->dev == dev) { |
---|
2058 | | - drm_gem_object_get(cb_data->obj); |
---|
2059 | | - return cb_data->obj; |
---|
2060 | | - } |
---|
2061 | | -#endif |
---|
2062 | | - |
---|
2063 | 1789 | if (!dev->driver->gem_prime_import_sg_table) |
---|
2064 | 1790 | return ERR_PTR(-EINVAL); |
---|
2065 | 1791 | |
---|
.. | .. |
---|
2068 | 1794 | return ERR_CAST(attach); |
---|
2069 | 1795 | |
---|
2070 | 1796 | get_dma_buf(dma_buf); |
---|
2071 | | - |
---|
2072 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
2073 | | - cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); |
---|
2074 | | - if (!cb_data) { |
---|
2075 | | - ret = -ENOMEM; |
---|
2076 | | - goto fail_detach; |
---|
2077 | | - } |
---|
2078 | | -#endif |
---|
2079 | 1797 | |
---|
2080 | 1798 | sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); |
---|
2081 | 1799 | if (IS_ERR(sgt)) { |
---|
.. | .. |
---|
2090 | 1808 | } |
---|
2091 | 1809 | |
---|
2092 | 1810 | obj->import_attach = attach; |
---|
2093 | | - |
---|
2094 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
2095 | | - cb_data->obj = obj; |
---|
2096 | | - cb_data->sgt = sgt; |
---|
2097 | | - dma_buf_set_release_callback(dma_buf, |
---|
2098 | | - drm_gem_prime_dmabuf_release_callback, cb_data); |
---|
2099 | | - dma_buf_put(dma_buf); |
---|
2100 | | - drm_gem_object_get(obj); |
---|
2101 | | -#endif |
---|
| 1811 | + obj->resv = dma_buf->resv; |
---|
2102 | 1812 | |
---|
2103 | 1813 | return obj; |
---|
2104 | 1814 | |
---|
2105 | 1815 | fail_unmap: |
---|
2106 | 1816 | dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); |
---|
2107 | 1817 | fail_detach: |
---|
2108 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
2109 | | - kfree(cb_data); |
---|
2110 | | -#endif |
---|
2111 | 1818 | dma_buf_detach(dma_buf, attach); |
---|
2112 | 1819 | dma_buf_put(dma_buf); |
---|
2113 | 1820 | |
---|
.. | .. |
---|
2120 | 1827 | return rockchip_drm_gem_prime_import_dev(dev, dma_buf, dev->dev); |
---|
2121 | 1828 | } |
---|
2122 | 1829 | |
---|
2123 | | -static struct dma_buf *rockchip_drm_gem_prime_export(struct drm_device *dev, |
---|
2124 | | - struct drm_gem_object *obj, |
---|
| 1830 | +static struct dma_buf *rockchip_drm_gem_prime_export(struct drm_gem_object *obj, |
---|
2125 | 1831 | int flags) |
---|
2126 | 1832 | { |
---|
| 1833 | + struct drm_device *dev = obj->dev; |
---|
2127 | 1834 | struct dma_buf_export_info exp_info = { |
---|
2128 | 1835 | .exp_name = KBUILD_MODNAME, /* white lie for debug */ |
---|
2129 | 1836 | .owner = dev->driver->fops->owner, |
---|
.. | .. |
---|
2131 | 1838 | .size = obj->size, |
---|
2132 | 1839 | .flags = flags, |
---|
2133 | 1840 | .priv = obj, |
---|
| 1841 | + .resv = obj->resv, |
---|
2134 | 1842 | }; |
---|
2135 | | - |
---|
2136 | | - if (dev->driver->gem_prime_res_obj) |
---|
2137 | | - exp_info.resv = dev->driver->gem_prime_res_obj(obj); |
---|
2138 | 1843 | |
---|
2139 | 1844 | return drm_gem_dmabuf_export(dev, &exp_info); |
---|
2140 | 1845 | } |
---|
2141 | 1846 | |
---|
2142 | 1847 | static struct drm_driver rockchip_drm_driver = { |
---|
2143 | | - .driver_features = DRIVER_MODESET | DRIVER_GEM | |
---|
2144 | | - DRIVER_PRIME | DRIVER_ATOMIC | |
---|
2145 | | - DRIVER_RENDER, |
---|
| 1848 | + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_RENDER, |
---|
2146 | 1849 | .postclose = rockchip_drm_postclose, |
---|
2147 | 1850 | .lastclose = rockchip_drm_lastclose, |
---|
2148 | 1851 | .open = rockchip_drm_open, |
---|
2149 | 1852 | .gem_vm_ops = &drm_gem_cma_vm_ops, |
---|
2150 | 1853 | .gem_free_object_unlocked = rockchip_gem_free_object, |
---|
2151 | 1854 | .dumb_create = rockchip_gem_dumb_create, |
---|
2152 | | - .dumb_map_offset = rockchip_gem_dumb_map_offset, |
---|
2153 | | - .dumb_destroy = drm_gem_dumb_destroy, |
---|
2154 | 1855 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, |
---|
2155 | 1856 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, |
---|
2156 | 1857 | .gem_prime_import = rockchip_drm_gem_prime_import, |
---|
.. | .. |
---|
2171 | 1872 | .date = DRIVER_DATE, |
---|
2172 | 1873 | .major = DRIVER_MAJOR, |
---|
2173 | 1874 | .minor = DRIVER_MINOR, |
---|
2174 | | - .patchlevel = DRIVER_PATCH, |
---|
2175 | 1875 | }; |
---|
2176 | 1876 | |
---|
2177 | 1877 | #ifdef CONFIG_PM_SLEEP |
---|
2178 | | -static void rockchip_drm_fb_suspend(struct drm_device *drm) |
---|
2179 | | -{ |
---|
2180 | | - struct rockchip_drm_private *priv = drm->dev_private; |
---|
2181 | | - |
---|
2182 | | - console_lock(); |
---|
2183 | | - drm_fb_helper_set_suspend(priv->fbdev_helper, 1); |
---|
2184 | | - console_unlock(); |
---|
2185 | | -} |
---|
2186 | | - |
---|
2187 | | -static void rockchip_drm_fb_resume(struct drm_device *drm) |
---|
2188 | | -{ |
---|
2189 | | - struct rockchip_drm_private *priv = drm->dev_private; |
---|
2190 | | - |
---|
2191 | | - console_lock(); |
---|
2192 | | - drm_fb_helper_set_suspend(priv->fbdev_helper, 0); |
---|
2193 | | - console_unlock(); |
---|
2194 | | -} |
---|
2195 | | - |
---|
2196 | 1878 | static int rockchip_drm_sys_suspend(struct device *dev) |
---|
2197 | 1879 | { |
---|
2198 | 1880 | struct drm_device *drm = dev_get_drvdata(dev); |
---|
2199 | | - struct rockchip_drm_private *priv; |
---|
2200 | 1881 | |
---|
2201 | | - if (!drm) |
---|
2202 | | - return 0; |
---|
2203 | | - |
---|
2204 | | - drm_kms_helper_poll_disable(drm); |
---|
2205 | | - rockchip_drm_fb_suspend(drm); |
---|
2206 | | - |
---|
2207 | | - priv = drm->dev_private; |
---|
2208 | | - priv->state = drm_atomic_helper_suspend(drm); |
---|
2209 | | - if (IS_ERR(priv->state)) { |
---|
2210 | | - rockchip_drm_fb_resume(drm); |
---|
2211 | | - drm_kms_helper_poll_enable(drm); |
---|
2212 | | - return PTR_ERR(priv->state); |
---|
2213 | | - } |
---|
2214 | | - |
---|
2215 | | - return 0; |
---|
| 1882 | + return drm_mode_config_helper_suspend(drm); |
---|
2216 | 1883 | } |
---|
2217 | 1884 | |
---|
2218 | 1885 | static int rockchip_drm_sys_resume(struct device *dev) |
---|
2219 | 1886 | { |
---|
2220 | 1887 | struct drm_device *drm = dev_get_drvdata(dev); |
---|
2221 | | - struct rockchip_drm_private *priv; |
---|
2222 | 1888 | |
---|
2223 | | - if (!drm) |
---|
2224 | | - return 0; |
---|
2225 | | - |
---|
2226 | | - priv = drm->dev_private; |
---|
2227 | | - drm_atomic_helper_resume(drm, priv->state); |
---|
2228 | | - rockchip_drm_fb_resume(drm); |
---|
2229 | | - drm_kms_helper_poll_enable(drm); |
---|
2230 | | - |
---|
2231 | | - return 0; |
---|
| 1889 | + return drm_mode_config_helper_resume(drm); |
---|
2232 | 1890 | } |
---|
2233 | 1891 | #endif |
---|
2234 | 1892 | |
---|
.. | .. |
---|
2240 | 1898 | #define MAX_ROCKCHIP_SUB_DRIVERS 16 |
---|
2241 | 1899 | static struct platform_driver *rockchip_sub_drivers[MAX_ROCKCHIP_SUB_DRIVERS]; |
---|
2242 | 1900 | static int num_rockchip_sub_drivers; |
---|
| 1901 | + |
---|
| 1902 | +/* |
---|
| 1903 | + * Check if a vop endpoint is leading to a rockchip subdriver or bridge. |
---|
| 1904 | + * Should be called from the component bind stage of the drivers |
---|
| 1905 | + * to ensure that all subdrivers are probed. |
---|
| 1906 | + * |
---|
| 1907 | + * @ep: endpoint of a rockchip vop |
---|
| 1908 | + * |
---|
| 1909 | + * returns true if subdriver, false if external bridge and -ENODEV |
---|
| 1910 | + * if remote port does not contain a device. |
---|
| 1911 | + */ |
---|
| 1912 | +int rockchip_drm_endpoint_is_subdriver(struct device_node *ep) |
---|
| 1913 | +{ |
---|
| 1914 | + struct device_node *node = of_graph_get_remote_port_parent(ep); |
---|
| 1915 | + struct platform_device *pdev; |
---|
| 1916 | + struct device_driver *drv; |
---|
| 1917 | + int i; |
---|
| 1918 | + |
---|
| 1919 | + if (!node) |
---|
| 1920 | + return -ENODEV; |
---|
| 1921 | + |
---|
| 1922 | + /* status disabled will prevent creation of platform-devices */ |
---|
| 1923 | + pdev = of_find_device_by_node(node); |
---|
| 1924 | + of_node_put(node); |
---|
| 1925 | + if (!pdev) |
---|
| 1926 | + return -ENODEV; |
---|
| 1927 | + |
---|
| 1928 | + /* |
---|
| 1929 | + * All rockchip subdrivers have probed at this point, so |
---|
| 1930 | + * any device not having a driver now is an external bridge. |
---|
| 1931 | + */ |
---|
| 1932 | + drv = pdev->dev.driver; |
---|
| 1933 | + if (!drv) { |
---|
| 1934 | + platform_device_put(pdev); |
---|
| 1935 | + return false; |
---|
| 1936 | + } |
---|
| 1937 | + |
---|
| 1938 | + for (i = 0; i < num_rockchip_sub_drivers; i++) { |
---|
| 1939 | + if (rockchip_sub_drivers[i] == to_platform_driver(drv)) { |
---|
| 1940 | + platform_device_put(pdev); |
---|
| 1941 | + return true; |
---|
| 1942 | + } |
---|
| 1943 | + } |
---|
| 1944 | + |
---|
| 1945 | + platform_device_put(pdev); |
---|
| 1946 | + return false; |
---|
| 1947 | +} |
---|
2243 | 1948 | |
---|
2244 | 1949 | static int compare_dev(struct device *dev, void *data) |
---|
2245 | 1950 | { |
---|
.. | .. |
---|
2264 | 1969 | struct device *p = NULL, *d; |
---|
2265 | 1970 | |
---|
2266 | 1971 | do { |
---|
2267 | | - d = bus_find_device(&platform_bus_type, p, &drv->driver, |
---|
2268 | | - (void *)platform_bus_type.match); |
---|
| 1972 | + d = platform_find_device_by_driver(p, &drv->driver); |
---|
2269 | 1973 | put_device(p); |
---|
2270 | 1974 | p = d; |
---|
2271 | 1975 | |
---|
.. | .. |
---|
2311 | 2015 | } |
---|
2312 | 2016 | |
---|
2313 | 2017 | iommu = of_parse_phandle(port->parent, "iommus", 0); |
---|
2314 | | - if (!iommu || !of_device_is_available(iommu->parent)) { |
---|
| 2018 | + if (!iommu || !of_device_is_available(iommu)) { |
---|
2315 | 2019 | DRM_DEV_DEBUG(dev, |
---|
2316 | 2020 | "no iommu attached for %pOF, using non-iommu buffers\n", |
---|
2317 | 2021 | port->parent); |
---|
.. | .. |
---|
2323 | 2027 | } |
---|
2324 | 2028 | |
---|
2325 | 2029 | found = true; |
---|
2326 | | - iommu_reserve_map |= of_property_read_bool(iommu, "rockchip,reserve-map"); |
---|
2327 | 2030 | |
---|
| 2031 | + iommu_reserve_map |= of_property_read_bool(iommu, "rockchip,reserve-map"); |
---|
2328 | 2032 | of_node_put(iommu); |
---|
2329 | 2033 | of_node_put(port); |
---|
2330 | 2034 | } |
---|
.. | .. |
---|
2359 | 2063 | if (IS_ERR(match)) |
---|
2360 | 2064 | return PTR_ERR(match); |
---|
2361 | 2065 | |
---|
| 2066 | + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64)); |
---|
| 2067 | + if (ret) |
---|
| 2068 | + goto err; |
---|
| 2069 | + |
---|
2362 | 2070 | ret = component_master_add_with_match(dev, &rockchip_drm_ops, match); |
---|
2363 | | - if (ret < 0) { |
---|
2364 | | - rockchip_drm_match_remove(dev); |
---|
2365 | | - return ret; |
---|
2366 | | - } |
---|
2367 | | - dev->coherent_dma_mask = DMA_BIT_MASK(64); |
---|
| 2071 | + if (ret < 0) |
---|
| 2072 | + goto err; |
---|
2368 | 2073 | |
---|
2369 | 2074 | return 0; |
---|
| 2075 | +err: |
---|
| 2076 | + rockchip_drm_match_remove(dev); |
---|
| 2077 | + |
---|
| 2078 | + return ret; |
---|
2370 | 2079 | } |
---|
2371 | 2080 | |
---|
2372 | 2081 | static int rockchip_drm_platform_remove(struct platform_device *pdev) |
---|
.. | .. |
---|
2382 | 2091 | { |
---|
2383 | 2092 | struct drm_device *drm = platform_get_drvdata(pdev); |
---|
2384 | 2093 | |
---|
2385 | | - if (drm) { |
---|
2386 | | - drm_kms_helper_poll_fini(drm); |
---|
| 2094 | + if (drm) |
---|
2387 | 2095 | drm_atomic_helper_shutdown(drm); |
---|
2388 | | - } |
---|
2389 | 2096 | } |
---|
2390 | 2097 | |
---|
2391 | 2098 | static const struct of_device_id rockchip_drm_dt_ids[] = { |
---|
.. | .. |
---|
2421 | 2128 | #else |
---|
2422 | 2129 | ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP); |
---|
2423 | 2130 | ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2); |
---|
| 2131 | + ADD_ROCKCHIP_SUB_DRIVER(vconn_platform_driver, CONFIG_ROCKCHIP_VCONN); |
---|
2424 | 2132 | ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, |
---|
2425 | 2133 | CONFIG_ROCKCHIP_LVDS); |
---|
2426 | 2134 | ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, |
---|
.. | .. |
---|
2428 | 2136 | ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP); |
---|
2429 | 2137 | ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver, |
---|
2430 | 2138 | CONFIG_ROCKCHIP_DW_HDMI); |
---|
2431 | | - ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_driver, |
---|
| 2139 | + ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver, |
---|
| 2140 | + CONFIG_ROCKCHIP_DW_MIPI_DSI); |
---|
| 2141 | + ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi2_rockchip_driver, |
---|
2432 | 2142 | CONFIG_ROCKCHIP_DW_MIPI_DSI); |
---|
2433 | 2143 | ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI); |
---|
2434 | | - ADD_ROCKCHIP_SUB_DRIVER(rockchip_tve_driver, |
---|
2435 | | - CONFIG_ROCKCHIP_DRM_TVE); |
---|
| 2144 | + ADD_ROCKCHIP_SUB_DRIVER(rk3066_hdmi_driver, |
---|
| 2145 | + CONFIG_ROCKCHIP_RK3066_HDMI); |
---|
2436 | 2146 | ADD_ROCKCHIP_SUB_DRIVER(rockchip_rgb_driver, CONFIG_ROCKCHIP_RGB); |
---|
| 2147 | + ADD_ROCKCHIP_SUB_DRIVER(rockchip_tve_driver, CONFIG_ROCKCHIP_DRM_TVE); |
---|
| 2148 | + ADD_ROCKCHIP_SUB_DRIVER(dw_dp_driver, CONFIG_ROCKCHIP_DW_DP); |
---|
| 2149 | + |
---|
2437 | 2150 | #endif |
---|
2438 | 2151 | ret = platform_register_drivers(rockchip_sub_drivers, |
---|
2439 | 2152 | num_rockchip_sub_drivers); |
---|
.. | .. |
---|
2443 | 2156 | ret = platform_driver_register(&rockchip_drm_platform_driver); |
---|
2444 | 2157 | if (ret) |
---|
2445 | 2158 | goto err_unreg_drivers; |
---|
| 2159 | + |
---|
| 2160 | + rockchip_gem_get_ddr_info(); |
---|
2446 | 2161 | |
---|
2447 | 2162 | return 0; |
---|
2448 | 2163 | |
---|
.. | .. |
---|
2460 | 2175 | num_rockchip_sub_drivers); |
---|
2461 | 2176 | } |
---|
2462 | 2177 | |
---|
| 2178 | +#ifdef CONFIG_VIDEO_REVERSE_IMAGE |
---|
| 2179 | +fs_initcall(rockchip_drm_init); |
---|
| 2180 | +#else |
---|
2463 | 2181 | module_init(rockchip_drm_init); |
---|
| 2182 | +#endif |
---|
2464 | 2183 | module_exit(rockchip_drm_fini); |
---|
2465 | 2184 | |
---|
2466 | 2185 | MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>"); |
---|