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
serdes_panel_init(struct serdes * serdes)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 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
serdes_panel_prepare(struct rockchip_panel * panel)32 static void serdes_panel_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
serdes_panel_unprepare(struct rockchip_panel * panel)44 static void serdes_panel_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
serdes_panel_enable(struct rockchip_panel * panel)56 static void serdes_panel_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_init(serdes);
65
66 if (serdes->serdes_panel->backlight)
67 backlight_enable(serdes->serdes_panel->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
serdes_panel_disable(struct rockchip_panel * panel)76 static void serdes_panel_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->backlight)
85 backlight_disable(serdes->serdes_panel->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_ops = {
95 .prepare = serdes_panel_prepare,
96 .unprepare = serdes_panel_unprepare,
97 .enable = serdes_panel_enable,
98 .disable = serdes_panel_disable,
99 };
100
serdes_panel_probe(struct udevice * dev)101 static int serdes_panel_probe(struct udevice *dev)
102 {
103 struct serdes *serdes = dev_get_priv(dev->parent);
104 struct serdes_panel *serdes_panel = 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("warning: this chip is not des type\n");
119
120 serdes_panel = calloc(1, sizeof(*serdes_panel));
121 if (!serdes_panel)
122 return -ENOMEM;
123
124 serdes->serdes_panel = serdes_panel;
125
126 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
127 "backlight",
128 &serdes->serdes_panel->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_ops;
144
145 serdes->serdes_panel->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",},
163 #endif
164 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772)
165 { .compatible = "maxim,max96772-panel",},
166 #endif
167 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121)
168 { .compatible = "rockchip,rkx121-panel",},
169 #endif
170 { }
171 };
172
173 U_BOOT_DRIVER(serdes_panel) = {
174 .name = "serdes-panel",
175 .id = UCLASS_PANEL,
176 .of_match = serdes_of_match,
177 .probe = serdes_panel_probe,
178 .priv_auto_alloc_size = sizeof(struct serdes_panel),
179 };
180