1/*
2 * Copyright 2012-16 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25#include "dm_services.h"
26
27#include "dce/dce_11_0_d.h"
28#include "dce/dce_11_0_sh_mask.h"
29/* TODO: this needs to be looked at, used by Stella's workaround*/
30#include "gmc/gmc_8_2_d.h"
31#include "gmc/gmc_8_2_sh_mask.h"
32
33#include "include/logger_interface.h"
34#include "inc/dce_calcs.h"
35
36#include "dce/dce_mem_input.h"
37#include "dce110_mem_input_v.h"
38
39static void set_flip_control(
40	struct dce_mem_input *mem_input110,
41	bool immediate)
42{
43	uint32_t value = 0;
44
45	value = dm_read_reg(
46			mem_input110->base.ctx,
47			mmUNP_FLIP_CONTROL);
48
49	set_reg_field_value(value, 1,
50			UNP_FLIP_CONTROL,
51			GRPH_SURFACE_UPDATE_PENDING_MODE);
52
53	dm_write_reg(
54			mem_input110->base.ctx,
55			mmUNP_FLIP_CONTROL,
56			value);
57}
58
59/* chroma part */
60static void program_pri_addr_c(
61	struct dce_mem_input *mem_input110,
62	PHYSICAL_ADDRESS_LOC address)
63{
64	uint32_t value = 0;
65	uint32_t temp = 0;
66	/*high register MUST be programmed first*/
67	temp = address.high_part &
68UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MASK;
69
70	set_reg_field_value(value, temp,
71		UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C,
72		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C);
73
74	dm_write_reg(
75		mem_input110->base.ctx,
76		mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C,
77		value);
78
79	temp = 0;
80	value = 0;
81	temp = address.low_part >>
82	UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C__SHIFT;
83
84	set_reg_field_value(value, temp,
85		UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C,
86		GRPH_PRIMARY_SURFACE_ADDRESS_C);
87
88	dm_write_reg(
89		mem_input110->base.ctx,
90		mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C,
91		value);
92}
93
94/* luma part */
95static void program_pri_addr_l(
96	struct dce_mem_input *mem_input110,
97	PHYSICAL_ADDRESS_LOC address)
98{
99	uint32_t value = 0;
100	uint32_t temp = 0;
101
102	/*high register MUST be programmed first*/
103	temp = address.high_part &
104UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK;
105
106	set_reg_field_value(value, temp,
107		UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L,
108		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L);
109
110	dm_write_reg(
111		mem_input110->base.ctx,
112		mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L,
113		value);
114
115	temp = 0;
116	value = 0;
117	temp = address.low_part >>
118	UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT;
119
120	set_reg_field_value(value, temp,
121		UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L,
122		GRPH_PRIMARY_SURFACE_ADDRESS_L);
123
124	dm_write_reg(
125		mem_input110->base.ctx,
126		mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L,
127		value);
128}
129
130static void program_addr(
131	struct dce_mem_input *mem_input110,
132	const struct dc_plane_address *addr)
133{
134	switch (addr->type) {
135	case PLN_ADDR_TYPE_GRAPHICS:
136		program_pri_addr_l(
137			mem_input110,
138			addr->grph.addr);
139		break;
140	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
141		program_pri_addr_c(
142			mem_input110,
143			addr->video_progressive.chroma_addr);
144		program_pri_addr_l(
145			mem_input110,
146			addr->video_progressive.luma_addr);
147		break;
148	default:
149		/* not supported */
150		BREAK_TO_DEBUGGER();
151	}
152}
153
154static void enable(struct dce_mem_input *mem_input110)
155{
156	uint32_t value = 0;
157
158	value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_ENABLE);
159	set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE);
160	dm_write_reg(mem_input110->base.ctx,
161		mmUNP_GRPH_ENABLE,
162		value);
163}
164
165static void program_tiling(
166	struct dce_mem_input *mem_input110,
167	const union dc_tiling_info *info,
168	const enum surface_pixel_format pixel_format)
169{
170	uint32_t value = 0;
171
172	set_reg_field_value(value, info->gfx8.num_banks,
173		UNP_GRPH_CONTROL, GRPH_NUM_BANKS);
174
175	set_reg_field_value(value, info->gfx8.bank_width,
176		UNP_GRPH_CONTROL, GRPH_BANK_WIDTH_L);
177
178	set_reg_field_value(value, info->gfx8.bank_height,
179		UNP_GRPH_CONTROL, GRPH_BANK_HEIGHT_L);
180
181	set_reg_field_value(value, info->gfx8.tile_aspect,
182		UNP_GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT_L);
183
184	set_reg_field_value(value, info->gfx8.tile_split,
185		UNP_GRPH_CONTROL, GRPH_TILE_SPLIT_L);
186
187	set_reg_field_value(value, info->gfx8.tile_mode,
188		UNP_GRPH_CONTROL, GRPH_MICRO_TILE_MODE_L);
189
190	set_reg_field_value(value, info->gfx8.pipe_config,
191		UNP_GRPH_CONTROL, GRPH_PIPE_CONFIG);
192
193	set_reg_field_value(value, info->gfx8.array_mode,
194		UNP_GRPH_CONTROL, GRPH_ARRAY_MODE);
195
196	set_reg_field_value(value, 1,
197		UNP_GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE);
198
199	set_reg_field_value(value, 0,
200		UNP_GRPH_CONTROL, GRPH_Z);
201
202	dm_write_reg(
203		mem_input110->base.ctx,
204		mmUNP_GRPH_CONTROL,
205		value);
206
207	value = 0;
208
209	set_reg_field_value(value, info->gfx8.bank_width_c,
210		UNP_GRPH_CONTROL_C, GRPH_BANK_WIDTH_C);
211
212	set_reg_field_value(value, info->gfx8.bank_height_c,
213		UNP_GRPH_CONTROL_C, GRPH_BANK_HEIGHT_C);
214
215	set_reg_field_value(value, info->gfx8.tile_aspect_c,
216		UNP_GRPH_CONTROL_C, GRPH_MACRO_TILE_ASPECT_C);
217
218	set_reg_field_value(value, info->gfx8.tile_split_c,
219		UNP_GRPH_CONTROL_C, GRPH_TILE_SPLIT_C);
220
221	set_reg_field_value(value, info->gfx8.tile_mode_c,
222		UNP_GRPH_CONTROL_C, GRPH_MICRO_TILE_MODE_C);
223
224	dm_write_reg(
225		mem_input110->base.ctx,
226		mmUNP_GRPH_CONTROL_C,
227		value);
228}
229
230static void program_size_and_rotation(
231	struct dce_mem_input *mem_input110,
232	enum dc_rotation_angle rotation,
233	const struct plane_size *plane_size)
234{
235	uint32_t value = 0;
236	struct plane_size local_size = *plane_size;
237
238	if (rotation == ROTATION_ANGLE_90 ||
239		rotation == ROTATION_ANGLE_270) {
240
241		swap(local_size.surface_size.x,
242		     local_size.surface_size.y);
243		swap(local_size.surface_size.width,
244		     local_size.surface_size.height);
245		swap(local_size.chroma_size.x,
246		     local_size.chroma_size.y);
247		swap(local_size.chroma_size.width,
248		     local_size.chroma_size.height);
249	}
250
251	value = 0;
252	set_reg_field_value(value, local_size.surface_pitch,
253			UNP_GRPH_PITCH_L, GRPH_PITCH_L);
254
255	dm_write_reg(
256		mem_input110->base.ctx,
257		mmUNP_GRPH_PITCH_L,
258		value);
259
260	value = 0;
261	set_reg_field_value(value, local_size.chroma_pitch,
262			UNP_GRPH_PITCH_C, GRPH_PITCH_C);
263	dm_write_reg(
264		mem_input110->base.ctx,
265		mmUNP_GRPH_PITCH_C,
266		value);
267
268	value = 0;
269	set_reg_field_value(value, 0,
270			UNP_GRPH_X_START_L, GRPH_X_START_L);
271	dm_write_reg(
272		mem_input110->base.ctx,
273		mmUNP_GRPH_X_START_L,
274		value);
275
276	value = 0;
277	set_reg_field_value(value, 0,
278			UNP_GRPH_X_START_C, GRPH_X_START_C);
279	dm_write_reg(
280		mem_input110->base.ctx,
281		mmUNP_GRPH_X_START_C,
282		value);
283
284	value = 0;
285	set_reg_field_value(value, 0,
286			UNP_GRPH_Y_START_L, GRPH_Y_START_L);
287	dm_write_reg(
288		mem_input110->base.ctx,
289		mmUNP_GRPH_Y_START_L,
290		value);
291
292	value = 0;
293	set_reg_field_value(value, 0,
294			UNP_GRPH_Y_START_C, GRPH_Y_START_C);
295	dm_write_reg(
296		mem_input110->base.ctx,
297		mmUNP_GRPH_Y_START_C,
298		value);
299
300	value = 0;
301	set_reg_field_value(value, local_size.surface_size.x +
302			local_size.surface_size.width,
303			UNP_GRPH_X_END_L, GRPH_X_END_L);
304	dm_write_reg(
305		mem_input110->base.ctx,
306		mmUNP_GRPH_X_END_L,
307		value);
308
309	value = 0;
310	set_reg_field_value(value, local_size.chroma_size.x +
311			local_size.chroma_size.width,
312			UNP_GRPH_X_END_C, GRPH_X_END_C);
313	dm_write_reg(
314		mem_input110->base.ctx,
315		mmUNP_GRPH_X_END_C,
316		value);
317
318	value = 0;
319	set_reg_field_value(value, local_size.surface_size.y +
320			local_size.surface_size.height,
321			UNP_GRPH_Y_END_L, GRPH_Y_END_L);
322	dm_write_reg(
323		mem_input110->base.ctx,
324		mmUNP_GRPH_Y_END_L,
325		value);
326
327	value = 0;
328	set_reg_field_value(value, local_size.chroma_size.y +
329			local_size.chroma_size.height,
330			UNP_GRPH_Y_END_C, GRPH_Y_END_C);
331	dm_write_reg(
332		mem_input110->base.ctx,
333		mmUNP_GRPH_Y_END_C,
334		value);
335
336	value = 0;
337	switch (rotation) {
338	case ROTATION_ANGLE_90:
339		set_reg_field_value(value, 3,
340			UNP_HW_ROTATION, ROTATION_ANGLE);
341		break;
342	case ROTATION_ANGLE_180:
343		set_reg_field_value(value, 2,
344			UNP_HW_ROTATION, ROTATION_ANGLE);
345		break;
346	case ROTATION_ANGLE_270:
347		set_reg_field_value(value, 1,
348			UNP_HW_ROTATION, ROTATION_ANGLE);
349		break;
350	default:
351		set_reg_field_value(value, 0,
352			UNP_HW_ROTATION, ROTATION_ANGLE);
353		break;
354	}
355
356	dm_write_reg(
357		mem_input110->base.ctx,
358		mmUNP_HW_ROTATION,
359		value);
360}
361
362static void program_pixel_format(
363	struct dce_mem_input *mem_input110,
364	enum surface_pixel_format format)
365{
366	if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
367		uint32_t value;
368		uint8_t grph_depth;
369		uint8_t grph_format;
370
371		value =	dm_read_reg(
372				mem_input110->base.ctx,
373				mmUNP_GRPH_CONTROL);
374
375		switch (format) {
376		case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
377			grph_depth = 0;
378			grph_format = 0;
379			break;
380		case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
381			grph_depth = 1;
382			grph_format = 1;
383			break;
384		case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
385		case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
386			grph_depth = 2;
387			grph_format = 0;
388			break;
389		case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
390		case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
391		case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
392			grph_depth = 2;
393			grph_format = 1;
394			break;
395		case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
396		case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
397		case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
398		case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
399			grph_depth = 3;
400			grph_format = 0;
401			break;
402		default:
403			grph_depth = 2;
404			grph_format = 0;
405			break;
406		}
407
408		set_reg_field_value(
409				value,
410				grph_depth,
411				UNP_GRPH_CONTROL,
412				GRPH_DEPTH);
413		set_reg_field_value(
414				value,
415				grph_format,
416				UNP_GRPH_CONTROL,
417				GRPH_FORMAT);
418
419		dm_write_reg(
420				mem_input110->base.ctx,
421				mmUNP_GRPH_CONTROL,
422				value);
423
424		value =	dm_read_reg(
425				mem_input110->base.ctx,
426				mmUNP_GRPH_CONTROL_EXP);
427
428		/* VIDEO FORMAT 0 */
429		set_reg_field_value(
430				value,
431				0,
432				UNP_GRPH_CONTROL_EXP,
433				VIDEO_FORMAT);
434		dm_write_reg(
435				mem_input110->base.ctx,
436				mmUNP_GRPH_CONTROL_EXP,
437				value);
438
439	} else {
440		/* Video 422 and 420 needs UNP_GRPH_CONTROL_EXP programmed */
441		uint32_t value;
442		uint8_t video_format;
443
444		value =	dm_read_reg(
445				mem_input110->base.ctx,
446				mmUNP_GRPH_CONTROL_EXP);
447
448		switch (format) {
449		case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
450			video_format = 2;
451			break;
452		case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
453			video_format = 3;
454			break;
455		default:
456			video_format = 0;
457			break;
458		}
459
460		set_reg_field_value(
461			value,
462			video_format,
463			UNP_GRPH_CONTROL_EXP,
464			VIDEO_FORMAT);
465
466		dm_write_reg(
467			mem_input110->base.ctx,
468			mmUNP_GRPH_CONTROL_EXP,
469			value);
470	}
471}
472
473static bool dce_mem_input_v_is_surface_pending(struct mem_input *mem_input)
474{
475	struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input);
476	uint32_t value;
477
478	value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_UPDATE);
479
480	if (get_reg_field_value(value, UNP_GRPH_UPDATE,
481			GRPH_SURFACE_UPDATE_PENDING))
482		return true;
483
484	mem_input->current_address = mem_input->request_address;
485	return false;
486}
487
488static bool dce_mem_input_v_program_surface_flip_and_addr(
489	struct mem_input *mem_input,
490	const struct dc_plane_address *address,
491	bool flip_immediate)
492{
493	struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input);
494
495	set_flip_control(mem_input110, flip_immediate);
496	program_addr(mem_input110,
497		address);
498
499	mem_input->request_address = *address;
500
501	return true;
502}
503
504/* Scatter Gather param tables */
505static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = {
506		{  8, 64, 64,  8,  8, 1, 4, 0, 0},
507		{ 16, 64, 32,  8, 16, 1, 8, 0, 0},
508		{ 32, 32, 32, 16, 16, 1, 8, 0, 0},
509		{ 64,  8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
510};
511
512static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = {
513		{  8, 512, 8, 1, 0, 1, 0, 0, 0},  /* 0 for invalid */
514		{ 16, 256, 8, 2, 0, 1, 0, 0, 0},
515		{ 32, 128, 8, 4, 0, 1, 0, 0, 0},
516		{ 64,  64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
517};
518
519static const unsigned int dvmm_Hw_Setting_Linear[4][9] = {
520		{  8, 4096, 1, 8, 0, 1, 0, 0, 0},
521		{ 16, 2048, 1, 8, 0, 1, 0, 0, 0},
522		{ 32, 1024, 1, 8, 0, 1, 0, 0, 0},
523		{ 64,  512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
524};
525
526/* Helper to get table entry from surface info */
527static const unsigned int *get_dvmm_hw_setting(
528		union dc_tiling_info *tiling_info,
529		enum surface_pixel_format format,
530		bool chroma)
531{
532	enum bits_per_pixel {
533		bpp_8 = 0,
534		bpp_16,
535		bpp_32,
536		bpp_64
537	} bpp;
538
539	if (format >= SURFACE_PIXEL_FORMAT_INVALID)
540		bpp = bpp_32;
541	else if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
542		bpp = chroma ? bpp_16 : bpp_8;
543	else
544		bpp = bpp_8;
545
546	switch (tiling_info->gfx8.array_mode) {
547	case DC_ARRAY_1D_TILED_THIN1:
548	case DC_ARRAY_1D_TILED_THICK:
549	case DC_ARRAY_PRT_TILED_THIN1:
550		return dvmm_Hw_Setting_1DTiling[bpp];
551	case DC_ARRAY_2D_TILED_THIN1:
552	case DC_ARRAY_2D_TILED_THICK:
553	case DC_ARRAY_2D_TILED_X_THICK:
554	case DC_ARRAY_PRT_2D_TILED_THIN1:
555	case DC_ARRAY_PRT_2D_TILED_THICK:
556		return dvmm_Hw_Setting_2DTiling[bpp];
557	case DC_ARRAY_LINEAR_GENERAL:
558	case DC_ARRAY_LINEAR_ALLIGNED:
559		return dvmm_Hw_Setting_Linear[bpp];
560	default:
561		return dvmm_Hw_Setting_2DTiling[bpp];
562	}
563}
564
565static void dce_mem_input_v_program_pte_vm(
566		struct mem_input *mem_input,
567		enum surface_pixel_format format,
568		union dc_tiling_info *tiling_info,
569		enum dc_rotation_angle rotation)
570{
571	struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input);
572	const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format, false);
573	const unsigned int *pte_chroma = get_dvmm_hw_setting(tiling_info, format, true);
574
575	unsigned int page_width = 0;
576	unsigned int page_height = 0;
577	unsigned int page_width_chroma = 0;
578	unsigned int page_height_chroma = 0;
579	unsigned int temp_page_width = pte[1];
580	unsigned int temp_page_height = pte[2];
581	unsigned int min_pte_before_flip = 0;
582	unsigned int min_pte_before_flip_chroma = 0;
583	uint32_t value = 0;
584
585	while ((temp_page_width >>= 1) != 0)
586		page_width++;
587	while ((temp_page_height >>= 1) != 0)
588		page_height++;
589
590	temp_page_width = pte_chroma[1];
591	temp_page_height = pte_chroma[2];
592	while ((temp_page_width >>= 1) != 0)
593		page_width_chroma++;
594	while ((temp_page_height >>= 1) != 0)
595		page_height_chroma++;
596
597	switch (rotation) {
598	case ROTATION_ANGLE_90:
599	case ROTATION_ANGLE_270:
600		min_pte_before_flip = pte[4];
601		min_pte_before_flip_chroma = pte_chroma[4];
602		break;
603	default:
604		min_pte_before_flip = pte[3];
605		min_pte_before_flip_chroma = pte_chroma[3];
606		break;
607	}
608
609	value = dm_read_reg(mem_input110->base.ctx, mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT);
610	/* TODO: un-hardcode requestlimit */
611	set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L);
612	set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C);
613	dm_write_reg(mem_input110->base.ctx, mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT, value);
614
615	value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL);
616	set_reg_field_value(value, page_width, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH);
617	set_reg_field_value(value, page_height, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT);
618	set_reg_field_value(value, min_pte_before_flip, UNP_DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP);
619	dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL, value);
620
621	value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL);
622	set_reg_field_value(value, pte[5], UNP_DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK);
623	set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING);
624	dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL, value);
625
626	value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL_C);
627	set_reg_field_value(value, page_width_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_WIDTH_C);
628	set_reg_field_value(value, page_height_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_HEIGHT_C);
629	set_reg_field_value(value, min_pte_before_flip_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_MIN_PTE_BEFORE_FLIP_C);
630	dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL_C, value);
631
632	value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL_C);
633	set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C);
634	set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C);
635	dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL_C, value);
636}
637
638static void dce_mem_input_v_program_surface_config(
639	struct mem_input *mem_input,
640	enum surface_pixel_format format,
641	union dc_tiling_info *tiling_info,
642	struct plane_size *plane_size,
643	enum dc_rotation_angle rotation,
644	struct dc_plane_dcc_param *dcc,
645	bool horizotal_mirror)
646{
647	struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input);
648
649	enable(mem_input110);
650	program_tiling(mem_input110, tiling_info, format);
651	program_size_and_rotation(mem_input110, rotation, plane_size);
652	program_pixel_format(mem_input110, format);
653}
654
655static void program_urgency_watermark(
656	const struct dc_context *ctx,
657	const uint32_t urgency_addr,
658	const uint32_t wm_addr,
659	struct dce_watermarks marks_low,
660	uint32_t total_dest_line_time_ns)
661{
662	/* register value */
663	uint32_t urgency_cntl = 0;
664	uint32_t wm_mask_cntl = 0;
665
666	/*Write mask to enable reading/writing of watermark set A*/
667	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
668	set_reg_field_value(wm_mask_cntl,
669			1,
670			DPGV0_WATERMARK_MASK_CONTROL,
671			URGENCY_WATERMARK_MASK);
672	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
673
674	urgency_cntl = dm_read_reg(ctx, urgency_addr);
675
676	set_reg_field_value(
677		urgency_cntl,
678		marks_low.a_mark,
679		DPGV0_PIPE_URGENCY_CONTROL,
680		URGENCY_LOW_WATERMARK);
681
682	set_reg_field_value(
683		urgency_cntl,
684		total_dest_line_time_ns,
685		DPGV0_PIPE_URGENCY_CONTROL,
686		URGENCY_HIGH_WATERMARK);
687	dm_write_reg(ctx, urgency_addr, urgency_cntl);
688
689	/*Write mask to enable reading/writing of watermark set B*/
690	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
691	set_reg_field_value(wm_mask_cntl,
692			2,
693			DPGV0_WATERMARK_MASK_CONTROL,
694			URGENCY_WATERMARK_MASK);
695	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
696
697	urgency_cntl = dm_read_reg(ctx, urgency_addr);
698
699	set_reg_field_value(urgency_cntl,
700		marks_low.b_mark,
701		DPGV0_PIPE_URGENCY_CONTROL,
702		URGENCY_LOW_WATERMARK);
703
704	set_reg_field_value(urgency_cntl,
705		total_dest_line_time_ns,
706		DPGV0_PIPE_URGENCY_CONTROL,
707		URGENCY_HIGH_WATERMARK);
708
709	dm_write_reg(ctx, urgency_addr, urgency_cntl);
710}
711
712static void program_urgency_watermark_l(
713	const struct dc_context *ctx,
714	struct dce_watermarks marks_low,
715	uint32_t total_dest_line_time_ns)
716{
717	program_urgency_watermark(
718		ctx,
719		mmDPGV0_PIPE_URGENCY_CONTROL,
720		mmDPGV0_WATERMARK_MASK_CONTROL,
721		marks_low,
722		total_dest_line_time_ns);
723}
724
725static void program_urgency_watermark_c(
726	const struct dc_context *ctx,
727	struct dce_watermarks marks_low,
728	uint32_t total_dest_line_time_ns)
729{
730	program_urgency_watermark(
731		ctx,
732		mmDPGV1_PIPE_URGENCY_CONTROL,
733		mmDPGV1_WATERMARK_MASK_CONTROL,
734		marks_low,
735		total_dest_line_time_ns);
736}
737
738static void program_stutter_watermark(
739	const struct dc_context *ctx,
740	const uint32_t stutter_addr,
741	const uint32_t wm_addr,
742	struct dce_watermarks marks)
743{
744	/* register value */
745	uint32_t stutter_cntl = 0;
746	uint32_t wm_mask_cntl = 0;
747
748	/*Write mask to enable reading/writing of watermark set A*/
749
750	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
751	set_reg_field_value(wm_mask_cntl,
752		1,
753		DPGV0_WATERMARK_MASK_CONTROL,
754		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK);
755	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
756
757	stutter_cntl = dm_read_reg(ctx, stutter_addr);
758
759	if (ctx->dc->debug.disable_stutter) {
760		set_reg_field_value(stutter_cntl,
761			0,
762			DPGV0_PIPE_STUTTER_CONTROL,
763			STUTTER_ENABLE);
764	} else {
765		set_reg_field_value(stutter_cntl,
766			1,
767			DPGV0_PIPE_STUTTER_CONTROL,
768			STUTTER_ENABLE);
769	}
770
771	set_reg_field_value(stutter_cntl,
772		1,
773		DPGV0_PIPE_STUTTER_CONTROL,
774		STUTTER_IGNORE_FBC);
775
776	/*Write watermark set A*/
777	set_reg_field_value(stutter_cntl,
778		marks.a_mark,
779		DPGV0_PIPE_STUTTER_CONTROL,
780		STUTTER_EXIT_SELF_REFRESH_WATERMARK);
781	dm_write_reg(ctx, stutter_addr, stutter_cntl);
782
783	/*Write mask to enable reading/writing of watermark set B*/
784	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
785	set_reg_field_value(wm_mask_cntl,
786		2,
787		DPGV0_WATERMARK_MASK_CONTROL,
788		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK);
789	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
790
791	stutter_cntl = dm_read_reg(ctx, stutter_addr);
792	/*Write watermark set B*/
793	set_reg_field_value(stutter_cntl,
794		marks.b_mark,
795		DPGV0_PIPE_STUTTER_CONTROL,
796		STUTTER_EXIT_SELF_REFRESH_WATERMARK);
797	dm_write_reg(ctx, stutter_addr, stutter_cntl);
798}
799
800static void program_stutter_watermark_l(
801	const struct dc_context *ctx,
802	struct dce_watermarks marks)
803{
804	program_stutter_watermark(ctx,
805			mmDPGV0_PIPE_STUTTER_CONTROL,
806			mmDPGV0_WATERMARK_MASK_CONTROL,
807			marks);
808}
809
810static void program_stutter_watermark_c(
811	const struct dc_context *ctx,
812	struct dce_watermarks marks)
813{
814	program_stutter_watermark(ctx,
815			mmDPGV1_PIPE_STUTTER_CONTROL,
816			mmDPGV1_WATERMARK_MASK_CONTROL,
817			marks);
818}
819
820static void program_nbp_watermark(
821	const struct dc_context *ctx,
822	const uint32_t wm_mask_ctrl_addr,
823	const uint32_t nbp_pstate_ctrl_addr,
824	struct dce_watermarks marks)
825{
826	uint32_t value;
827
828	/* Write mask to enable reading/writing of watermark set A */
829
830	value = dm_read_reg(ctx, wm_mask_ctrl_addr);
831
832	set_reg_field_value(
833		value,
834		1,
835		DPGV0_WATERMARK_MASK_CONTROL,
836		NB_PSTATE_CHANGE_WATERMARK_MASK);
837	dm_write_reg(ctx, wm_mask_ctrl_addr, value);
838
839	value = dm_read_reg(ctx, nbp_pstate_ctrl_addr);
840
841	set_reg_field_value(
842		value,
843		1,
844		DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
845		NB_PSTATE_CHANGE_ENABLE);
846	set_reg_field_value(
847		value,
848		1,
849		DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
850		NB_PSTATE_CHANGE_URGENT_DURING_REQUEST);
851	set_reg_field_value(
852		value,
853		1,
854		DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
855		NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST);
856	dm_write_reg(ctx, nbp_pstate_ctrl_addr, value);
857
858	/* Write watermark set A */
859	value = dm_read_reg(ctx, nbp_pstate_ctrl_addr);
860	set_reg_field_value(
861		value,
862		marks.a_mark,
863		DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
864		NB_PSTATE_CHANGE_WATERMARK);
865	dm_write_reg(ctx, nbp_pstate_ctrl_addr, value);
866
867	/* Write mask to enable reading/writing of watermark set B */
868	value = dm_read_reg(ctx, wm_mask_ctrl_addr);
869	set_reg_field_value(
870		value,
871		2,
872		DPGV0_WATERMARK_MASK_CONTROL,
873		NB_PSTATE_CHANGE_WATERMARK_MASK);
874	dm_write_reg(ctx, wm_mask_ctrl_addr, value);
875
876	value = dm_read_reg(ctx, nbp_pstate_ctrl_addr);
877	set_reg_field_value(
878		value,
879		1,
880		DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
881		NB_PSTATE_CHANGE_ENABLE);
882	set_reg_field_value(
883		value,
884		1,
885		DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
886		NB_PSTATE_CHANGE_URGENT_DURING_REQUEST);
887	set_reg_field_value(
888		value,
889		1,
890		DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
891		NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST);
892	dm_write_reg(ctx, nbp_pstate_ctrl_addr, value);
893
894	/* Write watermark set B */
895	value = dm_read_reg(ctx, nbp_pstate_ctrl_addr);
896	set_reg_field_value(
897		value,
898		marks.b_mark,
899		DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
900		NB_PSTATE_CHANGE_WATERMARK);
901	dm_write_reg(ctx, nbp_pstate_ctrl_addr, value);
902}
903
904static void program_nbp_watermark_l(
905	const struct dc_context *ctx,
906	struct dce_watermarks marks)
907{
908	program_nbp_watermark(ctx,
909			mmDPGV0_WATERMARK_MASK_CONTROL,
910			mmDPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL,
911			marks);
912}
913
914static void program_nbp_watermark_c(
915	const struct dc_context *ctx,
916	struct dce_watermarks marks)
917{
918	program_nbp_watermark(ctx,
919			mmDPGV1_WATERMARK_MASK_CONTROL,
920			mmDPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL,
921			marks);
922}
923
924static void dce_mem_input_v_program_display_marks(
925	struct mem_input *mem_input,
926	struct dce_watermarks nbp,
927	struct dce_watermarks stutter,
928	struct dce_watermarks stutter_enter,
929	struct dce_watermarks urgent,
930	uint32_t total_dest_line_time_ns)
931{
932	program_urgency_watermark_l(
933		mem_input->ctx,
934		urgent,
935		total_dest_line_time_ns);
936
937	program_nbp_watermark_l(
938		mem_input->ctx,
939		nbp);
940
941	program_stutter_watermark_l(
942		mem_input->ctx,
943		stutter);
944
945}
946
947static void dce_mem_input_program_chroma_display_marks(
948	struct mem_input *mem_input,
949	struct dce_watermarks nbp,
950	struct dce_watermarks stutter,
951	struct dce_watermarks urgent,
952	uint32_t total_dest_line_time_ns)
953{
954	program_urgency_watermark_c(
955		mem_input->ctx,
956		urgent,
957		total_dest_line_time_ns);
958
959	program_nbp_watermark_c(
960		mem_input->ctx,
961		nbp);
962
963	program_stutter_watermark_c(
964		mem_input->ctx,
965		stutter);
966}
967
968static void dce110_allocate_mem_input_v(
969	struct mem_input *mi,
970	uint32_t h_total,/* for current stream */
971	uint32_t v_total,/* for current stream */
972	uint32_t pix_clk_khz,/* for current stream */
973	uint32_t total_stream_num)
974{
975	uint32_t addr;
976	uint32_t value;
977	uint32_t pix_dur;
978	if (pix_clk_khz != 0) {
979		addr = mmDPGV0_PIPE_ARBITRATION_CONTROL1;
980		value = dm_read_reg(mi->ctx, addr);
981		pix_dur = 1000000000ULL / pix_clk_khz;
982		set_reg_field_value(
983			value,
984			pix_dur,
985			DPGV0_PIPE_ARBITRATION_CONTROL1,
986			PIXEL_DURATION);
987		dm_write_reg(mi->ctx, addr, value);
988
989		addr = mmDPGV1_PIPE_ARBITRATION_CONTROL1;
990		value = dm_read_reg(mi->ctx, addr);
991		pix_dur = 1000000000ULL / pix_clk_khz;
992		set_reg_field_value(
993			value,
994			pix_dur,
995			DPGV1_PIPE_ARBITRATION_CONTROL1,
996			PIXEL_DURATION);
997		dm_write_reg(mi->ctx, addr, value);
998
999		addr = mmDPGV0_PIPE_ARBITRATION_CONTROL2;
1000		value = 0x4000800;
1001		dm_write_reg(mi->ctx, addr, value);
1002
1003		addr = mmDPGV1_PIPE_ARBITRATION_CONTROL2;
1004		value = 0x4000800;
1005		dm_write_reg(mi->ctx, addr, value);
1006	}
1007
1008}
1009
1010static void dce110_free_mem_input_v(
1011	struct mem_input *mi,
1012	uint32_t total_stream_num)
1013{
1014}
1015
1016static const struct mem_input_funcs dce110_mem_input_v_funcs = {
1017	.mem_input_program_display_marks =
1018			dce_mem_input_v_program_display_marks,
1019	.mem_input_program_chroma_display_marks =
1020			dce_mem_input_program_chroma_display_marks,
1021	.allocate_mem_input = dce110_allocate_mem_input_v,
1022	.free_mem_input = dce110_free_mem_input_v,
1023	.mem_input_program_surface_flip_and_addr =
1024			dce_mem_input_v_program_surface_flip_and_addr,
1025	.mem_input_program_pte_vm =
1026			dce_mem_input_v_program_pte_vm,
1027	.mem_input_program_surface_config =
1028			dce_mem_input_v_program_surface_config,
1029	.mem_input_is_flip_pending =
1030			dce_mem_input_v_is_surface_pending
1031};
1032/*****************************************/
1033/* Constructor, Destructor               */
1034/*****************************************/
1035
1036void dce110_mem_input_v_construct(
1037	struct dce_mem_input *dce_mi,
1038	struct dc_context *ctx)
1039{
1040	dce_mi->base.funcs = &dce110_mem_input_v_funcs;
1041	dce_mi->base.ctx = ctx;
1042}
1043
1044