1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <drm/drmP.h>
19#include <drm/drm_crtc.h>
20#include <drm/drm_crtc_helper.h>
21#include <drm/drm_fourcc.h>
22
23#include <linux/device.h>
24#include <linux/interrupt.h>
25#include <linux/irqreturn.h>
26#include <linux/list.h>
27#include <linux/module.h>
28#include <linux/mutex.h>
29#include <linux/of.h>
30#include <linux/platform_device.h>
31
32#include "xilinx_drm_dp_sub.h"
33#include "xilinx_drm_drv.h"
34
35
36#define XILINX_DP_SUB_V_BLEND_BG_CLR_0 0x0
37#define XILINX_DP_SUB_V_BLEND_BG_CLR_1 0x4
38#define XILINX_DP_SUB_V_BLEND_BG_CLR_2 0x8
39#define XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA 0xc
40#define XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA_MASK 0x1fe
41#define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT 0x14
42#define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB 0x0
43#define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR444 0x1
44#define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR422 0x2
45#define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YONLY 0x3
46#define XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_XVYCC 0x4
47#define XILINX_DP_SUB_V_BLEND_OUTPUT_EN_DOWNSAMPLE BIT(4)
48#define XILINX_DP_SUB_V_BLEND_LAYER_CONTROL 0x18
49#define XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_EN_US BIT(0)
50#define XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_RGB BIT(1)
51#define XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_BYPASS BIT(8)
52#define XILINX_DP_SUB_V_BLEND_NUM_COEFF 9
53#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF0 0x20
54#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF1 0x24
55#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF2 0x28
56#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF3 0x2c
57#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF4 0x30
58#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF5 0x34
59#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF6 0x38
60#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF7 0x3c
61#define XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF8 0x40
62#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF0 0x44
63#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF1 0x48
64#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF2 0x4c
65#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF3 0x50
66#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF4 0x54
67#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF5 0x58
68#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF6 0x5c
69#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF7 0x60
70#define XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF8 0x64
71#define XILINX_DP_SUB_V_BLEND_NUM_OFFSET 3
72#define XILINX_DP_SUB_V_BLEND_LUMA_IN1CSC_OFFSET 0x68
73#define XILINX_DP_SUB_V_BLEND_CR_IN1CSC_OFFSET 0x6c
74#define XILINX_DP_SUB_V_BLEND_CB_IN1CSC_OFFSET 0x70
75#define XILINX_DP_SUB_V_BLEND_LUMA_OUTCSC_OFFSET 0x74
76#define XILINX_DP_SUB_V_BLEND_CR_OUTCSC_OFFSET 0x78
77#define XILINX_DP_SUB_V_BLEND_CB_OUTCSC_OFFSET 0x7c
78#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF0 0x80
79#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF1 0x84
80#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF2 0x88
81#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF3 0x8c
82#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF4 0x90
83#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF5 0x94
84#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF6 0x98
85#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF7 0x9c
86#define XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF8 0xa0
87#define XILINX_DP_SUB_V_BLEND_LUMA_IN2CSC_OFFSET 0xa4
88#define XILINX_DP_SUB_V_BLEND_CR_IN2CSC_OFFSET 0xa8
89#define XILINX_DP_SUB_V_BLEND_CB_IN2CSC_OFFSET 0xac
90#define XILINX_DP_SUB_V_BLEND_CHROMA_KEY_ENABLE 0x1d0
91#define XILINX_DP_SUB_V_BLEND_CHROMA_KEY_COMP1 0x1d4
92#define XILINX_DP_SUB_V_BLEND_CHROMA_KEY_COMP2 0x1d8
93#define XILINX_DP_SUB_V_BLEND_CHROMA_KEY_COMP3 0x1dc
94
95
96#define XILINX_DP_SUB_AV_BUF_FMT 0x0
97#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_SHIFT 0
98#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_MASK (0x1f << 0)
99#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_UYVY (0 << 0)
100#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_VYUY (1 << 0)
101#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YVYU (2 << 0)
102#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUYV (3 << 0)
103#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16 (4 << 0)
104#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV24 (5 << 0)
105#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI (6 << 0)
106#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_MONO (7 << 0)
107#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI2 (8 << 0)
108#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUV444 (9 << 0)
109#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888 (10 << 0)
110#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGBA8880 (11 << 0)
111#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888_10 (12 << 0)
112#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUV444_10 (13 << 0)
113#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI2_10 (14 << 0)
114#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_10 (15 << 0)
115#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16_10 (16 << 0)
116#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV24_10 (17 << 0)
117#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YONLY_10 (18 << 0)
118#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16_420 (19 << 0)
119#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_420 (20 << 0)
120#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI2_420 (21 << 0)
121#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16_420_10 (22 << 0)
122#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_420_10 (23 << 0)
123#define XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI2_420_10 (24 << 0)
124#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_SHIFT 8
125#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_MASK (0xf << 8)
126#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA8888 (0 << 8)
127#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_ABGR8888 (1 << 8)
128#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB888 (2 << 8)
129#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_BGR888 (3 << 8)
130#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA5551 (4 << 8)
131#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA4444 (5 << 8)
132#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB565 (6 << 8)
133#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_8BPP (7 << 8)
134#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_4BPP (8 << 8)
135#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_2BPP (9 << 8)
136#define XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_1BPP (10 << 8)
137#define XILINX_DP_SUB_AV_BUF_NON_LIVE_LATENCY 0x8
138#define XILINX_DP_SUB_AV_BUF_CHBUF 0x10
139#define XILINX_DP_SUB_AV_BUF_CHBUF_EN BIT(0)
140#define XILINX_DP_SUB_AV_BUF_CHBUF_FLUSH BIT(1)
141#define XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_SHIFT 2
142#define XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_MASK (0xf << 2)
143#define XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_MAX 0xf
144#define XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_AUD_MAX 0x3
145#define XILINX_DP_SUB_AV_BUF_STATUS 0x28
146#define XILINX_DP_SUB_AV_BUF_STC_CTRL 0x2c
147#define XILINX_DP_SUB_AV_BUF_STC_CTRL_EN BIT(0)
148#define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_SHIFT 1
149#define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_EX_VSYNC 0
150#define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_EX_VID 1
151#define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_EX_AUD 2
152#define XILINX_DP_SUB_AV_BUF_STC_CTRL_EVENT_INT_VSYNC 3
153#define XILINX_DP_SUB_AV_BUF_STC_INIT_VALUE0 0x30
154#define XILINX_DP_SUB_AV_BUF_STC_INIT_VALUE1 0x34
155#define XILINX_DP_SUB_AV_BUF_STC_ADJ 0x38
156#define XILINX_DP_SUB_AV_BUF_STC_VID_VSYNC_TS0 0x3c
157#define XILINX_DP_SUB_AV_BUF_STC_VID_VSYNC_TS1 0x40
158#define XILINX_DP_SUB_AV_BUF_STC_EXT_VSYNC_TS0 0x44
159#define XILINX_DP_SUB_AV_BUF_STC_EXT_VSYNC_TS1 0x48
160#define XILINX_DP_SUB_AV_BUF_STC_CUSTOM_EVENT_TS0 0x4c
161#define XILINX_DP_SUB_AV_BUF_STC_CUSTOM_EVENT_TS1 0x50
162#define XILINX_DP_SUB_AV_BUF_STC_CUSTOM_EVENT2_TS0 0x54
163#define XILINX_DP_SUB_AV_BUF_STC_CUSTOM_EVENT2_TS1 0x58
164#define XILINX_DP_SUB_AV_BUF_STC_SNAPSHOT0 0x60
165#define XILINX_DP_SUB_AV_BUF_STC_SNAPSHOT1 0x64
166#define XILINX_DP_SUB_AV_BUF_OUTPUT 0x70
167#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_SHIFT 0
168#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MASK (0x3 << 0)
169#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_PL (0 << 0)
170#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MEM (1 << 0)
171#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_PATTERN (2 << 0)
172#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_NONE (3 << 0)
173#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_SHIFT 2
174#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MASK (0x3 << 2)
175#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_DISABLE (0 << 2)
176#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MEM (1 << 2)
177#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_LIVE (2 << 2)
178#define XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_NONE (3 << 2)
179#define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_SHIFT 4
180#define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MASK (0x3 << 4)
181#define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_PL (0 << 4)
182#define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MEM (1 << 4)
183#define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_PATTERN (2 << 4)
184#define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_DISABLE (3 << 4)
185#define XILINX_DP_SUB_AV_BUF_OUTPUT_AUD2_EN BIT(6)
186#define XILINX_DP_SUB_AV_BUF_HCOUNT_VCOUNT_INT0 0x74
187#define XILINX_DP_SUB_AV_BUF_HCOUNT_VCOUNT_INT1 0x78
188#define XILINX_DP_SUB_AV_BUF_PATTERN_GEN_SELECT 0x100
189#define XILINX_DP_SUB_AV_BUF_CLK_SRC 0x120
190#define XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_FROM_PS BIT(0)
191#define XILINX_DP_SUB_AV_BUF_CLK_SRC_AUD_FROM_PS BIT(1)
192#define XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING BIT(2)
193#define XILINX_DP_SUB_AV_BUF_SRST_REG 0x124
194#define XILINX_DP_SUB_AV_BUF_SRST_REG_VID_RST BIT(1)
195#define XILINX_DP_SUB_AV_BUF_AUDIO_CH_CONFIG 0x12c
196#define XILINX_DP_SUB_AV_BUF_GFX_COMP0_SF 0x200
197#define XILINX_DP_SUB_AV_BUF_GFX_COMP1_SF 0x204
198#define XILINX_DP_SUB_AV_BUF_GFX_COMP2_SF 0x208
199#define XILINX_DP_SUB_AV_BUF_VID_COMP0_SF 0x20c
200#define XILINX_DP_SUB_AV_BUF_VID_COMP1_SF 0x210
201#define XILINX_DP_SUB_AV_BUF_VID_COMP2_SF 0x214
202#define XILINX_DP_SUB_AV_BUF_LIVE_VID_COMP0_SF 0x218
203#define XILINX_DP_SUB_AV_BUF_LIVE_VID_COMP1_SF 0x21c
204#define XILINX_DP_SUB_AV_BUF_LIVE_VID_COMP2_SF 0x220
205#define XILINX_DP_SUB_AV_BUF_4BIT_SF 0x11111
206#define XILINX_DP_SUB_AV_BUF_5BIT_SF 0x10842
207#define XILINX_DP_SUB_AV_BUF_6BIT_SF 0x10410
208#define XILINX_DP_SUB_AV_BUF_8BIT_SF 0x10101
209#define XILINX_DP_SUB_AV_BUF_10BIT_SF 0x10040
210#define XILINX_DP_SUB_AV_BUF_NULL_SF 0
211#define XILINX_DP_SUB_AV_BUF_NUM_SF 3
212#define XILINX_DP_SUB_AV_BUF_LIVE_CB_CR_SWAP 0x224
213#define XILINX_DP_SUB_AV_BUF_PALETTE_MEMORY 0x400
214
215
216#define XILINX_DP_SUB_AUD_MIXER_VOLUME 0x0
217#define XILINX_DP_SUB_AUD_MIXER_VOLUME_NO_SCALE 0x20002000
218#define XILINX_DP_SUB_AUD_MIXER_META_DATA 0x4
219#define XILINX_DP_SUB_AUD_CH_STATUS0 0x8
220#define XILINX_DP_SUB_AUD_CH_STATUS1 0xc
221#define XILINX_DP_SUB_AUD_CH_STATUS2 0x10
222#define XILINX_DP_SUB_AUD_CH_STATUS3 0x14
223#define XILINX_DP_SUB_AUD_CH_STATUS4 0x18
224#define XILINX_DP_SUB_AUD_CH_STATUS5 0x1c
225#define XILINX_DP_SUB_AUD_CH_A_DATA0 0x20
226#define XILINX_DP_SUB_AUD_CH_A_DATA1 0x24
227#define XILINX_DP_SUB_AUD_CH_A_DATA2 0x28
228#define XILINX_DP_SUB_AUD_CH_A_DATA3 0x2c
229#define XILINX_DP_SUB_AUD_CH_A_DATA4 0x30
230#define XILINX_DP_SUB_AUD_CH_A_DATA5 0x34
231#define XILINX_DP_SUB_AUD_CH_B_DATA0 0x38
232#define XILINX_DP_SUB_AUD_CH_B_DATA1 0x3c
233#define XILINX_DP_SUB_AUD_CH_B_DATA2 0x40
234#define XILINX_DP_SUB_AUD_CH_B_DATA3 0x44
235#define XILINX_DP_SUB_AUD_CH_B_DATA4 0x48
236#define XILINX_DP_SUB_AUD_CH_B_DATA5 0x4c
237#define XILINX_DP_SUB_AUD_SOFT_RESET 0xc00
238#define XILINX_DP_SUB_AUD_SOFT_RESET_AUD_SRST BIT(0)
239
240#define XILINX_DP_SUB_AV_BUF_NUM_VID_GFX_BUFFERS 4
241#define XILINX_DP_SUB_AV_BUF_NUM_BUFFERS 6
242
243
244
245
246
247
248enum xilinx_drm_dp_sub_layer_type {
249 XILINX_DRM_DP_SUB_LAYER_VID,
250 XILINX_DRM_DP_SUB_LAYER_GFX
251};
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267struct xilinx_drm_dp_sub_layer {
268 enum xilinx_drm_dp_sub_layer_type id;
269 u32 offset;
270 bool avail;
271 bool primary;
272 bool enabled;
273 const struct xilinx_drm_dp_sub_fmt *fmt;
274 uint32_t *drm_fmts;
275 unsigned int num_fmts;
276 uint32_t w;
277 uint32_t h;
278 struct xilinx_drm_dp_sub_layer *other;
279};
280
281
282
283
284
285struct xilinx_drm_dp_sub_blend {
286 void __iomem *base;
287};
288
289
290
291
292
293struct xilinx_drm_dp_sub_av_buf {
294 void __iomem *base;
295};
296
297
298
299
300
301struct xilinx_drm_dp_sub_aud {
302 void __iomem *base;
303};
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319struct xilinx_drm_dp_sub {
320 struct device *dev;
321 struct xilinx_drm_dp_sub_blend blend;
322 struct xilinx_drm_dp_sub_av_buf av_buf;
323 struct xilinx_drm_dp_sub_aud aud;
324 struct xilinx_drm_dp_sub_layer layers[XILINX_DRM_DP_SUB_NUM_LAYERS];
325 struct list_head list;
326 void (*vblank_fn)(void *);
327 void *vblank_data;
328 bool vid_clk_pl;
329 u32 alpha;
330 bool alpha_en;
331};
332
333
334
335
336
337
338
339
340
341
342
343struct xilinx_drm_dp_sub_fmt {
344 uint32_t drm_fmt;
345 u32 dp_sub_fmt;
346 bool rgb;
347 bool swap;
348 bool chroma_sub;
349 u32 sf[3];
350 const char *name;
351};
352
353static LIST_HEAD(xilinx_drm_dp_sub_list);
354static DEFINE_MUTEX(xilinx_drm_dp_sub_lock);
355
356
357
358
359
360
361
362
363
364
365static void
366xilinx_drm_dp_sub_blend_layer_enable(struct xilinx_drm_dp_sub_blend *blend,
367 struct xilinx_drm_dp_sub_layer *layer)
368{
369 u32 reg, offset, i, s0, s1;
370 u16 sdtv_coeffs[] = { 0x1000, 0x166f, 0x0,
371 0x1000, 0x7483, 0x7a7f,
372 0x1000, 0x0, 0x1c5a };
373 u16 swap_coeffs[] = { 0x1000, 0x0, 0x0,
374 0x0, 0x1000, 0x0,
375 0x0, 0x0, 0x1000 };
376 u16 *coeffs;
377 u32 offsets[] = { 0x0, 0x1800, 0x1800 };
378
379 reg = layer->fmt->rgb ? XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_RGB : 0;
380 reg |= layer->fmt->chroma_sub ?
381 XILINX_DP_SUB_V_BLEND_LAYER_CONTROL_EN_US : 0;
382
383 xilinx_drm_writel(blend->base,
384 XILINX_DP_SUB_V_BLEND_LAYER_CONTROL + layer->offset,
385 reg);
386
387
388 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID)
389 offset = XILINX_DP_SUB_V_BLEND_IN1CSC_COEFF0;
390 else
391 offset = XILINX_DP_SUB_V_BLEND_IN2CSC_COEFF0;
392
393 if (!layer->fmt->rgb) {
394 coeffs = sdtv_coeffs;
395 s0 = 1;
396 s1 = 2;
397 } else {
398 coeffs = swap_coeffs;
399 s0 = 0;
400 s1 = 2;
401
402
403 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_OFFSET; i++)
404 offsets[i] = 0;
405 }
406
407 if (layer->fmt->swap) {
408 for (i = 0; i < 3; i++) {
409 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
410 coeffs[i * 3 + s1] ^= coeffs[i * 3 + s0];
411 coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
412 }
413 }
414
415
416 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_COEFF; i++)
417 xilinx_drm_writel(blend->base, offset + i * 4, coeffs[i]);
418
419 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID)
420 offset = XILINX_DP_SUB_V_BLEND_LUMA_IN1CSC_OFFSET;
421 else
422 offset = XILINX_DP_SUB_V_BLEND_LUMA_IN2CSC_OFFSET;
423
424
425 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_OFFSET; i++)
426 xilinx_drm_writel(blend->base, offset + i * 4, offsets[i]);
427}
428
429
430
431
432
433
434
435
436static void
437xilinx_drm_dp_sub_blend_layer_disable(struct xilinx_drm_dp_sub_blend *blend,
438 struct xilinx_drm_dp_sub_layer *layer)
439{
440 xilinx_drm_writel(blend->base,
441 XILINX_DP_SUB_V_BLEND_LAYER_CONTROL + layer->offset,
442 0);
443}
444
445
446
447
448
449
450
451
452
453
454static void
455xilinx_drm_dp_sub_blend_set_bg_color(struct xilinx_drm_dp_sub_blend *blend,
456 u32 c0, u32 c1, u32 c2)
457{
458 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_BG_CLR_0, c0);
459 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_BG_CLR_1, c1);
460 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_BG_CLR_2, c2);
461}
462
463
464
465
466
467
468
469
470static void
471xilinx_drm_dp_sub_blend_set_alpha(struct xilinx_drm_dp_sub_blend *blend,
472 u32 alpha)
473{
474 u32 reg;
475
476 reg = xilinx_drm_readl(blend->base,
477 XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA);
478 reg &= ~XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA_MASK;
479 reg |= alpha << 1;
480 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA,
481 reg);
482}
483
484
485
486
487
488
489
490
491static void
492xilinx_drm_dp_sub_blend_enable_alpha(struct xilinx_drm_dp_sub_blend *blend,
493 bool enable)
494{
495 if (enable)
496 xilinx_drm_set(blend->base,
497 XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
498 else
499 xilinx_drm_clr(blend->base,
500 XILINX_DP_SUB_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
501}
502
503static const struct xilinx_drm_dp_sub_fmt blend_output_fmts[] = {
504 {
505 .drm_fmt = DRM_FORMAT_RGB888,
506 .dp_sub_fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB,
507 .rgb = true,
508 .swap = false,
509 .chroma_sub = false,
510 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
511 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
512 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
513 .name = "rgb888",
514 }, {
515 .drm_fmt = DRM_FORMAT_YUV444,
516 .dp_sub_fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR444,
517 .rgb = false,
518 .swap = false,
519 .chroma_sub = false,
520 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
521 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
522 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
523 .name = "yuv444",
524 }, {
525 .drm_fmt = DRM_FORMAT_YUV422,
526 .dp_sub_fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR422,
527 .rgb = false,
528 .swap = false,
529 .chroma_sub = true,
530 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
531 .sf[1] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
532 .sf[2] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
533 .name = "yuv422",
534 }, {
535 }
536};
537
538
539
540
541
542
543
544
545static void
546xilinx_drm_dp_sub_blend_set_output_fmt(struct xilinx_drm_dp_sub_blend *blend,
547 u32 fmt)
548{
549 xilinx_drm_writel(blend->base, XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT,
550 fmt);
551}
552
553
554
555static const struct xilinx_drm_dp_sub_fmt av_buf_vid_fmts[] = {
556 {
557 .drm_fmt = DRM_FORMAT_VYUY,
558 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_VYUY,
559 .rgb = false,
560 .swap = true,
561 .chroma_sub = true,
562 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
563 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
564 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
565 .name = "vyuy",
566 }, {
567 .drm_fmt = DRM_FORMAT_UYVY,
568 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_VYUY,
569 .rgb = false,
570 .swap = false,
571 .chroma_sub = true,
572 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
573 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
574 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
575 .name = "uyvy",
576 }, {
577 .drm_fmt = DRM_FORMAT_YUYV,
578 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUYV,
579 .rgb = false,
580 .swap = false,
581 .chroma_sub = true,
582 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
583 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
584 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
585 .name = "yuyv",
586 }, {
587 .drm_fmt = DRM_FORMAT_YVYU,
588 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YUYV,
589 .rgb = false,
590 .swap = true,
591 .chroma_sub = true,
592 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
593 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
594 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
595 .name = "yvyu",
596 }, {
597 .drm_fmt = DRM_FORMAT_NV16,
598 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI,
599 .rgb = false,
600 .swap = false,
601 .chroma_sub = true,
602 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
603 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
604 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
605 .name = "nv16",
606 }, {
607 .drm_fmt = DRM_FORMAT_NV61,
608 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI,
609 .rgb = false,
610 .swap = true,
611 .chroma_sub = true,
612 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
613 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
614 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
615 .name = "nv61",
616 }, {
617 .drm_fmt = DRM_FORMAT_BGR888,
618 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888,
619 .rgb = true,
620 .swap = false,
621 .chroma_sub = false,
622 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
623 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
624 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
625 .name = "bgr888",
626 }, {
627 .drm_fmt = DRM_FORMAT_RGB888,
628 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGB888,
629 .rgb = true,
630 .swap = true,
631 .chroma_sub = false,
632 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
633 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
634 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
635 .name = "rgb888",
636 }, {
637 .drm_fmt = DRM_FORMAT_XBGR8888,
638 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGBA8880,
639 .rgb = true,
640 .swap = false,
641 .chroma_sub = false,
642 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
643 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
644 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
645 .name = "xbgr8888",
646 }, {
647 .drm_fmt = DRM_FORMAT_XRGB8888,
648 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_RGBA8880,
649 .rgb = true,
650 .swap = true,
651 .chroma_sub = false,
652 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
653 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
654 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
655 .name = "xrgb8888",
656 }, {
657 .drm_fmt = DRM_FORMAT_NV12,
658 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_420,
659 .rgb = false,
660 .swap = false,
661 .chroma_sub = true,
662 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
663 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
664 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
665 .name = "nv12",
666 }, {
667 .drm_fmt = DRM_FORMAT_NV21,
668 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_VID_YV16CI_420,
669 .rgb = false,
670 .swap = true,
671 .chroma_sub = true,
672 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
673 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
674 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
675 .name = "nv21",
676 }
677};
678
679static const struct xilinx_drm_dp_sub_fmt av_buf_gfx_fmts[] = {
680 {
681 .drm_fmt = DRM_FORMAT_ABGR8888,
682 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA8888,
683 .rgb = true,
684 .swap = false,
685 .chroma_sub = false,
686 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
687 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
688 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
689 .name = "abgr8888",
690 }, {
691 .drm_fmt = DRM_FORMAT_ARGB8888,
692 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA8888,
693 .rgb = true,
694 .swap = true,
695 .chroma_sub = false,
696 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
697 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
698 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
699 .name = "argb8888",
700 }, {
701 .drm_fmt = DRM_FORMAT_RGBA8888,
702 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_ABGR8888,
703 .rgb = true,
704 .swap = false,
705 .chroma_sub = false,
706 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
707 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
708 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
709 .name = "rgba8888",
710 }, {
711 .drm_fmt = DRM_FORMAT_BGRA8888,
712 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_ABGR8888,
713 .rgb = true,
714 .swap = true,
715 .chroma_sub = false,
716 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
717 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
718 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
719 .name = "bgra8888",
720 }, {
721 .drm_fmt = DRM_FORMAT_BGR888,
722 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB888,
723 .rgb = true,
724 .swap = false,
725 .chroma_sub = false,
726 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
727 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
728 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
729 .name = "bgr888",
730 }, {
731 .drm_fmt = DRM_FORMAT_RGB888,
732 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_BGR888,
733 .rgb = true,
734 .swap = false,
735 .chroma_sub = false,
736 .sf[0] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
737 .sf[1] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
738 .sf[2] = XILINX_DP_SUB_AV_BUF_8BIT_SF,
739 .name = "rgb888",
740 }, {
741 .drm_fmt = DRM_FORMAT_RGBA5551,
742 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA5551,
743 .rgb = true,
744 .swap = false,
745 .chroma_sub = false,
746 .sf[0] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
747 .sf[1] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
748 .sf[2] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
749 .name = "rgba5551",
750 }, {
751 .drm_fmt = DRM_FORMAT_BGRA5551,
752 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA5551,
753 .rgb = true,
754 .swap = true,
755 .chroma_sub = false,
756 .sf[0] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
757 .sf[1] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
758 .sf[2] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
759 .name = "bgra5551",
760 }, {
761 .drm_fmt = DRM_FORMAT_RGBA4444,
762 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA4444,
763 .rgb = true,
764 .swap = false,
765 .chroma_sub = false,
766 .sf[0] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
767 .sf[1] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
768 .sf[2] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
769 .name = "rgba4444",
770 }, {
771 .drm_fmt = DRM_FORMAT_BGRA4444,
772 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGBA4444,
773 .rgb = true,
774 .swap = true,
775 .chroma_sub = false,
776 .sf[0] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
777 .sf[1] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
778 .sf[2] = XILINX_DP_SUB_AV_BUF_4BIT_SF,
779 .name = "bgra4444",
780 }, {
781 .drm_fmt = DRM_FORMAT_RGB565,
782 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB565,
783 .rgb = true,
784 .swap = false,
785 .chroma_sub = false,
786 .sf[0] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
787 .sf[1] = XILINX_DP_SUB_AV_BUF_6BIT_SF,
788 .sf[2] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
789 .name = "rgb565",
790 }, {
791 .drm_fmt = DRM_FORMAT_BGR565,
792 .dp_sub_fmt = XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_RGB565,
793 .rgb = true,
794 .swap = true,
795 .chroma_sub = false,
796 .sf[0] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
797 .sf[1] = XILINX_DP_SUB_AV_BUF_6BIT_SF,
798 .sf[2] = XILINX_DP_SUB_AV_BUF_5BIT_SF,
799 .name = "bgr565",
800 }
801};
802
803
804
805
806
807
808
809
810
811static void
812xilinx_drm_dp_sub_av_buf_set_fmt(struct xilinx_drm_dp_sub_av_buf *av_buf,
813 u32 fmt)
814{
815 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_FMT, fmt);
816}
817
818
819
820
821
822
823
824
825
826
827static u32
828xilinx_drm_dp_sub_av_buf_get_fmt(struct xilinx_drm_dp_sub_av_buf *av_buf)
829{
830 return xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_FMT);
831}
832
833
834
835
836
837
838
839
840
841static void xilinx_drm_dp_sub_av_buf_set_vid_clock_src(
842 struct xilinx_drm_dp_sub_av_buf *av_buf, bool from_ps)
843{
844 u32 reg;
845
846 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC);
847 if (from_ps)
848 reg |= XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_FROM_PS;
849 else
850 reg &= ~XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_FROM_PS;
851 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC, reg);
852}
853
854
855
856
857
858
859
860
861
862static void xilinx_drm_dp_sub_av_buf_set_vid_timing_src(
863 struct xilinx_drm_dp_sub_av_buf *av_buf, bool internal)
864{
865 u32 reg;
866
867 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC);
868 if (internal)
869 reg |= XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
870 else
871 reg &= ~XILINX_DP_SUB_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
872 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC, reg);
873}
874
875
876
877
878
879
880
881
882
883static void xilinx_drm_dp_sub_av_buf_set_aud_clock_src(
884 struct xilinx_drm_dp_sub_av_buf *av_buf, bool from_ps)
885{
886 u32 reg;
887
888 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC);
889 if (from_ps)
890 reg |= XILINX_DP_SUB_AV_BUF_CLK_SRC_AUD_FROM_PS;
891 else
892 reg &= ~XILINX_DP_SUB_AV_BUF_CLK_SRC_AUD_FROM_PS;
893 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_CLK_SRC, reg);
894}
895
896
897
898
899
900
901
902static void
903xilinx_drm_dp_sub_av_buf_enable_buf(struct xilinx_drm_dp_sub_av_buf *av_buf)
904{
905 u32 reg, i;
906
907 reg = XILINX_DP_SUB_AV_BUF_CHBUF_EN;
908 reg |= XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_MAX <<
909 XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_SHIFT;
910
911 for (i = 0; i < XILINX_DP_SUB_AV_BUF_NUM_VID_GFX_BUFFERS; i++)
912 xilinx_drm_writel(av_buf->base,
913 XILINX_DP_SUB_AV_BUF_CHBUF + i * 4, reg);
914
915 reg = XILINX_DP_SUB_AV_BUF_CHBUF_EN;
916 reg |= XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_AUD_MAX <<
917 XILINX_DP_SUB_AV_BUF_CHBUF_BURST_LEN_SHIFT;
918
919 for (; i < XILINX_DP_SUB_AV_BUF_NUM_BUFFERS; i++)
920 xilinx_drm_writel(av_buf->base,
921 XILINX_DP_SUB_AV_BUF_CHBUF + i * 4, reg);
922}
923
924
925
926
927
928
929
930static void
931xilinx_drm_dp_sub_av_buf_disable_buf(struct xilinx_drm_dp_sub_av_buf *av_buf)
932{
933 u32 reg, i;
934
935 reg = XILINX_DP_SUB_AV_BUF_CHBUF_FLUSH & ~XILINX_DP_SUB_AV_BUF_CHBUF_EN;
936 for (i = 0; i < XILINX_DP_SUB_AV_BUF_NUM_BUFFERS; i++)
937 xilinx_drm_writel(av_buf->base,
938 XILINX_DP_SUB_AV_BUF_CHBUF + i * 4, reg);
939}
940
941
942
943
944
945
946
947static void
948xilinx_drm_dp_sub_av_buf_enable_aud(struct xilinx_drm_dp_sub_av_buf *av_buf)
949{
950 u32 reg;
951
952 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT);
953 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MASK;
954 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MEM;
955 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_AUD2_EN;
956 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT, reg);
957}
958
959
960
961
962
963
964
965static void
966xilinx_drm_dp_sub_av_buf_enable(struct xilinx_drm_dp_sub_av_buf *av_buf)
967{
968 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_SRST_REG, 0);
969}
970
971
972
973
974
975
976
977static void
978xilinx_drm_dp_sub_av_buf_disable(struct xilinx_drm_dp_sub_av_buf *av_buf)
979{
980 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_SRST_REG,
981 XILINX_DP_SUB_AV_BUF_SRST_REG_VID_RST);
982}
983
984
985
986
987
988
989
990static void
991xilinx_drm_dp_sub_av_buf_disable_aud(struct xilinx_drm_dp_sub_av_buf *av_buf)
992{
993 u32 reg;
994
995 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT);
996 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_MASK;
997 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_AUD1_DISABLE;
998 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_AUD2_EN;
999 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT, reg);
1000}
1001
1002
1003
1004
1005
1006
1007
1008
1009static void
1010xilinx_drm_dp_sub_av_buf_enable_vid(struct xilinx_drm_dp_sub_av_buf *av_buf,
1011 struct xilinx_drm_dp_sub_layer *layer)
1012{
1013 u32 reg;
1014
1015 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT);
1016 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID) {
1017 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MASK;
1018 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MEM;
1019 } else {
1020 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MASK;
1021 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MEM;
1022 }
1023 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT, reg);
1024}
1025
1026
1027
1028
1029
1030
1031
1032
1033static void
1034xilinx_drm_dp_sub_av_buf_disable_vid(struct xilinx_drm_dp_sub_av_buf *av_buf,
1035 struct xilinx_drm_dp_sub_layer *layer)
1036{
1037 u32 reg;
1038
1039 reg = xilinx_drm_readl(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT);
1040
1041 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID) {
1042 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_MASK;
1043 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_VID1_NONE;
1044 } else {
1045 reg &= ~XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_MASK;
1046 reg |= XILINX_DP_SUB_AV_BUF_OUTPUT_VID2_DISABLE;
1047 }
1048
1049 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_OUTPUT, reg);
1050}
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060static void
1061xilinx_drm_dp_sub_av_buf_init_fmts(struct xilinx_drm_dp_sub_av_buf *av_buf,
1062 const struct xilinx_drm_dp_sub_fmt *vid_fmt,
1063 const struct xilinx_drm_dp_sub_fmt *gfx_fmt)
1064{
1065 u32 reg;
1066
1067 reg = vid_fmt->dp_sub_fmt;
1068 reg |= gfx_fmt->dp_sub_fmt;
1069 xilinx_drm_writel(av_buf->base, XILINX_DP_SUB_AV_BUF_FMT, reg);
1070}
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080static void
1081xilinx_drm_dp_sub_av_buf_init_sf(struct xilinx_drm_dp_sub_av_buf *av_buf,
1082 const struct xilinx_drm_dp_sub_fmt *vid_fmt,
1083 const struct xilinx_drm_dp_sub_fmt *gfx_fmt)
1084{
1085 unsigned int i;
1086 int offset;
1087
1088 offset = XILINX_DP_SUB_AV_BUF_GFX_COMP0_SF;
1089 for (i = 0; i < XILINX_DP_SUB_AV_BUF_NUM_SF; i++)
1090 xilinx_drm_writel(av_buf->base, offset + i * 4, gfx_fmt->sf[i]);
1091
1092 offset = XILINX_DP_SUB_AV_BUF_VID_COMP0_SF;
1093 for (i = 0; i < XILINX_DP_SUB_AV_BUF_NUM_SF; i++)
1094 xilinx_drm_writel(av_buf->base, offset + i * 4, vid_fmt->sf[i]);
1095}
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106static void xilinx_drm_dp_sub_aud_init(struct xilinx_drm_dp_sub_aud *aud)
1107{
1108
1109 xilinx_drm_writel(aud->base, XILINX_DP_SUB_AUD_SOFT_RESET, 0);
1110 xilinx_drm_writel(aud->base, XILINX_DP_SUB_AUD_MIXER_VOLUME,
1111 XILINX_DP_SUB_AUD_MIXER_VOLUME_NO_SCALE);
1112}
1113
1114
1115
1116
1117
1118
1119
1120static void xilinx_drm_dp_sub_aud_deinit(struct xilinx_drm_dp_sub_aud *aud)
1121{
1122 xilinx_drm_set(aud->base, XILINX_DP_SUB_AUD_SOFT_RESET,
1123 XILINX_DP_SUB_AUD_SOFT_RESET_AUD_SRST);
1124}
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141int xilinx_drm_dp_sub_layer_check_size(struct xilinx_drm_dp_sub *dp_sub,
1142 struct xilinx_drm_dp_sub_layer *layer,
1143 uint32_t width, uint32_t height)
1144{
1145 struct xilinx_drm_dp_sub_layer *other = layer->other;
1146
1147 if (other->enabled && (other->w != width || other->h != height)) {
1148 dev_err(dp_sub->dev, "Layer width:height must be %d:%d\n",
1149 other->w, other->h);
1150 return -EINVAL;
1151 }
1152
1153 layer->w = width;
1154 layer->h = height;
1155
1156 return 0;
1157}
1158EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_check_size);
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172static const struct xilinx_drm_dp_sub_fmt *
1173xilinx_drm_dp_sub_map_fmt(const struct xilinx_drm_dp_sub_fmt fmts[],
1174 unsigned int size, uint32_t drm_fmt)
1175{
1176 unsigned int i;
1177
1178 for (i = 0; i < size; i++)
1179 if (fmts[i].drm_fmt == drm_fmt)
1180 return &fmts[i];
1181
1182 return NULL;
1183}
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195int xilinx_drm_dp_sub_layer_set_fmt(struct xilinx_drm_dp_sub *dp_sub,
1196 struct xilinx_drm_dp_sub_layer *layer,
1197 uint32_t drm_fmt)
1198{
1199 const struct xilinx_drm_dp_sub_fmt *table;
1200 const struct xilinx_drm_dp_sub_fmt *fmt;
1201 u32 size, fmts, mask;
1202
1203 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID) {
1204 table = av_buf_vid_fmts;
1205 size = ARRAY_SIZE(av_buf_vid_fmts);
1206 mask = ~XILINX_DP_SUB_AV_BUF_FMT_NL_VID_MASK;
1207 } else {
1208 table = av_buf_gfx_fmts;
1209 size = ARRAY_SIZE(av_buf_gfx_fmts);
1210 mask = ~XILINX_DP_SUB_AV_BUF_FMT_NL_GFX_MASK;
1211 }
1212
1213 fmt = xilinx_drm_dp_sub_map_fmt(table, size, drm_fmt);
1214 if (!fmt)
1215 return -EINVAL;
1216
1217 fmts = xilinx_drm_dp_sub_av_buf_get_fmt(&dp_sub->av_buf);
1218 fmts &= mask;
1219 fmts |= fmt->dp_sub_fmt;
1220 xilinx_drm_dp_sub_av_buf_set_fmt(&dp_sub->av_buf, fmts);
1221
1222 layer->fmt = fmt;
1223
1224 return 0;
1225}
1226EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_set_fmt);
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237uint32_t xilinx_drm_dp_sub_layer_get_fmt(struct xilinx_drm_dp_sub *dp_sub,
1238 struct xilinx_drm_dp_sub_layer *layer)
1239{
1240 return layer->fmt->drm_fmt;
1241}
1242EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_get_fmt);
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253void xilinx_drm_dp_sub_layer_get_fmts(struct xilinx_drm_dp_sub *dp_sub,
1254 struct xilinx_drm_dp_sub_layer *layer,
1255 uint32_t **drm_fmts,
1256 unsigned int *num_fmts)
1257{
1258 *drm_fmts = layer->drm_fmts;
1259 *num_fmts = layer->num_fmts;
1260}
1261EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_get_fmts);
1262
1263
1264
1265
1266
1267
1268
1269
1270void xilinx_drm_dp_sub_layer_enable(struct xilinx_drm_dp_sub *dp_sub,
1271 struct xilinx_drm_dp_sub_layer *layer)
1272{
1273 xilinx_drm_dp_sub_av_buf_enable_vid(&dp_sub->av_buf, layer);
1274 xilinx_drm_dp_sub_blend_layer_enable(&dp_sub->blend, layer);
1275 layer->enabled = true;
1276 if (layer->other->enabled) {
1277 xilinx_drm_dp_sub_blend_set_alpha(&dp_sub->blend,
1278 dp_sub->alpha);
1279 xilinx_drm_dp_sub_blend_enable_alpha(&dp_sub->blend,
1280 dp_sub->alpha_en);
1281 } else {
1282 u32 alpha;
1283
1284 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID)
1285 alpha = 0;
1286 else
1287 alpha = XILINX_DRM_DP_SUB_MAX_ALPHA;
1288 xilinx_drm_dp_sub_blend_set_alpha(&dp_sub->blend, alpha);
1289 xilinx_drm_dp_sub_blend_enable_alpha(&dp_sub->blend, true);
1290 }
1291}
1292EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_enable);
1293
1294
1295
1296
1297
1298
1299
1300
1301void xilinx_drm_dp_sub_layer_disable(struct xilinx_drm_dp_sub *dp_sub,
1302 struct xilinx_drm_dp_sub_layer *layer)
1303{
1304 xilinx_drm_dp_sub_av_buf_disable_vid(&dp_sub->av_buf, layer);
1305 xilinx_drm_dp_sub_blend_layer_disable(&dp_sub->blend, layer);
1306 layer->enabled = false;
1307 if (layer->other->enabled) {
1308 u32 alpha;
1309
1310 if (layer->id == XILINX_DRM_DP_SUB_LAYER_VID)
1311 alpha = XILINX_DRM_DP_SUB_MAX_ALPHA;
1312 else
1313 alpha = 0;
1314 xilinx_drm_dp_sub_blend_set_alpha(&dp_sub->blend, alpha);
1315 xilinx_drm_dp_sub_blend_enable_alpha(&dp_sub->blend, true);
1316 }
1317}
1318EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_disable);
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330struct xilinx_drm_dp_sub_layer *
1331xilinx_drm_dp_sub_layer_get(struct xilinx_drm_dp_sub *dp_sub, bool primary)
1332{
1333 struct xilinx_drm_dp_sub_layer *layer = NULL;
1334 unsigned int i;
1335
1336 for (i = 0; i < XILINX_DRM_DP_SUB_NUM_LAYERS; i++) {
1337 if (dp_sub->layers[i].primary == primary) {
1338 layer = &dp_sub->layers[i];
1339 break;
1340 }
1341 }
1342
1343 if (!layer || !layer->avail)
1344 return ERR_PTR(-ENODEV);
1345
1346 return layer;
1347
1348}
1349EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_get);
1350
1351
1352
1353
1354
1355
1356
1357
1358void xilinx_drm_dp_sub_layer_put(struct xilinx_drm_dp_sub *dp_sub,
1359 struct xilinx_drm_dp_sub_layer *layer)
1360{
1361 layer->avail = true;
1362}
1363EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_layer_put);
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377int xilinx_drm_dp_sub_set_output_fmt(struct xilinx_drm_dp_sub *dp_sub,
1378 uint32_t drm_fmt)
1379{
1380 const struct xilinx_drm_dp_sub_fmt *fmt;
1381
1382 fmt = xilinx_drm_dp_sub_map_fmt(blend_output_fmts,
1383 ARRAY_SIZE(blend_output_fmts), drm_fmt);
1384 if (!fmt)
1385 return -EINVAL;
1386
1387 xilinx_drm_dp_sub_blend_set_output_fmt(&dp_sub->blend, fmt->dp_sub_fmt);
1388
1389 return 0;
1390}
1391EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_set_output_fmt);
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402void xilinx_drm_dp_sub_set_bg_color(struct xilinx_drm_dp_sub *dp_sub,
1403 u32 c0, u32 c1, u32 c2)
1404{
1405 xilinx_drm_dp_sub_blend_set_bg_color(&dp_sub->blend, c0, c1, c2);
1406}
1407EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_set_bg_color);
1408
1409
1410
1411
1412
1413
1414
1415
1416void xilinx_drm_dp_sub_set_alpha(struct xilinx_drm_dp_sub *dp_sub, u32 alpha)
1417{
1418 dp_sub->alpha = alpha;
1419 if (dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID].enabled &&
1420 dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX].enabled)
1421 xilinx_drm_dp_sub_blend_set_alpha(&dp_sub->blend, alpha);
1422}
1423EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_set_alpha);
1424
1425
1426
1427
1428
1429
1430
1431
1432void
1433xilinx_drm_dp_sub_enable_alpha(struct xilinx_drm_dp_sub *dp_sub, bool enable)
1434{
1435 dp_sub->alpha_en = enable;
1436 if (dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID].enabled &&
1437 dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX].enabled)
1438 xilinx_drm_dp_sub_blend_enable_alpha(&dp_sub->blend, enable);
1439}
1440EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_enable_alpha);
1441
1442
1443
1444
1445
1446
1447
1448
1449void xilinx_drm_dp_sub_handle_vblank(struct xilinx_drm_dp_sub *dp_sub)
1450{
1451 if (dp_sub->vblank_fn)
1452 dp_sub->vblank_fn(dp_sub->vblank_data);
1453}
1454EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_handle_vblank);
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465void xilinx_drm_dp_sub_enable_vblank(struct xilinx_drm_dp_sub *dp_sub,
1466 void (*vblank_fn)(void *),
1467 void *vblank_data)
1468{
1469 dp_sub->vblank_fn = vblank_fn;
1470 dp_sub->vblank_data = vblank_data;
1471}
1472EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_enable_vblank);
1473
1474
1475
1476
1477
1478
1479
1480void xilinx_drm_dp_sub_disable_vblank(struct xilinx_drm_dp_sub *dp_sub)
1481{
1482 dp_sub->vblank_fn = NULL;
1483 dp_sub->vblank_data = NULL;
1484}
1485EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_disable_vblank);
1486
1487
1488
1489
1490
1491
1492
1493void xilinx_drm_dp_sub_enable(struct xilinx_drm_dp_sub *dp_sub)
1494{
1495 const struct xilinx_drm_dp_sub_fmt *vid_fmt;
1496 const struct xilinx_drm_dp_sub_fmt *gfx_fmt;
1497
1498 vid_fmt = dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID].fmt;
1499 gfx_fmt = dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX].fmt;
1500 xilinx_drm_dp_sub_av_buf_enable(&dp_sub->av_buf);
1501 xilinx_drm_dp_sub_av_buf_init_fmts(&dp_sub->av_buf, vid_fmt, gfx_fmt);
1502 xilinx_drm_dp_sub_av_buf_init_sf(&dp_sub->av_buf, vid_fmt, gfx_fmt);
1503 xilinx_drm_dp_sub_av_buf_set_vid_clock_src(&dp_sub->av_buf,
1504 !dp_sub->vid_clk_pl);
1505 xilinx_drm_dp_sub_av_buf_set_vid_timing_src(&dp_sub->av_buf, true);
1506 xilinx_drm_dp_sub_av_buf_set_aud_clock_src(&dp_sub->av_buf, true);
1507 xilinx_drm_dp_sub_av_buf_enable_buf(&dp_sub->av_buf);
1508 xilinx_drm_dp_sub_av_buf_enable_aud(&dp_sub->av_buf);
1509 xilinx_drm_dp_sub_aud_init(&dp_sub->aud);
1510}
1511EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_enable);
1512
1513
1514
1515
1516
1517
1518
1519void xilinx_drm_dp_sub_disable(struct xilinx_drm_dp_sub *dp_sub)
1520{
1521 xilinx_drm_dp_sub_aud_deinit(&dp_sub->aud);
1522 xilinx_drm_dp_sub_av_buf_disable_aud(&dp_sub->av_buf);
1523 xilinx_drm_dp_sub_av_buf_disable_buf(&dp_sub->av_buf);
1524 xilinx_drm_dp_sub_av_buf_disable(&dp_sub->av_buf);
1525}
1526EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_disable);
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543struct xilinx_drm_dp_sub *xilinx_drm_dp_sub_of_get(struct device_node *np)
1544{
1545 struct device_node *xilinx_drm_dp_sub_node;
1546 struct xilinx_drm_dp_sub *found = NULL;
1547 struct xilinx_drm_dp_sub *dp_sub;
1548
1549 if (!of_find_property(np, "xlnx,dp-sub", NULL))
1550 return NULL;
1551
1552 xilinx_drm_dp_sub_node = of_parse_phandle(np, "xlnx,dp-sub", 0);
1553 if (xilinx_drm_dp_sub_node == NULL)
1554 return ERR_PTR(-EINVAL);
1555
1556 mutex_lock(&xilinx_drm_dp_sub_lock);
1557 list_for_each_entry(dp_sub, &xilinx_drm_dp_sub_list, list) {
1558 if (dp_sub->dev->of_node == xilinx_drm_dp_sub_node) {
1559 found = dp_sub;
1560 break;
1561 }
1562 }
1563 mutex_unlock(&xilinx_drm_dp_sub_lock);
1564
1565 of_node_put(xilinx_drm_dp_sub_node);
1566
1567 if (!found)
1568 return ERR_PTR(-EPROBE_DEFER);
1569
1570 return found;
1571}
1572EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_of_get);
1573
1574
1575
1576
1577
1578
1579
1580void xilinx_drm_dp_sub_put(struct xilinx_drm_dp_sub *dp_sub)
1581{
1582
1583}
1584EXPORT_SYMBOL_GPL(xilinx_drm_dp_sub_put);
1585
1586
1587
1588
1589
1590
1591
1592static void xilinx_drm_dp_sub_register_device(struct xilinx_drm_dp_sub *dp_sub)
1593{
1594 mutex_lock(&xilinx_drm_dp_sub_lock);
1595 list_add_tail(&dp_sub->list, &xilinx_drm_dp_sub_list);
1596 mutex_unlock(&xilinx_drm_dp_sub_lock);
1597}
1598
1599
1600
1601
1602
1603
1604
1605static void
1606xilinx_drm_dp_sub_unregister_device(struct xilinx_drm_dp_sub *dp_sub)
1607{
1608 mutex_lock(&xilinx_drm_dp_sub_lock);
1609 list_del(&dp_sub->list);
1610 mutex_unlock(&xilinx_drm_dp_sub_lock);
1611}
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621static int xilinx_drm_dp_sub_parse_of(struct xilinx_drm_dp_sub *dp_sub)
1622{
1623 struct device_node *node = dp_sub->dev->of_node;
1624 struct xilinx_drm_dp_sub_layer *layer;
1625 const char *string;
1626 u32 fmt, i, size;
1627 bool ret;
1628
1629 ret = of_property_read_string(node, "xlnx,output-fmt", &string);
1630 if (ret < 0) {
1631 dev_err(dp_sub->dev, "No colormetry in DT\n");
1632 return ret;
1633 }
1634
1635 if (strcmp(string, "rgb") == 0) {
1636 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB;
1637 } else if (strcmp(string, "ycrcb444") == 0) {
1638 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR444;
1639 } else if (strcmp(string, "ycrcb422") == 0) {
1640 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YCBCR422;
1641 fmt |= XILINX_DP_SUB_V_BLEND_OUTPUT_EN_DOWNSAMPLE;
1642 } else if (strcmp(string, "yonly") == 0) {
1643 fmt = XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_YONLY;
1644 } else {
1645 dev_err(dp_sub->dev, "Invalid output format in DT\n");
1646 return -EINVAL;
1647 }
1648
1649 xilinx_drm_writel(dp_sub->blend.base,
1650 XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT, fmt);
1651
1652 if (fmt != XILINX_DP_SUB_V_BLEND_OUTPUT_VID_FMT_RGB) {
1653 u16 sdtv_coeffs[] = { 0x4c9, 0x864, 0x1d3,
1654 0x7d4d, 0x7ab3, 0x800,
1655 0x800, 0x794d, 0x7eb3 };
1656 u32 full_range_offsets[] = { 0x0, 0x8000000, 0x8000000 };
1657 u32 offset, i;
1658
1659
1660 offset = XILINX_DP_SUB_V_BLEND_RGB2YCBCR_COEFF0;
1661 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_COEFF; i++)
1662 xilinx_drm_writel(dp_sub->blend.base, offset + i * 4,
1663 sdtv_coeffs[i]);
1664
1665 offset = XILINX_DP_SUB_V_BLEND_LUMA_OUTCSC_OFFSET;
1666 for (i = 0; i < XILINX_DP_SUB_V_BLEND_NUM_OFFSET; i++)
1667 xilinx_drm_writel(dp_sub->blend.base, offset + i * 4,
1668 full_range_offsets[i]);
1669 }
1670
1671 ret = of_property_read_bool(node, "xlnx,vid-primary");
1672 if (ret)
1673 dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID].primary = true;
1674 else
1675 dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX].primary = true;
1676
1677 ret = of_property_read_string(node, "xlnx,vid-fmt", &string);
1678 if (!ret) {
1679 layer = &dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_VID];
1680 size = ARRAY_SIZE(av_buf_vid_fmts);
1681 layer->num_fmts = size;
1682 layer->drm_fmts = devm_kzalloc(dp_sub->dev,
1683 sizeof(*layer->drm_fmts) * size,
1684 GFP_KERNEL);
1685 if (!layer->drm_fmts)
1686 return -ENOMEM;
1687
1688 for (i = 0; i < layer->num_fmts; i++) {
1689 const struct xilinx_drm_dp_sub_fmt *fmt =
1690 &av_buf_vid_fmts[i];
1691
1692 if (strcmp(string, fmt->name) == 0)
1693 layer->fmt = fmt;
1694
1695 layer->drm_fmts[i] = fmt->drm_fmt;
1696 }
1697
1698 if (!layer->fmt) {
1699 dev_info(dp_sub->dev, "Invalid vid-fmt in DT\n");
1700 layer->fmt = &av_buf_vid_fmts[0];
1701 }
1702 }
1703
1704 ret = of_property_read_string(node, "xlnx,gfx-fmt", &string);
1705 if (!ret) {
1706 layer = &dp_sub->layers[XILINX_DRM_DP_SUB_LAYER_GFX];
1707 size = ARRAY_SIZE(av_buf_gfx_fmts);
1708 layer->num_fmts = size;
1709 layer->drm_fmts = devm_kzalloc(dp_sub->dev,
1710 sizeof(*layer->drm_fmts) * size,
1711 GFP_KERNEL);
1712 if (!layer->drm_fmts)
1713 return -ENOMEM;
1714
1715 for (i = 0; i < layer->num_fmts; i++) {
1716 const struct xilinx_drm_dp_sub_fmt *fmt =
1717 &av_buf_gfx_fmts[i];
1718
1719 if (strcmp(string, fmt->name) == 0)
1720 layer->fmt = fmt;
1721
1722 layer->drm_fmts[i] = fmt->drm_fmt;
1723 }
1724
1725 if (!layer->fmt) {
1726 dev_info(dp_sub->dev, "Invalid vid-fmt in DT\n");
1727 layer->fmt = &av_buf_gfx_fmts[0];
1728 }
1729 }
1730
1731 dp_sub->vid_clk_pl = of_property_read_bool(node, "xlnx,vid-clk-pl");
1732
1733 return 0;
1734}
1735
1736static int xilinx_drm_dp_sub_probe(struct platform_device *pdev)
1737{
1738 struct xilinx_drm_dp_sub *dp_sub;
1739 struct resource *res;
1740 int ret;
1741
1742 dp_sub = devm_kzalloc(&pdev->dev, sizeof(*dp_sub), GFP_KERNEL);
1743 if (!dp_sub)
1744 return -ENOMEM;
1745
1746 dp_sub->dev = &pdev->dev;
1747
1748 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
1749 dp_sub->blend.base = devm_ioremap_resource(&pdev->dev, res);
1750 if (IS_ERR(dp_sub->blend.base))
1751 return PTR_ERR(dp_sub->blend.base);
1752
1753 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
1754 dp_sub->av_buf.base = devm_ioremap_resource(&pdev->dev, res);
1755 if (IS_ERR(dp_sub->av_buf.base))
1756 return PTR_ERR(dp_sub->av_buf.base);
1757
1758 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
1759 dp_sub->aud.base = devm_ioremap_resource(&pdev->dev, res);
1760 if (IS_ERR(dp_sub->aud.base))
1761 return PTR_ERR(dp_sub->aud.base);
1762
1763 dp_sub->layers[0].id = XILINX_DRM_DP_SUB_LAYER_VID;
1764 dp_sub->layers[0].offset = 0;
1765 dp_sub->layers[0].avail = true;
1766 dp_sub->layers[0].other = &dp_sub->layers[1];
1767
1768 dp_sub->layers[1].id = XILINX_DRM_DP_SUB_LAYER_GFX;
1769 dp_sub->layers[1].offset = 4;
1770 dp_sub->layers[1].avail = true;
1771 dp_sub->layers[1].other = &dp_sub->layers[0];
1772
1773 ret = xilinx_drm_dp_sub_parse_of(dp_sub);
1774 if (ret)
1775 return ret;
1776
1777 platform_set_drvdata(pdev, dp_sub);
1778
1779 xilinx_drm_dp_sub_register_device(dp_sub);
1780
1781 dev_info(dp_sub->dev, "Xilinx DisplayPort Subsystem is probed\n");
1782
1783 return 0;
1784}
1785
1786static int xilinx_drm_dp_sub_remove(struct platform_device *pdev)
1787{
1788 struct xilinx_drm_dp_sub *dp_sub = platform_get_drvdata(pdev);
1789
1790 xilinx_drm_dp_sub_unregister_device(dp_sub);
1791
1792 return 0;
1793}
1794
1795static const struct of_device_id xilinx_drm_dp_sub_of_id_table[] = {
1796 { .compatible = "xlnx,dp-sub" },
1797 { }
1798};
1799MODULE_DEVICE_TABLE(of, xilinx_drm_dp_sub_of_id_table);
1800
1801static struct platform_driver xilinx_drm_dp_sub_driver = {
1802 .driver = {
1803 .name = "xilinx-drm-dp-sub",
1804 .of_match_table = xilinx_drm_dp_sub_of_id_table,
1805 },
1806 .probe = xilinx_drm_dp_sub_probe,
1807 .remove = xilinx_drm_dp_sub_remove,
1808};
1809
1810module_platform_driver(xilinx_drm_dp_sub_driver);
1811
1812MODULE_DESCRIPTION("Xilinx DisplayPort Subsystem Driver");
1813MODULE_LICENSE("GPL v2");
1814