]> rtime.felk.cvut.cz Git - zynq/linux.git/blob - drivers/gpu/drm/xlnx/xlnx_mixer.c
drm: xlnx: mixer: remove deprecated dmaengine_terminate_all
[zynq/linux.git] / drivers / gpu / drm / xlnx / xlnx_mixer.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Xilinx logicore video mixer driver
4  *
5  * Copyright (C) 2017 - 2018 Xilinx, Inc.
6  *
7  * Author: Saurabh Sengar <saurabhs@xilinx.com>
8  *       : Jeffrey Mouroux <jmouroux@xilinx.com>
9  */
10
11 #include <drm/drmP.h>
12 #include <drm/drm_atomic.h>
13 #include <drm/drm_atomic_helper.h>
14 #include <drm/drm_crtc.h>
15 #include <drm/drm_fb_cma_helper.h>
16 #include <drm/drm_fourcc.h>
17 #include <drm/drm_gem_cma_helper.h>
18 #include <drm/drm_modeset_helper_vtables.h>
19 #include <linux/clk.h>
20 #include <linux/component.h>
21 #include <linux/dma/xilinx_frmbuf.h>
22 #include <linux/gpio/consumer.h>
23 #include <linux/of.h>
24 #include <linux/of_dma.h>
25 #include <linux/of_address.h>
26 #include <linux/of_irq.h>
27 #include <linux/dmaengine.h>
28 #include "xlnx_drv.h"
29 #include "xlnx_crtc.h"
30
31 /**************************** Register Data **********************************/
32 #define XVMIX_AP_CTRL                   0x00000
33 #define XVMIX_GIE                       0x00004
34 #define XVMIX_IER                       0x00008
35 #define XVMIX_ISR                       0x0000c
36 #define XVMIX_WIDTH_DATA                0x00010
37 #define XVMIX_HEIGHT_DATA               0x00018
38 #define XVMIX_BACKGROUND_Y_R_DATA       0x00028
39 #define XVMIX_BACKGROUND_U_G_DATA       0x00030
40 #define XVMIX_BACKGROUND_V_B_DATA       0x00038
41 #define XVMIX_LAYERENABLE_DATA          0x00040
42 #define XVMIX_LAYERALPHA_0_DATA         0x00100
43 #define XVMIX_LAYERSTARTX_0_DATA        0x00108
44 #define XVMIX_LAYERSTARTY_0_DATA        0x00110
45 #define XVMIX_LAYERWIDTH_0_DATA         0x00118
46 #define XVMIX_LAYERSTRIDE_0_DATA        0x00120
47 #define XVMIX_LAYERHEIGHT_0_DATA        0x00128
48 #define XVMIX_LAYERSCALE_0_DATA         0x00130
49 #define XVMIX_LAYERVIDEOFORMAT_0_DATA   0x00138
50 #define XVMIX_LAYER1_BUF1_V_DATA        0x00240
51 #define XVMIX_LAYER1_BUF2_V_DATA        0x0024c
52 #define XVMIX_LOGOSTARTX_DATA           0x01000
53 #define XVMIX_LOGOSTARTY_DATA           0x01008
54 #define XVMIX_LOGOWIDTH_DATA            0x01010
55 #define XVMIX_LOGOHEIGHT_DATA           0x01018
56 #define XVMIX_LOGOSCALEFACTOR_DATA      0x01020
57 #define XVMIX_LOGOALPHA_DATA            0x01028
58 #define XVMIX_LOGOCLRKEYMIN_R_DATA      0x01030
59 #define XVMIX_LOGOCLRKEYMIN_G_DATA      0x01038
60 #define XVMIX_LOGOCLRKEYMIN_B_DATA      0x01040
61 #define XVMIX_LOGOCLRKEYMAX_R_DATA      0x01048
62 #define XVMIX_LOGOCLRKEYMAX_G_DATA      0x01050
63 #define XVMIX_LOGOCLRKEYMAX_B_DATA      0x01058
64 #define XVMIX_LOGOR_V_BASE              0x10000
65 #define XVMIX_LOGOR_V_HIGH              0x10fff
66 #define XVMIX_LOGOG_V_BASE              0x20000
67 #define XVMIX_LOGOG_V_HIGH              0x20fff
68 #define XVMIX_LOGOB_V_BASE              0x30000
69 #define XVMIX_LOGOB_V_HIGH              0x30fff
70 #define XVMIX_LOGOA_V_BASE              0x40000
71 #define XVMIX_LOGOA_V_HIGH              0x40fff
72
73 /************************** Constant Definitions *****************************/
74 #define XVMIX_LOGO_EN                   BIT(15)
75 #define XVMIX_MASK_ENABLE_ALL_LAYERS    (GENMASK(8, 0) | XVMIX_LOGO_EN)
76 #define XVMIX_MASK_DISABLE_ALL_LAYERS   0x0
77 #define XVMIX_REG_OFFSET                0x100
78 #define XVMIX_MASTER_LAYER_IDX          0x0
79 #define XVMIX_LOGO_LAYER_IDX            0x1
80 #define XVMIX_DISP_MAX_WIDTH            4096
81 #define XVMIX_DISP_MAX_HEIGHT           2160
82 #define XVMIX_MAX_LAYERS                10
83 #define XVMIX_MAX_BPC                   16
84 #define XVMIX_ALPHA_MIN                 0
85 #define XVMIX_ALPHA_MAX                 256
86 #define XVMIX_LAYER_WIDTH_MIN           64
87 #define XVMIX_LAYER_HEIGHT_MIN          64
88 #define XVMIX_LOGO_LAYER_WIDTH_MIN      32
89 #define XVMIX_LOGO_LAYER_HEIGHT_MIN     32
90 #define XVMIX_LOGO_LAYER_WIDTH_MAX      256
91 #define XVMIX_LOGO_LAYER_HEIGHT_MAX     256
92 #define XVMIX_IRQ_DONE_MASK             BIT(0)
93 #define XVMIX_GIE_EN_MASK               BIT(0)
94 #define XVMIX_AP_EN_MASK                BIT(0)
95 #define XVMIX_AP_RST_MASK               BIT(7)
96 #define XVMIX_MAX_NUM_SUB_PLANES        4
97 #define XVMIX_SCALE_FACTOR_1X           0
98 #define XVMIX_SCALE_FACTOR_2X           1
99 #define XVMIX_SCALE_FACTOR_4X           2
100 #define XVMIX_SCALE_FACTOR_INVALID      3
101 #define XVMIX_BASE_ALIGN                8
102
103 /*************************** STATIC DATA  ************************************/
104 static const u32 color_table[] = {
105         DRM_FORMAT_BGR888,
106         DRM_FORMAT_RGB888,
107         DRM_FORMAT_XBGR2101010,
108         DRM_FORMAT_XRGB8888,
109         DRM_FORMAT_RGBA8888,
110         DRM_FORMAT_ABGR8888,
111         DRM_FORMAT_ARGB8888,
112         DRM_FORMAT_XBGR8888,
113         DRM_FORMAT_YUYV,
114         DRM_FORMAT_UYVY,
115         DRM_FORMAT_AYUV,
116         DRM_FORMAT_NV12,
117         DRM_FORMAT_NV16,
118         DRM_FORMAT_Y8,
119         DRM_FORMAT_Y10,
120         DRM_FORMAT_XVUY2101010,
121         DRM_FORMAT_VUY888,
122         DRM_FORMAT_XVUY8888,
123         DRM_FORMAT_XV15,
124         DRM_FORMAT_XV20,
125 };
126
127 /*********************** Inline Functions/Macros *****************************/
128 #define to_mixer_hw(p) (&((p)->mixer->mixer_hw))
129 #define to_xlnx_crtc(x) container_of(x, struct xlnx_crtc, crtc)
130 #define to_xlnx_plane(x)        container_of(x, struct xlnx_mix_plane, base)
131 #define to_xlnx_mixer(x)        container_of(x, struct xlnx_mix, crtc)
132
133 /**
134  * enum xlnx_mix_layer_id - Describes the layer by index to be acted upon
135  * @XVMIX_LAYER_MASTER: Master layer
136  * @XVMIX_LAYER_1: Layer 1
137  * @XVMIX_LAYER_2: Layer 2
138  * @XVMIX_LAYER_3: Layer 3
139  * @XVMIX_LAYER_4: Layer 4
140  * @XVMIX_LAYER_5: Layer 5
141  * @XVMIX_LAYER_6: Layer 6
142  * @XVMIX_LAYER_7: Layer 7
143  * @XVMIX_LAYER_8: Layer 8
144  * @XVMIX_LAYER_LOGO: Logo Layer
145  * @XVMIX_LAYER_ALL: Layer count
146  */
147 enum xlnx_mix_layer_id {
148         XVMIX_LAYER_MASTER = 0,
149         XVMIX_LAYER_1,
150         XVMIX_LAYER_2,
151         XVMIX_LAYER_3,
152         XVMIX_LAYER_4,
153         XVMIX_LAYER_5,
154         XVMIX_LAYER_6,
155         XVMIX_LAYER_7,
156         XVMIX_LAYER_8,
157         XVMIX_LAYER_LOGO,
158         XVMIX_LAYER_ALL
159 };
160
161 /**
162  * struct xlnx_mix_layer_data - Describes the hardware configuration of a given
163  * mixer layer
164  * @hw_config: struct specifying the IP hardware constraints for this layer
165  * @vid_fmt: DRM format for this layer
166  * @can_alpha: Indicates that layer alpha is enabled for this layer
167  * @can_scale: Indicates that layer scaling is enabled for this layer
168  * @is_streaming: Indicates layer is not using mixer DMA but streaming from
169  *  external DMA
170  * @max_width: Max possible pixel width
171  * @max_height: Max possible pixel height
172  * @min_width: Min possible pixel width
173  * @min_height: Min possible pixel height
174  * @layer_regs: struct containing current cached register values
175  * @buff_addr: Current physical address of image buffer
176  * @x_pos: Current CRTC x offset
177  * @y_pos: Current CRTC y offset
178  * @width: Current width in pixels
179  * @height: Current hight in pixels
180  * @stride: Current stride (when Mixer is performing DMA)
181  * @alpha: Current alpha setting
182  * @is_active: Logical flag indicating layer in use.  If false, calls to
183  *  enable layer will be ignored.
184  * @scale_fact: Current scaling factor applied to layer
185  * @id: The logical layer id identifies which layer this struct describes
186  *  (e.g. 0 = master, 1-7 = overlay).
187  *
188  * All mixer layers are reprsented by an instance of this struct:
189  * output streaming, overlay, logo.
190  * Current layer-specific register state is stored in the layer_regs struct.
191  * The hardware configuration is stored in struct hw_config.
192  *
193  * Note:
194  * Some properties of the logo layer are unique and not described in this
195  * struct.  Those properites are part of the xlnx_mix struct as global
196  * properties.
197  */
198 struct xlnx_mix_layer_data {
199         struct {
200                 u32     vid_fmt;
201                 bool    can_alpha;
202                 bool    can_scale;
203                 bool    is_streaming;
204                 u32     max_width;
205                 u32     max_height;
206                 u32     min_width;
207                 u32     min_height;
208         } hw_config;
209
210         struct {
211                 u64     buff_addr1;
212                 u64     buff_addr2;
213                 u32     x_pos;
214                 u32     y_pos;
215                 u32     width;
216                 u32     height;
217                 u32     stride;
218                 u32     alpha;
219                 bool    is_active;
220                 u32     scale_fact;
221         } layer_regs;
222
223         enum xlnx_mix_layer_id id;
224 };
225
226 /**
227  * struct xlnx_mix_hw - Describes a mixer IP block instance within the design
228  * @base: Base physical address of Mixer IP in memory map
229  * @logo_layer_en: Indicates logo layer is enabled in hardware
230  * @logo_pixel_alpha_enabled: Indicates that per-pixel alpha supported for logo
231  *  layer
232  * @max_layer_width: Max possible width for any layer on this Mixer
233  * @max_layer_height: Max possible height for any layer on this Mixer
234  * @max_logo_layer_width: Min possible width for any layer on this Mixer
235  * @max_logo_layer_height: Min possible height for any layer on this Mixer
236  * @max_layers: Max number of layers (excl: logo)
237  * @bg_layer_bpc: Bits per component for the background streaming layer
238  * @dma_addr_size: dma address size in bits
239  * @ppc: Pixels per component
240  * @irq: Interrupt request number assigned
241  * @bg_color: Current RGB color value for internal background color generator
242  * @layer_data: Array of layer data
243  * @layer_cnt: Layer data array count
244  * @reset_gpio: GPIO line used to reset IP between modesetting operations
245  * @intrpt_handler_fn: Interrupt handler function called when frame is completed
246  * @intrpt_data: Data pointer passed to interrupt handler
247  *
248  * Used as the primary data structure for many L2 driver functions. Logo layer
249  * data, if enabled within the IP, is described in this structure.  All other
250  * layers are described by an instance of xlnx_mix_layer_data referenced by this
251  * struct.
252  *
253  */
254 struct xlnx_mix_hw {
255         void __iomem        *base;
256         bool                logo_layer_en;
257         bool                logo_pixel_alpha_enabled;
258         u32                 max_layer_width;
259         u32                 max_layer_height;
260         u32                 max_logo_layer_width;
261         u32                 max_logo_layer_height;
262         u32                 max_layers;
263         u32                 bg_layer_bpc;
264         u32                 dma_addr_size;
265         u32                 ppc;
266         int                 irq;
267         u64                 bg_color;
268         struct xlnx_mix_layer_data *layer_data;
269         u32 layer_cnt;
270         struct gpio_desc *reset_gpio;
271         void (*intrpt_handler_fn)(void *);
272         void *intrpt_data;
273 };
274
275 /**
276  * struct xlnx_mix - Container for interfacing DRM driver to mixer
277  * @mixer_hw: Object representing actual hardware state of mixer
278  * @master: Logical master device from xlnx drm
279  * @crtc: Xilinx DRM driver crtc object
280  * @drm_primary_layer: Hardware layer serving as logical DRM primary layer
281  * @hw_master_layer: Base video streaming layer
282  * @hw_logo_layer: Hardware logo layer
283  * @planes: Mixer overlay layers
284  * @num_planes : number of planes
285  * @max_width : maximum width of plane
286  * @max_height : maximum height of plane
287  * @max_cursor_width : maximum cursor width
288  * @max_cursor_height: maximum cursor height
289  * @alpha_prop: Global layer alpha property
290  * @scale_prop: Layer scale property (1x, 2x or 4x)
291  * @bg_color: Background color property for primary layer
292  * @drm: core drm object
293  * @pixel_clock: pixel clock for mixer
294  * @pixel_clock_enabled: pixel clock status
295  * @dpms: mixer drm state
296  * @event: vblank pending event
297  *
298  * Contains pointers to logical constructions such as the DRM plane manager as
299  * well as pointers to distinquish the mixer layer serving as the DRM "primary"
300  * plane from the actual mixer layer which serves as the background layer in
301  * hardware.
302  *
303  */
304 struct xlnx_mix {
305         struct xlnx_mix_hw mixer_hw;
306         struct platform_device *master;
307         struct xlnx_crtc crtc;
308         struct xlnx_mix_plane *drm_primary_layer;
309         struct xlnx_mix_plane *hw_master_layer;
310         struct xlnx_mix_plane *hw_logo_layer;
311         struct xlnx_mix_plane *planes;
312         u32 num_planes;
313         u32 max_width;
314         u32 max_height;
315         u32 max_cursor_width;
316         u32 max_cursor_height;
317         struct drm_property *alpha_prop;
318         struct drm_property *scale_prop;
319         struct drm_property *bg_color;
320         struct drm_device *drm;
321         struct clk *pixel_clock;
322         bool pixel_clock_enabled;
323         int dpms;
324         struct drm_pending_vblank_event *event;
325 };
326
327 /**
328  * struct xlnx_mix_plane_dma - Xilinx drm plane VDMA object
329  *
330  * @chan: dma channel
331  * @xt: dma interleaved configuration template
332  * @sgl: data chunk for dma_interleaved_template
333  * @is_active: flag if the DMA is active
334  */
335 struct xlnx_mix_plane_dma {
336         struct dma_chan *chan;
337         struct dma_interleaved_template xt;
338         struct data_chunk sgl[1];
339         bool is_active;
340 };
341
342 /**
343  * struct xlnx_mix_plane - Xilinx drm plane object
344  *
345  * @base: base drm plane object
346  * @mixer_layer: video mixer hardware layer data instance
347  * @mixer: mixer DRM object
348  * @dma: dma object
349  * @id: plane id
350  * @dpms: current dpms level
351  * @format: pixel format
352  */
353 struct xlnx_mix_plane {
354         struct drm_plane base;
355         struct xlnx_mix_layer_data *mixer_layer;
356         struct xlnx_mix *mixer;
357         struct xlnx_mix_plane_dma dma[XVMIX_MAX_NUM_SUB_PLANES];
358         int id;
359         int dpms;
360         u32 format;
361 };
362
363 static inline void reg_writel(void __iomem *base, int offset, u32 val)
364 {
365         writel(val, base + offset);
366 }
367
368 static inline void reg_writeq(void __iomem *base, int offset, u64 val)
369 {
370         writel(upper_32_bits(val), base + offset);
371         writel(lower_32_bits(val), base + offset + 4);
372 }
373
374 static inline u32 reg_readl(void __iomem *base, int offset)
375 {
376         return readl(base + offset);
377 }
378
379 /**
380  * xlnx_mix_intrpt_enable_done - Enables interrupts
381  * @mixer: instance of mixer IP core
382  *
383  * Enables interrupts in the mixer core
384  */
385 static void xlnx_mix_intrpt_enable_done(struct xlnx_mix_hw *mixer)
386 {
387         u32 curr_val = reg_readl(mixer->base, XVMIX_IER);
388
389         /* Enable Interrupts */
390         reg_writel(mixer->base, XVMIX_IER, curr_val | XVMIX_IRQ_DONE_MASK);
391         reg_writel(mixer->base, XVMIX_GIE, XVMIX_GIE_EN_MASK);
392 }
393
394 /**
395  * xlnx_mix_intrpt_disable - Disable interrupts
396  * @mixer: instance of mixer IP core
397  *
398  * Disables interrupts in the mixer core
399  */
400 static void xlnx_mix_intrpt_disable(struct xlnx_mix_hw *mixer)
401 {
402         u32 curr_val =  reg_readl(mixer->base, XVMIX_IER);
403
404         reg_writel(mixer->base, XVMIX_IER, curr_val & (~XVMIX_IRQ_DONE_MASK));
405         reg_writel(mixer->base, XVMIX_GIE, 0);
406 }
407
408 /**
409  * xlnx_mix_start - Start the mixer core video generator
410  * @mixer: Mixer core instance for which to start video output
411  *
412  * Starts the core to generate a video frame.
413  */
414 static void xlnx_mix_start(struct xlnx_mix_hw *mixer)
415 {
416         u32 val;
417
418         val = XVMIX_AP_RST_MASK | XVMIX_AP_EN_MASK;
419         reg_writel(mixer->base, XVMIX_AP_CTRL, val);
420 }
421
422 /**
423  * xlnx_mix_stop - Stop the mixer core video generator
424  * @mixer: Mixer core instance for which to stop video output
425  *
426  * Starts the core to generate a video frame.
427  */
428 static void xlnx_mix_stop(struct xlnx_mix_hw *mixer)
429 {
430         reg_writel(mixer->base, XVMIX_AP_CTRL, 0);
431 }
432
433 static inline uint32_t xlnx_mix_get_intr_status(struct xlnx_mix_hw *mixer)
434 {
435         return reg_readl(mixer->base, XVMIX_ISR) & XVMIX_IRQ_DONE_MASK;
436 }
437
438 static inline void xlnx_mix_clear_intr_status(struct xlnx_mix_hw *mixer,
439                                               uint32_t intr)
440 {
441         reg_writel(mixer->base, XVMIX_ISR, intr);
442 }
443
444 /**
445  * xlnx_mix_get_layer_data - Retrieve current hardware and register
446  * values for a logical video layer
447  * @mixer: Mixer instance to interrogate
448  * @id: Id of layer for which data is requested
449  *
450  * Return:
451  * Structure containing layer-specific data; NULL upon failure
452  */
453 static struct xlnx_mix_layer_data *
454 xlnx_mix_get_layer_data(struct xlnx_mix_hw *mixer, enum xlnx_mix_layer_id id)
455 {
456         u32 i;
457         struct xlnx_mix_layer_data *layer_data;
458
459         for (i = 0; i <= (mixer->layer_cnt - 1); i++) {
460                 layer_data = &mixer->layer_data[i];
461                 if (layer_data->id == id)
462                         return layer_data;
463         }
464         return NULL;
465 }
466
467 /**
468  * xlnx_mix_set_active_area - Sets the number of active horizontal and
469  * vertical scan lines for the mixer background layer.
470  * @mixer: Mixer instance for which to set a new viewable area
471  * @hactive: Width of new background image dimension
472  * @vactive: Height of new background image dimension
473  *
474  * Minimum values are 64x64 with maximum values determined by the IP hardware
475  * design.
476  *
477  * Return:
478  * Zero on success, -EINVAL on failure
479  */
480 static int xlnx_mix_set_active_area(struct xlnx_mix_hw *mixer,
481                                     u32 hactive, u32 vactive)
482 {
483         struct xlnx_mix_layer_data *ld =
484                 xlnx_mix_get_layer_data(mixer, XVMIX_LAYER_MASTER);
485
486         if (hactive > ld->hw_config.max_width ||
487             vactive > ld->hw_config.max_height) {
488                 DRM_ERROR("Invalid layer dimention\n");
489                 return -EINVAL;
490         }
491         /* set resolution */
492         reg_writel(mixer->base, XVMIX_HEIGHT_DATA, vactive);
493         reg_writel(mixer->base, XVMIX_WIDTH_DATA, hactive);
494         ld->layer_regs.width  = hactive;
495         ld->layer_regs.height = vactive;
496
497         return 0;
498 }
499
500 /**
501  * is_window_valid - Validate requested plane dimensions
502  * @mixer: Mixer core instance for which to stop video output
503  * @x_pos: x position requested for start of plane
504  * @y_pos: y position requested for start of plane
505  * @width: width of plane
506  * @height: height of plane
507  * @scale: scale factor of plane
508  *
509  * Validates if the requested window is within the frame boundary
510  *
511  * Return:
512  * true on success, false on failure
513  */
514 static bool is_window_valid(struct xlnx_mix_hw *mixer, u32 x_pos, u32 y_pos,
515                             u32 width, u32 height, u32 scale)
516 {
517         struct xlnx_mix_layer_data *master_layer;
518         int scale_factor[3] = {1, 2, 4};
519
520         master_layer = xlnx_mix_get_layer_data(mixer, XVMIX_LAYER_MASTER);
521
522         /* Check if window scale factor is set */
523         if (scale < XVMIX_SCALE_FACTOR_INVALID) {
524                 width  *= scale_factor[scale];
525                 height *= scale_factor[scale];
526         }
527
528         /* verify overlay falls within currently active background area */
529         if (((x_pos + width)  <= master_layer->layer_regs.width) &&
530             ((y_pos + height) <= master_layer->layer_regs.height))
531                 return true;
532
533         DRM_ERROR("Requested plane dimensions can't be set\n");
534         return false;
535 }
536
537 /**
538  *  xlnx_mix_layer_enable - Enables the requested layers
539  * @mixer: Mixer instance in which to enable a video layer
540  * @id: Logical id (e.g. 8 = logo layer) to enable
541  *
542  * Enables (permit video output) for layers in mixer
543  * Enables the layer denoted by id in the IP core.
544  * Layer 0 will indicate the background layer and layer 8 the logo
545  * layer. Passing in the enum value XVMIX_LAYER_ALL will enable all
546  */
547 static void xlnx_mix_layer_enable(struct xlnx_mix_hw *mixer,
548                                   enum xlnx_mix_layer_id id)
549 {
550         struct xlnx_mix_layer_data *layer_data;
551         u32 curr_state;
552
553         /* Ensure layer is marked as 'active' by application before
554          * turning on in hardware.  In some cases, layer register data
555          * may be written to otherwise inactive layers in lieu of, eventually,
556          * turning them on.
557          */
558         layer_data = xlnx_mix_get_layer_data(mixer, id);
559         if (!layer_data) {
560                 DRM_ERROR("Invalid layer id %d\n", id);
561                 return;
562         }
563         if (!layer_data->layer_regs.is_active)
564                 return; /* for inactive layers silently return */
565
566         /* Check if request is to enable all layers or single layer */
567         if (id == XVMIX_LAYER_ALL) {
568                 reg_writel(mixer->base, XVMIX_LAYERENABLE_DATA,
569                            XVMIX_MASK_ENABLE_ALL_LAYERS);
570
571         } else if ((id < mixer->layer_cnt) ||
572                    ((id == XVMIX_LAYER_LOGO) && mixer->logo_layer_en)) {
573                 curr_state = reg_readl(mixer->base, XVMIX_LAYERENABLE_DATA);
574                 if (id == XVMIX_LAYER_LOGO)
575                         curr_state |= XVMIX_LOGO_EN;
576                 else
577                         curr_state |= BIT(id);
578                 reg_writel(mixer->base, XVMIX_LAYERENABLE_DATA, curr_state);
579         } else {
580                 DRM_ERROR("Can't enable requested layer %d\n", id);
581         }
582 }
583
584 /**
585  * xlnx_mix_disp_layer_enable - Enables video output represented by the
586  * plane object
587  * @plane: Drm plane object describing video layer to enable
588  *
589  */
590 static void xlnx_mix_disp_layer_enable(struct xlnx_mix_plane *plane)
591 {
592         struct xlnx_mix_hw *mixer_hw;
593         struct xlnx_mix_layer_data *l_data;
594         u32 id;
595
596         if (!plane)
597                 return;
598         mixer_hw = to_mixer_hw(plane);
599         l_data = plane->mixer_layer;
600         id = l_data->id;
601         if (id < XVMIX_LAYER_MASTER  || id > XVMIX_LAYER_LOGO) {
602                 DRM_DEBUG_KMS("Attempt to activate invalid layer: %d\n", id);
603                 return;
604         }
605         if (id == XVMIX_LAYER_MASTER && !l_data->hw_config.is_streaming)
606                 return;
607
608         xlnx_mix_layer_enable(mixer_hw, id);
609 }
610
611 /**
612  * xlnx_mix_layer_disable - Disables the requested layer
613  * @mixer:  Mixer for which the layer will be disabled
614  * @id: Logical id of the layer to be disabled (0-8)
615  *
616  * Disables the layer denoted by layer_id in the IP core.
617  * Layer 0 will indicate the background layer and layer 8 the logo
618  * layer. Passing in the enum value XVMIX_LAYER_ALL will disable all
619  * layers.
620  */
621 static void xlnx_mix_layer_disable(struct xlnx_mix_hw *mixer,
622                                    enum xlnx_mix_layer_id id)
623 {
624         u32 num_layers, curr_state;
625
626         num_layers = mixer->layer_cnt;
627
628         if (id == XVMIX_LAYER_ALL) {
629                 reg_writel(mixer->base, XVMIX_LAYERENABLE_DATA,
630                            XVMIX_MASK_DISABLE_ALL_LAYERS);
631         } else if ((id < num_layers) ||
632                    ((id == XVMIX_LAYER_LOGO) && (mixer->logo_layer_en))) {
633                 curr_state = reg_readl(mixer->base, XVMIX_LAYERENABLE_DATA);
634                 if (id == XVMIX_LAYER_LOGO)
635                         curr_state &= ~XVMIX_LOGO_EN;
636                 else
637                         curr_state &= ~(BIT(id));
638                 reg_writel(mixer->base, XVMIX_LAYERENABLE_DATA, curr_state);
639         } else {
640                 DRM_ERROR("Can't disable requested layer %d\n", id);
641         }
642 }
643
644 /**
645  * xlnx_mix_disp_layer_disable - Disables video output represented by the
646  * plane object
647  * @plane: Drm plane object describing video layer to disable
648  *
649  */
650 static void xlnx_mix_disp_layer_disable(struct xlnx_mix_plane *plane)
651 {
652         struct xlnx_mix_hw *mixer_hw;
653         u32 layer_id;
654
655         if (plane)
656                 mixer_hw = to_mixer_hw(plane);
657         else
658                 return;
659         layer_id = plane->mixer_layer->id;
660         if (layer_id < XVMIX_LAYER_MASTER  || layer_id > XVMIX_LAYER_LOGO)
661                 return;
662
663         xlnx_mix_layer_disable(mixer_hw, layer_id);
664 }
665
666 static int xlnx_mix_mark_layer_inactive(struct xlnx_mix_plane *plane)
667 {
668         if (!plane || !plane->mixer_layer)
669                 return -ENODEV;
670
671         plane->mixer_layer->layer_regs.is_active = false;
672
673         return 0;
674 }
675
676 /* apply mode to plane pipe */
677 static void xlnx_mix_plane_commit(struct drm_plane *base_plane)
678 {
679         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
680         struct dma_async_tx_descriptor *desc;
681         enum dma_ctrl_flags flags;
682         unsigned int i;
683
684         /* for xlnx video framebuffer dma, if used */
685         xilinx_xdma_drm_config(plane->dma[0].chan, plane->format);
686         for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++) {
687                 struct xlnx_mix_plane_dma *dma = &plane->dma[i];
688
689                 if (dma->chan && dma->is_active) {
690                         flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
691                         desc = dmaengine_prep_interleaved_dma(dma->chan,
692                                                               &dma->xt,
693                                                               flags);
694                         if (!desc) {
695                                 DRM_ERROR("failed to prepare DMA descriptor\n");
696                                 return;
697                         }
698                         dmaengine_submit(desc);
699                         dma_async_issue_pending(dma->chan);
700                 }
701         }
702 }
703
704 static int xlnx_mix_plane_get_max_width(struct drm_plane *base_plane)
705 {
706         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
707
708         return plane->mixer->max_width;
709 }
710
711 static int xlnx_mix_plane_get_max_height(struct drm_plane *base_plane)
712 {
713         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
714
715         return plane->mixer->max_height;
716 }
717
718 static int xlnx_mix_plane_get_max_cursor_width(struct drm_plane *base_plane)
719 {
720         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
721
722         return plane->mixer->max_cursor_width;
723 }
724
725 static int xlnx_mix_plane_get_max_cursor_height(struct drm_plane *base_plane)
726 {
727         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
728
729         return plane->mixer->max_cursor_height;
730 }
731
732 static int xlnx_mix_crtc_get_max_width(struct xlnx_crtc *crtc)
733 {
734         return xlnx_mix_plane_get_max_width(crtc->crtc.primary);
735 }
736
737 static int xlnx_mix_crtc_get_max_height(struct xlnx_crtc *crtc)
738 {
739         return xlnx_mix_plane_get_max_height(crtc->crtc.primary);
740 }
741
742 static unsigned int xlnx_mix_crtc_get_max_cursor_width(struct xlnx_crtc *crtc)
743 {
744         return xlnx_mix_plane_get_max_cursor_width(crtc->crtc.primary);
745 }
746
747 static unsigned int xlnx_mix_crtc_get_max_cursor_height(struct xlnx_crtc *crtc)
748 {
749         return xlnx_mix_plane_get_max_cursor_height(crtc->crtc.primary);
750 }
751
752 /**
753  * xlnx_mix_crtc_get_format - Get the current device format
754  * @crtc: xlnx crtc object
755  *
756  * Get the current format of pipeline
757  *
758  * Return: the corresponding DRM_FORMAT_XXX
759  */
760 static uint32_t xlnx_mix_crtc_get_format(struct xlnx_crtc *crtc)
761 {
762         struct xlnx_mix_plane *plane = to_xlnx_plane(crtc->crtc.primary);
763
764         return plane->format;
765 }
766
767 /**
768  * xlnx_mix_crtc_get_align - Get the alignment value for pitch
769  * @crtc: xlnx crtc object
770  *
771  * Get the alignment value for pitch from the plane
772  *
773  * Return: The alignment value if successful, or the error code.
774  */
775 static unsigned int xlnx_mix_crtc_get_align(struct xlnx_crtc *crtc)
776 {
777         struct xlnx_mix_plane *plane = to_xlnx_plane(crtc->crtc.primary);
778         struct xlnx_mix *m = plane->mixer;
779
780         return XVMIX_BASE_ALIGN * m->mixer_hw.ppc;
781 }
782
783 /**
784  * xlnx_mix_attach_plane_prop - Attach mixer-specific drm property to
785  * the given plane
786  * @plane: Xilinx drm plane object to inspect and attach appropriate
787  *  properties to
788  *
789  * The linked mixer layer will be inspected to see what capabilities it offers
790  * (e.g. global layer alpha; scaling) and drm property objects that indicate
791  * those capabilities will then be attached and initialized to default values.
792  */
793 static void xlnx_mix_attach_plane_prop(struct xlnx_mix_plane *plane)
794 {
795         struct drm_mode_object *base = &plane->base.base;
796         struct xlnx_mix *mixer = plane->mixer;
797
798         if (plane->mixer_layer->hw_config.can_scale)
799                 drm_object_attach_property(base, mixer->scale_prop,
800                                            XVMIX_SCALE_FACTOR_1X);
801         if (plane->mixer_layer->hw_config.can_alpha)
802                 drm_object_attach_property(base, mixer->alpha_prop,
803                                            XVMIX_ALPHA_MAX);
804 }
805
806 static int xlnx_mix_mark_layer_active(struct xlnx_mix_plane *plane)
807 {
808         if (!plane->mixer_layer)
809                 return -ENODEV;
810         plane->mixer_layer->layer_regs.is_active = true;
811
812         return 0;
813 }
814
815 static bool xlnx_mix_isfmt_support(u32 format)
816 {
817         int i;
818
819         for (i = 0; i < ARRAY_SIZE(color_table); i++) {
820                 if (format == color_table[i])
821                         return true;
822         }
823         return false;
824 }
825
826 /*************** DISPLAY ************/
827
828 /**
829  * xlnx_mix_get_layer_scaling - Get layer scaling factor
830  * @mixer: Mixer instance to program with new background color
831  * @id: Plane id
832  *
833  * Applicable only for overlay layers
834  *
835  * Return:
836  * scaling factor of the specified layer
837  */
838 static int xlnx_mix_get_layer_scaling(struct xlnx_mix_hw *mixer,
839                                       enum xlnx_mix_layer_id id)
840 {
841         int scale_factor = 0;
842         u32 reg;
843         struct xlnx_mix_layer_data *l_data = xlnx_mix_get_layer_data(mixer, id);
844
845         switch (id) {
846         case XVMIX_LAYER_LOGO:
847                 if (mixer->logo_layer_en) {
848                         reg = XVMIX_LOGOSCALEFACTOR_DATA;
849                         scale_factor = reg_readl(mixer->base, reg);
850                         l_data->layer_regs.scale_fact = scale_factor;
851                 }
852                 break;
853
854         default: /*Layer0-Layer7*/
855                 if (id < XVMIX_LAYER_LOGO && l_data->hw_config.can_scale) {
856                         reg = XVMIX_LAYERSCALE_0_DATA + (id * XVMIX_REG_OFFSET);
857                         scale_factor = reg_readl(mixer->base, reg);
858                         l_data->layer_regs.scale_fact = scale_factor;
859                 }
860                 break;
861         }
862         return scale_factor;
863 }
864
865 /**
866  * xlnx_mix_set_layer_window - Sets the position of an overlay layer
867  * @mixer: Specific mixer object instance controlling the video
868  * @id: Logical layer id (1-7) to be positioned
869  * @x_pos: new: Column to start display of overlay layer
870  * @y_pos: new: Row to start display of overlay layer
871  * @width: Number of active columns to dislay for overlay layer
872  * @height: Number of active columns to display for overlay layer
873  * @stride: Width in bytes of overaly memory buffer (memory layer only)
874  *
875  * Sets the position of an overlay layer over the background layer (layer 0)
876  * Applicable only for layers 1-7 or the logo layer
877  *
878  * Return:
879  * Zero on success, -EINVAL if position is invalid or -ENODEV if layer
880  */
881 static int xlnx_mix_set_layer_window(struct xlnx_mix_hw *mixer,
882                                      enum xlnx_mix_layer_id id, u32 x_pos,
883                                      u32 y_pos, u32 width, u32 height,
884                                      u32 stride)
885 {
886         struct xlnx_mix_layer_data *l_data;
887         u32 scale = 0;
888         int status = -EINVAL;
889         u32 x_reg, y_reg, w_reg, h_reg, s_reg;
890         u32 off;
891
892         l_data = xlnx_mix_get_layer_data(mixer, id);
893         if (!l_data)
894                 return status;
895
896         scale = xlnx_mix_get_layer_scaling(mixer, id);
897         if (!is_window_valid(mixer, x_pos, y_pos, width, height, scale))
898                 return status;
899
900         switch (id) {
901         case XVMIX_LAYER_LOGO:
902                 if (!(mixer->logo_layer_en &&
903                       width <= l_data->hw_config.max_width &&
904                       height <= l_data->hw_config.max_height &&
905                       height >= l_data->hw_config.min_height &&
906                       width >= l_data->hw_config.min_width))
907                         return status;
908
909                 x_reg = XVMIX_LOGOSTARTX_DATA;
910                 y_reg = XVMIX_LOGOSTARTY_DATA;
911                 w_reg = XVMIX_LOGOWIDTH_DATA;
912                 h_reg = XVMIX_LOGOHEIGHT_DATA;
913                 reg_writel(mixer->base, x_reg, x_pos);
914                 reg_writel(mixer->base, y_reg, y_pos);
915                 reg_writel(mixer->base, w_reg, width);
916                 reg_writel(mixer->base, h_reg, height);
917                 l_data->layer_regs.x_pos = x_pos;
918                 l_data->layer_regs.y_pos = y_pos;
919                 l_data->layer_regs.width = width;
920                 l_data->layer_regs.height = height;
921                 status = 0;
922                 break;
923
924         default: /*Layer1-Layer7*/
925
926                 if (!(id < mixer->layer_cnt &&
927                       width <= l_data->hw_config.max_width &&
928                       width >= l_data->hw_config.min_width))
929                         return status;
930                 x_reg = XVMIX_LAYERSTARTX_0_DATA;
931                 y_reg = XVMIX_LAYERSTARTY_0_DATA;
932                 w_reg = XVMIX_LAYERWIDTH_0_DATA;
933                 h_reg = XVMIX_LAYERHEIGHT_0_DATA;
934                 s_reg = XVMIX_LAYERSTRIDE_0_DATA;
935
936                 off = id * XVMIX_REG_OFFSET;
937                 reg_writel(mixer->base, (x_reg + off), x_pos);
938                 reg_writel(mixer->base, (y_reg + off), y_pos);
939                 reg_writel(mixer->base, (w_reg + off), width);
940                 reg_writel(mixer->base, (h_reg + off), height);
941                 l_data->layer_regs.x_pos = x_pos;
942                 l_data->layer_regs.y_pos = y_pos;
943                 l_data->layer_regs.width = width;
944                 l_data->layer_regs.height = height;
945
946                 if (!l_data->hw_config.is_streaming)
947                         reg_writel(mixer->base, (s_reg + off), stride);
948                 status = 0;
949                 break;
950         }
951         return status;
952 }
953
954 /**
955  * xlnx_mix_set_layer_dimensions - Set layer dimensions
956  * @plane: Drm plane object desribing video layer to reposition
957  * @crtc_x: New horizontal anchor postion from which to begin rendering
958  * @crtc_y: New vertical anchor position from which to begin rendering
959  * @width: Width, in pixels, to render from stream or memory buffer
960  * @height: Height, in pixels, to render from stream or memory buffer
961  * @stride: Width, in bytes, of a memory buffer.  Used only for
962  *  memory layers.  Use 0 for streaming layers.
963  *
964  * Establishes new coordinates and dimensions for a video plane layer
965  * New size and coordinates of window must fit within the currently active
966  * area of the crtc (e.g. the background resolution)
967  *
968  * Return: 0 if successful; Either -EINVAL if coordindate data is invalid
969  * or -ENODEV if layer data not present
970  */
971 static int xlnx_mix_set_layer_dimensions(struct xlnx_mix_plane *plane,
972                                          u32 crtc_x, u32 crtc_y,
973                                           u32 width, u32 height, u32 stride)
974 {
975         struct xlnx_mix *mixer = plane->mixer;
976         struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
977         struct xlnx_mix_layer_data *layer_data;
978         enum xlnx_mix_layer_id layer_id;
979         int ret = 0;
980
981         layer_data = plane->mixer_layer;
982         layer_id = layer_data->id;
983         if (layer_data->layer_regs.height != height ||
984             layer_data->layer_regs.width != width) {
985                 if (mixer->drm_primary_layer == plane)
986                         xlnx_mix_layer_disable(mixer_hw, XVMIX_LAYER_MASTER);
987
988                 xlnx_mix_layer_disable(mixer_hw, layer_id);
989         }
990         if (mixer->drm_primary_layer == plane) {
991                 crtc_x = 0;
992                 crtc_y = 0;
993                 ret = xlnx_mix_set_active_area(mixer_hw, width, height);
994                 if (ret)
995                         return ret;
996                 xlnx_mix_layer_enable(mixer_hw, XVMIX_LAYER_MASTER);
997         }
998         if (layer_id != XVMIX_LAYER_MASTER && layer_id < XVMIX_LAYER_ALL) {
999                 ret = xlnx_mix_set_layer_window(mixer_hw, layer_id, crtc_x,
1000                                                 crtc_y, width, height, stride);
1001                 if (ret)
1002                         return ret;
1003                 xlnx_mix_disp_layer_enable(plane);
1004         }
1005         return ret;
1006 }
1007
1008 /**
1009  * xlnx_mix_set_layer_scaling - Sets scaling factor
1010  * @mixer: Instance of mixer to be subject of scaling request
1011  * @id: Logical id of video layer subject to new scale setting
1012  * @scale: scale Factor (1x, 2x or 4x) for horiz. and vert. dimensions
1013  *
1014  * Sets the scaling factor for the specified video layer
1015  * Not applicable to background stream layer (layer 0)
1016  *
1017  * Return:
1018  * Zero on success, -EINVAL on failure to set scale for layer (likely
1019  * returned if resulting size of layer exceeds dimensions of active
1020  * display area
1021  */
1022 static int xlnx_mix_set_layer_scaling(struct xlnx_mix_hw *mixer,
1023                                       enum xlnx_mix_layer_id id, u32 scale)
1024 {
1025         void __iomem *reg = mixer->base;
1026         struct xlnx_mix_layer_data *l_data;
1027         int status = 0;
1028         u32 x_pos, y_pos, width, height, offset;
1029
1030         l_data = xlnx_mix_get_layer_data(mixer, id);
1031         x_pos = l_data->layer_regs.x_pos;
1032         y_pos = l_data->layer_regs.y_pos;
1033         width  = l_data->layer_regs.width;
1034         height = l_data->layer_regs.height;
1035
1036         if (!is_window_valid(mixer, x_pos, y_pos, width, height, scale))
1037                 return -EINVAL;
1038
1039         switch (id) {
1040         case XVMIX_LAYER_LOGO:
1041                 if (mixer->logo_layer_en) {
1042                         reg_writel(reg, XVMIX_LOGOSCALEFACTOR_DATA, scale);
1043                         l_data->layer_regs.scale_fact = scale;
1044                         status = 0;
1045                 }
1046                 break;
1047
1048         default: /* Layer0-Layer7 */
1049                 if (id < mixer->layer_cnt && l_data->hw_config.can_scale) {
1050                         offset = id * XVMIX_REG_OFFSET;
1051
1052                         reg_writel(reg, (XVMIX_LAYERSCALE_0_DATA + offset),
1053                                    scale);
1054                         l_data->layer_regs.scale_fact = scale;
1055                         status = 0;
1056                 }
1057                 break;
1058         }
1059         return status;
1060 }
1061
1062 /**
1063  * xlnx_mix_set_layer_scale - Change video scale factor for video plane
1064  * @plane: Drm plane object describing layer to be modified
1065  * @val: Index of scale factor to use:
1066  *              0 = 1x
1067  *              1 = 2x
1068  *              2 = 4x
1069  *
1070  * Return:
1071  * Zero on success, either -EINVAL if scale value is illegal or
1072  * -ENODEV if layer does not exist (null)
1073  */
1074 static int xlnx_mix_set_layer_scale(struct xlnx_mix_plane *plane,
1075                                     uint64_t val)
1076 {
1077         struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
1078         struct xlnx_mix_layer_data *layer = plane->mixer_layer;
1079         int ret;
1080
1081         if (!layer || !layer->hw_config.can_scale)
1082                 return -ENODEV;
1083         if (val > XVMIX_SCALE_FACTOR_4X || val < XVMIX_SCALE_FACTOR_1X) {
1084                 DRM_ERROR("Mixer layer scale value illegal.\n");
1085                 return -EINVAL;
1086         }
1087         xlnx_mix_disp_layer_disable(plane);
1088         msleep(50);
1089         ret = xlnx_mix_set_layer_scaling(mixer_hw, layer->id, val);
1090         xlnx_mix_disp_layer_enable(plane);
1091
1092         return ret;
1093 }
1094
1095 /**
1096  * xlnx_mix_set_layer_alpha - Set the alpha value
1097  * @mixer: Instance of mixer controlling layer to modify
1098  * @layer_id: Logical id of video overlay to adjust alpha setting
1099  * @alpha: Desired alpha setting (0-255) for layer specified
1100  *            255 = completely opaque
1101  *            0 = fully transparent
1102  *
1103  * Set the layer global transparency for a video overlay
1104  * Not applicable to background streaming layer
1105  *
1106  * Return:
1107  * Zero on success, -EINVAL on failure
1108  */
1109 static int xlnx_mix_set_layer_alpha(struct xlnx_mix_hw *mixer,
1110                                     enum xlnx_mix_layer_id layer_id, u32 alpha)
1111 {
1112         struct xlnx_mix_layer_data *layer_data;
1113         u32 reg;
1114         int status = -EINVAL;
1115
1116         layer_data = xlnx_mix_get_layer_data(mixer, layer_id);
1117         switch (layer_id) {
1118         case XVMIX_LAYER_LOGO:
1119                 if (mixer->logo_layer_en) {
1120                         reg = XVMIX_LOGOALPHA_DATA;
1121                         reg_writel(mixer->base, reg, alpha);
1122                         layer_data->layer_regs.alpha = alpha;
1123                         status = 0;
1124                 }
1125                 break;
1126
1127         default: /*Layer1-Layer7*/
1128                 if (layer_id < mixer->layer_cnt &&
1129                     layer_data->hw_config.can_alpha) {
1130                         u32 offset =  layer_id * XVMIX_REG_OFFSET;
1131
1132                         reg = XVMIX_LAYERALPHA_0_DATA;
1133                         reg_writel(mixer->base, (reg + offset), alpha);
1134                         layer_data->layer_regs.alpha = alpha;
1135                         status = 0;
1136                 }
1137                 break;
1138         }
1139         return status;
1140 }
1141
1142 /**
1143  * xlnx_mix_disp_set_layer_alpha - Change the transparency of an entire plane
1144  * @plane: Video layer affected by new alpha setting
1145  * @val: Value of transparency setting (0-255) with 255 being opaque
1146  *  0 being fully transparent
1147  *
1148  * Return:
1149  * Zero on success, -EINVAL on failure
1150  */
1151 static int xlnx_mix_disp_set_layer_alpha(struct xlnx_mix_plane *plane,
1152                                          uint64_t val)
1153 {
1154         struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
1155         struct xlnx_mix_layer_data *layer = plane->mixer_layer;
1156
1157         if (!layer || !layer->hw_config.can_alpha)
1158                 return -ENODEV;
1159         if (val > XVMIX_ALPHA_MAX || val < XVMIX_ALPHA_MIN) {
1160                 DRM_ERROR("Mixer layer alpha dts value illegal.\n");
1161                 return -EINVAL;
1162         }
1163         return xlnx_mix_set_layer_alpha(mixer_hw, layer->id, val);
1164 }
1165
1166 /**
1167  * xlnx_mix_set_layer_buff_addr - Set buff addr for layer
1168  * @mixer: Instance of mixer controlling layer to modify
1169  * @id: Logical id of video overlay to adjust alpha setting
1170  * @luma_addr: Start address of plane 1 of frame buffer for layer 1
1171  * @chroma_addr: Start address of plane 2 of frame buffer for layer 1
1172  *
1173  * Sets the buffer address of the specified layer
1174  * Return:
1175  * Zero on success, -EINVAL on failure
1176  */
1177 static int xlnx_mix_set_layer_buff_addr(struct xlnx_mix_hw *mixer,
1178                                         enum xlnx_mix_layer_id id,
1179                                         u64 luma_addr, u64 chroma_addr)
1180 {
1181         struct xlnx_mix_layer_data *layer_data;
1182         u32 align, offset;
1183         u32 reg1, reg2;
1184
1185         if (id >= mixer->layer_cnt)
1186                 return -EINVAL;
1187
1188         /* Check if addr is aligned to aximm width (PPC * 64-bits) */
1189         align = mixer->ppc * 8;
1190         if ((luma_addr % align) != 0 || (chroma_addr % align) != 0)
1191                 return -EINVAL;
1192
1193         offset = (id - 1) * XVMIX_REG_OFFSET;
1194         reg1 = XVMIX_LAYER1_BUF1_V_DATA + offset;
1195         reg2 = XVMIX_LAYER1_BUF2_V_DATA + offset;
1196         layer_data = &mixer->layer_data[id];
1197         if (mixer->dma_addr_size == 64 && sizeof(dma_addr_t) == 8) {
1198                 reg_writeq(mixer->base, reg1, luma_addr);
1199                 reg_writeq(mixer->base, reg2, chroma_addr);
1200         } else {
1201                 reg_writel(mixer->base, reg1, (u32)luma_addr);
1202                 reg_writel(mixer->base, reg2, (u32)chroma_addr);
1203         }
1204         layer_data->layer_regs.buff_addr1 = luma_addr;
1205         layer_data->layer_regs.buff_addr2 = chroma_addr;
1206
1207         return 0;
1208 }
1209
1210 /**
1211  * xlnx_mix_hw_plane_dpms - Implementation of display power management
1212  * system call (dpms).
1213  * @plane: Plane/mixer layer to enable/disable (based on dpms value)
1214  * @dpms: Display power management state to act upon
1215  *
1216  * Designed to disable and turn off a plane and restore all attached drm
1217  * properities to their initial values.  Alterntively, if dpms is "on", will
1218  * enable a layer.
1219  */
1220
1221 static void
1222 xlnx_mix_hw_plane_dpms(struct xlnx_mix_plane *plane, int dpms)
1223 {
1224         struct xlnx_mix *mixer;
1225
1226         if (!plane->mixer)
1227                 return;
1228         mixer = plane->mixer;
1229         plane->dpms = dpms;
1230
1231         switch (dpms) {
1232         case DRM_MODE_DPMS_ON:
1233                 xlnx_mix_disp_layer_enable(plane);
1234                 break;
1235         default:
1236                 xlnx_mix_mark_layer_inactive(plane);
1237                 xlnx_mix_disp_layer_disable(plane);
1238                 /* restore to default property values */
1239                 if (mixer->alpha_prop)
1240                         xlnx_mix_disp_set_layer_alpha(plane, XVMIX_ALPHA_MAX);
1241                 if (mixer->scale_prop)
1242                         xlnx_mix_set_layer_scale(plane, XVMIX_SCALE_FACTOR_1X);
1243         }
1244 }
1245
1246 static void xlnx_mix_plane_dpms(struct drm_plane *base_plane, int dpms)
1247 {
1248         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
1249         unsigned int i;
1250
1251         DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
1252         DRM_DEBUG_KMS("dpms: %d -> %d\n", plane->dpms, dpms);
1253
1254         if (plane->dpms == dpms)
1255                 return;
1256         plane->dpms = dpms;
1257         switch (dpms) {
1258         case DRM_MODE_DPMS_ON:
1259                 /* start dma engine */
1260                 for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++)
1261                         if (plane->dma[i].chan && plane->dma[i].is_active)
1262                                 dma_async_issue_pending(plane->dma[i].chan);
1263                 xlnx_mix_hw_plane_dpms(plane, dpms);
1264                 break;
1265         default:
1266                 xlnx_mix_hw_plane_dpms(plane, dpms);
1267                 /* stop dma engine and release descriptors */
1268                 for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++) {
1269                         if (plane->dma[i].chan && plane->dma[i].is_active) {
1270                                 dmaengine_terminate_sync(plane->dma[i].chan);
1271                                 plane->dma[i].is_active = false;
1272                         }
1273                 }
1274                 break;
1275         }
1276 }
1277
1278 static int
1279 xlnx_mix_disp_plane_atomic_set_property(struct drm_plane *base_plane,
1280                                         struct drm_plane_state *state,
1281                                       struct drm_property *property, u64 val)
1282 {
1283         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
1284         struct xlnx_mix *mixer = plane->mixer;
1285
1286         if (property == mixer->alpha_prop)
1287                 return xlnx_mix_disp_set_layer_alpha(plane, val);
1288         else if (property == mixer->scale_prop)
1289                 return xlnx_mix_set_layer_scale(plane, val);
1290         else
1291                 return -EINVAL;
1292         return 0;
1293 }
1294
1295 static int
1296 xlnx_mix_disp_plane_atomic_get_property(struct drm_plane *base_plane,
1297                                         const struct drm_plane_state *state,
1298                                       struct drm_property *property,
1299                                       uint64_t *val)
1300 {
1301         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
1302         struct xlnx_mix *mixer = plane->mixer;
1303         struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
1304         u32 layer_id = plane->mixer_layer->id;
1305
1306         if (property == mixer->alpha_prop)
1307                 *val = mixer_hw->layer_data[layer_id].layer_regs.alpha;
1308         else if (property == mixer->scale_prop)
1309                 *val = mixer_hw->layer_data[layer_id].layer_regs.scale_fact;
1310         else
1311                 return -EINVAL;
1312
1313         return 0;
1314 }
1315
1316 static struct drm_plane_funcs xlnx_mix_plane_funcs = {
1317         .update_plane   = drm_atomic_helper_update_plane,
1318         .disable_plane  = drm_atomic_helper_disable_plane,
1319         .atomic_set_property    = xlnx_mix_disp_plane_atomic_set_property,
1320         .atomic_get_property    = xlnx_mix_disp_plane_atomic_get_property,
1321         .destroy                = drm_plane_cleanup,
1322         .reset                  = drm_atomic_helper_plane_reset,
1323         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
1324         .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
1325 };
1326
1327 /**
1328  * xlnx_mix_logo_load - Loads mixer's internal bram
1329  * @mixer: Mixer instance to act upon
1330  * @logo_w: Width of logo in pixels
1331  * @logo_h: Height of logo in pixels
1332  * @r_buf: Pointer to byte buffer array of R data values
1333  * @g_buf: Pointer to byte buffer array of G data values
1334  * @b_buf: Pointer to byte buffer array of B data values
1335  * @a_buf: Pointer to byte buffer array of A data values
1336  *
1337  * Loads mixer's internal bram with planar R, G, B and A data
1338  *
1339  * Return:
1340  * Zero on success, -ENODEV if logo layer not enabled; -EINVAL otherwise
1341  */
1342 static int xlnx_mix_logo_load(struct xlnx_mix_hw *mixer, u32 logo_w, u32 logo_h,
1343                               u8 *r_buf, u8 *g_buf, u8 *b_buf, u8 *a_buf)
1344 {
1345         void __iomem *reg = mixer->base;
1346         struct xlnx_mix_layer_data *layer_data;
1347
1348         int x;
1349         u32 shift;
1350         u32 rword, gword, bword, aword;
1351         u32 pixel_cnt = logo_w * logo_h;
1352         u32 unaligned_pix_cnt = pixel_cnt % 4;
1353         u32 width, height, curr_x_pos, curr_y_pos;
1354         u32 rbase_addr, gbase_addr, bbase_addr, abase_addr;
1355
1356         layer_data = xlnx_mix_get_layer_data(mixer, XVMIX_LAYER_LOGO);
1357         rword = 0;
1358         gword = 0;
1359         bword = 0;
1360         aword = 0;
1361
1362         if (!layer_data)
1363                 return -ENODEV;
1364
1365         /* RGBA data should be 32-bit word aligned */
1366         if (unaligned_pix_cnt && mixer->logo_pixel_alpha_enabled)
1367                 return -EINVAL;
1368
1369         if (!(mixer->logo_layer_en &&
1370               logo_w <= layer_data->hw_config.max_width &&
1371             logo_h <= layer_data->hw_config.max_height))
1372                 return -EINVAL;
1373
1374         width  = logo_w;
1375         height = logo_h;
1376         rbase_addr = XVMIX_LOGOR_V_BASE;
1377         gbase_addr = XVMIX_LOGOG_V_BASE;
1378         bbase_addr = XVMIX_LOGOB_V_BASE;
1379         abase_addr = XVMIX_LOGOA_V_BASE;
1380
1381         for (x = 0; x < pixel_cnt; x++) {
1382                 shift = (x % 4) * 8;
1383                 rword |= r_buf[x] << shift;
1384                 gword |= g_buf[x] << shift;
1385                 bword |= b_buf[x] << shift;
1386                 if (mixer->logo_pixel_alpha_enabled)
1387                         aword |= a_buf[x] << shift;
1388
1389                 if (x % 4 == 3) {
1390                         reg_writel(reg, (rbase_addr + (x - 3)), rword);
1391                         reg_writel(reg, (gbase_addr + (x - 3)), gword);
1392                         reg_writel(reg, (bbase_addr + (x - 3)), bword);
1393                         if (mixer->logo_pixel_alpha_enabled)
1394                                 reg_writel(reg, (abase_addr + (x - 3)), aword);
1395                 }
1396         }
1397
1398         curr_x_pos = layer_data->layer_regs.x_pos;
1399         curr_y_pos = layer_data->layer_regs.y_pos;
1400         return xlnx_mix_set_layer_window(mixer, XVMIX_LAYER_LOGO, curr_x_pos,
1401                                          curr_y_pos, logo_w, logo_h, 0);
1402 }
1403
1404 static int xlnx_mix_update_logo_img(struct xlnx_mix_plane *plane,
1405                                     struct drm_gem_cma_object *buffer,
1406                                      u32 src_w, u32 src_h)
1407 {
1408         struct xlnx_mix_layer_data *logo_layer = plane->mixer_layer;
1409         size_t pixel_cnt = src_h * src_w;
1410         /* color comp defaults to offset in RG24 buffer */
1411         u32 pix_cmp_cnt;
1412         u32 logo_cmp_cnt;
1413         bool per_pixel_alpha = false;
1414         u32 max_width = logo_layer->hw_config.max_width;
1415         u32 max_height = logo_layer->hw_config.max_height;
1416         u32 min_width = logo_layer->hw_config.min_width;
1417         u32 min_height = logo_layer->hw_config.min_height;
1418         u8 *r_data = NULL;
1419         u8 *g_data = NULL;
1420         u8 *b_data = NULL;
1421         u8 *a_data = NULL;
1422         size_t el_size = sizeof(u8);
1423         u8 *pixel_mem_data;
1424         int ret, i, j;
1425
1426         /* ensure valid conditions for update */
1427         if (logo_layer->id != XVMIX_LAYER_LOGO)
1428                 return 0;
1429
1430         if (src_h > max_height || src_w > max_width ||
1431             src_h < min_height || src_w < min_width) {
1432                 DRM_ERROR("Mixer logo/cursor layer dimensions illegal.\n");
1433                 return -EINVAL;
1434         }
1435
1436         if (!xlnx_mix_isfmt_support(plane->mixer_layer->hw_config.vid_fmt)) {
1437                 DRM_ERROR("DRM color format not supported for logo layer\n");
1438                 return -EINVAL;
1439         }
1440         per_pixel_alpha = (logo_layer->hw_config.vid_fmt ==
1441                            DRM_FORMAT_RGBA8888) ? true : false;
1442         r_data = kcalloc(pixel_cnt, el_size, GFP_KERNEL);
1443         g_data = kcalloc(pixel_cnt, el_size, GFP_KERNEL);
1444         b_data = kcalloc(pixel_cnt, el_size, GFP_KERNEL);
1445         if (per_pixel_alpha)
1446                 a_data = kcalloc(pixel_cnt, el_size, GFP_KERNEL);
1447
1448         if (!r_data || !g_data || !b_data || (per_pixel_alpha && !a_data)) {
1449                 DRM_ERROR("Unable to allocate memory for logo layer data\n");
1450                 ret = -ENOMEM;
1451                 goto free;
1452         }
1453         pix_cmp_cnt = per_pixel_alpha ? 4 : 3;
1454         logo_cmp_cnt = pixel_cnt * pix_cmp_cnt;
1455         /* ensure buffer attributes have changed to indicate new logo
1456          * has been created
1457          */
1458         if ((phys_addr_t)buffer->vaddr == logo_layer->layer_regs.buff_addr1 &&
1459             src_w == logo_layer->layer_regs.width &&
1460             src_h == logo_layer->layer_regs.height)
1461                 return 0;
1462
1463         /* cache buffer address for future comparison */
1464         logo_layer->layer_regs.buff_addr1 = (phys_addr_t)buffer->vaddr;
1465         pixel_mem_data = (u8 *)(buffer->vaddr);
1466         for (i = 0, j = 0; j < pixel_cnt; j++) {
1467                 if (per_pixel_alpha && a_data)
1468                         a_data[j] = pixel_mem_data[i++];
1469
1470                 b_data[j] = pixel_mem_data[i++];
1471                 g_data[j] = pixel_mem_data[i++];
1472                 r_data[j] = pixel_mem_data[i++];
1473         }
1474         ret = xlnx_mix_logo_load(to_mixer_hw(plane), src_w, src_h, r_data,
1475                                  g_data, b_data,
1476                                  per_pixel_alpha ? a_data : NULL);
1477 free:
1478         kfree(r_data);
1479         kfree(g_data);
1480         kfree(b_data);
1481         kfree(a_data);
1482
1483         return ret;
1484 }
1485
1486 /**
1487  * xlnx_mix_set_plane - Implementation of DRM plane_update callback
1488  * @plane: xlnx_mix_plane object containing references to
1489  *  the base plane and mixer
1490  * @fb: Framebuffer descriptor
1491  * @crtc_x: X position of layer on crtc.  Note, if the plane represents either
1492  *  the master hardware layer (video0) or the layer representing the DRM primary
1493  *  layer, the crtc x/y coordinates are either ignored and/or set to 0/0
1494  *  respectively.
1495  * @crtc_y: Y position of layer.  See description of crtc_x handling
1496  * for more inforation.
1497  * @src_x: x-offset in memory buffer from which to start reading
1498  * @src_y: y-offset in memory buffer from which to start reading
1499  * @src_w: Number of horizontal pixels to read from memory per row
1500  * @src_h: Number of rows of video data to read from memory
1501  *
1502  * Configures a mixer layer to comply with user space SET_PLANE icotl
1503  * call.
1504  *
1505  * Return:
1506  * Zero on success, non-zero linux error code otherwise.
1507  */
1508 static int xlnx_mix_set_plane(struct xlnx_mix_plane *plane,
1509                               struct drm_framebuffer *fb,
1510                               int crtc_x, int crtc_y,
1511                               u32 src_x, u32 src_y,
1512                               u32 src_w, u32 src_h)
1513 {
1514         struct xlnx_mix_hw *mixer_hw;
1515         struct xlnx_mix *mixer;
1516         struct drm_gem_cma_object *luma_buffer;
1517         u32 luma_stride = fb->pitches[0];
1518         u64 luma_addr, chroma_addr = 0;
1519         u32 active_area_width;
1520         u32 active_area_height;
1521         enum xlnx_mix_layer_id layer_id;
1522         int ret;
1523         const struct drm_format_info *info = fb->format;
1524
1525         mixer = plane->mixer;
1526         mixer_hw = &mixer->mixer_hw;
1527         layer_id = plane->mixer_layer->id;
1528         active_area_width =
1529                 mixer->drm_primary_layer->mixer_layer->layer_regs.width;
1530         active_area_height =
1531                 mixer->drm_primary_layer->mixer_layer->layer_regs.height;
1532         /* compute memory data */
1533         luma_buffer = drm_fb_cma_get_gem_obj(fb, 0);
1534         luma_addr = drm_fb_cma_get_gem_addr(fb, plane->base.state, 0);
1535         if (!luma_addr) {
1536                 DRM_ERROR("%s failed to get luma paddr\n", __func__);
1537                 return -EINVAL;
1538         }
1539
1540         if (info->num_planes > 1) {
1541                 chroma_addr = drm_fb_cma_get_gem_addr(fb, plane->base.state, 1);
1542                 if (!chroma_addr) {
1543                         DRM_ERROR("failed to get chroma paddr\n");
1544                         return -EINVAL;
1545                 }
1546         }
1547         ret = xlnx_mix_mark_layer_active(plane);
1548         if (ret)
1549                 return ret;
1550
1551         switch (layer_id) {
1552         case XVMIX_LAYER_LOGO:
1553                 ret = xlnx_mix_update_logo_img(plane, luma_buffer,
1554                                                src_w, src_h);
1555                 if (ret)
1556                         break;
1557
1558                 ret = xlnx_mix_set_layer_dimensions(plane, crtc_x, crtc_y,
1559                                                     src_w, src_h, luma_stride);
1560                 break;
1561
1562         case XVMIX_LAYER_MASTER:
1563                 if (!plane->mixer_layer->hw_config.is_streaming)
1564                         xlnx_mix_mark_layer_inactive(plane);
1565                 if (mixer->drm_primary_layer == mixer->hw_master_layer) {
1566                         xlnx_mix_layer_disable(mixer_hw, layer_id);
1567                         msleep(50);
1568                         ret = xlnx_mix_set_active_area(mixer_hw, src_w, src_h);
1569                         if (ret)
1570                                 return ret;
1571                         xlnx_mix_layer_enable(mixer_hw, layer_id);
1572
1573                 } else if (src_w != active_area_width ||
1574                            src_h != active_area_height) {
1575                         DRM_ERROR("Invalid dimensions for mixer layer 0.\n");
1576                         return -EINVAL;
1577                 }
1578                 break;
1579
1580         default:
1581                 ret = xlnx_mix_set_layer_dimensions(plane, crtc_x, crtc_y,
1582                                                     src_w, src_h, luma_stride);
1583                 if (ret)
1584                         break;
1585
1586                 if (!plane->mixer_layer->hw_config.is_streaming)
1587                         ret = xlnx_mix_set_layer_buff_addr
1588                                                 (mixer_hw,
1589                                                  plane->mixer_layer->id,
1590                                                  luma_addr, chroma_addr);
1591         }
1592         return ret;
1593 }
1594
1595 /* mode set a plane */
1596 static int xlnx_mix_plane_mode_set(struct drm_plane *base_plane,
1597                                    struct drm_framebuffer *fb,
1598                                    int crtc_x, int crtc_y,
1599                                    unsigned int crtc_w, unsigned int crtc_h,
1600                                    u32 src_x, uint32_t src_y,
1601                                    u32 src_w, uint32_t src_h)
1602 {
1603         struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
1604         const struct drm_format_info *info = fb->format;
1605         size_t i = 0;
1606         dma_addr_t luma_paddr;
1607         int ret;
1608         u32 stride;
1609
1610         /* JPM TODO begin start of code to extract into prep-interleaved*/
1611         DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
1612         DRM_DEBUG_KMS("h: %d(%d), v: %d(%d)\n", src_w, crtc_x, src_h, crtc_y);
1613
1614         /* We have multiple dma channels.  Set each per video plane */
1615         for (; i < info->num_planes; i++) {
1616                 unsigned int width = src_w / (i ? info->hsub : 1);
1617                 unsigned int height = src_h / (i ? info->vsub : 1);
1618
1619                 luma_paddr = drm_fb_cma_get_gem_addr(fb, base_plane->state, i);
1620                 if (!luma_paddr) {
1621                         DRM_ERROR("%s failed to get luma paddr\n", __func__);
1622                         return -EINVAL;
1623                 }
1624
1625                 plane->dma[i].xt.numf = height;
1626                 plane->dma[i].sgl[0].size =
1627                         drm_format_plane_width_bytes(info, 0, width);
1628                 plane->dma[i].sgl[0].icg = fb->pitches[0] -
1629                                                 plane->dma[i].sgl[0].size;
1630                 plane->dma[i].xt.src_start = luma_paddr;
1631                 plane->dma[i].xt.frame_size = info->num_planes;
1632                 plane->dma[i].xt.dir = DMA_MEM_TO_DEV;
1633                 plane->dma[i].xt.src_sgl = true;
1634                 plane->dma[i].xt.dst_sgl = false;
1635                 plane->dma[i].is_active = true;
1636         }
1637
1638         for (; i < XVMIX_MAX_NUM_SUB_PLANES; i++)
1639                 plane->dma[i].is_active = false;
1640         /* Do we have a video format aware dma channel?
1641          * If so, modify descriptor accordingly
1642          */
1643         if (plane->dma[0].chan && !plane->dma[1].chan && info->num_planes > 1) {
1644                 stride = plane->dma[0].sgl[0].size + plane->dma[0].sgl[0].icg;
1645                 plane->dma[0].sgl[0].src_icg = plane->dma[1].xt.src_start -
1646                                 plane->dma[0].xt.src_start -
1647                                 (plane->dma[0].xt.numf * stride);
1648         }
1649
1650         ret = xlnx_mix_set_plane(plane, fb, crtc_x, crtc_y, src_x, src_y,
1651                                  src_w, src_h);
1652         return ret;
1653 }
1654
1655 static int xlnx_mix_plane_prepare_fb(struct drm_plane *plane,
1656                                      struct drm_plane_state *new_state)
1657 {
1658         return 0;
1659 }
1660
1661 static void xlnx_mix_plane_cleanup_fb(struct drm_plane *plane,
1662                                       struct drm_plane_state *old_state)
1663 {
1664 }
1665
1666 static int xlnx_mix_plane_atomic_check(struct drm_plane *plane,
1667                                        struct drm_plane_state *state)
1668 {
1669         return 0;
1670 }
1671
1672 static void xlnx_mix_plane_atomic_update(struct drm_plane *plane,
1673                                          struct drm_plane_state *old_state)
1674 {
1675         int ret;
1676
1677         ret = xlnx_mix_plane_mode_set(plane, plane->state->fb,
1678                                       plane->state->crtc_x,
1679                                       plane->state->crtc_y,
1680                                       plane->state->crtc_w,
1681                                       plane->state->crtc_h,
1682                                       plane->state->src_x >> 16,
1683                                       plane->state->src_y >> 16,
1684                                       plane->state->src_w >> 16,
1685                                       plane->state->src_h >> 16);
1686         if (ret) {
1687                 DRM_ERROR("failed to mode-set a plane\n");
1688                 return;
1689         }
1690         /* apply the new fb addr */
1691         xlnx_mix_plane_commit(plane);
1692         /* make sure a plane is on */
1693         xlnx_mix_plane_dpms(plane, DRM_MODE_DPMS_ON);
1694 }
1695
1696 static void xlnx_mix_plane_atomic_disable(struct drm_plane *plane,
1697                                           struct drm_plane_state *old_state)
1698 {
1699         xlnx_mix_plane_dpms(plane, DRM_MODE_DPMS_OFF);
1700 }
1701
1702 static const struct drm_plane_helper_funcs xlnx_mix_plane_helper_funcs = {
1703         .prepare_fb     = xlnx_mix_plane_prepare_fb,
1704         .cleanup_fb     = xlnx_mix_plane_cleanup_fb,
1705         .atomic_check   = xlnx_mix_plane_atomic_check,
1706         .atomic_update  = xlnx_mix_plane_atomic_update,
1707         .atomic_disable = xlnx_mix_plane_atomic_disable,
1708 };
1709
1710 static int xlnx_mix_init_plane(struct xlnx_mix_plane *plane,
1711                                unsigned int poss_crtcs,
1712                                struct device_node *layer_node)
1713 {
1714         struct xlnx_mix *mixer = plane->mixer;
1715         char name[16];
1716         enum drm_plane_type type;
1717         int ret, i;
1718
1719         plane->dpms = DRM_MODE_DPMS_OFF;
1720         type = DRM_PLANE_TYPE_OVERLAY;
1721
1722         for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++) {
1723                 snprintf(name, sizeof(name), "dma%d", i);
1724                 plane->dma[i].chan = of_dma_request_slave_channel(layer_node,
1725                                                                   name);
1726                 if (PTR_ERR(plane->dma[i].chan) == -ENODEV) {
1727                         plane->dma[i].chan = NULL;
1728                         continue;
1729                 }
1730                 if (IS_ERR(plane->dma[i].chan)) {
1731                         DRM_ERROR("failed to request dma channel\n");
1732                         ret = PTR_ERR(plane->dma[i].chan);
1733                         plane->dma[i].chan = NULL;
1734                         goto err_dma;
1735                 }
1736         }
1737         if (!xlnx_mix_isfmt_support(plane->mixer_layer->hw_config.vid_fmt)) {
1738                 DRM_ERROR("DRM color format not supported by mixer\n");
1739                 ret = -ENODEV;
1740                 goto err_init;
1741         }
1742         plane->format = plane->mixer_layer->hw_config.vid_fmt;
1743         if (plane == mixer->hw_logo_layer)
1744                 type = DRM_PLANE_TYPE_CURSOR;
1745         if (plane == mixer->drm_primary_layer)
1746                 type = DRM_PLANE_TYPE_PRIMARY;
1747
1748         /* initialize drm plane */
1749         ret = drm_universal_plane_init(mixer->drm, &plane->base,
1750                                        poss_crtcs, &xlnx_mix_plane_funcs,
1751                                        &plane->format,
1752                                        1, NULL, type, NULL);
1753
1754         if (ret) {
1755                 DRM_ERROR("failed to initialize plane\n");
1756                 goto err_init;
1757         }
1758         drm_plane_helper_add(&plane->base, &xlnx_mix_plane_helper_funcs);
1759         of_node_put(layer_node);
1760
1761         return 0;
1762
1763 err_init:
1764         xlnx_mix_disp_layer_disable(plane);
1765 err_dma:
1766         for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++)
1767                 if (plane->dma[i].chan)
1768                         dma_release_channel(plane->dma[i].chan);
1769
1770         of_node_put(layer_node);
1771         return ret;
1772 }
1773
1774 static int xlnx_mix_parse_dt_bg_video_fmt(struct device_node *node,
1775                                           struct xlnx_mix_hw *mixer_hw)
1776 {
1777         struct device_node *layer_node;
1778         struct xlnx_mix_layer_data *layer;
1779         const char *vformat;
1780
1781         layer_node = of_get_child_by_name(node, "layer_0");
1782         layer = &mixer_hw->layer_data[XVMIX_MASTER_LAYER_IDX];
1783
1784         /* Set default values */
1785         layer->hw_config.can_alpha = false;
1786         layer->hw_config.can_scale = false;
1787         layer->hw_config.min_width = XVMIX_LAYER_WIDTH_MIN;
1788         layer->hw_config.min_height = XVMIX_LAYER_HEIGHT_MIN;
1789
1790         if (of_property_read_string(layer_node, "xlnx,vformat",
1791                                     &vformat)) {
1792                 DRM_ERROR("No xlnx,vformat value for layer 0 in dts\n");
1793                 return -EINVAL;
1794         }
1795         strcpy((char *)&layer->hw_config.vid_fmt, vformat);
1796         layer->hw_config.is_streaming =
1797                 of_property_read_bool(layer_node, "xlnx,layer-streaming");
1798         if (of_property_read_u32(node, "xlnx,bpc", &mixer_hw->bg_layer_bpc)) {
1799                 DRM_ERROR("Failed to get bits per component (bpc) prop\n");
1800                 return -EINVAL;
1801         }
1802         if (of_property_read_u32(layer_node, "xlnx,layer-max-width",
1803                                  &layer->hw_config.max_width)) {
1804                 DRM_ERROR("Failed to get screen width prop\n");
1805                 return -EINVAL;
1806         }
1807         mixer_hw->max_layer_width = layer->hw_config.max_width;
1808         if (of_property_read_u32(layer_node, "xlnx,layer-max-height",
1809                                  &layer->hw_config.max_height)) {
1810                 DRM_ERROR("Failed to get screen height prop\n");
1811                 return -EINVAL;
1812         }
1813         mixer_hw->max_layer_height = layer->hw_config.max_height;
1814         layer->id = XVMIX_LAYER_MASTER;
1815
1816         return 0;
1817 }
1818
1819 static int xlnx_mix_parse_dt_logo_data(struct device_node *node,
1820                                        struct xlnx_mix_hw *mixer_hw)
1821 {
1822         struct xlnx_mix_layer_data *layer_data;
1823         struct device_node *logo_node;
1824         u32 max_width, max_height;
1825
1826         logo_node = of_get_child_by_name(node, "logo");
1827         if (!logo_node) {
1828                 DRM_ERROR("No logo node specified in device tree.\n");
1829                 return -EINVAL;
1830         }
1831
1832         layer_data = &mixer_hw->layer_data[XVMIX_LOGO_LAYER_IDX];
1833
1834         /* set defaults for logo layer */
1835         layer_data->hw_config.min_height = XVMIX_LOGO_LAYER_HEIGHT_MIN;
1836         layer_data->hw_config.min_width = XVMIX_LOGO_LAYER_WIDTH_MIN;
1837         layer_data->hw_config.is_streaming = false;
1838         layer_data->hw_config.vid_fmt = DRM_FORMAT_RGB888;
1839         layer_data->hw_config.can_alpha = true;
1840         layer_data->hw_config.can_scale = true;
1841         layer_data->layer_regs.buff_addr1 = 0;
1842         layer_data->layer_regs.buff_addr2 = 0;
1843         layer_data->id = XVMIX_LAYER_LOGO;
1844
1845         if (of_property_read_u32(logo_node, "xlnx,logo-width", &max_width)) {
1846                 DRM_ERROR("Failed to get logo width prop\n");
1847                 return -EINVAL;
1848         }
1849         if (max_width > XVMIX_LOGO_LAYER_WIDTH_MAX ||
1850             max_width < XVMIX_LOGO_LAYER_WIDTH_MIN) {
1851                 DRM_ERROR("Illegal mixer logo layer width.\n");
1852                 return -EINVAL;
1853         }
1854         layer_data->hw_config.max_width = max_width;
1855         mixer_hw->max_logo_layer_width = layer_data->hw_config.max_width;
1856
1857         if (of_property_read_u32(logo_node, "xlnx,logo-height", &max_height)) {
1858                 DRM_ERROR("Failed to get logo height prop\n");
1859                 return -EINVAL;
1860         }
1861         if (max_height > XVMIX_LOGO_LAYER_HEIGHT_MAX ||
1862             max_height < XVMIX_LOGO_LAYER_HEIGHT_MIN) {
1863                 DRM_ERROR("Illegal mixer logo layer height.\n");
1864                 return -EINVAL;
1865         }
1866         layer_data->hw_config.max_height = max_height;
1867         mixer_hw->max_logo_layer_height = layer_data->hw_config.max_height;
1868         mixer_hw->logo_pixel_alpha_enabled =
1869                 of_property_read_bool(logo_node, "xlnx,logo-pixel-alpha");
1870         if (mixer_hw->logo_pixel_alpha_enabled)
1871                 layer_data->hw_config.vid_fmt = DRM_FORMAT_RGBA8888;
1872
1873         return 0;
1874 }
1875
1876 static int xlnx_mix_dt_parse(struct device *dev, struct xlnx_mix *mixer)
1877 {
1878         struct xlnx_mix_plane *planes;
1879         struct xlnx_mix_hw *mixer_hw;
1880         struct device_node *node;
1881         struct xlnx_mix_layer_data *l_data;
1882         struct resource res;
1883         int ret, l_cnt, i;
1884
1885         node = dev->of_node;
1886         mixer_hw = &mixer->mixer_hw;
1887         mixer->dpms = DRM_MODE_DPMS_OFF;
1888
1889         mixer_hw->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
1890         if (IS_ERR(mixer_hw->reset_gpio)) {
1891                 ret = PTR_ERR(mixer_hw->reset_gpio);
1892                 if (ret == -EPROBE_DEFER)
1893                         dev_dbg(dev, "No gpio probed for mixer. Deferring\n");
1894                 else
1895                         dev_err(dev, "No reset gpio info from dts for mixer\n");
1896                 return ret;
1897         }
1898
1899         ret = of_address_to_resource(node, 0, &res);
1900         if (ret) {
1901                 dev_err(dev, "Invalid memory address for mixer %d\n", ret);
1902                 return ret;
1903         }
1904         /* Read in mandatory global dts properties */
1905         mixer_hw->base = devm_ioremap_resource(dev, &res);
1906         if (IS_ERR(mixer_hw->base)) {
1907                 dev_err(dev, "Failed to map io mem space for mixer\n");
1908                 return PTR_ERR(mixer_hw->base);
1909         }
1910         ret = of_property_read_u32(node, "xlnx,num-layers",
1911                                    &mixer_hw->max_layers);
1912         if (ret) {
1913                 dev_err(dev, "No xlnx,num-layers dts prop for mixer node\n");
1914                 return ret;
1915         }
1916         if (mixer_hw->max_layers > XVMIX_MAX_LAYERS) {
1917                 dev_err(dev, "Num layer nodes in device tree > mixer max\n");
1918                 return -EINVAL;
1919         }
1920         ret = of_property_read_u32(node, "xlnx,dma-addr-width",
1921                                    &mixer_hw->dma_addr_size);
1922         if (ret) {
1923                 dev_err(dev, "missing addr-width dts prop\n");
1924                 return ret;
1925         }
1926         if (mixer_hw->dma_addr_size != 32 && mixer_hw->dma_addr_size != 64) {
1927                 dev_err(dev, "invalid addr-width dts prop\n");
1928                 return -EINVAL;
1929         }
1930         mixer_hw->logo_layer_en = of_property_read_bool(node,
1931                                                         "xlnx,logo-layer");
1932         l_cnt = mixer_hw->max_layers + (mixer_hw->logo_layer_en ? 1 : 0);
1933         mixer_hw->layer_cnt = l_cnt;
1934
1935         l_data = devm_kzalloc(dev, sizeof(*l_data) * l_cnt, GFP_KERNEL);
1936         if (!l_data)
1937                 return -ENOMEM;
1938         mixer_hw->layer_data = l_data;
1939         /* init DRM planes */
1940         planes = devm_kzalloc(dev, sizeof(*planes) * l_cnt, GFP_KERNEL);
1941         if (!planes)
1942                 return -ENOMEM;
1943         mixer->planes = planes;
1944         mixer->num_planes = l_cnt;
1945         for (i = 0; i < mixer->num_planes; i++)
1946                 mixer->planes[i].mixer = mixer;
1947
1948         /* establish background layer video properties from dts */
1949         ret = xlnx_mix_parse_dt_bg_video_fmt(node, mixer_hw);
1950         if (ret)
1951                 return ret;
1952         /* read logo data from dts */
1953         ret = xlnx_mix_parse_dt_logo_data(node, mixer_hw);
1954                 return ret;
1955         return 0;
1956 }
1957
1958 static int xlnx_mix_of_init_layer(struct device *dev, struct device_node *node,
1959                                   char *name, struct xlnx_mix_layer_data *layer,
1960                                   u32 max_width, struct xlnx_mix *mixer, int id)
1961 {
1962         struct device_node *layer_node;
1963         const char *vformat;
1964         int ret;
1965
1966         layer_node = of_get_child_by_name(node, name);
1967         if (!layer_node)
1968                 return -EINVAL;
1969
1970         /* Set default values */
1971         layer->hw_config.can_alpha = false;
1972         layer->hw_config.can_scale = false;
1973         layer->hw_config.is_streaming = false;
1974         layer->hw_config.max_width = max_width;
1975         layer->hw_config.min_width = XVMIX_LAYER_WIDTH_MIN;
1976         layer->hw_config.min_height = XVMIX_LAYER_HEIGHT_MIN;
1977         layer->hw_config.vid_fmt = 0;
1978         layer->id = 0;
1979         mixer->planes[id].mixer_layer = layer;
1980
1981         ret = of_property_read_u32(layer_node, "xlnx,layer-id", &layer->id);
1982         if (ret) {
1983                 dev_err(dev, "xlnx,layer-id property not found\n");
1984                 return ret;
1985         }
1986         if (layer->id < 1 || layer->id >= XVMIX_MAX_LAYERS) {
1987                 dev_err(dev, "Mixer layer id %u in dts is out of legal range\n",
1988                         layer->id);
1989                 return -EINVAL;
1990         }
1991         ret = of_property_read_string(layer_node, "xlnx,vformat", &vformat);
1992         if (ret) {
1993                 dev_err(dev, "No mixer layer vformat in dts for layer id %d\n",
1994                         layer->id);
1995                 return ret;
1996         }
1997
1998         strcpy((char *)&layer->hw_config.vid_fmt, vformat);
1999         layer->hw_config.can_scale =
2000                     of_property_read_bool(layer_node, "xlnx,layer-scale");
2001         if (layer->hw_config.can_scale) {
2002                 ret = of_property_read_u32(layer_node, "xlnx,layer-max-width",
2003                                            &layer->hw_config.max_width);
2004                 if (ret) {
2005                         dev_err(dev, "Mixer layer %d dts missing width prop.\n",
2006                                 layer->id);
2007                         return ret;
2008                 }
2009
2010                 if (layer->hw_config.max_width > max_width) {
2011                         dev_err(dev, "Illlegal Mixer layer %d width %d\n",
2012                                 layer->id, layer->hw_config.max_width);
2013                         return -EINVAL;
2014                 }
2015         }
2016         layer->hw_config.can_alpha =
2017                     of_property_read_bool(layer_node, "xlnx,layer-alpha");
2018         layer->hw_config.is_streaming =
2019                     of_property_read_bool(layer_node, "xlnx,layer-streaming");
2020         if (of_property_read_bool(layer_node, "xlnx,layer-primary")) {
2021                 if (mixer->drm_primary_layer) {
2022                         dev_err(dev,
2023                                 "More than one primary layer in mixer dts\n");
2024                         return -EINVAL;
2025                 }
2026                 mixer->drm_primary_layer = &mixer->planes[id];
2027         }
2028         ret = xlnx_mix_init_plane(&mixer->planes[id], 1, layer_node);
2029         if (ret)
2030                 dev_err(dev, "Unable to init drm mixer plane id = %u", id);
2031
2032         return ret;
2033 }
2034
2035 static irqreturn_t xlnx_mix_intr_handler(int irq, void *data)
2036 {
2037         struct xlnx_mix_hw *mixer = data;
2038         u32 intr = xlnx_mix_get_intr_status(mixer);
2039
2040         if (!intr)
2041                 return IRQ_NONE;
2042         if (mixer->intrpt_handler_fn)
2043                 mixer->intrpt_handler_fn(mixer->intrpt_data);
2044         xlnx_mix_clear_intr_status(mixer, intr);
2045
2046         return IRQ_HANDLED;
2047 }
2048
2049 static void xlnx_mix_create_plane_properties(struct xlnx_mix *mixer)
2050 {
2051         mixer->scale_prop = drm_property_create_range(mixer->drm, 0, "scale",
2052                                                       XVMIX_SCALE_FACTOR_1X,
2053                                                       XVMIX_SCALE_FACTOR_4X);
2054         mixer->alpha_prop = drm_property_create_range(mixer->drm, 0, "alpha",
2055                                                       XVMIX_ALPHA_MIN,
2056                                                       XVMIX_ALPHA_MAX);
2057 }
2058
2059 static int xlnx_mix_plane_create(struct device *dev, struct xlnx_mix *mixer)
2060 {
2061         struct xlnx_mix_hw              *mixer_hw;
2062         struct device_node              *node, *layer_node;
2063         char                            name[20];
2064         struct xlnx_mix_layer_data      *layer_data;
2065         int                             ret, i;
2066         int                             layer_idx;
2067
2068         node = dev->of_node;
2069         mixer_hw = &mixer->mixer_hw;
2070         xlnx_mix_create_plane_properties(mixer);
2071
2072         mixer->planes[XVMIX_MASTER_LAYER_IDX].mixer_layer =
2073                                 &mixer_hw->layer_data[XVMIX_MASTER_LAYER_IDX];
2074         mixer->planes[XVMIX_MASTER_LAYER_IDX].id = XVMIX_MASTER_LAYER_IDX;
2075         mixer->hw_master_layer = &mixer->planes[XVMIX_MASTER_LAYER_IDX];
2076
2077         if (mixer_hw->logo_layer_en) {
2078                 mixer->planes[XVMIX_LOGO_LAYER_IDX].mixer_layer =
2079                                 &mixer_hw->layer_data[XVMIX_LOGO_LAYER_IDX];
2080                 mixer->planes[XVMIX_LOGO_LAYER_IDX].id = XVMIX_LOGO_LAYER_IDX;
2081                 mixer->hw_logo_layer = &mixer->planes[XVMIX_LOGO_LAYER_IDX];
2082                 layer_node = of_get_child_by_name(node, "logo");
2083                 ret = xlnx_mix_init_plane(&mixer->planes[XVMIX_LOGO_LAYER_IDX],
2084                                           1, layer_node);
2085                 if (ret)
2086                         return ret;
2087         }
2088         layer_idx = mixer_hw->logo_layer_en ? 2 : 1;
2089         for (i = 1; i < mixer_hw->max_layers; i++, layer_idx++) {
2090                 snprintf(name, sizeof(name), "layer_%d", i);
2091                 ret = xlnx_mix_of_init_layer(dev, node, name,
2092                                              &mixer_hw->layer_data[layer_idx],
2093                                              mixer_hw->max_layer_width,
2094                                              mixer, layer_idx);
2095                 if (ret)
2096                         return ret;
2097         }
2098         /* If none of the overlay layers were designated as the drm
2099          * primary layer, default to the mixer's video0 layer as drm primary
2100          */
2101         if (!mixer->drm_primary_layer)
2102                 mixer->drm_primary_layer = mixer->hw_master_layer;
2103         layer_node = of_get_child_by_name(node, "layer_0");
2104         ret = xlnx_mix_init_plane(&mixer->planes[XVMIX_MASTER_LAYER_IDX], 1,
2105                                   layer_node);
2106         /* request irq and obtain pixels-per-clock (ppc) property */
2107         mixer_hw->irq = irq_of_parse_and_map(node, 0);
2108         if (mixer_hw->irq > 0) {
2109                 ret = devm_request_irq(dev, mixer_hw->irq,
2110                                        xlnx_mix_intr_handler,
2111                                        IRQF_SHARED, "xlnx-mixer", mixer_hw);
2112                 if (ret) {
2113                         dev_err(dev, "Failed to request irq\n");
2114                         return ret;
2115                 }
2116         }
2117         ret = of_property_read_u32(node, "xlnx,ppc", &mixer_hw->ppc);
2118         if (ret) {
2119                 dev_err(dev, "No xlnx,ppc property for mixer dts\n");
2120                 return ret;
2121         }
2122
2123         mixer->max_width = XVMIX_DISP_MAX_WIDTH;
2124         mixer->max_height = XVMIX_DISP_MAX_HEIGHT;
2125         if (mixer->hw_logo_layer) {
2126                 layer_data = &mixer_hw->layer_data[XVMIX_LOGO_LAYER_IDX];
2127                 mixer->max_cursor_width = layer_data->hw_config.max_width;
2128                 mixer->max_cursor_height = layer_data->hw_config.max_height;
2129         }
2130         return 0;
2131 }
2132
2133 /**
2134  * xlnx_mix_plane_restore - Restore the plane states
2135  * @mixer: mixer device core structure
2136  *
2137  * Restore the plane states to the default ones. Any state that needs to be
2138  * restored should be here. This improves consistency as applications see
2139  * the same default values, and removes mismatch between software and hardware
2140  * values as software values are updated as hardware values are reset.
2141  */
2142 static void xlnx_mix_plane_restore(struct xlnx_mix *mixer)
2143 {
2144         struct xlnx_mix_plane *plane;
2145         unsigned int i;
2146
2147         if (!mixer)
2148                 return;
2149         /*
2150          * Reinitialize property default values as they get reset by DPMS OFF
2151          * operation. User will read the correct default values later, and
2152          * planes will be initialized with default values.
2153          */
2154         for (i = 0; i < mixer->num_planes; i++) {
2155                 plane = &mixer->planes[i];
2156                 if (!plane)
2157                         continue;
2158                 xlnx_mix_hw_plane_dpms(plane, DRM_MODE_DPMS_OFF);
2159         }
2160 }
2161
2162 /**
2163  * xlnx_mix_set_bkg_col - Set background color
2164  * @mixer: Mixer instance to program with new background color
2165  * @rgb_value: RGB encoded as 32-bit integer in little-endian format
2166  *
2167  * Set the color to be output as background color when background stream layer
2168  */
2169 static void xlnx_mix_set_bkg_col(struct xlnx_mix_hw *mixer, u64 rgb_value)
2170 {
2171         u32 bg_bpc = mixer->bg_layer_bpc;
2172         u32 bpc_mask_shift = XVMIX_MAX_BPC - bg_bpc;
2173         u32 val_mask = (GENMASK(15, 0) >> bpc_mask_shift);
2174         u16 b_val = (rgb_value >> (bg_bpc * 2)) & val_mask;
2175         u16 g_val = (rgb_value >> bg_bpc) & val_mask;
2176         u16 r_val = (rgb_value >> 0) &  val_mask;
2177
2178         /* Set Background Color */
2179         reg_writel(mixer->base, XVMIX_BACKGROUND_Y_R_DATA, r_val);
2180         reg_writel(mixer->base, XVMIX_BACKGROUND_U_G_DATA, g_val);
2181         reg_writel(mixer->base, XVMIX_BACKGROUND_V_B_DATA, b_val);
2182         mixer->bg_color = rgb_value;
2183 }
2184
2185 /**
2186  * xlnx_mix_reset - Reset the mixer core video generator
2187  * @mixer: Mixer core instance for which to start video output
2188  *
2189  * Toggle the reset gpio and restores the bg color, plane and interrupt mask.
2190  */
2191 static void xlnx_mix_reset(struct xlnx_mix *mixer)
2192 {
2193         struct xlnx_mix_hw *mixer_hw = &mixer->mixer_hw;
2194
2195         gpiod_set_raw_value(mixer_hw->reset_gpio, 0);
2196         gpiod_set_raw_value(mixer_hw->reset_gpio, 1);
2197         /* restore layer properties and bg color after reset */
2198         xlnx_mix_set_bkg_col(mixer_hw, mixer_hw->bg_color);
2199         xlnx_mix_plane_restore(mixer);
2200         xlnx_mix_intrpt_enable_done(&mixer->mixer_hw);
2201 }
2202
2203 static void xlnx_mix_dpms(struct xlnx_mix *mixer, int dpms)
2204 {
2205         switch (dpms) {
2206         case DRM_MODE_DPMS_ON:
2207                 xlnx_mix_start(&mixer->mixer_hw);
2208                 break;
2209         default:
2210                 xlnx_mix_stop(&mixer->mixer_hw);
2211                 mdelay(50); /* let IP shut down */
2212                 xlnx_mix_reset(mixer);
2213         }
2214 }
2215
2216 /* set crtc dpms */
2217 static void xlnx_mix_crtc_dpms(struct drm_crtc *base_crtc, int dpms)
2218 {
2219         struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
2220         struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
2221         int ret;
2222
2223         DRM_DEBUG_KMS("dpms: %d\n", dpms);
2224         if (mixer->dpms == dpms)
2225                 return;
2226         mixer->dpms = dpms;
2227
2228         switch (dpms) {
2229         case DRM_MODE_DPMS_ON:
2230                 if (!mixer->pixel_clock_enabled) {
2231                         ret = clk_prepare_enable(mixer->pixel_clock);
2232                         if (ret) {
2233                                 DRM_ERROR("failed to enable a pixel clock\n");
2234                                 mixer->pixel_clock_enabled = false;
2235                         }
2236                 }
2237                 mixer->pixel_clock_enabled = true;
2238
2239                 xlnx_mix_dpms(mixer, dpms);
2240                 xlnx_mix_plane_dpms(base_crtc->primary, dpms);
2241                 break;
2242         default:
2243                 xlnx_mix_plane_dpms(base_crtc->primary, dpms);
2244                 xlnx_mix_dpms(mixer, dpms);
2245                 if (mixer->pixel_clock_enabled) {
2246                         clk_disable_unprepare(mixer->pixel_clock);
2247                         mixer->pixel_clock_enabled = false;
2248                 }
2249                 break;
2250         }
2251 }
2252
2253 static void xlnx_mix_set_intr_handler(struct xlnx_mix *mixer,
2254                                       void (*intr_handler_fn)(void *),
2255                                        void *data)
2256 {
2257         mixer->mixer_hw.intrpt_handler_fn = intr_handler_fn;
2258         mixer->mixer_hw.intrpt_data = data;
2259 }
2260
2261 static void xlnx_mix_crtc_vblank_handler(void *data)
2262 {
2263         struct drm_crtc *base_crtc = data;
2264         struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
2265         struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
2266         struct drm_device *drm = base_crtc->dev;
2267         struct drm_pending_vblank_event *event;
2268         unsigned long flags;
2269
2270         drm_crtc_handle_vblank(base_crtc);
2271         /* Finish page flip */
2272         spin_lock_irqsave(&drm->event_lock, flags);
2273         event = mixer->event;
2274         mixer->event = NULL;
2275         if (event) {
2276                 drm_crtc_send_vblank_event(base_crtc, event);
2277                 drm_crtc_vblank_put(base_crtc);
2278         }
2279         spin_unlock_irqrestore(&drm->event_lock, flags);
2280 }
2281
2282 static int xlnx_mix_crtc_enable_vblank(struct drm_crtc *base_crtc)
2283 {
2284         struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
2285         struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
2286
2287         xlnx_mix_set_intr_handler(mixer, xlnx_mix_crtc_vblank_handler,
2288                                   base_crtc);
2289         return 0;
2290 }
2291
2292 static void xlnx_mix_crtc_disable_vblank(struct drm_crtc *base_crtc)
2293 {
2294         struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
2295         struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
2296
2297         mixer->mixer_hw.intrpt_handler_fn = NULL;
2298         mixer->mixer_hw.intrpt_data = NULL;
2299 }
2300
2301 static void xlnx_mix_crtc_destroy(struct drm_crtc *base_crtc)
2302 {
2303         struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
2304         struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
2305
2306         /* make sure crtc is off */
2307         mixer->alpha_prop = NULL;
2308         mixer->scale_prop = NULL;
2309         mixer->bg_color = NULL;
2310         xlnx_mix_crtc_dpms(base_crtc, DRM_MODE_DPMS_OFF);
2311
2312         if (mixer->pixel_clock_enabled) {
2313                 clk_disable_unprepare(mixer->pixel_clock);
2314                 mixer->pixel_clock_enabled = false;
2315         }
2316         drm_crtc_cleanup(base_crtc);
2317 }
2318
2319 static int
2320 xlnx_mix_disp_crtc_atomic_set_property(struct drm_crtc *crtc,
2321                                        struct drm_crtc_state *state,
2322                                      struct drm_property *property,
2323                                      uint64_t val)
2324 {
2325         return 0;
2326 }
2327
2328 static int
2329 xlnx_mix_disp_crtc_atomic_get_property(struct drm_crtc *crtc,
2330                                        const struct drm_crtc_state *state,
2331                                      struct drm_property *property,
2332                                      uint64_t *val)
2333 {
2334         return 0;
2335 }
2336
2337 static struct drm_crtc_funcs xlnx_mix_crtc_funcs = {
2338         .destroy                = xlnx_mix_crtc_destroy,
2339         .set_config             = drm_atomic_helper_set_config,
2340         .page_flip              = drm_atomic_helper_page_flip,
2341         .atomic_set_property    = xlnx_mix_disp_crtc_atomic_set_property,
2342         .atomic_get_property    = xlnx_mix_disp_crtc_atomic_get_property,
2343         .reset                  = drm_atomic_helper_crtc_reset,
2344         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
2345         .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
2346         .enable_vblank          = xlnx_mix_crtc_enable_vblank,
2347         .disable_vblank         = xlnx_mix_crtc_disable_vblank,
2348 };
2349
2350 static void
2351 xlnx_mix_crtc_atomic_enable(struct drm_crtc *crtc,
2352                             struct drm_crtc_state *old_crtc_state)
2353 {
2354         xlnx_mix_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
2355 }
2356
2357 /**
2358  * xlnx_mix_clear_event - Clear any event if pending
2359  * @crtc: DRM crtc object
2360  *
2361  */
2362 static void xlnx_mix_clear_event(struct drm_crtc *crtc)
2363 {
2364         if (crtc->state->event) {
2365                 complete_all(crtc->state->event->base.completion);
2366                 crtc->state->event = NULL;
2367         }
2368 }
2369
2370 static void
2371 xlnx_mix_crtc_atomic_disable(struct drm_crtc *crtc,
2372                              struct drm_crtc_state *old_crtc_state)
2373 {
2374         xlnx_mix_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
2375         xlnx_mix_clear_event(crtc);
2376 }
2377
2378 static void xlnx_mix_crtc_mode_set_nofb(struct drm_crtc *crtc)
2379 {
2380 }
2381
2382 static int xlnx_mix_crtc_atomic_check(struct drm_crtc *crtc,
2383                                       struct drm_crtc_state *state)
2384 {
2385         return drm_atomic_add_affected_planes(state->state, crtc);
2386 }
2387
2388 static void
2389 xlnx_mix_crtc_atomic_begin(struct drm_crtc *crtc,
2390                            struct drm_crtc_state *old_crtc_state)
2391 {
2392         /* Don't rely on vblank when disabling crtc */
2393         if (crtc->state->event) {
2394                 struct xlnx_crtc *xcrtc = to_xlnx_crtc(crtc);
2395                 struct xlnx_mix *mixer = to_xlnx_mixer(xcrtc);
2396
2397                 /* Consume the flip_done event from atomic helper */
2398                 crtc->state->event->pipe = drm_crtc_index(crtc);
2399                 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
2400                 mixer->event = crtc->state->event;
2401                 crtc->state->event = NULL;
2402         }
2403 }
2404
2405 static struct drm_crtc_helper_funcs xlnx_mix_crtc_helper_funcs = {
2406         .atomic_enable  = xlnx_mix_crtc_atomic_enable,
2407         .atomic_disable = xlnx_mix_crtc_atomic_disable,
2408         .mode_set_nofb  = xlnx_mix_crtc_mode_set_nofb,
2409         .atomic_check   = xlnx_mix_crtc_atomic_check,
2410         .atomic_begin   = xlnx_mix_crtc_atomic_begin,
2411 };
2412
2413 /**
2414  * xlnx_mix_crtc_create - create crtc for mixer
2415  * @mixer: xilinx video mixer object
2416  *
2417  * Return:
2418  * Zero on success, error on failure
2419  *
2420  */
2421 static int xlnx_mix_crtc_create(struct xlnx_mix *mixer)
2422 {
2423         struct xlnx_crtc *crtc;
2424         struct drm_plane *primary_plane = NULL;
2425         struct drm_plane *cursor_plane = NULL;
2426         int ret, i;
2427
2428         crtc = &mixer->crtc;
2429         primary_plane = &mixer->drm_primary_layer->base;
2430         cursor_plane = &mixer->hw_logo_layer->base;
2431
2432         for (i = 0; i < mixer->num_planes; i++)
2433                 xlnx_mix_attach_plane_prop(&mixer->planes[i]);
2434         mixer->pixel_clock = devm_clk_get(mixer->drm->dev, NULL);
2435         if (IS_ERR(mixer->pixel_clock)) {
2436                 DRM_DEBUG_KMS("failed to get pixel clock\n");
2437                 mixer->pixel_clock = NULL;
2438         }
2439         ret = clk_prepare_enable(mixer->pixel_clock);
2440         if (ret) {
2441                 DRM_ERROR("failed to enable a pixel clock\n");
2442                 mixer->pixel_clock_enabled = false;
2443                 goto err_plane;
2444         }
2445         mixer->pixel_clock_enabled = true;
2446         /* initialize drm crtc */
2447         ret = drm_crtc_init_with_planes(mixer->drm, &crtc->crtc,
2448                                         &mixer->drm_primary_layer->base,
2449                                         &mixer->hw_logo_layer->base,
2450                                         &xlnx_mix_crtc_funcs, NULL);
2451         if (ret) {
2452                 DRM_ERROR("failed to initialize mixer crtc\n");
2453                 goto err_pixel_clk;
2454         }
2455         drm_crtc_helper_add(&crtc->crtc, &xlnx_mix_crtc_helper_funcs);
2456         crtc->get_max_width = &xlnx_mix_crtc_get_max_width;
2457         crtc->get_max_height = &xlnx_mix_crtc_get_max_height;
2458         crtc->get_align = &xlnx_mix_crtc_get_align;
2459         crtc->get_format = &xlnx_mix_crtc_get_format;
2460         crtc->get_cursor_height = &xlnx_mix_crtc_get_max_cursor_height;
2461         crtc->get_cursor_width = &xlnx_mix_crtc_get_max_cursor_width;
2462         xlnx_crtc_register(mixer->drm, crtc);
2463
2464         return 0;
2465
2466 err_pixel_clk:
2467         if (mixer->pixel_clock_enabled) {
2468                 clk_disable_unprepare(mixer->pixel_clock);
2469                 mixer->pixel_clock_enabled = false;
2470         }
2471 err_plane:
2472         return ret;
2473 }
2474
2475 /**
2476  * xlnx_mix_init - Establishes a default power-on state for the mixer IP
2477  * core
2478  * @mixer: instance of IP core to initialize to a default state
2479  *
2480  * Background layer initialized to maximum height and width settings based on
2481  * device tree properties and all overlay layers set to minimum height and width
2482  * sizes and positioned to 0,0 in the crtc.   All layers are inactive (resulting
2483  * in video output being generated by the background color generator).
2484  * Interrupts are disabled and the IP is started (with auto-restart enabled).
2485  */
2486 static void xlnx_mix_init(struct xlnx_mix_hw *mixer)
2487 {
2488         u32 i;
2489         u32 bg_bpc = mixer->bg_layer_bpc;
2490         u64 rgb_bg_clr = (0xFFFF >> (XVMIX_MAX_BPC - bg_bpc)) << (bg_bpc * 2);
2491         enum xlnx_mix_layer_id layer_id;
2492         struct xlnx_mix_layer_data *layer_data;
2493
2494         layer_data = xlnx_mix_get_layer_data(mixer, XVMIX_LAYER_MASTER);
2495         xlnx_mix_layer_disable(mixer, XVMIX_LAYER_ALL);
2496         xlnx_mix_set_active_area(mixer, layer_data->hw_config.max_width,
2497                                  layer_data->hw_config.max_height);
2498         /* default to blue */
2499         xlnx_mix_set_bkg_col(mixer, rgb_bg_clr);
2500
2501         for (i = 0; i < mixer->layer_cnt; i++) {
2502                 layer_id = mixer->layer_data[i].id;
2503                 layer_data = &mixer->layer_data[i];
2504                 if (layer_id == XVMIX_LAYER_MASTER)
2505                         continue;
2506                 xlnx_mix_set_layer_window(mixer, layer_id, 0, 0,
2507                                           XVMIX_LAYER_WIDTH_MIN,
2508                                           XVMIX_LAYER_HEIGHT_MIN, 0);
2509                 if (layer_data->hw_config.can_scale)
2510                         xlnx_mix_set_layer_scaling(mixer, layer_id, 0);
2511                 if (layer_data->hw_config.can_alpha)
2512                         xlnx_mix_set_layer_alpha(mixer, layer_id,
2513                                                  XVMIX_ALPHA_MAX);
2514         }
2515         xlnx_mix_intrpt_enable_done(mixer);
2516 }
2517
2518 static int xlnx_mix_bind(struct device *dev, struct device *master,
2519                          void *data)
2520 {
2521         struct xlnx_mix *mixer = dev_get_drvdata(dev);
2522         struct drm_device *drm = data;
2523         u32 ret;
2524
2525         mixer->drm = drm;
2526         ret = xlnx_mix_plane_create(dev, mixer);
2527         if (ret)
2528                 return ret;
2529         ret = xlnx_mix_crtc_create(mixer);
2530         if (ret)
2531                 return ret;
2532         xlnx_mix_init(&mixer->mixer_hw);
2533
2534         return ret;
2535 }
2536
2537 static void xlnx_mix_unbind(struct device *dev, struct device *master,
2538                             void *data)
2539 {
2540         struct xlnx_mix *mixer = dev_get_drvdata(dev);
2541
2542         dev_set_drvdata(dev, NULL);
2543         xlnx_mix_intrpt_disable(&mixer->mixer_hw);
2544         xlnx_crtc_unregister(mixer->drm, &mixer->crtc);
2545 }
2546
2547 static const struct component_ops xlnx_mix_component_ops = {
2548         .bind   = xlnx_mix_bind,
2549         .unbind = xlnx_mix_unbind,
2550 };
2551
2552 static int xlnx_mix_probe(struct platform_device *pdev)
2553 {
2554         struct xlnx_mix *mixer;
2555         int ret;
2556
2557         mixer = devm_kzalloc(&pdev->dev, sizeof(*mixer), GFP_KERNEL);
2558         if (!mixer)
2559                 return -ENOMEM;
2560
2561         /* Sub-driver will access mixer from drvdata */
2562         platform_set_drvdata(pdev, mixer);
2563         ret = xlnx_mix_dt_parse(&pdev->dev, mixer);
2564         if (ret) {
2565                 if (ret != -EPROBE_DEFER)
2566                         dev_err(&pdev->dev, "Failed to probe mixer\n");
2567                 return ret;
2568         }
2569
2570         ret = component_add(&pdev->dev, &xlnx_mix_component_ops);
2571         if (ret)
2572                 goto err;
2573
2574         mixer->master = xlnx_drm_pipeline_init(pdev);
2575         if (IS_ERR(mixer->master)) {
2576                 dev_err(&pdev->dev, "Failed to initialize the drm pipeline\n");
2577                 goto err_component;
2578         }
2579
2580         dev_info(&pdev->dev, "Xilinx Mixer driver probed success\n");
2581         return ret;
2582
2583 err_component:
2584         component_del(&pdev->dev, &xlnx_mix_component_ops);
2585 err:
2586         return ret;
2587 }
2588
2589 static int xlnx_mix_remove(struct platform_device *pdev)
2590 {
2591         struct xlnx_mix *mixer = platform_get_drvdata(pdev);
2592
2593         xlnx_drm_pipeline_exit(mixer->master);
2594         component_del(&pdev->dev, &xlnx_mix_component_ops);
2595         return 0;
2596 }
2597
2598 static const struct of_device_id xlnx_mix_of_match[] = {
2599         { .compatible = "xlnx,mixer-3.0", },
2600         { /* end of table */ },
2601 };
2602 MODULE_DEVICE_TABLE(of, xlnx_mix_of_match);
2603
2604 static struct platform_driver xlnx_mix_driver = {
2605         .probe                  = xlnx_mix_probe,
2606         .remove                 = xlnx_mix_remove,
2607         .driver                 = {
2608                 .name           = "xlnx-mixer",
2609                 .of_match_table = xlnx_mix_of_match,
2610         },
2611 };
2612
2613 module_platform_driver(xlnx_mix_driver);
2614
2615 MODULE_AUTHOR("Saurabh Sengar");
2616 MODULE_DESCRIPTION("Xilinx Mixer Driver");
2617 MODULE_LICENSE("GPL v2");