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