2 * Copyright (C) 2008 Maarten Maathuis.
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:
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.
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.
27 #include "nv50_connector.h"
29 static struct nv50_output *nv50_connector_to_output(struct nv50_connector *connector, bool digital)
31 struct nv50_display *display = nv50_get_display(connector->dev);
32 struct nv50_output *output = NULL;
33 bool digital_possible = false;
34 bool analog_possible = false;
36 switch (connector->type) {
39 analog_possible = true;
42 analog_possible = true;
43 digital_possible = true;
47 digital_possible = true;
53 /* Return early on bad situations. */
54 if (!analog_possible && !digital_possible)
57 if (!analog_possible && !digital)
60 if (!digital_possible && digital)
63 list_for_each_entry(output, &display->outputs, head) {
64 if (connector->bus != output->bus)
66 if (digital && output->type == OUTPUT_TMDS)
68 if (digital && output->type == OUTPUT_LVDS)
70 if (!digital && output->type == OUTPUT_DAC)
72 if (!digital && output->type == OUTPUT_TV)
79 static bool nv50_connector_detect(struct nv50_connector *connector)
81 /* kindly borrrowed from the intel driver, hope it works. */
82 uint8_t out_buf[] = { 0x0, 0x0};
85 struct i2c_msg msgs[] = {
102 if (!connector->i2c_chan)
105 ret = i2c_transfer(&connector->i2c_chan->adapter, msgs, 2);
106 DRM_INFO("I2C detect returned %d\n", ret);
114 static int nv50_connector_destroy(struct nv50_connector *connector)
116 struct drm_device *dev = connector->dev;
117 struct drm_nouveau_private *dev_priv = dev->dev_private;
118 struct nv50_display *display = nv50_get_display(dev);
122 if (!display || !connector)
125 list_del(&connector->head);
127 if (connector->i2c_chan)
128 nv50_i2c_channel_destroy(connector->i2c_chan);
130 if (dev_priv->free_connector)
131 dev_priv->free_connector(connector);
136 int nv50_connector_create(struct drm_device *dev, int bus, int i2c_index, int type)
138 struct nv50_connector *connector = NULL;
139 struct drm_nouveau_private *dev_priv = dev->dev_private;
140 struct nv50_display *display = NULL;
144 /* This allows the public layer to do it's thing. */
145 if (dev_priv->alloc_connector)
146 connector = dev_priv->alloc_connector(dev);
151 connector->dev = dev;
153 display = nv50_get_display(dev);
157 if (type == CONNECTOR_UNKNOWN)
160 list_add_tail(&connector->head, &display->connectors);
162 connector->bus = bus;
163 connector->type = type;
167 DRM_INFO("Detected a VGA connector\n");
169 case CONNECTOR_DVI_D:
170 DRM_INFO("Detected a DVI-D connector\n");
172 case CONNECTOR_DVI_I:
173 DRM_INFO("Detected a DVI-I connector\n");
176 DRM_INFO("Detected a LVDS connector\n");
179 DRM_INFO("Detected a TV connector\n");
182 DRM_ERROR("Unknown connector, this is not good.\n");
186 /* some reasonable defaults */
187 if (type == CONNECTOR_DVI_D || type == CONNECTOR_LVDS)
188 connector->scaling_mode = SCALE_FULLSCREEN;
190 connector->scaling_mode = SCALE_PANEL;
193 connector->i2c_chan = nv50_i2c_channel_create(dev, i2c_index);
195 /* set function pointers */
196 connector->detect = nv50_connector_detect;
197 connector->destroy = nv50_connector_destroy;
198 connector->to_output = nv50_connector_to_output;
203 if (dev_priv->free_connector)
204 dev_priv->free_connector(connector);