radeon: remove unused legacy state
[platform/upstream/libdrm.git] / linux-core / nv50_lut.c
1 /*
2  * Copyright (C) 2008 Maarten Maathuis.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26
27 #include "nv50_lut.h"
28 #include "nv50_fb.h"
29 #include "nv50_crtc.h"
30 #include "nv50_display.h"
31
32 static int nv50_lut_alloc(struct nv50_crtc *crtc)
33 {
34         struct mem_block *block;
35         struct drm_file *file_priv = kzalloc(sizeof(struct drm_file), GFP_KERNEL);
36         uint32_t flags = NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED;
37         int rval = 0;
38
39         NV50_DEBUG("\n");
40
41         if (!file_priv)
42                 return -ENOMEM;
43
44         /* Any file_priv should do as it's pointer is used as identification. */
45         block = nouveau_mem_alloc(crtc->dev, 0, 4096, flags, file_priv);
46
47         if (!block) {
48                 rval = -ENOMEM;
49                 goto out;
50         }
51
52         crtc->lut->block = block;
53
54         return 0;
55
56 out:
57         if (file_priv)
58                 kfree(file_priv);
59
60         return rval;
61 }
62
63 static int nv50_lut_free(struct nv50_crtc *crtc)
64 {
65         struct drm_file *file_priv = crtc->lut->block->file_priv;
66
67         NV50_DEBUG("\n");
68
69         nouveau_mem_free(crtc->dev, crtc->lut->block);
70
71         kfree(file_priv);
72
73         return 0;
74 }
75
76 #define NV50_LUT_INDEX(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
77 static int nv50_lut_set(struct nv50_crtc *crtc, uint16_t *red, uint16_t *green, uint16_t *blue)
78 {
79         uint32_t index = 0, i;
80         struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
81         void __iomem *lut = NULL;
82
83         NV50_DEBUG("\n");
84
85         if (!crtc->lut || !crtc->lut->block) {
86                 DRM_ERROR("Something wrong with the LUT\n");
87                 return -EINVAL;
88         }
89
90         /* 16 bits, red, green, blue, unused, total of 64 bits per index */
91         /* maybe switch to ioremap_wc once it becomes available. */
92         lut = ioremap(dev_priv->fb_phys + crtc->lut->block->start, crtc->lut->block->size);
93         if (!lut) {
94                 DRM_ERROR("ioremap failed on LUT\n");
95                 return -EINVAL;
96         }
97
98         /* 10 bits lut, with 14 bits values. */
99         switch (crtc->fb->depth) {
100                 case 15:
101                         /* R5G5B5 */
102                         for (i = 0; i < 32; i++) {
103                                 index = NV50_LUT_INDEX(i, 5);
104                                 writew(red[i] >> 2, lut + 8*index + 0);
105                                 writew(green[i] >> 2, lut + 8*index + 2);
106                                 writew(blue[i] >> 2, lut + 8*index + 4);
107                         }
108                         break;
109                 case 16:
110                         /* R5G6B5 */
111                         for (i = 0; i < 32; i++) {
112                                 index = NV50_LUT_INDEX(i, 5);
113                                 writew(red[i] >> 2, lut + 8*index + 0);
114                                 writew(blue[i] >> 2, lut + 8*index + 4);
115                         }
116
117                         /* Green has an extra bit. */
118                         for (i = 0; i < 64; i++) {
119                                 index = NV50_LUT_INDEX(i, 6);
120                                 writew(green[i] >> 2, lut + 8*index + 2);
121                         }
122                         break;
123                 default:
124                         /* R8G8B8 */
125                         for (i = 0; i < 256; i++) {
126                                 writew(red[i] >> 2, lut + 8*i + 0);
127                                 writew(green[i] >> 2, lut + 8*i + 2);
128                                 writew(blue[i] >> 2, lut + 8*i + 4);
129                         }
130                         break;
131         }
132
133         crtc->lut->depth = crtc->fb->depth;
134
135         /* Cleaning time. */
136         iounmap(lut);
137
138         return 0;
139 }
140
141 int nv50_lut_create(struct nv50_crtc *crtc)
142 {
143         int rval = 0;
144
145         NV50_DEBUG("\n");
146
147         if (!crtc)
148                 return -EINVAL;
149
150         crtc->lut = kzalloc(sizeof(struct nv50_lut), GFP_KERNEL);
151
152         if (!crtc->lut)
153                 return -ENOMEM;
154
155         rval = nv50_lut_alloc(crtc);
156         if (rval != 0) {
157                 goto out;
158         }
159
160         /* lut will be inited when fb is bound */
161         crtc->lut->depth = 0;
162
163         /* function pointers */
164         crtc->lut->set = nv50_lut_set;
165
166         return 0;
167
168 out:
169         if (crtc->lut)
170                 kfree(crtc->lut);
171
172         return rval;
173 }
174
175 int nv50_lut_destroy(struct nv50_crtc *crtc)
176 {
177         int rval = 0;
178
179         NV50_DEBUG("\n");
180
181         if (!crtc)
182                 return -EINVAL;
183
184         rval = nv50_lut_free(crtc);
185
186         kfree(crtc->lut);
187         crtc->lut = NULL;
188
189         if (rval != 0)
190                 return rval;
191
192         return 0;
193 }