|
24 | 24 | #define DISP_GAMMA_SIZE 0x0030
|
25 | 25 | #define DISP_GAMMA_SIZE_HSIZE GENMASK(28, 16)
|
26 | 26 | #define DISP_GAMMA_SIZE_VSIZE GENMASK(12, 0)
|
| 27 | +#define DISP_GAMMA_BANK 0x0100 |
| 28 | +#define DISP_GAMMA_BANK_BANK GENMASK(1, 0) |
27 | 29 | #define DISP_GAMMA_LUT 0x0700
|
28 | 30 |
|
29 | 31 | #define DISP_GAMMA_LUT_10BIT_R GENMASK(29, 20)
|
|
33 | 35 | struct mtk_disp_gamma_data {
|
34 | 36 | bool has_dither;
|
35 | 37 | bool lut_diff;
|
| 38 | + u16 lut_bank_size; |
36 | 39 | u16 lut_size;
|
37 | 40 | };
|
38 | 41 |
|
@@ -75,40 +78,53 @@ void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
|
75 | 78 | unsigned int i;
|
76 | 79 | struct drm_color_lut *lut;
|
77 | 80 | void __iomem *lut_base;
|
78 |
| - u32 cfg_val, word; |
| 81 | + u32 cfg_val, lbank_val, word; |
| 82 | + int cur_bank, num_lut_banks; |
79 | 83 |
|
80 | 84 | /* If there's no gamma lut there's nothing to do here. */
|
81 | 85 | if (!state->gamma_lut)
|
82 | 86 | return;
|
83 | 87 |
|
| 88 | + num_lut_banks = gamma->data->lut_size / gamma->data->lut_bank_size; |
84 | 89 | lut_base = gamma->regs + DISP_GAMMA_LUT;
|
85 | 90 | lut = (struct drm_color_lut *)state->gamma_lut->data;
|
86 |
| - for (i = 0; i < gamma->data->lut_size; i++) { |
87 |
| - struct drm_color_lut diff, hwlut; |
88 |
| - |
89 |
| - hwlut.red = drm_color_lut_extract(lut[i].red, 10); |
90 |
| - hwlut.green = drm_color_lut_extract(lut[i].green, 10); |
91 |
| - hwlut.blue = drm_color_lut_extract(lut[i].blue, 10); |
92 |
| - |
93 |
| - if (!gamma->data->lut_diff || (i % 2 == 0)) { |
94 |
| - word = FIELD_PREP(DISP_GAMMA_LUT_10BIT_R, hwlut.red); |
95 |
| - word |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_G, hwlut.green); |
96 |
| - word |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_B, hwlut.blue); |
97 |
| - } else { |
98 |
| - diff.red = lut[i].red - lut[i - 1].red; |
99 |
| - diff.red = drm_color_lut_extract(diff.red, 10); |
100 |
| - |
101 |
| - diff.green = lut[i].green - lut[i - 1].green; |
102 |
| - diff.green = drm_color_lut_extract(diff.green, 10); |
103 |
| - |
104 |
| - diff.blue = lut[i].blue - lut[i - 1].blue; |
105 |
| - diff.blue = drm_color_lut_extract(diff.blue, 10); |
106 |
| - |
107 |
| - word = FIELD_PREP(DISP_GAMMA_LUT_10BIT_R, diff.red); |
108 |
| - word |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_G, diff.green); |
109 |
| - word |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_B, diff.blue); |
| 91 | + |
| 92 | + for (cur_bank = 0; cur_bank < num_lut_banks; cur_bank++) { |
| 93 | + |
| 94 | + /* Switch gamma bank and set data mode before writing LUT */ |
| 95 | + if (num_lut_banks > 1) { |
| 96 | + lbank_val = FIELD_PREP(DISP_GAMMA_BANK_BANK, cur_bank); |
| 97 | + writel(lbank_val, gamma->regs + DISP_GAMMA_BANK); |
| 98 | + } |
| 99 | + |
| 100 | + for (i = 0; i < gamma->data->lut_bank_size; i++) { |
| 101 | + int n = cur_bank * gamma->data->lut_bank_size + i; |
| 102 | + struct drm_color_lut diff, hwlut; |
| 103 | + |
| 104 | + hwlut.red = drm_color_lut_extract(lut[n].red, 10); |
| 105 | + hwlut.green = drm_color_lut_extract(lut[n].green, 10); |
| 106 | + hwlut.blue = drm_color_lut_extract(lut[n].blue, 10); |
| 107 | + |
| 108 | + if (!gamma->data->lut_diff || (i % 2 == 0)) { |
| 109 | + word = FIELD_PREP(DISP_GAMMA_LUT_10BIT_R, hwlut.red); |
| 110 | + word |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_G, hwlut.green); |
| 111 | + word |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_B, hwlut.blue); |
| 112 | + } else { |
| 113 | + diff.red = lut[n].red - lut[n - 1].red; |
| 114 | + diff.red = drm_color_lut_extract(diff.red, 10); |
| 115 | + |
| 116 | + diff.green = lut[n].green - lut[n - 1].green; |
| 117 | + diff.green = drm_color_lut_extract(diff.green, 10); |
| 118 | + |
| 119 | + diff.blue = lut[n].blue - lut[n - 1].blue; |
| 120 | + diff.blue = drm_color_lut_extract(diff.blue, 10); |
| 121 | + |
| 122 | + word = FIELD_PREP(DISP_GAMMA_LUT_10BIT_R, diff.red); |
| 123 | + word |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_G, diff.green); |
| 124 | + word |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_B, diff.blue); |
| 125 | + } |
| 126 | + writel(word, lut_base + i * 4); |
110 | 127 | }
|
111 |
| - writel(word, lut_base + i * 4); |
112 | 128 | }
|
113 | 129 |
|
114 | 130 | cfg_val = readl(gamma->regs + DISP_GAMMA_CFG);
|
@@ -212,10 +228,12 @@ static void mtk_disp_gamma_remove(struct platform_device *pdev)
|
212 | 228 |
|
213 | 229 | static const struct mtk_disp_gamma_data mt8173_gamma_driver_data = {
|
214 | 230 | .has_dither = true,
|
| 231 | + .lut_bank_size = 512, |
215 | 232 | .lut_size = 512,
|
216 | 233 | };
|
217 | 234 |
|
218 | 235 | static const struct mtk_disp_gamma_data mt8183_gamma_driver_data = {
|
| 236 | + .lut_bank_size = 512, |
219 | 237 | .lut_diff = true,
|
220 | 238 | .lut_size = 512,
|
221 | 239 | };
|
|
0 commit comments