Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1/*
  2 * Copyright 2009 Red Hat Inc.
  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 shall be included in
 12 * all copies or substantial portions of the Software.
 13 *
 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 20 * OTHER DEALINGS IN THE SOFTWARE.
 21 *
 22 * Author: Ben Skeggs
 23 */
 24
 25#include "drmP.h"
 26#include "drm.h"
 27#include "drm_crtc_helper.h"
 28
 29#include "nouveau_drv.h"
 30#include "nouveau_fb.h"
 31#include "nouveau_hw.h"
 32#include "nouveau_encoder.h"
 33#include "nouveau_connector.h"
 34
 35static void nv04_vblank_crtc0_isr(struct drm_device *);
 36static void nv04_vblank_crtc1_isr(struct drm_device *);
 37
 38static void
 39nv04_display_store_initial_head_owner(struct drm_device *dev)
 40{
 41	struct drm_nouveau_private *dev_priv = dev->dev_private;
 42
 43	if (dev_priv->chipset != 0x11) {
 44		dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44);
 45		return;
 46	}
 47
 48	/* reading CR44 is broken on nv11, so we attempt to infer it */
 49	if (nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28))	/* heads tied, restore both */
 50		dev_priv->crtc_owner = 0x4;
 51	else {
 52		uint8_t slaved_on_A, slaved_on_B;
 53		bool tvA = false;
 54		bool tvB = false;
 55
 56		slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) &
 57									0x80;
 58		if (slaved_on_B)
 59			tvB = !(NVReadVgaCrtc(dev, 1, NV_CIO_CRE_LCD__INDEX) &
 60					MASK(NV_CIO_CRE_LCD_LCD_SELECT));
 61
 62		slaved_on_A = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX) &
 63									0x80;
 64		if (slaved_on_A)
 65			tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) &
 66					MASK(NV_CIO_CRE_LCD_LCD_SELECT));
 67
 68		if (slaved_on_A && !tvA)
 69			dev_priv->crtc_owner = 0x0;
 70		else if (slaved_on_B && !tvB)
 71			dev_priv->crtc_owner = 0x3;
 72		else if (slaved_on_A)
 73			dev_priv->crtc_owner = 0x0;
 74		else if (slaved_on_B)
 75			dev_priv->crtc_owner = 0x3;
 76		else
 77			dev_priv->crtc_owner = 0x0;
 78	}
 79}
 80
 81int
 82nv04_display_early_init(struct drm_device *dev)
 83{
 84	/* Make the I2C buses accessible. */
 85	if (!nv_gf4_disp_arch(dev)) {
 86		uint32_t pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
 87
 88		if (!(pmc_enable & 1))
 89			nv_wr32(dev, NV03_PMC_ENABLE, pmc_enable | 1);
 90	}
 91
 92	/* Unlock the VGA CRTCs. */
 93	NVLockVgaCrtcs(dev, false);
 94
 95	/* Make sure the CRTCs aren't in slaved mode. */
 96	if (nv_two_heads(dev)) {
 97		nv04_display_store_initial_head_owner(dev);
 98		NVSetOwner(dev, 0);
 99	}
100
101	return 0;
102}
103
104void
105nv04_display_late_takedown(struct drm_device *dev)
106{
107	struct drm_nouveau_private *dev_priv = dev->dev_private;
108
109	if (nv_two_heads(dev))
110		NVSetOwner(dev, dev_priv->crtc_owner);
111
112	NVLockVgaCrtcs(dev, true);
113}
114
115int
116nv04_display_create(struct drm_device *dev)
117{
118	struct drm_nouveau_private *dev_priv = dev->dev_private;
119	struct dcb_table *dcb = &dev_priv->vbios.dcb;
120	struct drm_connector *connector, *ct;
121	struct drm_encoder *encoder;
122	struct drm_crtc *crtc;
123	int i, ret;
124
125	NV_DEBUG_KMS(dev, "\n");
126
127	nouveau_hw_save_vga_fonts(dev, 1);
128
129	drm_mode_config_init(dev);
130	drm_mode_create_scaling_mode_property(dev);
131	drm_mode_create_dithering_property(dev);
132
133	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
134
135	dev->mode_config.min_width = 0;
136	dev->mode_config.min_height = 0;
137	switch (dev_priv->card_type) {
138	case NV_04:
139		dev->mode_config.max_width = 2048;
140		dev->mode_config.max_height = 2048;
141		break;
142	default:
143		dev->mode_config.max_width = 4096;
144		dev->mode_config.max_height = 4096;
145		break;
146	}
147
148	dev->mode_config.fb_base = dev_priv->fb_phys;
149
150	nv04_crtc_create(dev, 0);
151	if (nv_two_heads(dev))
152		nv04_crtc_create(dev, 1);
153
154	for (i = 0; i < dcb->entries; i++) {
155		struct dcb_entry *dcbent = &dcb->entry[i];
156
157		connector = nouveau_connector_create(dev, dcbent->connector);
158		if (IS_ERR(connector))
159			continue;
160
161		switch (dcbent->type) {
162		case OUTPUT_ANALOG:
163			ret = nv04_dac_create(connector, dcbent);
164			break;
165		case OUTPUT_LVDS:
166		case OUTPUT_TMDS:
167			ret = nv04_dfp_create(connector, dcbent);
168			break;
169		case OUTPUT_TV:
170			if (dcbent->location == DCB_LOC_ON_CHIP)
171				ret = nv17_tv_create(connector, dcbent);
172			else
173				ret = nv04_tv_create(connector, dcbent);
174			break;
175		default:
176			NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
177			continue;
178		}
179
180		if (ret)
181			continue;
182	}
183
184	list_for_each_entry_safe(connector, ct,
185				 &dev->mode_config.connector_list, head) {
186		if (!connector->encoder_ids[0]) {
187			NV_WARN(dev, "%s has no encoders, removing\n",
188				drm_get_connector_name(connector));
189			connector->funcs->destroy(connector);
190		}
191	}
192
193	/* Save previous state */
194	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
195		crtc->funcs->save(crtc);
196
197	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
198		struct drm_encoder_helper_funcs *func = encoder->helper_private;
199
200		func->save(encoder);
201	}
202
203	nouveau_irq_register(dev, 24, nv04_vblank_crtc0_isr);
204	nouveau_irq_register(dev, 25, nv04_vblank_crtc1_isr);
205	return 0;
206}
207
208void
209nv04_display_destroy(struct drm_device *dev)
210{
211	struct drm_encoder *encoder;
212	struct drm_crtc *crtc;
213
214	NV_DEBUG_KMS(dev, "\n");
215
216	nouveau_irq_unregister(dev, 24);
217	nouveau_irq_unregister(dev, 25);
218
219	/* Turn every CRTC off. */
220	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
221		struct drm_mode_set modeset = {
222			.crtc = crtc,
223		};
224
225		crtc->funcs->set_config(&modeset);
226	}
227
228	/* Restore state */
229	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
230		struct drm_encoder_helper_funcs *func = encoder->helper_private;
231
232		func->restore(encoder);
233	}
234
235	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
236		crtc->funcs->restore(crtc);
237
238	drm_mode_config_cleanup(dev);
239
240	nouveau_hw_save_vga_fonts(dev, 0);
241}
242
243int
244nv04_display_init(struct drm_device *dev)
245{
246	struct drm_encoder *encoder;
247	struct drm_crtc *crtc;
248
249	/* meh.. modeset apparently doesn't setup all the regs and depends
250	 * on pre-existing state, for now load the state of the card *before*
251	 * nouveau was loaded, and then do a modeset.
252	 *
253	 * best thing to do probably is to make save/restore routines not
254	 * save/restore "pre-load" state, but more general so we can save
255	 * on suspend too.
256	 */
257	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
258		struct drm_encoder_helper_funcs *func = encoder->helper_private;
259
260		func->restore(encoder);
261	}
262
263	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
264		crtc->funcs->restore(crtc);
265
266	return 0;
267}
268
269static void
270nv04_vblank_crtc0_isr(struct drm_device *dev)
271{
272	nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
273	drm_handle_vblank(dev, 0);
274}
275
276static void
277nv04_vblank_crtc1_isr(struct drm_device *dev)
278{
279	nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
280	drm_handle_vblank(dev, 1);
281}