Hi Dmity, thanks for the patch, it is OK for me. Reviewed-by: Xin Ji <[email protected]>
> Swapping the data role requires sending the message to the other USB-C side. > Implement sending these messages through the OCM. The code is largely > based on the anx7411.c USB-C driver. > > Signed-off-by: Dmitry Baryshkov <[email protected]> > --- > drivers/gpu/drm/bridge/analogix/anx7625.c | 68 > +++++++++++++++++++++++++++++++ > drivers/gpu/drm/bridge/analogix/anx7625.h | 12 ++++++ > 2 files changed, 80 insertions(+) > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c > b/drivers/gpu/drm/bridge/analogix/anx7625.c > index 8dc6e3b16968..c43519097a45 100644 > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c > @@ -1484,6 +1484,73 @@ static void anx7625_start_dp_work(struct > anx7625_data *ctx) } > > #if IS_REACHABLE(CONFIG_TYPEC) > +static u8 anx7625_checksum(u8 *buf, u8 len) { > + u8 ret = 0; > + u8 i; > + > + for (i = 0; i < len; i++) > + ret += buf[i]; > + > + return ret; > +} > + > +static int anx7625_read_msg_ctrl_status(struct anx7625_data *ctx) { > + return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, > CMD_SEND_BUF); } > + > +static int anx7625_wait_msg_empty(struct anx7625_data *ctx) { > + int val; > + > + return readx_poll_timeout(anx7625_read_msg_ctrl_status, ctx, > + val, (val < 0) || (val == 0), > + 2000, 2000 * 150); > +} > + > +static int anx7625_send_msg(struct anx7625_data *ctx, u8 type, u8 *buf, > +u8 size) { > + struct fw_msg *msg = &ctx->send_msg; > + u8 crc; > + int ret; > + > + size = min_t(u8, size, (u8)MAX_BUF_LEN); > + memcpy(msg->buf, buf, size); > + msg->msg_type = type; > + > + /* msg len equals buffer length + msg_type */ > + msg->msg_len = size + 1; > + > + crc = anx7625_checksum((u8 *)msg, size + HEADER_LEN); > + msg->buf[size] = 0 - crc; > + > + ret = anx7625_wait_msg_empty(ctx); > + if (ret) > + return ret; > + > + ret = anx7625_reg_block_write(ctx, ctx->i2c.rx_p0_client, > + CMD_SEND_BUF + 1, size + HEADER_LEN, > + &msg->msg_type); > + ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client, CMD_SEND_BUF, > + msg->msg_len); > + return ret; > +} > + > +static int anx7625_typec_dr_set(struct typec_port *port, enum > +typec_data_role role) { > + struct anx7625_data *ctx = typec_get_drvdata(port); > + > + if (role == ctx->typec_data_role) > + return 0; > + > + return anx7625_send_msg(ctx, 0x11, NULL, 0); } > + > +static const struct typec_operations anx7625_typec_ops = { > + .dr_set = anx7625_typec_dr_set, > +}; > + > static void anx7625_typec_set_orientation(struct anx7625_data *ctx) { > u32 val = anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, > SYSTEM_STSTUS); @@ -1542,6 +1609,7 @@ static int > anx7625_typec_register(struct anx7625_data *ctx) > typec_cap.orientation_aware = true; > > typec_cap.driver_data = ctx; > + typec_cap.ops = &anx7625_typec_ops; > > ctx->typec_port = typec_register_port(ctx->dev, &typec_cap); > if (IS_ERR(ctx->typec_port)) > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h > b/drivers/gpu/drm/bridge/analogix/anx7625.h > index a18561c213af..957d234ec07c 100644 > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h > @@ -67,6 +67,9 @@ > #define CC2_RA BIT(5) > #define CC2_RP (BIT(6) | BIT(7)) > > +#define CMD_SEND_BUF 0xC0 > +#define CMD_RECV_BUF 0xE0 > + > /******** END of I2C Address 0x58 ********/ > > > /*************************************************************** > / > @@ -462,6 +465,14 @@ struct anx7625_i2c_client { struct typec_port; struct > usb_role_switch; > > +#define MAX_BUF_LEN 30 > +struct fw_msg { > + u8 msg_len; > + u8 msg_type; > + u8 buf[MAX_BUF_LEN]; > +} __packed; > +#define HEADER_LEN 2 > + > struct anx7625_data { > struct anx7625_platform_data pdata; > struct platform_device *audio_pdev; > @@ -497,6 +508,7 @@ struct anx7625_data { > struct drm_connector *connector; > struct mipi_dsi_device *dsi; > struct drm_dp_aux aux; > + struct fw_msg send_msg; > }; > > #endif /* __ANX7625_H__ */ > > -- > 2.47.3
