riscv:linux:drm
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / verisilicon / vs_simple_enc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 VeriSilicon Holdings Co., Ltd.
4  */
5 #include <linux/version.h>
6 #include <linux/component.h>
7 #include <linux/of_device.h>
8 #if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
9 #include <linux/module.h>
10
11 #include <drm/drm_bridge.h>
12 #else
13 #include <drm/drmP.h>
14 #endif
15
16 #include <drm/drm_crtc_helper.h>
17 #include <drm/drm_of.h>
18 #include <linux/regmap.h>
19 #include <linux/mfd/syscon.h>
20
21 #include "vs_crtc.h"
22 #include "vs_simple_enc.h"
23
24 static const struct simple_encoder_priv hdmi_priv = {
25         .encoder_type = DRM_MODE_ENCODER_TMDS
26 };
27
28 static const struct simple_encoder_priv dsi_priv = {
29         .encoder_type = DRM_MODE_ENCODER_DSI
30 };
31
32 static const struct drm_encoder_funcs encoder_funcs = {
33         .destroy = drm_encoder_cleanup
34 };
35
36 static inline struct simple_encoder *to_simple_encoder(struct drm_encoder *enc)
37 {
38         return container_of(enc, struct simple_encoder, encoder);
39 }
40
41 #if 0
42 static int encoder_parse_dt(struct device *dev)
43 {
44         struct simple_encoder *simple = dev_get_drvdata(dev);
45         int ret = 0;
46         int cnt, i;
47         u32 *vals;
48         u32 *masks;
49
50         simple->dss_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
51                                                 "verisilicon,dss-syscon");
52
53         if (IS_ERR(simple->dss_regmap)) {
54                 if (PTR_ERR(simple->dss_regmap) != -ENODEV) {
55                         dev_err(dev, "failed to get dss-syscon\n");
56                         ret = PTR_ERR(simple->dss_regmap);
57                         goto err;
58                 }
59                 simple->dss_regmap = NULL;
60                 goto err;
61         }
62
63         cnt = of_property_count_elems_of_size(dev->of_node,
64                                 "verisilicon,mux-mask", 4);
65         if (!cnt) {
66                 ret = cnt;
67                 goto err;
68         }
69
70         simple->dss_regdatas = devm_kzalloc(dev,
71                 sizeof(*simple->dss_regdatas) * cnt, GFP_KERNEL);
72
73         masks = kcalloc(cnt, sizeof(*masks), GFP_KERNEL);
74         if (!masks) {
75                 ret = -ENOMEM;
76                 goto err;
77         }
78
79         vals = kcalloc(cnt, sizeof(*vals), GFP_KERNEL);
80         if (!vals) {
81                 ret = -ENOMEM;
82                 goto err_free_masks;
83         }
84
85         ret = of_property_read_u32_array(
86                         dev->of_node, "verisilicon,mux-mask", masks, cnt);
87         if (ret)
88                 goto err_free_vals;
89
90         ret = of_property_read_u32_array(
91                         dev->of_node, "verisilicon,mux-val", vals, cnt);
92         if (ret)
93                 goto err_free_vals;
94
95         for (i = 0; i < cnt; i++) {
96                 simple->dss_regdatas[i].mask = masks[i];
97                 simple->dss_regdatas[i].value = vals[i];
98         }
99
100 err_free_vals:
101         kfree(vals);
102 err_free_masks:
103         kfree(masks);
104 err:
105         return ret;
106 }
107 #endif
108
109 #define DOM_VOUT_SYSCON_8                                                                       0x8U
110 #define U0_LCD_DATA_MAPPING_DPI_DP_SEL_SHIFT                            0x2U
111 #define U0_LCD_DATA_MAPPING_DPI_DP_SEL_MASK                                     0x4U
112
113 #define DOM_VOUT_SYSCON_4                                                                       0x4U
114 #define U0_DISPLAY_PANEL_MUX_PANEL_SEL_SHIFT                            0x14U
115 #define U0_DISPLAY_PANEL_MUX_PANEL_SEL_MASK                                     0x100000U
116
117 void encoder_atomic_enable(struct drm_encoder *encoder,
118                                                 struct drm_atomic_state *state)
119 {
120         return;
121 }
122
123 int encoder_atomic_check(struct drm_encoder *encoder,
124                         struct drm_crtc_state *crtc_state,
125                         struct drm_connector_state *conn_state)
126 {
127         struct vs_crtc_state *vs_crtc_state = to_vs_crtc_state(crtc_state);
128         struct drm_connector *connector = conn_state->connector;
129         int ret = 0;
130 #if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
131         struct drm_bridge *first_bridge = drm_bridge_chain_get_first_bridge(encoder);
132         struct drm_bridge_state *bridge_state = ERR_PTR(-EINVAL);
133 #endif
134
135         vs_crtc_state->encoder_type = encoder->encoder_type;
136
137 #if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
138         if (first_bridge && first_bridge->funcs->atomic_duplicate_state)
139                 bridge_state = drm_atomic_get_bridge_state(
140                                            crtc_state->state, first_bridge);
141
142         if (IS_ERR(bridge_state)) {
143                 if (connector->display_info.num_bus_formats)
144                         vs_crtc_state->output_fmt = connector->display_info.bus_formats[0];
145                 else
146                         vs_crtc_state->output_fmt = MEDIA_BUS_FMT_FIXED;
147         } else {
148                 vs_crtc_state->output_fmt = bridge_state->input_bus_cfg.format;
149         }
150 #else
151         if (connector->display_info.num_bus_formats)
152                 vs_crtc_state->output_fmt = connector->display_info.bus_formats[0];
153         else
154                 vs_crtc_state->output_fmt = MEDIA_BUS_FMT_RGB888_1X24;
155 #endif
156
157         switch (vs_crtc_state->output_fmt) {
158         case MEDIA_BUS_FMT_FIXED:
159         case MEDIA_BUS_FMT_RGB565_1X16:
160         case MEDIA_BUS_FMT_RGB666_1X18:
161         case MEDIA_BUS_FMT_RGB888_1X24:
162         case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
163         case MEDIA_BUS_FMT_RGB101010_1X30:
164         case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
165         case MEDIA_BUS_FMT_UYVY8_1X16:
166         case MEDIA_BUS_FMT_YUV8_1X24:
167         case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
168         case MEDIA_BUS_FMT_UYVY10_1X20:
169         case MEDIA_BUS_FMT_YUV10_1X30:
170                 ret = 0;
171                 break;
172         default:
173                 ret = -EINVAL;
174                 break;
175         }
176
177         /* If MEDIA_BUS_FMT_FIXED, set it to default value */
178         if (vs_crtc_state->output_fmt == MEDIA_BUS_FMT_FIXED)
179                 vs_crtc_state->output_fmt = MEDIA_BUS_FMT_RGB888_1X24;
180
181         return ret;
182 }
183
184 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
185         .atomic_enable = encoder_atomic_enable,
186         .atomic_check = encoder_atomic_check,
187 };
188
189 static int encoder_bind(struct device *dev, struct device *master, void *data)
190 {
191
192         struct drm_device *drm_dev = data;
193         struct simple_encoder *simple = dev_get_drvdata(dev);
194         struct drm_encoder *encoder;
195         struct drm_bridge *bridge;
196         
197         int ret;
198
199 #ifdef CONFIG_STARFIVE_DSI
200         struct drm_panel *tmp_panel;
201 #endif
202
203         encoder = &simple->encoder;
204
205         /* Encoder. */
206         dev_info(dev,"encoder_bind begin\n");
207
208         ret = drm_encoder_init(drm_dev, encoder, &encoder_funcs,
209                                    simple->priv->encoder_type, NULL);
210         if (ret)
211                 return ret;
212
213         drm_encoder_helper_add(encoder, &encoder_helper_funcs);
214
215         encoder->possible_crtcs =
216                         drm_of_find_possible_crtcs(drm_dev, dev->of_node);
217         encoder->possible_crtcs = 2;
218
219         /* output port is port1*/
220
221 #ifdef CONFIG_STARFIVE_DSI
222         ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0,&tmp_panel, &bridge);
223         if (ret){
224                 printk("==no panel, %d\n",ret);
225                 //dev_err_probe(dev, ret, "endpoint returns %d\n", ret);
226                 goto err;
227         }
228         if (tmp_panel)
229                 dev_err(dev, "found panel on endpoint\n");
230 #else
231         ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL, &bridge);
232                 if (ret)
233                         goto err;
234 #endif
235 #if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE
236         ret = drm_bridge_attach(encoder, bridge, NULL, 0);
237 #else
238         ret = drm_bridge_attach(encoder, bridge, NULL);
239 #endif
240         if (ret)
241                 goto err;
242
243         dev_info(dev,"encoder_bind end\n");
244         return 0;
245 err:
246         drm_encoder_cleanup(encoder);
247         dev_info(dev,"encoder_bind error\n");
248
249         //return ret;
250         return 0;
251 }
252
253 static void encoder_unbind(struct device *dev, struct device *master,
254                                   void *data)
255 {
256         struct simple_encoder *simple = dev_get_drvdata(dev);
257
258         drm_encoder_cleanup(&simple->encoder);
259 }
260
261 static const struct component_ops encoder_component_ops = {
262         .bind = encoder_bind,
263         .unbind = encoder_unbind,
264 };
265
266 static const struct of_device_id simple_encoder_dt_match[] = {
267         { .compatible = "verisilicon,rgb-encoder", .data = &hdmi_priv},
268         { .compatible = "verisilicon,dp-encoder", .data = &hdmi_priv},
269         { .compatible = "verisilicon,dsi-encoder", .data = &dsi_priv},
270         {},
271 };
272 MODULE_DEVICE_TABLE(of, simple_encoder_dt_match);
273
274 static int encoder_probe(struct platform_device *pdev)
275 {
276         struct device *dev = &pdev->dev;
277         struct simple_encoder *simple;
278
279         simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
280         if (!simple)
281                 return -ENOMEM;
282
283         simple->priv = of_device_get_match_data(dev);
284
285         simple->dev = dev;
286
287         dev_set_drvdata(dev, simple);
288 #if 0
289         ret = encoder_parse_dt(dev);
290         if (ret)
291                 return ret;
292 #endif
293         return component_add(dev, &encoder_component_ops);
294 }
295
296 static int encoder_remove(struct platform_device *pdev)
297 {
298         struct device *dev = &pdev->dev;
299
300         component_del(dev, &encoder_component_ops);
301
302         dev_set_drvdata(dev, NULL);
303
304         return 0;
305 }
306
307 struct platform_driver simple_encoder_driver = {
308         .probe = encoder_probe,
309         .remove = encoder_remove,
310         .driver = {
311                 .name = "vs-simple-encoder",
312                 .of_match_table = of_match_ptr(simple_encoder_dt_match),
313         },
314 };
315
316 MODULE_DESCRIPTION("Simple Encoder Driver");
317 MODULE_LICENSE("GPL v2");