]> Git Repo - linux.git/blob - drivers/gpu/drm/sun4i/sun8i_mixer.c
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux.git] / drivers / gpu / drm / sun4i / sun8i_mixer.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2017 Icenowy Zheng <[email protected]>
4  *
5  * Based on sun4i_backend.c, which is:
6  *   Copyright (C) 2015 Free Electrons
7  *   Copyright (C) 2015 NextThing Co
8  */
9
10 #include <linux/component.h>
11 #include <linux/dma-mapping.h>
12 #include <linux/module.h>
13 #include <linux/of_device.h>
14 #include <linux/of_graph.h>
15 #include <linux/reset.h>
16
17 #include <drm/drm_atomic_helper.h>
18 #include <drm/drm_crtc.h>
19 #include <drm/drm_fb_cma_helper.h>
20 #include <drm/drm_framebuffer.h>
21 #include <drm/drm_gem_cma_helper.h>
22 #include <drm/drm_plane_helper.h>
23 #include <drm/drm_probe_helper.h>
24
25 #include "sun4i_drv.h"
26 #include "sun8i_mixer.h"
27 #include "sun8i_ui_layer.h"
28 #include "sun8i_vi_layer.h"
29 #include "sunxi_engine.h"
30
31 struct de2_fmt_info {
32         u32     drm_fmt;
33         u32     de2_fmt;
34 };
35
36 static const struct de2_fmt_info de2_formats[] = {
37         {
38                 .drm_fmt = DRM_FORMAT_ARGB8888,
39                 .de2_fmt = SUN8I_MIXER_FBFMT_ARGB8888,
40         },
41         {
42                 .drm_fmt = DRM_FORMAT_ABGR8888,
43                 .de2_fmt = SUN8I_MIXER_FBFMT_ABGR8888,
44         },
45         {
46                 .drm_fmt = DRM_FORMAT_RGBA8888,
47                 .de2_fmt = SUN8I_MIXER_FBFMT_RGBA8888,
48         },
49         {
50                 .drm_fmt = DRM_FORMAT_BGRA8888,
51                 .de2_fmt = SUN8I_MIXER_FBFMT_BGRA8888,
52         },
53         {
54                 .drm_fmt = DRM_FORMAT_XRGB8888,
55                 .de2_fmt = SUN8I_MIXER_FBFMT_XRGB8888,
56         },
57         {
58                 .drm_fmt = DRM_FORMAT_XBGR8888,
59                 .de2_fmt = SUN8I_MIXER_FBFMT_XBGR8888,
60         },
61         {
62                 .drm_fmt = DRM_FORMAT_RGBX8888,
63                 .de2_fmt = SUN8I_MIXER_FBFMT_RGBX8888,
64         },
65         {
66                 .drm_fmt = DRM_FORMAT_BGRX8888,
67                 .de2_fmt = SUN8I_MIXER_FBFMT_BGRX8888,
68         },
69         {
70                 .drm_fmt = DRM_FORMAT_RGB888,
71                 .de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
72         },
73         {
74                 .drm_fmt = DRM_FORMAT_BGR888,
75                 .de2_fmt = SUN8I_MIXER_FBFMT_BGR888,
76         },
77         {
78                 .drm_fmt = DRM_FORMAT_RGB565,
79                 .de2_fmt = SUN8I_MIXER_FBFMT_RGB565,
80         },
81         {
82                 .drm_fmt = DRM_FORMAT_BGR565,
83                 .de2_fmt = SUN8I_MIXER_FBFMT_BGR565,
84         },
85         {
86                 .drm_fmt = DRM_FORMAT_ARGB4444,
87                 .de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444,
88         },
89         {
90                 /* for DE2 VI layer which ignores alpha */
91                 .drm_fmt = DRM_FORMAT_XRGB4444,
92                 .de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444,
93         },
94         {
95                 .drm_fmt = DRM_FORMAT_ABGR4444,
96                 .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444,
97         },
98         {
99                 /* for DE2 VI layer which ignores alpha */
100                 .drm_fmt = DRM_FORMAT_XBGR4444,
101                 .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444,
102         },
103         {
104                 .drm_fmt = DRM_FORMAT_RGBA4444,
105                 .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444,
106         },
107         {
108                 /* for DE2 VI layer which ignores alpha */
109                 .drm_fmt = DRM_FORMAT_RGBX4444,
110                 .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444,
111         },
112         {
113                 .drm_fmt = DRM_FORMAT_BGRA4444,
114                 .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444,
115         },
116         {
117                 /* for DE2 VI layer which ignores alpha */
118                 .drm_fmt = DRM_FORMAT_BGRX4444,
119                 .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444,
120         },
121         {
122                 .drm_fmt = DRM_FORMAT_ARGB1555,
123                 .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
124         },
125         {
126                 /* for DE2 VI layer which ignores alpha */
127                 .drm_fmt = DRM_FORMAT_XRGB1555,
128                 .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
129         },
130         {
131                 .drm_fmt = DRM_FORMAT_ABGR1555,
132                 .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
133         },
134         {
135                 /* for DE2 VI layer which ignores alpha */
136                 .drm_fmt = DRM_FORMAT_XBGR1555,
137                 .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
138         },
139         {
140                 .drm_fmt = DRM_FORMAT_RGBA5551,
141                 .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
142         },
143         {
144                 /* for DE2 VI layer which ignores alpha */
145                 .drm_fmt = DRM_FORMAT_RGBX5551,
146                 .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
147         },
148         {
149                 .drm_fmt = DRM_FORMAT_BGRA5551,
150                 .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
151         },
152         {
153                 /* for DE2 VI layer which ignores alpha */
154                 .drm_fmt = DRM_FORMAT_BGRX5551,
155                 .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
156         },
157         {
158                 .drm_fmt = DRM_FORMAT_ARGB2101010,
159                 .de2_fmt = SUN8I_MIXER_FBFMT_ARGB2101010,
160         },
161         {
162                 .drm_fmt = DRM_FORMAT_ABGR2101010,
163                 .de2_fmt = SUN8I_MIXER_FBFMT_ABGR2101010,
164         },
165         {
166                 .drm_fmt = DRM_FORMAT_RGBA1010102,
167                 .de2_fmt = SUN8I_MIXER_FBFMT_RGBA1010102,
168         },
169         {
170                 .drm_fmt = DRM_FORMAT_BGRA1010102,
171                 .de2_fmt = SUN8I_MIXER_FBFMT_BGRA1010102,
172         },
173         {
174                 .drm_fmt = DRM_FORMAT_UYVY,
175                 .de2_fmt = SUN8I_MIXER_FBFMT_UYVY,
176         },
177         {
178                 .drm_fmt = DRM_FORMAT_VYUY,
179                 .de2_fmt = SUN8I_MIXER_FBFMT_VYUY,
180         },
181         {
182                 .drm_fmt = DRM_FORMAT_YUYV,
183                 .de2_fmt = SUN8I_MIXER_FBFMT_YUYV,
184         },
185         {
186                 .drm_fmt = DRM_FORMAT_YVYU,
187                 .de2_fmt = SUN8I_MIXER_FBFMT_YVYU,
188         },
189         {
190                 .drm_fmt = DRM_FORMAT_NV16,
191                 .de2_fmt = SUN8I_MIXER_FBFMT_NV16,
192         },
193         {
194                 .drm_fmt = DRM_FORMAT_NV61,
195                 .de2_fmt = SUN8I_MIXER_FBFMT_NV61,
196         },
197         {
198                 .drm_fmt = DRM_FORMAT_NV12,
199                 .de2_fmt = SUN8I_MIXER_FBFMT_NV12,
200         },
201         {
202                 .drm_fmt = DRM_FORMAT_NV21,
203                 .de2_fmt = SUN8I_MIXER_FBFMT_NV21,
204         },
205         {
206                 .drm_fmt = DRM_FORMAT_YUV422,
207                 .de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
208         },
209         {
210                 .drm_fmt = DRM_FORMAT_YUV420,
211                 .de2_fmt = SUN8I_MIXER_FBFMT_YUV420,
212         },
213         {
214                 .drm_fmt = DRM_FORMAT_YUV411,
215                 .de2_fmt = SUN8I_MIXER_FBFMT_YUV411,
216         },
217         {
218                 .drm_fmt = DRM_FORMAT_YVU422,
219                 .de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
220         },
221         {
222                 .drm_fmt = DRM_FORMAT_YVU420,
223                 .de2_fmt = SUN8I_MIXER_FBFMT_YUV420,
224         },
225         {
226                 .drm_fmt = DRM_FORMAT_YVU411,
227                 .de2_fmt = SUN8I_MIXER_FBFMT_YUV411,
228         },
229         {
230                 .drm_fmt = DRM_FORMAT_P010,
231                 .de2_fmt = SUN8I_MIXER_FBFMT_P010_YUV,
232         },
233         {
234                 .drm_fmt = DRM_FORMAT_P210,
235                 .de2_fmt = SUN8I_MIXER_FBFMT_P210_YUV,
236         },
237 };
238
239 int sun8i_mixer_drm_format_to_hw(u32 format, u32 *hw_format)
240 {
241         unsigned int i;
242
243         for (i = 0; i < ARRAY_SIZE(de2_formats); ++i)
244                 if (de2_formats[i].drm_fmt == format) {
245                         *hw_format = de2_formats[i].de2_fmt;
246                         return 0;
247                 }
248
249         return -EINVAL;
250 }
251
252 static void sun8i_mixer_commit(struct sunxi_engine *engine)
253 {
254         DRM_DEBUG_DRIVER("Committing changes\n");
255
256         regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
257                      SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
258 }
259
260 static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
261                                             struct sunxi_engine *engine)
262 {
263         struct drm_plane **planes;
264         struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
265         int i;
266
267         planes = devm_kcalloc(drm->dev,
268                               mixer->cfg->vi_num + mixer->cfg->ui_num + 1,
269                               sizeof(*planes), GFP_KERNEL);
270         if (!planes)
271                 return ERR_PTR(-ENOMEM);
272
273         for (i = 0; i < mixer->cfg->vi_num; i++) {
274                 struct sun8i_vi_layer *layer;
275
276                 layer = sun8i_vi_layer_init_one(drm, mixer, i);
277                 if (IS_ERR(layer)) {
278                         dev_err(drm->dev,
279                                 "Couldn't initialize overlay plane\n");
280                         return ERR_CAST(layer);
281                 }
282
283                 planes[i] = &layer->plane;
284         }
285
286         for (i = 0; i < mixer->cfg->ui_num; i++) {
287                 struct sun8i_ui_layer *layer;
288
289                 layer = sun8i_ui_layer_init_one(drm, mixer, i);
290                 if (IS_ERR(layer)) {
291                         dev_err(drm->dev, "Couldn't initialize %s plane\n",
292                                 i ? "overlay" : "primary");
293                         return ERR_CAST(layer);
294                 }
295
296                 planes[mixer->cfg->vi_num + i] = &layer->plane;
297         }
298
299         return planes;
300 }
301
302 static void sun8i_mixer_mode_set(struct sunxi_engine *engine,
303                                  const struct drm_display_mode *mode)
304 {
305         struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
306         u32 bld_base, size, val;
307         bool interlaced;
308
309         bld_base = sun8i_blender_base(mixer);
310         interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
311         size = SUN8I_MIXER_SIZE(mode->hdisplay, mode->vdisplay);
312
313         DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n",
314                          mode->hdisplay, mode->vdisplay);
315
316         regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_SIZE, size);
317         regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
318
319         if (interlaced)
320                 val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
321         else
322                 val = 0;
323
324         regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
325                            SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val);
326
327         DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
328                          interlaced ? "on" : "off");
329 }
330
331 static const struct sunxi_engine_ops sun8i_engine_ops = {
332         .commit         = sun8i_mixer_commit,
333         .layers_init    = sun8i_layers_init,
334         .mode_set       = sun8i_mixer_mode_set,
335 };
336
337 static const struct regmap_config sun8i_mixer_regmap_config = {
338         .reg_bits       = 32,
339         .val_bits       = 32,
340         .reg_stride     = 4,
341         .max_register   = 0xffffc, /* guessed */
342 };
343
344 static int sun8i_mixer_of_get_id(struct device_node *node)
345 {
346         struct device_node *ep, *remote;
347         struct of_endpoint of_ep;
348
349         /* Output port is 1, and we want the first endpoint. */
350         ep = of_graph_get_endpoint_by_regs(node, 1, -1);
351         if (!ep)
352                 return -EINVAL;
353
354         remote = of_graph_get_remote_endpoint(ep);
355         of_node_put(ep);
356         if (!remote)
357                 return -EINVAL;
358
359         of_graph_parse_endpoint(remote, &of_ep);
360         of_node_put(remote);
361         return of_ep.id;
362 }
363
364 static int sun8i_mixer_bind(struct device *dev, struct device *master,
365                               void *data)
366 {
367         struct platform_device *pdev = to_platform_device(dev);
368         struct drm_device *drm = data;
369         struct sun4i_drv *drv = drm->dev_private;
370         struct sun8i_mixer *mixer;
371         void __iomem *regs;
372         unsigned int base;
373         int plane_cnt;
374         int i, ret;
375
376         /*
377          * The mixer uses single 32-bit register to store memory
378          * addresses, so that it cannot deal with 64-bit memory
379          * addresses.
380          * Restrict the DMA mask so that the mixer won't be
381          * allocated some memory that is too high.
382          */
383         ret = dma_set_mask(dev, DMA_BIT_MASK(32));
384         if (ret) {
385                 dev_err(dev, "Cannot do 32-bit DMA.\n");
386                 return ret;
387         }
388
389         mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
390         if (!mixer)
391                 return -ENOMEM;
392         dev_set_drvdata(dev, mixer);
393         mixer->engine.ops = &sun8i_engine_ops;
394         mixer->engine.node = dev->of_node;
395
396         if (of_find_property(dev->of_node, "iommus", NULL)) {
397                 /*
398                  * This assume we have the same DMA constraints for
399                  * all our the mixers in our pipeline. This sounds
400                  * bad, but it has always been the case for us, and
401                  * DRM doesn't do per-device allocation either, so we
402                  * would need to fix DRM first...
403                  */
404                 ret = of_dma_configure(drm->dev, dev->of_node, true);
405                 if (ret)
406                         return ret;
407         }
408
409         /*
410          * While this function can fail, we shouldn't do anything
411          * if this happens. Some early DE2 DT entries don't provide
412          * mixer id but work nevertheless because matching between
413          * TCON and mixer is done by comparing node pointers (old
414          * way) instead comparing ids. If this function fails and
415          * id is needed, it will fail during id matching anyway.
416          */
417         mixer->engine.id = sun8i_mixer_of_get_id(dev->of_node);
418
419         mixer->cfg = of_device_get_match_data(dev);
420         if (!mixer->cfg)
421                 return -EINVAL;
422
423         regs = devm_platform_ioremap_resource(pdev, 0);
424         if (IS_ERR(regs))
425                 return PTR_ERR(regs);
426
427         mixer->engine.regs = devm_regmap_init_mmio(dev, regs,
428                                                    &sun8i_mixer_regmap_config);
429         if (IS_ERR(mixer->engine.regs)) {
430                 dev_err(dev, "Couldn't create the mixer regmap\n");
431                 return PTR_ERR(mixer->engine.regs);
432         }
433
434         mixer->reset = devm_reset_control_get(dev, NULL);
435         if (IS_ERR(mixer->reset)) {
436                 dev_err(dev, "Couldn't get our reset line\n");
437                 return PTR_ERR(mixer->reset);
438         }
439
440         ret = reset_control_deassert(mixer->reset);
441         if (ret) {
442                 dev_err(dev, "Couldn't deassert our reset line\n");
443                 return ret;
444         }
445
446         mixer->bus_clk = devm_clk_get(dev, "bus");
447         if (IS_ERR(mixer->bus_clk)) {
448                 dev_err(dev, "Couldn't get the mixer bus clock\n");
449                 ret = PTR_ERR(mixer->bus_clk);
450                 goto err_assert_reset;
451         }
452         clk_prepare_enable(mixer->bus_clk);
453
454         mixer->mod_clk = devm_clk_get(dev, "mod");
455         if (IS_ERR(mixer->mod_clk)) {
456                 dev_err(dev, "Couldn't get the mixer module clock\n");
457                 ret = PTR_ERR(mixer->mod_clk);
458                 goto err_disable_bus_clk;
459         }
460
461         /*
462          * It seems that we need to enforce that rate for whatever
463          * reason for the mixer to be functional. Make sure it's the
464          * case.
465          */
466         if (mixer->cfg->mod_rate)
467                 clk_set_rate(mixer->mod_clk, mixer->cfg->mod_rate);
468
469         clk_prepare_enable(mixer->mod_clk);
470
471         list_add_tail(&mixer->engine.list, &drv->engine_list);
472
473         base = sun8i_blender_base(mixer);
474
475         /* Reset registers and disable unused sub-engines */
476         if (mixer->cfg->is_de3) {
477                 for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4)
478                         regmap_write(mixer->engine.regs, i, 0);
479
480                 regmap_write(mixer->engine.regs, SUN50I_MIXER_FCE_EN, 0);
481                 regmap_write(mixer->engine.regs, SUN50I_MIXER_PEAK_EN, 0);
482                 regmap_write(mixer->engine.regs, SUN50I_MIXER_LCTI_EN, 0);
483                 regmap_write(mixer->engine.regs, SUN50I_MIXER_BLS_EN, 0);
484                 regmap_write(mixer->engine.regs, SUN50I_MIXER_FCC_EN, 0);
485                 regmap_write(mixer->engine.regs, SUN50I_MIXER_DNS_EN, 0);
486                 regmap_write(mixer->engine.regs, SUN50I_MIXER_DRC_EN, 0);
487                 regmap_write(mixer->engine.regs, SUN50I_MIXER_FMT_EN, 0);
488                 regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC0_EN, 0);
489                 regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC1_EN, 0);
490         } else {
491                 for (i = 0; i < DE2_MIXER_UNIT_SIZE; i += 4)
492                         regmap_write(mixer->engine.regs, i, 0);
493
494                 regmap_write(mixer->engine.regs, SUN8I_MIXER_FCE_EN, 0);
495                 regmap_write(mixer->engine.regs, SUN8I_MIXER_BWS_EN, 0);
496                 regmap_write(mixer->engine.regs, SUN8I_MIXER_LTI_EN, 0);
497                 regmap_write(mixer->engine.regs, SUN8I_MIXER_PEAK_EN, 0);
498                 regmap_write(mixer->engine.regs, SUN8I_MIXER_ASE_EN, 0);
499                 regmap_write(mixer->engine.regs, SUN8I_MIXER_FCC_EN, 0);
500                 regmap_write(mixer->engine.regs, SUN8I_MIXER_DCSC_EN, 0);
501         }
502
503         /* Enable the mixer */
504         regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
505                      SUN8I_MIXER_GLOBAL_CTL_RT_EN);
506
507         /* Set background color to black */
508         regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
509                      SUN8I_MIXER_BLEND_COLOR_BLACK);
510
511         /*
512          * Set fill color of bottom plane to black. Generally not needed
513          * except when VI plane is at bottom (zpos = 0) and enabled.
514          */
515         regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
516                      SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
517         regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
518                      SUN8I_MIXER_BLEND_COLOR_BLACK);
519
520         plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
521         for (i = 0; i < plane_cnt; i++)
522                 regmap_write(mixer->engine.regs,
523                              SUN8I_MIXER_BLEND_MODE(base, i),
524                              SUN8I_MIXER_BLEND_MODE_DEF);
525
526         regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
527                            SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
528
529         return 0;
530
531 err_disable_bus_clk:
532         clk_disable_unprepare(mixer->bus_clk);
533 err_assert_reset:
534         reset_control_assert(mixer->reset);
535         return ret;
536 }
537
538 static void sun8i_mixer_unbind(struct device *dev, struct device *master,
539                                  void *data)
540 {
541         struct sun8i_mixer *mixer = dev_get_drvdata(dev);
542
543         list_del(&mixer->engine.list);
544
545         clk_disable_unprepare(mixer->mod_clk);
546         clk_disable_unprepare(mixer->bus_clk);
547         reset_control_assert(mixer->reset);
548 }
549
550 static const struct component_ops sun8i_mixer_ops = {
551         .bind   = sun8i_mixer_bind,
552         .unbind = sun8i_mixer_unbind,
553 };
554
555 static int sun8i_mixer_probe(struct platform_device *pdev)
556 {
557         return component_add(&pdev->dev, &sun8i_mixer_ops);
558 }
559
560 static int sun8i_mixer_remove(struct platform_device *pdev)
561 {
562         component_del(&pdev->dev, &sun8i_mixer_ops);
563
564         return 0;
565 }
566
567 static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
568         .ccsc           = CCSC_MIXER0_LAYOUT,
569         .scaler_mask    = 0xf,
570         .scanline_yuv   = 2048,
571         .ui_num         = 3,
572         .vi_num         = 1,
573 };
574
575 static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
576         .ccsc           = CCSC_MIXER1_LAYOUT,
577         .scaler_mask    = 0x3,
578         .scanline_yuv   = 2048,
579         .ui_num         = 1,
580         .vi_num         = 1,
581 };
582
583 static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
584         .ccsc           = CCSC_MIXER0_LAYOUT,
585         .mod_rate       = 432000000,
586         .scaler_mask    = 0xf,
587         .scanline_yuv   = 2048,
588         .ui_num         = 3,
589         .vi_num         = 1,
590 };
591
592 static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
593         .ccsc           = CCSC_MIXER0_LAYOUT,
594         .mod_rate       = 297000000,
595         .scaler_mask    = 0xf,
596         .scanline_yuv   = 2048,
597         .ui_num         = 3,
598         .vi_num         = 1,
599 };
600
601 static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
602         .ccsc           = CCSC_MIXER1_LAYOUT,
603         .mod_rate       = 297000000,
604         .scaler_mask    = 0x3,
605         .scanline_yuv   = 2048,
606         .ui_num         = 1,
607         .vi_num         = 1,
608 };
609
610 static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
611         .vi_num = 2,
612         .ui_num = 1,
613         .scaler_mask = 0x3,
614         .scanline_yuv = 2048,
615         .ccsc = CCSC_MIXER0_LAYOUT,
616         .mod_rate = 150000000,
617 };
618
619 static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = {
620         .ccsc           = CCSC_D1_MIXER0_LAYOUT,
621         .mod_rate       = 297000000,
622         .scaler_mask    = 0x3,
623         .scanline_yuv   = 2048,
624         .ui_num         = 1,
625         .vi_num         = 1,
626 };
627
628 static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = {
629         .ccsc           = CCSC_MIXER1_LAYOUT,
630         .mod_rate       = 297000000,
631         .scaler_mask    = 0x1,
632         .scanline_yuv   = 1024,
633         .ui_num         = 0,
634         .vi_num         = 1,
635 };
636
637 static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
638         .ccsc           = CCSC_MIXER0_LAYOUT,
639         .mod_rate       = 297000000,
640         .scaler_mask    = 0xf,
641         .scanline_yuv   = 4096,
642         .ui_num         = 3,
643         .vi_num         = 1,
644 };
645
646 static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
647         .ccsc           = CCSC_MIXER1_LAYOUT,
648         .mod_rate       = 297000000,
649         .scaler_mask    = 0x3,
650         .scanline_yuv   = 2048,
651         .ui_num         = 1,
652         .vi_num         = 1,
653 };
654
655 static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
656         .ccsc           = CCSC_MIXER0_LAYOUT,
657         .is_de3         = true,
658         .mod_rate       = 600000000,
659         .scaler_mask    = 0xf,
660         .scanline_yuv   = 4096,
661         .ui_num         = 3,
662         .vi_num         = 1,
663 };
664
665 static const struct of_device_id sun8i_mixer_of_table[] = {
666         {
667                 .compatible = "allwinner,sun8i-a83t-de2-mixer-0",
668                 .data = &sun8i_a83t_mixer0_cfg,
669         },
670         {
671                 .compatible = "allwinner,sun8i-a83t-de2-mixer-1",
672                 .data = &sun8i_a83t_mixer1_cfg,
673         },
674         {
675                 .compatible = "allwinner,sun8i-h3-de2-mixer-0",
676                 .data = &sun8i_h3_mixer0_cfg,
677         },
678         {
679                 .compatible = "allwinner,sun8i-r40-de2-mixer-0",
680                 .data = &sun8i_r40_mixer0_cfg,
681         },
682         {
683                 .compatible = "allwinner,sun8i-r40-de2-mixer-1",
684                 .data = &sun8i_r40_mixer1_cfg,
685         },
686         {
687                 .compatible = "allwinner,sun8i-v3s-de2-mixer",
688                 .data = &sun8i_v3s_mixer_cfg,
689         },
690         {
691                 .compatible = "allwinner,sun20i-d1-de2-mixer-0",
692                 .data = &sun20i_d1_mixer0_cfg,
693         },
694         {
695                 .compatible = "allwinner,sun20i-d1-de2-mixer-1",
696                 .data = &sun20i_d1_mixer1_cfg,
697         },
698         {
699                 .compatible = "allwinner,sun50i-a64-de2-mixer-0",
700                 .data = &sun50i_a64_mixer0_cfg,
701         },
702         {
703                 .compatible = "allwinner,sun50i-a64-de2-mixer-1",
704                 .data = &sun50i_a64_mixer1_cfg,
705         },
706         {
707                 .compatible = "allwinner,sun50i-h6-de3-mixer-0",
708                 .data = &sun50i_h6_mixer0_cfg,
709         },
710         { }
711 };
712 MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
713
714 static struct platform_driver sun8i_mixer_platform_driver = {
715         .probe          = sun8i_mixer_probe,
716         .remove         = sun8i_mixer_remove,
717         .driver         = {
718                 .name           = "sun8i-mixer",
719                 .of_match_table = sun8i_mixer_of_table,
720         },
721 };
722 module_platform_driver(sun8i_mixer_platform_driver);
723
724 MODULE_AUTHOR("Icenowy Zheng <[email protected]>");
725 MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
726 MODULE_LICENSE("GPL");
This page took 0.075195 seconds and 4 git commands to generate.