Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2009 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Author: Ben Skeggs
0023  */
0024 
0025 #include <drm/drm_crtc_helper.h>
0026 
0027 #include "nouveau_drv.h"
0028 #include "nouveau_reg.h"
0029 #include "hw.h"
0030 #include "nouveau_encoder.h"
0031 #include "nouveau_connector.h"
0032 #include "nouveau_bo.h"
0033 #include "nouveau_gem.h"
0034 #include "nouveau_chan.h"
0035 
0036 #include <nvif/if0004.h>
0037 
0038 struct nouveau_connector *
0039 nv04_encoder_get_connector(struct nouveau_encoder *encoder)
0040 {
0041     struct drm_device *dev = to_drm_encoder(encoder)->dev;
0042     struct drm_connector *connector;
0043     struct drm_connector_list_iter conn_iter;
0044     struct nouveau_connector *nv_connector = NULL;
0045 
0046     drm_connector_list_iter_begin(dev, &conn_iter);
0047     drm_for_each_connector_iter(connector, &conn_iter) {
0048         if (connector->encoder == to_drm_encoder(encoder))
0049             nv_connector = nouveau_connector(connector);
0050     }
0051     drm_connector_list_iter_end(&conn_iter);
0052 
0053     return nv_connector;
0054 }
0055 
0056 static void
0057 nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend)
0058 {
0059     struct nouveau_drm *drm = nouveau_drm(dev);
0060     struct nv04_display *disp = nv04_display(dev);
0061     struct drm_crtc *crtc;
0062 
0063     /* Disable flip completion events. */
0064     nvif_notify_put(&disp->flip);
0065 
0066     /* Disable vblank interrupts. */
0067     NVWriteCRTC(dev, 0, NV_PCRTC_INTR_EN_0, 0);
0068     if (nv_two_heads(dev))
0069         NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0);
0070 
0071     if (!runtime)
0072         cancel_work_sync(&drm->hpd_work);
0073 
0074     if (!suspend)
0075         return;
0076 
0077     /* Un-pin FB and cursors so they'll be evicted to system memory. */
0078     list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0079         struct drm_framebuffer *fb = crtc->primary->fb;
0080         struct nouveau_bo *nvbo;
0081 
0082         if (!fb || !fb->obj[0])
0083             continue;
0084         nvbo = nouveau_gem_object(fb->obj[0]);
0085         nouveau_bo_unpin(nvbo);
0086     }
0087 
0088     list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0089         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
0090         if (nv_crtc->cursor.nvbo) {
0091             if (nv_crtc->cursor.set_offset)
0092                 nouveau_bo_unmap(nv_crtc->cursor.nvbo);
0093             nouveau_bo_unpin(nv_crtc->cursor.nvbo);
0094         }
0095     }
0096 }
0097 
0098 static int
0099 nv04_display_init(struct drm_device *dev, bool resume, bool runtime)
0100 {
0101     struct nv04_display *disp = nv04_display(dev);
0102     struct nouveau_drm *drm = nouveau_drm(dev);
0103     struct nouveau_encoder *encoder;
0104     struct drm_crtc *crtc;
0105     int ret;
0106 
0107     /* meh.. modeset apparently doesn't setup all the regs and depends
0108      * on pre-existing state, for now load the state of the card *before*
0109      * nouveau was loaded, and then do a modeset.
0110      *
0111      * best thing to do probably is to make save/restore routines not
0112      * save/restore "pre-load" state, but more general so we can save
0113      * on suspend too.
0114      */
0115     list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0116         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
0117         nv_crtc->save(&nv_crtc->base);
0118     }
0119 
0120     list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head)
0121         encoder->enc_save(&encoder->base.base);
0122 
0123     /* Enable flip completion events. */
0124     nvif_notify_get(&disp->flip);
0125 
0126     if (!resume)
0127         return 0;
0128 
0129     /* Re-pin FB/cursors. */
0130     list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0131         struct drm_framebuffer *fb = crtc->primary->fb;
0132         struct nouveau_bo *nvbo;
0133 
0134         if (!fb || !fb->obj[0])
0135             continue;
0136         nvbo = nouveau_gem_object(fb->obj[0]);
0137         ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, true);
0138         if (ret)
0139             NV_ERROR(drm, "Could not pin framebuffer\n");
0140     }
0141 
0142     list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0143         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
0144         if (!nv_crtc->cursor.nvbo)
0145             continue;
0146 
0147         ret = nouveau_bo_pin(nv_crtc->cursor.nvbo,
0148                      NOUVEAU_GEM_DOMAIN_VRAM, true);
0149         if (!ret && nv_crtc->cursor.set_offset)
0150             ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
0151         if (ret)
0152             NV_ERROR(drm, "Could not pin/map cursor.\n");
0153     }
0154 
0155     /* Force CLUT to get re-loaded during modeset. */
0156     list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0157         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
0158 
0159         nv_crtc->lut.depth = 0;
0160     }
0161 
0162     /* This should ensure we don't hit a locking problem when someone
0163      * wakes us up via a connector.  We should never go into suspend
0164      * while the display is on anyways.
0165      */
0166     if (runtime)
0167         return 0;
0168 
0169     /* Restore mode. */
0170     drm_helper_resume_force_mode(dev);
0171 
0172     list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
0173         struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
0174 
0175         if (!nv_crtc->cursor.nvbo)
0176             continue;
0177 
0178         if (nv_crtc->cursor.set_offset)
0179             nv_crtc->cursor.set_offset(nv_crtc,
0180                            nv_crtc->cursor.nvbo->offset);
0181         nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
0182                          nv_crtc->cursor_saved_y);
0183     }
0184 
0185     return 0;
0186 }
0187 
0188 static void
0189 nv04_display_destroy(struct drm_device *dev)
0190 {
0191     struct nv04_display *disp = nv04_display(dev);
0192     struct nouveau_drm *drm = nouveau_drm(dev);
0193     struct nouveau_encoder *encoder;
0194     struct nouveau_crtc *nv_crtc;
0195 
0196     /* Restore state */
0197     list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head)
0198         encoder->enc_restore(&encoder->base.base);
0199 
0200     list_for_each_entry(nv_crtc, &dev->mode_config.crtc_list, base.head)
0201         nv_crtc->restore(&nv_crtc->base);
0202 
0203     nouveau_hw_save_vga_fonts(dev, 0);
0204 
0205     nvif_notify_dtor(&disp->flip);
0206 
0207     nouveau_display(dev)->priv = NULL;
0208     vfree(disp);
0209 
0210     nvif_object_unmap(&drm->client.device.object);
0211 }
0212 
0213 int
0214 nv04_display_create(struct drm_device *dev)
0215 {
0216     struct nouveau_drm *drm = nouveau_drm(dev);
0217     struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device);
0218     struct dcb_table *dcb = &drm->vbios.dcb;
0219     struct drm_connector *connector, *ct;
0220     struct drm_encoder *encoder;
0221     struct nouveau_encoder *nv_encoder;
0222     struct nouveau_crtc *crtc;
0223     struct nv04_display *disp;
0224     int i, ret;
0225 
0226     disp = vzalloc(sizeof(*disp));
0227     if (!disp)
0228         return -ENOMEM;
0229 
0230     nvif_object_map(&drm->client.device.object, NULL, 0);
0231 
0232     nouveau_display(dev)->priv = disp;
0233     nouveau_display(dev)->dtor = nv04_display_destroy;
0234     nouveau_display(dev)->init = nv04_display_init;
0235     nouveau_display(dev)->fini = nv04_display_fini;
0236 
0237     /* Pre-nv50 doesn't support atomic, so don't expose the ioctls */
0238     dev->driver_features &= ~DRIVER_ATOMIC;
0239 
0240     /* Request page flip completion event. */
0241     if (drm->channel) {
0242         nvif_notify_ctor(&drm->channel->nvsw, "kmsFlip", nv04_flip_complete,
0243                  false, NV04_NVSW_NTFY_UEVENT,
0244                  NULL, 0, 0, &disp->flip);
0245     }
0246 
0247     nouveau_hw_save_vga_fonts(dev, 1);
0248 
0249     nv04_crtc_create(dev, 0);
0250     if (nv_two_heads(dev))
0251         nv04_crtc_create(dev, 1);
0252 
0253     for (i = 0; i < dcb->entries; i++) {
0254         struct dcb_output *dcbent = &dcb->entry[i];
0255 
0256         connector = nouveau_connector_create(dev, dcbent);
0257         if (IS_ERR(connector))
0258             continue;
0259 
0260         switch (dcbent->type) {
0261         case DCB_OUTPUT_ANALOG:
0262             ret = nv04_dac_create(connector, dcbent);
0263             break;
0264         case DCB_OUTPUT_LVDS:
0265         case DCB_OUTPUT_TMDS:
0266             ret = nv04_dfp_create(connector, dcbent);
0267             break;
0268         case DCB_OUTPUT_TV:
0269             if (dcbent->location == DCB_LOC_ON_CHIP)
0270                 ret = nv17_tv_create(connector, dcbent);
0271             else
0272                 ret = nv04_tv_create(connector, dcbent);
0273             break;
0274         default:
0275             NV_WARN(drm, "DCB type %d not known\n", dcbent->type);
0276             continue;
0277         }
0278 
0279         if (ret)
0280             continue;
0281     }
0282 
0283     list_for_each_entry_safe(connector, ct,
0284                  &dev->mode_config.connector_list, head) {
0285         if (!connector->possible_encoders) {
0286             NV_WARN(drm, "%s has no encoders, removing\n",
0287                 connector->name);
0288             connector->funcs->destroy(connector);
0289         }
0290     }
0291 
0292     list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
0293         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
0294         struct nvkm_i2c_bus *bus =
0295             nvkm_i2c_bus_find(i2c, nv_encoder->dcb->i2c_index);
0296         nv_encoder->i2c = bus ? &bus->i2c : NULL;
0297     }
0298 
0299     /* Save previous state */
0300     list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
0301         crtc->save(&crtc->base);
0302 
0303     list_for_each_entry(nv_encoder, &dev->mode_config.encoder_list, base.base.head)
0304         nv_encoder->enc_save(&nv_encoder->base.base);
0305 
0306     nouveau_overlay_init(dev);
0307 
0308     return 0;
0309 }