]> Pileus Git - ~andy/linux/blob - drivers/gpu/drm/nouveau/nv50_dac.c
Merge tag 'tags/disintegrate-tile-20121009' into for-linus
[~andy/linux] / drivers / gpu / drm / nouveau / nv50_dac.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 <drm/drmP.h>
28 #include <drm/drm_crtc_helper.h>
29
30 #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
31 #include "nouveau_reg.h"
32 #include "nouveau_drm.h"
33 #include "nouveau_dma.h"
34 #include "nouveau_encoder.h"
35 #include "nouveau_connector.h"
36 #include "nouveau_crtc.h"
37 #include "nv50_display.h"
38
39 #include <subdev/timer.h>
40
41 static void
42 nv50_dac_disconnect(struct drm_encoder *encoder)
43 {
44         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
45         struct drm_device *dev = encoder->dev;
46         struct nouveau_drm *drm = nouveau_drm(dev);
47         struct nouveau_channel *evo = nv50_display(dev)->master;
48         int ret;
49
50         if (!nv_encoder->crtc)
51                 return;
52         nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true);
53
54         NV_DEBUG(drm, "Disconnecting DAC %d\n", nv_encoder->or);
55
56         ret = RING_SPACE(evo, 4);
57         if (ret) {
58                 NV_ERROR(drm, "no space while disconnecting DAC\n");
59                 return;
60         }
61         BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1);
62         OUT_RING  (evo, 0);
63         BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1);
64         OUT_RING  (evo, 0);
65
66         nv_encoder->crtc = NULL;
67 }
68
69 static enum drm_connector_status
70 nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
71 {
72         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
73         struct nouveau_device *device = nouveau_dev(encoder->dev);
74         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
75         enum drm_connector_status status = connector_status_disconnected;
76         uint32_t dpms_state, load_pattern, load_state;
77         int or = nv_encoder->or;
78
79         nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001);
80         dpms_state = nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or));
81
82         nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
83                 0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
84         if (!nv_wait(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
85                      NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
86                 NV_ERROR(drm, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
87                 NV_ERROR(drm, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
88                           nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
89                 return status;
90         }
91
92         /* Use bios provided value if possible. */
93         if (drm->vbios.dactestval) {
94                 load_pattern = drm->vbios.dactestval;
95                 NV_DEBUG(drm, "Using bios provided load_pattern of %d\n",
96                           load_pattern);
97         } else {
98                 load_pattern = 340;
99                 NV_DEBUG(drm, "Using default load_pattern of %d\n",
100                          load_pattern);
101         }
102
103         nv_wr32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or),
104                 NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern);
105         mdelay(45); /* give it some time to process */
106         load_state = nv_rd32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or));
107
108         nv_wr32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0);
109         nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state |
110                 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
111
112         if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) ==
113                           NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT)
114                 status = connector_status_connected;
115
116         if (status == connector_status_connected)
117                 NV_DEBUG(drm, "Load was detected on output with or %d\n", or);
118         else
119                 NV_DEBUG(drm, "Load was not detected on output with or %d\n", or);
120
121         return status;
122 }
123
124 static void
125 nv50_dac_dpms(struct drm_encoder *encoder, int mode)
126 {
127         struct nouveau_device *device = nouveau_dev(encoder->dev);
128         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
129         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
130         uint32_t val;
131         int or = nv_encoder->or;
132
133         NV_DEBUG(drm, "or %d mode %d\n", or, mode);
134
135         /* wait for it to be done */
136         if (!nv_wait(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
137                      NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
138                 NV_ERROR(drm, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
139                 NV_ERROR(drm, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
140                          nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
141                 return;
142         }
143
144         val = nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F;
145
146         if (mode != DRM_MODE_DPMS_ON)
147                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED;
148
149         switch (mode) {
150         case DRM_MODE_DPMS_STANDBY:
151                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
152                 break;
153         case DRM_MODE_DPMS_SUSPEND:
154                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
155                 break;
156         case DRM_MODE_DPMS_OFF:
157                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_OFF;
158                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
159                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
160                 break;
161         default:
162                 break;
163         }
164
165         nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val |
166                 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
167 }
168
169 static void
170 nv50_dac_save(struct drm_encoder *encoder)
171 {
172         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
173         NV_ERROR(drm, "!!\n");
174 }
175
176 static void
177 nv50_dac_restore(struct drm_encoder *encoder)
178 {
179         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
180         NV_ERROR(drm, "!!\n");
181 }
182
183 static bool
184 nv50_dac_mode_fixup(struct drm_encoder *encoder,
185                     const struct drm_display_mode *mode,
186                     struct drm_display_mode *adjusted_mode)
187 {
188         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
189         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
190         struct nouveau_connector *connector;
191
192         NV_DEBUG(drm, "or %d\n", nv_encoder->or);
193
194         connector = nouveau_encoder_connector_get(nv_encoder);
195         if (!connector) {
196                 NV_ERROR(drm, "Encoder has no connector\n");
197                 return false;
198         }
199
200         if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
201              connector->native_mode)
202                 drm_mode_copy(adjusted_mode, connector->native_mode);
203
204         return true;
205 }
206
207 static void
208 nv50_dac_commit(struct drm_encoder *encoder)
209 {
210 }
211
212 static void
213 nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
214                   struct drm_display_mode *adjusted_mode)
215 {
216         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
217         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
218         struct drm_device *dev = encoder->dev;
219         struct nouveau_channel *evo = nv50_display(dev)->master;
220         struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
221         uint32_t mode_ctl = 0, mode_ctl2 = 0;
222         int ret;
223
224         NV_DEBUG(drm, "or %d type %d crtc %d\n",
225                      nv_encoder->or, nv_encoder->dcb->type, crtc->index);
226
227         nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON);
228
229         if (crtc->index == 1)
230                 mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC1;
231         else
232                 mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0;
233
234         /* Lacking a working tv-out, this is not a 100% sure. */
235         if (nv_encoder->dcb->type == DCB_OUTPUT_ANALOG)
236                 mode_ctl |= 0x40;
237         else
238         if (nv_encoder->dcb->type == DCB_OUTPUT_TV)
239                 mode_ctl |= 0x100;
240
241         if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
242                 mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NHSYNC;
243
244         if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
245                 mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NVSYNC;
246
247         ret = RING_SPACE(evo, 3);
248         if (ret) {
249                 NV_ERROR(drm, "no space while connecting DAC\n");
250                 return;
251         }
252         BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2);
253         OUT_RING(evo, mode_ctl);
254         OUT_RING(evo, mode_ctl2);
255
256         nv_encoder->crtc = encoder->crtc;
257 }
258
259 static struct drm_crtc *
260 nv50_dac_crtc_get(struct drm_encoder *encoder)
261 {
262         return nouveau_encoder(encoder)->crtc;
263 }
264
265 static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = {
266         .dpms = nv50_dac_dpms,
267         .save = nv50_dac_save,
268         .restore = nv50_dac_restore,
269         .mode_fixup = nv50_dac_mode_fixup,
270         .prepare = nv50_dac_disconnect,
271         .commit = nv50_dac_commit,
272         .mode_set = nv50_dac_mode_set,
273         .get_crtc = nv50_dac_crtc_get,
274         .detect = nv50_dac_detect,
275         .disable = nv50_dac_disconnect
276 };
277
278 static void
279 nv50_dac_destroy(struct drm_encoder *encoder)
280 {
281         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
282         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
283
284         if (!encoder)
285                 return;
286
287         NV_DEBUG(drm, "\n");
288
289         drm_encoder_cleanup(encoder);
290         kfree(nv_encoder);
291 }
292
293 static const struct drm_encoder_funcs nv50_dac_encoder_funcs = {
294         .destroy = nv50_dac_destroy,
295 };
296
297 int
298 nv50_dac_create(struct drm_connector *connector, struct dcb_output *entry)
299 {
300         struct nouveau_encoder *nv_encoder;
301         struct drm_encoder *encoder;
302
303         nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
304         if (!nv_encoder)
305                 return -ENOMEM;
306         encoder = to_drm_encoder(nv_encoder);
307
308         nv_encoder->dcb = entry;
309         nv_encoder->or = ffs(entry->or) - 1;
310
311         drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs,
312                          DRM_MODE_ENCODER_DAC);
313         drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs);
314
315         encoder->possible_crtcs = entry->heads;
316         encoder->possible_clones = 0;
317
318         drm_mode_connector_attach_encoder(connector, encoder);
319         return 0;
320 }
321