1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * serdes-bridge.c -- display bridge for different serdes chips 4 * 5 * Copyright (c) 2023 Rockchip Electronics Co. Ltd. 6 * 7 * Author: luowei <lw@rock-chips.com> 8 */ 9 10 #include "core.h" 11 12 static void serdes_bridge_init(struct serdes *serdes) 13 { 14 if (serdes->vpower_supply) 15 regulator_set_enable(serdes->vpower_supply, true); 16 17 if (dm_gpio_is_valid(&serdes->enable_gpio)) 18 dm_gpio_set_value(&serdes->enable_gpio, 1); 19 20 mdelay(5); 21 22 //video_bridge_set_active(serdes->dev, true); 23 24 if (serdes->chip_data->bridge_ops->init) 25 serdes->chip_data->bridge_ops->init(serdes); 26 27 serdes_i2c_set_sequence(serdes); 28 29 SERDES_DBG_MFD("%s: %s %s\n", __func__, 30 serdes->dev->name, 31 serdes->chip_data->name); 32 } 33 34 static void serdes_bridge_pre_enable(struct rockchip_bridge *bridge) 35 { 36 struct udevice *dev = bridge->dev; 37 struct serdes *serdes = dev_get_priv(dev->parent); 38 39 //serdes_bridge_init(serdes); 40 41 if (serdes->chip_data->bridge_ops->pre_enable) 42 serdes->chip_data->bridge_ops->pre_enable(serdes); 43 44 SERDES_DBG_MFD("%s: %s %s\n", __func__, 45 serdes->dev->name, 46 serdes->chip_data->name); 47 } 48 49 static void serdes_bridge_post_disable(struct rockchip_bridge *bridge) 50 { 51 struct udevice *dev = bridge->dev; 52 struct serdes *serdes = dev_get_priv(dev->parent); 53 54 if (serdes->chip_data->bridge_ops->post_disable) 55 serdes->chip_data->bridge_ops->post_disable(serdes); 56 57 SERDES_DBG_MFD("%s: %s %s\n", __func__, 58 serdes->dev->name, 59 serdes->chip_data->name); 60 } 61 62 static void serdes_bridge_enable(struct rockchip_bridge *bridge) 63 { 64 struct udevice *dev = bridge->dev; 65 struct serdes *serdes = dev_get_priv(dev->parent); 66 67 if (serdes->chip_data->serdes_type == TYPE_DES) 68 serdes_bridge_init(serdes); 69 70 if (serdes->chip_data->bridge_ops->enable) 71 serdes->chip_data->bridge_ops->enable(serdes); 72 73 SERDES_DBG_MFD("%s: %s %s\n", __func__, 74 serdes->dev->name, 75 serdes->chip_data->name); 76 } 77 78 static void serdes_bridge_disable(struct rockchip_bridge *bridge) 79 { 80 struct udevice *dev = bridge->dev; 81 struct serdes *serdes = dev_get_priv(dev->parent); 82 83 if (serdes->chip_data->bridge_ops->disable) 84 serdes->chip_data->bridge_ops->disable(serdes); 85 86 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 87 serdes->chip_data->name); 88 } 89 90 static void serdes_bridge_mode_set(struct rockchip_bridge *bridge, 91 const struct drm_display_mode *mode) 92 { 93 struct udevice *dev = bridge->dev; 94 struct serdes *serdes = dev_get_priv(dev->parent); 95 96 memcpy(&serdes->serdes_bridge->mode, mode, 97 sizeof(struct drm_display_mode)); 98 99 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 100 serdes->chip_data->name); 101 } 102 103 static bool serdes_bridge_detect(struct rockchip_bridge *bridge) 104 { 105 bool ret = true; 106 struct udevice *dev = bridge->dev; 107 struct serdes *serdes = dev_get_priv(dev->parent); 108 109 if (serdes->mcu_enable) { 110 printf("serdes %s detect link status in MCU\n", 111 serdes->dev->name); 112 return ret; 113 } 114 115 if (serdes->chip_data->bridge_ops->detect) 116 ret = serdes->chip_data->bridge_ops->detect(serdes, SER_LINKA); 117 118 SERDES_DBG_MFD("%s: %s %s %s\n", __func__, serdes->dev->name, 119 serdes->chip_data->name, (ret == true) ? "detected" : "no detected"); 120 121 return ret; 122 } 123 124 struct rockchip_bridge_funcs serdes_bridge_ops = { 125 .pre_enable = serdes_bridge_pre_enable, 126 .post_disable = serdes_bridge_post_disable, 127 .enable = serdes_bridge_enable, 128 .disable = serdes_bridge_disable, 129 .mode_set = serdes_bridge_mode_set, 130 .detect = serdes_bridge_detect, 131 }; 132 133 static int serdes_bridge_probe(struct udevice *dev) 134 { 135 struct rockchip_bridge *bridge; 136 struct serdes *serdes = dev_get_priv(dev->parent); 137 struct mipi_dsi_device *device = dev_get_platdata(dev); 138 139 if (!serdes->chip_data->bridge_ops) { 140 SERDES_DBG_MFD("%s %s no bridge ops\n", 141 __func__, serdes->chip_data->name); 142 return 0; 143 } 144 145 serdes->sel_mipi = dev_read_bool(dev->parent, "sel-mipi"); 146 if (serdes->sel_mipi) { 147 device->dev = dev; 148 device->lanes = dev_read_u32_default(dev->parent, "dsi,lanes", 4); 149 device->format = dev_read_u32_default(dev->parent, "dsi,format", 150 MIPI_DSI_FMT_RGB888); 151 device->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; 152 device->channel = dev_read_u32_default(dev->parent, "reg", 0); 153 } 154 155 bridge = calloc(1, sizeof(*bridge)); 156 if (!bridge) 157 return -ENOMEM; 158 159 dev->driver_data = (ulong)bridge; 160 bridge->dev = dev; 161 bridge->funcs = &serdes_bridge_ops; 162 163 serdes->serdes_bridge->bridge = bridge; 164 165 SERDES_DBG_MFD("%s: %s %s bridge=%p name=%s device=%p\n", 166 __func__, serdes->dev->name, 167 serdes->chip_data->name, 168 bridge, bridge->dev->name, device); 169 170 return 0; 171 } 172 173 static const struct udevice_id serdes_of_match[] = { 174 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82) 175 { .compatible = "rohm,bu18tl82-bridge", }, 176 #endif 177 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82) 178 { .compatible = "rohm,bu18rl82-bridge", }, 179 #endif 180 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) 181 { .compatible = "maxim,max96745-bridge", }, 182 #endif 183 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) 184 { .compatible = "maxim,max96755-bridge", }, 185 #endif 186 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) 187 { .compatible = "maxim,max96789-bridge", }, 188 #endif 189 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111) 190 { .compatible = "rockchip,rkx111-bridge", }, 191 #endif 192 { } 193 }; 194 195 U_BOOT_DRIVER(serdes_bridge) = { 196 .name = "serdes-bridge", 197 .id = UCLASS_VIDEO_BRIDGE, 198 .of_match = serdes_of_match, 199 .probe = serdes_bridge_probe, 200 .priv_auto_alloc_size = sizeof(struct serdes_bridge), 201 .platdata_auto_alloc_size = sizeof(struct mipi_dsi_device), 202 }; 203