1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * serdes-panel.c -- display panel 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_panel_split_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 if (serdes->chip_data->panel_ops->init) 23 serdes->chip_data->panel_ops->init(serdes); 24 25 if (serdes->chip_data->serdes_type == TYPE_DES) 26 serdes_i2c_set_sequence(serdes); 27 28 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 29 serdes->chip_data->name); 30 } 31 32 static void serdes_panel_split_prepare(struct rockchip_panel *panel) 33 { 34 struct udevice *dev = panel->dev; 35 struct serdes *serdes = dev_get_priv(dev->parent); 36 37 if (serdes->chip_data->panel_ops->prepare) 38 serdes->chip_data->panel_ops->prepare(serdes); 39 40 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 41 serdes->chip_data->name); 42 } 43 44 static void serdes_panel_split_unprepare(struct rockchip_panel *panel) 45 { 46 struct udevice *dev = panel->dev; 47 struct serdes *serdes = dev_get_priv(dev->parent); 48 49 if (serdes->chip_data->panel_ops->unprepare) 50 serdes->chip_data->panel_ops->unprepare(serdes); 51 52 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 53 serdes->chip_data->name); 54 } 55 56 static void serdes_panel_split_enable(struct rockchip_panel *panel) 57 { 58 struct udevice *dev = panel->dev; 59 struct serdes *serdes = dev_get_priv(dev->parent); 60 61 if (serdes->chip_data->panel_ops->enable) 62 serdes->chip_data->panel_ops->enable(serdes); 63 64 serdes_panel_split_init(serdes); 65 66 if (serdes->serdes_panel_split->backlight) 67 backlight_enable(serdes->serdes_panel_split->backlight); 68 69 if (serdes->chip_data->panel_ops->backlight_enable) 70 serdes->chip_data->panel_ops->backlight_enable(serdes); 71 72 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 73 serdes->chip_data->name); 74 } 75 76 static void serdes_panel_split_disable(struct rockchip_panel *panel) 77 { 78 struct udevice *dev = panel->dev; 79 struct serdes *serdes = dev_get_priv(dev->parent); 80 81 if (serdes->chip_data->panel_ops->backlight_disable) 82 serdes->chip_data->panel_ops->backlight_disable(serdes); 83 84 if (serdes->serdes_panel_split->backlight) 85 backlight_disable(serdes->serdes_panel_split->backlight); 86 87 if (serdes->chip_data->panel_ops->disable) 88 serdes->chip_data->panel_ops->disable(serdes); 89 90 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 91 serdes->chip_data->name); 92 } 93 94 static struct rockchip_panel_funcs serdes_panel_split_ops = { 95 .prepare = serdes_panel_split_prepare, 96 .unprepare = serdes_panel_split_unprepare, 97 .enable = serdes_panel_split_enable, 98 .disable = serdes_panel_split_disable, 99 }; 100 101 static int serdes_panel_split_probe(struct udevice *dev) 102 { 103 struct serdes *serdes = dev_get_priv(dev->parent); 104 struct serdes_panel_split *serdes_panel_split = NULL; 105 struct rockchip_panel *panel; 106 int ret; 107 108 SERDES_DBG_MFD("%s: %s %s start\n", __func__, serdes->dev->name, 109 serdes->chip_data->name); 110 111 if (!serdes->chip_data->panel_ops) { 112 printf("%s %s no panel ops\n", 113 __func__, serdes->chip_data->name); 114 return -1; 115 } 116 117 if (serdes->chip_data->serdes_type != TYPE_DES) 118 printf("%s warning: this chip is not des type\n", __func__); 119 120 serdes_panel_split = calloc(1, sizeof(*serdes_panel_split)); 121 if (!serdes_panel_split) 122 return -ENOMEM; 123 124 serdes->serdes_panel_split = serdes_panel_split; 125 126 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 127 "backlight", 128 &serdes->serdes_panel_split->backlight); 129 if (ret && ret != -ENOENT) 130 printf("%s: Cannot get backlight: %d\n", __func__, ret); 131 132 panel = calloc(1, sizeof(*panel)); 133 if (!panel) 134 return -ENOMEM; 135 136 ret = serdes_get_init_seq(serdes); 137 if (ret) 138 goto free_panel; 139 140 dev->driver_data = (ulong)panel; 141 panel->dev = dev; 142 panel->bus_format = MEDIA_BUS_FMT_RGB888_1X24; 143 panel->funcs = &serdes_panel_split_ops; 144 145 serdes->serdes_panel_split->panel = panel; 146 147 printf("%s %s successful, version %s\n", 148 __func__, 149 serdes->dev->name, 150 SERDES_UBOOT_DISPLAY_VERSION); 151 152 return 0; 153 154 free_panel: 155 free(panel); 156 157 return ret; 158 } 159 160 static const struct udevice_id serdes_of_match[] = { 161 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752) 162 { .compatible = "maxim,max96752-panel-split",}, 163 #endif 164 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772) 165 { .compatible = "maxim,max96772-panel-split",}, 166 #endif 167 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121) 168 { .compatible = "rockchip,rkx121-panel-split",}, 169 #endif 170 { } 171 }; 172 173 U_BOOT_DRIVER(serdes_panel_split) = { 174 .name = "serdes-panel-split", 175 .id = UCLASS_PANEL, 176 .of_match = serdes_of_match, 177 .probe = serdes_panel_split_probe, 178 .priv_auto_alloc_size = sizeof(struct serdes_panel_split), 179 }; 180