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