| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | #include <linux/component.h> |
|---|
| 2 | 3 | #include <linux/export.h> |
|---|
| 3 | 4 | #include <linux/list.h> |
|---|
| 4 | 5 | #include <linux/of_graph.h> |
|---|
| 5 | | -#include <drm/drmP.h> |
|---|
| 6 | + |
|---|
| 6 | 7 | #include <drm/drm_bridge.h> |
|---|
| 7 | 8 | #include <drm/drm_crtc.h> |
|---|
| 9 | +#include <drm/drm_device.h> |
|---|
| 8 | 10 | #include <drm/drm_encoder.h> |
|---|
| 9 | | -#include <drm/drm_panel.h> |
|---|
| 10 | 11 | #include <drm/drm_of.h> |
|---|
| 12 | +#include <drm/drm_panel.h> |
|---|
| 11 | 13 | |
|---|
| 12 | 14 | /** |
|---|
| 13 | 15 | * DOC: overview |
|---|
| .. | .. |
|---|
| 64 | 66 | uint32_t possible_crtcs = 0; |
|---|
| 65 | 67 | |
|---|
| 66 | 68 | for_each_endpoint_of_node(port, ep) { |
|---|
| 67 | | - if (!of_device_is_available(ep)) { |
|---|
| 68 | | - of_node_put(ep); |
|---|
| 69 | | - continue; |
|---|
| 70 | | - } |
|---|
| 71 | | - |
|---|
| 72 | 69 | remote_port = of_graph_get_remote_port(ep); |
|---|
| 73 | 70 | if (!remote_port) { |
|---|
| 74 | 71 | of_node_put(ep); |
|---|
| .. | .. |
|---|
| 222 | 219 | } |
|---|
| 223 | 220 | EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); |
|---|
| 224 | 221 | |
|---|
| 225 | | -/* |
|---|
| 222 | +/** |
|---|
| 226 | 223 | * drm_of_find_panel_or_bridge - return connected panel or bridge device |
|---|
| 227 | 224 | * @np: device tree node containing encoder output ports |
|---|
| 225 | + * @port: port in the device tree node |
|---|
| 226 | + * @endpoint: endpoint in the device tree node |
|---|
| 228 | 227 | * @panel: pointer to hold returned drm_panel |
|---|
| 229 | 228 | * @bridge: pointer to hold returned drm_bridge |
|---|
| 230 | 229 | * |
|---|
| .. | .. |
|---|
| 247 | 246 | if (panel) |
|---|
| 248 | 247 | *panel = NULL; |
|---|
| 249 | 248 | |
|---|
| 249 | + /* |
|---|
| 250 | + * of_graph_get_remote_node() produces a noisy error message if port |
|---|
| 251 | + * node isn't found and the absence of the port is a legit case here, |
|---|
| 252 | + * so at first we silently check whether graph presents in the |
|---|
| 253 | + * device-tree node. |
|---|
| 254 | + */ |
|---|
| 255 | + if (!of_graph_is_present(np)) |
|---|
| 256 | + return -ENODEV; |
|---|
| 257 | + |
|---|
| 250 | 258 | remote = of_graph_get_remote_node(np, port, endpoint); |
|---|
| 251 | 259 | if (!remote) |
|---|
| 252 | 260 | return -ENODEV; |
|---|
| 253 | | - |
|---|
| 254 | | - if (!of_device_is_available(remote)) { |
|---|
| 255 | | - of_node_put(remote); |
|---|
| 256 | | - return -ENODEV; |
|---|
| 257 | | - } |
|---|
| 258 | 261 | |
|---|
| 259 | 262 | if (panel) { |
|---|
| 260 | 263 | *panel = of_drm_find_panel(remote); |
|---|
| .. | .. |
|---|
| 284 | 287 | enum drm_of_lvds_pixels { |
|---|
| 285 | 288 | DRM_OF_LVDS_EVEN = BIT(0), |
|---|
| 286 | 289 | DRM_OF_LVDS_ODD = BIT(1), |
|---|
| 287 | | - DRM_OF_LVDS_LEFT = BIT(2), |
|---|
| 288 | | - DRM_OF_LVDS_RIGHT = BIT(3), |
|---|
| 289 | 290 | }; |
|---|
| 290 | 291 | |
|---|
| 291 | 292 | static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node) |
|---|
| .. | .. |
|---|
| 294 | 295 | of_property_read_bool(port_node, "dual-lvds-even-pixels"); |
|---|
| 295 | 296 | bool odd_pixels = |
|---|
| 296 | 297 | of_property_read_bool(port_node, "dual-lvds-odd-pixels"); |
|---|
| 297 | | - bool left_pixels = |
|---|
| 298 | | - of_property_read_bool(port_node, "dual-lvds-left-pixels"); |
|---|
| 299 | | - bool right_pixels = |
|---|
| 300 | | - of_property_read_bool(port_node, "dual-lvds-right-pixels"); |
|---|
| 301 | 298 | |
|---|
| 302 | 299 | return (even_pixels ? DRM_OF_LVDS_EVEN : 0) | |
|---|
| 303 | | - (odd_pixels ? DRM_OF_LVDS_ODD : 0) | |
|---|
| 304 | | - (left_pixels ? DRM_OF_LVDS_LEFT : 0) | |
|---|
| 305 | | - (right_pixels ? DRM_OF_LVDS_RIGHT : 0); |
|---|
| 300 | + (odd_pixels ? DRM_OF_LVDS_ODD : 0); |
|---|
| 306 | 301 | } |
|---|
| 307 | 302 | |
|---|
| 308 | 303 | static int drm_of_lvds_get_remote_pixels_type( |
|---|
| .. | .. |
|---|
| 320 | 315 | |
|---|
| 321 | 316 | remote_port = of_graph_get_remote_port(endpoint); |
|---|
| 322 | 317 | if (!remote_port) { |
|---|
| 323 | | - of_node_put(remote_port); |
|---|
| 318 | + of_node_put(endpoint); |
|---|
| 324 | 319 | return -EPIPE; |
|---|
| 325 | 320 | } |
|---|
| 326 | 321 | |
|---|
| .. | .. |
|---|
| 336 | 331 | * configurations by passing the endpoints explicitly to |
|---|
| 337 | 332 | * drm_of_lvds_get_dual_link_pixel_order(). |
|---|
| 338 | 333 | */ |
|---|
| 339 | | - if (!current_pt || pixels_type != current_pt) |
|---|
| 334 | + if (!current_pt || pixels_type != current_pt) { |
|---|
| 335 | + of_node_put(endpoint); |
|---|
| 340 | 336 | return -EINVAL; |
|---|
| 337 | + } |
|---|
| 341 | 338 | } |
|---|
| 342 | 339 | |
|---|
| 343 | 340 | return pixels_type; |
|---|
| .. | .. |
|---|
| 348 | 345 | * @port1: First DT port node of the Dual-link LVDS source |
|---|
| 349 | 346 | * @port2: Second DT port node of the Dual-link LVDS source |
|---|
| 350 | 347 | * |
|---|
| 351 | | - * An LVDS dual-link connection is made of two links, the two link can transmit |
|---|
| 352 | | - * odd pixels and even pixels independently, or the two link can also transmit |
|---|
| 353 | | - * left pixels and right pixels independently. This function returns for two |
|---|
| 354 | | - * ports of an LVDS dual-link source, based on the requirements of the connected |
|---|
| 355 | | - * sink. |
|---|
| 348 | + * An LVDS dual-link connection is made of two links, with even pixels |
|---|
| 349 | + * transitting on one link, and odd pixels on the other link. This function |
|---|
| 350 | + * returns, for two ports of an LVDS dual-link source, which port shall transmit |
|---|
| 351 | + * the even and odd pixels, based on the requirements of the connected sink. |
|---|
| 356 | 352 | * |
|---|
| 357 | | - * The pixel order is determined from the dual-lvds-even-pixels + |
|---|
| 358 | | - * dual-lvds-odd-pixels or dual-lvds-left-pixels + dual-lvds-right-pixels |
|---|
| 359 | | - * properties in the sink's DT port nodes. If those |
|---|
| 353 | + * The pixel order is determined from the dual-lvds-even-pixels and |
|---|
| 354 | + * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those |
|---|
| 360 | 355 | * properties are not present, or if their usage is not valid, this function |
|---|
| 361 | 356 | * returns -EINVAL. |
|---|
| 362 | 357 | * |
|---|
| .. | .. |
|---|
| 371 | 366 | * carries odd pixels |
|---|
| 372 | 367 | * * DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS - @port1 carries odd pixels and @port2 |
|---|
| 373 | 368 | * carries even pixels |
|---|
| 374 | | - * * DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS - @port1 carries left pixels and |
|---|
| 375 | | - * @port2 carries right pixels |
|---|
| 376 | | - * * DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS - @port1 carries right pixels and |
|---|
| 377 | | - * @port2 carries left pixels |
|---|
| 378 | | - |
|---|
| 379 | 369 | * * -EINVAL - @port1 and @port2 are not connected to a dual-link LVDS sink, or |
|---|
| 380 | 370 | * the sink configuration is invalid |
|---|
| 381 | 371 | * * -EPIPE - when @port1 or @port2 are not connected |
|---|
| .. | .. |
|---|
| 398 | 388 | |
|---|
| 399 | 389 | /* |
|---|
| 400 | 390 | * A valid dual-lVDS bus is found when one remote port is marked with |
|---|
| 401 | | - * "dual-lvds-even-pixels" or "dual-lvds-left-pixels", and the other |
|---|
| 402 | | - * remote port is marked with "dual-lvds-odd-pixels"or |
|---|
| 403 | | - * "dual-lvds-right-pixels", bail out if the markers are not right. |
|---|
| 391 | + * "dual-lvds-even-pixels", and the other remote port is marked with |
|---|
| 392 | + * "dual-lvds-odd-pixels", bail out if the markers are not right. |
|---|
| 404 | 393 | */ |
|---|
| 405 | | - if ((remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD) && |
|---|
| 406 | | - (remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_LEFT + DRM_OF_LVDS_RIGHT)) |
|---|
| 394 | + if (remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD) |
|---|
| 407 | 395 | return -EINVAL; |
|---|
| 408 | 396 | |
|---|
| 409 | | - if (remote_p1_pt == DRM_OF_LVDS_EVEN) |
|---|
| 410 | | - return DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS; |
|---|
| 411 | | - else if (remote_p1_pt == DRM_OF_LVDS_ODD) |
|---|
| 412 | | - return DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS; |
|---|
| 413 | | - else if (remote_p1_pt == DRM_OF_LVDS_LEFT) |
|---|
| 414 | | - return DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS; |
|---|
| 415 | | - else |
|---|
| 416 | | - return DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS; |
|---|
| 397 | + return remote_p1_pt == DRM_OF_LVDS_EVEN ? |
|---|
| 398 | + DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS : |
|---|
| 399 | + DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS; |
|---|
| 417 | 400 | } |
|---|
| 418 | 401 | EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order); |
|---|