diff --git a/drivers/gpu/drm/bridge/microchip-lvds.c b/drivers/gpu/drm/bridge/microchip-lvds.c index 042e83494d8c..12fc442f9867 100644 --- a/drivers/gpu/drm/bridge/microchip-lvds.c +++ b/drivers/gpu/drm/bridge/microchip-lvds.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -40,9 +41,11 @@ /* Bitfields in LVDSC_CFGR (Configuration Register) */ #define LVDSC_CFGR_PIXSIZE_24BITS 0 +#define LVDSC_CFGR_PIXSIZE_18BITS BIT(0) #define LVDSC_CFGR_DEN_POL_HIGH 0 #define LVDSC_CFGR_DC_UNBALANCED 0 #define LVDSC_CFGR_MAPPING_JEIDA BIT(6) +#define LVDSC_CFGR_MAPPING_VESA 0 /*Bitfields in LVDSC_SR */ #define LVDSC_SR_CS BIT(0) @@ -74,9 +77,10 @@ static inline void lvds_writel(struct mchp_lvds *lvds, u32 offset, u32 val) writel_relaxed(val, lvds->regs + offset); } -static void lvds_serialiser_on(struct mchp_lvds *lvds) +static void lvds_serialiser_on(struct mchp_lvds *lvds, u32 bus_format) { unsigned long timeout = jiffies + msecs_to_jiffies(LVDS_POLL_TIMEOUT_MS); + u8 map, pix_size; /* The LVDSC registers can only be written if WPEN is cleared */ lvds_writel(lvds, LVDSC_WPMR, (LVDSC_WPMR_WPKEY_PSSWD & @@ -91,11 +95,24 @@ static void lvds_serialiser_on(struct mchp_lvds *lvds) usleep_range(1000, 2000); } + switch (bus_format) { + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + map = LVDSC_CFGR_MAPPING_JEIDA; + pix_size = LVDSC_CFGR_PIXSIZE_18BITS; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + map = LVDSC_CFGR_MAPPING_VESA; + pix_size = LVDSC_CFGR_PIXSIZE_24BITS; + break; + default: + map = LVDSC_CFGR_MAPPING_JEIDA; + pix_size = LVDSC_CFGR_PIXSIZE_24BITS; + break; + } + /* Configure the LVDSC */ - lvds_writel(lvds, LVDSC_CFGR, (LVDSC_CFGR_MAPPING_JEIDA | - LVDSC_CFGR_DC_UNBALANCED | - LVDSC_CFGR_DEN_POL_HIGH | - LVDSC_CFGR_PIXSIZE_24BITS)); + lvds_writel(lvds, LVDSC_CFGR, map | LVDSC_CFGR_DC_UNBALANCED | + LVDSC_CFGR_DEN_POL_HIGH | pix_size); /* Enable the LVDS serializer */ lvds_writel(lvds, LVDSC_CR, LVDSC_CR_SER_EN); @@ -115,6 +132,7 @@ static void mchp_lvds_atomic_enable(struct drm_bridge *bridge, struct drm_atomic_state *state) { struct mchp_lvds *lvds = bridge_to_lvds(bridge); + struct drm_connector *connector; int ret; ret = clk_prepare_enable(lvds->pclk); @@ -129,7 +147,14 @@ static void mchp_lvds_atomic_enable(struct drm_bridge *bridge, return; } - lvds_serialiser_on(lvds); + /* default to jeida-24 */ + u32 bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA; + + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (connector && connector->display_info.num_bus_formats) + bus_format = connector->display_info.bus_formats[0]; + + lvds_serialiser_on(lvds, bus_format); } static void mchp_lvds_atomic_disable(struct drm_bridge *bridge,