drm/i915: initialize DDI buffer translations
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / i915 / intel_ddi.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Eugeni Dodonov <eugeni.dodonov@intel.com>
25  *
26  */
27
28 #include "i915_drv.h"
29 #include "intel_drv.h"
30
31 /* HDMI/DVI modes ignore everything but the last 2 items. So we share
32  * them for both DP and FDI transports, allowing those ports to
33  * automatically adapt to HDMI connections as well
34  */
35 static const u32 hsw_ddi_translations_dp[] = {
36         0x00FFFFFF, 0x0006000E,         /* DP parameters */
37         0x00D75FFF, 0x0005000A,
38         0x00C30FFF, 0x00040006,
39         0x80AAAFFF, 0x000B0000,
40         0x00FFFFFF, 0x0005000A,
41         0x00D75FFF, 0x000C0004,
42         0x80C30FFF, 0x000B0000,
43         0x00FFFFFF, 0x00040006,
44         0x80D75FFF, 0x000B0000,
45         0x00FFFFFF, 0x00040006          /* HDMI parameters */
46 };
47
48 static const u32 hsw_ddi_translations_fdi[] = {
49         0x00FFFFFF, 0x0007000E,         /* FDI parameters */
50         0x00D75FFF, 0x000F000A,
51         0x00C30FFF, 0x00060006,
52         0x00AAAFFF, 0x001E0000,
53         0x00FFFFFF, 0x000F000A,
54         0x00D75FFF, 0x00160004,
55         0x00C30FFF, 0x001E0000,
56         0x00FFFFFF, 0x00060006,
57         0x00D75FFF, 0x001E0000,
58         0x00FFFFFF, 0x00040006          /* HDMI parameters */
59 };
60
61 /* On Haswell, DDI port buffers must be programmed with correct values
62  * in advance. The buffer values are different for FDI and DP modes,
63  * but the HDMI/DVI fields are shared among those. So we program the DDI
64  * in either FDI or DP modes only, as HDMI connections will work with both
65  * of those
66  */
67 void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool use_fdi_mode)
68 {
69         struct drm_i915_private *dev_priv = dev->dev_private;
70         u32 reg;
71         int i;
72         const u32 *ddi_translations = ((use_fdi_mode) ?
73                 hsw_ddi_translations_fdi :
74                 hsw_ddi_translations_dp);
75
76         DRM_DEBUG_DRIVER("Initializing DDI buffers for port %c in %s mode\n",
77                         port_name(port),
78                         use_fdi_mode ? "FDI" : "DP");
79
80         WARN((use_fdi_mode && (port != PORT_E)),
81                 "Programming port %c in FDI mode, this probably will not work.\n",
82                 port_name(port));
83
84         for (i=0, reg=DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
85                 I915_WRITE(reg, ddi_translations[i]);
86                 reg += 4;
87         }
88 }
89
90 /* Program DDI buffers translations for DP. By default, program ports A-D in DP
91  * mode and port E for FDI.
92  */
93 void intel_prepare_ddi(struct drm_device *dev)
94 {
95         int port;
96
97         if (IS_HASWELL(dev)) {
98                 for (port = PORT_A; port < PORT_E; port++)
99                         intel_prepare_ddi_buffers(dev, port, false);
100
101                 /* DDI E is the suggested one to work in FDI mode, so program is as such by
102                  * default. It will have to be re-programmed in case a digital DP output
103                  * will be detected on it
104                  */
105                 intel_prepare_ddi_buffers(dev, PORT_E, true);
106         }
107 }