aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/0443-drm-amd-display-Implement-input-gamma-LUT.patch
blob: 53cc7a1f6f0e94bf37a813f055fba6a20ceb88c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
From b8ab2b526e89e29e9ffb15ee043c29138c1ab0d2 Mon Sep 17 00:00:00 2001
From: "Leo (Sunpeng) Li" <sunpeng.li@amd.com>
Date: Tue, 16 May 2017 16:07:30 -0400
Subject: [PATCH 0443/4131] drm/amd/display: Implement input gamma LUT

1. Implemented dcn10_ipp_program_input_lut(), following the existing
   interface.
2. Added missing registers as needed
3. Change to REG_GET for *ram_select() funcs.
4. Removed gamma table init from DiagsDM::make_surface() for resolving
   CRC errors. Reason: Legacy LUT will be deprecated soon for Raven in
   favor of degamma/regamma.

Signed-off-by: Leo (Sunpeng) Li <sunpeng.li@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c  |  6 +-
 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c   | 82 +++++++++++++++++++++-
 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h   | 22 ++++++
 3 files changed, 108 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 28b47be..62a77f4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -29,9 +29,9 @@
 #include "core_types.h"
 #include "core_status.h"
 #include "resource.h"
-#include "hw_sequencer.h"
 #include "dcn10_hw_sequencer.h"
 #include "dce110/dce110_hw_sequencer.h"
+#include "dce/dce_hwseq.h"
 #include "abm.h"
 
 #include "dcn10/dcn10_transform.h"
@@ -952,6 +952,10 @@ static bool dcn10_set_input_transfer_func(
 	if (surface->public.in_transfer_func)
 		tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func);
 
+	if (surface->public.gamma_correction && dce_use_lut(surface))
+	    ipp->funcs->ipp_program_input_lut(ipp,
+			    surface->public.gamma_correction);
+
 	if (tf == NULL)
 		ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
 	else if (tf->public.type == TF_TYPE_PREDEFINED) {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c
index 082c98c..1e7a55d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c
@@ -814,7 +814,9 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp,
 	uint32_t status_reg = 0;
 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
 
-	status_reg = (REG_READ(CM_IGAM_LUT_RW_CONTROL) & 0x0F00) >>16;
+	REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
+			&status_reg);
+
 	if (status_reg == 9) {
 		*ram_a_inuse = true;
 		ret = true;
@@ -825,6 +827,28 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp,
 	return ret;
 }
 
+static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp,
+							bool *ram_a_inuse)
+{
+	bool in_use = false;
+	uint32_t status_reg = 0;
+	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
+
+	REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
+				&status_reg);
+
+	// 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB
+	if (status_reg == 1 || status_reg == 3 || status_reg == 4) {
+		*ram_a_inuse = true;
+		in_use = true;
+	// 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB
+	} else if (status_reg == 2 || status_reg == 5 || status_reg == 6) {
+		*ram_a_inuse = false;
+		in_use = true;
+	}
+	return in_use;
+}
+
 static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp,
 							bool use_ram_a)
 {
@@ -855,6 +879,61 @@ static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp,
 	dcn10_degamma_ram_select(ipp, !is_ram_a);
 }
 
+/*
+ * Input gamma LUT currently supports 256 values only. This means input color
+ * can have a maximum of 8 bits per channel (= 256 possible values) in order to
+ * have a one-to-one mapping with the LUT. Truncation will occur with color
+ * values greater than 8 bits.
+ *
+ * In the future, this function should support additional input gamma methods,
+ * such as piecewise linear mapping, and input gamma bypass.
+ */
+void dcn10_ipp_program_input_lut(
+		struct input_pixel_processor *ipp,
+		const struct dc_gamma *gamma)
+{
+	int i;
+	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
+	bool rama_occupied = false;
+	uint32_t ram_num;
+	// Power on LUT memory.
+	REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1);
+	dcn10_ipp_enable_cm_block(ipp);
+	// Determine whether to use RAM A or RAM B
+	dcn10_ingamma_ram_inuse(ipp, &rama_occupied);
+	if (!rama_occupied)
+		REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0);
+	else
+		REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1);
+	// RW mode is 256-entry LUT
+	REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0);
+	// IGAM Input format should be 8 bits per channel.
+	REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0);
+	// Do not mask any R,G,B values
+	REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7);
+	// LUT-256, unsigned, integer, new u0.12 format
+	REG_UPDATE_3(
+		CM_IGAM_CONTROL,
+		CM_IGAM_LUT_FORMAT_R, 3,
+		CM_IGAM_LUT_FORMAT_G, 3,
+		CM_IGAM_LUT_FORMAT_B, 3);
+	// Start at index 0 of IGAM LUT
+	REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0);
+	for (i = 0; i < INPUT_LUT_ENTRIES; i++) {
+		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
+					gamma->red[i]);
+		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
+					gamma->green[i]);
+		REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
+					gamma->blue[i]);
+	}
+	// Power off LUT memory
+	REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0);
+	// Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB
+	REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2);
+	REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num);
+}
+
 /*****************************************/
 /* Constructor, Destructor               */
 /*****************************************/
@@ -869,6 +948,7 @@ static const struct ipp_funcs dcn10_ipp_funcs = {
 	.ipp_cursor_set_attributes	= dcn10_cursor_set_attributes,
 	.ipp_cursor_set_position	= dcn10_cursor_set_position,
 	.ipp_set_degamma		= dcn10_ipp_set_degamma,
+	.ipp_program_input_lut 		= dcn10_ipp_program_input_lut,
 	.ipp_full_bypass		= dcn10_ipp_full_bypass,
 	.ipp_setup			= dcn10_ipp_cnv_setup,
 	.ipp_program_degamma_pwl	= dcn10_ipp_set_degamma_pwl,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h
index a4ea4e7..5119935 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h
@@ -87,6 +87,8 @@
 	SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \
 	SRI(CM_MEM_PWR_CTRL, CM, id), \
 	SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \
+	SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \
+	SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \
 	SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \
 	SRI(CM_DGAM_LUT_INDEX, CM, id), \
 	SRI(CM_DGAM_LUT_DATA, CM, id), \
@@ -238,7 +240,13 @@
 	IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \
 	IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \
 	IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \
 	IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \
 	IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \
 	IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \
 	IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \
@@ -251,6 +259,9 @@
 	IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \
 	IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \
 	IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \
+	IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \
 	IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \
 	IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \
 	IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \
@@ -404,7 +415,16 @@
 	type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \
 	type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \
 	type SHARED_MEM_PWR_DIS; \
+	type CM_IGAM_LUT_FORMAT_R; \
+	type CM_IGAM_LUT_FORMAT_G; \
+	type CM_IGAM_LUT_FORMAT_B; \
 	type CM_IGAM_LUT_HOST_EN; \
+	type CM_IGAM_LUT_RW_INDEX; \
+	type CM_IGAM_LUT_RW_MODE; \
+	type CM_IGAM_LUT_WRITE_EN_MASK; \
+	type CM_IGAM_LUT_SEL; \
+	type CM_IGAM_LUT_SEQ_COLOR; \
+	type CM_IGAM_DGAM_CONFIG_STATUS; \
 	type CM_DGAM_LUT_WRITE_EN_MASK; \
 	type CM_DGAM_LUT_WRITE_SEL; \
 	type CM_DGAM_LUT_INDEX; \
@@ -507,6 +527,8 @@ struct dcn10_ipp_registers {
 	uint32_t CM_DGAM_RAMA_REGION_14_15;
 	uint32_t CM_MEM_PWR_CTRL;
 	uint32_t CM_IGAM_LUT_RW_CONTROL;
+	uint32_t CM_IGAM_LUT_RW_INDEX;
+	uint32_t CM_IGAM_LUT_SEQ_COLOR;
 	uint32_t CM_DGAM_LUT_WRITE_EN_MASK;
 	uint32_t CM_DGAM_LUT_INDEX;
 	uint32_t CM_DGAM_LUT_DATA;
-- 
2.7.4