1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2022 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <i2c.h> 10 #include <max96755f.h> 11 #include <video_bridge.h> 12 #include <dm/of_access.h> 13 #include <linux/media-bus-format.h> 14 15 #include "rockchip_bridge.h" 16 #include "rockchip_display.h" 17 #include "rockchip_panel.h" 18 19 static void max96755f_mipi_dsi_rx_config(struct max96755f_priv *priv) 20 { 21 struct drm_display_mode *mode = &priv->mode; 22 u32 hfp, hsa, hbp, hact; 23 u32 vact, vsa, vfp, vbp; 24 25 dm_i2c_reg_clrset(priv->dev, 0x0331, NUM_LANES, 26 FIELD_PREP(NUM_LANES, priv->num_lanes - 1)); 27 if (!priv->dpi_deskew_en) 28 return; 29 30 vact = mode->vdisplay; 31 vsa = mode->vsync_end - mode->vsync_start; 32 vfp = mode->vsync_start - mode->vdisplay; 33 vbp = mode->vtotal - mode->vsync_end; 34 hact = mode->hdisplay; 35 hsa = mode->hsync_end - mode->hsync_start; 36 hfp = mode->hsync_start - mode->hdisplay; 37 hbp = mode->htotal - mode->hsync_end; 38 dm_i2c_reg_write(priv->dev, 0x03A4, 0xc1); 39 dm_i2c_reg_write(priv->dev, 0x0385, FIELD_PREP(DPI_HSYNC_WIDTH_L, hsa)); 40 dm_i2c_reg_write(priv->dev, 0x0386, FIELD_PREP(DPI_VYSNC_WIDTH_L, vsa)); 41 dm_i2c_reg_write(priv->dev, 0x0387, 42 FIELD_PREP(DPI_VSYNC_WIDTH_H, (vsa >> 8)) | 43 FIELD_PREP(DPI_HSYNC_WIDTH_H, (hsa >> 8))); 44 dm_i2c_reg_write(priv->dev, 0x03a5, FIELD_PREP(DPI_VFP_L, vfp)); 45 dm_i2c_reg_write(priv->dev, 0x03a6, 46 FIELD_PREP(DPI_VBP_L, vbp) | 47 FIELD_PREP(DPI_VFP_H, (vfp >> 8))); 48 dm_i2c_reg_write(priv->dev, 0x03a7, FIELD_PREP(DPI_VBP_H, (vbp >> 4))); 49 dm_i2c_reg_write(priv->dev, 0x03a8, FIELD_PREP(DPI_VACT_L, vact)); 50 dm_i2c_reg_write(priv->dev, 0x03a9, FIELD_PREP(DPI_VACT_H, (vact >> 8))); 51 dm_i2c_reg_write(priv->dev, 0x03aa, FIELD_PREP(DPI_HFP_L, hfp)); 52 dm_i2c_reg_write(priv->dev, 0x03ab, 53 FIELD_PREP(DPI_HBP_L, hbp) | 54 FIELD_PREP(DPI_HFP_H, (hfp >> 7))); 55 dm_i2c_reg_write(priv->dev, 0x03ac, FIELD_PREP(DPI_HBP_H, (hbp >> 4))); 56 dm_i2c_reg_write(priv->dev, 0x03ad, FIELD_PREP(DPI_HACT_L, hact)); 57 dm_i2c_reg_write(priv->dev, 0x03ae, FIELD_PREP(DPI_HACT_H, (hact >> 8))); 58 } 59 60 static void max96755f_bridge_enable(struct rockchip_bridge *bridge) 61 { 62 struct udevice *dev = bridge->dev; 63 struct max96755f_priv *priv = dev_get_priv(dev->parent); 64 65 max96755f_mipi_dsi_rx_config(priv); 66 if (priv->split_mode) { 67 dm_i2c_reg_clrset(dev->parent, 0x0010, 68 RESET_ONESHOT | AUTO_LINK | LINK_CFG, 69 FIELD_PREP(RESET_ONESHOT, 1) | 70 FIELD_PREP(AUTO_LINK, 0) | 71 FIELD_PREP(LINK_CFG, SPLITTER_MODE)); 72 mdelay(50); 73 dm_i2c_reg_clrset(dev->parent, 0x0053, 74 TX_SPLIT_MASK_B | TX_SPLIT_MASK_A | TX_STR_SEL, 75 FIELD_PREP(TX_SPLIT_MASK_B, 0) | 76 FIELD_PREP(TX_SPLIT_MASK_A, 1) | 77 FIELD_PREP(TX_STR_SEL, 0)); 78 dm_i2c_reg_clrset(dev->parent, 0x0057, 79 TX_SPLIT_MASK_B | TX_SPLIT_MASK_A | TX_STR_SEL, 80 FIELD_PREP(TX_SPLIT_MASK_B, 1) | 81 FIELD_PREP(TX_SPLIT_MASK_A, 0) | 82 FIELD_PREP(TX_STR_SEL, 1)); 83 dm_i2c_reg_clrset(dev->parent, 0x032a, 84 DV_SWP_AB | DV_CONV | DV_SPL | DV_EN, 85 FIELD_PREP(DV_SWP_AB, priv->dv_swp_ab) | 86 FIELD_PREP(DV_CONV, 1) | 87 FIELD_PREP(DV_SPL, 1) | 88 FIELD_PREP(DV_EN, 1)); 89 dm_i2c_reg_clrset(dev->parent, 0x0311, 90 START_PORTAX | START_PORTAY, 91 FIELD_PREP(START_PORTAX, 1) | 92 FIELD_PREP(START_PORTAY, 1)); 93 dm_i2c_reg_clrset(dev->parent, 0x0002, 94 VID_TX_EN_X | VID_TX_EN_Y, 95 FIELD_PREP(VID_TX_EN_X, 1) | 96 FIELD_PREP(VID_TX_EN_Y, 1)); 97 98 } else { 99 dm_i2c_reg_clrset(dev->parent, 0x0002, VID_TX_EN_X, 100 FIELD_PREP(VID_TX_EN_X, 1)); 101 dm_i2c_reg_clrset(dev->parent, 0x0311, START_PORTAX, 102 FIELD_PREP(START_PORTAX, 1)); 103 } 104 105 dm_i2c_reg_clrset(dev->parent, 0x0010, RESET_ONESHOT, 106 FIELD_PREP(RESET_ONESHOT, 1)); 107 mdelay(100); 108 } 109 110 static void max96755f_bridge_disable(struct rockchip_bridge *bridge) 111 { 112 struct udevice *dev = bridge->dev; 113 struct max96755f_priv *priv = dev_get_priv(dev->parent); 114 115 dm_i2c_reg_clrset(dev->parent, 0x0002, VID_TX_EN_X, 116 FIELD_PREP(VID_TX_EN_X, 0)); 117 118 if (priv->split_mode) 119 dm_i2c_reg_clrset(dev->parent, 0x0010, 120 AUTO_LINK | LINK_CFG, 121 FIELD_PREP(AUTO_LINK, 0) | 122 FIELD_PREP(LINK_CFG, LINKA)); 123 } 124 125 static void max96755f_bridge_mode_set(struct rockchip_bridge *bridge, 126 const struct drm_display_mode *mode) 127 { 128 struct udevice *dev = bridge->dev; 129 struct max96755f_priv *priv = dev_get_priv(dev->parent); 130 131 memcpy(&priv->mode, mode, sizeof(struct drm_display_mode)); 132 } 133 134 static bool max96755f_bridge_detect(struct rockchip_bridge *bridge) 135 { 136 struct max96755f_priv *priv = dev_get_priv(bridge->dev->parent); 137 138 if (!dm_gpio_get_value(&priv->lock_gpio)) 139 return false; 140 141 return true; 142 } 143 144 static const struct rockchip_bridge_funcs max96755f_bridge_funcs = { 145 .enable = max96755f_bridge_enable, 146 .disable = max96755f_bridge_disable, 147 .mode_set = max96755f_bridge_mode_set, 148 .detect = max96755f_bridge_detect, 149 }; 150 151 static int max96755f_bridge_probe(struct udevice *dev) 152 { 153 struct rockchip_bridge *bridge; 154 struct max96755f_priv *priv = dev_get_priv(dev->parent); 155 int ret; 156 157 bridge = calloc(1, sizeof(*bridge)); 158 if (!bridge) 159 return -ENOMEM; 160 161 dev->driver_data = (ulong)bridge; 162 bridge->dev = dev; 163 bridge->funcs = &max96755f_bridge_funcs; 164 165 priv->num_lanes = dev_read_u32_default(dev, "dsi,lanes", 4); 166 priv->dv_swp_ab = dev_read_bool(dev, "vd-swap-ab"); 167 priv->dpi_deskew_en = dev_read_bool(dev, "dpi-deskew-en"); 168 169 ret = gpio_request_by_name(dev, "lock-gpios", 0, &priv->lock_gpio, 170 GPIOD_IS_IN); 171 if (ret) { 172 dev_err(dev, "failed to get lock GPIO: %d\n", ret); 173 return ret; 174 } 175 176 return 0; 177 } 178 179 static const struct udevice_id max96755f_bridge_of_match[] = { 180 { .compatible = "maxim,max96755f-bridge", }, 181 { } 182 }; 183 184 U_BOOT_DRIVER(max96755f_bridge) = { 185 .name = "max96755f_bridge", 186 .id = UCLASS_VIDEO_BRIDGE, 187 .of_match = max96755f_bridge_of_match, 188 .probe = max96755f_bridge_probe, 189 }; 190