1*013413cdSMasahiro Yamada // SPDX-License-Identifier: GPL-2.0+ 2*013413cdSMasahiro Yamada 3*013413cdSMasahiro Yamada /* 4*013413cdSMasahiro Yamada * Copyright 2020 NXP 5*013413cdSMasahiro Yamada */ 6*013413cdSMasahiro Yamada 7*013413cdSMasahiro Yamada #include <linux/clk.h> 8*013413cdSMasahiro Yamada #include <linux/media-bus-format.h> 9*013413cdSMasahiro Yamada #include <linux/mfd/syscon.h> 10*013413cdSMasahiro Yamada #include <linux/module.h> 11*013413cdSMasahiro Yamada #include <linux/of.h> 12*013413cdSMasahiro Yamada #include <linux/of_device.h> 13*013413cdSMasahiro Yamada #include <linux/of_graph.h> 14*013413cdSMasahiro Yamada #include <linux/phy/phy.h> 15*013413cdSMasahiro Yamada #include <linux/pm_runtime.h> 16*013413cdSMasahiro Yamada #include <linux/regmap.h> 17*013413cdSMasahiro Yamada 18*013413cdSMasahiro Yamada #include <drm/drm_atomic_state_helper.h> 19*013413cdSMasahiro Yamada #include <drm/drm_bridge.h> 20*013413cdSMasahiro Yamada #include <drm/drm_connector.h> 21*013413cdSMasahiro Yamada #include <drm/drm_fourcc.h> 22*013413cdSMasahiro Yamada #include <drm/drm_of.h> 23*013413cdSMasahiro Yamada #include <drm/drm_print.h> 24*013413cdSMasahiro Yamada 25*013413cdSMasahiro Yamada #include "imx-ldb-helper.h" 26*013413cdSMasahiro Yamada 27*013413cdSMasahiro Yamada #define LDB_CH_SEL BIT(28) 28*013413cdSMasahiro Yamada 29*013413cdSMasahiro Yamada #define SS_CTRL 0x20 30*013413cdSMasahiro Yamada #define CH_HSYNC_M(id) BIT(0 + ((id) * 2)) 31*013413cdSMasahiro Yamada #define CH_VSYNC_M(id) BIT(1 + ((id) * 2)) 32*013413cdSMasahiro Yamada #define CH_PHSYNC(id) BIT(0 + ((id) * 2)) 33*013413cdSMasahiro Yamada #define CH_PVSYNC(id) BIT(1 + ((id) * 2)) 34*013413cdSMasahiro Yamada 35*013413cdSMasahiro Yamada #define DRIVER_NAME "imx8qxp-ldb" 36*013413cdSMasahiro Yamada 37*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel { 38*013413cdSMasahiro Yamada struct ldb_channel base; 39*013413cdSMasahiro Yamada struct phy *phy; 40*013413cdSMasahiro Yamada unsigned int di_id; 41*013413cdSMasahiro Yamada }; 42*013413cdSMasahiro Yamada 43*013413cdSMasahiro Yamada struct imx8qxp_ldb { 44*013413cdSMasahiro Yamada struct ldb base; 45*013413cdSMasahiro Yamada struct device *dev; 46*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel channel[MAX_LDB_CHAN_NUM]; 47*013413cdSMasahiro Yamada struct clk *clk_pixel; 48*013413cdSMasahiro Yamada struct clk *clk_bypass; 49*013413cdSMasahiro Yamada struct drm_bridge *companion; 50*013413cdSMasahiro Yamada int active_chno; 51*013413cdSMasahiro Yamada }; 52*013413cdSMasahiro Yamada 53*013413cdSMasahiro Yamada static inline struct imx8qxp_ldb_channel * 54*013413cdSMasahiro Yamada base_to_imx8qxp_ldb_channel(struct ldb_channel *base) 55*013413cdSMasahiro Yamada { 56*013413cdSMasahiro Yamada return container_of(base, struct imx8qxp_ldb_channel, base); 57*013413cdSMasahiro Yamada } 58*013413cdSMasahiro Yamada 59*013413cdSMasahiro Yamada static inline struct imx8qxp_ldb *base_to_imx8qxp_ldb(struct ldb *base) 60*013413cdSMasahiro Yamada { 61*013413cdSMasahiro Yamada return container_of(base, struct imx8qxp_ldb, base); 62*013413cdSMasahiro Yamada } 63*013413cdSMasahiro Yamada 64*013413cdSMasahiro Yamada static void imx8qxp_ldb_set_phy_cfg(struct imx8qxp_ldb *imx8qxp_ldb, 65*013413cdSMasahiro Yamada unsigned long di_clk, bool is_split, 66*013413cdSMasahiro Yamada struct phy_configure_opts_lvds *phy_cfg) 67*013413cdSMasahiro Yamada { 68*013413cdSMasahiro Yamada phy_cfg->bits_per_lane_and_dclk_cycle = 7; 69*013413cdSMasahiro Yamada phy_cfg->lanes = 4; 70*013413cdSMasahiro Yamada 71*013413cdSMasahiro Yamada if (is_split) { 72*013413cdSMasahiro Yamada phy_cfg->differential_clk_rate = di_clk / 2; 73*013413cdSMasahiro Yamada phy_cfg->is_slave = !imx8qxp_ldb->companion; 74*013413cdSMasahiro Yamada } else { 75*013413cdSMasahiro Yamada phy_cfg->differential_clk_rate = di_clk; 76*013413cdSMasahiro Yamada phy_cfg->is_slave = false; 77*013413cdSMasahiro Yamada } 78*013413cdSMasahiro Yamada } 79*013413cdSMasahiro Yamada 80*013413cdSMasahiro Yamada static int 81*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_atomic_check(struct drm_bridge *bridge, 82*013413cdSMasahiro Yamada struct drm_bridge_state *bridge_state, 83*013413cdSMasahiro Yamada struct drm_crtc_state *crtc_state, 84*013413cdSMasahiro Yamada struct drm_connector_state *conn_state) 85*013413cdSMasahiro Yamada { 86*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch = bridge->driver_private; 87*013413cdSMasahiro Yamada struct ldb *ldb = ldb_ch->ldb; 88*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = 89*013413cdSMasahiro Yamada base_to_imx8qxp_ldb_channel(ldb_ch); 90*013413cdSMasahiro Yamada struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); 91*013413cdSMasahiro Yamada struct drm_bridge *companion = imx8qxp_ldb->companion; 92*013413cdSMasahiro Yamada struct drm_display_mode *adj = &crtc_state->adjusted_mode; 93*013413cdSMasahiro Yamada unsigned long di_clk = adj->clock * 1000; 94*013413cdSMasahiro Yamada bool is_split = ldb_channel_is_split_link(ldb_ch); 95*013413cdSMasahiro Yamada union phy_configure_opts opts = { }; 96*013413cdSMasahiro Yamada struct phy_configure_opts_lvds *phy_cfg = &opts.lvds; 97*013413cdSMasahiro Yamada int ret; 98*013413cdSMasahiro Yamada 99*013413cdSMasahiro Yamada ret = ldb_bridge_atomic_check_helper(bridge, bridge_state, 100*013413cdSMasahiro Yamada crtc_state, conn_state); 101*013413cdSMasahiro Yamada if (ret) 102*013413cdSMasahiro Yamada return ret; 103*013413cdSMasahiro Yamada 104*013413cdSMasahiro Yamada imx8qxp_ldb_set_phy_cfg(imx8qxp_ldb, di_clk, is_split, phy_cfg); 105*013413cdSMasahiro Yamada ret = phy_validate(imx8qxp_ldb_ch->phy, PHY_MODE_LVDS, 0, &opts); 106*013413cdSMasahiro Yamada if (ret < 0) { 107*013413cdSMasahiro Yamada DRM_DEV_DEBUG_DRIVER(imx8qxp_ldb->dev, 108*013413cdSMasahiro Yamada "failed to validate PHY: %d\n", ret); 109*013413cdSMasahiro Yamada return ret; 110*013413cdSMasahiro Yamada } 111*013413cdSMasahiro Yamada 112*013413cdSMasahiro Yamada if (is_split && companion) { 113*013413cdSMasahiro Yamada ret = companion->funcs->atomic_check(companion, 114*013413cdSMasahiro Yamada bridge_state, crtc_state, conn_state); 115*013413cdSMasahiro Yamada if (ret) 116*013413cdSMasahiro Yamada return ret; 117*013413cdSMasahiro Yamada } 118*013413cdSMasahiro Yamada 119*013413cdSMasahiro Yamada return ret; 120*013413cdSMasahiro Yamada } 121*013413cdSMasahiro Yamada 122*013413cdSMasahiro Yamada static void 123*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_mode_set(struct drm_bridge *bridge, 124*013413cdSMasahiro Yamada const struct drm_display_mode *mode, 125*013413cdSMasahiro Yamada const struct drm_display_mode *adjusted_mode) 126*013413cdSMasahiro Yamada { 127*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch = bridge->driver_private; 128*013413cdSMasahiro Yamada struct ldb_channel *companion_ldb_ch; 129*013413cdSMasahiro Yamada struct ldb *ldb = ldb_ch->ldb; 130*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = 131*013413cdSMasahiro Yamada base_to_imx8qxp_ldb_channel(ldb_ch); 132*013413cdSMasahiro Yamada struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); 133*013413cdSMasahiro Yamada struct drm_bridge *companion = imx8qxp_ldb->companion; 134*013413cdSMasahiro Yamada struct device *dev = imx8qxp_ldb->dev; 135*013413cdSMasahiro Yamada unsigned long di_clk = adjusted_mode->clock * 1000; 136*013413cdSMasahiro Yamada bool is_split = ldb_channel_is_split_link(ldb_ch); 137*013413cdSMasahiro Yamada union phy_configure_opts opts = { }; 138*013413cdSMasahiro Yamada struct phy_configure_opts_lvds *phy_cfg = &opts.lvds; 139*013413cdSMasahiro Yamada u32 chno = ldb_ch->chno; 140*013413cdSMasahiro Yamada int ret; 141*013413cdSMasahiro Yamada 142*013413cdSMasahiro Yamada ret = pm_runtime_get_sync(dev); 143*013413cdSMasahiro Yamada if (ret < 0) 144*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to get runtime PM sync: %d\n", ret); 145*013413cdSMasahiro Yamada 146*013413cdSMasahiro Yamada ret = phy_init(imx8qxp_ldb_ch->phy); 147*013413cdSMasahiro Yamada if (ret < 0) 148*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to initialize PHY: %d\n", ret); 149*013413cdSMasahiro Yamada 150*013413cdSMasahiro Yamada ret = phy_set_mode(imx8qxp_ldb_ch->phy, PHY_MODE_LVDS); 151*013413cdSMasahiro Yamada if (ret < 0) 152*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to set PHY mode: %d\n", ret); 153*013413cdSMasahiro Yamada 154*013413cdSMasahiro Yamada if (is_split && companion) { 155*013413cdSMasahiro Yamada companion_ldb_ch = bridge_to_ldb_ch(companion); 156*013413cdSMasahiro Yamada 157*013413cdSMasahiro Yamada companion_ldb_ch->in_bus_format = ldb_ch->in_bus_format; 158*013413cdSMasahiro Yamada companion_ldb_ch->out_bus_format = ldb_ch->out_bus_format; 159*013413cdSMasahiro Yamada } 160*013413cdSMasahiro Yamada 161*013413cdSMasahiro Yamada clk_set_rate(imx8qxp_ldb->clk_bypass, di_clk); 162*013413cdSMasahiro Yamada clk_set_rate(imx8qxp_ldb->clk_pixel, di_clk); 163*013413cdSMasahiro Yamada 164*013413cdSMasahiro Yamada imx8qxp_ldb_set_phy_cfg(imx8qxp_ldb, di_clk, is_split, phy_cfg); 165*013413cdSMasahiro Yamada ret = phy_configure(imx8qxp_ldb_ch->phy, &opts); 166*013413cdSMasahiro Yamada if (ret < 0) 167*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to configure PHY: %d\n", ret); 168*013413cdSMasahiro Yamada 169*013413cdSMasahiro Yamada if (chno == 0) 170*013413cdSMasahiro Yamada ldb->ldb_ctrl &= ~LDB_CH_SEL; 171*013413cdSMasahiro Yamada else 172*013413cdSMasahiro Yamada ldb->ldb_ctrl |= LDB_CH_SEL; 173*013413cdSMasahiro Yamada 174*013413cdSMasahiro Yamada /* input VSYNC signal from pixel link is active low */ 175*013413cdSMasahiro Yamada if (imx8qxp_ldb_ch->di_id == 0) 176*013413cdSMasahiro Yamada ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW; 177*013413cdSMasahiro Yamada else 178*013413cdSMasahiro Yamada ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW; 179*013413cdSMasahiro Yamada 180*013413cdSMasahiro Yamada /* 181*013413cdSMasahiro Yamada * For split mode, settle input VSYNC signal polarity and 182*013413cdSMasahiro Yamada * channel selection down early. 183*013413cdSMasahiro Yamada */ 184*013413cdSMasahiro Yamada if (is_split) 185*013413cdSMasahiro Yamada regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl); 186*013413cdSMasahiro Yamada 187*013413cdSMasahiro Yamada ldb_bridge_mode_set_helper(bridge, mode, adjusted_mode); 188*013413cdSMasahiro Yamada 189*013413cdSMasahiro Yamada if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) 190*013413cdSMasahiro Yamada regmap_update_bits(ldb->regmap, SS_CTRL, CH_VSYNC_M(chno), 0); 191*013413cdSMasahiro Yamada else if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) 192*013413cdSMasahiro Yamada regmap_update_bits(ldb->regmap, SS_CTRL, 193*013413cdSMasahiro Yamada CH_VSYNC_M(chno), CH_PVSYNC(chno)); 194*013413cdSMasahiro Yamada 195*013413cdSMasahiro Yamada if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) 196*013413cdSMasahiro Yamada regmap_update_bits(ldb->regmap, SS_CTRL, CH_HSYNC_M(chno), 0); 197*013413cdSMasahiro Yamada else if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) 198*013413cdSMasahiro Yamada regmap_update_bits(ldb->regmap, SS_CTRL, 199*013413cdSMasahiro Yamada CH_HSYNC_M(chno), CH_PHSYNC(chno)); 200*013413cdSMasahiro Yamada 201*013413cdSMasahiro Yamada if (is_split && companion) 202*013413cdSMasahiro Yamada companion->funcs->mode_set(companion, mode, adjusted_mode); 203*013413cdSMasahiro Yamada } 204*013413cdSMasahiro Yamada 205*013413cdSMasahiro Yamada static void 206*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge, 207*013413cdSMasahiro Yamada struct drm_bridge_state *old_bridge_state) 208*013413cdSMasahiro Yamada { 209*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch = bridge->driver_private; 210*013413cdSMasahiro Yamada struct ldb *ldb = ldb_ch->ldb; 211*013413cdSMasahiro Yamada struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); 212*013413cdSMasahiro Yamada struct drm_bridge *companion = imx8qxp_ldb->companion; 213*013413cdSMasahiro Yamada bool is_split = ldb_channel_is_split_link(ldb_ch); 214*013413cdSMasahiro Yamada 215*013413cdSMasahiro Yamada clk_prepare_enable(imx8qxp_ldb->clk_pixel); 216*013413cdSMasahiro Yamada clk_prepare_enable(imx8qxp_ldb->clk_bypass); 217*013413cdSMasahiro Yamada 218*013413cdSMasahiro Yamada if (is_split && companion) 219*013413cdSMasahiro Yamada companion->funcs->atomic_pre_enable(companion, old_bridge_state); 220*013413cdSMasahiro Yamada } 221*013413cdSMasahiro Yamada 222*013413cdSMasahiro Yamada static void 223*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge, 224*013413cdSMasahiro Yamada struct drm_bridge_state *old_bridge_state) 225*013413cdSMasahiro Yamada { 226*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch = bridge->driver_private; 227*013413cdSMasahiro Yamada struct ldb *ldb = ldb_ch->ldb; 228*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = 229*013413cdSMasahiro Yamada base_to_imx8qxp_ldb_channel(ldb_ch); 230*013413cdSMasahiro Yamada struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); 231*013413cdSMasahiro Yamada struct drm_bridge *companion = imx8qxp_ldb->companion; 232*013413cdSMasahiro Yamada struct device *dev = imx8qxp_ldb->dev; 233*013413cdSMasahiro Yamada bool is_split = ldb_channel_is_split_link(ldb_ch); 234*013413cdSMasahiro Yamada int ret; 235*013413cdSMasahiro Yamada 236*013413cdSMasahiro Yamada if (ldb_ch->chno == 0 || is_split) { 237*013413cdSMasahiro Yamada ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; 238*013413cdSMasahiro Yamada ldb->ldb_ctrl |= imx8qxp_ldb_ch->di_id == 0 ? 239*013413cdSMasahiro Yamada LDB_CH0_MODE_EN_TO_DI0 : LDB_CH0_MODE_EN_TO_DI1; 240*013413cdSMasahiro Yamada } 241*013413cdSMasahiro Yamada if (ldb_ch->chno == 1 || is_split) { 242*013413cdSMasahiro Yamada ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; 243*013413cdSMasahiro Yamada ldb->ldb_ctrl |= imx8qxp_ldb_ch->di_id == 0 ? 244*013413cdSMasahiro Yamada LDB_CH1_MODE_EN_TO_DI0 : LDB_CH1_MODE_EN_TO_DI1; 245*013413cdSMasahiro Yamada } 246*013413cdSMasahiro Yamada 247*013413cdSMasahiro Yamada ldb_bridge_enable_helper(bridge); 248*013413cdSMasahiro Yamada 249*013413cdSMasahiro Yamada ret = phy_power_on(imx8qxp_ldb_ch->phy); 250*013413cdSMasahiro Yamada if (ret) 251*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to power on PHY: %d\n", ret); 252*013413cdSMasahiro Yamada 253*013413cdSMasahiro Yamada if (is_split && companion) 254*013413cdSMasahiro Yamada companion->funcs->atomic_enable(companion, old_bridge_state); 255*013413cdSMasahiro Yamada } 256*013413cdSMasahiro Yamada 257*013413cdSMasahiro Yamada static void 258*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_atomic_disable(struct drm_bridge *bridge, 259*013413cdSMasahiro Yamada struct drm_bridge_state *old_bridge_state) 260*013413cdSMasahiro Yamada { 261*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch = bridge->driver_private; 262*013413cdSMasahiro Yamada struct ldb *ldb = ldb_ch->ldb; 263*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = 264*013413cdSMasahiro Yamada base_to_imx8qxp_ldb_channel(ldb_ch); 265*013413cdSMasahiro Yamada struct imx8qxp_ldb *imx8qxp_ldb = base_to_imx8qxp_ldb(ldb); 266*013413cdSMasahiro Yamada struct drm_bridge *companion = imx8qxp_ldb->companion; 267*013413cdSMasahiro Yamada struct device *dev = imx8qxp_ldb->dev; 268*013413cdSMasahiro Yamada bool is_split = ldb_channel_is_split_link(ldb_ch); 269*013413cdSMasahiro Yamada int ret; 270*013413cdSMasahiro Yamada 271*013413cdSMasahiro Yamada ret = phy_power_off(imx8qxp_ldb_ch->phy); 272*013413cdSMasahiro Yamada if (ret) 273*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to power off PHY: %d\n", ret); 274*013413cdSMasahiro Yamada 275*013413cdSMasahiro Yamada ret = phy_exit(imx8qxp_ldb_ch->phy); 276*013413cdSMasahiro Yamada if (ret < 0) 277*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to teardown PHY: %d\n", ret); 278*013413cdSMasahiro Yamada 279*013413cdSMasahiro Yamada ldb_bridge_disable_helper(bridge); 280*013413cdSMasahiro Yamada 281*013413cdSMasahiro Yamada clk_disable_unprepare(imx8qxp_ldb->clk_bypass); 282*013413cdSMasahiro Yamada clk_disable_unprepare(imx8qxp_ldb->clk_pixel); 283*013413cdSMasahiro Yamada 284*013413cdSMasahiro Yamada if (is_split && companion) 285*013413cdSMasahiro Yamada companion->funcs->atomic_disable(companion, old_bridge_state); 286*013413cdSMasahiro Yamada 287*013413cdSMasahiro Yamada ret = pm_runtime_put(dev); 288*013413cdSMasahiro Yamada if (ret < 0) 289*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to put runtime PM: %d\n", ret); 290*013413cdSMasahiro Yamada } 291*013413cdSMasahiro Yamada 292*013413cdSMasahiro Yamada static const u32 imx8qxp_ldb_bus_output_fmts[] = { 293*013413cdSMasahiro Yamada MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, 294*013413cdSMasahiro Yamada MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, 295*013413cdSMasahiro Yamada MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, 296*013413cdSMasahiro Yamada MEDIA_BUS_FMT_FIXED, 297*013413cdSMasahiro Yamada }; 298*013413cdSMasahiro Yamada 299*013413cdSMasahiro Yamada static bool imx8qxp_ldb_bus_output_fmt_supported(u32 fmt) 300*013413cdSMasahiro Yamada { 301*013413cdSMasahiro Yamada int i; 302*013413cdSMasahiro Yamada 303*013413cdSMasahiro Yamada for (i = 0; i < ARRAY_SIZE(imx8qxp_ldb_bus_output_fmts); i++) { 304*013413cdSMasahiro Yamada if (imx8qxp_ldb_bus_output_fmts[i] == fmt) 305*013413cdSMasahiro Yamada return true; 306*013413cdSMasahiro Yamada } 307*013413cdSMasahiro Yamada 308*013413cdSMasahiro Yamada return false; 309*013413cdSMasahiro Yamada } 310*013413cdSMasahiro Yamada 311*013413cdSMasahiro Yamada static u32 * 312*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, 313*013413cdSMasahiro Yamada struct drm_bridge_state *bridge_state, 314*013413cdSMasahiro Yamada struct drm_crtc_state *crtc_state, 315*013413cdSMasahiro Yamada struct drm_connector_state *conn_state, 316*013413cdSMasahiro Yamada u32 output_fmt, 317*013413cdSMasahiro Yamada unsigned int *num_input_fmts) 318*013413cdSMasahiro Yamada { 319*013413cdSMasahiro Yamada struct drm_display_info *di; 320*013413cdSMasahiro Yamada const struct drm_format_info *finfo; 321*013413cdSMasahiro Yamada u32 *input_fmts; 322*013413cdSMasahiro Yamada 323*013413cdSMasahiro Yamada if (!imx8qxp_ldb_bus_output_fmt_supported(output_fmt)) 324*013413cdSMasahiro Yamada return NULL; 325*013413cdSMasahiro Yamada 326*013413cdSMasahiro Yamada *num_input_fmts = 1; 327*013413cdSMasahiro Yamada 328*013413cdSMasahiro Yamada input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL); 329*013413cdSMasahiro Yamada if (!input_fmts) 330*013413cdSMasahiro Yamada return NULL; 331*013413cdSMasahiro Yamada 332*013413cdSMasahiro Yamada switch (output_fmt) { 333*013413cdSMasahiro Yamada case MEDIA_BUS_FMT_FIXED: 334*013413cdSMasahiro Yamada di = &conn_state->connector->display_info; 335*013413cdSMasahiro Yamada 336*013413cdSMasahiro Yamada /* 337*013413cdSMasahiro Yamada * Look at the first bus format to determine input format. 338*013413cdSMasahiro Yamada * Default to MEDIA_BUS_FMT_RGB888_1X24, if no match. 339*013413cdSMasahiro Yamada */ 340*013413cdSMasahiro Yamada if (di->num_bus_formats) { 341*013413cdSMasahiro Yamada finfo = drm_format_info(di->bus_formats[0]); 342*013413cdSMasahiro Yamada 343*013413cdSMasahiro Yamada input_fmts[0] = finfo->depth == 18 ? 344*013413cdSMasahiro Yamada MEDIA_BUS_FMT_RGB666_1X24_CPADHI : 345*013413cdSMasahiro Yamada MEDIA_BUS_FMT_RGB888_1X24; 346*013413cdSMasahiro Yamada } else { 347*013413cdSMasahiro Yamada input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; 348*013413cdSMasahiro Yamada } 349*013413cdSMasahiro Yamada break; 350*013413cdSMasahiro Yamada case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 351*013413cdSMasahiro Yamada input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; 352*013413cdSMasahiro Yamada break; 353*013413cdSMasahiro Yamada case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 354*013413cdSMasahiro Yamada case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 355*013413cdSMasahiro Yamada input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; 356*013413cdSMasahiro Yamada break; 357*013413cdSMasahiro Yamada default: 358*013413cdSMasahiro Yamada kfree(input_fmts); 359*013413cdSMasahiro Yamada input_fmts = NULL; 360*013413cdSMasahiro Yamada break; 361*013413cdSMasahiro Yamada } 362*013413cdSMasahiro Yamada 363*013413cdSMasahiro Yamada return input_fmts; 364*013413cdSMasahiro Yamada } 365*013413cdSMasahiro Yamada 366*013413cdSMasahiro Yamada static u32 * 367*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, 368*013413cdSMasahiro Yamada struct drm_bridge_state *bridge_state, 369*013413cdSMasahiro Yamada struct drm_crtc_state *crtc_state, 370*013413cdSMasahiro Yamada struct drm_connector_state *conn_state, 371*013413cdSMasahiro Yamada unsigned int *num_output_fmts) 372*013413cdSMasahiro Yamada { 373*013413cdSMasahiro Yamada *num_output_fmts = ARRAY_SIZE(imx8qxp_ldb_bus_output_fmts); 374*013413cdSMasahiro Yamada return kmemdup(imx8qxp_ldb_bus_output_fmts, 375*013413cdSMasahiro Yamada sizeof(imx8qxp_ldb_bus_output_fmts), GFP_KERNEL); 376*013413cdSMasahiro Yamada } 377*013413cdSMasahiro Yamada 378*013413cdSMasahiro Yamada static enum drm_mode_status 379*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_mode_valid(struct drm_bridge *bridge, 380*013413cdSMasahiro Yamada const struct drm_display_info *info, 381*013413cdSMasahiro Yamada const struct drm_display_mode *mode) 382*013413cdSMasahiro Yamada { 383*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch = bridge->driver_private; 384*013413cdSMasahiro Yamada bool is_single = ldb_channel_is_single_link(ldb_ch); 385*013413cdSMasahiro Yamada 386*013413cdSMasahiro Yamada if (mode->clock > 170000) 387*013413cdSMasahiro Yamada return MODE_CLOCK_HIGH; 388*013413cdSMasahiro Yamada 389*013413cdSMasahiro Yamada if (mode->clock > 150000 && is_single) 390*013413cdSMasahiro Yamada return MODE_CLOCK_HIGH; 391*013413cdSMasahiro Yamada 392*013413cdSMasahiro Yamada return MODE_OK; 393*013413cdSMasahiro Yamada } 394*013413cdSMasahiro Yamada 395*013413cdSMasahiro Yamada static const struct drm_bridge_funcs imx8qxp_ldb_bridge_funcs = { 396*013413cdSMasahiro Yamada .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 397*013413cdSMasahiro Yamada .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 398*013413cdSMasahiro Yamada .atomic_reset = drm_atomic_helper_bridge_reset, 399*013413cdSMasahiro Yamada .mode_valid = imx8qxp_ldb_bridge_mode_valid, 400*013413cdSMasahiro Yamada .attach = ldb_bridge_attach_helper, 401*013413cdSMasahiro Yamada .atomic_check = imx8qxp_ldb_bridge_atomic_check, 402*013413cdSMasahiro Yamada .mode_set = imx8qxp_ldb_bridge_mode_set, 403*013413cdSMasahiro Yamada .atomic_pre_enable = imx8qxp_ldb_bridge_atomic_pre_enable, 404*013413cdSMasahiro Yamada .atomic_enable = imx8qxp_ldb_bridge_atomic_enable, 405*013413cdSMasahiro Yamada .atomic_disable = imx8qxp_ldb_bridge_atomic_disable, 406*013413cdSMasahiro Yamada .atomic_get_input_bus_fmts = 407*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_atomic_get_input_bus_fmts, 408*013413cdSMasahiro Yamada .atomic_get_output_bus_fmts = 409*013413cdSMasahiro Yamada imx8qxp_ldb_bridge_atomic_get_output_bus_fmts, 410*013413cdSMasahiro Yamada }; 411*013413cdSMasahiro Yamada 412*013413cdSMasahiro Yamada static int imx8qxp_ldb_set_di_id(struct imx8qxp_ldb *imx8qxp_ldb) 413*013413cdSMasahiro Yamada { 414*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = 415*013413cdSMasahiro Yamada &imx8qxp_ldb->channel[imx8qxp_ldb->active_chno]; 416*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch = &imx8qxp_ldb_ch->base; 417*013413cdSMasahiro Yamada struct device_node *ep, *remote; 418*013413cdSMasahiro Yamada struct device *dev = imx8qxp_ldb->dev; 419*013413cdSMasahiro Yamada struct of_endpoint endpoint; 420*013413cdSMasahiro Yamada int ret; 421*013413cdSMasahiro Yamada 422*013413cdSMasahiro Yamada ep = of_graph_get_endpoint_by_regs(ldb_ch->np, 0, -1); 423*013413cdSMasahiro Yamada if (!ep) { 424*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to get port0 endpoint\n"); 425*013413cdSMasahiro Yamada return -EINVAL; 426*013413cdSMasahiro Yamada } 427*013413cdSMasahiro Yamada 428*013413cdSMasahiro Yamada remote = of_graph_get_remote_endpoint(ep); 429*013413cdSMasahiro Yamada of_node_put(ep); 430*013413cdSMasahiro Yamada if (!remote) { 431*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to get port0 remote endpoint\n"); 432*013413cdSMasahiro Yamada return -EINVAL; 433*013413cdSMasahiro Yamada } 434*013413cdSMasahiro Yamada 435*013413cdSMasahiro Yamada ret = of_graph_parse_endpoint(remote, &endpoint); 436*013413cdSMasahiro Yamada of_node_put(remote); 437*013413cdSMasahiro Yamada if (ret) { 438*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to parse port0 remote endpoint: %d\n", 439*013413cdSMasahiro Yamada ret); 440*013413cdSMasahiro Yamada return ret; 441*013413cdSMasahiro Yamada } 442*013413cdSMasahiro Yamada 443*013413cdSMasahiro Yamada imx8qxp_ldb_ch->di_id = endpoint.id; 444*013413cdSMasahiro Yamada 445*013413cdSMasahiro Yamada return 0; 446*013413cdSMasahiro Yamada } 447*013413cdSMasahiro Yamada 448*013413cdSMasahiro Yamada static int 449*013413cdSMasahiro Yamada imx8qxp_ldb_check_chno_and_dual_link(struct ldb_channel *ldb_ch, int link) 450*013413cdSMasahiro Yamada { 451*013413cdSMasahiro Yamada if ((link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS && ldb_ch->chno != 0) || 452*013413cdSMasahiro Yamada (link == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS && ldb_ch->chno != 1)) 453*013413cdSMasahiro Yamada return -EINVAL; 454*013413cdSMasahiro Yamada 455*013413cdSMasahiro Yamada return 0; 456*013413cdSMasahiro Yamada } 457*013413cdSMasahiro Yamada 458*013413cdSMasahiro Yamada static int imx8qxp_ldb_parse_dt_companion(struct imx8qxp_ldb *imx8qxp_ldb) 459*013413cdSMasahiro Yamada { 460*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel *imx8qxp_ldb_ch = 461*013413cdSMasahiro Yamada &imx8qxp_ldb->channel[imx8qxp_ldb->active_chno]; 462*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch = &imx8qxp_ldb_ch->base; 463*013413cdSMasahiro Yamada struct ldb_channel *companion_ldb_ch; 464*013413cdSMasahiro Yamada struct device_node *companion; 465*013413cdSMasahiro Yamada struct device_node *child; 466*013413cdSMasahiro Yamada struct device_node *companion_port = NULL; 467*013413cdSMasahiro Yamada struct device_node *port1, *port2; 468*013413cdSMasahiro Yamada struct device *dev = imx8qxp_ldb->dev; 469*013413cdSMasahiro Yamada const struct of_device_id *match; 470*013413cdSMasahiro Yamada u32 i; 471*013413cdSMasahiro Yamada int dual_link; 472*013413cdSMasahiro Yamada int ret; 473*013413cdSMasahiro Yamada 474*013413cdSMasahiro Yamada /* Locate the companion LDB for dual-link operation, if any. */ 475*013413cdSMasahiro Yamada companion = of_parse_phandle(dev->of_node, "fsl,companion-ldb", 0); 476*013413cdSMasahiro Yamada if (!companion) 477*013413cdSMasahiro Yamada return 0; 478*013413cdSMasahiro Yamada 479*013413cdSMasahiro Yamada if (!of_device_is_available(companion)) { 480*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "companion LDB is not available\n"); 481*013413cdSMasahiro Yamada ret = -ENODEV; 482*013413cdSMasahiro Yamada goto out; 483*013413cdSMasahiro Yamada } 484*013413cdSMasahiro Yamada 485*013413cdSMasahiro Yamada /* 486*013413cdSMasahiro Yamada * Sanity check: the companion bridge must have the same compatible 487*013413cdSMasahiro Yamada * string. 488*013413cdSMasahiro Yamada */ 489*013413cdSMasahiro Yamada match = of_match_device(dev->driver->of_match_table, dev); 490*013413cdSMasahiro Yamada if (!of_device_is_compatible(companion, match->compatible)) { 491*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "companion LDB is incompatible\n"); 492*013413cdSMasahiro Yamada ret = -ENXIO; 493*013413cdSMasahiro Yamada goto out; 494*013413cdSMasahiro Yamada } 495*013413cdSMasahiro Yamada 496*013413cdSMasahiro Yamada for_each_available_child_of_node(companion, child) { 497*013413cdSMasahiro Yamada ret = of_property_read_u32(child, "reg", &i); 498*013413cdSMasahiro Yamada if (ret || i > MAX_LDB_CHAN_NUM - 1) { 499*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, 500*013413cdSMasahiro Yamada "invalid channel node address: %u\n", i); 501*013413cdSMasahiro Yamada ret = -EINVAL; 502*013413cdSMasahiro Yamada of_node_put(child); 503*013413cdSMasahiro Yamada goto out; 504*013413cdSMasahiro Yamada } 505*013413cdSMasahiro Yamada 506*013413cdSMasahiro Yamada /* 507*013413cdSMasahiro Yamada * Channel numbers have to be different, because channel0 508*013413cdSMasahiro Yamada * transmits odd pixels and channel1 transmits even pixels. 509*013413cdSMasahiro Yamada */ 510*013413cdSMasahiro Yamada if (i == (ldb_ch->chno ^ 0x1)) { 511*013413cdSMasahiro Yamada companion_port = child; 512*013413cdSMasahiro Yamada break; 513*013413cdSMasahiro Yamada } 514*013413cdSMasahiro Yamada } 515*013413cdSMasahiro Yamada 516*013413cdSMasahiro Yamada if (!companion_port) { 517*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, 518*013413cdSMasahiro Yamada "failed to find companion LDB channel port\n"); 519*013413cdSMasahiro Yamada ret = -EINVAL; 520*013413cdSMasahiro Yamada goto out; 521*013413cdSMasahiro Yamada } 522*013413cdSMasahiro Yamada 523*013413cdSMasahiro Yamada /* 524*013413cdSMasahiro Yamada * We need to work out if the sink is expecting us to function in 525*013413cdSMasahiro Yamada * dual-link mode. We do this by looking at the DT port nodes we are 526*013413cdSMasahiro Yamada * connected to. If they are marked as expecting odd pixels and 527*013413cdSMasahiro Yamada * even pixels than we need to enable LDB split mode. 528*013413cdSMasahiro Yamada */ 529*013413cdSMasahiro Yamada port1 = of_graph_get_port_by_id(ldb_ch->np, 1); 530*013413cdSMasahiro Yamada port2 = of_graph_get_port_by_id(companion_port, 1); 531*013413cdSMasahiro Yamada dual_link = drm_of_lvds_get_dual_link_pixel_order(port1, port2); 532*013413cdSMasahiro Yamada of_node_put(port1); 533*013413cdSMasahiro Yamada of_node_put(port2); 534*013413cdSMasahiro Yamada 535*013413cdSMasahiro Yamada switch (dual_link) { 536*013413cdSMasahiro Yamada case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: 537*013413cdSMasahiro Yamada ldb_ch->link_type = LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS; 538*013413cdSMasahiro Yamada break; 539*013413cdSMasahiro Yamada case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: 540*013413cdSMasahiro Yamada ldb_ch->link_type = LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS; 541*013413cdSMasahiro Yamada break; 542*013413cdSMasahiro Yamada default: 543*013413cdSMasahiro Yamada ret = dual_link; 544*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, 545*013413cdSMasahiro Yamada "failed to get dual link pixel order: %d\n", ret); 546*013413cdSMasahiro Yamada goto out; 547*013413cdSMasahiro Yamada } 548*013413cdSMasahiro Yamada 549*013413cdSMasahiro Yamada ret = imx8qxp_ldb_check_chno_and_dual_link(ldb_ch, dual_link); 550*013413cdSMasahiro Yamada if (ret < 0) { 551*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, 552*013413cdSMasahiro Yamada "unmatched channel number(%u) vs dual link(%d)\n", 553*013413cdSMasahiro Yamada ldb_ch->chno, dual_link); 554*013413cdSMasahiro Yamada goto out; 555*013413cdSMasahiro Yamada } 556*013413cdSMasahiro Yamada 557*013413cdSMasahiro Yamada imx8qxp_ldb->companion = of_drm_find_bridge(companion_port); 558*013413cdSMasahiro Yamada if (!imx8qxp_ldb->companion) { 559*013413cdSMasahiro Yamada ret = -EPROBE_DEFER; 560*013413cdSMasahiro Yamada DRM_DEV_DEBUG_DRIVER(dev, 561*013413cdSMasahiro Yamada "failed to find bridge for companion bridge: %d\n", 562*013413cdSMasahiro Yamada ret); 563*013413cdSMasahiro Yamada goto out; 564*013413cdSMasahiro Yamada } 565*013413cdSMasahiro Yamada 566*013413cdSMasahiro Yamada DRM_DEV_DEBUG_DRIVER(dev, 567*013413cdSMasahiro Yamada "dual-link configuration detected (companion bridge %pOF)\n", 568*013413cdSMasahiro Yamada companion); 569*013413cdSMasahiro Yamada 570*013413cdSMasahiro Yamada companion_ldb_ch = bridge_to_ldb_ch(imx8qxp_ldb->companion); 571*013413cdSMasahiro Yamada companion_ldb_ch->link_type = ldb_ch->link_type; 572*013413cdSMasahiro Yamada out: 573*013413cdSMasahiro Yamada of_node_put(companion_port); 574*013413cdSMasahiro Yamada of_node_put(companion); 575*013413cdSMasahiro Yamada return ret; 576*013413cdSMasahiro Yamada } 577*013413cdSMasahiro Yamada 578*013413cdSMasahiro Yamada static int imx8qxp_ldb_probe(struct platform_device *pdev) 579*013413cdSMasahiro Yamada { 580*013413cdSMasahiro Yamada struct device *dev = &pdev->dev; 581*013413cdSMasahiro Yamada struct imx8qxp_ldb *imx8qxp_ldb; 582*013413cdSMasahiro Yamada struct imx8qxp_ldb_channel *imx8qxp_ldb_ch; 583*013413cdSMasahiro Yamada struct ldb *ldb; 584*013413cdSMasahiro Yamada struct ldb_channel *ldb_ch; 585*013413cdSMasahiro Yamada int ret, i; 586*013413cdSMasahiro Yamada 587*013413cdSMasahiro Yamada imx8qxp_ldb = devm_kzalloc(dev, sizeof(*imx8qxp_ldb), GFP_KERNEL); 588*013413cdSMasahiro Yamada if (!imx8qxp_ldb) 589*013413cdSMasahiro Yamada return -ENOMEM; 590*013413cdSMasahiro Yamada 591*013413cdSMasahiro Yamada imx8qxp_ldb->clk_pixel = devm_clk_get(dev, "pixel"); 592*013413cdSMasahiro Yamada if (IS_ERR(imx8qxp_ldb->clk_pixel)) { 593*013413cdSMasahiro Yamada ret = PTR_ERR(imx8qxp_ldb->clk_pixel); 594*013413cdSMasahiro Yamada if (ret != -EPROBE_DEFER) 595*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, 596*013413cdSMasahiro Yamada "failed to get pixel clock: %d\n", ret); 597*013413cdSMasahiro Yamada return ret; 598*013413cdSMasahiro Yamada } 599*013413cdSMasahiro Yamada 600*013413cdSMasahiro Yamada imx8qxp_ldb->clk_bypass = devm_clk_get(dev, "bypass"); 601*013413cdSMasahiro Yamada if (IS_ERR(imx8qxp_ldb->clk_bypass)) { 602*013413cdSMasahiro Yamada ret = PTR_ERR(imx8qxp_ldb->clk_bypass); 603*013413cdSMasahiro Yamada if (ret != -EPROBE_DEFER) 604*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, 605*013413cdSMasahiro Yamada "failed to get bypass clock: %d\n", ret); 606*013413cdSMasahiro Yamada return ret; 607*013413cdSMasahiro Yamada } 608*013413cdSMasahiro Yamada 609*013413cdSMasahiro Yamada imx8qxp_ldb->dev = dev; 610*013413cdSMasahiro Yamada 611*013413cdSMasahiro Yamada ldb = &imx8qxp_ldb->base; 612*013413cdSMasahiro Yamada ldb->dev = dev; 613*013413cdSMasahiro Yamada ldb->ctrl_reg = 0xe0; 614*013413cdSMasahiro Yamada 615*013413cdSMasahiro Yamada for (i = 0; i < MAX_LDB_CHAN_NUM; i++) 616*013413cdSMasahiro Yamada ldb->channel[i] = &imx8qxp_ldb->channel[i].base; 617*013413cdSMasahiro Yamada 618*013413cdSMasahiro Yamada ret = ldb_init_helper(ldb); 619*013413cdSMasahiro Yamada if (ret) 620*013413cdSMasahiro Yamada return ret; 621*013413cdSMasahiro Yamada 622*013413cdSMasahiro Yamada if (ldb->available_ch_cnt == 0) { 623*013413cdSMasahiro Yamada DRM_DEV_DEBUG_DRIVER(dev, "no available channel\n"); 624*013413cdSMasahiro Yamada return 0; 625*013413cdSMasahiro Yamada } else if (ldb->available_ch_cnt > 1) { 626*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "invalid available channel number(%u)\n", 627*013413cdSMasahiro Yamada ldb->available_ch_cnt); 628*013413cdSMasahiro Yamada return -EINVAL; 629*013413cdSMasahiro Yamada } 630*013413cdSMasahiro Yamada 631*013413cdSMasahiro Yamada for (i = 0; i < MAX_LDB_CHAN_NUM; i++) { 632*013413cdSMasahiro Yamada imx8qxp_ldb_ch = &imx8qxp_ldb->channel[i]; 633*013413cdSMasahiro Yamada ldb_ch = &imx8qxp_ldb_ch->base; 634*013413cdSMasahiro Yamada 635*013413cdSMasahiro Yamada if (ldb_ch->is_available) { 636*013413cdSMasahiro Yamada imx8qxp_ldb->active_chno = ldb_ch->chno; 637*013413cdSMasahiro Yamada break; 638*013413cdSMasahiro Yamada } 639*013413cdSMasahiro Yamada } 640*013413cdSMasahiro Yamada 641*013413cdSMasahiro Yamada imx8qxp_ldb_ch->phy = devm_of_phy_get(dev, ldb_ch->np, "lvds_phy"); 642*013413cdSMasahiro Yamada if (IS_ERR(imx8qxp_ldb_ch->phy)) { 643*013413cdSMasahiro Yamada ret = PTR_ERR(imx8qxp_ldb_ch->phy); 644*013413cdSMasahiro Yamada if (ret != -EPROBE_DEFER) 645*013413cdSMasahiro Yamada DRM_DEV_ERROR(dev, "failed to get channel%d PHY: %d\n", 646*013413cdSMasahiro Yamada imx8qxp_ldb->active_chno, ret); 647*013413cdSMasahiro Yamada return ret; 648*013413cdSMasahiro Yamada } 649*013413cdSMasahiro Yamada 650*013413cdSMasahiro Yamada ret = ldb_find_next_bridge_helper(ldb); 651*013413cdSMasahiro Yamada if (ret) 652*013413cdSMasahiro Yamada return ret; 653*013413cdSMasahiro Yamada 654*013413cdSMasahiro Yamada ret = imx8qxp_ldb_set_di_id(imx8qxp_ldb); 655*013413cdSMasahiro Yamada if (ret) 656*013413cdSMasahiro Yamada return ret; 657*013413cdSMasahiro Yamada 658*013413cdSMasahiro Yamada ret = imx8qxp_ldb_parse_dt_companion(imx8qxp_ldb); 659*013413cdSMasahiro Yamada if (ret) 660*013413cdSMasahiro Yamada return ret; 661*013413cdSMasahiro Yamada 662*013413cdSMasahiro Yamada platform_set_drvdata(pdev, imx8qxp_ldb); 663*013413cdSMasahiro Yamada pm_runtime_enable(dev); 664*013413cdSMasahiro Yamada 665*013413cdSMasahiro Yamada ldb_add_bridge_helper(ldb, &imx8qxp_ldb_bridge_funcs); 666*013413cdSMasahiro Yamada 667*013413cdSMasahiro Yamada return ret; 668*013413cdSMasahiro Yamada } 669*013413cdSMasahiro Yamada 670*013413cdSMasahiro Yamada static void imx8qxp_ldb_remove(struct platform_device *pdev) 671*013413cdSMasahiro Yamada { 672*013413cdSMasahiro Yamada struct imx8qxp_ldb *imx8qxp_ldb = platform_get_drvdata(pdev); 673*013413cdSMasahiro Yamada struct ldb *ldb = &imx8qxp_ldb->base; 674*013413cdSMasahiro Yamada 675*013413cdSMasahiro Yamada ldb_remove_bridge_helper(ldb); 676*013413cdSMasahiro Yamada 677*013413cdSMasahiro Yamada pm_runtime_disable(&pdev->dev); 678*013413cdSMasahiro Yamada } 679*013413cdSMasahiro Yamada 680*013413cdSMasahiro Yamada static int __maybe_unused imx8qxp_ldb_runtime_suspend(struct device *dev) 681*013413cdSMasahiro Yamada { 682*013413cdSMasahiro Yamada return 0; 683*013413cdSMasahiro Yamada } 684*013413cdSMasahiro Yamada 685*013413cdSMasahiro Yamada static int __maybe_unused imx8qxp_ldb_runtime_resume(struct device *dev) 686*013413cdSMasahiro Yamada { 687*013413cdSMasahiro Yamada struct imx8qxp_ldb *imx8qxp_ldb = dev_get_drvdata(dev); 688*013413cdSMasahiro Yamada struct ldb *ldb = &imx8qxp_ldb->base; 689*013413cdSMasahiro Yamada 690*013413cdSMasahiro Yamada /* disable LDB by resetting the control register to POR default */ 691*013413cdSMasahiro Yamada regmap_write(ldb->regmap, ldb->ctrl_reg, 0); 692*013413cdSMasahiro Yamada 693*013413cdSMasahiro Yamada return 0; 694*013413cdSMasahiro Yamada } 695*013413cdSMasahiro Yamada 696*013413cdSMasahiro Yamada static const struct dev_pm_ops imx8qxp_ldb_pm_ops = { 697*013413cdSMasahiro Yamada SET_RUNTIME_PM_OPS(imx8qxp_ldb_runtime_suspend, 698*013413cdSMasahiro Yamada imx8qxp_ldb_runtime_resume, NULL) 699*013413cdSMasahiro Yamada }; 700*013413cdSMasahiro Yamada 701*013413cdSMasahiro Yamada static const struct of_device_id imx8qxp_ldb_dt_ids[] = { 702*013413cdSMasahiro Yamada { .compatible = "fsl,imx8qxp-ldb" }, 703*013413cdSMasahiro Yamada { /* sentinel */ } 704*013413cdSMasahiro Yamada }; 705*013413cdSMasahiro Yamada MODULE_DEVICE_TABLE(of, imx8qxp_ldb_dt_ids); 706*013413cdSMasahiro Yamada 707*013413cdSMasahiro Yamada static struct platform_driver imx8qxp_ldb_driver = { 708*013413cdSMasahiro Yamada .probe = imx8qxp_ldb_probe, 709*013413cdSMasahiro Yamada .remove_new = imx8qxp_ldb_remove, 710*013413cdSMasahiro Yamada .driver = { 711*013413cdSMasahiro Yamada .pm = &imx8qxp_ldb_pm_ops, 712*013413cdSMasahiro Yamada .name = DRIVER_NAME, 713*013413cdSMasahiro Yamada .of_match_table = imx8qxp_ldb_dt_ids, 714*013413cdSMasahiro Yamada }, 715*013413cdSMasahiro Yamada }; 716*013413cdSMasahiro Yamada module_platform_driver(imx8qxp_ldb_driver); 717*013413cdSMasahiro Yamada 718*013413cdSMasahiro Yamada MODULE_DESCRIPTION("i.MX8QXP LVDS Display Bridge(LDB)/Pixel Mapper bridge driver"); 719*013413cdSMasahiro Yamada MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>"); 720*013413cdSMasahiro Yamada MODULE_LICENSE("GPL v2"); 721*013413cdSMasahiro Yamada MODULE_ALIAS("platform:" DRIVER_NAME); 722