~ubuntu-branches/ubuntu/natty/linux-backports-modules-2.6.32/natty

« back to all changes in this revision

Viewing changes to updates/nouveau/nouveau/nv04_tv.c

  • Committer: Bazaar Package Importer
  • Author(s): Andy Whitcroft, Andy Whitcroft, Tim Gardner
  • Date: 2010-03-08 08:59:41 UTC
  • Revision ID: james.westby@ubuntu.com-20100308085941-rrlpd5wtuh7m2an9
Tags: 2.6.32-16.6
[ Andy Whitcroft ]

* Lucid ABI 16
* nouveau -- make the nouveau package an optional build
* nouveau -- disable generation of nouveau
* nouveau -- drop the redundant nouveau source

[ Tim Gardner ]

* Added iwlwifi 6000 series firmware
* udev expects firmware in /lib/firmware/updates/`uname -r`

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2009 Francisco Jerez.
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 "drmP.h"
28
 
#include "nouveau_drv.h"
29
 
#include "nouveau_encoder.h"
30
 
#include "nouveau_connector.h"
31
 
#include "nouveau_crtc.h"
32
 
#include "nouveau_hw.h"
33
 
#include "drm_crtc_helper.h"
34
 
 
35
 
#include "i2c/ch7006.h"
36
 
 
37
 
static struct {
38
 
        struct i2c_board_info board_info;
39
 
        struct drm_encoder_funcs funcs;
40
 
        struct drm_encoder_helper_funcs hfuncs;
41
 
        void *params;
42
 
 
43
 
} nv04_tv_encoder_info[] = {
44
 
        {
45
 
                .board_info = { I2C_BOARD_INFO("ch7006", 0x75) },
46
 
                .params = &(struct ch7006_encoder_params) {
47
 
                        CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
48
 
                        0, 0, 0,
49
 
                        CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
50
 
                        CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
51
 
                },
52
 
        },
53
 
};
54
 
 
55
 
static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr)
56
 
{
57
 
        struct i2c_msg msg = {
58
 
                .addr = addr,
59
 
                .len = 0,
60
 
        };
61
 
 
62
 
        return i2c_transfer(adapter, &msg, 1) == 1;
63
 
}
64
 
 
65
 
int nv04_tv_identify(struct drm_device *dev, int i2c_index)
66
 
{
67
 
        struct nouveau_i2c_chan *i2c;
68
 
        bool was_locked;
69
 
        int i, ret;
70
 
 
71
 
        NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index);
72
 
 
73
 
        i2c = nouveau_i2c_find(dev, i2c_index);
74
 
        if (!i2c)
75
 
                return -ENODEV;
76
 
 
77
 
        was_locked = NVLockVgaCrtcs(dev, false);
78
 
 
79
 
        for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) {
80
 
                if (probe_i2c_addr(&i2c->adapter,
81
 
                                   nv04_tv_encoder_info[i].board_info.addr)) {
82
 
                        ret = i;
83
 
                        break;
84
 
                }
85
 
        }
86
 
 
87
 
        if (i < ARRAY_SIZE(nv04_tv_encoder_info)) {
88
 
                NV_TRACE(dev, "Detected TV encoder: %s\n",
89
 
                         nv04_tv_encoder_info[i].board_info.type);
90
 
 
91
 
        } else {
92
 
                NV_TRACE(dev, "No TV encoders found.\n");
93
 
                i = -ENODEV;
94
 
        }
95
 
 
96
 
        NVLockVgaCrtcs(dev, was_locked);
97
 
        return i;
98
 
}
99
 
 
100
 
#define PLLSEL_TV_CRTC1_MASK                            \
101
 
        (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1          \
102
 
         | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1)
103
 
#define PLLSEL_TV_CRTC2_MASK                            \
104
 
        (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2          \
105
 
         | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2)
106
 
 
107
 
static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
108
 
{
109
 
        struct drm_device *dev = encoder->dev;
110
 
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
111
 
        struct drm_nouveau_private *dev_priv = dev->dev_private;
112
 
        struct nv04_mode_state *state = &dev_priv->mode_reg;
113
 
        uint8_t crtc1A;
114
 
 
115
 
        NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n",
116
 
                mode, nv_encoder->dcb->index);
117
 
 
118
 
        state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
119
 
 
120
 
        if (mode == DRM_MODE_DPMS_ON) {
121
 
                int head = nouveau_crtc(encoder->crtc)->index;
122
 
                crtc1A = NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX);
123
 
 
124
 
                state->pllsel |= head ? PLLSEL_TV_CRTC2_MASK :
125
 
                                        PLLSEL_TV_CRTC1_MASK;
126
 
 
127
 
                /* Inhibit hsync */
128
 
                crtc1A |= 0x80;
129
 
 
130
 
                NVWriteVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX, crtc1A);
131
 
        }
132
 
 
133
 
        NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel);
134
 
 
135
 
        to_encoder_slave(encoder)->slave_funcs->dpms(encoder, mode);
136
 
}
137
 
 
138
 
static void nv04_tv_bind(struct drm_device *dev, int head, bool bind)
139
 
{
140
 
        struct drm_nouveau_private *dev_priv = dev->dev_private;
141
 
        struct nv04_crtc_reg *state = &dev_priv->mode_reg.crtc_reg[head];
142
 
 
143
 
        state->tv_setup = 0;
144
 
 
145
 
        if (bind) {
146
 
                state->CRTC[NV_CIO_CRE_LCD__INDEX] = 0;
147
 
                state->CRTC[NV_CIO_CRE_49] |= 0x10;
148
 
        } else {
149
 
                state->CRTC[NV_CIO_CRE_49] &= ~0x10;
150
 
        }
151
 
 
152
 
        NVWriteVgaCrtc(dev, head, NV_CIO_CRE_LCD__INDEX,
153
 
                       state->CRTC[NV_CIO_CRE_LCD__INDEX]);
154
 
        NVWriteVgaCrtc(dev, head, NV_CIO_CRE_49,
155
 
                       state->CRTC[NV_CIO_CRE_49]);
156
 
        NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP,
157
 
                      state->tv_setup);
158
 
}
159
 
 
160
 
static void nv04_tv_prepare(struct drm_encoder *encoder)
161
 
{
162
 
        struct drm_device *dev = encoder->dev;
163
 
        int head = nouveau_crtc(encoder->crtc)->index;
164
 
        struct drm_encoder_helper_funcs *helper = encoder->helper_private;
165
 
 
166
 
        helper->dpms(encoder, DRM_MODE_DPMS_OFF);
167
 
 
168
 
        nv04_dfp_disable(dev, head);
169
 
 
170
 
        if (nv_two_heads(dev))
171
 
                nv04_tv_bind(dev, head ^ 1, false);
172
 
 
173
 
        nv04_tv_bind(dev, head, true);
174
 
}
175
 
 
176
 
static void nv04_tv_mode_set(struct drm_encoder *encoder,
177
 
                             struct drm_display_mode *mode,
178
 
                             struct drm_display_mode *adjusted_mode)
179
 
{
180
 
        struct drm_device *dev = encoder->dev;
181
 
        struct drm_nouveau_private *dev_priv = dev->dev_private;
182
 
        struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
183
 
        struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
184
 
 
185
 
        regp->tv_htotal = adjusted_mode->htotal;
186
 
        regp->tv_vtotal = adjusted_mode->vtotal;
187
 
 
188
 
        /* These delay the TV signals with respect to the VGA port,
189
 
         * they might be useful if we ever allow a CRTC to drive
190
 
         * multiple outputs.
191
 
         */
192
 
        regp->tv_hskew = 1;
193
 
        regp->tv_hsync_delay = 1;
194
 
        regp->tv_hsync_delay2 = 64;
195
 
        regp->tv_vskew = 1;
196
 
        regp->tv_vsync_delay = 1;
197
 
 
198
 
        to_encoder_slave(encoder)->slave_funcs->mode_set(encoder, mode, adjusted_mode);
199
 
}
200
 
 
201
 
static void nv04_tv_commit(struct drm_encoder *encoder)
202
 
{
203
 
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
204
 
        struct drm_device *dev = encoder->dev;
205
 
        struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
206
 
        struct drm_encoder_helper_funcs *helper = encoder->helper_private;
207
 
 
208
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
209
 
 
210
 
        NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
211
 
                      drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
212
 
                      '@' + ffs(nv_encoder->dcb->or));
213
 
}
214
 
 
215
 
static void nv04_tv_destroy(struct drm_encoder *encoder)
216
 
{
217
 
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
218
 
 
219
 
        to_encoder_slave(encoder)->slave_funcs->destroy(encoder);
220
 
 
221
 
        drm_encoder_cleanup(encoder);
222
 
 
223
 
        kfree(nv_encoder);
224
 
}
225
 
 
226
 
int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
227
 
{
228
 
        struct nouveau_encoder *nv_encoder;
229
 
        struct drm_encoder *encoder;
230
 
        struct drm_nouveau_private *dev_priv = dev->dev_private;
231
 
        struct i2c_adapter *adap;
232
 
        struct drm_encoder_funcs *funcs = NULL;
233
 
        struct drm_encoder_helper_funcs *hfuncs = NULL;
234
 
        struct drm_encoder_slave_funcs *sfuncs = NULL;
235
 
        int i2c_index = entry->i2c_index;
236
 
        int type, ret;
237
 
        bool was_locked;
238
 
 
239
 
        /* Ensure that we can talk to this encoder */
240
 
        type = nv04_tv_identify(dev, i2c_index);
241
 
        if (type < 0)
242
 
                return type;
243
 
 
244
 
        /* Allocate the necessary memory */
245
 
        nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
246
 
        if (!nv_encoder)
247
 
                return -ENOMEM;
248
 
 
249
 
        /* Initialize the common members */
250
 
        encoder = to_drm_encoder(nv_encoder);
251
 
 
252
 
        funcs = &nv04_tv_encoder_info[type].funcs;
253
 
        hfuncs = &nv04_tv_encoder_info[type].hfuncs;
254
 
 
255
 
        drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC);
256
 
        drm_encoder_helper_add(encoder, hfuncs);
257
 
 
258
 
        encoder->possible_crtcs = entry->heads;
259
 
        encoder->possible_clones = 0;
260
 
 
261
 
        nv_encoder->dcb = entry;
262
 
        nv_encoder->or = ffs(entry->or) - 1;
263
 
 
264
 
        /* Run the slave-specific initialization */
265
 
        adap = &dev_priv->vbios->dcb->i2c[i2c_index].chan->adapter;
266
 
 
267
 
        was_locked = NVLockVgaCrtcs(dev, false);
268
 
 
269
 
        ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap,
270
 
                                   &nv04_tv_encoder_info[type].board_info);
271
 
 
272
 
        NVLockVgaCrtcs(dev, was_locked);
273
 
 
274
 
        if (ret < 0)
275
 
                goto fail;
276
 
 
277
 
        /* Fill the function pointers */
278
 
        sfuncs = to_encoder_slave(encoder)->slave_funcs;
279
 
 
280
 
        *funcs = (struct drm_encoder_funcs) {
281
 
                .destroy = nv04_tv_destroy,
282
 
        };
283
 
 
284
 
        *hfuncs = (struct drm_encoder_helper_funcs) {
285
 
                .dpms = nv04_tv_dpms,
286
 
                .save = sfuncs->save,
287
 
                .restore = sfuncs->restore,
288
 
                .mode_fixup = sfuncs->mode_fixup,
289
 
                .prepare = nv04_tv_prepare,
290
 
                .commit = nv04_tv_commit,
291
 
                .mode_set = nv04_tv_mode_set,
292
 
                .detect = sfuncs->detect,
293
 
        };
294
 
 
295
 
        /* Set the slave encoder configuration */
296
 
        sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params);
297
 
 
298
 
        return 0;
299
 
 
300
 
fail:
301
 
        drm_encoder_cleanup(encoder);
302
 
 
303
 
        kfree(nv_encoder);
304
 
        return ret;
305
 
}