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