xref: /rk3399_rockchip-uboot/drivers/video/drm/rohm-bu18rl82.c (revision 80cf78ca99a6cc7b4f99b472e0c2da510bdf528b)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2022 Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <i2c.h>
10 #include <video_bridge.h>
11 #include <asm/unaligned.h>
12 #include <linux/media-bus-format.h>
13 #include <power/regulator.h>
14 
15 #include "rockchip_bridge.h"
16 #include "rockchip_display.h"
17 #include "rockchip_panel.h"
18 
19 struct des_reg_sequence {
20 	uint reg;
21 	uint def;
22 };
23 
24 struct serdes_init_seq {
25 	struct des_reg_sequence *reg_sequence;
26 	uint reg_seq_cnt;
27 };
28 
29 struct bu18rl82_priv {
30 	struct udevice *dev;
31 	struct serdes_init_seq *serdes_init_seq;
32 };
33 
34 static void bu18rl82_serdes_init_sequence_write(struct bu18rl82_priv *priv)
35 {
36 	struct serdes_init_seq *serdes_init_seq = priv->serdes_init_seq;
37 	struct des_reg_sequence *reg_sequence =  serdes_init_seq->reg_sequence;
38 	uint cnt = serdes_init_seq->reg_seq_cnt;
39 	struct udevice *dev = priv->dev;
40 	uint i;
41 
42 	for (i = 0; i < cnt; i++)
43 		dm_i2c_reg_write(dev, reg_sequence[i].reg, reg_sequence[i].def);
44 }
45 
46 static void bu18rl82_bridge_enable(struct rockchip_bridge *bridge)
47 {
48 	struct udevice *dev = bridge->dev;
49 	struct bu18rl82_priv *priv = dev_get_priv(dev);
50 
51 	bu18rl82_serdes_init_sequence_write(priv);
52 }
53 
54 static const struct rockchip_bridge_funcs bu18rl82_bridge_funcs = {
55 	.enable = bu18rl82_bridge_enable,
56 };
57 
58 static int bu18rl82_parse_init_seq(struct udevice *dev, const u16 *data,
59 				   int length, struct serdes_init_seq *seq)
60 {
61 	struct des_reg_sequence *reg_sequence;
62 	u16 *buf, *d;
63 	unsigned int i, cnt;
64 	int ret;
65 
66 	if (!seq)
67 		return -EINVAL;
68 
69 	buf = calloc(1, length);
70 	if (!buf)
71 		return -ENOMEM;
72 
73 	memcpy(buf, data, length);
74 
75 	d = buf;
76 	cnt = length / 4;
77 	seq->reg_seq_cnt = cnt;
78 
79 	seq->reg_sequence = calloc(cnt, sizeof(struct des_reg_sequence));
80 	if (!seq->reg_sequence) {
81 		ret = -ENOMEM;
82 		goto free_buf;
83 	}
84 
85 	for (i = 0; i < cnt; i++) {
86 		reg_sequence = &seq->reg_sequence[i];
87 		reg_sequence->reg = get_unaligned_be16(&d[0]);
88 		reg_sequence->def = get_unaligned_be16(&d[1]);
89 		d += 2;
90 	}
91 
92 	return 0;
93 
94 free_buf:
95 	free(buf);
96 
97 	return ret;
98 }
99 
100 static int bu18rl82_get_init_seq(struct bu18rl82_priv *priv)
101 {
102 	const void *data = NULL;
103 	int len, err;
104 
105 	data = dev_read_prop(priv->dev, "serdes-init-sequence", &len);
106 	if (!data) {
107 		printf("failed to get serdes-init-sequence\n");
108 		return -EINVAL;
109 	}
110 
111 	priv->serdes_init_seq = calloc(1, sizeof(*priv->serdes_init_seq));
112 	if (!priv->serdes_init_seq)
113 		return -ENOMEM;
114 
115 	err = bu18rl82_parse_init_seq(priv->dev, data, len, priv->serdes_init_seq);
116 	if (err) {
117 		printf("failed to parse serdes-init-sequence\n");
118 		goto free_init_seq;
119 	}
120 
121 	return 0;
122 
123 free_init_seq:
124 	free(priv->serdes_init_seq);
125 
126 	return err;
127 }
128 
129 static int bu18rl82_probe(struct udevice *dev)
130 {
131 	struct bu18rl82_priv *priv = dev_get_priv(dev);
132 	struct rockchip_bridge *bridge;
133 	int ret;
134 
135 	ret = i2c_set_chip_offset_len(dev, 2);
136 	if (ret)
137 		return ret;
138 
139 	priv->dev = dev;
140 
141 	bridge = calloc(1, sizeof(*bridge));
142 	if (!bridge)
143 		return -ENOMEM;
144 
145 	ret = bu18rl82_get_init_seq(priv);
146 	if (ret)
147 		goto free_bridge;
148 
149 	dev->driver_data = (ulong)bridge;
150 	bridge->dev = dev;
151 	bridge->funcs = &bu18rl82_bridge_funcs;
152 
153 	return 0;
154 
155 free_bridge:
156 	free(bridge);
157 
158 	return ret;
159 }
160 
161 static const struct udevice_id bu18rl82_of_match[] = {
162 	{ .compatible = "rohm,bu18rl82", },
163 	{}
164 };
165 
166 U_BOOT_DRIVER(bu18rl82) = {
167 	.name = "bu18rl82",
168 	.id = UCLASS_VIDEO_BRIDGE,
169 	.of_match = bu18rl82_of_match,
170 	.probe = bu18rl82_probe,
171 	.priv_auto_alloc_size = sizeof(struct bu18rl82_priv),
172 };
173