drm/bridge: parade-ps8622: fix some usage to make it work on rockchip platform

Change-Id: Ia8dd97389f6e532141bba501a9d75feb264ebc53
Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
Wyon Bi
2019-04-19 17:31:14 +08:00
committed by Tao Huang
parent d6653db29a
commit e4683661b8
2 changed files with 70 additions and 24 deletions

View File

@@ -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>;
};
};
};
};
};

View File

@@ -28,6 +28,7 @@
#include <linux/regulator/consumer.h>
#include <drm/drm_panel.h>
#include <drm/drm_of.h>
#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");