drm/nv50/disp: call into core for dac load detection
[firefly-linux-kernel-4.4.55.git] / 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 <core/class.h>
40
41 #include <subdev/timer.h>
42
43 static void
44 nv50_dac_disconnect(struct drm_encoder *encoder)
45 {
46         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
47         struct drm_device *dev = encoder->dev;
48         struct nouveau_drm *drm = nouveau_drm(dev);
49         struct nouveau_channel *evo = nv50_display(dev)->master;
50         int ret;
51
52         if (!nv_encoder->crtc)
53                 return;
54         nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true);
55
56         NV_DEBUG(drm, "Disconnecting DAC %d\n", nv_encoder->or);
57
58         ret = RING_SPACE(evo, 4);
59         if (ret) {
60                 NV_ERROR(drm, "no space while disconnecting DAC\n");
61                 return;
62         }
63         BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1);
64         OUT_RING  (evo, 0);
65         BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1);
66         OUT_RING  (evo, 0);
67
68         nv_encoder->crtc = NULL;
69 }
70
71 static enum drm_connector_status
72 nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
73 {
74         struct nv50_display *priv = nv50_display(encoder->dev);
75         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
76         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
77         int or = nv_encoder->or, ret;
78         u32 load;
79
80         if (drm->vbios.dactestval)
81                 load = drm->vbios.dactestval;
82         else
83                 load = 340;
84
85         ret = nv_exec(priv->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
86         if (ret || load != 7)
87                 return connector_status_disconnected;
88
89         return connector_status_connected;
90 }
91
92 static void
93 nv50_dac_dpms(struct drm_encoder *encoder, int mode)
94 {
95         struct nv50_display *priv = nv50_display(encoder->dev);
96         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
97         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
98         uint32_t val;
99         int or = nv_encoder->or;
100
101         NV_DEBUG(drm, "or %d mode %d\n", or, mode);
102
103         if (mode != DRM_MODE_DPMS_ON)
104                 val = NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED;
105         else
106                 val = 0;
107
108         switch (mode) {
109         case DRM_MODE_DPMS_STANDBY:
110                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
111                 break;
112         case DRM_MODE_DPMS_SUSPEND:
113                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
114                 break;
115         case DRM_MODE_DPMS_OFF:
116                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_OFF;
117                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
118                 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
119                 break;
120         default:
121                 break;
122         }
123
124         nv_call(priv->core, NV50_DISP_DAC_PWR + or, val);
125 }
126
127 static void
128 nv50_dac_save(struct drm_encoder *encoder)
129 {
130         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
131         NV_ERROR(drm, "!!\n");
132 }
133
134 static void
135 nv50_dac_restore(struct drm_encoder *encoder)
136 {
137         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
138         NV_ERROR(drm, "!!\n");
139 }
140
141 static bool
142 nv50_dac_mode_fixup(struct drm_encoder *encoder,
143                     const struct drm_display_mode *mode,
144                     struct drm_display_mode *adjusted_mode)
145 {
146         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
147         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
148         struct nouveau_connector *connector;
149
150         NV_DEBUG(drm, "or %d\n", nv_encoder->or);
151
152         connector = nouveau_encoder_connector_get(nv_encoder);
153         if (!connector) {
154                 NV_ERROR(drm, "Encoder has no connector\n");
155                 return false;
156         }
157
158         if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
159              connector->native_mode)
160                 drm_mode_copy(adjusted_mode, connector->native_mode);
161
162         return true;
163 }
164
165 static void
166 nv50_dac_commit(struct drm_encoder *encoder)
167 {
168 }
169
170 static void
171 nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
172                   struct drm_display_mode *adjusted_mode)
173 {
174         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
175         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
176         struct drm_device *dev = encoder->dev;
177         struct nouveau_channel *evo = nv50_display(dev)->master;
178         struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
179         uint32_t mode_ctl = 0, mode_ctl2 = 0;
180         int ret;
181
182         NV_DEBUG(drm, "or %d type %d crtc %d\n",
183                      nv_encoder->or, nv_encoder->dcb->type, crtc->index);
184
185         nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON);
186
187         if (crtc->index == 1)
188                 mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC1;
189         else
190                 mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0;
191
192         /* Lacking a working tv-out, this is not a 100% sure. */
193         if (nv_encoder->dcb->type == DCB_OUTPUT_ANALOG)
194                 mode_ctl |= 0x40;
195         else
196         if (nv_encoder->dcb->type == DCB_OUTPUT_TV)
197                 mode_ctl |= 0x100;
198
199         if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
200                 mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NHSYNC;
201
202         if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
203                 mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NVSYNC;
204
205         ret = RING_SPACE(evo, 3);
206         if (ret) {
207                 NV_ERROR(drm, "no space while connecting DAC\n");
208                 return;
209         }
210         BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2);
211         OUT_RING(evo, mode_ctl);
212         OUT_RING(evo, mode_ctl2);
213
214         nv_encoder->crtc = encoder->crtc;
215 }
216
217 static struct drm_crtc *
218 nv50_dac_crtc_get(struct drm_encoder *encoder)
219 {
220         return nouveau_encoder(encoder)->crtc;
221 }
222
223 static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = {
224         .dpms = nv50_dac_dpms,
225         .save = nv50_dac_save,
226         .restore = nv50_dac_restore,
227         .mode_fixup = nv50_dac_mode_fixup,
228         .prepare = nv50_dac_disconnect,
229         .commit = nv50_dac_commit,
230         .mode_set = nv50_dac_mode_set,
231         .get_crtc = nv50_dac_crtc_get,
232         .detect = nv50_dac_detect,
233         .disable = nv50_dac_disconnect
234 };
235
236 static void
237 nv50_dac_destroy(struct drm_encoder *encoder)
238 {
239         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
240
241         if (!encoder)
242                 return;
243
244         drm_encoder_cleanup(encoder);
245         kfree(nv_encoder);
246 }
247
248 static const struct drm_encoder_funcs nv50_dac_encoder_funcs = {
249         .destroy = nv50_dac_destroy,
250 };
251
252 int
253 nv50_dac_create(struct drm_connector *connector, struct dcb_output *entry)
254 {
255         struct nouveau_encoder *nv_encoder;
256         struct drm_encoder *encoder;
257
258         nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
259         if (!nv_encoder)
260                 return -ENOMEM;
261         encoder = to_drm_encoder(nv_encoder);
262
263         nv_encoder->dcb = entry;
264         nv_encoder->or = ffs(entry->or) - 1;
265
266         drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs,
267                          DRM_MODE_ENCODER_DAC);
268         drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs);
269
270         encoder->possible_crtcs = entry->heads;
271         encoder->possible_clones = 0;
272
273         drm_mode_connector_attach_encoder(connector, encoder);
274         return 0;
275 }
276