From e4683661b853d41290cb189fe3aac59a2de7e751 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 19 Apr 2019 17:31:14 +0800 Subject: [PATCH] drm/bridge: parade-ps8622: fix some usage to make it work on rockchip platform Change-Id: Ia8dd97389f6e532141bba501a9d75feb264ebc53 Signed-off-by: Wyon Bi --- .../bindings/display/bridge/ps8622.txt | 35 ++++++++--- drivers/gpu/drm/bridge/parade-ps8622.c | 59 +++++++++++++------ 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/ps8622.txt b/Documentation/devicetree/bindings/display/bridge/ps8622.txt index c989c3807f2b..7345bc871f90 100644 --- a/Documentation/devicetree/bindings/display/bridge/ps8622.txt +++ b/Documentation/devicetree/bindings/display/bridge/ps8622.txt @@ -11,21 +11,42 @@ Optional properties: - use-external-pwm: backlight will be controlled by an external PWM - video interfaces: Device node can contain video interface port nodes for panel according to [1]. + - dual-channel: boolean. if it exists, enable dual channel mode [1]: Documentation/devicetree/bindings/media/video-interfaces.txt Example: - lvds-bridge@48 { - compatible = "parade,ps8622"; + +&i2c4 { + status = "okay"; + + ps8625: ps8625@48 { + compatible = "parade,ps8625"; reg = <0x48>; - sleep-gpios = <&gpc3 6 1 0 0>; - reset-gpios = <&gpc3 1 1 0 0>; - lane-count = <1>; + sleep-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>; + lane-count = <2>; + use-external-pwm; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { - bridge_out: endpoint { - remote-endpoint = <&panel_in>; + reg = <0>; + + ps8625_in_edp: endpoint { + remote-endpoint = <&edp_out_ps8625>; + }; + }; + + port@1 { + reg = <1>; + + ps8625_out_panel: endpoint { + remote-endpoint = <&panel_in_ps8625>; }; }; }; }; +}; diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index be881e9fef8f..c4d56a7ed9d5 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -28,6 +28,7 @@ #include #include +#include #include "drmP.h" #include "drm_crtc.h" @@ -64,6 +65,8 @@ struct ps8622_bridge { u32 max_lane_count; u32 lane_count; + u32 bus_format; + bool dual_channel; bool enabled; }; @@ -102,6 +105,7 @@ static int ps8622_set(struct i2c_client *client, u8 page, u8 reg, u8 val) static int ps8622_send_config(struct ps8622_bridge *ps8622) { struct i2c_client *cl = ps8622->client; + u8 format; int err = 0; /* HPD low */ @@ -305,8 +309,22 @@ static int ps8622_send_config(struct ps8622_bridge *ps8622) goto error; } - /* Set LVDS output as 6bit-VESA mapping, single LVDS channel */ - err = ps8622_set(cl, 0x01, 0xcc, 0x13); + switch (ps8622->bus_format) { + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + format = 0x03; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + format = 0x01; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + default: + format = 0x00; + break; + } + + /* Set LVDS color depth, data mapping and single/dual link */ + err = ps8622_set(cl, 0x01, 0xcc, 0x10 | (ps8622->dual_channel << 2) | + format); if (err) goto error; @@ -467,11 +485,22 @@ static void ps8622_post_disable(struct drm_bridge *bridge) static int ps8622_get_modes(struct drm_connector *connector) { - struct ps8622_bridge *ps8622; + struct ps8622_bridge *ps8622 = connector_to_ps8622(connector); + struct drm_display_info *info = &connector->display_info; + u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; + int num_modes = 0; - ps8622 = connector_to_ps8622(connector); + num_modes = drm_panel_get_modes(ps8622->panel); - return drm_panel_get_modes(ps8622->panel); + if (info->num_bus_formats) + ps8622->bus_format = info->bus_formats[0]; + else + ps8622->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG; + + drm_display_info_set_bus_formats(&connector->display_info, + &bus_format, 1); + + return num_modes; } static struct drm_encoder *ps8622_best_encoder(struct drm_connector *connector) @@ -519,6 +548,7 @@ static int ps8622_attach(struct drm_bridge *bridge) return -ENODEV; } + ps8622->connector.port = ps8622->client->dev.of_node; ps8622->connector.polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(bridge->dev, &ps8622->connector, &ps8622_connector_funcs, DRM_MODE_CONNECTOR_LVDS); @@ -528,7 +558,6 @@ static int ps8622_attach(struct drm_bridge *bridge) } drm_connector_helper_add(&ps8622->connector, &ps8622_connector_helper_funcs); - drm_connector_register(&ps8622->connector); drm_mode_connector_attach_encoder(&ps8622->connector, bridge->encoder); @@ -559,7 +588,6 @@ static int ps8622_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; - struct device_node *endpoint, *panel_node; struct ps8622_bridge *ps8622; int ret; @@ -567,19 +595,16 @@ static int ps8622_probe(struct i2c_client *client, if (!ps8622) return -ENOMEM; - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); - if (endpoint) { - panel_node = of_graph_get_remote_port_parent(endpoint); - if (panel_node) { - ps8622->panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); - if (!ps8622->panel) - return -EPROBE_DEFER; - } - } + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, + &ps8622->panel, NULL); + if (ret) + return ret; ps8622->client = client; + ps8622->dual_channel = of_property_read_bool(dev->of_node, + "dual-channel"); + ps8622->v12 = devm_regulator_get(dev, "vdd12"); if (IS_ERR(ps8622->v12)) { dev_info(dev, "no 1.2v regulator found for PS8622\n");