root/drivers/gpu/drm/nouveau/nvkm/engine/disp/vga.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nvkm_rdport
  2. nvkm_wrport
  3. nvkm_rdvgas
  4. nvkm_wrvgas
  5. nvkm_rdvgag
  6. nvkm_wrvgag
  7. nvkm_rdvgac
  8. nvkm_wrvgac
  9. nvkm_rdvgai
  10. nvkm_wrvgai
  11. nvkm_lockvgac
  12. nvkm_rdvgaowner
  13. nvkm_wrvgaowner

   1 /*
   2  * Copyright 2012 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  * Authors: Ben Skeggs
  23  */
  24 #include <subdev/vga.h>
  25 
  26 u8
  27 nvkm_rdport(struct nvkm_device *device, int head, u16 port)
  28 {
  29         if (device->card_type >= NV_50)
  30                 return nvkm_rd08(device, 0x601000 + port);
  31 
  32         if (port == 0x03c0 || port == 0x03c1 || /* AR */
  33             port == 0x03c2 || port == 0x03da || /* INP0 */
  34             port == 0x03d4 || port == 0x03d5)   /* CR */
  35                 return nvkm_rd08(device, 0x601000 + (head * 0x2000) + port);
  36 
  37         if (port == 0x03c2 || port == 0x03cc || /* MISC */
  38             port == 0x03c4 || port == 0x03c5 || /* SR */
  39             port == 0x03ce || port == 0x03cf) { /* GR */
  40                 if (device->card_type < NV_40)
  41                         head = 0; /* CR44 selects head */
  42                 return nvkm_rd08(device, 0x0c0000 + (head * 0x2000) + port);
  43         }
  44 
  45         return 0x00;
  46 }
  47 
  48 void
  49 nvkm_wrport(struct nvkm_device *device, int head, u16 port, u8 data)
  50 {
  51         if (device->card_type >= NV_50)
  52                 nvkm_wr08(device, 0x601000 + port, data);
  53         else
  54         if (port == 0x03c0 || port == 0x03c1 || /* AR */
  55             port == 0x03c2 || port == 0x03da || /* INP0 */
  56             port == 0x03d4 || port == 0x03d5)   /* CR */
  57                 nvkm_wr08(device, 0x601000 + (head * 0x2000) + port, data);
  58         else
  59         if (port == 0x03c2 || port == 0x03cc || /* MISC */
  60             port == 0x03c4 || port == 0x03c5 || /* SR */
  61             port == 0x03ce || port == 0x03cf) { /* GR */
  62                 if (device->card_type < NV_40)
  63                         head = 0; /* CR44 selects head */
  64                 nvkm_wr08(device, 0x0c0000 + (head * 0x2000) + port, data);
  65         }
  66 }
  67 
  68 u8
  69 nvkm_rdvgas(struct nvkm_device *device, int head, u8 index)
  70 {
  71         nvkm_wrport(device, head, 0x03c4, index);
  72         return nvkm_rdport(device, head, 0x03c5);
  73 }
  74 
  75 void
  76 nvkm_wrvgas(struct nvkm_device *device, int head, u8 index, u8 value)
  77 {
  78         nvkm_wrport(device, head, 0x03c4, index);
  79         nvkm_wrport(device, head, 0x03c5, value);
  80 }
  81 
  82 u8
  83 nvkm_rdvgag(struct nvkm_device *device, int head, u8 index)
  84 {
  85         nvkm_wrport(device, head, 0x03ce, index);
  86         return nvkm_rdport(device, head, 0x03cf);
  87 }
  88 
  89 void
  90 nvkm_wrvgag(struct nvkm_device *device, int head, u8 index, u8 value)
  91 {
  92         nvkm_wrport(device, head, 0x03ce, index);
  93         nvkm_wrport(device, head, 0x03cf, value);
  94 }
  95 
  96 u8
  97 nvkm_rdvgac(struct nvkm_device *device, int head, u8 index)
  98 {
  99         nvkm_wrport(device, head, 0x03d4, index);
 100         return nvkm_rdport(device, head, 0x03d5);
 101 }
 102 
 103 void
 104 nvkm_wrvgac(struct nvkm_device *device, int head, u8 index, u8 value)
 105 {
 106         nvkm_wrport(device, head, 0x03d4, index);
 107         nvkm_wrport(device, head, 0x03d5, value);
 108 }
 109 
 110 u8
 111 nvkm_rdvgai(struct nvkm_device *device, int head, u16 port, u8 index)
 112 {
 113         if (port == 0x03c4) return nvkm_rdvgas(device, head, index);
 114         if (port == 0x03ce) return nvkm_rdvgag(device, head, index);
 115         if (port == 0x03d4) return nvkm_rdvgac(device, head, index);
 116         return 0x00;
 117 }
 118 
 119 void
 120 nvkm_wrvgai(struct nvkm_device *device, int head, u16 port, u8 index, u8 value)
 121 {
 122         if      (port == 0x03c4) nvkm_wrvgas(device, head, index, value);
 123         else if (port == 0x03ce) nvkm_wrvgag(device, head, index, value);
 124         else if (port == 0x03d4) nvkm_wrvgac(device, head, index, value);
 125 }
 126 
 127 bool
 128 nvkm_lockvgac(struct nvkm_device *device, bool lock)
 129 {
 130         bool locked = !nvkm_rdvgac(device, 0, 0x1f);
 131         u8 data = lock ? 0x99 : 0x57;
 132         if (device->card_type < NV_50)
 133                 nvkm_wrvgac(device, 0, 0x1f, data);
 134         else
 135                 nvkm_wrvgac(device, 0, 0x3f, data);
 136         if (device->chipset == 0x11) {
 137                 if (!(nvkm_rd32(device, 0x001084) & 0x10000000))
 138                         nvkm_wrvgac(device, 1, 0x1f, data);
 139         }
 140         return locked;
 141 }
 142 
 143 /* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied)
 144  * it affects only the 8 bit vga io regs, which we access using mmio at
 145  * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d*
 146  * in general, the set value of cr44 does not matter: reg access works as
 147  * expected and values can be set for the appropriate head by using a 0x2000
 148  * offset as required
 149  * however:
 150  * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and
 151  *    cr44 must be set to 0 or 3 for accessing values on the correct head
 152  *    through the common 0xc03c* addresses
 153  * b) in tied mode (4) head B is programmed to the values set on head A, and
 154  *    access using the head B addresses can have strange results, ergo we leave
 155  *    tied mode in init once we know to what cr44 should be restored on exit
 156  *
 157  * the owner parameter is slightly abused:
 158  * 0 and 1 are treated as head values and so the set value is (owner * 3)
 159  * other values are treated as literal values to set
 160  */
 161 u8
 162 nvkm_rdvgaowner(struct nvkm_device *device)
 163 {
 164         if (device->card_type < NV_50) {
 165                 if (device->chipset == 0x11) {
 166                         u32 tied = nvkm_rd32(device, 0x001084) & 0x10000000;
 167                         if (tied == 0) {
 168                                 u8 slA = nvkm_rdvgac(device, 0, 0x28) & 0x80;
 169                                 u8 tvA = nvkm_rdvgac(device, 0, 0x33) & 0x01;
 170                                 u8 slB = nvkm_rdvgac(device, 1, 0x28) & 0x80;
 171                                 u8 tvB = nvkm_rdvgac(device, 1, 0x33) & 0x01;
 172                                 if (slA && !tvA) return 0x00;
 173                                 if (slB && !tvB) return 0x03;
 174                                 if (slA) return 0x00;
 175                                 if (slB) return 0x03;
 176                                 return 0x00;
 177                         }
 178                         return 0x04;
 179                 }
 180 
 181                 return nvkm_rdvgac(device, 0, 0x44);
 182         }
 183 
 184         return 0x00;
 185 }
 186 
 187 void
 188 nvkm_wrvgaowner(struct nvkm_device *device, u8 select)
 189 {
 190         if (device->card_type < NV_50) {
 191                 u8 owner = (select == 1) ? 3 : select;
 192                 if (device->chipset == 0x11) {
 193                         /* workaround hw lockup bug */
 194                         nvkm_rdvgac(device, 0, 0x1f);
 195                         nvkm_rdvgac(device, 1, 0x1f);
 196                 }
 197 
 198                 nvkm_wrvgac(device, 0, 0x44, owner);
 199 
 200                 if (device->chipset == 0x11) {
 201                         nvkm_wrvgac(device, 0, 0x2e, owner);
 202                         nvkm_wrvgac(device, 0, 0x2e, owner);
 203                 }
 204         }
 205 }

/* [<][>][^][v][top][bottom][index][help] */