| 1 | |
| 2 | #include <linux/component.h>
|
| 3 | #include <linux/export.h>
|
| 4 | #include <linux/list.h>
|
| 5 | #include <linux/media-bus-format.h>
|
| 6 | #include <linux/of.h>
|
| 7 | #include <linux/of_graph.h>
|
| 8 |
|
| 9 | #include <drm/drm_bridge.h>
|
| 10 | #include <drm/drm_connector.h>
|
| 11 | #include <drm/drm_crtc.h>
|
| 12 | #include <drm/drm_device.h>
|
| 13 | #include <drm/drm_encoder.h>
|
| 14 | #include <drm/drm_mipi_dsi.h>
|
| 15 | #include <drm/drm_of.h>
|
| 16 | #include <drm/drm_panel.h>
|
| 17 |
|
| 18 | |
| 19 | * DOC: overview
|
| 20 | *
|
| 21 | * A set of helper functions to aid DRM drivers in parsing standard DT
|
| 22 | * properties.
|
| 23 |
|
| 24 |
|
| 25 | |
| 26 | * drm_of_crtc_port_mask - find the mask of a registered CRTC by port OF node
|
| 27 | * @dev: DRM device
|
| 28 | * @port: port OF node
|
| 29 | *
|
| 30 | * Given a port OF node, return the possible mask of the corresponding
|
| 31 | * CRTC within a device's list of CRTCs. Returns zero if not found.
|
| 32 |
|
| 33 | uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
|
| 34 | struct device_node *port)
|
| 35 | {
|
| 36 | unsigned int index = 0;
|
| 37 | struct drm_crtc *tmp;
|
| 38 |
|
| 39 | drm_for_each_crtc(tmp, dev) {
|
| 40 | if (tmp->port == port)
|
| 41 | return 1 << index;
|
| 42 |
|
| 43 | index++;
|
| 44 | }
|
| 45 |
|
| 46 | return 0;
|
| 47 | }
|
| 48 | EXPORT_SYMBOL(drm_of_crtc_port_mask);
|
| 49 |
|
| 50 | |
| 51 | * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port
|
| 52 | * @dev: DRM device
|
| 53 | * @port: encoder port to scan for endpoints
|
| 54 | *
|
| 55 | * Scan all endpoints attached to a port, locate their attached CRTCs,
|
| 56 | * and generate the DRM mask of CRTCs which may be attached to this
|
| 57 | * encoder.
|
| 58 | *
|
| 59 | * See https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/graph.yaml
|
| 60 | * for the bindings.
|
| 61 |
|
| 62 | uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
| 63 | struct device_node *port)
|
| 64 | {
|
| 65 | struct device_node *remote_port, *ep;
|
| 66 | uint32_t possible_crtcs = 0;
|
| 67 |
|
| 68 | for_each_endpoint_of_node(port, ep) {
|
| 69 | remote_port = of_graph_get_remote_port(ep);
|
| 70 | if (!remote_port) {
|
| 71 | of_node_put(ep);
|
| 72 | return 0;
|
| 73 | }
|
| 74 |
|
| 75 | possible_crtcs |= drm_of_crtc_port_mask(dev, remote_port);
|
| 76 |
|
| 77 | of_node_put(remote_port);
|
| 78 | }
|
| 79 |
|
| 80 | return possible_crtcs;
|
| 81 | }
|
| 82 | EXPORT_SYMBOL(drm_of_find_possible_crtcs);
|
| 83 |
|
| 84 | |
| 85 | * drm_of_component_match_add - Add a component helper OF node match rule
|
| 86 | * @master: master device
|
| 87 | * @matchptr: component match pointer
|
| 88 | * @compare: compare function used for matching component
|
| 89 | * @node: of_node
|
| 90 |
|
| 91 | void drm_of_component_match_add(struct device *master,
|
| 92 | struct component_match **matchptr,
|
| 93 | int (*compare)(struct device *, void *),
|
| 94 | struct device_node *node)
|
| 95 | {
|
| 96 | of_node_get(node);
|
| 97 | component_match_add_release(master, matchptr, component_release_of,
|
| 98 | compare, node);
|
| 99 | }
|
| 100 | EXPORT_SYMBOL_GPL(drm_of_component_match_add);
|
| 101 |
|
| 102 | |
| 103 | * drm_of_component_probe - Generic probe function for a component based master
|
| 104 | * @dev: master device containing the OF node
|
| 105 | * @compare_of: compare function used for matching components
|
| 106 | * @m_ops: component master ops to be used
|
| 107 | *
|
| 108 | * Parse the platform device OF node and bind all the components associated
|
| 109 | * with the master. Interface ports are added before the encoders in order to
|
| 110 | * satisfy their .bind requirements
|
| 111 | *
|
| 112 | * See https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/graph.yaml
|
| 113 | * for the bindings.
|
| 114 | *
|
| 115 | * Returns zero if successful, or one of the standard error codes if it fails.
|
| 116 |
|
| 117 | int drm_of_component_probe(struct device *dev,
|
| 118 | int (*compare_of)(struct device *, void *),
|
| 119 | const struct component_master_ops *m_ops)
|
| 120 | {
|
| 121 | struct device_node *ep, *port, *remote;
|
| 122 | struct component_match *match = NULL;
|
| 123 | int i;
|
| 124 |
|
| 125 | if (!dev->of_node)
|
| 126 | return -EINVAL;
|
| 127 |
|
| 128 | |
| 129 | * Bind the crtc's ports first, so that drm_of_find_possible_crtcs()
|
| 130 | * called from encoder's .bind callbacks works as expected
|
| 131 |
|
| 132 | for (i = 0; ; i++) {
|
| 133 | port = of_parse_phandle(dev->of_node, "ports", i);
|
| 134 | if (!port)
|
| 135 | break;
|
| 136 |
|
| 137 | if (of_device_is_available(port->parent))
|
| 138 | drm_of_component_match_add(dev, &match, compare_of,
|
| 139 | port);
|
| 140 |
|
| 141 | of_node_put(port);
|
| 142 | }
|
| 143 |
|
| 144 | if (i == 0) {
|
| 145 | dev_err(dev, "missing 'ports' property\n");
|
| 146 | return -ENODEV;
|
| 147 | }
|
| 148 |
|
| 149 | if (!match) {
|
| 150 | dev_err(dev, "no available port\n");
|
| 151 | return -ENODEV;
|
| 152 | }
|
| 153 |
|
| 154 | |
| 155 | * For bound crtcs, bind the encoders attached to their remote endpoint
|
| 156 |
|
| 157 | for (i = 0; ; i++) {
|
| 158 | port = of_parse_phandle(dev->of_node, "ports", i);
|
| 159 | if (!port)
|
| 160 | break;
|
| 161 |
|
| 162 | if (!of_device_is_available(port->parent)) {
|
| 163 | of_node_put(port);
|
| 164 | continue;
|
| 165 | }
|
| 166 |
|
| 167 | for_each_child_of_node(port, ep) {
|
| 168 | remote = of_graph_get_remote_port_parent(ep);
|
| 169 | if (!remote || !of_device_is_available(remote)) {
|
| 170 | of_node_put(remote);
|
| 171 | continue;
|
| 172 | } else if (!of_device_is_available(remote->parent)) {
|
| 173 | dev_warn(dev, "parent device of %pOF is not available\n",
|
| 174 | remote);
|
| 175 | of_node_put(remote);
|
| 176 | continue;
|
| 177 | }
|
| 178 |
|
| 179 | drm_of_component_match_add(dev, &match, compare_of,
|
| 180 | remote);
|
| 181 | of_node_put(remote);
|
| 182 | }
|
| 183 | of_node_put(port);
|
| 184 | }
|
| 185 |
|
| 186 | return component_master_add_with_match(dev, m_ops, match);
|
| 187 | }
|
| 188 | EXPORT_SYMBOL(drm_of_component_probe);
|
| 189 |
|
| 190 | |
| 191 | * drm_of_encoder_active_endpoint - return the active encoder endpoint
|
| 192 | * @node: device tree node containing encoder input ports
|
| 193 | * @encoder: drm_encoder
|
| 194 | *
|
| 195 | * Given an encoder device node and a drm_encoder with a connected crtc,
|
| 196 | * parse the encoder endpoint connecting to the crtc port.
|
| 197 |
|
| 198 | int drm_of_encoder_active_endpoint(struct device_node *node,
|
| 199 | struct drm_encoder *encoder,
|
| 200 | struct of_endpoint *endpoint)
|
| 201 | {
|
| 202 | struct device_node *ep;
|
| 203 | struct drm_crtc *crtc = encoder->crtc;
|
| 204 | struct device_node *port;
|
| 205 | int ret;
|
| 206 |
|
| 207 | if (!node || !crtc)
|
| 208 | return -EINVAL;
|
| 209 |
|
| 210 | for_each_endpoint_of_node(node, ep) {
|
| 211 | port = of_graph_get_remote_port(ep);
|
| 212 | of_node_put(port);
|
| 213 | if (port == crtc->port) {
|
| 214 | ret = of_graph_parse_endpoint(ep, endpoint);
|
| 215 | of_node_put(ep);
|
| 216 | return ret;
|
| 217 | }
|
| 218 | }
|
| 219 |
|
| 220 | return -EINVAL;
|
| 221 | }
|
| 222 | EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
|
| 223 |
|
| 224 | |
| 225 | * drm_of_get_panel_orientation - look up the orientation of the panel through
|
| 226 | * the "rotation" binding from a device tree node
|
| 227 | * @np: device tree node of the panel
|
| 228 | * @orientation: orientation enum to be filled in
|
| 229 | *
|
| 230 | * Looks up the rotation of a panel in the device tree. The orientation of the
|
| 231 | * panel is expressed as a property name "rotation" in the device tree. The
|
| 232 | * rotation in the device tree is counter clockwise.
|
| 233 | *
|
| 234 | * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the
|
| 235 | * rotation property doesn't exist. Return a negative error code on failure.
|
| 236 |
|
| 237 | int drm_of_get_panel_orientation(const struct device_node *np,
|
| 238 | enum drm_panel_orientation *orientation)
|
| 239 | {
|
| 240 | int rotation, ret;
|
| 241 |
|
| 242 | ret = of_property_read_u32(np, "rotation", &rotation);
|
| 243 | if (ret == -EINVAL) {
|
| 244 |
|
| 245 | *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
| 246 | return 0;
|
| 247 | }
|
| 248 |
|
| 249 | if (ret < 0)
|
| 250 | return ret;
|
| 251 |
|
| 252 | if (rotation == 0)
|
| 253 | *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
| 254 | else if (rotation == 90)
|
| 255 | *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
|
| 256 | else if (rotation == 180)
|
| 257 | *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
|
| 258 | else if (rotation == 270)
|
| 259 | *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
|
| 260 | else
|
| 261 | return -EINVAL;
|
| 262 |
|
| 263 | return 0;
|
| 264 | }
|
| 265 | EXPORT_SYMBOL_GPL(drm_of_get_panel_orientation);
|
| 266 |
|
| 267 | |
| 268 | * drm_of_find_panel_or_bridge - return connected panel or bridge device
|
| 269 | * @np: device tree node containing encoder output ports
|
| 270 | * @port: port in the device tree node
|
| 271 | * @endpoint: endpoint in the device tree node
|
| 272 | * @panel: pointer to hold returned drm_panel, must not be NULL. On success
|
| 273 | * the caller must call drm_panel_put() when done with the panel
|
| 274 | * @bridge: pointer to hold returned drm_bridge
|
| 275 | *
|
| 276 | * Given a DT node's port and endpoint number, find the connected node and
|
| 277 | * return either the associated struct drm_panel or drm_bridge device.
|
| 278 | *
|
| 279 | * This function is deprecated and should not be used in new drivers. Use
|
| 280 | * of_drm_get_bridge_by_endpoint() instead when not looking for a panel, or
|
| 281 | * devm_drm_of_get_bridge() otherwise.
|
| 282 | *
|
| 283 | * Returns zero if successful, or one of the standard error codes if it fails.
|
| 284 |
|
| 285 | int drm_of_find_panel_or_bridge(const struct device_node *np,
|
| 286 | int port, int endpoint,
|
| 287 | struct drm_panel **panel,
|
| 288 | struct drm_bridge **bridge)
|
| 289 | {
|
| 290 | int ret = -EPROBE_DEFER;
|
| 291 | struct device_node *remote;
|
| 292 |
|
| 293 | if (WARN_ON(!panel))
|
| 294 | return -EINVAL;
|
| 295 |
|
| 296 | *panel = NULL;
|
| 297 |
|
| 298 | |
| 299 | * of_graph_get_remote_node() produces a noisy error message if port
|
| 300 | * node isn't found and the absence of the port is a legit case here,
|
| 301 | * so at first we silently check whether a graph is present in the
|
| 302 | * device-tree node.
|
| 303 |
|
| 304 | if (!of_graph_is_present(np))
|
| 305 | return -ENODEV;
|
| 306 |
|
| 307 | remote = of_graph_get_remote_node(np, port, endpoint);
|
| 308 | if (!remote)
|
| 309 | return -ENODEV;
|
| 310 |
|
| 311 | *panel = of_drm_find_panel(remote);
|
| 312 | if (!IS_ERR(*panel))
|
| 313 | ret = 0;
|
| 314 | else
|
| 315 | *panel = NULL;
|
| 316 |
|
| 317 | if (bridge) {
|
| 318 | if (ret) {
|
| 319 |
|
| 320 | *bridge = of_drm_find_bridge(remote);
|
| 321 | if (*bridge)
|
| 322 | ret = 0;
|
| 323 | } else {
|
| 324 | *bridge = NULL;
|
| 325 | }
|
| 326 |
|
| 327 | }
|
| 328 |
|
| 329 | of_node_put(remote);
|
| 330 | return ret;
|
| 331 | }
|
| 332 | EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge);
|
| 333 |
|
| 334 | enum drm_of_lvds_pixels {
|
| 335 | DRM_OF_LVDS_EVEN = BIT(0),
|
| 336 | DRM_OF_LVDS_ODD = BIT(1),
|
| 337 | };
|
| 338 |
|
| 339 | static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node)
|
| 340 | {
|
| 341 | bool even_pixels =
|
| 342 | of_property_read_bool(port_node, "dual-lvds-even-pixels");
|
| 343 | bool odd_pixels =
|
| 344 | of_property_read_bool(port_node, "dual-lvds-odd-pixels");
|
| 345 |
|
| 346 | return (even_pixels ? DRM_OF_LVDS_EVEN : 0) |
|
| 347 | (odd_pixels ? DRM_OF_LVDS_ODD : 0);
|
| 348 | }
|
| 349 |
|
| 350 | static int drm_of_lvds_get_remote_pixels_type(
|
| 351 | const struct device_node *port_node)
|
| 352 | {
|
| 353 | struct device_node *endpoint = NULL;
|
| 354 | int pixels_type = -EPIPE;
|
| 355 |
|
| 356 | for_each_child_of_node(port_node, endpoint) {
|
| 357 | struct device_node *remote_port;
|
| 358 | int current_pt;
|
| 359 |
|
| 360 | if (!of_node_name_eq(endpoint, "endpoint"))
|
| 361 | continue;
|
| 362 |
|
| 363 | remote_port = of_graph_get_remote_port(endpoint);
|
| 364 | if (!remote_port) {
|
| 365 | of_node_put(endpoint);
|
| 366 | return -EPIPE;
|
| 367 | }
|
| 368 |
|
| 369 | current_pt = drm_of_lvds_get_port_pixels_type(remote_port);
|
| 370 | of_node_put(remote_port);
|
| 371 | if (pixels_type < 0)
|
| 372 | pixels_type = current_pt;
|
| 373 |
|
| 374 | |
| 375 | * Sanity check, ensure that all remote endpoints have the same
|
| 376 | * pixel type. We may lift this restriction later if we need to
|
| 377 | * support multiple sinks with different dual-link
|
| 378 | * configurations by passing the endpoints explicitly to
|
| 379 | * drm_of_lvds_get_dual_link_pixel_order().
|
| 380 |
|
| 381 | if (!current_pt || pixels_type != current_pt) {
|
| 382 | of_node_put(endpoint);
|
| 383 | return -EINVAL;
|
| 384 | }
|
| 385 | }
|
| 386 |
|
| 387 | return pixels_type;
|
| 388 | }
|
| 389 |
|
| 390 | static int __drm_of_lvds_get_dual_link_pixel_order(int p1_pt, int p2_pt)
|
| 391 | {
|
| 392 | |
| 393 | * A valid dual-lVDS bus is found when one port is marked with
|
| 394 | * "dual-lvds-even-pixels", and the other port is marked with
|
| 395 | * "dual-lvds-odd-pixels", bail out if the markers are not right.
|
| 396 |
|
| 397 | if (p1_pt + p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
|
| 398 | return -EINVAL;
|
| 399 |
|
| 400 | return p1_pt == DRM_OF_LVDS_EVEN ?
|
| 401 | DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS :
|
| 402 | DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
|
| 403 | }
|
| 404 |
|
| 405 | |
| 406 | * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link source pixel order
|
| 407 | * @port1: First DT port node of the Dual-link LVDS source
|
| 408 | * @port2: Second DT port node of the Dual-link LVDS source
|
| 409 | *
|
| 410 | * An LVDS dual-link connection is made of two links, with even pixels
|
| 411 | * transitting on one link, and odd pixels on the other link. This function
|
| 412 | * returns, for two ports of an LVDS dual-link source, which port shall transmit
|
| 413 | * the even and odd pixels, based on the requirements of the connected sink.
|
| 414 | *
|
| 415 | * The pixel order is determined from the dual-lvds-even-pixels and
|
| 416 | * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those
|
| 417 | * properties are not present, or if their usage is not valid, this function
|
| 418 | * returns -EINVAL.
|
| 419 | *
|
| 420 | * If either port is not connected, this function returns -EPIPE.
|
| 421 | *
|
| 422 | * @port1 and @port2 are typically DT sibling nodes, but may have different
|
| 423 | * parents when, for instance, two separate LVDS encoders carry the even and odd
|
| 424 | * pixels.
|
| 425 | *
|
| 426 | * Return:
|
| 427 | * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries even pixels and @port2
|
| 428 | * carries odd pixels
|
| 429 | * * DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS - @port1 carries odd pixels and @port2
|
| 430 | * carries even pixels
|
| 431 | * * -EINVAL - @port1 and @port2 are not connected to a dual-link LVDS sink, or
|
| 432 | * the sink configuration is invalid
|
| 433 | * * -EPIPE - when @port1 or @port2 are not connected
|
| 434 |
|
| 435 | int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
|
| 436 | const struct device_node *port2)
|
| 437 | {
|
| 438 | int remote_p1_pt, remote_p2_pt;
|
| 439 |
|
| 440 | if (!port1 || !port2)
|
| 441 | return -EINVAL;
|
| 442 |
|
| 443 | remote_p1_pt = drm_of_lvds_get_remote_pixels_type(port1);
|
| 444 | if (remote_p1_pt < 0)
|
| 445 | return remote_p1_pt;
|
| 446 |
|
| 447 | remote_p2_pt = drm_of_lvds_get_remote_pixels_type(port2);
|
| 448 | if (remote_p2_pt < 0)
|
| 449 | return remote_p2_pt;
|
| 450 |
|
| 451 | return __drm_of_lvds_get_dual_link_pixel_order(remote_p1_pt, remote_p2_pt);
|
| 452 | }
|
| 453 | EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order);
|
| 454 |
|
| 455 | |
| 456 | * drm_of_lvds_get_dual_link_pixel_order_sink - Get LVDS dual-link sink pixel order
|
| 457 | * @port1: First DT port node of the Dual-link LVDS sink
|
| 458 | * @port2: Second DT port node of the Dual-link LVDS sink
|
| 459 | *
|
| 460 | * An LVDS dual-link connection is made of two links, with even pixels
|
| 461 | * transitting on one link, and odd pixels on the other link. This function
|
| 462 | * returns, for two ports of an LVDS dual-link sink, which port shall transmit
|
| 463 | * the even and odd pixels, based on the requirements of the sink.
|
| 464 | *
|
| 465 | * The pixel order is determined from the dual-lvds-even-pixels and
|
| 466 | * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those
|
| 467 | * properties are not present, or if their usage is not valid, this function
|
| 468 | * returns -EINVAL.
|
| 469 | *
|
| 470 | * If either port is not connected, this function returns -EPIPE.
|
| 471 | *
|
| 472 | * @port1 and @port2 are typically DT sibling nodes, but may have different
|
| 473 | * parents when, for instance, two separate LVDS decoders receive the even and
|
| 474 | * odd pixels.
|
| 475 | *
|
| 476 | * Return:
|
| 477 | * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 receives even pixels and @port2
|
| 478 | * receives odd pixels
|
| 479 | * * DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS - @port1 receives odd pixels and @port2
|
| 480 | * receives even pixels
|
| 481 | * * -EINVAL - @port1 or @port2 are NULL
|
| 482 | * * -EPIPE - when @port1 or @port2 are not connected
|
| 483 |
|
| 484 | int drm_of_lvds_get_dual_link_pixel_order_sink(struct device_node *port1,
|
| 485 | struct device_node *port2)
|
| 486 | {
|
| 487 | int sink_p1_pt, sink_p2_pt;
|
| 488 |
|
| 489 | if (!port1 || !port2)
|
| 490 | return -EINVAL;
|
| 491 |
|
| 492 | sink_p1_pt = drm_of_lvds_get_port_pixels_type(port1);
|
| 493 | if (!sink_p1_pt)
|
| 494 | return -EPIPE;
|
| 495 |
|
| 496 | sink_p2_pt = drm_of_lvds_get_port_pixels_type(port2);
|
| 497 | if (!sink_p2_pt)
|
| 498 | return -EPIPE;
|
| 499 |
|
| 500 | return __drm_of_lvds_get_dual_link_pixel_order(sink_p1_pt, sink_p2_pt);
|
| 501 | }
|
| 502 | EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order_sink);
|
| 503 |
|
| 504 | |
| 505 | * drm_of_lvds_get_data_mapping - Get LVDS data mapping
|
| 506 | * @port: DT port node of the LVDS source or sink
|
| 507 | *
|
| 508 | * Convert DT "data-mapping" property string value into media bus format value.
|
| 509 | *
|
| 510 | * Return:
|
| 511 | * * MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - data-mapping is "jeida-18"
|
| 512 | * * MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA - data-mapping is "jeida-24"
|
| 513 | * * MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA - data-mapping is "jeida-30"
|
| 514 | * * MEDIA_BUS_FMT_RGB888_1X7X4_SPWG - data-mapping is "vesa-24"
|
| 515 | * * MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG - data-mapping is "vesa-30"
|
| 516 | * * -EINVAL - the "data-mapping" property is unsupported
|
| 517 | * * -ENODEV - the "data-mapping" property is missing
|
| 518 |
|
| 519 | int drm_of_lvds_get_data_mapping(const struct device_node *port)
|
| 520 | {
|
| 521 | const char *mapping;
|
| 522 | int ret;
|
| 523 |
|
| 524 | ret = of_property_read_string(port, "data-mapping", &mapping);
|
| 525 | if (ret < 0)
|
| 526 | return -ENODEV;
|
| 527 |
|
| 528 | if (!strcmp(mapping, "jeida-18"))
|
| 529 | return MEDIA_BUS_FMT_RGB666_1X7X3_SPWG;
|
| 530 | if (!strcmp(mapping, "jeida-24"))
|
| 531 | return MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
|
| 532 | if (!strcmp(mapping, "jeida-30"))
|
| 533 | return MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA;
|
| 534 | if (!strcmp(mapping, "vesa-24"))
|
| 535 | return MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;
|
| 536 | if (!strcmp(mapping, "vesa-30"))
|
| 537 | return MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG;
|
| 538 |
|
| 539 | return -EINVAL;
|
| 540 | }
|
| 541 | EXPORT_SYMBOL_GPL(drm_of_lvds_get_data_mapping);
|
| 542 |
|
| 543 | |
| 544 | * drm_of_get_data_lanes_count - Get DSI/(e)DP data lane count
|
| 545 | * @endpoint: DT endpoint node of the DSI/(e)DP source or sink
|
| 546 | * @min: minimum supported number of data lanes
|
| 547 | * @max: maximum supported number of data lanes
|
| 548 | *
|
| 549 | * Count DT "data-lanes" property elements and check for validity.
|
| 550 | *
|
| 551 | * Return:
|
| 552 | * * min..max - positive integer count of "data-lanes" elements
|
| 553 | * * -ve - the "data-lanes" property is missing or invalid
|
| 554 | * * -EINVAL - the "data-lanes" property is unsupported
|
| 555 |
|
| 556 | int drm_of_get_data_lanes_count(const struct device_node *endpoint,
|
| 557 | const unsigned int min, const unsigned int max)
|
| 558 | {
|
| 559 | int ret;
|
| 560 |
|
| 561 | ret = of_property_count_u32_elems(endpoint, "data-lanes");
|
| 562 | if (ret < 0)
|
| 563 | return ret;
|
| 564 |
|
| 565 | if (ret < min || ret > max)
|
| 566 | return -EINVAL;
|
| 567 |
|
| 568 | return ret;
|
| 569 | }
|
| 570 | EXPORT_SYMBOL_GPL(drm_of_get_data_lanes_count);
|
| 571 |
|
| 572 | |
| 573 | * drm_of_get_data_lanes_count_ep - Get DSI/(e)DP data lane count by endpoint
|
| 574 | * @port: DT port node of the DSI/(e)DP source or sink
|
| 575 | * @port_reg: identifier (value of reg property) of the parent port node
|
| 576 | * @reg: identifier (value of reg property) of the endpoint node
|
| 577 | * @min: minimum supported number of data lanes
|
| 578 | * @max: maximum supported number of data lanes
|
| 579 | *
|
| 580 | * Count DT "data-lanes" property elements and check for validity.
|
| 581 | * This variant uses endpoint specifier.
|
| 582 | *
|
| 583 | * Return:
|
| 584 | * * min..max - positive integer count of "data-lanes" elements
|
| 585 | * * -EINVAL - the "data-mapping" property is unsupported
|
| 586 | * * -ENODEV - the "data-mapping" property is missing
|
| 587 |
|
| 588 | int drm_of_get_data_lanes_count_ep(const struct device_node *port,
|
| 589 | int port_reg, int reg,
|
| 590 | const unsigned int min,
|
| 591 | const unsigned int max)
|
| 592 | {
|
| 593 | struct device_node *endpoint;
|
| 594 | int ret;
|
| 595 |
|
| 596 | endpoint = of_graph_get_endpoint_by_regs(port, port_reg, reg);
|
| 597 | ret = drm_of_get_data_lanes_count(endpoint, min, max);
|
| 598 | of_node_put(endpoint);
|
| 599 |
|
| 600 | return ret;
|
| 601 | }
|
| 602 | EXPORT_SYMBOL_GPL(drm_of_get_data_lanes_count_ep);
|
| 603 |
|
| 604 | |
| 605 | * drm_of_get_data_lanes_count_remote - Get DSI/(e)DP data lane count by endpoint
|
| 606 | * @port: DT port node of the DSI/(e)DP source or sink
|
| 607 | * @port_reg: identifier (value of reg property) of the parent port node
|
| 608 | * @reg: identifier (value of reg property) of the endpoint node
|
| 609 | * @min: minimum supported number of data lanes
|
| 610 | * @max: maximum supported number of data lanes
|
| 611 | *
|
| 612 | * Count DT "data-lanes" property elements in the remote endpoint and check for
|
| 613 | * validity. This variant uses endpoint specifier.
|
| 614 | *
|
| 615 | * Return:
|
| 616 | * * min..max - positive integer count of "data-lanes" elements
|
| 617 | * * -EINVAL - the "data-lanes" property is unsupported
|
| 618 | * * -ENODEV - the "data-lanes" property is missing
|
| 619 |
|
| 620 | int drm_of_get_data_lanes_count_remote(const struct device_node *port,
|
| 621 | int port_reg, int reg,
|
| 622 | const unsigned int min,
|
| 623 | const unsigned int max)
|
| 624 | {
|
| 625 | struct device_node *endpoint, *remote;
|
| 626 | int ret;
|
| 627 |
|
| 628 | endpoint = of_graph_get_endpoint_by_regs(port, port_reg, reg);
|
| 629 | remote = of_graph_get_remote_endpoint(endpoint);
|
| 630 | of_node_put(endpoint);
|
| 631 | ret = drm_of_get_data_lanes_count(remote, min, max);
|
| 632 | of_node_put(remote);
|
| 633 |
|
| 634 | return ret;
|
| 635 | }
|
| 636 | EXPORT_SYMBOL_GPL(drm_of_get_data_lanes_count_remote);
|
| 637 |
|
| 638 | #if IS_ENABLED(CONFIG_DRM_MIPI_DSI)
|
| 639 |
|
| 640 | |
| 641 | * drm_of_get_dsi_bus - find the DSI bus for a given device
|
| 642 | * @dev: parent device of display (SPI, I2C)
|
| 643 | *
|
| 644 | * Gets parent DSI bus for a DSI device controlled through a bus other
|
| 645 | * than MIPI-DCS (SPI, I2C, etc.) using the Device Tree.
|
| 646 | *
|
| 647 | * This function assumes that the device's port@0 is the DSI input.
|
| 648 | *
|
| 649 | * Returns pointer to mipi_dsi_host if successful, -EINVAL if the
|
| 650 | * request is unsupported, -EPROBE_DEFER if the DSI host is found but
|
| 651 | * not available, or -ENODEV otherwise.
|
| 652 |
|
| 653 | struct mipi_dsi_host *drm_of_get_dsi_bus(struct device *dev)
|
| 654 | {
|
| 655 | struct mipi_dsi_host *dsi_host;
|
| 656 | struct device_node *endpoint, *dsi_host_node;
|
| 657 |
|
| 658 | |
| 659 | * Get first endpoint child from device.
|
| 660 |
|
| 661 | endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
|
| 662 | if (!endpoint)
|
| 663 | return ERR_PTR(-ENODEV);
|
| 664 |
|
| 665 | |
| 666 | * Follow the first endpoint to get the DSI host node and then
|
| 667 | * release the endpoint since we no longer need it.
|
| 668 |
|
| 669 | dsi_host_node = of_graph_get_remote_port_parent(endpoint);
|
| 670 | of_node_put(endpoint);
|
| 671 | if (!dsi_host_node)
|
| 672 | return ERR_PTR(-ENODEV);
|
| 673 |
|
| 674 | |
| 675 | * Get the DSI host from the DSI host node. If we get an error
|
| 676 | * or the return is null assume we're not ready to probe just
|
| 677 | * yet. Release the DSI host node since we're done with it.
|
| 678 |
|
| 679 | dsi_host = of_find_mipi_dsi_host_by_node(dsi_host_node);
|
| 680 | of_node_put(dsi_host_node);
|
| 681 | if (IS_ERR_OR_NULL(dsi_host))
|
| 682 | return ERR_PTR(-EPROBE_DEFER);
|
| 683 |
|
| 684 | return dsi_host;
|
| 685 | }
|
| 686 | EXPORT_SYMBOL_GPL(drm_of_get_dsi_bus);
|
| 687 |
|
| 688 | #endif
|