diff --git a/drivers/gpu/drm/bridge/maxim-max96745.c b/drivers/gpu/drm/bridge/maxim-max96745.c index 9755f129f519..00bd4dc5886d 100644 --- a/drivers/gpu/drm/bridge/maxim-max96745.c +++ b/drivers/gpu/drm/bridge/maxim-max96745.c @@ -88,6 +88,23 @@ static void max96745_bridge_enable(struct drm_bridge *bridge) { struct max96745_bridge *ser = to_max96745_bridge(bridge); struct max96745 *max96745 = ser->parent; + struct drm_display_mode *mode = &bridge->encoder->crtc->state->adjusted_mode; + u8 cxtp, tx_rate; + u32 reg; + + regmap_read(ser->regmap, 0x0011, ®); + cxtp = FIELD_GET(CXTP_A, reg); + regmap_read(ser->regmap, 0x0028, ®); + tx_rate = FIELD_GET(TX_RATE, reg); + if (!cxtp && mode->clock > 95000 && tx_rate == 1) { + regmap_update_bits(ser->regmap, 0x0028, TX_RATE, + FIELD_PREP(TX_RATE, 2)); + regmap_update_bits(ser->regmap, 0x0029, RESET_ONESHOT, + FIELD_PREP(RESET_ONESHOT, 1)); + if (regmap_read_poll_timeout(ser->regmap, 0x002a, reg, + reg & LINK_LOCKED, 10000, 200000)) + dev_err(ser->dev, "%s: GMSL link not locked\n", __func__); + } if (ser->panel) drm_panel_enable(ser->panel); @@ -109,9 +126,30 @@ static void max96745_bridge_disable(struct drm_bridge *bridge) static void max96745_bridge_post_disable(struct drm_bridge *bridge) { struct max96745_bridge *ser = to_max96745_bridge(bridge); + u8 cxtp, tx_rate, link_locked; + u32 reg; + + regmap_read(ser->regmap, 0x002a, ®); + link_locked = FIELD_GET(LINK_LOCKED, reg); if (ser->panel) drm_panel_unprepare(ser->panel); + + regmap_read(ser->regmap, 0x0011, ®); + cxtp = FIELD_GET(CXTP_A, reg); + regmap_read(ser->regmap, 0x0028, ®); + tx_rate = FIELD_GET(TX_RATE, reg); + if (!cxtp && tx_rate == 2) { + regmap_update_bits(ser->regmap, 0x0028, TX_RATE, + FIELD_PREP(TX_RATE, 1)); + regmap_update_bits(ser->regmap, 0x0029, RESET_ONESHOT, + FIELD_PREP(RESET_ONESHOT, 1)); + if (link_locked) { + if (regmap_read_poll_timeout(ser->regmap, 0x002a, reg, + reg & LINK_LOCKED, 10000, 200000)) + dev_err(ser->dev, "%s: GMSL link not locked\n", __func__); + } + } } static enum drm_connector_status diff --git a/drivers/mfd/max96745.c b/drivers/mfd/max96745.c index f65ba34a3b22..e18a1b881f88 100644 --- a/drivers/mfd/max96745.c +++ b/drivers/mfd/max96745.c @@ -46,8 +46,6 @@ static bool max96745_vid_tx_active(struct max96745 *max96745) static bool max96745_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { - case 0x0028 ... 0x0029: - case 0x0032 ... 0x0033: case 0x0076: case 0x0086: case 0x0100: diff --git a/include/linux/mfd/max96745.h b/include/linux/mfd/max96745.h index f2159a23b2e8..7eef5153a760 100644 --- a/include/linux/mfd/max96745.h +++ b/include/linux/mfd/max96745.h @@ -35,6 +35,10 @@ struct max96745 { #define RESET_ALL BIT(7) #define SLEEP BIT(3) +/* 0011h */ +#define CXTP_B BIT(2) +#define CXTP_A BIT(0) + /* 0013h */ #define LOCKED BIT(3) #define ERROR BIT(2) @@ -49,6 +53,7 @@ struct max96745 { /* 0028h, 0032h */ #define LINK_EN BIT(7) +#define TX_RATE GENMASK(3, 2) /* 0029h, 0033h */ #define RESET_LINK BIT(0)