drm/bridge: anx7625: send DPCD command to downstream
Subsystems (4)
PATCH v4 1/4 drm/bridge: anx7625: send DPCD command to downstream
From: Xin Ji <[email protected]>
Send DPCD command to downstream before anx7625 power down, let downstream monitor enter into standby mode.
---v3->v4:
Use common DP_AUX_NATIVE_READ/WRITE
--- drivers/gpu/drm/bridge/analogix/anx7625.c | 42 +++++++++++++++++++---- drivers/gpu/drm/bridge/analogix/anx7625.h | 2 -- 2 files changed, 35 insertions(+), 9 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +35 -7
@@ -129,6 +129,23 @@ static int anx7625_reg_write(struct anx7625_data *ctx,return ret; } +static int anx7625_reg_block_write (struct anx7625_data *ctx, +struct i2c_client *client, +u8 reg_addr,u8 len,u8 *buf) +{ +int ret; +struct device *dev = &client->dev; + +i2c_access_workaround (ctx, client); + + ret =i2c_smbus_write_i2c_block_data (client, reg_addr, len, buf); +if (ret <0 ) +dev_err (dev,"write i2c block failed id=%x\n:%x" , + client->addr, reg_addr); + +return ret; +} +static int anx7625_write_or (struct anx7625_data *ctx,struct i2c_client *client,u8 offset,u8 mask)
@@ -214,8 +231,8 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)return 0 ; } -static int anx7625_aux_dpcd_read (struct anx7625_data *ctx, -u32 address,u8 len,u8 *buf) +static int anx7625_aux_dpcd_trans (struct anx7625_data *ctx,u8 op, +u32 address,u8 len,u8 *buf) {struct device *dev = &ctx->client->dev;int ret;
@@ -231,8 +248,7 @@ static int anx7625_aux_dpcd_read(struct anx7625_data *ctx, addrm = (address >>8 ) &0xFF ; addrh = (address >>16 ) &0xFF ; - cmd =DPCD_CMD (len,DPCD_READ ); - cmd = ((len -1 ) <<4 ) |0x09 ; + cmd =DPCD_CMD (len, op);/* Set command and length */ ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -246,6 +262,9 @@ static int anx7625_aux_dpcd_read(struct anx7625_data *ctx, ret |=anx7625_reg_write (ctx, ctx->i2c.rx_p0_client,AP_AUX_ADDR_19_16 , addrh); +if (op ==DP_AUX_NATIVE_WRITE ) + ret |=anx7625_reg_block_write (ctx, ctx->i2c.rx_p0_client, +AP_AUX_BUFF_START , len, buf);/* Enable aux access */ ret |=anx7625_write_or (ctx, ctx->i2c.rx_p0_client,AP_AUX_CTRL_STATUS ,AP_AUX_CTRL_OP_EN );
@@ -255,14 +274,17 @@ static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,return -EIO ; } -usleep_range (2000 ,2100 ); - ret =wait_aux_op_finish (ctx);if (ret) {dev_err (dev,"aux IO error: wait aux op finish.\n" );return ret; } +/* Write done */ +if (op ==DP_AUX_NATIVE_WRITE ) +return 0 ; + +/* Read done, read out dpcd data */ ret =anx7625_reg_block_read (ctx, ctx->i2c.rx_p0_client,AP_AUX_BUFF_START , len, buf);if (ret <0 ) {
@@ -845,7 +867,7 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx) }/* Read downstream capability */ -anx7625_aux_dpcd_read (ctx,0x68028 ,1 , &bcap); +anx7625_aux_dpcd_trans (ctx,DP_AUX_NATIVE_READ ,0x68028 ,1 , &bcap);if (!(bcap &0x01 )) {pr_warn ("downstream not support HDCP 1.4, cap(%x).\n" , bcap);return 0 ;
@@ -918,6 +940,7 @@ static void anx7625_dp_stop(struct anx7625_data *ctx) {struct device *dev = &ctx->client->dev;int ret; +u8 data;DRM_DEV_DEBUG_DRIVER (dev,"stop dp output\n" );
@@ -929,6 +952,11 @@ static void anx7625_dp_stop(struct anx7625_data *ctx) ret |=anx7625_write_and (ctx, ctx->i2c.tx_p2_client,0x08 ,0x7f ); ret |=anx7625_video_mute_control (ctx,1 ); + +dev_dbg (dev,"notify downstream enter into standby\n" ); +/* Downstream monitor enter into standby mode */ + data =2 ; + ret |=anx7625_aux_dpcd_trans (ctx,DP_AUX_NATIVE_WRITE ,0x000600 ,1 , &data);if (ret <0 )DRM_DEV_ERROR (dev,"IO error : mute video fail\n" );
drivers/gpu/drm/bridge/analogix/anx7625.h +0 -2
@@ -242,8 +242,6 @@#define AP_AUX_COMMAND 0x27/* com+len */ #define LENGTH_SHIFT 4 -#define DPCD_READ 0x09 -#define DPCD_WRITE 0x08#define DPCD_CMD (len, cmd) ((((len) - 1) << LENGTH_SHIFT) | (cmd))/* Bit 0&1: 3D video structure */
Signature · 1 line
2.34.1.703.g22d0c6ccf7-goog
PATCH v4 2/4 drm/bridge: anx7625: Convert to use devm_kzalloc
Use devm_kzalloc instead of kzalloc and drop kfree(). Let the memory handled by driver detach.
---v2->v3: remove kfree() in anx7625_i2c_remove().
--- drivers/gpu/drm/bridge/analogix/anx7625.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +3 -7
@@ -2515,7 +2515,7 @@ static int anx7625_i2c_probe(struct i2c_client *client,return -ENODEV ; } - platform =kzalloc (sizeof (*platform),GFP_KERNEL ); + platform =devm_kzalloc (dev,sizeof (*platform),GFP_KERNEL );if (!platform) {DRM_DEV_ERROR (dev,"fail to allocate driver data\n" );return -ENOMEM ;
@@ -2527,7 +2527,7 @@ static int anx7625_i2c_probe(struct i2c_client *client,if (ret) {if (ret != -EPROBE_DEFER )DRM_DEV_ERROR (dev,"fail to parse DT : %d\n" , ret); - goto free_platform; +return ret; } platform->client = client;
@@ -2552,7 +2552,7 @@ static int anx7625_i2c_probe(struct i2c_client *client,if (!platform->hdcp_workqueue) {dev_err (dev,"fail to create work queue\n" ); ret = -ENOMEM ; - goto free_platform; +return ret; } platform->pdata.intp_irq = client->irq;
@@ -2637,9 +2637,6 @@ static int anx7625_i2c_probe(struct i2c_client *client,if (platform->hdcp_workqueue)destroy_workqueue (platform->hdcp_workqueue); -free_platform: -kfree (platform); -return ret; }
@@ -2666,7 +2663,6 @@ static int anx7625_i2c_remove(struct i2c_client *client)if (platform->pdata.audio_en)anx7625_unregister_audio (platform); -kfree (platform);return 0 ; }
Signature · 1 line
2.34.1.703.g22d0c6ccf7-goog
PATCH v4 3/4 drm/bridge: anx7625: Support reading edid through aux channel
In reply to Hsin-Yi WangSupport reading edid through aux channel if panel is connected to aux bus. Extend anx7625_aux_dpcd_trans() to implement aux transfer function:
1. panel is populated in devm_of_dp_aux_populate_ep_devices(), so move anx7625_parse_dt() after.
2. Use pm runtime autosuspend since aux transfer function is called multiple times when reading edid.
3. No-op if aux transfer length is 0.
---v3->v4:
rebase to latest drm-misc-next
--- drivers/gpu/drm/bridge/analogix/anx7625.c | 120 ++++++++++++++++++---- drivers/gpu/drm/bridge/analogix/anx7625.h | 1 + 2 files changed, 103 insertions(+), 18 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +102 -18
@@ -24,6 +24,7 @@#include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_dp_aux_bus.h> #include <drm/dp/drm_dp_helper.h> #include <drm/drm_edid.h> #include <drm/drm_hdcp.h>
@@ -231,19 +232,23 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)return 0 ; } -static int anx7625_aux_dpcd_trans (struct anx7625_data *ctx,u8 op, -u32 address,u8 len,u8 *buf) +static int anx7625_aux_trans (struct anx7625_data *ctx,u8 op,u32 address, +u8 len,u8 *buf) {struct device *dev = &ctx->client->dev;int ret;u8 addrh, addrm, addrl;u8 cmd; +bool is_write = !(op &DP_AUX_I2C_READ ); -if (len >MAX_DPCD_BUFFER_SIZE ) { +if (len >DP_AUX_MAX_PAYLOAD_BYTES ) {dev_err (dev,"exceed aux buffer len.\n" );return -EINVAL ; } +if (!len) +return len; + addrl = address &0xFF ; addrm = (address >>8 ) &0xFF ; addrh = (address >>16 ) &0xFF ;
@@ -262,7 +267,7 @@ static int anx7625_aux_dpcd_trans(struct anx7625_data *ctx, u8 op, ret |=anx7625_reg_write (ctx, ctx->i2c.rx_p0_client,AP_AUX_ADDR_19_16 , addrh); -if (op ==DP_AUX_NATIVE_WRITE ) +if (is_write) ret |=anx7625_reg_block_write (ctx, ctx->i2c.rx_p0_client,AP_AUX_BUFF_START , len, buf);/* Enable aux access */
@@ -275,14 +280,14 @@ static int anx7625_aux_dpcd_trans(struct anx7625_data *ctx, u8 op, } ret =wait_aux_op_finish (ctx); -if (ret) { +if (ret <0 ) {dev_err (dev,"aux IO error: wait aux op finish.\n" );return ret; }/* Write done */ -if (op ==DP_AUX_NATIVE_WRITE ) -return 0 ; +if (is_write) +return len;/* Read done, read out dpcd data */ ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
@@ -292,7 +297,7 @@ static int anx7625_aux_dpcd_trans(struct anx7625_data *ctx, u8 op,return -EIO ; } -return 0 ; +return len; } static int anx7625_video_mute_control(struct anx7625_data *ctx,
@@ -867,7 +872,7 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx) }/* Read downstream capability */ -anx7625_aux_dpcd_trans (ctx,DP_AUX_NATIVE_READ ,0x68028 ,1 , &bcap); +anx7625_aux_trans (ctx,DP_AUX_NATIVE_READ ,0x68028 ,1 , &bcap);if (!(bcap &0x01 )) {pr_warn ("downstream not support HDCP 1.4, cap(%x).\n" , bcap);return 0 ;
@@ -956,7 +961,7 @@ static void anx7625_dp_stop(struct anx7625_data *ctx)dev_dbg (dev,"notify downstream enter into standby\n" );/* Downstream monitor enter into standby mode */ data =2 ; - ret |=anx7625_aux_dpcd_trans (ctx,DP_AUX_NATIVE_WRITE ,0x000600 ,1 , &data); + ret |=anx7625_aux_trans (ctx,DP_AUX_NATIVE_WRITE ,0x000600 ,1 , &data);if (ret <0 )DRM_DEV_ERROR (dev,"IO error : mute video fail\n" );
@@ -1655,11 +1660,56 @@ static int anx7625_parse_dt(struct device *dev,return 0 ; } +static bool anx7625_of_panel_on_aux_bus (struct device *dev) +{ +struct device_node *bus, *panel; + + bus =of_get_child_by_name (dev->of_node,"aux-bus" ); +if (!bus) +return false; + + panel =of_get_child_by_name (bus,"panel" ); +of_node_put (bus); +if (!panel) +return false; +of_node_put (panel); + +return true; +} +static inline struct anx7625_data *bridge_to_anx7625 (struct drm_bridge *bridge) { return container_of(bridge, struct anx7625_data, bridge); } +static ssize_t anx7625_aux_transfer (struct drm_dp_aux *aux, +struct drm_dp_aux_msg *msg) +{ + struct anx7625_data *ctx = container_of(aux, struct anx7625_data, aux); +struct device *dev = &ctx->client->dev; +u8 request = msg->request & ~DP_AUX_I2C_MOT ; +int ret =0 ; + +pm_runtime_get_sync (dev); + msg->reply =0 ; +switch (request) { +case DP_AUX_NATIVE_WRITE : +case DP_AUX_I2C_WRITE : +case DP_AUX_NATIVE_READ : +case DP_AUX_I2C_READ : +break ; +default : + ret = -EINVAL ; + } +if (!ret) + ret =anx7625_aux_trans (ctx, msg->request, msg->address, + msg->size, msg->buffer); +pm_runtime_mark_last_busy (dev); +pm_runtime_put_autosuspend (dev); + +return ret; +} +static struct edid *anx7625_get_edid (struct anx7625_data *ctx) {struct device *dev = &ctx->client->dev;
@@ -2066,6 +2116,13 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,return -ENODEV ; } + ctx->aux.drm_dev = bridge->dev; + err =drm_dp_aux_register (&ctx->aux); +if (err) { +dev_err (dev,"failed to register aux channel: %d\n" , err); +return err; + } +if (ctx->pdata.panel_bridge) { err = drm_bridge_attach(bridge->encoder, ctx->pdata.panel_bridge,
@@ -2079,6 +2136,13 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,return 0 ; } +static void anx7625_bridge_detach (struct drm_bridge *bridge) +{ +struct anx7625_data *ctx =bridge_to_anx7625 (bridge); + +drm_dp_aux_unregister (&ctx->aux); +} + static enum drm_mode_status anx7625_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info,
@@ -2344,6 +2408,7 @@ static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge,static const struct drm_bridge_funcs anx7625_bridge_funcs = { .attach = anx7625_bridge_attach, + .detach = anx7625_bridge_detach, .mode_valid = anx7625_bridge_mode_valid, .mode_set = anx7625_bridge_mode_set, .atomic_check = anx7625_bridge_atomic_check,
@@ -2501,6 +2566,12 @@ static const struct dev_pm_ops anx7625_pm_ops = { anx7625_runtime_pm_resume, NULL) }; +static void anx7625_runtime_disable (void *data) +{ +pm_runtime_dont_use_autosuspend (data); +pm_runtime_disable (data); +} +static int anx7625_i2c_probe (struct i2c_client *client,const struct i2c_device_id *id) {
@@ -2523,13 +2594,6 @@ static int anx7625_i2c_probe(struct i2c_client *client, pdata = &platform->pdata; - ret =anx7625_parse_dt (dev, pdata); -if (ret) { -if (ret != -EPROBE_DEFER ) -DRM_DEV_ERROR (dev,"fail to parse DT : %d\n" , ret); -return ret; - } - platform->client = client;i2c_set_clientdata (client, platform);
@@ -2577,6 +2641,19 @@ static int anx7625_i2c_probe(struct i2c_client *client, } } + platform->aux.name ="anx7625-aux" ; + platform->aux.dev = dev; + platform->aux.transfer = anx7625_aux_transfer; +drm_dp_aux_init (&platform->aux); +devm_of_dp_aux_populate_ep_devices (&platform->aux); + + ret =anx7625_parse_dt (dev, pdata); +if (ret) { +if (ret != -EPROBE_DEFER ) +DRM_DEV_ERROR (dev,"fail to parse DT : %d\n" , ret); +return ret; + } +if (anx7625_register_i2c_dummy_clients (platform, client) !=0 ) { ret = -ENOMEM ;DRM_DEV_ERROR (dev,"fail to reserve I2C bus.\n" );
@@ -2584,6 +2661,12 @@ static int anx7625_i2c_probe(struct i2c_client *client, }pm_runtime_enable (dev); +pm_runtime_set_autosuspend_delay (dev,1000 ); +pm_runtime_use_autosuspend (dev); +pm_suspend_ignore_children (dev, true); + ret =devm_add_action_or_reset (dev, anx7625_runtime_disable, dev); +if (ret) +return ret;if (!platform->pdata.low_power_mode) {anx7625_disable_pd_protocol (platform);
@@ -2596,7 +2679,8 @@ static int anx7625_i2c_probe(struct i2c_client *client, platform->bridge.funcs = &anx7625_bridge_funcs; platform->bridge.of_node = client->dev.of_node; - platform->bridge.ops =DRM_BRIDGE_OP_EDID ; +if (!anx7625_of_panel_on_aux_bus (&client->dev)) + platform->bridge.ops |=DRM_BRIDGE_OP_EDID ;if (!platform->pdata.panel_bridge) platform->bridge.ops |=DRM_BRIDGE_OP_HPD |DRM_BRIDGE_OP_DETECT ;
drivers/gpu/drm/bridge/analogix/anx7625.h +1 -0
@@ -472,6 +472,7 @@ struct anx7625_data {u8 bridge_attached;struct drm_connector *connector;struct mipi_dsi_device *dsi; + struct drm_dp_aux aux; };#endif /* __ANX7625_H__ */
Signature · 1 line
2.34.1.703.g22d0c6ccf7-goog
Re: [PATCH v4 3/4] drm/bridge: anx7625: Support reading edid through aux channel
Quoted 25 lines · Hsin-Yi Wang
Support reading edid through aux channel if panel is connected to aux bus. Extend
anx7625_aux_dpcd_trans()to implement aux transfer function:1. panel is populated in
devm_of_dp_aux_populate_ep_devices(), so moveanx7625_parse_dt()after.
2. Use pm runtime autosuspend since aux transfer function is called multiple times when reading edid.
3. No-op if aux transfer length is 0.Signed-off-by Hsin-Yi Wang <[email protected]>Reviewed-by Xin Ji <[email protected]>---
v3->v4:
rebase to latest drm-misc-next--- drivers/gpu/drm/bridge/analogix/anx7625.c | 120 ++++++++++++++++++---- drivers/gpu/drm/bridge/analogix/anx7625.h | 1 + 2 files changed, 103 insertions(+), 18 deletions(-)drivers/gpu/drm/bridge/analogix/anx7625.c +0
-0
drivers/gpu/drm/bridge/analogix/anx7625.c line 27
Quoted 4 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1
-0@@ -24,6 +24,7 @@#include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_dp_aux_bus.h>
drivers/gpu/drm/bridge/analogix/anx7625.c:27:10: fatal error:drm/drm_dp_aux_bus.h: No such file or directory
27 | #include <drm/drm_dp_aux_bus.h>
drm/dp/rm_dp_aux_bus.h is probably the correct path.
Quoted 102 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +28
-10#include <drm/dp/drm_dp_helper.h> #include <drm/drm_edid.h> #include <drm/drm_hdcp.h> @@ -231,19 +232,23 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)return 0 ; } -static int anx7625_aux_dpcd_trans (struct anx7625_data *ctx,u8 op, -u32 address,u8 len,u8 *buf) +static int anx7625_aux_trans (struct anx7625_data *ctx,u8 op,u32 address, +u8 len,u8 *buf) {struct device *dev = &ctx->client->dev;int ret;u8 addrh, addrm, addrl;u8 cmd; +bool is_write = !(op &DP_AUX_I2C_READ ); -if (len >MAX_DPCD_BUFFER_SIZE ) { +if (len >DP_AUX_MAX_PAYLOAD_BYTES ) {dev_err (dev,"exceed aux buffer len.\n" );return -EINVAL ; } +if (!len) +return len; + addrl = address &0xFF ; addrm = (address >>8 ) &0xFF ; addrh = (address >>16 ) &0xFF ;@@ -262,7 +267,7 @@ static int anx7625_aux_dpcd_trans(struct anx7625_data *ctx, u8 op, ret |=anx7625_reg_write (ctx, ctx->i2c.rx_p0_client,AP_AUX_ADDR_19_16 , addrh); -if (op ==DP_AUX_NATIVE_WRITE ) +if (is_write) ret |=anx7625_reg_block_write (ctx, ctx->i2c.rx_p0_client,AP_AUX_BUFF_START , len, buf);/* Enable aux access */ @@ -275,14 +280,14 @@ static int anx7625_aux_dpcd_trans(struct anx7625_data *ctx, u8 op, } ret =wait_aux_op_finish (ctx); -if (ret) { +if (ret <0 ) {dev_err (dev,"aux IO error: wait aux op finish.\n" );return ret; }/* Write done */ -if (op ==DP_AUX_NATIVE_WRITE ) -return 0 ; +if (is_write) +return len;/* Read done, read out dpcd data */ ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,@@ -292,7 +297,7 @@ static int anx7625_aux_dpcd_trans(struct anx7625_data *ctx, u8 op,return -EIO ; } -return 0 ; +return len; } static int anx7625_video_mute_control(struct anx7625_data *ctx,@@ -867,7 +872,7 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx) }/* Read downstream capability */ -anx7625_aux_dpcd_trans (ctx,DP_AUX_NATIVE_READ ,0x68028 ,1 , &bcap); +anx7625_aux_trans (ctx,DP_AUX_NATIVE_READ ,0x68028 ,1 , &bcap);if (!(bcap &0x01 )) {pr_warn ("downstream not support HDCP 1.4, cap(%x).\n" , bcap);return 0 ;@@ -956,7 +961,7 @@ static void anx7625_dp_stop(struct anx7625_data *ctx)dev_dbg (dev,"notify downstream enter into standby\n" );/* Downstream monitor enter into standby mode */ data =2 ; - ret |=anx7625_aux_dpcd_trans (ctx,DP_AUX_NATIVE_WRITE ,0x000600 ,1 , &data); + ret |=anx7625_aux_trans (ctx,DP_AUX_NATIVE_WRITE ,0x000600 ,1 , &data);if (ret <0 )DRM_DEV_ERROR (dev,"IO error : mute video fail\n" );@@ -1655,11 +1660,56 @@ static int anx7625_parse_dt(struct device *dev,return 0 ; } +static bool anx7625_of_panel_on_aux_bus (struct device *dev) +{ +struct device_node *bus, *panel; + + bus =of_get_child_by_name (dev->of_node,"aux-bus" ); +if (!bus) +return false; + + panel =of_get_child_by_name (bus,"panel" ); +of_node_put (bus); +if (!panel) +return false; +of_node_put (panel); +
drivers/gpu/drm/bridge/analogix/anx7625.c static int anx7625_parse_dt(struct device *dev, · line 1686
Quoted 10 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +5
-0+return true; +} +static inline struct anx7625_data *bridge_to_anx7625 (struct drm_bridge *bridge) { return container_of(bridge, struct anx7625_data, bridge); } +static ssize_t anx7625_aux_transfer (struct drm_dp_aux *aux, +struct drm_dp_aux_msg *msg)
checkpatch --strict is unhappy about the above line not using as many tabs as possible.
Quoted 150 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +68
-8+{ + struct anx7625_data *ctx = container_of(aux, struct anx7625_data, aux); +struct device *dev = &ctx->client->dev; +u8 request = msg->request & ~DP_AUX_I2C_MOT ; +int ret =0 ; + +pm_runtime_get_sync (dev); + msg->reply =0 ; +switch (request) { +case DP_AUX_NATIVE_WRITE : +case DP_AUX_I2C_WRITE : +case DP_AUX_NATIVE_READ : +case DP_AUX_I2C_READ : +break ; +default : + ret = -EINVAL ; + } +if (!ret) + ret =anx7625_aux_trans (ctx, msg->request, msg->address, + msg->size, msg->buffer); +pm_runtime_mark_last_busy (dev); +pm_runtime_put_autosuspend (dev); + +return ret; +} +static struct edid *anx7625_get_edid (struct anx7625_data *ctx) {struct device *dev = &ctx->client->dev;@@ -2066,6 +2116,13 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,return -ENODEV ; } + ctx->aux.drm_dev = bridge->dev; + err =drm_dp_aux_register (&ctx->aux); +if (err) { +dev_err (dev,"failed to register aux channel: %d\n" , err); +return err; + } +if (ctx->pdata.panel_bridge) { err = drm_bridge_attach(bridge->encoder, ctx->pdata.panel_bridge,@@ -2079,6 +2136,13 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,return 0 ; } +static void anx7625_bridge_detach (struct drm_bridge *bridge) +{ +struct anx7625_data *ctx =bridge_to_anx7625 (bridge); + +drm_dp_aux_unregister (&ctx->aux); +} + static enum drm_mode_status anx7625_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info,@@ -2344,6 +2408,7 @@ static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge,static const struct drm_bridge_funcs anx7625_bridge_funcs = { .attach = anx7625_bridge_attach, + .detach = anx7625_bridge_detach, .mode_valid = anx7625_bridge_mode_valid, .mode_set = anx7625_bridge_mode_set, .atomic_check = anx7625_bridge_atomic_check,@@ -2501,6 +2566,12 @@ static const struct dev_pm_ops anx7625_pm_ops = { anx7625_runtime_pm_resume, NULL) }; +static void anx7625_runtime_disable (void *data) +{ +pm_runtime_dont_use_autosuspend (data); +pm_runtime_disable (data); +} +static int anx7625_i2c_probe (struct i2c_client *client,const struct i2c_device_id *id) {@@ -2523,13 +2594,6 @@ static int anx7625_i2c_probe(struct i2c_client *client, pdata = &platform->pdata; - ret =anx7625_parse_dt (dev, pdata); -if (ret) { -if (ret != -EPROBE_DEFER ) -DRM_DEV_ERROR (dev,"fail to parse DT : %d\n" , ret); -return ret; - } - platform->client = client;i2c_set_clientdata (client, platform);@@ -2577,6 +2641,19 @@ static int anx7625_i2c_probe(struct i2c_client *client, } } + platform->aux.name ="anx7625-aux" ; + platform->aux.dev = dev; + platform->aux.transfer = anx7625_aux_transfer; +drm_dp_aux_init (&platform->aux); +devm_of_dp_aux_populate_ep_devices (&platform->aux); + + ret =anx7625_parse_dt (dev, pdata); +if (ret) { +if (ret != -EPROBE_DEFER ) +DRM_DEV_ERROR (dev,"fail to parse DT : %d\n" , ret); +return ret; + } +if (anx7625_register_i2c_dummy_clients (platform, client) !=0 ) { ret = -ENOMEM ;DRM_DEV_ERROR (dev,"fail to reserve I2C bus.\n" );@@ -2584,6 +2661,12 @@ static int anx7625_i2c_probe(struct i2c_client *client, }pm_runtime_enable (dev); +pm_runtime_set_autosuspend_delay (dev,1000 ); +pm_runtime_use_autosuspend (dev); +pm_suspend_ignore_children (dev, true); + ret =devm_add_action_or_reset (dev, anx7625_runtime_disable, dev); +if (ret) +return ret;if (!platform->pdata.low_power_mode) {anx7625_disable_pd_protocol (platform);@@ -2596,7 +2679,8 @@ static int anx7625_i2c_probe(struct i2c_client *client, platform->bridge.funcs = &anx7625_bridge_funcs; platform->bridge.of_node = client->dev.of_node; - platform->bridge.ops =DRM_BRIDGE_OP_EDID ; +if (!anx7625_of_panel_on_aux_bus (&client->dev)) + platform->bridge.ops |=DRM_BRIDGE_OP_EDID ;if (!platform->pdata.panel_bridge) platform->bridge.ops |=DRM_BRIDGE_OP_HPD |DRM_BRIDGE_OP_DETECT ;drivers/gpu/drm/bridge/analogix/anx7625.h +1
-1@@ -472,6 +472,7 @@ struct anx7625_data {u8 bridge_attached;struct drm_connector *connector;struct mipi_dsi_device *dsi; + struct drm_dp_aux aux; };#endif /* __ANX7625_H__ */ --2.34.1.703.g22d0c6ccf7-goog
PATCH v4 4/4 dt-bindings: drm/bridge: anx7625: Add aux-bus node
In reply to Hsin-Yi WangList panel under aux-bus node if it's connected to anx7625's aux bus.
--- .../display/bridge/analogix,anx7625.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +17 -0
@@ -83,6 +83,9 @@ properties: type: boolean description: let the driver enable audio HDMI codec function or not. + aux-bus: + $ref: /schemas/display/dp-aux-bus.yaml# + ports: $ref: /schemas/graph.yaml#/properties/ports
@@ -167,5 +170,19 @@ examples: }; }; }; + + aux-bus { + panel { + compatible = "innolux,n125hce-gn1"; + power-supply = <&pp3300_disp_x>; + backlight = <&backlight_lcd0>; + + port { + panel_in: endpoint { + remote-endpoint = <&anx7625_out>; + }; + }; + }; + }; }; };
Signature · 1 line
2.34.1.703.g22d0c6ccf7-goog