summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/bridge/analogix/analogix-anx6345.c')
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx6345.c112
1 files changed, 38 insertions, 74 deletions
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
index 9af39ec958db..f3fe47b12edc 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
@@ -18,11 +18,10 @@
#include <linux/regulator/consumer.h>
#include <linux/types.h>
+#include <drm/display/drm_dp_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_dp_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
@@ -48,7 +47,7 @@ struct anx6345 {
struct drm_dp_aux aux;
struct drm_bridge bridge;
struct i2c_client *client;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
struct drm_connector connector;
struct drm_panel *panel;
struct regulator *dvdd12;
@@ -144,35 +143,7 @@ static int anx6345_dp_link_training(struct anx6345 *anx6345)
if (err)
return err;
- /*
- * Power up the sink (DP_SET_POWER register is only available on DPCD
- * v1.1 and later).
- */
- if (anx6345->dpcd[DP_DPCD_REV] >= 0x11) {
- err = drm_dp_dpcd_readb(&anx6345->aux, DP_SET_POWER, &dpcd[0]);
- if (err < 0) {
- DRM_ERROR("Failed to read DP_SET_POWER register: %d\n",
- err);
- return err;
- }
-
- dpcd[0] &= ~DP_SET_POWER_MASK;
- dpcd[0] |= DP_SET_POWER_D0;
-
- err = drm_dp_dpcd_writeb(&anx6345->aux, DP_SET_POWER, dpcd[0]);
- if (err < 0) {
- DRM_ERROR("Failed to power up DisplayPort link: %d\n",
- err);
- return err;
- }
-
- /*
- * According to the DP 1.1 specification, a "Sink Device must
- * exit the power saving state within 1 ms" (Section 2.5.3.1,
- * Table 5-52, "Sink Control Field" (register 0x600).
- */
- usleep_range(1000, 2000);
- }
+ drm_dp_link_power_up(&anx6345->aux, anx6345->dpcd[DP_DPCD_REV]);
/* Possibly enable downspread on the sink */
err = regmap_write(anx6345->map[I2C_IDX_DPTX],
@@ -459,7 +430,7 @@ static int anx6345_get_modes(struct drm_connector *connector)
mutex_lock(&anx6345->lock);
- if (!anx6345->edid) {
+ if (!anx6345->drm_edid) {
if (!anx6345->powered) {
anx6345_poweron(anx6345);
power_off = true;
@@ -471,19 +442,18 @@ static int anx6345_get_modes(struct drm_connector *connector)
goto unlock;
}
- anx6345->edid = drm_get_edid(connector, &anx6345->aux.ddc);
- if (!anx6345->edid)
+ anx6345->drm_edid = drm_edid_read_ddc(connector, &anx6345->aux.ddc);
+ if (!anx6345->drm_edid)
DRM_ERROR("Failed to read EDID from panel\n");
- err = drm_connector_update_edid_property(connector,
- anx6345->edid);
+ err = drm_edid_connector_update(connector, anx6345->drm_edid);
if (err) {
DRM_ERROR("Failed to update EDID property: %d\n", err);
goto unlock;
}
}
- num_modes += drm_add_edid_modes(connector, anx6345->edid);
+ num_modes += drm_edid_connector_add_modes(connector);
/* Driver currently supports only 6bpc */
connector->display_info.bpc = 6;
@@ -507,10 +477,6 @@ static const struct drm_connector_helper_funcs anx6345_connector_helper_funcs =
static void
anx6345_connector_destroy(struct drm_connector *connector)
{
- struct anx6345 *anx6345 = connector_to_anx6345(connector);
-
- if (anx6345->panel)
- drm_panel_detach(anx6345->panel);
drm_connector_cleanup(connector);
}
@@ -523,6 +489,7 @@ static const struct drm_connector_funcs anx6345_connector_funcs = {
};
static int anx6345_bridge_attach(struct drm_bridge *bridge,
+ struct drm_encoder *encoder,
enum drm_bridge_attach_flags flags)
{
struct anx6345 *anx6345 = bridge_to_anx6345(bridge);
@@ -533,14 +500,10 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
}
- if (!bridge->encoder) {
- DRM_ERROR("Parent encoder object not found");
- return -ENODEV;
- }
-
/* Register aux channel */
anx6345->aux.name = "DP-AUX";
anx6345->aux.dev = &anx6345->client->dev;
+ anx6345->aux.drm_dev = bridge->dev;
anx6345->aux.transfer = anx6345_aux_transfer;
err = drm_dp_aux_register(&anx6345->aux);
@@ -554,40 +517,43 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge,
DRM_MODE_CONNECTOR_eDP);
if (err) {
DRM_ERROR("Failed to initialize connector: %d\n", err);
- return err;
+ goto aux_unregister;
}
drm_connector_helper_add(&anx6345->connector,
&anx6345_connector_helper_funcs);
- err = drm_connector_register(&anx6345->connector);
- if (err) {
- DRM_ERROR("Failed to register connector: %d\n", err);
- return err;
- }
-
anx6345->connector.polled = DRM_CONNECTOR_POLL_HPD;
err = drm_connector_attach_encoder(&anx6345->connector,
- bridge->encoder);
+ encoder);
if (err) {
DRM_ERROR("Failed to link up connector to encoder: %d\n", err);
- return err;
+ goto connector_cleanup;
}
- if (anx6345->panel) {
- err = drm_panel_attach(anx6345->panel, &anx6345->connector);
- if (err) {
- DRM_ERROR("Failed to attach panel: %d\n", err);
- return err;
- }
+ err = drm_connector_register(&anx6345->connector);
+ if (err) {
+ DRM_ERROR("Failed to register connector: %d\n", err);
+ goto connector_cleanup;
}
return 0;
+connector_cleanup:
+ drm_connector_cleanup(&anx6345->connector);
+aux_unregister:
+ drm_dp_aux_unregister(&anx6345->aux);
+ return err;
+}
+
+static void anx6345_bridge_detach(struct drm_bridge *bridge)
+{
+ drm_dp_aux_unregister(&bridge_to_anx6345(bridge)->aux);
}
static enum drm_mode_status
anx6345_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
const struct drm_display_mode *mode)
{
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -635,6 +601,7 @@ static void anx6345_bridge_enable(struct drm_bridge *bridge)
static const struct drm_bridge_funcs anx6345_bridge_funcs = {
.attach = anx6345_bridge_attach,
+ .detach = anx6345_bridge_detach,
.mode_valid = anx6345_bridge_mode_valid,
.disable = anx6345_bridge_disable,
.enable = anx6345_bridge_enable,
@@ -691,16 +658,16 @@ static bool anx6345_get_chip_id(struct anx6345 *anx6345)
return false;
}
-static int anx6345_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int anx6345_i2c_probe(struct i2c_client *client)
{
struct anx6345 *anx6345;
struct device *dev;
int i, err;
- anx6345 = devm_kzalloc(&client->dev, sizeof(*anx6345), GFP_KERNEL);
- if (!anx6345)
- return -ENOMEM;
+ anx6345 = devm_drm_bridge_alloc(&client->dev, struct anx6345, bridge,
+ &anx6345_bridge_funcs);
+ if (IS_ERR(anx6345))
+ return PTR_ERR(anx6345);
mutex_init(&anx6345->lock);
@@ -772,7 +739,6 @@ static int anx6345_i2c_probe(struct i2c_client *client,
/* Look for supported chip ID */
anx6345_poweron(anx6345);
if (anx6345_get_chip_id(anx6345)) {
- anx6345->bridge.funcs = &anx6345_bridge_funcs;
drm_bridge_add(&anx6345->bridge);
return 0;
@@ -786,7 +752,7 @@ err_unregister_i2c:
return err;
}
-static int anx6345_i2c_remove(struct i2c_client *client)
+static void anx6345_i2c_remove(struct i2c_client *client)
{
struct anx6345 *anx6345 = i2c_get_clientdata(client);
@@ -794,15 +760,13 @@ static int anx6345_i2c_remove(struct i2c_client *client)
unregister_i2c_dummy_clients(anx6345);
- kfree(anx6345->edid);
+ drm_edid_free(anx6345->drm_edid);
mutex_destroy(&anx6345->lock);
-
- return 0;
}
static const struct i2c_device_id anx6345_id[] = {
- { "anx6345", 0 },
+ { "anx6345" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, anx6345_id);
@@ -816,7 +780,7 @@ MODULE_DEVICE_TABLE(of, anx6345_match_table);
static struct i2c_driver anx6345_driver = {
.driver = {
.name = "anx6345",
- .of_match_table = of_match_ptr(anx6345_match_table),
+ .of_match_table = anx6345_match_table,
},
.probe = anx6345_i2c_probe,
.remove = anx6345_i2c_remove,